Skip to content

Instantly share code, notes, and snippets.

@psykzz
Created March 25, 2026 16:39
Show Gist options
  • Select an option

  • Save psykzz/1c0130f74148e9b92e2eaae40a472b57 to your computer and use it in GitHub Desktop.

Select an option

Save psykzz/1c0130f74148e9b92e2eaae40a472b57 to your computer and use it in GitHub Desktop.
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