Created
March 25, 2026 16:39
-
-
Save psykzz/1c0130f74148e9b92e2eaae40a472b57 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Logger from "./src/Logger.js"; | |
| import StorageManager from "./src/StorageManager.js"; | |
| let logger = new Logger(); | |
| let storageManager = new StorageManager(logger); | |
| let isSyncing = false; | |
| // Hilfsfunktion: Alle aktuell angepinnten Tabs abrufen | |
| async function getPinnedTabs() { | |
| const tabs = await browser.tabs.query({ pinned: true }); | |
| // De-duplizierung basierend auf normalisierten URLs | |
| const uniqueUrls = []; | |
| const seen = new Set(); | |
| for (const tab of tabs) { | |
| const norm = tab.url; | |
| if (!seen.has(norm)) { | |
| seen.add(norm); | |
| uniqueUrls.push(tab.url); | |
| } | |
| } | |
| return uniqueUrls; | |
| } | |
| // Hilfsfunktion: Speicher aktualisieren | |
| async function updateStoredPinnedTabs() { | |
| if (isSyncing) return; | |
| const windows = await browser.windows.getAll({ windowTypes: ["normal"] }); | |
| if (windows.length === 0) { | |
| logger.log("Keine normalen Fenster offen, überspringe Speichern (vermutlich macOS-Schließvorgang)."); | |
| return; | |
| } | |
| const pinnedUrls = await getPinnedTabs(); | |
| await storageManager.saveList(pinnedUrls); | |
| } | |
| // Hilfsfunktion: Lokale Tabs mit den gespeicherten synchronisieren | |
| async function syncLocalTabs(storedUrls, overwrite=false) { | |
| if (isSyncing) return; | |
| isSyncing = true; | |
| try { | |
| const windows = await browser.windows.getAll({ populate: true }); | |
| for (const window of windows) { | |
| // Nur normale Browserfenster berücksichtigen | |
| if (window.type !== "normal") continue; | |
| const currentPinned = window.tabs.filter(t => t.pinned); | |
| // veraltete Tabs aktualisieren | |
| for (let i = 0; i < currentPinned.length; i++) { | |
| let currentTab = currentPinned[i]; | |
| let storedUrl = storedUrls[i]; | |
| if(storageManager.normalizeUrl(currentTab.url) !== storageManager.normalizeUrl(storedUrl)){ | |
| await browser.tabs.update(currentTab.id,{url: storedUrl}); | |
| } | |
| } | |
| //Überzählige Tabs schließen | |
| if(currentPinned.length>storedUrls.length){ | |
| let start = storedUrls.length; | |
| for (let i = start; i < currentPinned.length; i++) { | |
| await browser.tabs.remove(currentPinned[i].id); | |
| } | |
| } | |
| //Fehlende Tabs hinzufügen | |
| if(currentPinned.length<storedUrls.length){ | |
| let start = currentPinned.length; | |
| for (let i = start; i < storedUrls.length; i++) { | |
| await browser.tabs.create({ | |
| windowId: window.id, | |
| url: storedUrls[i], | |
| pinned: true, | |
| active: false | |
| }); | |
| } | |
| } | |
| } | |
| } finally { | |
| // Kurze Verzögerung beim Zurücksetzen, um Event-Spams abzufangen | |
| setTimeout(() => { | |
| isSyncing = false; | |
| }, 200); | |
| } | |
| } | |
| // Listener für Tab-Änderungen | |
| browser.tabs.onUpdated.addListener((tabId, changeInfo, tab) => { | |
| // Nur reagieren, wenn das Pinnen geändert wurde oder die URL in einem Pinned Tab | |
| // (Wir reagieren erst, wenn das Tab-Objekt auch eine URL hat, falls sie sich ändert) | |
| if (changeInfo.pinned !== undefined) { | |
| if(changeInfo.pinned){ | |
| logger.log("tabPinned"); | |
| updateStoredPinnedTabs(); | |
| } else { | |
| logger.log("tabUnpinned"); | |
| removeListener(tab.windowId); | |
| } | |
| } | |
| }); | |
| browser.tabs.onRemoved.addListener((tabId, removeInfo) => { | |
| removeListener(removeInfo.windowId); | |
| }); | |
| async function removeListener(windowId){ | |
| browser.windows.get(windowId, { populate: true }).then( | |
| (win)=>{ | |
| let tabsUrls = win.tabs.filter(t=>t.pinned).map(t=>t.url) | |
| logger.log("onRemoved pinned"); | |
| storageManager.saveList(tabsUrls); | |
| }, | |
| ()=>{ | |
| //Dows not exist. Nothing to do | |
| } | |
| ); | |
| } | |
| // Listener für neue Fenster | |
| browser.windows.onCreated.addListener(async (window) => { | |
| if (window.type !== "normal") return; | |
| const data = await browser.storage.sync.get("pinnedTabs"); | |
| if (data.pinnedTabs && data.pinnedTabs.length > 0) { | |
| // Kurze Verzögerung, damit das Fenster stabil ist | |
| setTimeout(() => { | |
| syncLocalTabs(data.pinnedTabs); | |
| }, 1000); | |
| } | |
| }); | |
| // Listener für Speicheränderungen (Cross-Device / Cross-Window Sync) | |
| browser.storage.onChanged.addListener((changes, area) => { | |
| if (area === "sync" && changes.pinnedTabs) { | |
| logger.log("Speicheränderung erkannt, ersetze alle tabs: "+changes.pinnedTabs.newValue.map(e=>storageManager.normalizeUrl(e))); | |
| replaceAllTabs(changes); | |
| } | |
| }); | |
| async function replaceAllTabs(changes){ | |
| if(isSyncing) return; | |
| syncLocalTabs(changes.pinnedTabs.newValue || [], true); | |
| } | |
| // Initialisierung beim Start | |
| async function init() { | |
| const data = await browser.storage.sync.get("pinnedTabs"); | |
| if (data.pinnedTabs && data.pinnedTabs.length > 0) { | |
| logger.log("Gepinnte Tabs in Cloud gefunden: "+ data.pinnedTabs.map(e=>storageManager.normalizeUrl(e))); | |
| await syncLocalTabs(data.pinnedTabs); | |
| } else { | |
| logger.log("Keine gepinnten Tabs in Cloud gefunden, speichere aktuellen lokalen Zustand..."); | |
| await updateStoredPinnedTabs(); | |
| } | |
| } | |
| // Sobald der Service Worker / Hintergrundscript bereit ist | |
| init() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment