Преглед изворни кода

added option "filename conflict resolution" > "skip duplicate files"

Former-commit-id: 753b87c58c1553dcba76784d74671531a2acaf6a
Gildas пре 5 година
родитељ
комит
2a9920e916

+ 5 - 1
_locales/de/messages.json

@@ -195,7 +195,11 @@
 		"message": "Dialogfenster zur Eingabe eines Dateinamens",
 		"description": "Value for 'name conflict resolution' option: 'prompt for a name'"
 	},
-	"optionsHTMLContentSubTitle": {
+	"optionFilenameConflictActionSkip": {
+        "message": "Überspringen doppelter Dateien",
+        "description": "Value for 'filename conflict resolution' option: 'skip duplicate files'"
+    },
+    "optionsHTMLContentSubTitle": {
 		"message": "HTML-Inhalt",
 		"description": "Options sub-title: 'HTML content'"
 	},

+ 5 - 1
_locales/en/messages.json

@@ -195,7 +195,11 @@
 		"message": "prompt for a name",
 		"description": "Value for 'name conflict resolution' option: 'prompt for a name'"
 	},
-	"optionsHTMLContentSubTitle": {
+	"optionFilenameConflictActionSkip": {
+        "message": "skip duplicate files",
+        "description": "Value for 'filename conflict resolution' option: 'skip duplicate files'"
+    },
+    "optionsHTMLContentSubTitle": {
 		"message": "HTML content",
 		"description": "Options sub-title: 'HTML content'"
 	},

+ 5 - 1
_locales/es/messages.json

@@ -195,7 +195,11 @@
 		"message": "preguntar por un nombre",
 		"description": "Value for 'name conflict resolution' option: 'prompt for a name'"
 	},
-	"optionsHTMLContentSubTitle": {
+	"optionFilenameConflictActionSkip": {
+        "message": "saltar los archivos duplicados",
+        "description": "Value for 'filename conflict resolution' option: 'skip duplicate files'"
+    },
+    "optionsHTMLContentSubTitle": {
 		"message": "Contenido HTML",
 		"description": "Options sub-title: 'HTML content'"
 	},

+ 5 - 1
_locales/fr/messages.json

@@ -195,7 +195,11 @@
 		"message": "demander un nom de fichier",
 		"description": "Value for 'filename conflict resolution' option: 'prompt for a filename'"
 	},
-	"optionsHTMLContentSubTitle": {
+	"optionFilenameConflictActionSkip": {
+        "message": "passer les fichiers en double",
+        "description": "Value for 'filename conflict resolution' option: 'skip duplicate files'"
+    },
+    "optionsHTMLContentSubTitle": {
 		"message": "Contenu HTML",
 		"description": "Options sub-title: 'HTML content'"
 	},

+ 5 - 1
_locales/ja/messages.json

@@ -195,7 +195,11 @@
 		"message": "名前を求めるプロンプト",
 		"description": "Value for 'name conflict resolution' option: 'prompt for a name'"
 	},
-	"optionsHTMLContentSubTitle": {
+	"optionFilenameConflictActionSkip": {
+        "message": "skip duplicate files",
+        "description": "Value for 'filename conflict resolution' option: 'skip duplicate files'"
+    },
+    "optionsHTMLContentSubTitle": {
 		"message": "HTML コンテンツ",
 		"description": "Options sub-title: 'HTML content'"
 	},

+ 5 - 1
_locales/pl/messages.json

@@ -195,7 +195,11 @@
 		"message": "zapytaj o nazwę",
 		"description": "Value for 'name conflict resolution' option: 'prompt for a name'"
 	},
-	"optionsHTMLContentSubTitle": {
+	"optionFilenameConflictActionSkip": {
+        "message": "skip duplicate files",
+        "description": "Value for 'filename conflict resolution' option: 'skip duplicate files'"
+    },
+    "optionsHTMLContentSubTitle": {
 		"message": "Zawartość HTML",
 		"description": "Options sub-title: 'HTML content'"
 	},

+ 5 - 1
_locales/ru/messages.json

@@ -195,7 +195,11 @@
 		"message": "запросить новое имя",
 		"description": "Value for 'name conflict resolution' option: 'prompt for a name'"
 	},
-	"optionsHTMLContentSubTitle": {
+	"optionFilenameConflictActionSkip": {
+        "message": "skip duplicate files",
+        "description": "Value for 'filename conflict resolution' option: 'skip duplicate files'"
+    },
+    "optionsHTMLContentSubTitle": {
 		"message": "Содержимое HTML",
 		"description": "Options sub-title: 'HTML content'"
 	},

+ 5 - 1
_locales/uk/messages.json

@@ -195,7 +195,11 @@
 		"message": "запит імені",
 		"description": "Value for 'name conflict resolution' option: 'prompt for a name'"
 	},
-	"optionsHTMLContentSubTitle": {
+	"optionFilenameConflictActionSkip": {
+        "message": "skip duplicate files",
+        "description": "Value for 'filename conflict resolution' option: 'skip duplicate files'"
+    },
+    "optionsHTMLContentSubTitle": {
 		"message": "HTML-вміст",
 		"description": "Options sub-title: 'HTML content'"
 	},

+ 5 - 1
_locales/zh_CN/messages.json

@@ -195,7 +195,11 @@
 		"message": "指定一个新名称",
 		"description": "Value for 'name conflict resolution' option: 'prompt for a name'"
 	},
-	"optionsHTMLContentSubTitle": {
+	"optionFilenameConflictActionSkip": {
+        "message": "skip duplicate files",
+        "description": "Value for 'filename conflict resolution' option: 'skip duplicate files'"
+    },
+    "optionsHTMLContentSubTitle": {
 		"message": "HTML 内容",
 		"description": "Options sub-title: 'HTML content'"
 	},

+ 5 - 1
_locales/zh_TW/messages.json

@@ -195,7 +195,11 @@
 		"message": "指定一個新名稱",
 		"description": "Value for 'name conflict resolution' option: 'prompt for a name'"
 	},
-	"optionsHTMLContentSubTitle": {
+	"optionFilenameConflictActionSkip": {
+        "message": "skip duplicate files",
+        "description": "Value for 'filename conflict resolution' option: 'skip duplicate files'"
+    },
+    "optionsHTMLContentSubTitle": {
 		"message": "HTML 內容",
 		"description": "Options sub-title: 'HTML content'"
 	},

+ 28 - 6
extension/core/bg/downloads.js

@@ -38,6 +38,9 @@ singlefile.extension.core.bg.downloads = (() => {
 	const ERROR_INVALID_FILENAME_CHROMIUM = "invalid filename";
 	const CLIENT_ID = "207618107333-bktohpfmdfnv5hfavi1ll18h74gqi27v.apps.googleusercontent.com";
 	const SCOPES = ["https://www.googleapis.com/auth/drive.file"];
+	const CONFLICT_ACTION_SKIP = "skip";
+	const CONFLICT_ACTION_UNIQUIFY = "uniquify";
+	const REGEXP_ESCAPE = /([{}()^$&.*?/+|[\\\\]|\]|-)/g;
 
 	const manifest = browser.runtime.getManifest();
 	const requestPermissionIdentity = manifest.optional_permissions && manifest.optional_permissions.includes("identity");
@@ -138,12 +141,27 @@ singlefile.extension.core.bg.downloads = (() => {
 				});
 			} else {
 				message.url = URL.createObjectURL(blob);
-				await downloadPage(message, {
-					confirmFilename: message.confirmFilename,
-					incognito,
-					filenameConflictAction: message.filenameConflictAction,
-					filenameReplacementCharacter: message.filenameReplacementCharacter
-				});
+				const filenameConflictAction = message.filenameConflictAction;
+				let skipped;
+				if (filenameConflictAction == CONFLICT_ACTION_SKIP) {
+					const downloadItems = await browser.downloads.search({
+						filenameRegex: "(\\\\|/)" + getRegExp(message.filename) + "$",
+						exists: true
+					});
+					if (downloadItems.length) {
+						skipped = true;
+					} else {
+						message.filenameConflictAction = CONFLICT_ACTION_UNIQUIFY;
+					}
+				}
+				if (!skipped) {
+					await downloadPage(message, {
+						confirmFilename: message.confirmFilename,
+						incognito,
+						filenameConflictAction: message.filenameConflictAction,
+						filenameReplacementCharacter: message.filenameReplacementCharacter
+					});
+				}
 			}
 			singlefile.extension.ui.bg.main.onEnd(tabId);
 		} catch (error) {
@@ -158,6 +176,10 @@ singlefile.extension.core.bg.downloads = (() => {
 		}
 	}
 
+	function getRegExp(string) {
+		return string.replace(REGEXP_ESCAPE, "\\$1");
+	}
+
 	async function getAuthInfo(authOptions, force) {
 		let authInfo = await singlefile.extension.core.bg.config.getAuthInfo();
 		const options = {

+ 2 - 0
extension/ui/bg/ui-options.js

@@ -53,6 +53,7 @@
 	const filenameConflictActionUniquifyLabel = document.getElementById("filenameConflictActionUniquifyLabel");
 	const filenameConflictActionOverwriteLabel = document.getElementById("filenameConflictActionOverwriteLabel");
 	const filenameConflictActionPromptLabel = document.getElementById("filenameConflictActionPromptLabel");
+	const filenameConflictActionSkipLabel = document.getElementById("filenameConflictActionSkipLabel");
 	const removeAudioLabel = document.getElementById("removeAudioLabel");
 	const removeVideoLabel = document.getElementById("removeVideoLabel");
 	const displayInfobarLabel = document.getElementById("displayInfobarLabel");
@@ -447,6 +448,7 @@
 	filenameConflictActionUniquifyLabel.textContent = browser.i18n.getMessage("optionFilenameConflictActionUniquify");
 	filenameConflictActionOverwriteLabel.textContent = browser.i18n.getMessage("optionFilenameConflictActionOverwrite");
 	filenameConflictActionPromptLabel.textContent = browser.i18n.getMessage("optionFilenameConflictActionPrompt");
+	filenameConflictActionSkipLabel.textContent = browser.i18n.getMessage("optionFilenameConflictActionSkip");
 	removeAudioLabel.textContent = browser.i18n.getMessage("optionRemoveAudio");
 	removeVideoLabel.textContent = browser.i18n.getMessage("optionRemoveVideo");
 	displayInfobarLabel.textContent = browser.i18n.getMessage("optionDisplayInfobar");

+ 2 - 1
extension/ui/pages/help.html

@@ -186,7 +186,8 @@
 					<li data-options-label="filenameConflictActionLabel"> <span class="option">Option: file name
 							conflict resolution</span>
 						<p>Choose the most appropriate action when a the filename of the saved page is conflicting with
-							existing ones on the filesystem.</p>
+							existing ones on the filesystem. The "skip duplicate files" action only detects duplicates
+							among files downloaded during the current browsing session.</p>
 					</li>
 				</ul>
 				<p>HTML content</p>

+ 1 - 0
extension/ui/pages/options.html

@@ -79,6 +79,7 @@
 					<option id="filenameConflictActionUniquifyLabel" value="uniquify"></option>
 					<option id="filenameConflictActionOverwriteLabel" value="overwrite"></option>
 					<option id="filenameConflictActionPromptLabel" value="prompt"></option>
+					<option id="filenameConflictActionSkipLabel" value="skip"></option>
 				</select>
 			</div>
 		</details>