menu.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /**
  2. * FeHelper 右键菜单管理
  3. * @type {{manage}}
  4. * @author zhaoxianlie
  5. */
  6. import CrxDownloader from './crx-download.js';
  7. import Awesome from './awesome.js';
  8. import toolMap from './tools.js';
  9. import Settings from '../options/settings.js';
  10. export default (function () {
  11. let FeJson = {
  12. contextMenuId:"fhm_main"
  13. };
  14. // 邮件菜单配置项
  15. let defaultMenuOptions = {
  16. 'download-crx': {
  17. icon: '♥',
  18. text: '插件下载分享',
  19. onClick: function (info, tab) {
  20. CrxDownloader.downloadCrx(tab);
  21. }
  22. },
  23. 'fehelper-setting': {
  24. icon: '❂',
  25. text: 'FeHelper设置',
  26. onClick: function (info, tab) {
  27. chrome.runtime.openOptionsPage();
  28. }
  29. }
  30. };
  31. // 初始化菜单配置
  32. let _initMenuOptions = (() => {
  33. Object.keys(toolMap).forEach(tool => {
  34. // context-menu
  35. switch (tool) {
  36. case 'json-format':
  37. toolMap[tool].menuConfig[0].onClick = function (info, tab) {
  38. chrome.scripting.executeScript({
  39. target: {tabId:tab.id,allFrames:false},
  40. args: [info.selectionText || ''],
  41. func: (text) => text
  42. }, resp => chrome.DynamicToolRunner({
  43. tool, withContent: resp[0].result
  44. }));
  45. };
  46. break;
  47. case 'code-beautify':
  48. case 'en-decode':
  49. toolMap[tool].menuConfig[0].onClick = function (info, tab) {
  50. chrome.scripting.executeScript({
  51. target: {tabId:tab.id,allFrames:false},
  52. args: [info.linkUrl || info.srcUrl || info.selectionText || info.pageUrl || ''],
  53. func: (text) => text
  54. }, resp => chrome.DynamicToolRunner({
  55. tool, withContent: resp[0].result
  56. }));
  57. };
  58. break;
  59. case 'qr-code':
  60. toolMap[tool].menuConfig[0].onClick = function (info, tab) {
  61. chrome.scripting.executeScript({
  62. target: {tabId:tab.id,allFrames:false},
  63. args: [info.linkUrl || info.srcUrl || info.selectionText || info.pageUrl || tab.url || ''],
  64. func: (text) => text
  65. }, resp => chrome.DynamicToolRunner({
  66. tool, withContent: resp[0].result
  67. }));
  68. };
  69. toolMap[tool].menuConfig[1].onClick = function (info, tab) {
  70. chrome.scripting.executeScript({
  71. target: {tabId:tab.id,allFrames:false},
  72. args: [info.srcUrl || ''],
  73. func: (text) => {
  74. try {
  75. if (typeof window.qrcodeContentScript === 'function') {
  76. let qrcode = window.qrcodeContentScript();
  77. if (typeof qrcode.decode === 'function') {
  78. qrcode.decode(text);
  79. return 1;
  80. }
  81. }
  82. } catch (e) {
  83. return 0;
  84. }
  85. }
  86. });
  87. };
  88. break;
  89. default:
  90. toolMap[tool].menuConfig[0].onClick = function (info, tab) {
  91. chrome.DynamicToolRunner({
  92. tool, withContent: tool === 'image-base64' ? info.srcUrl : ''
  93. })
  94. };
  95. break;
  96. }
  97. });
  98. })();
  99. /**
  100. * 创建一个menu 菜单
  101. * @param toolName
  102. * @param menuList
  103. * @returns {boolean}
  104. * @private
  105. */
  106. let _createItem = (toolName, menuList) => {
  107. menuList && menuList.forEach && menuList.forEach(menu => {
  108. // 确保每次创建出来的是一个新的主菜单,防止onClick事件冲突
  109. let menuItemId = 'fhm_c' + escape(menu.text).replace(/\W/g,'') + new Date*1;
  110. chrome.contextMenus.create({
  111. id: menuItemId,
  112. title: menu.icon + ' ' + menu.text,
  113. contexts: menu.contexts || ['all'],
  114. parentId: FeJson.contextMenuId
  115. });
  116. chrome.contextMenus.onClicked.addListener(((tool,mId,mFunc) => (info, tab) => {
  117. if(info.menuItemId === mId) {
  118. if(mFunc) {
  119. mFunc(info,tab);
  120. }else{
  121. chrome.DynamicToolRunner({ tool });
  122. }
  123. }
  124. })(toolName,menuItemId,menu.onClick));
  125. });
  126. };
  127. /**
  128. * 绘制一条分割线
  129. * @private
  130. */
  131. let _createSeparator = function () {
  132. chrome.contextMenus.create({
  133. id: 'fhm_s' + Math.ceil(Math.random()*10e9),
  134. type: 'separator',
  135. parentId: FeJson.contextMenuId
  136. });
  137. };
  138. /**
  139. * 创建扩展专属的右键菜单
  140. */
  141. let _initMenus = function () {
  142. _removeContextMenu(() => {
  143. let id = chrome.contextMenus.create({
  144. id: FeJson.contextMenuId ,
  145. title: "FeHelper",
  146. contexts: ['page', 'selection', 'editable', 'link', 'image'],
  147. documentUrlPatterns: ['http://*/*', 'https://*/*', 'file://*/*']
  148. });
  149. // 绘制用户安装的菜单,放在前面
  150. Awesome.getInstalledTools().then(tools => {
  151. let allMenus = Object.keys(tools).filter(tool => tools[tool].installed && tools[tool].menu);
  152. let onlineTools = allMenus.filter(tool => tool !== 'devtools' && !tools[tool].hasOwnProperty('_devTool'));
  153. let devTools = allMenus.filter(tool => tool === 'devtools' || tools[tool].hasOwnProperty('_devTool'));
  154. // 绘制FH提供的工具菜单
  155. onlineTools.forEach(tool => _createItem(tool, tools[tool].menuConfig));
  156. // 如果有本地工具的菜单需要绘制,则需要加一条分割线
  157. devTools.length && _createSeparator();
  158. // 绘制本地工具的菜单
  159. devTools.forEach(tool => {
  160. // 说明是自定义工具 构造menuConfig
  161. if(!tools[tool].menuConfig) {
  162. tools[tool].menuConfig = [{
  163. icon: tools[tool].icon,
  164. text: tools[tool].name,
  165. onClick: (info, tab) => {
  166. chrome.DynamicToolRunner({
  167. page: 'dynamic',
  168. noPage: !!tools[tool].noPage,
  169. query: `tool=${tool}`
  170. });
  171. !!tools[tool].noPage && setTimeout(window.close, 200);
  172. }
  173. }];
  174. }
  175. _createItem(tool, tools[tool].menuConfig)
  176. });
  177. });
  178. // 绘制两个系统提供的菜单,放到最后
  179. let sysMenu = ['download-crx', 'fehelper-setting'];
  180. let arrPromises = sysMenu.map(menu => Awesome.menuMgr(menu, 'get'));
  181. Promise.all(arrPromises).then(values => {
  182. let needDraw = String(values[0]) === '1' || String(values[1]) !== '0';
  183. // 绘制一条分割线
  184. _createSeparator();
  185. // 绘制菜单
  186. String(values[0]) === '1' && _createItem(sysMenu[0], [defaultMenuOptions[sysMenu[0]]]);
  187. String(values[1]) !== '0' && _createItem(sysMenu[1], [defaultMenuOptions[sysMenu[1]]]);
  188. });
  189. });
  190. };
  191. /**
  192. * 移除扩展专属的右键菜单
  193. */
  194. let _removeContextMenu = function (callback) {
  195. chrome.contextMenus.removeAll(callback);
  196. };
  197. /**
  198. * 创建或移除扩展专属的右键菜单
  199. */
  200. let _createOrRemoveContextMenu = function () {
  201. Settings.getOptions((opts) => {
  202. if (String(opts['OPT_ITEM_CONTEXTMENUS']) !== 'false') {
  203. _initMenus();
  204. } else {
  205. _removeContextMenu();
  206. }
  207. });
  208. };
  209. return {
  210. rebuild: _createOrRemoveContextMenu
  211. };
  212. })();