PageRenderTime 100ms CodeModel.GetById 54ms RepoModel.GetById 0ms app.codeStats 0ms

/gnome-extensions/extensions/web_search_dialog@awamper.gmail.com/helper.js

https://gitlab.com/jhta/.myconfig
JavaScript | 250 lines | 205 code | 44 blank | 1 comment | 17 complexity | ece138d78bb4a46622d946d0a789603a MD5 | raw file
Possible License(s): GPL-2.0
  1. const St = imports.gi.St;
  2. const Lang = imports.lang;
  3. const PopupMenu = imports.ui.popupMenu;
  4. const Animation = imports.ui.animation;
  5. const Params = imports.misc.params;
  6. const Tweener = imports.ui.tweener;
  7. const Soup = imports.gi.Soup;
  8. const Me = imports.misc.extensionUtils.getCurrentExtension();
  9. const Utils = Me.imports.utils;
  10. const _httpSession = Utils._httpSession;
  11. const DUCKDUCKGO_API_URL =
  12. "https://api.duckduckgo.com/?format=json&no_redirect=1"+
  13. "&skip_disambig=1&q=";
  14. const HelperSpinnerMenuItem = Lang.Class({
  15. Name: 'HelperSpinnerMenuItem',
  16. Extends: PopupMenu.PopupBaseMenuItem,
  17. _init: function(text) {
  18. this.parent({
  19. reactive: false,
  20. activate: false,
  21. hover: false,
  22. can_focus: false
  23. });
  24. this._type = 'HELPER';
  25. let spinner = new Animation.AnimatedIcon(
  26. global.datadir + '/theme/process-working.svg',
  27. 24
  28. );
  29. spinner.actor.show();
  30. spinner.play();
  31. let label = new St.Label({
  32. text: Utils.is_blank(text) ? 'Checking helper...' : text
  33. });
  34. let box = new St.BoxLayout({
  35. style_class: 'helper-title'
  36. });
  37. box.add(spinner.actor);
  38. box.add(label);
  39. this.actor.add_child(box);
  40. }
  41. });
  42. const DuckDuckGoHelperMenuItem = new Lang.Class({
  43. Name: 'DuckDuckGoHelperMenuItem',
  44. Extends: PopupMenu.PopupBaseMenuItem,
  45. _init: function(data) {
  46. this.parent({
  47. reactive: false,
  48. activate: false,
  49. hover: false,
  50. can_focus: false
  51. });
  52. this._type = 'HELPER';
  53. data = Params.parse(data, {
  54. heading: '',
  55. definition: '',
  56. abstract: '',
  57. icon: ''
  58. });
  59. if(Utils.is_blank(data.abstract) && Utils.is_blank(data.definition)) {
  60. return false;
  61. }
  62. let icon = this._get_icon(data.icon);
  63. let table = new St.Table({
  64. name: 'helper_table',
  65. style_class: 'helper-box'
  66. });
  67. let max_length = 80;
  68. if(icon) {
  69. table.add(icon, {
  70. row: 0,
  71. col: 1,
  72. x_fill: false,
  73. y_fill: false
  74. });
  75. }
  76. else {
  77. max_length = 110;
  78. }
  79. let text = '';
  80. if(data.definition) {text += '<i>'+data.definition.trim()+'</i>\n';}
  81. if(data.abstract) {text += data.abstract.trim();}
  82. let label = this._get_label(text, 'helper-abstract', max_length);
  83. table.add(label, {
  84. row: 0,
  85. col: 0
  86. });
  87. this.actor.add_child(table);
  88. return true;
  89. },
  90. _get_icon: function(icon_info) {
  91. let info = Params.parse(icon_info, {
  92. url: false,
  93. width: 120,
  94. height: 100
  95. });
  96. if(!info.url) {
  97. return false;
  98. }
  99. let scale_factor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
  100. let textureCache = St.TextureCache.get_default();
  101. let icon = textureCache.load_uri_async(
  102. info.url,
  103. info.width,
  104. info.height,
  105. scale_factor
  106. );
  107. this.icon_box = new St.BoxLayout({
  108. style_class: 'helper-icon-box',
  109. opacity: 0
  110. });
  111. this.icon_box.add(icon);
  112. this.icon_box.connect('notify::allocation', Lang.bind(this, function() {
  113. let natural_width = this.icon_box.get_preferred_width(-1)[1];
  114. if(natural_width > 10) {
  115. Tweener.addTween(this.icon_box, {
  116. transition: 'easeOutQuad',
  117. time: 1,
  118. opacity: 255
  119. });
  120. }
  121. }));
  122. return this.icon_box;
  123. },
  124. _get_label: function(text, class_name, max_length) {
  125. if(Utils.is_blank(text)) {
  126. return false;
  127. }
  128. text = Utils.wordwrap(text.trim(), max_length);
  129. let label = new St.Label({
  130. text: text,
  131. style_class: class_name
  132. });
  133. label.clutter_text.use_markup = true;
  134. label.clutter_text.line_wrap = true;
  135. return label;
  136. }
  137. });
  138. const DuckDuckGoHelper = new Lang.Class({
  139. Name: 'DuckDuckGoHelper',
  140. _init: function() {
  141. // nothing
  142. },
  143. _get_data_async: function(url, callback) {
  144. let request = Soup.Message.new('GET', url);
  145. _httpSession.queue_message(request,
  146. Lang.bind(this, function(_httpSession, message) {
  147. if(message.status_code === 200) {
  148. callback.call(this, request.response_body.data);
  149. }
  150. else {
  151. callback.call(this, false);
  152. }
  153. })
  154. );
  155. },
  156. _parse_response: function(response) {
  157. response = JSON.parse(response);
  158. let result = {
  159. heading: Utils.is_blank(response.Heading)
  160. ? false
  161. : response.Heading.trim().replace(/<[^>]+>/g, ""),
  162. abstract: Utils.is_blank(response.Abstract)
  163. ? false
  164. : response.AbstractText.trim().replace(/<[^>]+>/g, ""),
  165. definition:
  166. Utils.is_blank(response.Definition) ||
  167. response.Definition == response.Abstract
  168. ? false
  169. : response.Definition.trim().replace(/<[^>]+>/g, ""),
  170. image: Utils.is_blank(response.Image)
  171. ? false
  172. : response.Image.trim()
  173. };
  174. return result;
  175. },
  176. get_info: function(query, callback) {
  177. query = query.trim();
  178. if(Utils.is_blank(query)) {
  179. return false;
  180. }
  181. let url = DUCKDUCKGO_API_URL+encodeURIComponent(query);
  182. this._get_data_async(url, Lang.bind(this, function(result) {
  183. if(!result) {
  184. callback.call(this, false);
  185. }
  186. let info = this._parse_response(result);
  187. callback.call(this, info);
  188. }));
  189. return true;
  190. },
  191. get_menu_item: function(data) {
  192. data = Params.parse(data, {
  193. heading: '',
  194. definition: '',
  195. abstract: '',
  196. icon: false
  197. });
  198. if(Utils.is_blank(data.abstract) && Utils.is_blank(data.definition)) {
  199. return false;
  200. }
  201. else {
  202. let menu_item = new DuckDuckGoHelperMenuItem(data);
  203. return menu_item;
  204. }
  205. }
  206. });