diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json
index bb45aecb1..218478dc7 100644
--- a/src/_locales/en/messages.json
+++ b/src/_locales/en/messages.json
@@ -1148,8 +1148,20 @@
"description": "last focused"
},
"commandSettingLabelTabClosePinned": {
- "message": "Close pinned tabs",
- "description": "Close pinned tabs"
+ "message": "Pinned tabs behavior",
+ "description": "Pinned tabs behavior"
+ },
+ "commandSettingLabelTabClosePinnedNone": {
+ "message": "Do nothing",
+ "description": "Do nothing"
+ },
+ "commandSettingLabelTabClosePinnedClose": {
+ "message": "Close",
+ "description": "Close"
+ },
+ "commandSettingLabelTabClosePinnedDiscard": {
+ "message": "Discard",
+ "description": "Discard"
},
"commandSettingLabelRestoreCurrentWindow": {
"message": "Current window only",
@@ -1345,8 +1357,8 @@
"description": "Determines which tab should be focused next."
},
"commandSettingDescriptionTabClosePinned": {
- "message": "Determines if pinned tabs can be closed or not.",
- "description": "Determines if pinned tabs can be closed or not."
+ "message": "Determines how the close gesture handles pinned tabs: do nothing (ignore), close (remove tab), or discard (unload content but keep tab).",
+ "description": "Determines how the close gesture handles pinned tabs: do nothing (ignore), close (remove tab), or discard (unload content but keep tab)."
},
"commandSettingDescriptionRestoreCurrentWindow": {
"message": "Determines if only tabs which belong to the current window should be restored.",
diff --git a/src/_locales/ja_JP/messages.json b/src/_locales/ja_JP/messages.json
index b23ce1284..0c544fc3c 100644
--- a/src/_locales/ja_JP/messages.json
+++ b/src/_locales/ja_JP/messages.json
@@ -1132,8 +1132,20 @@
"description": "last focused"
},
"commandSettingLabelTabClosePinned": {
- "message": "ピン留めされたタブを閉じる",
- "description": "Close pinned tabs"
+ "message": "ピン留めタブの動作",
+ "description": "Pinned tabs behavior"
+ },
+ "commandSettingLabelTabClosePinnedNone": {
+ "message": "何もしない",
+ "description": "Do nothing"
+ },
+ "commandSettingLabelTabClosePinnedClose": {
+ "message": "閉じる",
+ "description": "Close"
+ },
+ "commandSettingLabelTabClosePinnedDiscard": {
+ "message": "アンロード",
+ "description": "Discard"
},
"commandSettingLabelRestoreCurrentWindow": {
"message": "現在のウィンドウのみ",
@@ -1328,8 +1340,8 @@
"description": "Determines which tab should be focused next."
},
"commandSettingDescriptionTabClosePinned": {
- "message": "ピン留めされたタブを閉じるかどうかを指定します。",
- "description": "Determines if pinned tabs can be closed or not."
+ "message": "閉じるジェスチャーがピン留めタブをどう処理するか:何もしない(無視)、閉じる(タブを削除)、またはアンロード(コンテンツをアンロードしてタブを保持)",
+ "description": "Determines how the close gesture handles pinned tabs: do nothing (ignore), close (remove tab), or discard (unload content but keep tab)."
},
"commandSettingDescriptionRestoreCurrentWindow": {
"message": "タブの復元を現在のウィンドウのみにするかどうかを指定します。",
diff --git a/src/_locales/ko_KR/messages.json b/src/_locales/ko_KR/messages.json
index 0d2a8589c..fd2348a4e 100644
--- a/src/_locales/ko_KR/messages.json
+++ b/src/_locales/ko_KR/messages.json
@@ -1132,8 +1132,20 @@
"description": "last focused"
},
"commandSettingLabelTabClosePinned": {
- "message": "고정 탭 닫기",
- "description": "Close pinned tabs"
+ "message": "고정 탭 동작",
+ "description": "Pinned tabs behavior"
+ },
+ "commandSettingLabelTabClosePinnedNone": {
+ "message": "아무것도 안 함",
+ "description": "Do nothing"
+ },
+ "commandSettingLabelTabClosePinnedClose": {
+ "message": "닫기",
+ "description": "Close"
+ },
+ "commandSettingLabelTabClosePinnedDiscard": {
+ "message": "언로드",
+ "description": "Discard"
},
"commandSettingLabelRestoreCurrentWindow": {
"message": "현재 창만",
@@ -1328,8 +1340,8 @@
"description": "Determines which tab should be focused next."
},
"commandSettingDescriptionTabClosePinned": {
- "message": "고정된 탭의 닫기 여부를 정의합니다.",
- "description": "Determines if pinned tabs can be closed or not."
+ "message": "닫기 제스처가 고정 탭을 처리하는 방법: 아무것도 안 함(무시), 닫기(탭 제거), 또는 언로드(내용을 언로드하지만 탭 유지)",
+ "description": "Determines how the close gesture handles pinned tabs: do nothing (ignore), close (remove tab), or discard (unload content but keep tab)."
},
"commandSettingDescriptionRestoreCurrentWindow": {
"message": "현재 창에 속한 탭만 복원할지 여부를 결정합니다.",
diff --git a/src/_locales/zh_CN/messages.json b/src/_locales/zh_CN/messages.json
index f320947be..7be39e05f 100644
--- a/src/_locales/zh_CN/messages.json
+++ b/src/_locales/zh_CN/messages.json
@@ -1132,8 +1132,20 @@
"description": "last focused"
},
"commandSettingLabelTabClosePinned": {
- "message": "关闭固定的标签页",
- "description": "Close pinned tabs"
+ "message": "固定标签页的处理方式",
+ "description": "Pinned tabs behavior"
+ },
+ "commandSettingLabelTabClosePinnedNone": {
+ "message": "不操作",
+ "description": "Do nothing"
+ },
+ "commandSettingLabelTabClosePinnedClose": {
+ "message": "关闭",
+ "description": "Close"
+ },
+ "commandSettingLabelTabClosePinnedDiscard": {
+ "message": "卸载",
+ "description": "Discard"
},
"commandSettingLabelRestoreCurrentWindow": {
"message": "仅当前窗口",
@@ -1328,8 +1340,8 @@
"description": "Determines which tab should be focused next."
},
"commandSettingDescriptionTabClosePinned": {
- "message": "决定是否关闭固定的标签页。",
- "description": "Determines if pinned tabs can be closed or not."
+ "message": "决定关闭手势对固定标签页的处理方式:不操作(忽略)、关闭(移除标签页)、或卸载(清空内容但保留标签页)",
+ "description": "Determines how the close gesture handles pinned tabs: do nothing (ignore), close (remove tab), or discard (unload content but keep tab)."
},
"commandSettingDescriptionRestoreCurrentWindow": {
"message": "决定是否只恢复属于当前窗口的标签页。",
diff --git a/src/_locales/zh_TW/messages.json b/src/_locales/zh_TW/messages.json
index 3e238f469..3e60aa017 100644
--- a/src/_locales/zh_TW/messages.json
+++ b/src/_locales/zh_TW/messages.json
@@ -1132,8 +1132,20 @@
"description": "last focused"
},
"commandSettingLabelTabClosePinned": {
- "message": "關閉釘選的分頁",
- "description": "Close pinned tabs"
+ "message": "釘選分頁的處理方式",
+ "description": "Pinned tabs behavior"
+ },
+ "commandSettingLabelTabClosePinnedNone": {
+ "message": "不操作",
+ "description": "Do nothing"
+ },
+ "commandSettingLabelTabClosePinnedClose": {
+ "message": "關閉",
+ "description": "Close"
+ },
+ "commandSettingLabelTabClosePinnedDiscard": {
+ "message": "卸載",
+ "description": "Discard"
},
"commandSettingLabelRestoreCurrentWindow": {
"message": "僅目前的視窗",
@@ -1328,8 +1340,8 @@
"description": "Determines which tab should be focused next."
},
"commandSettingDescriptionTabClosePinned": {
- "message": "決定被釘選的分頁是否能被關閉",
- "description": "Determines if pinned tabs can be closed or not."
+ "message": "決定關閉手勢對釘選分頁的處理方式:不操作(忽略)、關閉(移除分頁)、或卸載(清空內容但保留分頁)",
+ "description": "Determines how the close gesture handles pinned tabs: do nothing (ignore), close (remove tab), or discard (unload content but keep tab)."
},
"commandSettingDescriptionRestoreCurrentWindow": {
"message": "決定是否僅還原屬於目前視窗的分頁",
diff --git a/src/core/commands.mjs b/src/core/commands.mjs
index b5b2b1275..5bbd7c5db 100644
--- a/src/core/commands.mjs
+++ b/src/core/commands.mjs
@@ -78,8 +78,71 @@ export async function NewTab (sender, data) {
export async function CloseTab (sender, data) {
- // remove tab if not pinned or remove-pinned-tabs option is enabled
- if (this.getSetting("closePinned") || !sender.tab.pinned) {
+ let closePinnedBehavior = this.getSetting("closePinned");
+
+ // Handle backward compatibility: convert boolean to string
+ if (typeof closePinnedBehavior === "boolean") {
+ closePinnedBehavior = closePinnedBehavior ? "close" : "none";
+ }
+
+ // If tab is pinned and behavior is "none", do nothing
+ if (sender.tab.pinned && closePinnedBehavior === "none") {
+ return;
+ }
+
+ // If tab is pinned and behavior is "discard"
+ if (sender.tab.pinned && closePinnedBehavior === "discard") {
+ try {
+ const tabs = await browser.tabs.query({
+ windowId: sender.tab.windowId,
+ active: false,
+ hidden: false
+ });
+
+ // if there are other tabs to focus
+ if (tabs.length > 0) {
+ let nextTab = null;
+ const nextFocusSetting = this.getSetting("nextFocus");
+
+ switch (nextFocusSetting) {
+ case "default":
+ case "next":
+ // get closest tab to the right (if not found it will return the closest tab to the left)
+ nextTab = tabs.reduce((acc, cur) =>
+ (acc.index <= sender.tab.index && cur.index > acc.index) || (cur.index > sender.tab.index && cur.index < acc.index) ? cur : acc
+ );
+ break;
+
+ case "previous":
+ // get closest tab to the left (if not found it will return the closest tab to the right)
+ nextTab = tabs.reduce((acc, cur) =>
+ (acc.index >= sender.tab.index && cur.index < acc.index) || (cur.index < sender.tab.index && cur.index > acc.index) ? cur : acc
+ );
+ break;
+
+ case "recent":
+ // get the previous tab
+ nextTab = tabs.reduce((acc, cur) => acc.lastAccessed > cur.lastAccessed ? acc : cur);
+ break;
+ }
+
+ if (nextTab) {
+ await browser.tabs.update(nextTab.id, { active: true });
+ // Discard the tab after switching focus (cannot discard active tab)
+ await browser.tabs.discard(sender.tab.id);
+ return true;
+ }
+ }
+
+ return false;
+ } catch (error) {
+ console.error("Error discarding pinned tab:", error);
+ return false;
+ }
+ }
+
+ // remove tab if not pinned or remove-pinned-tabs option is "close"
+ if (closePinnedBehavior === "close" || !sender.tab.pinned) {
const tabs = await browser.tabs.query({
windowId: sender.tab.windowId,
active: false,
diff --git a/src/resources/json/commands.json b/src/resources/json/commands.json
index 523bf8798..da166f621 100644
--- a/src/resources/json/commands.json
+++ b/src/resources/json/commands.json
@@ -37,7 +37,7 @@
"command": "CloseTab",
"settings": {
"nextFocus": "default",
- "closePinned": true
+ "closePinned": "close"
},
"group": "tabs"
},
diff --git a/src/views/options/fragments/command-setting-templates.inc b/src/views/options/fragments/command-setting-templates.inc
index 69c513cdb..38fb7e38a 100644
--- a/src/views/options/fragments/command-setting-templates.inc
+++ b/src/views/options/fragments/command-setting-templates.inc
@@ -81,8 +81,14 @@
-
+
+
+