diff --git a/background.js b/background.js index 060d8db75..406d9f3b6 100644 --- a/background.js +++ b/background.js @@ -4,6 +4,8 @@ chrome.commands.onCommand.addListener(async function (command) { await saveSelection(); } else if (command == "saveWholePage") { await saveWholePage(); + } else if (command == "saveTabs") { + await saveTabs(); } else if (command == "saveScreenshot") { const activeTab = await getActiveTab(); @@ -100,6 +102,18 @@ async function getActiveTab() { return tabs[0]; } +async function getWindowTabs() { + const tabs = await browser.tabs.query({ + currentWindow: true + }); + + return tabs; +} + +async function closeWindowTabs(tabs) { + await browser.tabs.remove(tabs.map(tab=>{return tab.id})); +} + async function sendMessageToActiveTab(message) { const activeTab = await getActiveTab(); @@ -237,6 +251,50 @@ async function saveWholePage() { toast("Page has been saved to Trilium.", resp.noteId); } +async function getTabsPayload(tabs) { + let content = ''; + + // topDomains string with 1-3 most used domains will be used as the note title + // to help the user differentiate between multiple notes of this type + const domainsCount = tabs.map(tab => tab.url) + .reduce((acc, url) => { + const hostname = new URL(url).hostname + return acc.set(hostname, (acc.get(hostname) || 0) + 1) + }, new Map()); + + let topDomains = [...domainsCount] + .sort((a, b) => {return b[1]-a[1]}) + .slice(0,3) + .map(domain=>domain[0]) + .join(', ') + + if (tabs.length > 3) { topDomains += '...' }; + + return { + title: `${tabs.length} browser tabs: ${topDomains}`, + content: content, + clipType: 'tabs' + }; +} + +async function saveTabs() { + const tabs = await getWindowTabs(); + + const payload = await getTabsPayload(tabs); + + const resp = await triliumServerFacade.callService('POST', 'notes', payload); + + if (!resp) { + return; + } + + await closeWindowTabs(tabs); +} + async function saveNote(title, content) { const resp = await triliumServerFacade.callService('POST', 'notes', { title: title, @@ -330,6 +388,9 @@ browser.runtime.onMessage.addListener(async request => { else if (request.name === 'save-whole-page') { return await saveWholePage(); } + else if (request.name === 'save-tabs') { + return await saveTabs(); + } else if (request.name === 'save-note') { return await saveNote(request.title, request.content); } diff --git a/popup/popup.html b/popup/popup.html index fe94eed29..3a85fd7a1 100644 --- a/popup/popup.html +++ b/popup/popup.html @@ -21,6 +21,7 @@ +
@@ -43,4 +44,4 @@ - \ No newline at end of file + diff --git a/popup/popup.js b/popup/popup.js index ff61ca423..0b5a008db 100644 --- a/popup/popup.js +++ b/popup/popup.js @@ -12,6 +12,7 @@ async function sendMessage(message) { const $showOptionsButton = $("#show-options-button"); const $clipScreenShotButton = $("#clip-screenshot-button"); const $saveWholePageButton = $("#save-whole-page-button"); +const $saveTabsButton = $("#save-tabs-button"); $showOptionsButton.on("click", () => browser.runtime.openOptionsPage()); @@ -19,6 +20,8 @@ $clipScreenShotButton.on("click", () => sendMessage({name: 'save-screenshot'})); $saveWholePageButton.on("click", () => sendMessage({name: 'save-whole-page'})); +$saveTabsButton.on("click", () => sendMessage({name: 'save-tabs'})); + const $createTextNoteWrapper = $("#create-text-note-wrapper"); const $textNote = $("#create-text-note-textarea"); @@ -141,4 +144,4 @@ $checkConnectionButton.on("click", () => { }) }); -$(() => browser.runtime.sendMessage({name: "send-trilium-search-status"})); \ No newline at end of file +$(() => browser.runtime.sendMessage({name: "send-trilium-search-status"}));