// ── Toolbar button: open settings page ── browser.browserAction.onClicked.addListener(() => { browser.runtime.openOptionsPage(); }); // ── "Erledigt" button in message display ── async function executeErledigtAction(tab, actionConfig) { const message = await messenger.messageDisplay.getDisplayedMessage(tab.id); if (!message) { browser.notifications.create({ type: 'basic', iconUrl: browser.runtime.getURL('icons/icon.png'), title: 'Fehler', message: 'Keine Nachricht ausgewählt.' }); return; } const storage = await browser.storage.local.get(['gitea_config', 'schlagwoerter_cache']); const config = storage.gitea_config || {}; const schlagwoerter = storage.schlagwoerter_cache; // Apply user's tag let tagKey = null; if (Array.isArray(schlagwoerter) && config.authorName) { const match = schlagwoerter.find(u => u.name.toLowerCase() === config.authorName.toLowerCase()); if (match) { tagKey = `$hps_${match.name.toLowerCase().replace(/\s+/g, '_')}`; } } if (tagKey) { const currentTags = message.tags || []; if (!currentTags.includes(tagKey)) { await messenger.messages.update(message.id, { tags: [...currentTags, tagKey] }); } } // Move to target folder if (actionConfig.targetFolder) { const folderInfo = JSON.parse(actionConfig.targetFolder); await messenger.messages.move([message.id], folderInfo); } // Feedback const parts = []; if (tagKey) parts.push('markiert'); if (actionConfig.targetFolder) parts.push('verschoben'); const title = actionConfig.name || 'Erledigt'; browser.notifications.create({ type: 'basic', iconUrl: browser.runtime.getURL('icons/icon.png'), title, message: parts.length ? `Nachricht ${parts.join(' & ')}.` : 'Kein Schlagwort oder Zielordner konfiguriert.' }); } // Single action: direct click without popup messenger.messageDisplayAction.onClicked.addListener(async (tab) => { try { const result = await browser.storage.local.get('erledigt_config'); const actions = (result.erledigt_config || {}).actions || []; await executeErledigtAction(tab, actions[0] || {}); } catch (e) { console.error('Erledigt-Button Fehler:', e); browser.notifications.create({ type: 'basic', iconUrl: browser.runtime.getURL('icons/icon.png'), title: 'Fehler', message: e.message }); } }); // Toggle popup vs direct click based on action count async function updateErledigtPopup() { const result = await browser.storage.local.get('erledigt_config'); const actions = (result.erledigt_config || {}).actions || []; if (actions.length > 1) { await messenger.messageDisplayAction.setPopup({ popup: 'message_popup.html' }); await messenger.messageDisplayAction.setTitle({ title: 'Aktion wählen' }); } else { await messenger.messageDisplayAction.setPopup({ popup: '' }); await messenger.messageDisplayAction.setTitle({ title: actions[0]?.name || 'Erledigt' }); } } // Update on config change browser.storage.onChanged.addListener((changes, area) => { if (area === 'local' && changes.erledigt_config) updateErledigtPopup(); }); updateErledigtPopup(); // ── Template insertion ── browser.runtime.onMessage.addListener((msg, sender, sendResponse) => { if (msg.action === 'erledigtAction') { (async () => { try { const [tab] = await browser.tabs.query({ active: true, currentWindow: true }); const result = await browser.storage.local.get('erledigt_config'); const actions = (result.erledigt_config || {}).actions || []; const action = actions[msg.index] || {}; await executeErledigtAction(tab, action); sendResponse({ success: true }); } catch (e) { console.error('Erledigt-Action Fehler:', e); browser.notifications.create({ type: 'basic', iconUrl: browser.runtime.getURL('icons/icon.png'), title: 'Fehler', message: e.message }); sendResponse({ success: false, error: e.message }); } })(); return true; } if (msg.action !== 'insertTemplate') return; handleInsertTemplate(msg).then(() => sendResponse()) .catch(err => sendResponse({ error: err.message })); return true; // keep channel open for async response }); async function handleInsertTemplate(msg) { try { const [tab] = await browser.tabs.query({ active: true, currentWindow: true, windowType: 'messageCompose', }); if (!tab) throw new Error('Kein Compose-Fenster gefunden'); const details = await browser.compose.getComposeDetails(tab.id); const isHtmlTemplate = msg.text.includes('<'); // If compose is plain text but template is HTML, switch to HTML mode first if (details.isPlainText && isHtmlTemplate) { await browser.compose.setComposeDetails(tab.id, { isPlainText: false }); } if (details.isPlainText && !isHtmlTemplate) { // Plain text template in plain text mode - use old method const old = details.plainTextBody || ''; const newBody = msg.text + (old ? '\n' + old : ''); await browser.compose.setComposeDetails(tab.id, { plainTextBody: newBody }); } else { // HTML mode: use insertText API to go through the editor's rendering pipeline const htmlContent = isHtmlTemplate ? msg.text : msg.text.replace(/\n/g, '
'); // Move cursor to beginning of body first via script injection await browser.tabs.executeScript(tab.id, { code: ` const editor = document.getElementById('messageEditor'); const editorDoc = editor ? editor.contentDocument : document; const body = editorDoc.body; if (body) { const range = editorDoc.createRange(); range.setStart(body, 0); range.collapse(true); const sel = editorDoc.getSelection(); sel.removeAllRanges(); sel.addRange(range); } ` }).catch(() => { // Fallback: some TB versions structure the editor differently }); // Insert HTML at cursor position - this goes through the editor's render pipeline await browser.compose.insertText(tab.id, htmlContent + '
', { insertAsText: false }); } } catch (e) { console.error('background.js error:', e); // Fallback: if insertText fails, try setComposeDetails try { const [tab] = await browser.tabs.query({ active: true, currentWindow: true, windowType: 'messageCompose', }); if (tab) { const details = await browser.compose.getComposeDetails(tab.id); const old = details.body || ''; const htmlTpl = msg.text.includes('<') ? msg.text : msg.text.replace(/\n/g, '
'); const bodyIdx = old.indexOf('', bodyIdx) + 1; newBody = old.slice(0, insertAt) + '\n' + htmlTpl + '\n' + old.slice(insertAt); } else { newBody = htmlTpl + '
' + old; } await browser.compose.setComposeDetails(tab.id, { body: newBody }); } } catch (e2) { console.error('background.js fallback error:', e2); browser.notifications.create({ type: 'basic', iconUrl: browser.runtime.getURL('icons/icon.png'), title: 'Fehler beim Einfügen', message: e2.message, }); } } }