ui-menu.js 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  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 DEFAULT_TITLE = "Save page with SingleFile";
  23. const BROWSER_MENUS_API_SUPPORTED = browser.menus && browser.menus.onClicked && browser.menus.create && browser.menus.update && browser.menus.removeAll;
  24. const MENU_ID_SAVE_PAGE = "save-page";
  25. const MENU_ID_SAVE_SELECTED = "save-selected";
  26. const MENU_ID_SAVE_FRAME = "save-frame";
  27. const MENU_ID_SAVE_SELECTED_TABS = "save-selected-tabs";
  28. const MENU_ID_SAVE_UNPINNED_TABS = "save-unpinned-tabs";
  29. const MENU_ID_SAVE_ALL_TABS = "save-tabs";
  30. const MENU_ID_AUTO_SAVE = "auto-save";
  31. const MENU_ID_AUTO_SAVE_DISABLED = "auto-save-disabled";
  32. const MENU_ID_AUTO_SAVE_TAB = "auto-save-tab";
  33. const MENU_ID_AUTO_SAVE_UNPINNED = "auto-save-unpinned";
  34. const MENU_ID_AUTO_SAVE_ALL = "auto-save-all";
  35. initialize();
  36. browser.tabs.onActivated.addListener(async activeInfo => {
  37. const tab = await browser.tabs.get(activeInfo.tabId);
  38. await refreshState(tab);
  39. });
  40. browser.tabs.onCreated.addListener(refreshState);
  41. return {
  42. refresh
  43. };
  44. async function refresh() {
  45. const config = await singlefile.config.get();
  46. if (BROWSER_MENUS_API_SUPPORTED) {
  47. const pageContextsEnabled = ["page", "frame", "image"];
  48. const defaultContextsDisabled = ["browser_action"];
  49. const defaultContextsEnabled = defaultContextsDisabled.concat(...pageContextsEnabled);
  50. const defaultContexts = config.contextMenuEnabled ? defaultContextsEnabled : defaultContextsDisabled;
  51. await browser.menus.removeAll();
  52. if (config.contextMenuEnabled) {
  53. browser.menus.create({
  54. id: MENU_ID_SAVE_PAGE,
  55. contexts: pageContextsEnabled,
  56. title: DEFAULT_TITLE
  57. });
  58. }
  59. if (config.contextMenuEnabled) {
  60. browser.menus.create({
  61. id: "separator-1",
  62. contexts: pageContextsEnabled,
  63. type: "separator"
  64. });
  65. }
  66. browser.menus.create({
  67. id: MENU_ID_SAVE_SELECTED,
  68. contexts: config.contextMenuEnabled ? defaultContextsDisabled.concat(["selection"]) : defaultContextsDisabled,
  69. title: "Save selection"
  70. });
  71. if (config.contextMenuEnabled) {
  72. browser.menus.create({
  73. id: MENU_ID_SAVE_FRAME,
  74. contexts: ["frame"],
  75. title: "Save frame"
  76. });
  77. browser.menus.create({
  78. id: MENU_ID_SAVE_SELECTED_TABS,
  79. contexts: pageContextsEnabled,
  80. title: "Save selected tabs"
  81. });
  82. }
  83. browser.menus.create({
  84. id: MENU_ID_SAVE_UNPINNED_TABS,
  85. contexts: defaultContexts,
  86. title: "Save unpinned tabs"
  87. });
  88. browser.menus.create({
  89. id: MENU_ID_SAVE_ALL_TABS,
  90. contexts: defaultContexts,
  91. title: "Save all tabs"
  92. });
  93. if (config.contextMenuEnabled) {
  94. browser.menus.create({
  95. id: "separator-2",
  96. contexts: pageContextsEnabled,
  97. type: "separator"
  98. });
  99. }
  100. browser.menus.create({
  101. id: MENU_ID_AUTO_SAVE,
  102. contexts: defaultContexts,
  103. title: "Auto-save"
  104. });
  105. browser.menus.create({
  106. id: MENU_ID_AUTO_SAVE_DISABLED,
  107. type: "radio",
  108. title: "Disabled",
  109. contexts: defaultContexts,
  110. checked: true,
  111. parentId: MENU_ID_AUTO_SAVE
  112. });
  113. browser.menus.create({
  114. id: MENU_ID_AUTO_SAVE_TAB,
  115. type: "radio",
  116. title: "Auto-save this tab",
  117. contexts: defaultContexts,
  118. checked: false,
  119. parentId: MENU_ID_AUTO_SAVE
  120. });
  121. browser.menus.create({
  122. id: MENU_ID_AUTO_SAVE_UNPINNED,
  123. type: "radio",
  124. title: "Auto-save unpinned tabs",
  125. contexts: defaultContexts,
  126. checked: false,
  127. parentId: MENU_ID_AUTO_SAVE
  128. });
  129. browser.menus.create({
  130. id: MENU_ID_AUTO_SAVE_ALL,
  131. type: "radio",
  132. title: "Auto-save all tabs",
  133. contexts: defaultContexts,
  134. checked: false,
  135. parentId: MENU_ID_AUTO_SAVE
  136. });
  137. }
  138. }
  139. async function initialize() {
  140. if (BROWSER_MENUS_API_SUPPORTED) {
  141. refresh();
  142. browser.menus.onClicked.addListener(async (event, tab) => {
  143. if (event.menuItemId == MENU_ID_SAVE_PAGE) {
  144. singlefile.ui.processTab(tab);
  145. }
  146. if (event.menuItemId == MENU_ID_SAVE_SELECTED) {
  147. singlefile.ui.processTab(tab, { selected: true });
  148. }
  149. if (event.menuItemId == MENU_ID_SAVE_FRAME) {
  150. singlefile.ui.processTab(tab, { frameId: event.frameId });
  151. }
  152. if (event.menuItemId == MENU_ID_SAVE_SELECTED_TABS) {
  153. const tabs = await browser.tabs.query({ currentWindow: true, highlighted: true });
  154. tabs.forEach(tab => singlefile.core.isAllowedURL(tab.url) && singlefile.ui.processTab(tab));
  155. }
  156. if (event.menuItemId == MENU_ID_SAVE_UNPINNED_TABS) {
  157. const tabs = await browser.tabs.query({ currentWindow: true, pinned: false });
  158. tabs.forEach(tab => singlefile.core.isAllowedURL(tab.url) && singlefile.ui.processTab(tab));
  159. }
  160. if (event.menuItemId == MENU_ID_SAVE_ALL_TABS) {
  161. const tabs = await browser.tabs.query({ currentWindow: true });
  162. tabs.forEach(tab => singlefile.core.isAllowedURL(tab.url) && singlefile.ui.processTab(tab));
  163. }
  164. if (event.menuItemId == MENU_ID_AUTO_SAVE_TAB) {
  165. const tabsData = await singlefile.storage.get();
  166. if (!tabsData[tab.id]) {
  167. tabsData[tab.id] = {};
  168. }
  169. tabsData[tab.id].autoSave = event.checked;
  170. await singlefile.storage.set(tabsData);
  171. refreshExternalComponents(tab.id, { autoSave: true });
  172. }
  173. if (event.menuItemId == MENU_ID_AUTO_SAVE_DISABLED) {
  174. const tabsData = await singlefile.storage.get();
  175. Object.keys(tabsData).forEach(tabId => tabsData[tabId].autoSave = false);
  176. tabsData.autoSaveUnpinned = tabsData.autoSaveAll = false;
  177. await singlefile.storage.set(tabsData);
  178. refreshExternalComponents(tab.id, { autoSave: false });
  179. }
  180. if (event.menuItemId == MENU_ID_AUTO_SAVE_ALL) {
  181. const tabsData = await singlefile.storage.get();
  182. tabsData.autoSaveAll = event.checked;
  183. await singlefile.storage.set(tabsData);
  184. refreshExternalComponents(tab.id, { autoSave: true });
  185. }
  186. if (event.menuItemId == MENU_ID_AUTO_SAVE_UNPINNED) {
  187. const tabsData = await singlefile.storage.get();
  188. tabsData.autoSaveUnpinned = event.checked;
  189. await singlefile.storage.set(tabsData);
  190. refreshExternalComponents(tab.id, { autoSave: true });
  191. }
  192. });
  193. const tabs = await browser.tabs.query({});
  194. tabs.forEach(tab => refreshState(tab));
  195. }
  196. }
  197. async function refreshExternalComponents(tabId, tabData) {
  198. await singlefile.ui.autosave.refresh();
  199. singlefile.ui.button.refresh(tabId, tabData);
  200. }
  201. async function refreshState(tab) {
  202. const tabsData = await singlefile.storage.get();
  203. if (BROWSER_MENUS_API_SUPPORTED) {
  204. try {
  205. const disabled = Boolean(!tabsData[tab.id] || !tabsData[tab.id].autoSave);
  206. await browser.menus.update(MENU_ID_AUTO_SAVE_DISABLED, { checked: disabled });
  207. await browser.menus.update(MENU_ID_AUTO_SAVE_TAB, { checked: !disabled });
  208. await browser.menus.update(MENU_ID_AUTO_SAVE_UNPINNED, { checked: Boolean(tabsData.autoSaveUnpinned) });
  209. await browser.menus.update(MENU_ID_AUTO_SAVE_ALL, { checked: Boolean(tabsData.autoSaveAll) });
  210. } catch (error) {
  211. /* ignored */
  212. }
  213. }
  214. }
  215. })();