ui-menu.js 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /*
  2. * Copyright 2018 Gildas Lormeau
  3. * contact : gildas.lormeau <at> gmail.com
  4. *
  5. * This file is part of SingleFile.
  6. *
  7. * SingleFile is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU Lesser General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * SingleFile is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public License
  18. * along with SingleFile. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. /* global browser, singlefile */
  21. singlefile.ui.menu = (() => {
  22. const BROWSER_MENUS_API_SUPPORTED = browser.menus && browser.menus.onClicked && browser.menus.create && browser.menus.update && browser.menus.removeAll;
  23. const MENU_ID_SAVE_PAGE = "save-page";
  24. const MENU_ID_SAVE_SELECTED = "save-selected";
  25. const MENU_ID_SAVE_FRAME = "save-frame";
  26. const MENU_ID_SAVE_SELECTED_TABS = "save-selected-tabs";
  27. const MENU_ID_SAVE_UNPINNED_TABS = "save-unpinned-tabs";
  28. const MENU_ID_SAVE_ALL_TABS = "save-tabs";
  29. const MENU_ID_AUTO_SAVE = "auto-save";
  30. const MENU_ID_AUTO_SAVE_DISABLED = "auto-save-disabled";
  31. const MENU_ID_AUTO_SAVE_TAB = "auto-save-tab";
  32. const MENU_ID_AUTO_SAVE_UNPINNED = "auto-save-unpinned";
  33. const MENU_ID_AUTO_SAVE_ALL = "auto-save-all";
  34. initialize();
  35. browser.tabs.onActivated.addListener(async activeInfo => {
  36. const tab = await browser.tabs.get(activeInfo.tabId);
  37. await refreshState(tab);
  38. });
  39. browser.tabs.onCreated.addListener(refreshState);
  40. return {
  41. refresh
  42. };
  43. async function refresh() {
  44. const config = await singlefile.config.get();
  45. if (BROWSER_MENUS_API_SUPPORTED) {
  46. const pageContextsEnabled = ["page", "frame", "image", "link", "video", "audio"];
  47. const defaultContextsDisabled = ["browser_action"];
  48. const defaultContextsEnabled = defaultContextsDisabled.concat(...pageContextsEnabled);
  49. const defaultContexts = config.contextMenuEnabled ? defaultContextsEnabled : defaultContextsDisabled;
  50. await browser.menus.removeAll();
  51. if (config.contextMenuEnabled) {
  52. browser.menus.create({
  53. id: MENU_ID_SAVE_PAGE,
  54. contexts: pageContextsEnabled,
  55. title: browser.i18n.getMessage("menuSavePage")
  56. });
  57. }
  58. if (config.contextMenuEnabled) {
  59. browser.menus.create({
  60. id: "separator-1",
  61. contexts: pageContextsEnabled,
  62. type: "separator"
  63. });
  64. }
  65. browser.menus.create({
  66. id: MENU_ID_SAVE_SELECTED,
  67. contexts: defaultContexts,
  68. title: browser.i18n.getMessage("menuSaveSelection")
  69. });
  70. if (config.contextMenuEnabled) {
  71. browser.menus.create({
  72. id: MENU_ID_SAVE_FRAME,
  73. contexts: ["frame"],
  74. title: browser.i18n.getMessage("menuSaveFrame")
  75. });
  76. browser.menus.create({
  77. id: MENU_ID_SAVE_SELECTED_TABS,
  78. contexts: pageContextsEnabled,
  79. title: browser.i18n.getMessage("menuSaveSelectedTabs")
  80. });
  81. }
  82. browser.menus.create({
  83. id: MENU_ID_SAVE_UNPINNED_TABS,
  84. contexts: defaultContexts,
  85. title: browser.i18n.getMessage("menuUnpinnedTabs")
  86. });
  87. browser.menus.create({
  88. id: MENU_ID_SAVE_ALL_TABS,
  89. contexts: defaultContexts,
  90. title: browser.i18n.getMessage("menuAllTabs")
  91. });
  92. if (config.contextMenuEnabled) {
  93. browser.menus.create({
  94. id: "separator-2",
  95. contexts: pageContextsEnabled,
  96. type: "separator"
  97. });
  98. }
  99. browser.menus.create({
  100. id: MENU_ID_AUTO_SAVE,
  101. contexts: defaultContexts,
  102. title: browser.i18n.getMessage("menuAutoSave")
  103. });
  104. browser.menus.create({
  105. id: MENU_ID_AUTO_SAVE_DISABLED,
  106. type: "radio",
  107. title: browser.i18n.getMessage("menuAutoSaveDisabled"),
  108. contexts: defaultContexts,
  109. checked: true,
  110. parentId: MENU_ID_AUTO_SAVE
  111. });
  112. browser.menus.create({
  113. id: MENU_ID_AUTO_SAVE_TAB,
  114. type: "radio",
  115. title: browser.i18n.getMessage("menuAutoSaveTab"),
  116. contexts: defaultContexts,
  117. checked: false,
  118. parentId: MENU_ID_AUTO_SAVE
  119. });
  120. browser.menus.create({
  121. id: MENU_ID_AUTO_SAVE_UNPINNED,
  122. type: "radio",
  123. title: browser.i18n.getMessage("menuAutoSaveUnpinnedTabs"),
  124. contexts: defaultContexts,
  125. checked: false,
  126. parentId: MENU_ID_AUTO_SAVE
  127. });
  128. browser.menus.create({
  129. id: MENU_ID_AUTO_SAVE_ALL,
  130. type: "radio",
  131. title: browser.i18n.getMessage("menuAutoSaveAllTabs"),
  132. contexts: defaultContexts,
  133. checked: false,
  134. parentId: MENU_ID_AUTO_SAVE
  135. });
  136. }
  137. }
  138. async function initialize() {
  139. if (BROWSER_MENUS_API_SUPPORTED) {
  140. refresh();
  141. browser.menus.onClicked.addListener(async (event, tab) => {
  142. if (event.menuItemId == MENU_ID_SAVE_PAGE) {
  143. singlefile.ui.saveTab(tab);
  144. }
  145. if (event.menuItemId == MENU_ID_SAVE_SELECTED) {
  146. singlefile.ui.saveTab(tab, { selected: true });
  147. }
  148. if (event.menuItemId == MENU_ID_SAVE_FRAME) {
  149. singlefile.ui.saveTab(tab, { frameId: event.frameId });
  150. }
  151. if (event.menuItemId == MENU_ID_SAVE_SELECTED_TABS) {
  152. const tabs = await browser.tabs.query({ currentWindow: true, highlighted: true });
  153. tabs.forEach(tab => singlefile.core.isAllowedURL(tab.url) && singlefile.ui.saveTab(tab));
  154. }
  155. if (event.menuItemId == MENU_ID_SAVE_UNPINNED_TABS) {
  156. const tabs = await browser.tabs.query({ currentWindow: true, pinned: false });
  157. tabs.forEach(tab => singlefile.core.isAllowedURL(tab.url) && singlefile.ui.saveTab(tab));
  158. }
  159. if (event.menuItemId == MENU_ID_SAVE_ALL_TABS) {
  160. const tabs = await browser.tabs.query({ currentWindow: true });
  161. tabs.forEach(tab => singlefile.core.isAllowedURL(tab.url) && singlefile.ui.saveTab(tab));
  162. }
  163. if (event.menuItemId == MENU_ID_AUTO_SAVE_TAB) {
  164. const tabsData = await singlefile.storage.get();
  165. if (!tabsData[tab.id]) {
  166. tabsData[tab.id] = {};
  167. }
  168. tabsData[tab.id].autoSave = event.checked;
  169. await singlefile.storage.set(tabsData);
  170. refreshExternalComponents(tab.id, { autoSave: true });
  171. }
  172. if (event.menuItemId == MENU_ID_AUTO_SAVE_DISABLED) {
  173. const tabsData = await singlefile.storage.get();
  174. Object.keys(tabsData).forEach(tabId => tabsData[tabId].autoSave = false);
  175. tabsData.autoSaveUnpinned = tabsData.autoSaveAll = false;
  176. await singlefile.storage.set(tabsData);
  177. refreshExternalComponents(tab.id, { autoSave: false });
  178. }
  179. if (event.menuItemId == MENU_ID_AUTO_SAVE_ALL) {
  180. const tabsData = await singlefile.storage.get();
  181. tabsData.autoSaveAll = event.checked;
  182. await singlefile.storage.set(tabsData);
  183. refreshExternalComponents(tab.id, { autoSave: true });
  184. }
  185. if (event.menuItemId == MENU_ID_AUTO_SAVE_UNPINNED) {
  186. const tabsData = await singlefile.storage.get();
  187. tabsData.autoSaveUnpinned = event.checked;
  188. await singlefile.storage.set(tabsData);
  189. refreshExternalComponents(tab.id, { autoSave: true });
  190. }
  191. });
  192. const tabs = await browser.tabs.query({});
  193. tabs.forEach(tab => refreshState(tab));
  194. }
  195. }
  196. async function refreshExternalComponents(tabId, tabData) {
  197. await singlefile.ui.autosave.refresh();
  198. singlefile.ui.button.refresh(tabId, tabData);
  199. }
  200. async function refreshState(tab) {
  201. const tabsData = await singlefile.storage.get();
  202. if (BROWSER_MENUS_API_SUPPORTED) {
  203. try {
  204. const disabled = Boolean(!tabsData[tab.id] || !tabsData[tab.id].autoSave);
  205. await browser.menus.update(MENU_ID_AUTO_SAVE_DISABLED, { checked: disabled });
  206. await browser.menus.update(MENU_ID_AUTO_SAVE_TAB, { checked: !disabled });
  207. await browser.menus.update(MENU_ID_AUTO_SAVE_UNPINNED, { checked: Boolean(tabsData.autoSaveUnpinned) });
  208. await browser.menus.update(MENU_ID_AUTO_SAVE_ALL, { checked: Boolean(tabsData.autoSaveAll) });
  209. } catch (error) {
  210. /* ignored */
  211. }
  212. }
  213. }
  214. })();