Compare commits

..

25 Commits

Author SHA1 Message Date
Mr. M
eefc8cb20c feat: Clone the previous state, b=no-bug, c=no-component 2025-11-13 17:03:27 +01:00
Mr. M
12c921fd87 feat: Run session saver before opening a new winodw, b=no-bug, c=tabs 2025-11-13 14:40:52 +01:00
mr. m
e419c4dc9f Merge branch 'dev' into window-sync
Signed-off-by: mr. m <91018726+mr-cheffy@users.noreply.github.com>
2025-11-13 13:58:38 +01:00
mr. m
68b37ac736 Discard changes to src/zen/tabs/ZenPinnedTabsStorage.mjs 2025-11-13 13:58:18 +01:00
mr. m
7f225ac3ee Discard changes to src/browser/components/tabbrowser/content/tabbrowser-js.patch 2025-11-13 13:57:55 +01:00
mr. m
3e39ef2538 Discard changes to src/browser/components/tabbrowser/content/tab-js.patch 2025-11-13 13:57:42 +01:00
mr. m
e5517eb164 Discard changes to src/browser/components/sessionstore/SessionStore-sys-mjs.patch 2025-11-13 13:57:32 +01:00
Mr. M
c4dd470864 chore: Update patches to ff 145, b=no-bug, c=no-component 2025-11-13 13:56:31 +01:00
Mr. M
bf1b0dcd48 feat: Dont restore windows that are already initialized, b=no-bug, c=no-component 2025-11-01 13:40:14 +01:00
Mr. M
76acc8b0e4 feat: Stop using pinned manager and use zen session sidebar, b=no-bug, c=common, folders, tabs, workspaces 2025-10-31 23:07:38 +01:00
mr. m
1b83b77cad Merge branch 'dev' into window-sync
Signed-off-by: mr. m <91018726+mr-cheffy@users.noreply.github.com>
2025-10-31 21:56:19 +01:00
Mr. M
79ff574978 feat: Start doing out own session restore, b=no-bug, c=folders, tabs 2025-10-29 23:57:20 +01:00
mr. m
af20a65fa1 Merge branch 'dev' into window-sync 2025-10-19 23:11:11 +02:00
mr. m
4a7f8fc9c0 Merge branch 'dev' into window-sync 2025-10-19 12:53:06 +02:00
mr. m
a738a829de Merge branch 'dev' into window-sync 2025-10-18 19:53:04 +02:00
mr. m
240a031e38 Discard changes to prefs/browser.yaml 2025-10-18 19:52:53 +02:00
Mr. M
9bc7b9ce4e Merge branch 'window-sync' of https://github.com/zen-browser/desktop into window-sync 2025-09-28 23:45:17 +02:00
Mr. M
86006c8891 feat: Start on new session restore, b=no-bug, c=no-component 2025-09-28 23:45:13 +02:00
Mr. M
a55b1c7495 feat: Properly handle tab moves, b=no-bug, c=workspaces 2025-09-27 17:54:28 +02:00
mr. m
6e6337a95b Merge branch 'dev' into window-sync 2025-09-27 16:58:29 +02:00
mr. m
6b12153c8a Merge branch 'dev' into window-sync 2025-09-27 09:35:44 +02:00
mr. m
f6922ef2ba Merge branch 'dev' into window-sync 2025-09-03 13:06:44 +02:00
Mr. M
91f5d58fbc feat: Dont session duplicate the tabs, b=no-bug, c=workspaces 2025-09-02 16:21:04 +02:00
mr. m
7a4cdaa45c feat: Also change icons and labels if the tab is pending, b=no-bug, c=tabs, workspaces 2025-09-01 16:09:59 +02:00
Mr. M
81e854a89f feat: Full cross-window workspace syncing, b=no-bug, c=workspaces 2025-08-27 23:25:07 +02:00
70 changed files with 820 additions and 951 deletions

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = إعادة تعيين علامة التبويب المثبتة .label = إعادة تعيين علامة التبويب المثبتة
.accesskey = ر .accesskey = ر
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Add to Essentials ({ $num } / { $max } slots filled)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Remove from Essentials .label = Remove from Essentials
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Restableix la pestanya fixada .label = Restableix la pestanya fixada
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Afegeix als essentials ({ $num } / { $max } espais ocupats)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Elimina dels essencials .label = Elimina dels essencials
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Resetovat připnuté karty .label = Resetovat připnuté karty
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Přidat do Essentials ({ $num } / { $max } zaplněných slotů)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Odstranit z Essentials .label = Odstranit z Essentials
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Ailosod Tab wedi'i Binio .label = Ailosod Tab wedi'i Binio
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Add to Essentials ({ $num } / { $max } slots filled)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Diddymu o Hanfodion .label = Diddymu o Hanfodion
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Nulstil fastgjort fane .label = Nulstil fastgjort fane
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Føj til Essentielle ({ $num } / { $max } pladser fyldt)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Fjern fra Essentielle .label = Fjern fra Essentielle
.accesskey = R .accesskey = R

View File

@@ -2,7 +2,7 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this # 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/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
pane-zen-looks-title = Aussehen pane-zen-looks-title = Erscheinungsbild
category-zen-looks = category-zen-looks =
.tooltiptext = { pane-zen-looks-title } .tooltiptext = { pane-zen-looks-title }
zen-warning-language = Das Ändern der Standardsprache könnte es Websites einfacher machen, Sie zu verfolgen. zen-warning-language = Das Ändern der Standardsprache könnte es Websites einfacher machen, Sie zu verfolgen.
@@ -47,10 +47,10 @@ zen-tabs-unloader-enabled =
zen-tabs-close-on-back-with-no-history = zen-tabs-close-on-back-with-no-history =
.label = Tab schließen und zum Besitzer-Tab (oder den zuletzt benutzten Tab) wechseln, wenn kein Tab-Verlauf vorhanden ist .label = Tab schließen und zum Besitzer-Tab (oder den zuletzt benutzten Tab) wechseln, wenn kein Tab-Verlauf vorhanden ist
zen-tabs-cycle-by-attribute = zen-tabs-cycle-by-attribute =
.label = Strg+Tab wechselt nur zwischen Essential- oder Arbeitsbereich-Tabs .label = Ctrl+Tab cycles within Essential or Workspace tabs only
zen-tabs-cycle-ignore-pending-tabs = zen-tabs-cycle-ignore-pending-tabs =
.label = Ausstehende Tabs beim Wechseln mit Strg+Tab ignorieren .label = Ignore Pending tabs when cycling with Ctrl+Tab
zen-tabs-cycle-by-attribute-warning = Strg+Tab wechselt in der zuletzt verwendeten Reihenfolge, da diese Option aktiviert ist zen-tabs-cycle-by-attribute-warning = Ctrl+Tab will cycle by recently used order, as it is enabled
zen-look-and-feel-compact-toolbar-themed = zen-look-and-feel-compact-toolbar-themed =
.label = Theme Hintergrund für kompakte Symbolleiste verwenden .label = Theme Hintergrund für kompakte Symbolleiste verwenden
zen-workspace-continue-where-left-off = zen-workspace-continue-where-left-off =
@@ -77,38 +77,38 @@ zen-pinned-tab-manager-close-close-shortcut-option =
.label = Tab schließen .label = Tab schließen
pane-zen-workspaces-header = Arbeitsbereiche pane-zen-workspaces-header = Arbeitsbereiche
zen-settings-workspaces-header = Allgemeine Einstellungen für Arbeitsbereiche zen-settings-workspaces-header = Allgemeine Einstellungen für Arbeitsbereiche
zen-settings-workspaces-description = Mit Arbeitsbereichen kannst du mehrere Browser-Sitzungen gleichzeitig haben zen-settings-workspaces-description = Mit Arbeitsbereichen können Sie mehrere Browser-Sitzungen gleichzeitig haben!
zen-settings-workspaces-enabled = zen-settings-workspaces-enabled =
.label = Arbeitsbereiche aktivieren (Experimentell) .label = Arbeitsbereiche aktivieren
zen-settings-workspaces-hide-default-container-indicator = zen-settings-workspaces-hide-default-container-indicator =
.label = Container-Indikator in der Tab-Leiste ausblenden .label = Standard-Container-Anzeige in der Tab-Leiste ausblenden
zen-key-unsaved = Nicht gespeichertes Tastenkürzel! Bitte speichern Sie es, indem Sie nach der Neueingabe die "Escape"-Taste drücken. zen-key-unsaved = Nicht gespeichertes Tastenkürzel! Bitte speichern Sie es, indem Sie nach der Neueingabe die "Escape"-Taste drücken.
zen-key-conflict = Konflikt mit { $group } -> { $shortcut } zen-key-conflict = Konflikt mit { $group } -> { $shortcut }
pane-zen-theme-title = Design-Einstellungen pane-zen-theme-title = Design-Einstellungen
zen-vertical-tabs-title = Seitenleiste und Tab-Layout zen-vertical-tabs-title = Seitenleiste und Tab-Layout
zen-vertical-tabs-header = Vertikale Tabs zen-vertical-tabs-header = Vertikale Tabs
zen-vertical-tabs-description = Verwalte die Ausrichtung der Tabs und andere Layout-Einstellungen zen-vertical-tabs-description = Verwalten Sie Ihre Tabs in einem vertikalen Layout
zen-vertical-tabs-show-expand-button = zen-vertical-tabs-show-expand-button =
.label = Erweitern-Schaltfläche anzeigen .label = Erweitern-Schaltfläche anzeigen
zen-vertical-tabs-newtab-on-tab-list = zen-vertical-tabs-newtab-on-tab-list =
.label = "Neuen Tab"-Button in der Tab-Liste anzeigen .label = Schaltfläche "Neuer Tab" in der Tab-Liste anzeigen
zen-vertical-tabs-newtab-top-button-up = zen-vertical-tabs-newtab-top-button-up =
.label = Schaltfläche "Neuer Tab" nach oben verschieben .label = Schaltfläche "Neuer Tab" nach oben verschieben
zen-vertical-tabs-expand-tabs-by-default = Tabs standardmäßig erweitern zen-vertical-tabs-expand-tabs-by-default = Tabs standardmäßig erweitern
zen-vertical-tabs-dont-expand-tabs-by-default = Tabs standardmäßig nicht erweitern zen-vertical-tabs-dont-expand-tabs-by-default = Tabs standardmäßig nicht erweitern
zen-vertical-tabs-expand-tabs-on-hover = Tabs bei Hover erweitern (funktioniert nicht im Kompaktmodus) zen-vertical-tabs-expand-tabs-on-hover = Tabs beim Drüberfahren erweitern (funktioniert nicht im Kompaktmodus)
zen-vertical-tabs-expand-tabs-header = Wie Tabs erweitert werden sollen zen-vertical-tabs-expand-tabs-header = Wie Tabs erweitert werden sollen
zen-vertical-tabs-expand-tabs-description = Wähle aus, wie Tabs in der Seitenleiste erweitert werden sollen zen-vertical-tabs-expand-tabs-description = Wählen Sie, wie Tabs in der Seitenleiste erweitert werden sollen
zen-theme-marketplace-header = Zen Mods zen-theme-marketplace-header = Zen Mods
zen-theme-disable-all-enabled = zen-theme-disable-all-enabled =
.title = Alle Mods deaktivieren .title = Alle Mods deaktivieren
zen-theme-disable-all-disabled = zen-theme-disable-all-disabled =
.title = Alle Mods aktivieren .title = Alle Mods aktivieren
zen-theme-marketplace-description = Finde und installiere Designs aus dem Store. zen-theme-marketplace-description = Finden und installieren Sie Mods aus dem Store.
zen-theme-marketplace-remove-button = zen-theme-marketplace-remove-button =
.label = Design entfernen .label = Mod entfernen
zen-theme-marketplace-check-for-updates-button = zen-theme-marketplace-check-for-updates-button =
.label = Nach Updates suchen .label = Auf Updates prüfen
zen-theme-marketplace-import-button = zen-theme-marketplace-import-button =
.label = Mods importieren .label = Mods importieren
zen-theme-marketplace-export-button = zen-theme-marketplace-export-button =
@@ -117,20 +117,20 @@ zen-theme-marketplace-import-success = Mods erfolgreich importiert
zen-theme-marketplace-import-failure = Beim Importieren der Mods ist ein Fehler aufgetreten zen-theme-marketplace-import-failure = Beim Importieren der Mods ist ein Fehler aufgetreten
zen-theme-marketplace-export-success = Mods erfolgreich exportiert zen-theme-marketplace-export-success = Mods erfolgreich exportiert
zen-theme-marketplace-export-failure = Beim Exportieren der Mods ist ein Fehler aufgetreten zen-theme-marketplace-export-failure = Beim Exportieren der Mods ist ein Fehler aufgetreten
zen-theme-marketplace-updates-success = Design erfolgreich aktualisiert zen-theme-marketplace-updates-success = Mods wurden erfolgreich aktualisiert
zen-theme-marketplace-updates-failure = Es konnten keine Updates gefunden werden! zen-theme-marketplace-updates-failure = Es konnten keine Updates gefunden werden!
zen-theme-marketplace-toggle-enabled-button = zen-theme-marketplace-toggle-enabled-button =
.title = Design deaktivieren .title = Mod deaktivieren
zen-theme-marketplace-toggle-disabled-button = zen-theme-marketplace-toggle-disabled-button =
.title = Design aktivieren .title = Mod aktivieren
zen-theme-marketplace-remove-confirmation = Möchtest du dieses Mod wirklich entfernen? zen-theme-marketplace-remove-confirmation = Sind Sie sicher, dass Sie diesen Mod entfernen möchten?
zen-theme-marketplace-close-modal = Schließen zen-theme-marketplace-close-modal = Schließen
zen-theme-marketplace-theme-header-title = zen-theme-marketplace-theme-header-title =
.title = CSS-Selektor: { $name } .title = CSS-Selektor: { $name }
zen-theme-marketplace-dropdown-default-label = zen-theme-marketplace-dropdown-default-label =
.label = Keine .label = Keine
zen-theme-marketplace-input-default-placeholder = zen-theme-marketplace-input-default-placeholder =
.placeholder = Gib etwas ein... .placeholder = Etwas eingeben...
pane-zen-marketplace-title = Zen Mods pane-zen-marketplace-title = Zen Mods
zen-themes-auto-update = zen-themes-auto-update =
.label = Installierte Mods beim Start automatisch aktualisieren .label = Installierte Mods beim Start automatisch aktualisieren
@@ -160,24 +160,24 @@ category-zen-CKS =
.tooltiptext = { pane-zen-CKS-title } .tooltiptext = { pane-zen-CKS-title }
pane-settings-CKS-title = { -brand-short-name } Tastenkürzel pane-settings-CKS-title = { -brand-short-name } Tastenkürzel
zen-settings-CKS-header = Passen Sie Ihre Tastenkürzel an zen-settings-CKS-header = Passen Sie Ihre Tastenkürzel an
zen-settings-CKS-description = Ändere die Standard-Tastenkürzel nach deinen Wünschen und verbessere dein Browser-Erlebnis zen-settings-CKS-description = Ändern Sie die Standard-Tastenkürzel nach Ihren Wünschen und verbessern Sie Ihr Browser-Erlebnis
zen-settings-CKS-disable-firefox = zen-settings-CKS-disable-firefox =
.label = { -brand-short-name } Standard-Tastenkürzel deaktivieren .label = { -brand-short-name } Standard-Tastenkürzel deaktivieren
zen-settings-CKS-duplicate-shortcut = zen-settings-CKS-duplicate-shortcut =
.label = Doppeltes Tastenkürzel .label = Tastenkürzel duplizieren
zen-settings-CKS-reset-shortcuts = zen-settings-CKS-reset-shortcuts =
.label = Auf Standard zurücksetzen .label = Auf Standard zurücksetzen
zenCKSOption-group-other = Sonstiges zenCKSOption-group-other = Sonstige
zenCKSOption-group-windowAndTabManagement = Fenster- und Tab-Verwaltung zenCKSOption-group-windowAndTabManagement = Fenster- & Tab-Verwaltung
zenCKSOption-group-navigation = Navigation zenCKSOption-group-navigation = Navigation
zenCKSOption-group-searchAndFind = Suchen und Finden zenCKSOption-group-searchAndFind = Suchen & Finden
zenCKSOption-group-pageOperations = Seitenoperationen zenCKSOption-group-pageOperations = Seitenoperationen
zenCKSOption-group-historyAndBookmarks = Verlauf & Lesezeichen zenCKSOption-group-historyAndBookmarks = Verlauf & Lesezeichen
zenCKSOption-group-mediaAndDisplay = Medien & Anzeige zenCKSOption-group-mediaAndDisplay = Medien & Anzeige
zenCKSOption-group-zen-compact-mode = Kompaktmodus zenCKSOption-group-zen-compact-mode = Kompaktmodus
zenCKSOption-group-zen-workspace = Zen Arbeitsbereiche zenCKSOption-group-zen-workspace = Arbeitsbereiche
zenCKSOption-group-zen-other = Andere Zen-Funktionen zenCKSOption-group-zen-other = Andere Zen-Funktionen
zenCKSOption-group-zen-split-view = Zen Geteilte Ansicht zenCKSOption-group-zen-split-view = Geteilte Ansicht
zenCKSOption-group-devTools = Entwicklertools zenCKSOption-group-devTools = Entwicklertools
zen-key-quick-restart = Schneller Neustart zen-key-quick-restart = Schneller Neustart
zen-window-new-shortcut = Neues Fenster zen-window-new-shortcut = Neues Fenster
@@ -186,7 +186,7 @@ zen-key-redo = Wiederholen
zen-restore-last-closed-tab-shortcut = Letzten geschlossenen Tab wiederherstellen zen-restore-last-closed-tab-shortcut = Letzten geschlossenen Tab wiederherstellen
zen-location-open-shortcut = Adresse öffnen zen-location-open-shortcut = Adresse öffnen
zen-location-open-shortcut-alt = Adresse öffnen (Alt) zen-location-open-shortcut-alt = Adresse öffnen (Alt)
zen-key-undo-close-window = Geschlossenes Fenster wiederherstellen zen-key-undo-close-window = Fenster schließen rückgängig machen
zen-text-action-undo-shortcut = Rückgängig zen-text-action-undo-shortcut = Rückgängig
zen-text-action-redo-shortcut = Wiederholen zen-text-action-redo-shortcut = Wiederholen
zen-text-action-cut-shortcut = Ausschneiden zen-text-action-cut-shortcut = Ausschneiden
@@ -196,15 +196,15 @@ zen-text-action-copy-url-markdown-shortcut = Aktuelle URL als Markdown kopieren
zen-text-action-paste-shortcut = Einfügen zen-text-action-paste-shortcut = Einfügen
zen-text-action-select-all-shortcut = Alles auswählen zen-text-action-select-all-shortcut = Alles auswählen
zen-text-action-delete-shortcut = Löschen zen-text-action-delete-shortcut = Löschen
zen-history-show-all-shortcut-mac = Verlauf anzeigen (Mac) zen-history-show-all-shortcut-mac = Gesamten Verlauf anzeigen (Mac)
zen-full-screen-shortcut = Vollbild umschalten zen-full-screen-shortcut = Vollbild umschalten
zen-reader-mode-toggle-shortcut-windows = Lesemodus umschalten (Windows) zen-reader-mode-toggle-shortcut-windows = Lesemodus umschalten (Windows)
zen-picture-in-picture-toggle-shortcut-alt = Bild-im-Bild umschalten (Alt) zen-picture-in-picture-toggle-shortcut-alt = Bild-in-Bild umschalten (Alt)
zen-picture-in-picture-toggle-shortcut-mac = Bild-im-Bild umschalten (Mac) zen-picture-in-picture-toggle-shortcut-mac = Bild-in-Bild umschalten (Mac)
zen-picture-in-picture-toggle-shortcut-mac-alt = Bild-im-Bild umschalten (Mac Alternative) zen-picture-in-picture-toggle-shortcut-mac-alt = Bild-in-Bild umschalten (Mac Alt)
zen-page-source-shortcut-safari = Seitenquelltext (Safari) zen-page-source-shortcut-safari = Seitenquelltext anzeigen (Safari)
zen-nav-stop-shortcut = Navigation stoppen zen-nav-stop-shortcut = Laden stoppen
zen-history-sidebar-shortcut = Verlaufs-Seitenleiste zen-history-sidebar-shortcut = Verlauf-Seitenleiste anzeigen
zen-window-minimize-shortcut = Fenster minimieren zen-window-minimize-shortcut = Fenster minimieren
zen-help-shortcut = Hilfe öffnen zen-help-shortcut = Hilfe öffnen
zen-preferences-shortcut = Einstellungen öffnen zen-preferences-shortcut = Einstellungen öffnen
@@ -218,11 +218,11 @@ zen-file-open-shortcut = Datei öffnen
zen-save-page-shortcut = Seite speichern zen-save-page-shortcut = Seite speichern
zen-print-shortcut = Seite drucken zen-print-shortcut = Seite drucken
zen-close-shortcut-2 = Tab schließen zen-close-shortcut-2 = Tab schließen
zen-mute-toggle-shortcut = Stumm schalten umschalten zen-mute-toggle-shortcut = Stummschaltung umschalten
zen-key-delete = Löschen-Taste zen-key-delete = Entfernen-Taste
zen-key-go-back = Zurück gehen zen-key-go-back = Zurück gehen
zen-key-go-forward = Vorwärts gehen zen-key-go-forward = Vorwärts gehen
zen-nav-back-shortcut-alt = Zurück navigieren (Alt) zen-nav-back-shortcut-alt = Rückwärts navigieren (Alt)
zen-nav-fwd-shortcut-alt = Vorwärts navigieren (Alt) zen-nav-fwd-shortcut-alt = Vorwärts navigieren (Alt)
zen-history-show-all-shortcut = Gesamten Verlauf anzeigen zen-history-show-all-shortcut = Gesamten Verlauf anzeigen
zen-key-enter-full-screen = Vollbild aktivieren zen-key-enter-full-screen = Vollbild aktivieren
@@ -232,15 +232,15 @@ zen-key-inspector-mac = Inspektor umschalten (Mac)
zen-toggle-sidebar-shortcut = Firefox-Seitenleiste umschalten zen-toggle-sidebar-shortcut = Firefox-Seitenleiste umschalten
zen-toggle-pin-tab-shortcut = Angepinnter Tab umschalten zen-toggle-pin-tab-shortcut = Angepinnter Tab umschalten
zen-reader-mode-toggle-shortcut-other = Lesemodus umschalten zen-reader-mode-toggle-shortcut-other = Lesemodus umschalten
zen-picture-in-picture-toggle-shortcut = Bild-im-Bild umschalten zen-picture-in-picture-toggle-shortcut = Bild-in-Bild umschalten
zen-nav-reload-shortcut-2 = Seite neu laden zen-nav-reload-shortcut-2 = Seite neu laden
zen-key-about-processes = Über Prozesse zen-key-about-processes = Über Prozesse
zen-page-source-shortcut = Seitenquelltext anzeigen zen-page-source-shortcut = Seitenquelltext anzeigen
zen-page-info-shortcut = Seiteninformationen anzeigen zen-page-info-shortcut = Seiteninformationen anzeigen
zen-find-shortcut = Auf Seite suchen zen-find-shortcut = Auf Seite suchen
zen-search-find-again-shortcut = Weitersuchen zen-search-find-again-shortcut = Erneut suchen
zen-search-find-again-shortcut-prev = Vorheriges suchen zen-search-find-again-shortcut-prev = Vorheriges suchen
zen-search-find-again-shortcut-2 = Weitersuchen (Alt) zen-search-find-again-shortcut-2 = Erneut suchen (Alt)
zen-bookmark-this-page-shortcut = Diese Seite zu Lesezeichen hinzufügen zen-bookmark-this-page-shortcut = Diese Seite zu Lesezeichen hinzufügen
zen-bookmark-show-library-shortcut = Lesezeichen-Bibliothek anzeigen zen-bookmark-show-library-shortcut = Lesezeichen-Bibliothek anzeigen
zen-key-stop = Laden stoppen zen-key-stop = Laden stoppen
@@ -250,13 +250,13 @@ zen-full-zoom-reset-shortcut = Zoom zurücksetzen
zen-full-zoom-reset-shortcut-alt = Zoom zurücksetzen (Alt) zen-full-zoom-reset-shortcut-alt = Zoom zurücksetzen (Alt)
zen-full-zoom-enlarge-shortcut-alt = Hineinzoomen (Alt) zen-full-zoom-enlarge-shortcut-alt = Hineinzoomen (Alt)
zen-full-zoom-enlarge-shortcut-alt2 = Hineinzoomen (Alt 2) zen-full-zoom-enlarge-shortcut-alt2 = Hineinzoomen (Alt 2)
zen-bidi-switch-direction-shortcut = Text-Richtung wechseln zen-bidi-switch-direction-shortcut = Textrichtung wechseln
zen-private-browsing-shortcut = Privaten Modus öffnen zen-private-browsing-shortcut = Privates Surfen
zen-screenshot-shortcut = Screenshot machen zen-screenshot-shortcut = Screenshot erstellen
zen-key-sanitize = Browser-Daten löschen zen-key-sanitize = Browserdaten löschen
zen-quit-app-shortcut = Anwendung beenden zen-quit-app-shortcut = Anwendung beenden
zen-key-wr-capture-cmd = WR-Aufnahme-Befehl zen-key-wr-capture-cmd = WR Aufnahmebefehl
zen-key-wr-toggle-capture-sequence-cmd = WR-Aufnahmesequenz umschalten zen-key-wr-toggle-capture-sequence-cmd = WR Aufnahmesequenz umschalten
zen-nav-reload-shortcut = Seite neu laden zen-nav-reload-shortcut = Seite neu laden
zen-nav-reload-shortcut-skip-cache = Seite neu laden (Cache überspringen) zen-nav-reload-shortcut-skip-cache = Seite neu laden (Cache überspringen)
zen-close-shortcut = Fenster schließen zen-close-shortcut = Fenster schließen
@@ -275,13 +275,13 @@ zen-workspace-shortcut-switch-7 = Zu Arbeitsbereich 7 wechseln
zen-workspace-shortcut-switch-8 = Zu Arbeitsbereich 8 wechseln zen-workspace-shortcut-switch-8 = Zu Arbeitsbereich 8 wechseln
zen-workspace-shortcut-switch-9 = Zu Arbeitsbereich 9 wechseln zen-workspace-shortcut-switch-9 = Zu Arbeitsbereich 9 wechseln
zen-workspace-shortcut-switch-10 = Zu Arbeitsbereich 10 wechseln zen-workspace-shortcut-switch-10 = Zu Arbeitsbereich 10 wechseln
zen-workspace-shortcut-forward = Zum nächsten Arbeitsbereich wechseln zen-workspace-shortcut-forward = Nächster Arbeitsbereich
zen-workspace-shortcut-backward = Zum vorherigen Arbeitsbereich wechseln zen-workspace-shortcut-backward = Vorheriger Arbeitsbereich
zen-sidebar-shortcut-toggle = Seitenleisten-Breite umschalten zen-sidebar-shortcut-toggle = Seitenleisten-Breite umschalten
zen-pinned-tab-shortcut-reset = Angehefteten Tab zurücksetzen zen-pinned-tab-shortcut-reset = Angepinnten Tab auf angepinnte URL zurücksetzen
zen-split-view-shortcut-grid = Raster-Layout für geteilte Ansicht umschalten zen-split-view-shortcut-grid = Geteilte Ansicht Raster umschalten
zen-split-view-shortcut-vertical = Vertikales Layout für geteilte Ansicht umschalten zen-split-view-shortcut-vertical = Geteilte Ansicht vertikal umschalten
zen-split-view-shortcut-horizontal = Horizontales Layout für geteilte Ansicht umschalten zen-split-view-shortcut-horizontal = Geteilte Ansicht horizontal umschalten
zen-split-view-shortcut-unsplit = Geteilte Ansicht schließen zen-split-view-shortcut-unsplit = Geteilte Ansicht schließen
zen-new-empty-split-view-shortcut = Neuer leerer Split View zen-new-empty-split-view-shortcut = Neuer leerer Split View
zen-key-select-tab-1 = Tab #1 auswählen zen-key-select-tab-1 = Tab #1 auswählen

View File

@@ -22,4 +22,4 @@ zen-folders-unload-all-tooltip =
.tooltiptext = Aktive Tabs in diesem Ordner entladen .tooltiptext = Aktive Tabs in diesem Ordner entladen
zen-folders-unload-folder = zen-folders-unload-folder =
.label = Alle Tabs entladen .label = Alle Tabs entladen
zen-folders-search-no-results = Keine passenden Tabs gefunden zen-folders-search-no-results = Keine passenden Tabs gefunden 🤔

View File

@@ -5,24 +5,23 @@
zen-panel-ui-current-profile-text = Aktuelles Profil zen-panel-ui-current-profile-text = Aktuelles Profil
unified-extensions-description = Erweiterungen werden verwendet, um { -brand-short-name } zusätzliche Funktionen hinzuzufügen. unified-extensions-description = Erweiterungen werden verwendet, um { -brand-short-name } zusätzliche Funktionen hinzuzufügen.
tab-context-zen-reset-pinned-tab = tab-context-zen-reset-pinned-tab =
.label = Angehefteten Tab zurücksetzen .label = Angepinnten Tab zurücksetzen
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Zu Essentials hinzufügen ({ $num } / { $max } Plätze belegt)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Aus Essentials entfernen .label = Aus Essentials entfernen
.accesskey = R .accesskey = R
tab-context-zen-replace-pinned-url-with-current = tab-context-zen-replace-pinned-url-with-current =
.label = Angeheftete URL durch aktuelle ersetzen .label = Angepinnte URL durch aktuelle ersetzen
.accesskey = C .accesskey = C
zen-themes-corrupted = Deine { -brand-short-name } Mods-Datei ist beschädigt. Sie wurde auf das Standard-Design zurückgesetzt. zen-themes-corrupted = Ihre { -brand-short-name } Mods-Datei ist beschädigt. Sie wurde auf das Standard-Design zurückgesetzt.
zen-shortcuts-corrupted = Deine { -brand-short-name } Tastenkürzel-Datei ist beschädigt. Sie wurde auf die Standard-Tastenkürzel zurückgesetzt. zen-shortcuts-corrupted = Ihre { -brand-short-name } Tastenkürzel-Datei ist beschädigt. Sie wurde auf die Standard-Tastenkürzel zurückgesetzt.
# note: Do not translate the "<br/>" tags in the following string # note: Do not translate the "<br/>" tags in the following string
zen-new-urlbar-notification = zen-new-urlbar-notification =
Die neue Adressleiste wurde aktiviert und macht neue Tab-Seiten überflüssig.<br/><br/> Die neue Adressleiste wurde aktiviert und macht neue Tab-Seiten überflüssig.<br/><br/>
Öffne einen neuen Tab, um die neue Adressleiste in Aktion zu sehen! Öffnen Sie einen neuen Tab, um die neue Adressleiste in Aktion zu sehen!
zen-disable = Deaktivieren zen-disable = Deaktivieren
pictureinpicture-minimize-btn = pictureinpicture-minimize-btn =
.aria-label = Minimieren .aria-label = Minimieren
@@ -34,7 +33,7 @@ zen-general-cancel-label =
.label = Abbrechen .label = Abbrechen
zen-general-confirm = zen-general-confirm =
.label = Bestätigen .label = Bestätigen
zen-pinned-tab-replaced = Die URL des angehefteten Tabs wurde durch die aktuelle URL ersetzt! zen-pinned-tab-replaced = Die URL des angepinnten Tabs wurde durch die aktuelle URL ersetzt!
zen-tabs-renamed = Tab wurde erfolgreich umbenannt! zen-tabs-renamed = Tab wurde erfolgreich umbenannt!
zen-background-tab-opened-toast = Neuer Hintergrund-Tab geöffnet! zen-background-tab-opened-toast = Neuer Hintergrund-Tab geöffnet!
zen-workspace-renamed-toast = Arbeitsbereich wurde erfolgreich umbenannt! zen-workspace-renamed-toast = Arbeitsbereich wurde erfolgreich umbenannt!
@@ -44,7 +43,7 @@ zen-library-sidebar-mods =
.label = Mods .label = Mods
zen-toggle-compact-mode-button = zen-toggle-compact-mode-button =
.label = Kompakter Modus .label = Kompakter Modus
.tooltiptext = Kompakten Modus umschalten .tooltiptext = Compact Mode umschalten
# note: Do not translate the "<br/>" tags in the following string # note: Do not translate the "<br/>" tags in the following string
@@ -93,8 +92,8 @@ zen-site-data-setting-site-protection = Tracking-Schutz
# Section: Feature callouts # Section: Feature callouts
zen-site-data-panel-feature-callout-title = Ein neuer Ort für Add-ons, Berechtigungen und mehr zen-site-data-panel-feature-callout-title = Eine neue Heimat für Add-ons, Berechtigungen und mehr
zen-site-data-panel-feature-callout-subtitle = Klicke auf das Symbol, um Website-Einstellungen zu verwalten, Sicherheitsinformationen anzuzeigen, auf Erweiterungen zuzugreifen und häufige Aktionen auszuführen. zen-site-data-panel-feature-callout-subtitle = Klicken Sie auf das Symbol, um Website-Einstellungen zu verwalten, Sicherheitsinformationen anzuzeigen, auf Erweiterungen zuzugreifen und häufige Aktionen auszuführen.
zen-open-link-in-glance = zen-open-link-in-glance =
.label = Link in Glance öffnen .label = Open Link in Glance
.accesskey = G .accesskey = G

View File

@@ -33,7 +33,7 @@ tabbrowser-unload-tab-button =
tabbrowser-reset-pin-button = tabbrowser-reset-pin-button =
.tooltiptext = .tooltiptext =
{ $tabCount -> { $tabCount ->
[one] Tab zurücksetzen und anheften [one] Tab zurücksetzen und anpinnen
*[other] { $tabCount } Tabs zurücksetzen und anheften *[other] { $tabCount } Tabs zurücksetzen und anpinnen
} }
tab-reset-pin-label = Zurück zur angehefteten URL tab-reset-pin-label = Zurück zur angepinnten URL

View File

@@ -6,21 +6,21 @@ zen-welcome-title-line1 = Willkommen zu
zen-welcome-title-line2 = einem ruhigeren Internet zen-welcome-title-line2 = einem ruhigeren Internet
zen-welcome-import-title = Ein neuer Anfang, dieselben Lesezeichen zen-welcome-import-title = Ein neuer Anfang, dieselben Lesezeichen
zen-welcome-import-description-1 = Ihre Lesezeichen, Ihr Verlauf und Ihre Passwörter sind wie eine Spur durch das Internet lassen Sie sie nicht zurück! zen-welcome-import-description-1 = Ihre Lesezeichen, Ihr Verlauf und Ihre Passwörter sind wie eine Spur durch das Internet lassen Sie sie nicht zurück!
zen-welcome-import-description-2 = Übertrage sie ganz einfach aus einem anderen Browser und mache genau dort weiter, wo du aufgehört hast. zen-welcome-import-description-2 = Übertragen Sie sie ganz einfach aus einem anderen Browser und machen Sie genau dort weiter, wo Sie aufgehört haben.
zen-welcome-import-button = Jetzt importieren zen-welcome-import-button = Jetzt importieren
zen-welcome-set-default-browser = { -brand-short-name } als Standardbrowser festlegen zen-welcome-set-default-browser = { -brand-short-name } als Standardbrowser festlegen
zen-welcome-dont-set-default-browser = { -brand-short-name } NICHT als Standardbrowser festlegen zen-welcome-dont-set-default-browser = { -brand-short-name } NICHT als Standardbrowser festlegen
zen-welcome-initial-essentials-title = Deine wichtigsten Tabs, immer in Reichweite zen-welcome-initial-essentials-title = Ihre wichtigsten Tabs, immer in Reichweite
zen-welcome-initial-essentials-description-1 = Halte deine wichtigsten Tabs leicht zugänglich und immer griffbereit, egal wie viele du öffnest. zen-welcome-initial-essentials-description-1 = Halten Sie Ihre wichtigsten Tabs leicht zugänglich und immer griffbereit, egal wie viele Sie öffnen.
zen-welcome-initial-essentials-description-2 = Essential-Tabs sind immer sichtbar, unabhängig davon, in welchem Arbeitsbereich du dich befindest. zen-welcome-initial-essentials-description-2 = Essential-Tabs sind immer sichtbar, unabhängig davon, in welchem Arbeitsbereich Sie sich befinden.
zen-welcome-workspace-colors-title = Deine Arbeitsbereiche, deine Farben zen-welcome-workspace-colors-title = Ihre Arbeitsbereiche, Ihre Farben
zen-welcome-workspace-colors-description = Personalisieren Sie Ihren Browser, indem Sie jedem Arbeitsbereich eine eigene Farbidentität geben. zen-welcome-workspace-colors-description = Personalisieren Sie Ihren Browser, indem Sie jedem Arbeitsbereich eine eigene Farbidentität geben.
zen-welcome-start-browsing-title = zen-welcome-start-browsing-title =
Alles bereit?<br/> Alles bereit?<br/>
Dann kann es losgehen! Dann kann es losgehen!
zen-welcome-start-browsing-description-1 = Du bist startklar! Klicke auf die Schaltfläche unten, um mit { -brand-short-name } zu beginnen. zen-welcome-start-browsing-description-1 = Sie sind startklar! Klicken Sie auf die Schaltfläche unten, um mit { -brand-short-name } zu beginnen.
zen-welcome-start-browsing = Los geht's! zen-welcome-start-browsing = Los geht's!
zen-welcome-default-search-title = Ihre Standard-Suchmaschine zen-welcome-default-search-title = Ihre Standard-Suchmaschine
zen-welcome-default-search-description = Wähle deine Standard-Suchmaschine. Du kannst sie jederzeit später ändern! zen-welcome-default-search-description = Wählen Sie Ihre Standard-Suchmaschine. Sie können diese später jederzeit ändern!
zen-welcome-skip-button = Überspringen zen-welcome-skip-button = Überspringen
zen-welcome-finished = Dein Zen wurde erfolgreich eingerichtet! zen-welcome-finished = Ihr Zen wurde erfolgreich eingerichtet!

View File

@@ -8,20 +8,20 @@ zen-panel-ui-workspaces-create =
zen-panel-ui-folder-create = zen-panel-ui-folder-create =
.label = Ordner erstellen .label = Ordner erstellen
zen-panel-ui-new-empty-split = zen-panel-ui-new-empty-split =
.label = Neuen Split erstellen .label = Split View erstellen
zen-workspaces-panel-context-delete = zen-workspaces-panel-context-delete =
.label = Arbeitsbereich löschen .label = Arbeitsbereich löschen
.accesskey = D .accesskey = D
zen-workspaces-panel-change-name = zen-workspaces-panel-change-name =
.label = Namen ändern .label = Name ändern
zen-workspaces-panel-change-icon = zen-workspaces-panel-change-icon =
.label = Symbol ändern .label = Symbol ändern
zen-workspaces-panel-context-default-profile = zen-workspaces-panel-context-default-profile =
.label = Profil festlegen .label = Profil festlegen
zen-workspaces-panel-unload = zen-workspaces-panel-unload =
.label = Arbeitsbereich entladen .label = Arbeitsbereich entladen
zen-workspaces-how-to-reorder-title = So ordnest du Arbeitsbereiche neu an zen-workspaces-how-to-reorder-title = Wie Arbeitsbereiche neu angeordnet werden
zen-workspaces-how-to-reorder-desc = Ziehe die Arbeitsbereich-Symbole am unteren Rand der Seitenleiste, um sie neu anzuordnen zen-workspaces-how-to-reorder-desc = Ziehen Sie die Arbeitsbereich-Symbole am unteren Rand der Seitenleiste, um sie neu anzuordnen
zen-workspaces-change-theme = zen-workspaces-change-theme =
.label = Design bearbeiten .label = Design bearbeiten
zen-workspaces-panel-context-open = zen-workspaces-panel-context-open =
@@ -54,12 +54,12 @@ zen-workspaces-panel-context-reorder =
zen-workspace-creation-profile = Profil zen-workspace-creation-profile = Profil
.tooltiptext = Profile werden verwendet, um Cookies und Website-Daten zwischen Arbeitsbereichen zu trennen. .tooltiptext = Profile werden verwendet, um Cookies und Website-Daten zwischen Arbeitsbereichen zu trennen.
zen-workspace-creation-header = Arbeitsbereich erstellen zen-workspace-creation-header = Arbeitsbereich erstellen
zen-workspace-creation-label = Arbeitsbereiche helfen dir, deine Tabs und Sitzungen zu organisieren. zen-workspace-creation-label = Arbeitsbereiche werden verwendet, um Ihre Tabs und Sitzungen zu organisieren.
zen-workspaces-delete-workspace-title = Arbeitsbereich löschen? zen-workspaces-delete-workspace-title = Arbeitsbereich löschen?
zen-workspaces-delete-workspace-body = Möchtest du { $name } wirklich löschen? Diese Aktion kann nicht rückgängig gemacht werden. zen-workspaces-delete-workspace-body = Sind Sie sicher, dass Sie { $name } löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden.
# Note that the html tag MUST not be changed or removed, as it is used to better # Note that the html tag MUST not be changed or removed, as it is used to better
# display the shortcut in the toast notification. # display the shortcut in the toast notification.
zen-workspaces-close-all-unpinned-tabs-toast = Tabs geschlossen! Nutze <span>{ $shortcut }</span> , um rückgängig zu machen. zen-workspaces-close-all-unpinned-tabs-toast = Tabs geschlossen! Nutze <span>{ $shortcut }</span> , um rückgängig zu machen.
zen-workspaces-close-all-unpinned-tabs-title = zen-workspaces-close-all-unpinned-tabs-title =
.label = Aufräumen .label = Löschen
.tooltiptext = Alle nicht angehefteten Tabs schließen .tooltiptext = Alle nicht angehefteten Tabs schließen

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Επαναφορά Καρφιτσωμένης Καρτέλας .label = Επαναφορά Καρφιτσωμένης Καρτέλας
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Προσθήκη στα Απαραίτητα ({ $num } / { $max } θέσεις γεμάτες)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Αφαίρεση από Απαραίτητα .label = Αφαίρεση από Απαραίτητα
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Reset Pinned Tab .label = Reset Pinned Tab
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Add to Essentials ({ $num } / { $max } slots filled)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Remove from Essentials .label = Remove from Essentials
.accesskey = R .accesskey = R

View File

@@ -9,9 +9,8 @@ tab-context-zen-reset-pinned-tab =
.label = Reset Pinned Tab .label = Reset Pinned Tab
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Add to Essentials ({ $num } / { $max } slots filled)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Remove from Essentials .label = Remove from Essentials
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Restablecer pestaña fijada .label = Restablecer pestaña fijada
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Añadir a esenciales ({ $num } / { $max } huecos llenos)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Quitar de esenciales .label = Quitar de esenciales
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Lähtesta püsikaart .label = Lähtesta püsikaart
.accesskey = p .accesskey = p
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Märgi oluliseks ({ $num } / { $max } täidetud)
.accesskey = o .accesskey = o
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Eemalda olulistest .label = Eemalda olulistest
.accesskey = o .accesskey = o

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Reset Pinned Tab .label = Reset Pinned Tab
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Add to Essentials ({ $num } / { $max } slots filled)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Remove from Essentials .label = Remove from Essentials
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Nollaa Kiinnitetty Välilehti .label = Nollaa Kiinnitetty Välilehti
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Add to Essentials ({ $num } / { $max } slots filled)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Poista olennaisista .label = Poista olennaisista
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Réinitialiser longlet épinglé .label = Réinitialiser longlet épinglé
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Ajouter aux Essentials ({ $num } / { $max } emplacements occupés)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Retirer des Essentials .label = Retirer des Essentials
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Athshocraigh an Cluaisín Prionáilte .label = Athshocraigh an Cluaisín Prionáilte
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Cuir le Bunriachtanais ({ $num } / { $max } sliotán líonta)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Bain de na Bunriachtanais .label = Bain de na Bunriachtanais
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = אפס כרטיסייה מוצמדת .label = אפס כרטיסייה מוצמדת
.accesskey = ר .accesskey = ר
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = הוסף לנחוצים ({ $num } / { $max } מקומות מלאים)
.accesskey = ק .accesskey = ק
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = הסר מנחוצים .label = הסר מנחוצים
.accesskey = ר .accesskey = ר

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Kitűzött lap visszaállítása .label = Kitűzött lap visszaállítása
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Felvétel az alapvetőkbe ({ $num } / { $max } hely foglalt)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Eltávolítás az alapvetőkből .label = Eltávolítás az alapvetőkből
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Kembalikan ke URL Awal .label = Kembalikan ke URL Awal
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Tambahkan ke Essentials ({ $num } / { $max } slot terisi)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Hapus dari Essentials .label = Hapus dari Essentials
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Endursetja Festan Flipa .label = Endursetja Festan Flipa
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Add to Essentials ({ $num } / { $max } slots filled)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Fjarlægja frá Höfuðatriði .label = Fjarlægja frá Höfuðatriði
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Reimposta scheda fissata .label = Reimposta scheda fissata
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Aggiungi a Essenziali ({ $num } / { $max } slot riempiti)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Rimuovi dagli Essenziali .label = Rimuovi dagli Essenziali
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = ピン留めされたタブをリセット .label = ピン留めされたタブをリセット
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Add to Essentials ({ $num } / { $max } slots filled)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Essentialsから削除 .label = Essentialsから削除
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = 고정된 탭 초기화 .label = 고정된 탭 초기화
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = 에센셜에 추가 ({ $num } / { $max } 개 추가됨)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = 에센셜에서 제거하기 .label = 에센셜에서 제거하기
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Atkurti prisegtą kortelę .label = Atkurti prisegtą kortelę
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Įtraukti į būtiniausius ({ $num } / { $max } užpildytų vietų)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Šalinti iš būtiniausių .label = Šalinti iš būtiniausių
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Vastgezette tabblad resetten .label = Vastgezette tabblad resetten
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Toevoegen aan Essentials ({ $num } / { $max } plekken gevuld)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Verwijderen uit Essentials .label = Verwijderen uit Essentials
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Reset Pinned Tab .label = Reset Pinned Tab
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Add to Essentials ({ $num } / { $max } slots filled)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Remove from Essentials .label = Remove from Essentials
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Resetuj przypiętą kartę .label = Resetuj przypiętą kartę
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Dodaj do Niezbędnych ({ $num } / { $max } miejsc wypełnione)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Usuń z Niezbędnych .label = Usuń z Niezbędnych
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Redefinir Guia Fixada .label = Redefinir Guia Fixada
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Adicionar aos Essenciais ({ $num } / { $max } espaços preenchidos)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Remover dos Essenciais .label = Remover dos Essenciais
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Repor o Separador Fixado .label = Repor o Separador Fixado
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Adicionar aos Essenciais ({ $num } / { $max } espaços preenchidos)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Remover dos Essenciais .label = Remover dos Essenciais
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Сбросить закреплённую вкладку .label = Сбросить закреплённую вкладку
.accesskey = К .accesskey = К
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Добавить в важное ({ $num } из { $max } слотов занято)
.accesskey = У .accesskey = У
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Удалить из важного .label = Удалить из важного
.accesskey = К .accesskey = К

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Återställ Fäst flik .label = Återställ Fäst flik
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Lägg till Essentials ({ $num } / { $max } platser fyllda)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Ta bort från Essentials .label = Ta bort från Essentials
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Reset Pinned Tab .label = Reset Pinned Tab
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Add to Essentials ({ $num } / { $max } slots filled)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Remove from Essentials .label = Remove from Essentials
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Sabitlenen Sekmeyi Sıfırla .label = Sabitlenen Sekmeyi Sıfırla
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Add to Essentials ({ $num } / { $max } slots filled)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Temel Ögelerden Kaldır .label = Temel Ögelerden Kaldır
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Скинути прикріплену вкладку .label = Скинути прикріплену вкладку
.accesskey = Р .accesskey = Р
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Додати до Основного ({ $num } / { $max } комірок заповнено)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Вилучити з основних елементів .label = Вилучити з основних елементів
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = Đặt lại thẻ đã ghim .label = Đặt lại thẻ đã ghim
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Thêm thẻ vào thường trú (đã thêm { $num } / { $max } )
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = Loại ra khỏi thẻ thường trú .label = Loại ra khỏi thẻ thường trú
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = 重置固定标签页 .label = 重置固定标签页
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = 添加到常驻标签页(已使用 { $num } / { $max }
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = 从常驻标签页中移除 .label = 从常驻标签页中移除
.accesskey = R .accesskey = R

View File

@@ -8,9 +8,8 @@ tab-context-zen-reset-pinned-tab =
.label = 重置釘選的分頁 .label = 重置釘選的分頁
.accesskey = R .accesskey = R
tab-context-zen-add-essential = tab-context-zen-add-essential =
.label = Add to Essentials .label = Add to Essentials ({ $num } / { $max } slots filled)
.accesskey = E .accesskey = E
tab-context-zen-add-essential-badge = { $num } / { $max } slots filled
tab-context-zen-remove-essential = tab-context-zen-remove-essential =
.label = 從 Essentials 中移除 .label = 從 Essentials 中移除
.accesskey = R .accesskey = R

View File

@@ -36,7 +36,7 @@
value: '@IS_TWILIGHT@' value: '@IS_TWILIGHT@'
- name: zen.theme.hide-unified-extensions-button - name: zen.theme.hide-unified-extensions-button
value: true value: false
# ==== Mark: border radius ==== # ==== Mark: border radius ====

View File

@@ -48,7 +48,6 @@
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenFolders.mjs"></script> <script type="text/javascript" src="chrome://browser/content/zen-components/ZenFolders.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenMods.mjs"></script> <script type="text/javascript" src="chrome://browser/content/zen-components/ZenMods.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenCompactMode.mjs"></script> <script type="text/javascript" src="chrome://browser/content/zen-components/ZenCompactMode.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenPinnedTabsStorage.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenWorkspacesStorage.mjs"></script> <script type="text/javascript" src="chrome://browser/content/zen-components/ZenWorkspacesStorage.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenPinnedTabManager.mjs"></script> <script type="text/javascript" src="chrome://browser/content/zen-components/ZenPinnedTabManager.mjs"></script>
<script type="text/javascript" src="chrome://browser/content/zen-components/ZenGradientGenerator.mjs"></script> <script type="text/javascript" src="chrome://browser/content/zen-components/ZenGradientGenerator.mjs"></script>
@@ -58,3 +57,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>

View File

@@ -41,6 +41,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)
@@ -50,7 +51,6 @@
content/browser/zen-components/ZenKeyboardShortcuts.mjs (../../zen/kbs/ZenKeyboardShortcuts.mjs) content/browser/zen-components/ZenKeyboardShortcuts.mjs (../../zen/kbs/ZenKeyboardShortcuts.mjs)
content/browser/zen-components/ZenPinnedTabsStorage.mjs (../../zen/tabs/ZenPinnedTabsStorage.mjs)
content/browser/zen-components/ZenPinnedTabManager.mjs (../../zen/tabs/ZenPinnedTabManager.mjs) content/browser/zen-components/ZenPinnedTabManager.mjs (../../zen/tabs/ZenPinnedTabManager.mjs)
* content/browser/zen-styles/zen-tabs.css (../../zen/tabs/zen-tabs.css) * content/browser/zen-styles/zen-tabs.css (../../zen/tabs/zen-tabs.css)
content/browser/zen-styles/zen-tabs/vertical-tabs.css (../../zen/tabs/zen-tabs/vertical-tabs.css) content/browser/zen-styles/zen-tabs/vertical-tabs.css (../../zen/tabs/zen-tabs/vertical-tabs.css)

View File

@@ -0,0 +1,21 @@
diff --git a/browser/components/sessionstore/SessionFile.sys.mjs b/browser/components/sessionstore/SessionFile.sys.mjs
index 31140cb8be3b529a0952ca8dc55165690b0e2120..605c9e0aa84da0a2d3171a0573e8cd95e27bd0c4 100644
--- a/browser/components/sessionstore/SessionFile.sys.mjs
+++ b/browser/components/sessionstore/SessionFile.sys.mjs
@@ -22,6 +22,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
RunState: "resource:///modules/sessionstore/RunState.sys.mjs",
SessionStore: "resource:///modules/sessionstore/SessionStore.sys.mjs",
SessionWriter: "resource:///modules/sessionstore/SessionWriter.sys.mjs",
+ ZenSessionStore: "resource:///modules/zen/ZenSessionManager.sys.mjs",
});
const PREF_UPGRADE_BACKUP = "browser.sessionstore.upgradeBackup.latestBuildID";
@@ -380,7 +381,7 @@ var SessionFileInternal = {
this._readOrigin = result.origin;
result.noFilesFound = noFilesFound;
-
+ await lazy.ZenSessionStore.readFile();
return result;
},

View File

@@ -0,0 +1,21 @@
diff --git a/browser/components/sessionstore/SessionStartup.sys.mjs b/browser/components/sessionstore/SessionStartup.sys.mjs
index be23213ae9ec7e59358a17276c6c3764d38d9996..ca5a8ccc916ceeab5140f1278d15233cefbe5815 100644
--- a/browser/components/sessionstore/SessionStartup.sys.mjs
+++ b/browser/components/sessionstore/SessionStartup.sys.mjs
@@ -40,6 +40,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
StartupPerformance:
"resource:///modules/sessionstore/StartupPerformance.sys.mjs",
sessionStoreLogger: "resource:///modules/sessionstore/SessionLogger.sys.mjs",
+ ZenSessionStore: "resource:///modules/zen/ZenSessionManager.sys.mjs",
});
const STATE_RUNNING_STR = "running";
@@ -179,6 +180,8 @@ export var SessionStartup = {
this._initialState = parsed;
}
+ lazy.ZenSessionStore.onFileRead(this._initialState);
+
if (this._initialState == null) {
// No valid session found.
this._sessionType = this.NO_SESSION;

View File

@@ -1,5 +1,5 @@
diff --git a/browser/components/sessionstore/SessionStore.sys.mjs b/browser/components/sessionstore/SessionStore.sys.mjs diff --git a/browser/components/sessionstore/SessionStore.sys.mjs b/browser/components/sessionstore/SessionStore.sys.mjs
index 1cdbc0f41bf5b55dfbbd850cb618c6d870f7a261..f13ed1412bb7ae6623aa2605d7691d10540eb659 100644 index 1cdbc0f41bf5b55dfbbd850cb618c6d870f7a261..7cd5b92c1b1ddbaea89de5e9627fc5bc3315aa98 100644
--- a/browser/components/sessionstore/SessionStore.sys.mjs --- a/browser/components/sessionstore/SessionStore.sys.mjs
+++ b/browser/components/sessionstore/SessionStore.sys.mjs +++ b/browser/components/sessionstore/SessionStore.sys.mjs
@@ -127,6 +127,8 @@ const TAB_EVENTS = [ @@ -127,6 +127,8 @@ const TAB_EVENTS = [
@@ -11,7 +11,15 @@ index 1cdbc0f41bf5b55dfbbd850cb618c6d870f7a261..f13ed1412bb7ae6623aa2605d7691d10
]; ];
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
@@ -1911,6 +1913,8 @@ var SessionStoreInternal = { @@ -196,6 +198,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
TabStateCache: "resource:///modules/sessionstore/TabStateCache.sys.mjs",
TabStateFlusher: "resource:///modules/sessionstore/TabStateFlusher.sys.mjs",
setTimeout: "resource://gre/modules/Timer.sys.mjs",
+ ZenSessionStore: "resource:///modules/zen/ZenSessionManager.sys.mjs",
});
ChromeUtils.defineLazyGetter(lazy, "blankURI", () => {
@@ -1911,6 +1914,8 @@ var SessionStoreInternal = {
case "TabPinned": case "TabPinned":
case "TabUnpinned": case "TabUnpinned":
case "SwapDocShells": case "SwapDocShells":
@@ -20,7 +28,7 @@ index 1cdbc0f41bf5b55dfbbd850cb618c6d870f7a261..f13ed1412bb7ae6623aa2605d7691d10
this.saveStateDelayed(win); this.saveStateDelayed(win);
break; break;
case "TabGroupCreate": case "TabGroupCreate":
@@ -2151,7 +2155,6 @@ var SessionStoreInternal = { @@ -2151,7 +2156,6 @@ var SessionStoreInternal = {
if (closedWindowState) { if (closedWindowState) {
let newWindowState; let newWindowState;
if ( if (
@@ -28,7 +36,18 @@ index 1cdbc0f41bf5b55dfbbd850cb618c6d870f7a261..f13ed1412bb7ae6623aa2605d7691d10
!lazy.SessionStartup.willRestore() !lazy.SessionStartup.willRestore()
) { ) {
// We want to split the window up into pinned tabs and unpinned tabs. // We want to split the window up into pinned tabs and unpinned tabs.
@@ -2384,11 +2387,9 @@ var SessionStoreInternal = { @@ -2215,6 +2219,10 @@ var SessionStoreInternal = {
});
this._shouldRestoreLastSession = false;
}
+ else if (!aInitialState && isRegularWindow) {
+ aInitialState = lazy.ZenSessionStore.getNewWindowData();
+ this.restoreWindows(aWindow, aInitialState, {});
+ }
if (this._restoreLastWindow && aWindow.toolbar.visible) {
// always reset (if not a popup window)
@@ -2384,11 +2392,9 @@ var SessionStoreInternal = {
tabbrowser.selectedTab.label; tabbrowser.selectedTab.label;
} }
@@ -40,7 +59,7 @@ index 1cdbc0f41bf5b55dfbbd850cb618c6d870f7a261..f13ed1412bb7ae6623aa2605d7691d10
// Store the window's close date to figure out when each individual tab // Store the window's close date to figure out when each individual tab
// was closed. This timestamp should allow re-arranging data based on how // was closed. This timestamp should allow re-arranging data based on how
@@ -3373,7 +3374,7 @@ var SessionStoreInternal = { @@ -3373,7 +3379,7 @@ var SessionStoreInternal = {
if (!isPrivateWindow && tabState.isPrivate) { if (!isPrivateWindow && tabState.isPrivate) {
return; return;
} }
@@ -49,7 +68,7 @@ index 1cdbc0f41bf5b55dfbbd850cb618c6d870f7a261..f13ed1412bb7ae6623aa2605d7691d10
return; return;
} }
@@ -4089,6 +4090,11 @@ var SessionStoreInternal = { @@ -4089,6 +4095,11 @@ var SessionStoreInternal = {
Math.min(tabState.index, tabState.entries.length) Math.min(tabState.index, tabState.entries.length)
); );
tabState.pinned = false; tabState.pinned = false;
@@ -61,7 +80,7 @@ index 1cdbc0f41bf5b55dfbbd850cb618c6d870f7a261..f13ed1412bb7ae6623aa2605d7691d10
if (inBackground === false) { if (inBackground === false) {
aWindow.gBrowser.selectedTab = newTab; aWindow.gBrowser.selectedTab = newTab;
@@ -4525,6 +4531,7 @@ var SessionStoreInternal = { @@ -4525,6 +4536,7 @@ var SessionStoreInternal = {
// Append the tab if we're opening into a different window, // Append the tab if we're opening into a different window,
tabIndex: aSource == aTargetWindow ? pos : Infinity, tabIndex: aSource == aTargetWindow ? pos : Infinity,
pinned: state.pinned, pinned: state.pinned,
@@ -69,7 +88,7 @@ index 1cdbc0f41bf5b55dfbbd850cb618c6d870f7a261..f13ed1412bb7ae6623aa2605d7691d10
userContextId: state.userContextId, userContextId: state.userContextId,
skipLoad: true, skipLoad: true,
preferredRemoteType, preferredRemoteType,
@@ -5374,7 +5381,7 @@ var SessionStoreInternal = { @@ -5374,7 +5386,7 @@ var SessionStoreInternal = {
for (let i = tabbrowser.pinnedTabCount; i < tabbrowser.tabs.length; i++) { for (let i = tabbrowser.pinnedTabCount; i < tabbrowser.tabs.length; i++) {
let tab = tabbrowser.tabs[i]; let tab = tabbrowser.tabs[i];
@@ -78,7 +97,7 @@ index 1cdbc0f41bf5b55dfbbd850cb618c6d870f7a261..f13ed1412bb7ae6623aa2605d7691d10
removableTabs.push(tab); removableTabs.push(tab);
} }
} }
@@ -5434,7 +5441,7 @@ var SessionStoreInternal = { @@ -5434,7 +5446,7 @@ var SessionStoreInternal = {
} }
let workspaceID = aWindow.getWorkspaceID(); let workspaceID = aWindow.getWorkspaceID();
@@ -87,7 +106,7 @@ index 1cdbc0f41bf5b55dfbbd850cb618c6d870f7a261..f13ed1412bb7ae6623aa2605d7691d10
winData.workspaceID = workspaceID; winData.workspaceID = workspaceID;
} }
}, },
@@ -5625,11 +5632,12 @@ var SessionStoreInternal = { @@ -5625,11 +5637,12 @@ var SessionStoreInternal = {
} }
let tabbrowser = aWindow.gBrowser; let tabbrowser = aWindow.gBrowser;
@@ -101,7 +120,7 @@ index 1cdbc0f41bf5b55dfbbd850cb618c6d870f7a261..f13ed1412bb7ae6623aa2605d7691d10
// update the internal state data for this window // update the internal state data for this window
for (let tab of tabs) { for (let tab of tabs) {
if (tab == aWindow.FirefoxViewHandler.tab) { if (tab == aWindow.FirefoxViewHandler.tab) {
@@ -5640,6 +5648,7 @@ var SessionStoreInternal = { @@ -5640,6 +5653,7 @@ var SessionStoreInternal = {
tabsData.push(tabData); tabsData.push(tabData);
} }
@@ -109,7 +128,7 @@ index 1cdbc0f41bf5b55dfbbd850cb618c6d870f7a261..f13ed1412bb7ae6623aa2605d7691d10
// update tab group state for this window // update tab group state for this window
winData.groups = []; winData.groups = [];
for (let tabGroup of aWindow.gBrowser.tabGroups) { for (let tabGroup of aWindow.gBrowser.tabGroups) {
@@ -5652,7 +5661,7 @@ var SessionStoreInternal = { @@ -5652,7 +5666,7 @@ var SessionStoreInternal = {
// a window is closed, point to the first item in the tab strip instead (it will never be the Firefox View tab, // a window is closed, point to the first item in the tab strip instead (it will never be the Firefox View tab,
// since it's only inserted into the tab strip after it's selected). // since it's only inserted into the tab strip after it's selected).
if (aWindow.FirefoxViewHandler.tab?.selected) { if (aWindow.FirefoxViewHandler.tab?.selected) {
@@ -118,7 +137,7 @@ index 1cdbc0f41bf5b55dfbbd850cb618c6d870f7a261..f13ed1412bb7ae6623aa2605d7691d10
winData.title = tabbrowser.tabs[0].label; winData.title = tabbrowser.tabs[0].label;
} }
winData.selected = selectedIndex; winData.selected = selectedIndex;
@@ -5764,8 +5773,8 @@ var SessionStoreInternal = { @@ -5764,8 +5778,8 @@ var SessionStoreInternal = {
// selectTab represents. // selectTab represents.
let selectTab = 0; let selectTab = 0;
if (overwriteTabs) { if (overwriteTabs) {
@@ -129,7 +148,7 @@ index 1cdbc0f41bf5b55dfbbd850cb618c6d870f7a261..f13ed1412bb7ae6623aa2605d7691d10
selectTab = Math.min(selectTab, winData.tabs.length); selectTab = Math.min(selectTab, winData.tabs.length);
} }
@@ -5808,6 +5817,8 @@ var SessionStoreInternal = { @@ -5808,6 +5822,8 @@ var SessionStoreInternal = {
winData.tabs, winData.tabs,
winData.groups ?? [] winData.groups ?? []
); );
@@ -138,7 +157,7 @@ index 1cdbc0f41bf5b55dfbbd850cb618c6d870f7a261..f13ed1412bb7ae6623aa2605d7691d10
this._log.debug( this._log.debug(
`restoreWindow, createTabsForSessionRestore returned ${tabs.length} tabs` `restoreWindow, createTabsForSessionRestore returned ${tabs.length} tabs`
); );
@@ -6371,6 +6382,25 @@ var SessionStoreInternal = { @@ -6371,6 +6387,25 @@ var SessionStoreInternal = {
// Most of tabData has been restored, now continue with restoring // Most of tabData has been restored, now continue with restoring
// attributes that may trigger external events. // attributes that may trigger external events.
@@ -152,8 +171,8 @@ index 1cdbc0f41bf5b55dfbbd850cb618c6d870f7a261..f13ed1412bb7ae6623aa2605d7691d10
+ if (tabData.zenHasStaticLabel) { + if (tabData.zenHasStaticLabel) {
+ tab.setAttribute("zen-has-static-label", "true"); + tab.setAttribute("zen-has-static-label", "true");
+ } + }
+ if (tabData.zenPinnedId) { + if (tabData.zenSyncId) {
+ tab.setAttribute("zen-pin-id", tabData.zenPinnedId); + tab.setAttribute("zen-sync-id", tabData.zenSyncId);
+ } + }
+ if (tabData.zenDefaultUserContextId) { + if (tabData.zenDefaultUserContextId) {
+ tab.setAttribute("zenDefaultUserContextId", true); + tab.setAttribute("zenDefaultUserContextId", true);
@@ -164,7 +183,7 @@ index 1cdbc0f41bf5b55dfbbd850cb618c6d870f7a261..f13ed1412bb7ae6623aa2605d7691d10
if (tabData.pinned) { if (tabData.pinned) {
tabbrowser.pinTab(tab); tabbrowser.pinTab(tab);
@@ -7289,7 +7319,7 @@ var SessionStoreInternal = { @@ -7289,7 +7324,7 @@ var SessionStoreInternal = {
let groupsToSave = new Map(); let groupsToSave = new Map();
for (let tIndex = 0; tIndex < window.tabs.length; ) { for (let tIndex = 0; tIndex < window.tabs.length; ) {

View File

@@ -1,5 +1,5 @@
diff --git a/browser/components/sessionstore/TabState.sys.mjs b/browser/components/sessionstore/TabState.sys.mjs diff --git a/browser/components/sessionstore/TabState.sys.mjs b/browser/components/sessionstore/TabState.sys.mjs
index 82721356d191055bec0d4b0ca49e481221988801..1ea5c394c704da295149443d7794961a12f2060b 100644 index 82721356d191055bec0d4b0ca49e481221988801..d1323fe17c995611ebdfe2869b0ccd2d45bcfa11 100644
--- a/browser/components/sessionstore/TabState.sys.mjs --- a/browser/components/sessionstore/TabState.sys.mjs
+++ b/browser/components/sessionstore/TabState.sys.mjs +++ b/browser/components/sessionstore/TabState.sys.mjs
@@ -85,7 +85,22 @@ class _TabState { @@ -85,7 +85,22 @@ class _TabState {
@@ -7,7 +7,7 @@ index 82721356d191055bec0d4b0ca49e481221988801..1ea5c394c704da295149443d7794961a
} }
+ tabData.zenWorkspace = tab.getAttribute("zen-workspace-id"); + tabData.zenWorkspace = tab.getAttribute("zen-workspace-id");
+ tabData.zenPinnedId = tab.getAttribute("zen-pin-id"); + tabData.zenSyncId = tab.getAttribute("zen-sync-id");
+ tabData.zenEssential = tab.getAttribute("zen-essential"); + tabData.zenEssential = tab.getAttribute("zen-essential");
+ tabData.pinned = tabData.pinned || tabData.zenEssential; + tabData.pinned = tabData.pinned || tabData.zenEssential;
+ tabData.zenDefaultUserContextId = tab.getAttribute("zenDefaultUserContextId"); + tabData.zenDefaultUserContextId = tab.getAttribute("zenDefaultUserContextId");

View File

@@ -1,5 +1,5 @@
diff --git a/browser/components/tabbrowser/content/drag-and-drop.js b/browser/components/tabbrowser/content/drag-and-drop.js diff --git a/browser/components/tabbrowser/content/drag-and-drop.js b/browser/components/tabbrowser/content/drag-and-drop.js
index c97c661656868bc7faaf7c66c9702eea056aafe1..3a2b4bd1a017697539a3b81432199812307b9a04 100644 index c97c661656868bc7faaf7c66c9702eea056aafe1..aa9f0ed071e4898cac2b98a4d81e95df6a41b8dd 100644
--- a/browser/components/tabbrowser/content/drag-and-drop.js --- a/browser/components/tabbrowser/content/drag-and-drop.js
+++ b/browser/components/tabbrowser/content/drag-and-drop.js +++ b/browser/components/tabbrowser/content/drag-and-drop.js
@@ -32,6 +32,9 @@ @@ -32,6 +32,9 @@
@@ -149,8 +149,8 @@ index c97c661656868bc7faaf7c66c9702eea056aafe1..3a2b4bd1a017697539a3b81432199812
this.#tabbrowserTabs.verticalMode && this.#tabbrowserTabs.verticalMode &&
- tab.pinned && - tab.pinned &&
- this.#tabbrowserTabs.hasAttribute("expanded") && - this.#tabbrowserTabs.hasAttribute("expanded") &&
+ tab.hasAttribute("zen-essential") && + (tab.hasAttribute("zen-essential")) &&
+ (this.#tabbrowserTabs.hasAttribute("expanded") || document.documentElement.hasAttribute("zen-sidebar-expanded")) && + (this.hasAttribute("expanded") || document.documentElement.hasAttribute("zen-sidebar-expanded")) &&
!this.#tabbrowserTabs.expandOnHover !this.#tabbrowserTabs.expandOnHover
); );
} }

View File

@@ -1,5 +1,5 @@
diff --git a/browser/components/tabbrowser/content/tab.js b/browser/components/tabbrowser/content/tab.js diff --git a/browser/components/tabbrowser/content/tab.js b/browser/components/tabbrowser/content/tab.js
index 4c1a48424316b29d27ae2bc8b64004df41c87bb6..f1ff9bf0947127a8e9115357cedac577b5fad08c 100644 index 4c1a48424316b29d27ae2bc8b64004df41c87bb6..ce54ed0c8a93d5521a436c55c9432c090b0420ac 100644
--- a/browser/components/tabbrowser/content/tab.js --- a/browser/components/tabbrowser/content/tab.js
+++ b/browser/components/tabbrowser/content/tab.js +++ b/browser/components/tabbrowser/content/tab.js
@@ -21,6 +21,7 @@ @@ -21,6 +21,7 @@
@@ -121,15 +121,7 @@ index 4c1a48424316b29d27ae2bc8b64004df41c87bb6..f1ff9bf0947127a8e9115357cedac577
on_click(event) { on_click(event) {
if (event.button != 0) { if (event.button != 0) {
return; return;
@@ -572,6 +594,7 @@ @@ -584,6 +606,14 @@
)
);
} else {
+ gZenPinnedTabManager._removePinnedAttributes(this, true);
gBrowser.removeTab(this, {
animate: true,
triggeringEvent: event,
@@ -584,6 +607,14 @@
// (see tabbrowser-tabs 'click' handler). // (see tabbrowser-tabs 'click' handler).
gBrowser.tabContainer._blockDblClick = true; gBrowser.tabContainer._blockDblClick = true;
} }
@@ -144,7 +136,7 @@ index 4c1a48424316b29d27ae2bc8b64004df41c87bb6..f1ff9bf0947127a8e9115357cedac577
} }
on_dblclick(event) { on_dblclick(event) {
@@ -607,6 +638,8 @@ @@ -607,6 +637,8 @@
animate: true, animate: true,
triggeringEvent: event, triggeringEvent: event,
}); });

View File

@@ -1,5 +1,5 @@
diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js
index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326cbd973686 100644 index c0eafd4faf8d57b8486c5bf8917375850ec8147e..30c8fd7e978eb3036f35b17ae3f6ea4cd44d980e 100644
--- a/browser/components/tabbrowser/content/tabbrowser.js --- a/browser/components/tabbrowser/content/tabbrowser.js
+++ b/browser/components/tabbrowser/content/tabbrowser.js +++ b/browser/components/tabbrowser/content/tabbrowser.js
@@ -450,15 +450,64 @@ @@ -450,15 +450,64 @@
@@ -490,19 +490,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
if (this.isTab(itemAfter) && itemAfter.group == tabGroup) { if (this.isTab(itemAfter) && itemAfter.group == tabGroup) {
// Place at the front of, or between tabs in, the same tab group // Place at the front of, or between tabs in, the same tab group
this.tabContainer.insertBefore(tab, itemAfter); this.tabContainer.insertBefore(tab, itemAfter);
@@ -4338,7 +4465,11 @@ @@ -4346,6 +4473,7 @@
const tabContainer = pinned
? this.tabContainer.pinnedTabsContainer
: this.tabContainer;
+ if (itemAfter) {
+ itemAfter.before(tab);
+ } else {
tabContainer.insertBefore(tab, itemAfter);
+ }
}
this._updateTabsAfterInsert();
@@ -4346,6 +4477,7 @@
if (pinned) { if (pinned) {
this._updateTabBarForPinnedTabs(); this._updateTabBarForPinnedTabs();
} }
@@ -510,17 +498,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
TabBarVisibility.update(); TabBarVisibility.update();
} }
@@ -4635,6 +4767,9 @@ @@ -4896,6 +5024,7 @@
return;
}
+ for (let tab of selectedTabs) {
+ gZenPinnedTabManager._removePinnedAttributes(tab, true);
+ }
this.removeTabs(selectedTabs, { isUserTriggered, telemetrySource });
}
@@ -4896,6 +5031,7 @@
telemetrySource, telemetrySource,
} = {} } = {}
) { ) {
@@ -528,7 +506,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
// When 'closeWindowWithLastTab' pref is enabled, closing all tabs // When 'closeWindowWithLastTab' pref is enabled, closing all tabs
// can be considered equivalent to closing the window. // can be considered equivalent to closing the window.
if ( if (
@@ -4985,6 +5121,7 @@ @@ -4985,6 +5114,7 @@
if (lastToClose) { if (lastToClose) {
this.removeTab(lastToClose, aParams); this.removeTab(lastToClose, aParams);
} }
@@ -536,7 +514,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
@@ -5023,6 +5160,12 @@ @@ -5023,6 +5153,12 @@
aTab._closeTimeNoAnimTimerId = Glean.browserTabclose.timeNoAnim.start(); aTab._closeTimeNoAnimTimerId = Glean.browserTabclose.timeNoAnim.start();
} }
@@ -549,7 +527,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
// Handle requests for synchronously removing an already // Handle requests for synchronously removing an already
// asynchronously closing tab. // asynchronously closing tab.
if (!animate && aTab.closing) { if (!animate && aTab.closing) {
@@ -5037,6 +5180,9 @@ @@ -5037,6 +5173,9 @@
// state). // state).
let tabWidth = window.windowUtils.getBoundsWithoutFlushing(aTab).width; let tabWidth = window.windowUtils.getBoundsWithoutFlushing(aTab).width;
let isLastTab = this.#isLastTabInWindow(aTab); let isLastTab = this.#isLastTabInWindow(aTab);
@@ -559,7 +537,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
if ( if (
!this._beginRemoveTab(aTab, { !this._beginRemoveTab(aTab, {
closeWindowFastpath: true, closeWindowFastpath: true,
@@ -5085,7 +5231,13 @@ @@ -5085,7 +5224,13 @@
// We're not animating, so we can cancel the animation stopwatch. // We're not animating, so we can cancel the animation stopwatch.
Glean.browserTabclose.timeAnim.cancel(aTab._closeTimeAnimTimerId); Glean.browserTabclose.timeAnim.cancel(aTab._closeTimeAnimTimerId);
aTab._closeTimeAnimTimerId = null; aTab._closeTimeAnimTimerId = null;
@@ -574,7 +552,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
return; return;
} }
@@ -5219,7 +5371,7 @@ @@ -5219,7 +5364,7 @@
closeWindowWithLastTab != null closeWindowWithLastTab != null
? closeWindowWithLastTab ? closeWindowWithLastTab
: !window.toolbar.visible || : !window.toolbar.visible ||
@@ -583,7 +561,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
if (closeWindow) { if (closeWindow) {
// We've already called beforeunload on all the relevant tabs if we get here, // We've already called beforeunload on all the relevant tabs if we get here,
@@ -5243,6 +5395,7 @@ @@ -5243,6 +5388,7 @@
newTab = true; newTab = true;
} }
@@ -591,7 +569,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
aTab._endRemoveArgs = [closeWindow, newTab]; aTab._endRemoveArgs = [closeWindow, newTab];
// swapBrowsersAndCloseOther will take care of closing the window without animation. // swapBrowsersAndCloseOther will take care of closing the window without animation.
@@ -5283,13 +5436,7 @@ @@ -5283,13 +5429,7 @@
aTab._mouseleave(); aTab._mouseleave();
if (newTab) { if (newTab) {
@@ -606,7 +584,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
} else { } else {
TabBarVisibility.update(); TabBarVisibility.update();
} }
@@ -5422,6 +5569,7 @@ @@ -5422,6 +5562,7 @@
this.tabs[i]._tPos = i; this.tabs[i]._tPos = i;
} }
@@ -614,7 +592,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
if (!this._windowIsClosing) { if (!this._windowIsClosing) {
// update tab close buttons state // update tab close buttons state
this.tabContainer._updateCloseButtons(); this.tabContainer._updateCloseButtons();
@@ -5643,6 +5791,7 @@ @@ -5643,6 +5784,7 @@
} }
let excludeTabs = new Set(aExcludeTabs); let excludeTabs = new Set(aExcludeTabs);
@@ -622,7 +600,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
// If this tab has a successor, it should be selectable, since // If this tab has a successor, it should be selectable, since
// hiding or closing a tab removes that tab as a successor. // hiding or closing a tab removes that tab as a successor.
@@ -5655,13 +5804,13 @@ @@ -5655,13 +5797,13 @@
!excludeTabs.has(aTab.owner) && !excludeTabs.has(aTab.owner) &&
Services.prefs.getBoolPref("browser.tabs.selectOwnerOnClose") Services.prefs.getBoolPref("browser.tabs.selectOwnerOnClose")
) { ) {
@@ -638,7 +616,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
); );
let tab = this.tabContainer.findNextTab(aTab, { let tab = this.tabContainer.findNextTab(aTab, {
@@ -5677,7 +5826,7 @@ @@ -5677,7 +5819,7 @@
} }
if (tab) { if (tab) {
@@ -647,7 +625,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
} }
// If no qualifying visible tab was found, see if there is a tab in // If no qualifying visible tab was found, see if there is a tab in
@@ -5698,7 +5847,7 @@ @@ -5698,7 +5840,7 @@
}); });
} }
@@ -656,7 +634,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
} }
_blurTab(aTab) { _blurTab(aTab) {
@@ -6104,10 +6253,10 @@ @@ -6104,10 +6246,10 @@
SessionStore.deleteCustomTabValue(aTab, "hiddenBy"); SessionStore.deleteCustomTabValue(aTab, "hiddenBy");
} }
@@ -669,7 +647,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
aTab.selected || aTab.selected ||
aTab.closing || aTab.closing ||
// Tabs that are sharing the screen, microphone or camera cannot be hidden. // Tabs that are sharing the screen, microphone or camera cannot be hidden.
@@ -6166,6 +6315,7 @@ @@ -6166,6 +6308,7 @@
* @param {MozTabbrowserTab|MozTabbrowserTabGroup|MozTabbrowserTabGroup.labelElement} aTab * @param {MozTabbrowserTab|MozTabbrowserTabGroup|MozTabbrowserTabGroup.labelElement} aTab
*/ */
replaceTabWithWindow(aTab, aOptions) { replaceTabWithWindow(aTab, aOptions) {
@@ -677,7 +655,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
if (this.tabs.length == 1) { if (this.tabs.length == 1) {
return null; return null;
} }
@@ -6299,7 +6449,7 @@ @@ -6299,7 +6442,7 @@
* `true` if element is a `<tab-group>` * `true` if element is a `<tab-group>`
*/ */
isTabGroup(element) { isTabGroup(element) {
@@ -686,7 +664,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
} }
/** /**
@@ -6375,8 +6525,8 @@ @@ -6375,8 +6518,8 @@
} }
// Don't allow mixing pinned and unpinned tabs. // Don't allow mixing pinned and unpinned tabs.
@@ -697,7 +675,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
} else { } else {
tabIndex = Math.max(tabIndex, this.pinnedTabCount); tabIndex = Math.max(tabIndex, this.pinnedTabCount);
} }
@@ -6402,10 +6552,16 @@ @@ -6402,10 +6545,16 @@
this.#handleTabMove( this.#handleTabMove(
element, element,
() => { () => {
@@ -716,7 +694,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
if (neighbor && this.isTab(element) && tabIndex > element._tPos) { if (neighbor && this.isTab(element) && tabIndex > element._tPos) {
neighbor.after(element); neighbor.after(element);
} else { } else {
@@ -6463,23 +6619,28 @@ @@ -6463,23 +6612,28 @@
#moveTabNextTo(element, targetElement, moveBefore = false, metricsContext) { #moveTabNextTo(element, targetElement, moveBefore = false, metricsContext) {
if (this.isTabGroupLabel(targetElement)) { if (this.isTabGroupLabel(targetElement)) {
targetElement = targetElement.group; targetElement = targetElement.group;
@@ -751,7 +729,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
} else if (!element.pinned && targetElement && targetElement.pinned) { } else if (!element.pinned && targetElement && targetElement.pinned) {
// If the caller asks to move an unpinned element next to a pinned // If the caller asks to move an unpinned element next to a pinned
// tab, move the unpinned element to be the first unpinned element // tab, move the unpinned element to be the first unpinned element
@@ -6492,14 +6653,34 @@ @@ -6492,14 +6646,34 @@
// move the tab group right before the first unpinned tab. // move the tab group right before the first unpinned tab.
// 4. Moving a tab group and the first unpinned tab is grouped: // 4. Moving a tab group and the first unpinned tab is grouped:
// move the tab group right before the first unpinned tab's tab group. // move the tab group right before the first unpinned tab's tab group.
@@ -787,7 +765,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
element.pinned element.pinned
? this.tabContainer.pinnedTabsContainer ? this.tabContainer.pinnedTabsContainer
: this.tabContainer; : this.tabContainer;
@@ -6508,7 +6689,7 @@ @@ -6508,7 +6682,7 @@
element, element,
() => { () => {
if (moveBefore) { if (moveBefore) {
@@ -796,7 +774,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
} else if (targetElement) { } else if (targetElement) {
targetElement.after(element); targetElement.after(element);
} else { } else {
@@ -6580,10 +6761,10 @@ @@ -6580,10 +6754,10 @@
* @param {TabMetricsContext} [metricsContext] * @param {TabMetricsContext} [metricsContext]
*/ */
moveTabToGroup(aTab, aGroup, metricsContext) { moveTabToGroup(aTab, aGroup, metricsContext) {
@@ -809,7 +787,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
return; return;
} }
if (aTab.group && aTab.group.id === aGroup.id) { if (aTab.group && aTab.group.id === aGroup.id) {
@@ -6613,6 +6794,7 @@ @@ -6613,6 +6787,7 @@
let state = { let state = {
tabIndex: tab._tPos, tabIndex: tab._tPos,
@@ -817,7 +795,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
}; };
if (tab.visible) { if (tab.visible) {
state.elementIndex = tab.elementIndex; state.elementIndex = tab.elementIndex;
@@ -6639,7 +6821,7 @@ @@ -6639,7 +6814,7 @@
let changedTabGroup = let changedTabGroup =
previousTabState.tabGroupId != currentTabState.tabGroupId; previousTabState.tabGroupId != currentTabState.tabGroupId;
@@ -826,7 +804,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
tab.dispatchEvent( tab.dispatchEvent(
new CustomEvent("TabMove", { new CustomEvent("TabMove", {
bubbles: true, bubbles: true,
@@ -6676,6 +6858,10 @@ @@ -6676,6 +6851,10 @@
moveActionCallback(); moveActionCallback();
@@ -837,7 +815,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
// Clear tabs cache after moving nodes because the order of tabs may have // Clear tabs cache after moving nodes because the order of tabs may have
// changed. // changed.
this.tabContainer._invalidateCachedTabs(); this.tabContainer._invalidateCachedTabs();
@@ -7576,7 +7762,7 @@ @@ -7576,7 +7755,7 @@
// preventDefault(). It will still raise the window if appropriate. // preventDefault(). It will still raise the window if appropriate.
break; break;
} }
@@ -846,7 +824,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
window.focus(); window.focus();
aEvent.preventDefault(); aEvent.preventDefault();
break; break;
@@ -7593,7 +7779,6 @@ @@ -7593,7 +7772,6 @@
} }
case "TabGroupCollapse": case "TabGroupCollapse":
aEvent.target.tabs.forEach(tab => { aEvent.target.tabs.forEach(tab => {
@@ -854,7 +832,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
}); });
break; break;
case "TabGroupCreateByUser": case "TabGroupCreateByUser":
@@ -8542,6 +8727,7 @@ @@ -8542,6 +8720,7 @@
aWebProgress.isTopLevel aWebProgress.isTopLevel
) { ) {
this.mTab.setAttribute("busy", "true"); this.mTab.setAttribute("busy", "true");
@@ -862,7 +840,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
gBrowser._tabAttrModified(this.mTab, ["busy"]); gBrowser._tabAttrModified(this.mTab, ["busy"]);
this.mTab._notselectedsinceload = !this.mTab.selected; this.mTab._notselectedsinceload = !this.mTab.selected;
} }
@@ -9543,7 +9729,7 @@ var TabContextMenu = { @@ -9543,7 +9722,7 @@ var TabContextMenu = {
); );
contextUnpinSelectedTabs.hidden = contextUnpinSelectedTabs.hidden =
!this.contextTab.pinned || !this.multiselected; !this.contextTab.pinned || !this.multiselected;
@@ -871,11 +849,3 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326c
// Build Ask Chat items // Build Ask Chat items
TabContextMenu.GenAI.buildTabMenu( TabContextMenu.GenAI.buildTabMenu(
document.getElementById("context_askChat"), document.getElementById("context_askChat"),
@@ -9863,6 +10049,7 @@ var TabContextMenu = {
)
);
} else {
+ gZenPinnedTabManager._removePinnedAttributes(this.contextTab, true);
gBrowser.removeTab(this.contextTab, {
animate: true,
...gBrowser.TabMetrics.userTriggeredContext(

View File

@@ -1,16 +1,7 @@
diff --git a/browser/themes/shared/identity-block/identity-block.css b/browser/themes/shared/identity-block/identity-block.css diff --git a/browser/themes/shared/identity-block/identity-block.css b/browser/themes/shared/identity-block/identity-block.css
index d542e962d42b17140888e299ed43a838047ee48c..806bc4f9d7b7557abf316a84858046e04c4f7ff5 100644 index d542e962d42b17140888e299ed43a838047ee48c..5e0b72f147687924c48dfed0318f53b765a4d497 100644
--- a/browser/themes/shared/identity-block/identity-block.css --- a/browser/themes/shared/identity-block/identity-block.css
+++ b/browser/themes/shared/identity-block/identity-block.css +++ b/browser/themes/shared/identity-block/identity-block.css
@@ -7,7 +7,7 @@
#identity-box {
margin-inline-end: var(--identity-box-margin-inline);
- &[pageproxystate="invalid"] {
+ :root[zen-has-empty-tab='true'] & {
pointer-events: none;
-moz-user-focus: ignore;
}
@@ -81,13 +81,6 @@ @@ -81,13 +81,6 @@
} }
} }

View File

@@ -504,17 +504,13 @@
} }
#identity-permission-box, #identity-permission-box,
:root:not([zen-has-empty-tab='true']) #identity-box:not([pageproxystate='invalid']) #identity-icon-box:not([open]),
#urlbar:not([breakout-extend='true']) #identity-box[pageproxystate='invalid'] #zen-site-data-icon-button {
#identity-icon-box:not([open]),
:root[zen-has-empty-tab='true'] #zen-site-data-icon-button,
#urlbar[breakout-extend='true'] #zen-site-data-icon-button {
display: none !important; display: none !important;
} }
#zen-site-data-icon-button { #zen-site-data-icon-button {
padding: 0 6px !important; padding: 0 6px;
border-radius: var(--urlbar-icon-border-radius) !important;
& image { & image {
list-style-image: url('permissions.svg'); list-style-image: url('permissions.svg');

View File

@@ -13,3 +13,4 @@
category app-startup nsBrowserGlue @mozilla.org/browser/browserglue;1 application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} category app-startup nsBrowserGlue @mozilla.org/browser/browserglue;1 application={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
#include common/Components.manifest #include common/Components.manifest
#include sessionstore/SessionComponents.manifest

View File

@@ -15,8 +15,8 @@
if (tabData.zenWorkspace) { if (tabData.zenWorkspace) {
tab.setAttribute('zen-workspace-id', tabData.zenWorkspace); tab.setAttribute('zen-workspace-id', tabData.zenWorkspace);
} }
if (tabData.zenPinnedId) { if (tabData.zenSyncId) {
tab.setAttribute('zen-pin-id', tabData.zenPinnedId); tab.setAttribute('zen-sync-id', tabData.zenSyncId);
} }
if (tabData.zenHasStaticLabel) { if (tabData.zenHasStaticLabel) {
tab.setAttribute('zen-has-static-label', 'true'); tab.setAttribute('zen-has-static-label', 'true');

View File

@@ -1303,14 +1303,6 @@ var gZenVerticalTabsManager = {
} else { } else {
gBrowser.setTabTitle(this._tabEdited); gBrowser.setTabTitle(this._tabEdited);
} }
if (this._tabEdited.getAttribute('zen-pin-id')) {
// Update pin title in storage
await gZenPinnedTabManager.updatePinTitle(
this._tabEdited,
this._tabEdited.label,
!!newName
);
}
// Maybe add some confetti here?!? // Maybe add some confetti here?!?
gZenUIManager.motion.animate( gZenUIManager.motion.animate(

View File

@@ -152,16 +152,16 @@
#navigator-toolbox[zen-has-implicit-hover='true'] &, #navigator-toolbox[zen-has-implicit-hover='true'] &,
&[open], &[open],
#urlbar[has-popup-open='true'] &, #urlbar[has-popup-open='true'] &,
:root[zen-has-empty-tab='true'] & { #identity-box[pageproxystate='invalid'] & {
opacity: 1; opacity: 1;
visibility: visible; visibility: visible;
} }
} }
} }
:root:not([zen-single-toolbar='true']):not([zen-has-empty-tab='true']) :root:not([zen-single-toolbar='true'])
#urlbar:not([breakout-extend='true']) #urlbar:not([breakout-extend='true'])
.urlbar-input-container { .urlbar-input-container:not([pageproxystate='invalid']) {
padding: 2px 3px; padding: 2px 3px;
gap: 2px; gap: 2px;
@@ -184,7 +184,8 @@
background: transparent !important; background: transparent !important;
} }
:root:is([zen-single-toolbar='true'], [zen-has-empty-tab='true']) { :root[zen-single-toolbar='true'],
#urlbar[pageproxystate='invalid'] {
#zen-copy-url-button[disabled] { #zen-copy-url-button[disabled] {
display: none !important; display: none !important;
} }
@@ -312,7 +313,6 @@
:root[zen-single-toolbar='true'] { :root[zen-single-toolbar='true'] {
--urlbar-icon-border-radius: 8px !important; --urlbar-icon-border-radius: 8px !important;
--urlbar-inner-border-radius: var(--toolbarbutton-border-radius) !important;
#identity-permission-box > *:not(#zen-site-data-icon-button) { #identity-permission-box > *:not(#zen-site-data-icon-button) {
visibility: collapse; visibility: collapse;
@@ -322,9 +322,11 @@
display: none; display: none;
} }
&:not([zen-has-empty-tab='true']) #urlbar:not([breakout-extend='true']) #identity-box { #urlbar:not([breakout-extend='true']) {
#identity-box:not([pageproxystate='invalid']) {
order: 2; order: 2;
} }
}
#notification-popup-box:not([open]) { #notification-popup-box:not([open]) {
margin-inline-start: calc(-10px - 2 * var(--urlbar-icon-padding)); margin-inline-start: calc(-10px - 2 * var(--urlbar-icon-padding));

View File

@@ -374,9 +374,8 @@ body > #confetti {
} }
.zen-site-data-section { .zen-site-data-section {
gap: 2px; gap: 6px;
padding: 10px; padding: 8px;
padding-bottom: 8px;
} }
.zen-site-data-section-header { .zen-site-data-section-header {
@@ -493,7 +492,7 @@ body > #confetti {
} }
} }
@media -moz-pref('zen.theme.hide-unified-extensions-button') { @media (-moz-pref('zen.theme.hide-unified-extensions-button')) {
#unified-extensions-button { #unified-extensions-button {
display: none !important; display: none !important;
} }
@@ -506,7 +505,7 @@ body > #confetti {
#zen-site-data-header { #zen-site-data-header {
gap: 8px; gap: 8px;
align-items: center; align-items: center;
padding: 10px 8px; padding: 10px 9px;
padding-bottom: 0; padding-bottom: 0;
:root[zen-single-toolbar='true']:not([zen-right-side='true']) & { :root[zen-single-toolbar='true']:not([zen-right-side='true']) & {
@@ -551,7 +550,7 @@ body > #confetti {
); );
box-shadow: box-shadow:
0px 2px 4px rgba(0, 0, 0, 0.1), 0px 2px 4px rgba(0, 0, 0, 0.075),
inset 0px 1px 0px light-dark(transparent, rgba(255, 255, 255, 0.15)); inset 0px 1px 0px light-dark(transparent, rgba(255, 255, 255, 0.15));
border-radius: 6px; border-radius: 6px;
--base-border-color: light-dark(rgba(0, 0, 0, 0.175), rgba(255, 255, 255, 0.1)); --base-border-color: light-dark(rgba(0, 0, 0, 0.175), rgba(255, 255, 255, 0.1));

View File

@@ -150,7 +150,6 @@
for (let tab of this.allItems.reverse()) { for (let tab of this.allItems.reverse()) {
tab = tab.group.hasAttribute('split-view-group') ? tab.group : tab; tab = tab.group.hasAttribute('split-view-group') ? tab.group : tab;
if (tab.hasAttribute('zen-empty-tab')) { if (tab.hasAttribute('zen-empty-tab')) {
await ZenPinnedTabsStorage.removePin(tab.getAttribute('zen-pin-id'));
gBrowser.removeTab(tab); gBrowser.removeTab(tab);
} else { } else {
gBrowser.ungroupTab(tab); gBrowser.ungroupTab(tab);
@@ -160,7 +159,6 @@
async delete() { async delete() {
for (const tab of this.allItemsRecursive) { for (const tab of this.allItemsRecursive) {
await ZenPinnedTabsStorage.removePin(tab.getAttribute('zen-pin-id'));
if (tab.hasAttribute('zen-empty-tab')) { if (tab.hasAttribute('zen-empty-tab')) {
// Manually remove the empty tabs as removeTabs() inside removeTabGroup // Manually remove the empty tabs as removeTabs() inside removeTabGroup
// does ignore them. // does ignore them.

View File

@@ -508,9 +508,6 @@
tabs = [emptyTab, ...filteredTabs]; tabs = [emptyTab, ...filteredTabs];
const folder = this._createFolderNode(options); const folder = this._createFolderNode(options);
if (options.initialPinId) {
folder.setAttribute('zen-pin-id', options.initialPinId);
}
if (options.insertAfter) { if (options.insertAfter) {
options.insertAfter.after(folder); options.insertAfter.after(folder);
@@ -940,7 +937,7 @@
if (!parentFolder && folder.hasAttribute('split-view-group')) continue; if (!parentFolder && folder.hasAttribute('split-view-group')) continue;
const emptyFolderTabs = folder.tabs const emptyFolderTabs = folder.tabs
.filter((tab) => tab.hasAttribute('zen-empty-tab')) .filter((tab) => tab.hasAttribute('zen-empty-tab'))
.map((tab) => tab.getAttribute('zen-pin-id')); .map((tab) => tab.getAttribute('zen-sync-id'));
let prevSiblingInfo = null; let prevSiblingInfo = null;
const prevSibling = folder.previousElementSibling; const prevSibling = folder.previousElementSibling;
@@ -949,8 +946,8 @@
if (prevSibling) { if (prevSibling) {
if (gBrowser.isTabGroup(prevSibling)) { if (gBrowser.isTabGroup(prevSibling)) {
prevSiblingInfo = { type: 'group', id: prevSibling.id }; prevSiblingInfo = { type: 'group', id: prevSibling.id };
} else if (gBrowser.isTab(prevSibling) && prevSibling.hasAttribute('zen-pin-id')) { } else if (gBrowser.isTab(prevSibling) && prevSibling.hasAttribute('zen-sync-id')) {
const zenPinId = prevSibling.getAttribute('zen-pin-id'); const zenPinId = prevSibling.getAttribute('zen-sync-id');
prevSiblingInfo = { type: 'tab', id: zenPinId }; prevSiblingInfo = { type: 'tab', id: zenPinId };
} else { } else {
prevSiblingInfo = { type: 'start', id: null }; prevSiblingInfo = { type: 'start', id: null };
@@ -969,7 +966,7 @@
prevSiblingInfo: prevSiblingInfo, prevSiblingInfo: prevSiblingInfo,
emptyTabIds: emptyFolderTabs, emptyTabIds: emptyFolderTabs,
userIcon: userIcon?.getAttribute('href'), userIcon: userIcon?.getAttribute('href'),
pinId: folder.getAttribute('zen-pin-id'), syncId: folder.getAttribute('zen-sync-id'),
// note: We shouldn't be using the workspace-id anywhere, we are just // note: We shouldn't be using the workspace-id anywhere, we are just
// remembering it for the pinned tabs manager to use it later. // remembering it for the pinned tabs manager to use it later.
workspaceId: folder.getAttribute('zen-workspace-id'), workspaceId: folder.getAttribute('zen-workspace-id'),
@@ -996,9 +993,9 @@
tabFolderWorkingData.set(folderData.id, workingData); tabFolderWorkingData.set(folderData.id, workingData);
const oldGroup = document.getElementById(folderData.id); const oldGroup = document.getElementById(folderData.id);
folderData.emptyTabIds.forEach((zenPinId) => { folderData.emptyTabIds.forEach((zenSyncId) => {
oldGroup oldGroup
?.querySelector(`tab[zen-pin-id="${zenPinId}"]`) ?.querySelector(`tab[zen-sync-id="${zenSyncId}"]`)
?.setAttribute('zen-empty-tab', true); ?.setAttribute('zen-empty-tab', true);
}); });
if (oldGroup) { if (oldGroup) {
@@ -1011,7 +1008,7 @@
saveOnWindowClose: folderData.saveOnWindowClose, saveOnWindowClose: folderData.saveOnWindowClose,
workspaceId: folderData.workspaceId, workspaceId: folderData.workspaceId,
}); });
folder.setAttribute('zen-pin-id', folderData.pinId); folder.setAttribute('zen-sync-id', folderData.syncId);
workingData.node = folder; workingData.node = folder;
oldGroup.before(folder); oldGroup.before(folder);
} else { } else {
@@ -1044,7 +1041,7 @@
switch (stateData?.prevSiblingInfo?.type) { switch (stateData?.prevSiblingInfo?.type) {
case 'tab': { case 'tab': {
const tab = parentWorkingData.node.querySelector( const tab = parentWorkingData.node.querySelector(
`[zen-pin-id="${stateData.prevSiblingInfo.id}"]` `[zen-sync-id="${stateData.prevSiblingInfo.id}"]`
); );
tab.after(node); tab.after(node);
break; break;
@@ -1156,7 +1153,10 @@
let dragDownThreshold = let dragDownThreshold =
Services.prefs.getIntPref('zen.view.drag-and-drop.drop-inside-lower-threshold') / 100; Services.prefs.getIntPref('zen.view.drag-and-drop.drop-inside-lower-threshold') / 100;
const dropElementGroup = dropElement; const dropElementGroup = dropElement.group;
if (!dropElementGroup) {
return { dropElement, colorCode, dropBefore };
}
const isSplitGroup = dropElement?.group?.hasAttribute('split-view-group'); const isSplitGroup = dropElement?.group?.hasAttribute('split-view-group');
let firstGroupElem = let firstGroupElem =
dropElementGroup.querySelector('.zen-tab-group-start').nextElementSibling; dropElementGroup.querySelector('.zen-tab-group-start').nextElementSibling;

View File

@@ -13,4 +13,5 @@ DIRS += [
"tests", "tests",
"urlbar", "urlbar",
"toolkit", "toolkit",
"sessionstore",
] ]

View File

@@ -0,0 +1,6 @@
# 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/.
# Browser global components initializing before UI startup
category browser-before-ui-startup resource:///modules/zen/ZenSessionManager.sys.mjs ZenSessionStore.init

View File

@@ -0,0 +1,40 @@
// 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/.
// Note that changing this hidden pref will make the previous session file
// unused, causing a new session file to be created on next write.
const SHOULD_COMPRESS_FILE = Services.prefs.getBoolPref('zen.session-store.compress-file', true);
const FILE_NAME = SHOULD_COMPRESS_FILE ? 'zen-sessions.jsonlz4' : 'zen-sessions.json';
export class nsZenSessionFile {
#path = PathUtils.join(PathUtils.profileDir, FILE_NAME);
#sidebar = [];
async read() {
try {
const data = await IOUtils.readJSON(this.#path, { compress: SHOULD_COMPRESS_FILE });
this.#sidebar = data.sidebar || [];
} catch {
// File doesn't exist yet, that's fine.
}
}
get sidebar() {
return this.#sidebar;
}
set sidebar(data) {
this.#sidebar = data;
}
async #write(data) {
await IOUtils.writeJSON(this.#path, data, { compress: SHOULD_COMPRESS_FILE });
}
async store() {
const data = { sidebar: this.#sidebar };
await this.#write(data);
}
}

View File

@@ -0,0 +1,167 @@
// 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/.
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
nsZenSessionFile: 'resource:///modules/zen/ZenSessionFile.sys.mjs',
PrivateBrowsingUtils: 'resource://gre/modules/PrivateBrowsingUtils.sys.mjs',
BrowserWindowTracker: 'resource:///modules/BrowserWindowTracker.sys.mjs',
TabGroupState: 'resource:///modules/sessionstore/TabGroupState.sys.mjs',
SessionStore: 'resource:///modules/sessionstore/SessionStore.sys.mjs',
SessionSaver: 'resource:///modules/sessionstore/SessionSaver.sys.mjs',
});
const LAZY_COLLECT_THRESHOLD = 5 * 60 * 1000; // 5 minutes
const OBSERVING = ['sessionstore-state-write-complete', 'browser-window-before-show'];
class nsZenSessionManager {
#file;
constructor() {
this.#file = new lazy.nsZenSessionFile();
}
// Called from SessionComponents.manifest on app-startup
init() {
this.#initObservers();
}
async readFile() {
await this.#file.read();
}
onFileRead(initialState) {
for (const winData of initialState.windows || []) {
this.restoreWindowData(winData);
}
}
#initObservers() {
for (let topic of OBSERVING) {
Services.obs.addObserver(this, topic);
}
}
get #sidebar() {
return this.#file.sidebar;
}
set #sidebar(data) {
this.#file.sidebar = data;
}
observe(aSubject, aTopic) {
switch (aTopic) {
case 'sessionstore-state-write-complete': {
this.#saveState(true);
break;
}
case 'browser-window-before-show': // catch new windows
this.#onBeforeBrowserWindowShown(aSubject);
break;
default:
break;
}
}
/** Handles the browser-window-before-show observer notification. */
#onBeforeBrowserWindowShown(aWindow) {
// TODO: Initialize new window
void aWindow;
}
get #topMostWindow() {
return lazy.BrowserWindowTracker.getTopWindow();
}
/**
* Saves the current session state. Collects data and writes to disk.
*
* @param forceUpdateAllWindows (optional)
* Forces us to recollect data for all windows and will bypass and
* update the corresponding caches.
*/
async #saveState(forceUpdateAllWindows = false) {
if (lazy.PrivateBrowsingUtils.permanentPrivateBrowsing) {
// Don't save (or even collect) anything in permanent private
// browsing mode
return;
}
// Collect an initial snapshot of window data before we do the flush.
const window = this.#topMostWindow;
// We don't have any normal windows or no windows at all
if (!window) {
return;
}
this.#collectWindowData(this.#topMostWindow, forceUpdateAllWindows);
this.#file.store();
}
/**
* Collects session data for a given window.
*
* @param window
* The window to collect data for.
* @param forceUpdate
* Forces us to recollect data and will bypass and update the
* corresponding caches.
*/
#collectWindowData(window, forceUpdate = false) {
let sidebarData = this.#sidebar;
if (!sidebarData || forceUpdate) {
sidebarData = {};
}
// If it hasn't changed, don't update.
if (
!forceUpdate &&
sidebarData.lastCollected &&
Date.now() - sidebarData.lastCollected < LAZY_COLLECT_THRESHOLD
) {
return;
}
sidebarData.lastCollected = Date.now();
this.#collectTabsData(window, sidebarData);
this.#sidebar = sidebarData;
}
/**
* Collects session data for all tabs in a given window.
*
* @param aWindow
* The window to collect tab data for.
* @param winData
* The window data object to populate.
*/
#collectTabsData(aWindow, sidebarData) {
const winData = lazy.SessionStore.getWindowState(aWindow).windows[0];
if (!winData) return;
sidebarData.tabs = winData.tabs;
sidebarData.folders = winData.folders;
sidebarData.splitViewData = winData.splitViewData;
sidebarData.groups = winData.groups;
}
restoreWindowData(aWindowData) {
const sidebar = this.#file.sidebar;
if (!sidebar) {
return;
}
aWindowData.tabs = sidebar.tabs || [];
aWindowData.splitViewData = sidebar.splitViewData;
aWindowData.folders = sidebar.folders;
aWindowData.groups = sidebar.groups;
}
getNewWindowData() {
lazy.SessionSaver.run();
const state = lazy.SessionStore.getCurrentState(true);
const windows = state.windows || {};
let newWindow = Cu.cloneInto(windows[0], {});
return { windows: [newWindow] };
}
}
export const ZenSessionStore = new nsZenSessionManager();

View File

@@ -0,0 +1,8 @@
# 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/.
EXTRA_JS_MODULES.zen += [
"ZenSessionFile.sys.mjs",
"ZenSessionManager.sys.mjs",
]

View File

@@ -5,23 +5,7 @@
const lazy = {}; const lazy = {};
class ZenPinnedTabsObserver { class ZenPinnedTabsObserver {
static ALL_EVENTS = [ static ALL_EVENTS = ['TabPinned', 'TabUnpinned'];
'TabPinned',
'TabUnpinned',
'TabMove',
'TabGroupCreate',
'TabGroupRemoved',
'TabGroupMoved',
'ZenFolderRenamed',
'ZenFolderIconChanged',
'TabGroupCollapse',
'TabGroupExpand',
'TabGrouped',
'TabUngrouped',
'ZenFolderChangedWorkspace',
'TabAddedToEssentials',
'TabRemovedFromEssentials',
];
#listeners = []; #listeners = [];
@@ -101,24 +85,12 @@
} }
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')) {
try {
setTimeout(async () => {
const favicon = await this.getFaviconAsBase64(tab.linkedBrowser.currentURI);
if (favicon) {
gBrowser.setIcon(tab, favicon);
}
});
} catch {
// Handle error
}
} else {
if (tab.hasAttribute('zen-essential')) { if (tab.hasAttribute('zen-essential')) {
tab.style.setProperty('--zen-essential-tab-icon', `url(${iconUrl})`); tab.style.setProperty('--zen-essential-tab-icon', `url(${iconUrl})`);
} }
} }
}
_onTabResetPinButton(event, tab) { _onTabResetPinButton(event, tab) {
event.stopPropagation(); event.stopPropagation();
@@ -148,261 +120,6 @@
return lazy.zenTabsEssentialsMax; return lazy.zenTabsEssentialsMax;
} }
async refreshPinnedTabs({ init = false } = {}) {
if (!this.enabled) {
return;
}
await ZenPinnedTabsStorage.promiseInitialized;
await this.#initializePinsCache();
setTimeout(async () => {
// Execute in a separate task to avoid blocking the main thread
await SessionStore.promiseAllWindowsRestored;
await gZenWorkspaces.promiseInitialized;
await this.#initializePinnedTabs(init);
if (init) {
this._hasFinishedLoading = true;
}
}, 10);
}
async #initializePinsCache() {
try {
// Get pin data
const pins = await ZenPinnedTabsStorage.getPins();
// Enhance pins with favicons
this._pinsCache = await Promise.all(
pins.map(async (pin) => {
try {
if (pin.isGroup) {
return pin; // Skip groups for now
}
const image = await this.getFaviconAsBase64(Services.io.newURI(pin.url));
return {
...pin,
iconUrl: image || null,
};
} catch {
// If favicon fetch fails, continue without icon
return {
...pin,
iconUrl: null,
};
}
})
);
} catch (ex) {
console.error('Failed to initialize pins cache:', ex);
this._pinsCache = [];
}
this.log(`Initialized pins cache with ${this._pinsCache.length} pins`);
return this._pinsCache;
}
#finishedInitializingPins() {
if (this.hasInitializedPins) {
return;
}
this._resolvePinnedInitializedInternal();
delete this._resolvePinnedInitializedInternal;
this.hasInitializedPins = true;
}
async #initializePinnedTabs(init = false) {
const pins = this._pinsCache;
if (!pins?.length || !init) {
this.#finishedInitializingPins();
return;
}
const pinnedTabsByUUID = new Map();
const pinsToCreate = new Set(pins.map((p) => p.uuid));
// First pass: identify existing tabs and remove those without pins
for (let tab of gZenWorkspaces.allStoredTabs) {
const pinId = tab.getAttribute('zen-pin-id');
if (!pinId) {
continue;
}
if (pinsToCreate.has(pinId)) {
// This is a valid pinned tab that matches a pin
pinnedTabsByUUID.set(pinId, tab);
pinsToCreate.delete(pinId);
if (lazy.zenPinnedTabRestorePinnedTabsToPinnedUrl && init) {
this._resetTabToStoredState(tab);
}
} else {
// This is a pinned tab that no longer has a corresponding pin
gBrowser.removeTab(tab);
}
}
for (const group of gZenWorkspaces.allTabGroups) {
const pinId = group.getAttribute('zen-pin-id');
if (!pinId) {
continue;
}
if (pinsToCreate.has(pinId)) {
// This is a valid pinned group that matches a pin
pinsToCreate.delete(pinId);
}
}
// Second pass: For every existing tab, update its label
// and set 'zen-has-static-label' attribute if it's been edited
for (let pin of pins) {
const tab = pinnedTabsByUUID.get(pin.uuid);
if (!tab) {
continue;
}
tab.removeAttribute('zen-has-static-label'); // So we can set it again
if (pin.title && pin.editedTitle) {
gBrowser._setTabLabel(tab, pin.title, { beforeTabOpen: true });
tab.setAttribute('zen-has-static-label', 'true');
}
}
const groups = new Map();
const pendingTabsInsideGroups = {};
// Third pass: create new tabs for pins that don't have tabs
for (let pin of pins) {
try {
if (!pinsToCreate.has(pin.uuid)) {
continue; // Skip pins that already have tabs
}
if (pin.isGroup) {
const tabs = [];
// If there's already existing tabs, let's use them
for (const [uuid, existingTab] of pinnedTabsByUUID) {
const pinObject = this._pinsCache.find((p) => p.uuid === uuid);
if (pinObject && pinObject.parentUuid === pin.uuid) {
tabs.push(existingTab);
}
}
// We still need to iterate through pending tabs since the database
// query doesn't guarantee the order of insertion
for (const [parentUuid, folderTabs] of Object.entries(pendingTabsInsideGroups)) {
if (parentUuid === pin.uuid) {
tabs.push(...folderTabs);
}
}
const group = gZenFolders.createFolder(tabs, {
label: pin.title,
collapsed: pin.isFolderCollapsed,
initialPinId: pin.uuid,
workspaceId: pin.workspaceUuid,
insertAfter:
groups.get(pin.parentUuid)?.querySelector('.tab-group-container')?.lastChild ||
null,
});
gZenFolders.setFolderUserIcon(group, pin.folderIcon);
groups.set(pin.uuid, group);
continue;
}
let params = {
skipAnimation: true,
allowInheritPrincipal: false,
skipBackgroundNotify: true,
userContextId: pin.containerTabId || 0,
createLazyBrowser: true,
skipLoad: true,
noInitialLabel: false,
};
// Create and initialize the tab
let newTab = gBrowser.addTrustedTab(pin.url, params);
newTab.setAttribute('zenDefaultUserContextId', true);
// Set initial label/title
if (pin.title) {
gBrowser.setInitialTabTitle(newTab, pin.title);
}
// Set the icon if we have it cached
if (pin.iconUrl) {
gBrowser.setIcon(newTab, pin.iconUrl);
}
newTab.setAttribute('zen-pin-id', pin.uuid);
if (pin.workspaceUuid) {
newTab.setAttribute('zen-workspace-id', pin.workspaceUuid);
}
if (pin.isEssential) {
newTab.setAttribute('zen-essential', 'true');
}
if (pin.editedTitle) {
newTab.setAttribute('zen-has-static-label', 'true');
}
// Initialize browser state if needed
if (!newTab.linkedBrowser._remoteAutoRemoved) {
let state = {
entries: [
{
url: pin.url,
title: pin.title,
triggeringPrincipal_base64: E10SUtils.SERIALIZED_SYSTEMPRINCIPAL,
},
],
userContextId: pin.containerTabId || 0,
image: pin.iconUrl,
};
SessionStore.setTabState(newTab, state);
}
this.log(`Created new pinned tab for pin ${pin.uuid} (isEssential: ${pin.isEssential})`);
gBrowser.pinTab(newTab);
if (pin.parentUuid) {
const parentGroup = groups.get(pin.parentUuid);
if (parentGroup) {
parentGroup.querySelector('.tab-group-container').appendChild(newTab);
} else {
if (pendingTabsInsideGroups[pin.parentUuid]) {
pendingTabsInsideGroups[pin.parentUuid].push(newTab);
} else {
pendingTabsInsideGroups[pin.parentUuid] = [newTab];
}
}
} else {
if (!pin.isEssential) {
const container = gZenWorkspaces.workspaceElement(
pin.workspaceUuid
)?.pinnedTabsContainer;
if (container) {
container.insertBefore(newTab, container.lastChild);
}
} else {
gZenWorkspaces.getEssentialsSection(pin.containerTabId).appendChild(newTab);
}
}
gBrowser.tabContainer._invalidateCachedTabs();
newTab.initialize();
} catch (ex) {
console.error('Failed to initialize pinned tabs:', ex);
}
}
setTimeout(() => {
this.#finishedInitializingPins();
}, 0);
gBrowser._updateTabBarForPinnedTabs();
gZenUIManager.updateTabsToolbar();
}
_onPinnedTabEvent(action, event) { _onPinnedTabEvent(action, event) {
if (!this.enabled) return; if (!this.enabled) return;
const tab = event.target; const tab = event.target;
@@ -412,238 +129,22 @@
} }
switch (action) { switch (action) {
case 'TabPinned': case 'TabPinned':
case 'TabAddedToEssentials':
tab._zenClickEventListener = this._zenClickEventListener; tab._zenClickEventListener = this._zenClickEventListener;
tab.addEventListener('click', tab._zenClickEventListener); tab.addEventListener('click', tab._zenClickEventListener);
this._setPinnedAttributes(tab);
break; break;
case 'TabRemovedFromEssentials':
if (tab.pinned) {
this.#onTabMove(tab);
break;
}
// [Fall through] // [Fall through]
case 'TabUnpinned': case 'TabUnpinned':
this._removePinnedAttributes(tab);
if (tab._zenClickEventListener) { if (tab._zenClickEventListener) {
tab.removeEventListener('click', tab._zenClickEventListener); tab.removeEventListener('click', tab._zenClickEventListener);
delete tab._zenClickEventListener; delete tab._zenClickEventListener;
} }
break; break;
case 'TabMove':
this.#onTabMove(tab);
break;
case 'TabGroupCreate':
this.#onTabGroupCreate(event);
break;
case 'TabGroupRemoved':
this.#onTabGroupRemoved(event);
break;
case 'TabGroupMoved':
this.#onTabGroupMoved(event);
break;
case 'ZenFolderRenamed':
case 'ZenFolderIconChanged':
case 'TabGroupCollapse':
case 'TabGroupExpand':
case 'ZenFolderChangedWorkspace':
this.#updateGroupInfo(event.originalTarget, action);
break;
case 'TabGrouped':
this.#onTabGrouped(event);
break;
case 'TabUngrouped':
this.#onTabUngrouped(event);
break;
default: default:
console.warn('ZenPinnedTabManager: Unhandled tab event', action); console.warn('ZenPinnedTabManager: Unhandled tab event', action);
break; break;
} }
} }
async #onTabGroupCreate(event) {
const group = event.originalTarget;
if (!group.isZenFolder) {
return;
}
if (group.hasAttribute('zen-pin-id')) {
return; // Group already exists in storage
}
const workspaceId = group.getAttribute('zen-workspace-id');
let id = await ZenPinnedTabsStorage.createGroup(
group.name,
group.iconURL,
group.collapsed,
workspaceId,
group.getAttribute('zen-pin-id'),
group._pPos
);
group.setAttribute('zen-pin-id', id);
for (const tab of group.tabs) {
// Only add it if the tab is directly under the group
if (
tab.pinned &&
tab.hasAttribute('zen-pin-id') &&
tab.group === group &&
this.hasInitializedPins
) {
const tabPinId = tab.getAttribute('zen-pin-id');
await ZenPinnedTabsStorage.addTabToGroup(tabPinId, id, /* position */ tab._pPos);
}
}
await this.refreshPinnedTabs();
}
async #onTabGrouped(event) {
const tab = event.detail;
const group = tab.group;
if (!group.isZenFolder) {
return;
}
const pinId = group.getAttribute('zen-pin-id');
const tabPinId = tab.getAttribute('zen-pin-id');
const tabPin = this._pinsCache?.find((p) => p.uuid === tabPinId);
if (!tabPin || !tabPin.group) {
return;
}
ZenPinnedTabsStorage.addTabToGroup(tabPinId, pinId, /* position */ tab._pPos);
}
async #onTabUngrouped(event) {
const tab = event.detail;
const group = tab.group;
if (!group?.isZenFolder) {
return;
}
const tabPinId = tab.getAttribute('zen-pin-id');
const tabPin = this._pinsCache?.find((p) => p.uuid === tabPinId);
if (!tabPin) {
return;
}
ZenPinnedTabsStorage.removeTabFromGroup(tabPinId, /* position */ tab._pPos);
}
async #updateGroupInfo(group, action) {
if (!group?.isZenFolder) {
return;
}
const pinId = group.getAttribute('zen-pin-id');
const groupPin = this._pinsCache?.find((p) => p.uuid === pinId);
if (groupPin) {
groupPin.title = group.name;
groupPin.folderIcon = group.iconURL;
groupPin.isFolderCollapsed = group.collapsed;
groupPin.position = group._pPos;
groupPin.parentUuid = group.group?.getAttribute('zen-pin-id') || null;
groupPin.workspaceUuid = group.getAttribute('zen-workspace-id') || null;
await this.savePin(groupPin);
switch (action) {
case 'ZenFolderRenamed':
case 'ZenFolderIconChanged':
case 'TabGroupCollapse':
case 'TabGroupExpand':
break;
default:
for (const item of group.allItems) {
if (gBrowser.isTabGroup(item)) {
await this.#updateGroupInfo(item, action);
} else {
await this.#onTabMove(item);
}
}
}
}
}
async #onTabGroupRemoved(event) {
const group = event.originalTarget;
if (!group.isZenFolder) {
return;
}
await ZenPinnedTabsStorage.removePin(group.getAttribute('zen-pin-id'));
group.removeAttribute('zen-pin-id');
}
async #onTabGroupMoved(event) {
const group = event.originalTarget;
if (!group.isZenFolder) {
return;
}
const newIndex = group._pPos;
const pinId = group.getAttribute('zen-pin-id');
if (!pinId) {
return;
}
for (const tab of group.allItemsRecursive) {
if (tab.pinned && tab.getAttribute('zen-pin-id') === pinId) {
const pin = this._pinsCache.find((p) => p.uuid === pinId);
if (pin) {
pin.position = tab._pPos;
pin.parentUuid = tab.group?.getAttribute('zen-pin-id') || null;
pin.workspaceUuid = group.getAttribute('zen-workspace-id');
await this.savePin(pin, false);
}
break;
}
}
const groupPin = this._pinsCache?.find((p) => p.uuid === pinId);
if (groupPin) {
groupPin.position = newIndex;
groupPin.parentUuid = group.group?.getAttribute('zen-pin-id');
groupPin.workspaceUuid = group.getAttribute('zen-workspace-id');
await this.savePin(groupPin);
}
}
async #onTabMove(tab) {
if (!tab.pinned || !this._pinsCache) {
return;
}
const allTabs = [...gBrowser.tabs, ...gBrowser.tabGroups];
for (let i = 0; i < allTabs.length; i++) {
const otherTab = allTabs[i];
if (
otherTab.pinned &&
otherTab.getAttribute('zen-pin-id') !== tab.getAttribute('zen-pin-id')
) {
const actualPin = this._pinsCache.find(
(pin) => pin.uuid === otherTab.getAttribute('zen-pin-id')
);
if (!actualPin) {
continue;
}
actualPin.position = otherTab._pPos;
actualPin.workspaceUuid = otherTab.getAttribute('zen-workspace-id');
actualPin.parentUuid = otherTab.group?.getAttribute('zen-pin-id') || null;
await this.savePin(actualPin, false);
}
}
const actualPin = this._pinsCache.find((pin) => pin.uuid === tab.getAttribute('zen-pin-id'));
if (!actualPin) {
return;
}
actualPin.position = tab._pPos;
actualPin.isEssential = tab.hasAttribute('zen-essential');
actualPin.parentUuid = tab.group?.getAttribute('zen-pin-id') || null;
actualPin.workspaceUuid = tab.getAttribute('zen-workspace-id') || null;
// There was a bug where the title and hasStaticLabel attribute were not being set
// This is a workaround to fix that
if (tab.hasAttribute('zen-has-static-label')) {
actualPin.editedTitle = true;
actualPin.title = tab.label;
}
await this.savePin(actualPin);
tab.dispatchEvent(
new CustomEvent('ZenPinnedTabMoved', {
detail: { tab },
})
);
}
async _onTabClick(e) { async _onTabClick(e) {
const tab = e.target?.closest('tab'); const tab = e.target?.closest('tab');
if (e.button === 1 && tab) { if (e.button === 1 && tab) {
@@ -673,106 +174,10 @@
return; return;
} }
const browser = tab.linkedBrowser;
const pin = this._pinsCache.find((pin) => pin.uuid === tab.getAttribute('zen-pin-id'));
if (!pin) {
return;
}
const userContextId = tab.getAttribute('usercontextid');
pin.title = tab.label || browser.contentTitle;
pin.url = browser.currentURI.spec;
pin.workspaceUuid = tab.getAttribute('zen-workspace-id');
pin.userContextId = userContextId ? parseInt(userContextId, 10) : 0;
await this.savePin(pin);
this.resetPinChangedUrl(tab); this.resetPinChangedUrl(tab);
await this.refreshPinnedTabs();
gZenUIManager.showToast('zen-pinned-tab-replaced'); gZenUIManager.showToast('zen-pinned-tab-replaced');
} }
async _setPinnedAttributes(tab) {
if (
tab.hasAttribute('zen-pin-id') ||
!this._hasFinishedLoading ||
tab.hasAttribute('zen-empty-tab')
) {
return;
}
this.log(`Setting pinned attributes for tab ${tab.linkedBrowser.currentURI.spec}`);
const browser = tab.linkedBrowser;
const uuid = gZenUIManager.generateUuidv4();
const userContextId = tab.getAttribute('usercontextid');
let entry = null;
if (tab.getAttribute('zen-pinned-entry')) {
entry = JSON.parse(tab.getAttribute('zen-pinned-entry'));
}
await this.savePin({
uuid,
title: entry?.title || tab.label || browser.contentTitle,
url: entry?.url || browser.currentURI.spec,
containerTabId: userContextId ? parseInt(userContextId, 10) : 0,
workspaceUuid: tab.getAttribute('zen-workspace-id'),
isEssential: tab.getAttribute('zen-essential') === 'true',
parentUuid: tab.group?.getAttribute('zen-pin-id') || null,
position: tab._pPos,
});
tab.setAttribute('zen-pin-id', uuid);
tab.dispatchEvent(
new CustomEvent('ZenPinnedTabCreated', {
detail: { tab },
})
);
// This is used while migrating old pins to new system - we don't want to refresh when migrating
if (tab.getAttribute('zen-pinned-entry')) {
tab.removeAttribute('zen-pinned-entry');
return;
}
this.onLocationChange(browser);
await this.refreshPinnedTabs();
}
async _removePinnedAttributes(tab, isClosing = false) {
tab.removeAttribute('zen-has-static-label');
if (!tab.getAttribute('zen-pin-id') || this._temporarilyUnpiningEssential) {
return;
}
if (Services.startup.shuttingDown || window.skipNextCanClose) {
return;
}
this.log(`Removing pinned attributes for tab ${tab.getAttribute('zen-pin-id')}`);
await ZenPinnedTabsStorage.removePin(tab.getAttribute('zen-pin-id'));
this.resetPinChangedUrl(tab);
if (!isClosing) {
tab.removeAttribute('zen-pin-id');
tab.removeAttribute('zen-essential'); // Just in case
if (!tab.hasAttribute('zen-workspace-id') && gZenWorkspaces.workspaceEnabled) {
const workspace = await gZenWorkspaces.getActiveWorkspace();
tab.setAttribute('zen-workspace-id', workspace.uuid);
}
}
await this.refreshPinnedTabs();
tab.dispatchEvent(
new CustomEvent('ZenPinnedTabRemoved', {
detail: { tab },
})
);
}
_initClosePinnedTabShortcut() { _initClosePinnedTabShortcut() {
let cmdClose = document.getElementById('cmd_close'); let cmdClose = document.getElementById('cmd_close');
@@ -781,21 +186,6 @@
} }
} }
async savePin(pin, notifyObservers = true) {
if (!this.hasInitializedPins && !gZenUIManager.testingEnabled) {
return;
}
const existingPin = this._pinsCache.find((p) => p.uuid === pin.uuid);
if (existingPin) {
Object.assign(existingPin, pin);
} else {
// We shouldn't need it, but just in case there's
// a race condition while making new pinned tabs.
this._pinsCache.push(pin);
}
await ZenPinnedTabsStorage.savePin(pin, notifyObservers);
}
async onCloseTabShortcut( async onCloseTabShortcut(
event, event,
selectedTab = gBrowser.selectedTab, selectedTab = gBrowser.selectedTab,
@@ -842,7 +232,6 @@
switch (behavior) { switch (behavior) {
case 'close': { case 'close': {
for (const tab of pinnedTabs) { for (const tab of pinnedTabs) {
this._removePinnedAttributes(tab, true);
gBrowser.removeTab(tab, { animate: true }); gBrowser.removeTab(tab, { animate: true });
} }
break; break;
@@ -1018,12 +407,6 @@
tab.removeAttribute('zen-workspace-id'); tab.removeAttribute('zen-workspace-id');
} }
if (tab.pinned && tab.hasAttribute('zen-pin-id')) { if (tab.pinned && tab.hasAttribute('zen-pin-id')) {
const pin = this._pinsCache.find((pin) => pin.uuid === tab.getAttribute('zen-pin-id'));
if (pin) {
pin.isEssential = true;
pin.workspaceUuid = null;
this.savePin(pin);
}
gBrowser.zenHandleTabMove(tab, () => { gBrowser.zenHandleTabMove(tab, () => {
if (tab.ownerGlobal !== window) { if (tab.ownerGlobal !== window) {
tab = gBrowser.adoptTab(tab, { tab = gBrowser.adoptTab(tab, {
@@ -1106,6 +489,7 @@
const element = window.MozXULElement.parseXULToFragment(` const element = window.MozXULElement.parseXULToFragment(`
<menuitem id="context_zen-add-essential" <menuitem id="context_zen-add-essential"
data-l10n-id="tab-context-zen-add-essential" data-l10n-id="tab-context-zen-add-essential"
data-l10n-args='{"num": "0", "max": "${this.maxEssentialTabs}"}'
hidden="true" hidden="true"
disabled="true" disabled="true"
command="cmd_contextZenAddToEssentials"/> command="cmd_contextZenAddToEssentials"/>
@@ -1118,24 +502,21 @@
document.getElementById('context_pinTab')?.before(element); document.getElementById('context_pinTab')?.before(element);
} }
async updatePinnedTabContextMenu(contextTab) { updatePinnedTabContextMenu(contextTab) {
if (!this.enabled) { if (!this.enabled) {
document.getElementById('context_pinTab').hidden = true; document.getElementById('context_pinTab').hidden = true;
return; return;
} }
const isVisible = contextTab.pinned && !contextTab.multiselected; const isVisible = contextTab.pinned && !contextTab.multiselected;
const zenAddEssential = document.getElementById('context_zen-add-essential');
document.getElementById('context_zen-reset-pinned-tab').hidden = document.getElementById('context_zen-reset-pinned-tab').hidden =
!isVisible || !contextTab.getAttribute('zen-pin-id'); !isVisible || !contextTab.getAttribute('zen-pin-id');
document.getElementById('context_zen-replace-pinned-url-with-current').hidden = !isVisible; document.getElementById('context_zen-replace-pinned-url-with-current').hidden = !isVisible;
zenAddEssential.hidden = contextTab.getAttribute('zen-essential') || !!contextTab.group; document.getElementById('context_zen-add-essential').hidden =
zenAddEssential.setAttribute( contextTab.getAttribute('zen-essential') || !!contextTab.group;
'badge', document.l10n.setArgs(document.getElementById('context_zen-add-essential'), {
await document.l10n.formatValue('tab-context-zen-add-essential-badge', {
num: gBrowser._numZenEssentials, num: gBrowser._numZenEssentials,
max: this.maxEssentialTabs, max: this.maxEssentialTabs,
}) });
);
document document
.getElementById('cmd_contextZenAddToEssentials') .getElementById('cmd_contextZenAddToEssentials')
.setAttribute('disabled', !this.canEssentialBeAdded(contextTab)); .setAttribute('disabled', !this.canEssentialBeAdded(contextTab));
@@ -1416,11 +797,8 @@
return document.documentElement.getAttribute('zen-sidebar-expanded') === 'true'; return document.documentElement.getAttribute('zen-sidebar-expanded') === 'true';
} }
async updatePinTitle(tab, newTitle, isEdited = true, notifyObservers = true) { async updatePinTitle(tab, newTitle, isEdited = true) {
const uuid = tab.getAttribute('zen-pin-id'); const uuid = tab.getAttribute('zen-pin-id');
await ZenPinnedTabsStorage.updatePinTitle(uuid, newTitle, isEdited, notifyObservers);
await this.refreshPinnedTabs();
const browsers = Services.wm.getEnumerator('navigator:browser'); const browsers = Services.wm.getEnumerator('navigator:browser');
@@ -1565,6 +943,7 @@
} }
async onTabLabelChanged(tab) { async onTabLabelChanged(tab) {
tab.dispatchEvent(new CustomEvent('ZenTabLabelChanged', { detail: { tab } }));
if (!this._pinsCache) { if (!this._pinsCache) {
return; return;
} }

View File

@@ -514,8 +514,10 @@
& #nav-bar { & #nav-bar {
padding-right: 0; padding-right: 0;
:root[zen-single-toolbar='true']:not([zen-has-empty-tab='true']) & { :root[zen-single-toolbar='true'] & {
& #urlbar:not([breakout-extend='true']) .urlbar-input-container { &
#urlbar:not([breakout-extend='true']):not([pageproxystate='invalid'])
.urlbar-input-container {
padding-left: 8px; padding-left: 8px;
padding-right: 4px; padding-right: 4px;
} }

View File

@@ -0,0 +1,308 @@
// 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') && !tab.hasAttribute('zen-empty-tab')) {
const tabId = gZenUIManager.generateUuidv4();
tab.setAttribute('zen-sync-id', tabId);
}
}
}
#setUpEventListeners() {
const kEvents = [
'TabClose',
'TabOpen',
'TabMove',
'TabPinned',
'TabUnpinned',
'TabAddedToEssentials',
'TabRemovedFromEssentials',
'TabHide',
'TabShow',
'ZenTabIconChanged',
'ZenTabLabelChanged',
'TabGroupCreate',
'TabGroupRemoved',
'TabGrouped',
'TabUngrouped',
'TabGroupMoved',
];
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':
case 'TabGroupMoved':
this.#onTabMove(event);
break;
case 'ZenTabIconChanged':
this.#onTabIconChanged(event);
break;
case 'ZenTabLabelChanged':
this.#onTabLabelChanged(event);
break;
case 'TabGroupCreate':
this.#onTabGroupCreate(event);
break;
case 'TabGroupRemoved':
case 'TabGrouped':
case 'TabUngrouped':
// Tab grouping changes are automatically synced by Firefox
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 tabToMove = this.#getTabWithId(tabId);
const workspaceId = targetTab.getAttribute('zen-workspace-id');
const isEssential = targetTab.hasAttribute('zen-essential');
if (tabToMove) {
let tabSibling = targetTab.previousElementSibling;
let isFirst = false;
if (!tabSibling?.hasAttribute('zen-sync-id')) {
isFirst = true;
}
gBrowser.zenHandleTabMove(tabToMove, () => {
if (isFirst) {
let container;
if (isEssential) {
container = gZenWorkspaces.getEssentialsSection(tabToMove);
} else {
const workspaceElement = gZenWorkspaces.workspaceElement(workspaceId);
container = tabToMove.pinned
? workspaceElement.pinnedTabsContainer
: workspaceElement.tabsContainer;
}
container.insertBefore(tabToMove, container.firstChild);
} else {
let relativeTab = gZenWorkspaces.allStoredTabs.find((tab) => {
return this.#getTabId(tab) === this.#getTabId(tabSibling);
});
if (relativeTab) {
relativeTab.after(tabToMove);
}
}
});
}
}
async #onTabOpen(event) {
const targetTab = event.target;
const isPinned = targetTab.pinned;
const isEssential = isPinned && targetTab.hasAttribute('zen-essential');
if (!this.#getTabId(targetTab) && !targetTab.hasAttribute('zen-empty-tab')) {
const tabId = gZenUIManager.generateUuidv4();
targetTab.setAttribute('zen-sync-id', tabId);
}
const duplicatedTab = gBrowser.addTrustedTab(targetTab.linkedBrowser.currentURI.spec, {
createLazyBrowser: true,
essential: isEssential,
pinned: isPinned,
});
if (!isEssential) {
gZenWorkspaces.moveTabToWorkspace(
duplicatedTab,
targetTab.getAttribute('zen-workspace-id')
);
}
duplicatedTab.setAttribute('zen-sync-id', targetTab.getAttribute('zen-sync-id'));
}
#onTabGroupCreate(event) {
void event;
//const targetGroup = event.target;
//const isSplitView = targetGroup.classList.contains('zen-split-view');
//const isFolder = targetGroup.isZenFolder;
}
}
window.gZenWorkspaceWindowSync = new nsZenWorkspaceWindowSync();
}

View File

@@ -932,7 +932,6 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature {
await this.workspaceBookmarks(); await this.workspaceBookmarks();
await this.initializeTabsStripSections(); await this.initializeTabsStripSections();
this._initializeEmptyTab(); this._initializeEmptyTab();
await gZenPinnedTabManager.refreshPinnedTabs({ init: true });
await this.changeWorkspace(activeWorkspace, { onInit: true }); await this.changeWorkspace(activeWorkspace, { onInit: true });
this.#fixTabPositions(); this.#fixTabPositions();
this.onWindowResize(); this.onWindowResize();
@@ -1471,11 +1470,6 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature {
!tab.hasAttribute('zen-empty-tab') && !tab.hasAttribute('zen-empty-tab') &&
!tab.hasAttribute('zen-essential') !tab.hasAttribute('zen-essential')
); );
for (const tab of tabs) {
if (tab.pinned) {
await ZenPinnedTabsStorage.removePin(tab.getAttribute('zen-pin-id'));
}
}
gBrowser.removeTabs(tabs, { gBrowser.removeTabs(tabs, {
animate: false, animate: false,
skipSessionStore: true, skipSessionStore: true,
@@ -2655,7 +2649,6 @@ var gZenWorkspaces = new (class extends nsZenMultiWindowFeature {
#changeToEmptyTab() { #changeToEmptyTab() {
const isEmpty = gBrowser.selectedTab.hasAttribute('zen-empty-tab'); const isEmpty = gBrowser.selectedTab.hasAttribute('zen-empty-tab');
gZenCompactModeManager.sidebar.toggleAttribute('zen-has-empty-tab', isEmpty); gZenCompactModeManager.sidebar.toggleAttribute('zen-has-empty-tab', isEmpty);
document.documentElement.setAttribute('zen-has-empty-tab', isEmpty);
} }
async onLocationChange(event) { async onLocationChange(event) {

View File

@@ -28,7 +28,6 @@ export default [
'ZenWorkspaceBookmarksStorage', 'ZenWorkspaceBookmarksStorage',
'gZenPinnedTabManager', 'gZenPinnedTabManager',
'ZenPinnedTabsStorage',
'gZenEmojiPicker', 'gZenEmojiPicker',
'gZenSessionStore', 'gZenSessionStore',