mirror of
https://github.com/zen-browser/desktop.git
synced 2025-09-06 19:38:24 +00:00
Compare commits
5 Commits
1.15.3b
...
window-syn
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f6922ef2ba | ||
![]() |
182c8a4ff7 | ||
![]() |
91f5d58fbc | ||
![]() |
7a4cdaa45c | ||
![]() |
81e854a89f |
@@ -15,7 +15,7 @@ zen-folders-panel-change-folder-space =
|
|||||||
zen-folders-panel-change-icon-folder =
|
zen-folders-panel-change-icon-folder =
|
||||||
.label = Změnit ikonu
|
.label = Změnit ikonu
|
||||||
zen-folders-unload-all-tooltip =
|
zen-folders-unload-all-tooltip =
|
||||||
.tooltiptext = Unload active in this folder
|
.tooltiptext = Uspat aktivní panely v této složce
|
||||||
zen-folders-unload-folder =
|
zen-folders-unload-folder =
|
||||||
.label = Uspat všechny panely
|
.label = Uspat všechny panely
|
||||||
zen-folders-search-no-results = Žádný panel neodpovídá tomuto hledání 🤔
|
zen-folders-search-no-results = Žádný panel neodpovídá tomuto hledání 🤔
|
||||||
|
@@ -27,7 +27,7 @@ zen-glance-trigger-shift-click =
|
|||||||
zen-glance-trigger-meta-click =
|
zen-glance-trigger-meta-click =
|
||||||
.label = Meta (Command) + 单击
|
.label = Meta (Command) + 单击
|
||||||
zen-glance-trigger-mantain-click =
|
zen-glance-trigger-mantain-click =
|
||||||
.label = 长按(即将上线)
|
.label = 长按(即将上线!)
|
||||||
zen-look-and-feel-compact-view-header = 以紧凑视图显示
|
zen-look-and-feel-compact-view-header = 以紧凑视图显示
|
||||||
zen-look-and-feel-compact-view-description = 仅显示您使用的工具栏!
|
zen-look-and-feel-compact-view-description = 仅显示您使用的工具栏!
|
||||||
zen-look-and-feel-compact-view-enabled =
|
zen-look-and-feel-compact-view-enabled =
|
||||||
|
@@ -1,21 +1,21 @@
|
|||||||
zen-folders-search-placeholder =
|
zen-folders-search-placeholder =
|
||||||
.placeholder = 搜索 { $folder-name }……
|
.placeholder = 搜索 { $folder-name }……
|
||||||
zen-folders-panel-rename-folder =
|
zen-folders-panel-rename-folder =
|
||||||
.label = Rename Folder
|
.label = 重命名文件夹
|
||||||
zen-folders-panel-unpack-folder =
|
zen-folders-panel-unpack-folder =
|
||||||
.label = Unpack Folder
|
.label = Unpack Folder
|
||||||
zen-folders-new-subfolder =
|
zen-folders-new-subfolder =
|
||||||
.label = New Subfolder
|
.label = 新建子文件夹
|
||||||
zen-folders-panel-delete-folder =
|
zen-folders-panel-delete-folder =
|
||||||
.label = Delete Folder
|
.label = 删除文件夹
|
||||||
zen-folders-panel-convert-folder-to-space =
|
zen-folders-panel-convert-folder-to-space =
|
||||||
.label = Convert folder to Space
|
.label = 将文件夹转换为工作区
|
||||||
zen-folders-panel-change-folder-space =
|
zen-folders-panel-change-folder-space =
|
||||||
.label = Change Space...
|
.label = 更改工作区……
|
||||||
zen-folders-panel-change-icon-folder =
|
zen-folders-panel-change-icon-folder =
|
||||||
.label = Change Icon
|
.label = 更改图标
|
||||||
zen-folders-unload-all-tooltip =
|
zen-folders-unload-all-tooltip =
|
||||||
.tooltiptext = Unload active in this folder
|
.tooltiptext = 卸载此文件夹中的活动
|
||||||
zen-folders-unload-folder =
|
zen-folders-unload-folder =
|
||||||
.label = Unload All Tabs
|
.label = Unload All Tabs
|
||||||
zen-folders-search-no-results = No tabs matching that search 🤔
|
zen-folders-search-no-results = 没有搜索到匹配的标签 🤔
|
||||||
|
@@ -43,6 +43,6 @@ zen-close-label = 关闭
|
|||||||
zen-singletoolbar-urlbar-placeholder-with-name =
|
zen-singletoolbar-urlbar-placeholder-with-name =
|
||||||
.placeholder = 搜索……
|
.placeholder = 搜索……
|
||||||
zen-icons-picker-emoji =
|
zen-icons-picker-emoji =
|
||||||
.label = Emojis
|
.label = 表情符号
|
||||||
zen-icons-picker-svg =
|
zen-icons-picker-svg =
|
||||||
.label = Icons
|
.label = 图标集
|
||||||
|
@@ -15,7 +15,7 @@ zen-toolbar-context-compact-mode-hide-both =
|
|||||||
.label = 两者都隐藏
|
.label = 两者都隐藏
|
||||||
.accesskey = H
|
.accesskey = H
|
||||||
zen-toolbar-context-new-folder =
|
zen-toolbar-context-new-folder =
|
||||||
.label = New Folder
|
.label = 新建文件夹
|
||||||
.accesskey = N
|
.accesskey = N
|
||||||
sidebar-zen-expand =
|
sidebar-zen-expand =
|
||||||
.label = 展开侧边栏
|
.label = 展开侧边栏
|
||||||
|
@@ -2,7 +2,7 @@ zen-panel-ui-workspaces-text = 工作区
|
|||||||
zen-panel-ui-workspaces-create =
|
zen-panel-ui-workspaces-create =
|
||||||
.label = 创建工作区
|
.label = 创建工作区
|
||||||
zen-panel-ui-folder-create =
|
zen-panel-ui-folder-create =
|
||||||
.label = Create Folder
|
.label = 新建文件夹
|
||||||
zen-workspaces-panel-context-delete =
|
zen-workspaces-panel-context-delete =
|
||||||
.label = 删除工作区
|
.label = 删除工作区
|
||||||
.accesskey = D
|
.accesskey = D
|
||||||
@@ -48,4 +48,4 @@ zen-workspace-creation-profile = 身份
|
|||||||
zen-workspace-creation-header = 创建工作区
|
zen-workspace-creation-header = 创建工作区
|
||||||
zen-workspace-creation-label = 工作区用于组织标签页和会话。
|
zen-workspace-creation-label = 工作区用于组织标签页和会话。
|
||||||
zen-workspaces-delete-workspace-title = 删除工作区?
|
zen-workspaces-delete-workspace-title = 删除工作区?
|
||||||
zen-workspaces-delete-workspace-body = Are you sure you want to delete { $name }? This action cannot be undone.
|
zen-workspaces-delete-workspace-body = 你确定要删除 { $name } 吗?这个操作无法撤销。
|
||||||
|
@@ -58,3 +58,4 @@
|
|||||||
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenDownloadAnimation.mjs"></script>
|
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenDownloadAnimation.mjs"></script>
|
||||||
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenEmojiPicker.mjs"></script>
|
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenEmojiPicker.mjs"></script>
|
||||||
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenWorkspaceCreation.mjs"></script>
|
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenWorkspaceCreation.mjs"></script>
|
||||||
|
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenWindowSyncing.mjs"></script>
|
||||||
|
@@ -44,6 +44,7 @@
|
|||||||
content/browser/zen-components/ZenWorkspaceIcons.mjs (../../zen/workspaces/ZenWorkspaceIcons.mjs)
|
content/browser/zen-components/ZenWorkspaceIcons.mjs (../../zen/workspaces/ZenWorkspaceIcons.mjs)
|
||||||
content/browser/zen-components/ZenWorkspace.mjs (../../zen/workspaces/ZenWorkspace.mjs)
|
content/browser/zen-components/ZenWorkspace.mjs (../../zen/workspaces/ZenWorkspace.mjs)
|
||||||
content/browser/zen-components/ZenWorkspaces.mjs (../../zen/workspaces/ZenWorkspaces.mjs)
|
content/browser/zen-components/ZenWorkspaces.mjs (../../zen/workspaces/ZenWorkspaces.mjs)
|
||||||
|
content/browser/zen-components/ZenWindowSyncing.mjs (../../zen/workspaces/ZenWindowSyncing.mjs)
|
||||||
content/browser/zen-components/ZenWorkspaceCreation.mjs (../../zen/workspaces/ZenWorkspaceCreation.mjs)
|
content/browser/zen-components/ZenWorkspaceCreation.mjs (../../zen/workspaces/ZenWorkspaceCreation.mjs)
|
||||||
content/browser/zen-components/ZenWorkspacesStorage.mjs (../../zen/workspaces/ZenWorkspacesStorage.mjs)
|
content/browser/zen-components/ZenWorkspacesStorage.mjs (../../zen/workspaces/ZenWorkspacesStorage.mjs)
|
||||||
content/browser/zen-components/ZenWorkspacesSync.mjs (../../zen/workspaces/ZenWorkspacesSync.mjs)
|
content/browser/zen-components/ZenWorkspacesSync.mjs (../../zen/workspaces/ZenWorkspacesSync.mjs)
|
||||||
|
@@ -92,6 +92,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
onTabIconChanged(tab, url = null) {
|
onTabIconChanged(tab, url = null) {
|
||||||
|
tab.dispatchEvent(new CustomEvent('ZenTabIconChanged', { bubbles: true, detail: { tab } }));
|
||||||
const iconUrl = url ?? tab.iconImage.src;
|
const iconUrl = url ?? tab.iconImage.src;
|
||||||
if (!iconUrl && tab.hasAttribute('zen-pin-id')) {
|
if (!iconUrl && tab.hasAttribute('zen-pin-id')) {
|
||||||
try {
|
try {
|
||||||
@@ -1466,6 +1467,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async onTabLabelChanged(tab) {
|
async onTabLabelChanged(tab) {
|
||||||
|
tab.dispatchEvent(new CustomEvent('ZenTabLabelChanged', { detail: { tab } }));
|
||||||
if (!this._pinsCache) {
|
if (!this._pinsCache) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
257
src/zen/workspaces/ZenWindowSyncing.mjs
Normal file
257
src/zen/workspaces/ZenWindowSyncing.mjs
Normal file
@@ -0,0 +1,257 @@
|
|||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
{
|
||||||
|
class nsZenWorkspaceWindowSync extends nsZenMultiWindowFeature {
|
||||||
|
#ignoreNextEvents = false;
|
||||||
|
#waitForPromise = null;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
if (!window.closed) {
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async init() {
|
||||||
|
await gZenWorkspaces.promiseInitialized;
|
||||||
|
this.#makeSureAllTabsHaveIds();
|
||||||
|
this.#setUpEventListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
#makeSureAllTabsHaveIds() {
|
||||||
|
const allTabs = gZenWorkspaces.allStoredTabs;
|
||||||
|
for (const tab of allTabs) {
|
||||||
|
if (!tab.hasAttribute('zen-sync-id')) {
|
||||||
|
const tabId = gZenUIManager.generateUuidv4();
|
||||||
|
tab.setAttribute('zen-sync-id', tabId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#setUpEventListeners() {
|
||||||
|
const kEvents = [
|
||||||
|
'TabClose',
|
||||||
|
'TabOpen',
|
||||||
|
'TabPinned',
|
||||||
|
'TabUnpinned',
|
||||||
|
'TabAddedToEssentials',
|
||||||
|
'TabRemovedFromEssentials',
|
||||||
|
'TabHide',
|
||||||
|
'TabShow',
|
||||||
|
'TabMove',
|
||||||
|
'ZenTabIconChanged',
|
||||||
|
'ZenTabLabelChanged',
|
||||||
|
];
|
||||||
|
const eventListener = this.#handleEvent.bind(this);
|
||||||
|
for (const event of kEvents) {
|
||||||
|
window.addEventListener(event, eventListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('unload', () => {
|
||||||
|
for (const event of kEvents) {
|
||||||
|
window.removeEventListener(event, eventListener);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#handleEvent(event) {
|
||||||
|
this.#propagateToOtherWindows(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
async #propagateToOtherWindows(event) {
|
||||||
|
if (this.#ignoreNextEvents) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.#waitForPromise) {
|
||||||
|
await this.#waitForPromise;
|
||||||
|
}
|
||||||
|
this.#waitForPromise = new Promise((resolve) => {
|
||||||
|
this.foreachWindowAsActive(async (browser) => {
|
||||||
|
if (browser.gZenWorkspaceWindowSync && !this.windowIsActive(browser)) {
|
||||||
|
await browser.gZenWorkspaceWindowSync.onExternalTabEvent(event);
|
||||||
|
}
|
||||||
|
}).then(() => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async onExternalTabEvent(event) {
|
||||||
|
this.#ignoreNextEvents = true;
|
||||||
|
switch (event.type) {
|
||||||
|
case 'TabClose':
|
||||||
|
this.#onTabClose(event);
|
||||||
|
break;
|
||||||
|
case 'TabOpen':
|
||||||
|
await this.#onTabOpen(event);
|
||||||
|
break;
|
||||||
|
case 'TabPinned':
|
||||||
|
this.#onTabPinned(event);
|
||||||
|
break;
|
||||||
|
case 'TabUnpinned':
|
||||||
|
this.#onTabUnpinned(event);
|
||||||
|
break;
|
||||||
|
case 'TabAddedToEssentials':
|
||||||
|
this.#onTabAddedToEssentials(event);
|
||||||
|
break;
|
||||||
|
case 'TabRemovedFromEssentials':
|
||||||
|
this.#onTabRemovedFromEssentials(event);
|
||||||
|
break;
|
||||||
|
case 'TabHide':
|
||||||
|
this.#onTabHide(event);
|
||||||
|
break;
|
||||||
|
case 'TabShow':
|
||||||
|
this.#onTabShow(event);
|
||||||
|
break;
|
||||||
|
case 'TabMove':
|
||||||
|
this.#onTabMove(event);
|
||||||
|
break;
|
||||||
|
case 'ZenTabIconChanged':
|
||||||
|
this.#onTabIconChanged(event);
|
||||||
|
break;
|
||||||
|
case 'ZenTabLabelChanged':
|
||||||
|
this.#onTabLabelChanged(event);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.warn(`Unhandled event type: ${event.type}`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this.#ignoreNextEvents = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#getTabId(tab) {
|
||||||
|
return tab.getAttribute('zen-sync-id');
|
||||||
|
}
|
||||||
|
|
||||||
|
#getTabWithId(tabId) {
|
||||||
|
for (const tab of gZenWorkspaces.allStoredTabs) {
|
||||||
|
if (this.#getTabId(tab) === tabId) {
|
||||||
|
return tab;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#onTabClose(event) {
|
||||||
|
const targetTab = event.target;
|
||||||
|
const tabId = this.#getTabId(targetTab);
|
||||||
|
const tabToClose = this.#getTabWithId(tabId);
|
||||||
|
if (tabToClose) {
|
||||||
|
gBrowser.removeTab(tabToClose);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#onTabPinned(event) {
|
||||||
|
const targetTab = event.target;
|
||||||
|
if (targetTab.hasAttribute('zen-essential')) {
|
||||||
|
return this.#onTabAddedToEssentials(event);
|
||||||
|
}
|
||||||
|
const tabId = this.#getTabId(targetTab);
|
||||||
|
const elementIndex = targetTab.elementIndex;
|
||||||
|
const tabToPin = this.#getTabWithId(tabId);
|
||||||
|
if (tabToPin) {
|
||||||
|
gBrowser.pinTab(tabToPin);
|
||||||
|
gBrowser.moveTabTo(tabToPin, { elementIndex, forceUngrouped: !!targetTab.group });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#onTabUnpinned(event) {
|
||||||
|
const targetTab = event.target;
|
||||||
|
const tabId = this.#getTabId(targetTab);
|
||||||
|
const tabToUnpin = this.#getTabWithId(tabId);
|
||||||
|
if (tabToUnpin) {
|
||||||
|
gBrowser.unpinTab(tabToUnpin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#onTabIconChanged(event) {
|
||||||
|
this.#updateTabIconAndLabel(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
#onTabLabelChanged(event) {
|
||||||
|
this.#updateTabIconAndLabel(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
#updateTabIconAndLabel(event) {
|
||||||
|
const targetTab = event.target;
|
||||||
|
const tabId = this.#getTabId(targetTab);
|
||||||
|
const tabToChange = this.#getTabWithId(tabId);
|
||||||
|
if (tabToChange && tabToChange.hasAttribute('pending')) {
|
||||||
|
gBrowser.setIcon(tabToChange, gBrowser.getIcon(targetTab));
|
||||||
|
gBrowser._setTabLabel(tabToChange, targetTab.label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#onTabAddedToEssentials(event) {
|
||||||
|
const targetTab = event.target;
|
||||||
|
const tabId = this.#getTabId(targetTab);
|
||||||
|
const tabToAdd = this.#getTabWithId(tabId);
|
||||||
|
if (tabToAdd) {
|
||||||
|
gZenPinnedTabManager.addToEssentials(tabToAdd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#onTabRemovedFromEssentials(event) {
|
||||||
|
const targetTab = event.target;
|
||||||
|
const tabId = this.#getTabId(targetTab);
|
||||||
|
const tabToRemove = this.#getTabWithId(tabId);
|
||||||
|
if (tabToRemove) {
|
||||||
|
gZenPinnedTabManager.removeFromEssentials(tabToRemove);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#onTabHide(event) {
|
||||||
|
const targetTab = event.target;
|
||||||
|
const tabId = this.#getTabId(targetTab);
|
||||||
|
const tabToHide = this.#getTabWithId(tabId);
|
||||||
|
if (tabToHide) {
|
||||||
|
gBrowser.hideTab(tabToHide);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#onTabShow(event) {
|
||||||
|
const targetTab = event.target;
|
||||||
|
const tabId = this.#getTabId(targetTab);
|
||||||
|
const tabToShow = this.#getTabWithId(tabId);
|
||||||
|
if (tabToShow) {
|
||||||
|
gBrowser.showTab(tabToShow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#onTabMove(event) {
|
||||||
|
const targetTab = event.target;
|
||||||
|
const tabId = this.#getTabId(targetTab);
|
||||||
|
const tabIndex = targetTab._pPos;
|
||||||
|
const tabToMove = this.#getTabWithId(tabId);
|
||||||
|
if (tabToMove) {
|
||||||
|
gBrowser.moveTabTo(tabToMove, { tabIndex, forceUngrouped: !!targetTab.group });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async #onTabOpen(event) {
|
||||||
|
const targetTab = event.target;
|
||||||
|
const isPinned = targetTab.pinned;
|
||||||
|
const isEssential = isPinned && targetTab.hasAttribute('zen-essential');
|
||||||
|
const elementIndex = targetTab.elementIndex;
|
||||||
|
|
||||||
|
const duplicatedTab = gBrowser.addTrustedTab(targetTab.linkedBrowser.currentURI.spec, {
|
||||||
|
createLazyBrowser: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
duplicatedTab.setAttribute('zen-pin-id', targetTab.getAttribute('zen-pin-id'));
|
||||||
|
duplicatedTab.setAttribute('zen-tab-id', targetTab.getAttribute('zen-tab-id'));
|
||||||
|
duplicatedTab.setAttribute('zen-workspace-id', targetTab.getAttribute('zen-workspace-id'));
|
||||||
|
|
||||||
|
if (isEssential) {
|
||||||
|
gZenPinnedTabManager.addToEssentials(duplicatedTab);
|
||||||
|
} else if (isPinned) {
|
||||||
|
gBrowser.pinTab(duplicatedTab);
|
||||||
|
}
|
||||||
|
|
||||||
|
gBrowser.moveTabTo(duplicatedTab, { elementIndex, forceUngrouped: !!targetTab.group });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.gZenWorkspaceWindowSync = new nsZenWorkspaceWindowSync();
|
||||||
|
}
|
Reference in New Issue
Block a user