Prechádzať zdrojové kódy

display auto-save status ("[A]") of the current tab in the action button

Gildas 7 rokov pred
rodič
commit
78abf40a14
2 zmenil súbory, kde vykonal 109 pridanie a 119 odobranie
  1. 11 3
      extension/core/bg/bg.js
  2. 98 116
      extension/ui/bg/ui.js

+ 11 - 3
extension/core/bg/bg.js

@@ -39,7 +39,7 @@ singlefile.core = (() => {
 		"/extension/core/content/content.js"
 	];
 
-	browser.runtime.onMessage.addListener(request => {
+	browser.runtime.onMessage.addListener((request, sender) => {
 		if (request.getConfig) {
 			return singlefile.config.get();
 		}
@@ -55,7 +55,7 @@ singlefile.core = (() => {
 			}
 		}
 		if (request.processContent) {
-			processBackgroundTab(request.content, request.url);
+			processBackgroundTab(sender.tab.id, request.content, request.url);
 		}
 	});
 
@@ -77,7 +77,7 @@ singlefile.core = (() => {
 		}
 	};
 
-	async function processBackgroundTab(content, url) {
+	async function processBackgroundTab(tabId, content, url) {
 		const options = await singlefile.config.get();
 		options.content = content;
 		options.url = url;
@@ -85,6 +85,14 @@ singlefile.core = (() => {
 		options.insertFaviconLink = true;
 		options.removeFrames = true;
 		options.backgroundTab = true;
+		options.autoSave = true;
+		options.onprogress = async event => {
+			if (event.type == event.RESOURCES_INITIALIZED || event.type == event.RESOURCE_LOADED) {
+				singlefile.ui.onTabProgress(tabId, event.details.index, event.details.max, { autoSave: true });
+			} else if (event.type == event.PAGE_ENDED) {
+				singlefile.ui.onTabEnd(tabId, { autoSave: true });
+			}
+		};
 		const processor = new (SingleFile.getClass())(options);
 		await processor.initialize();
 		await processor.preparePageData();

+ 98 - 116
extension/ui/bg/ui.js

@@ -26,7 +26,7 @@ singlefile.ui = (() => {
 	const WAIT_ICON_PATH_PREFIX = "/extension/ui/resources/icon_16_wait";
 	const DEFAULT_TITLE = "Save page with SingleFile";
 	const DEFAULT_COLOR = [2, 147, 20, 255];
-	const BADGE_PROPERTIES = [{ name: "text", browserActionMethod: "setBadgeText" }, { name: "color", browserActionMethod: "setBadgeBackgroundColor" }, { name: "title", browserActionMethod: "setTitle" }, { name: "path", browserActionMethod: "setIcon", mandatory: true }];
+	const BADGE_PROPERTIES = [{ name: "color", browserActionMethod: "setBadgeBackgroundColor" }, { name: "path", browserActionMethod: "setIcon" }, { name: "text", browserActionMethod: "setBadgeText" }, { name: "title", browserActionMethod: "setTitle" }];
 	const FORBIDDEN_URLS = ["https://chrome.google.com", "https://addons.mozilla.org"];
 	const BROWSER_MENUS_API_SUPPORTED = browser.menus && browser.menus.onClicked && browser.menus.create && browser.menus.update && browser.menus.removeAll;
 	const MENU_ID_SAVE_PAGE = "save-page";
@@ -44,57 +44,7 @@ singlefile.ui = (() => {
 	let temporaryTabsData;
 
 	getPersistentTabsData().then(tabsData => persistentTabsData = tabsData);
-
-	browser.runtime.onInstalled.addListener(refreshContextMenu);
-	if (BROWSER_MENUS_API_SUPPORTED) {
-		browser.menus.onClicked.addListener(async (event, tab) => {
-			if (event.menuItemId == MENU_ID_SAVE_PAGE) {
-				processTab(tab);
-			}
-			if (event.menuItemId == MENU_ID_SAVE_SELECTED) {
-				processTab(tab, { selected: true });
-			}
-			if (event.menuItemId == MENU_ID_SAVE_FRAME) {
-				processTab(tab, { frameId: event.frameId });
-			}
-			if (event.menuItemId == MENU_ID_SAVE_SELECTED_TABS) {
-				const tabs = await browser.tabs.query({ currentWindow: true, highlighted: true });
-				tabs.forEach(tab => isAllowedURL(tab.url) && processTab(tab));
-			}
-			if (event.menuItemId == MENU_ID_SAVE_UNPINNED_TABS) {
-				const tabs = await browser.tabs.query({ currentWindow: true, pinned: false });
-				tabs.forEach(tab => isAllowedURL(tab.url) && processTab(tab));
-			}
-			if (event.menuItemId == MENU_ID_SAVE_ALL_TABS) {
-				const tabs = await browser.tabs.query({ currentWindow: true });
-				tabs.forEach(tab => isAllowedURL(tab.url) && processTab(tab));
-			}
-			if (event.menuItemId == MENU_ID_AUTO_SAVE_TAB) {
-				const tabsData = await getPersistentTabsData();
-				if (!tabsData[tab.id]) {
-					tabsData[tab.id] = {};
-				}
-				tabsData[tab.id].autoSave = event.checked;
-				await browser.storage.local.set({ tabsData });
-			}
-			if (event.menuItemId == MENU_ID_AUTO_SAVE_DISABLED) {
-				const tabsData = await getPersistentTabsData();
-				Object.keys(tabsData).forEach(tabId => tabsData[tabId].autoSave = false);
-				tabsData.autoSaveUnpinned = tabsData.autoSaveAll = false;
-				await browser.storage.local.set({ tabsData });
-			}
-			if (event.menuItemId == MENU_ID_AUTO_SAVE_ALL) {
-				const tabsData = await getPersistentTabsData();
-				tabsData.autoSaveAll = event.checked;
-				await browser.storage.local.set({ tabsData });
-			}
-			if (event.menuItemId == MENU_ID_AUTO_SAVE_UNPINNED) {
-				const tabsData = await getPersistentTabsData();
-				tabsData.autoSaveUnpinned = event.checked;
-				await browser.storage.local.set({ tabsData });
-			}
-		});
-	}
+	initContextMenu();
 	browser.browserAction.onClicked.addListener(async tab => {
 		if (isAllowedURL(tab.url)) {
 			const tabs = await browser.tabs.query({ currentWindow: true, highlighted: true });
@@ -107,12 +57,10 @@ singlefile.ui = (() => {
 	});
 	browser.tabs.onActivated.addListener(async activeInfo => {
 		const tab = await browser.tabs.get(activeInfo.tabId);
-		await refreshContextMenuState(tab);
-		onTabActivated(tab);
+		await onTabActivated(tab);
 	});
 	browser.tabs.onCreated.addListener(async tab => {
-		await refreshContextMenuState(tab);
-		onTabActivated(tab);
+		await onTabActivated(tab);
 	});
 	browser.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => {
 		const [config, tabsData] = await Promise.all([singlefile.config.get(), getPersistentTabsData()]);
@@ -121,7 +69,7 @@ singlefile.ui = (() => {
 				processTab(tab, { autoSave: true });
 			}
 		}
-		onTabActivated(tab);
+		await onTabActivated(tab);
 	});
 	browser.tabs.onRemoved.addListener(tabId => onTabRemoved(tabId));
 	browser.runtime.onMessage.addListener((request, sender) => {
@@ -141,7 +89,70 @@ singlefile.ui = (() => {
 			return isAutoSaveUnloadEnabled(sender.tab.id);
 		}
 	});
-	return { update: refreshContextMenu };
+	return {
+		update: refreshContextMenu,
+		onTabProgress,
+		onTabEnd
+	};
+
+	async function initContextMenu() {
+		if (BROWSER_MENUS_API_SUPPORTED) {
+			browser.runtime.onInstalled.addListener(refreshContextMenu);
+			browser.menus.onClicked.addListener(async (event, tab) => {
+				if (event.menuItemId == MENU_ID_SAVE_PAGE) {
+					processTab(tab);
+				}
+				if (event.menuItemId == MENU_ID_SAVE_SELECTED) {
+					processTab(tab, { selected: true });
+				}
+				if (event.menuItemId == MENU_ID_SAVE_FRAME) {
+					processTab(tab, { frameId: event.frameId });
+				}
+				if (event.menuItemId == MENU_ID_SAVE_SELECTED_TABS) {
+					const tabs = await browser.tabs.query({ currentWindow: true, highlighted: true });
+					tabs.forEach(tab => isAllowedURL(tab.url) && processTab(tab));
+				}
+				if (event.menuItemId == MENU_ID_SAVE_UNPINNED_TABS) {
+					const tabs = await browser.tabs.query({ currentWindow: true, pinned: false });
+					tabs.forEach(tab => isAllowedURL(tab.url) && processTab(tab));
+				}
+				if (event.menuItemId == MENU_ID_SAVE_ALL_TABS) {
+					const tabs = await browser.tabs.query({ currentWindow: true });
+					tabs.forEach(tab => isAllowedURL(tab.url) && processTab(tab));
+				}
+				if (event.menuItemId == MENU_ID_AUTO_SAVE_TAB) {
+					const tabsData = await getPersistentTabsData();
+					if (!tabsData[tab.id]) {
+						tabsData[tab.id] = {};
+					}
+					tabsData[tab.id].autoSave = event.checked;
+					await browser.storage.local.set({ tabsData });
+					refreshBadgeState(tab, { autoSave: true });
+				}
+				if (event.menuItemId == MENU_ID_AUTO_SAVE_DISABLED) {
+					const tabsData = await getPersistentTabsData();
+					Object.keys(tabsData).forEach(tabId => tabsData[tabId].autoSave = false);
+					tabsData.autoSaveUnpinned = tabsData.autoSaveAll = false;
+					await browser.storage.local.set({ tabsData });
+					refreshBadgeState(tab, { autoSave: false });
+				}
+				if (event.menuItemId == MENU_ID_AUTO_SAVE_ALL) {
+					const tabsData = await getPersistentTabsData();
+					tabsData.autoSaveAll = event.checked;
+					await browser.storage.local.set({ tabsData });
+					refreshBadgeState(tab, { autoSave: true });
+				}
+				if (event.menuItemId == MENU_ID_AUTO_SAVE_UNPINNED) {
+					const tabsData = await getPersistentTabsData();
+					tabsData.autoSaveUnpinned = event.checked;
+					await browser.storage.local.set({ tabsData });
+					refreshBadgeState(tab, { autoSave: true });
+				}
+			});
+			const tabs = await browser.tabs.query({});
+			tabs.forEach(tab => refreshContextMenuState(tab));
+		}
+	}
 
 	async function refreshContextMenu() {
 		const config = await singlefile.config.get();
@@ -235,75 +246,30 @@ singlefile.ui = (() => {
 	async function processTab(tab, options = {}) {
 		const tabId = tab.id;
 		try {
-			refreshBadge(tabId, {
-				id: tabId,
-				text: "...",
-				color: DEFAULT_COLOR,
-				title: "Initializing SingleFile (1/2)",
-				path: DEFAULT_ICON_PATH,
-				progress: -1,
-				barProgress: -1
-			}, options);
+			refreshBadge(tabId, getBadgeProperties(tabId, options, "...", DEFAULT_COLOR, "Initializing SingleFile (1/2)"));
 			await singlefile.core.processTab(tab, options);
-			refreshBadge(tabId, {
-				id: tabId,
-				text: "...",
-				color: [4, 229, 36, 255],
-				title: "Initializing SingleFile (2/2)",
-				path: DEFAULT_ICON_PATH,
-				progress: -1,
-				barProgress: -1
-			}, options);
+			refreshBadge(tabId, getBadgeProperties(tabId, options, "...", [4, 229, 36, 255], "Initializing SingleFile (2/2)"));
 		} catch (error) {
 			if (error) {
 				onTabError(tabId, options);
 			} else {
-				refreshBadge(tabId, {
-					id: tabId,
-					text: "↻",
-					color: [255, 141, 1, 255],
-					title: "Reload the page",
-					path: DEFAULT_ICON_PATH,
-					progress: -1,
-					barProgress: -1
-				}, options);
+				refreshBadge(tabId, getBadgeProperties(tabId, options, "↻", [255, 141, 1, 255]));
 			}
 		}
 	}
 
 	function onTabError(tabId, options) {
-		refreshBadge(tabId, {
-			text: "ERR",
-			color: [229, 4, 12, 255],
-			title: DEFAULT_TITLE,
-			path: DEFAULT_ICON_PATH,
-			progress: -1,
-			barProgress: -1
-		}, options);
+		refreshBadge(tabId, getBadgeProperties(tabId, options, "ERR", [229, 4, 12, 255]));
 	}
 
 	async function onTabEnd(tabId, options) {
-		refreshBadge(tabId, {
-			text: "OK",
-			color: [4, 229, 36, 255],
-			title: DEFAULT_TITLE,
-			path: DEFAULT_ICON_PATH,
-			progress: -1,
-			barProgress: -1
-		}, options);
+		refreshBadge(tabId, getBadgeProperties(tabId, options, "OK", [4, 229, 36, 255]));
 	}
 
 	function onTabProgress(tabId, index, maxIndex, options) {
 		const progress = Math.max(Math.min(20, Math.floor((index / maxIndex) * 20)), 0);
 		const barProgress = Math.floor((index / maxIndex) * 8);
-		refreshBadge(tabId, {
-			progress,
-			text: "",
-			title: "Save progress: " + (progress * 5) + "%",
-			color: [4, 229, 36, 255],
-			barProgress,
-			path: WAIT_ICON_PATH_PREFIX + barProgress + ".png"
-		}, options);
+		refreshBadge(tabId, getBadgeProperties(tabId, options, "", [4, 229, 36, 255], "Save progress: " + (progress * 5) + "%", WAIT_ICON_PATH_PREFIX + barProgress + ".png", progress, barProgress));
 	}
 
 	async function onTabRemoved(tabId) {
@@ -312,7 +278,10 @@ singlefile.ui = (() => {
 		await browser.storage.local.set({ tabsData });
 	}
 
-	function onTabActivated(tab) {
+	async function onTabActivated(tab) {
+		await refreshContextMenuState(tab);
+		const autoSave = await isAutoSaveEnabled(tab.id);
+		await refreshBadgeState(tab, { autoSave });
 		if (isAllowedURL(tab.url) && browser.browserAction && browser.browserAction.enable && browser.browserAction.disable) {
 			if (isAllowedURL(tab.url)) {
 				browser.browserAction.enable(tab.id);
@@ -332,7 +301,22 @@ singlefile.ui = (() => {
 		return url && (url.startsWith("http://") || url.startsWith("https://") || url.startsWith("file://")) && !FORBIDDEN_URLS.find(storeUrl => url.startsWith(storeUrl));
 	}
 
-	async function refreshBadge(tabId, tabData, options) {
+	async function refreshBadgeState(tab, options) {
+		await refreshBadge(tab.id, getBadgeProperties(tab.id, options));
+	}
+
+	function getBadgeProperties(tabId, options, text, color, title = DEFAULT_TITLE, path = DEFAULT_ICON_PATH, progress = -1, barProgress = -1) {
+		return {
+			text: options.autoSave ? "[A]" : (text || ""),
+			color: options.autoSave ? [208, 208, 208, 255] : [4, 229, 36, 255],
+			title,
+			path,
+			progress,
+			barProgress
+		};
+	}
+
+	async function refreshBadge(tabId, tabData) {
 		const tabsData = await getTemporaryTabsData();
 		if (!tabsData[tabId]) {
 			tabsData[tabId] = {};
@@ -340,15 +324,13 @@ singlefile.ui = (() => {
 		if (!tabsData[tabId].pendingRefresh) {
 			tabsData[tabId].pendingRefresh = Promise.resolve();
 		}
-		tabsData[tabId].pendingRefresh = tabsData[tabId].pendingRefresh.then(() => refreshBadgeAsync(tabId, tabsData, tabData, options));
+		tabsData[tabId].pendingRefresh = tabsData[tabId].pendingRefresh.then(() => refreshBadgeAsync(tabId, tabsData, tabData));
 		await tabsData[tabId].pendingRefresh;
 	}
 
-	async function refreshBadgeAsync(tabId, tabsData, tabData, options) {
+	async function refreshBadgeAsync(tabId, tabsData, tabData) {
 		for (let property of BADGE_PROPERTIES) {
-			if (!options.backgroundTab && (!options.autoSave || property.mandatory)) {
-				await refreshBadgeProperty(tabId, tabsData, property.name, property.browserActionMethod, tabData);
-			}
+			await refreshBadgeProperty(tabId, tabsData, property.name, property.browserActionMethod, tabData);
 		}
 	}