Skip to content

Commit

Permalink
[extension] Add context menu item in the browser extension. Fixes #155 (
Browse files Browse the repository at this point in the history
#278)

* Add context menu item in the browser extension #155
Added a context menu entry to add links directly to hoarder

* Formalize protocol between extension and service worker, add support for text/images beside links

* fix build

---------

Co-authored-by: MohamedBassem <[email protected]>
  • Loading branch information
kamtschatka and MohamedBassem authored Aug 18, 2024
1 parent c7f9feb commit 0710147
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 31 deletions.
1 change: 1 addition & 0 deletions apps/browser-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
},
"dependencies": {
"@hoarder/shared-react": "workspace:^0.1.0",
"@hoarder/shared": "workspace:^0.1.0",
"@hoarder/trpc": "workspace:^0.1.0",
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-popover": "^1.0.7",
Expand Down
50 changes: 35 additions & 15 deletions apps/browser-extension/src/SavePage.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { useEffect, useState } from "react";
import { Navigate } from "react-router-dom";

import { BookmarkTypes } from "../../../packages/shared/types/bookmarks";
import {
BookmarkTypes,
ZNewBookmarkRequest,
zNewBookmarkRequestSchema,
} from "@hoarder/shared/types/bookmarks";

import { NEW_BOOKMARK_REQUEST_KEY_NAME } from "./background/protocol";
import Spinner from "./Spinner";
import { api } from "./utils/trpc";

Expand All @@ -19,23 +25,37 @@ export default function SavePage() {
});

useEffect(() => {
async function getNewBookmarkRequestFromBackgroundScriptIfAny(): Promise<ZNewBookmarkRequest | null> {
const { [NEW_BOOKMARK_REQUEST_KEY_NAME]: req } =
await chrome.storage.session.get(NEW_BOOKMARK_REQUEST_KEY_NAME);
if (!req) {
return null;
}
// Delete the request immediately to avoid issues with lingering values
await chrome.storage.session.remove(NEW_BOOKMARK_REQUEST_KEY_NAME);
return zNewBookmarkRequestSchema.parse(req);
}

async function runSave() {
let currentUrl;
const [currentTab] = await chrome.tabs.query({
active: true,
lastFocusedWindow: true,
});
if (currentTab?.url) {
currentUrl = currentTab.url;
} else {
setError("Couldn't find the URL of the current tab");
return;
let newBookmarkRequest =
await getNewBookmarkRequestFromBackgroundScriptIfAny();
if (!newBookmarkRequest) {
const [currentTab] = await chrome.tabs.query({
active: true,
lastFocusedWindow: true,
});
if (currentTab?.url) {
newBookmarkRequest = {
type: BookmarkTypes.LINK,
url: currentTab.url,
};
} else {
setError("Couldn't find the URL of the current tab");
return;
}
}

createBookmark({
type: BookmarkTypes.LINK,
url: currentUrl,
});
createBookmark(newBookmarkRequest);
}
runSave();
}, [createBookmark]);
Expand Down
50 changes: 45 additions & 5 deletions apps/browser-extension/src/background/background.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,79 @@
import {
BookmarkTypes,
ZNewBookmarkRequest,
} from "@hoarder/shared/types/bookmarks.ts";

import {
getPluginSettings,
Settings,
subscribeToSettingsChanges,
} from "../utils/settings.ts";
import { NEW_BOOKMARK_REQUEST_KEY_NAME } from "./protocol.ts";

const OPEN_HOARDER_ID = "open-hoarder";
const ADD_LINK_TO_HOARDER_ID = "add-link";

function checkSettingsState(settings: Settings) {
if (settings?.address) {
registerContextMenu();
registerContextMenus();
} else {
chrome.contextMenus.remove(OPEN_HOARDER_ID);
removeContextMenus();
}
}

function removeContextMenus() {
chrome.contextMenus.remove(OPEN_HOARDER_ID);
chrome.contextMenus.remove(ADD_LINK_TO_HOARDER_ID);
}

/**
* Registers a context menu button to open a tab with the currently configured hoarder instance
* Registers
* * a context menu button to open a tab with the currently configured hoarder instance
* * a context menu button to add a link to hoarder without loading the page
*/
function registerContextMenu() {
function registerContextMenus() {
chrome.contextMenus.create({
id: OPEN_HOARDER_ID,
title: "Open Hoarder",
contexts: ["action"],
});
chrome.contextMenus.create({
id: ADD_LINK_TO_HOARDER_ID,
title: "Add to Hoarder",
contexts: ["link", "page", "selection", "image"],
});
}

/**
* Reads the current settings and opens a new tab with hoarder
* @param info the information about the click in the context menu
*/
function handleContextMenuClick(info: chrome.contextMenus.OnClickData) {
async function handleContextMenuClick(info: chrome.contextMenus.OnClickData) {
const { menuItemId } = info;
if (menuItemId === OPEN_HOARDER_ID) {
getPluginSettings().then((settings: Settings) => {
chrome.tabs.create({ url: settings.address, active: true });
});
} else if (menuItemId === ADD_LINK_TO_HOARDER_ID) {
let newBookmark: ZNewBookmarkRequest | null = null;
if (info.selectionText) {
newBookmark = {
type: BookmarkTypes.TEXT,
text: info.selectionText,
// TODO: Include a source url in the snippet
};
} else if (info.srcUrl ?? info.linkUrl ?? info.pageUrl) {
newBookmark = {
type: BookmarkTypes.LINK,
url: info.srcUrl ?? info.linkUrl ?? info.pageUrl,
};
}
if (newBookmark) {
await chrome.storage.session.set({
[NEW_BOOKMARK_REQUEST_KEY_NAME]: newBookmark,
});
await chrome.action.openPopup();
}
}
}

Expand All @@ -46,4 +85,5 @@ subscribeToSettingsChanges((settings) => {
checkSettingsState(settings);
});

// eslint-disable-next-line @typescript-eslint/no-misused-promises -- Manifest V3 allows async functions for all callbacks
chrome.contextMenus.onClicked.addListener(handleContextMenuClick);
1 change: 1 addition & 0 deletions apps/browser-extension/src/background/protocol.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const NEW_BOOKMARK_REQUEST_KEY_NAME = "hoarder-new-bookmark";
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"eslint": "^8.57.0",
"husky": "^9.0.11",
"install": "^0.13.0",
"prettier": "3.2.5",
"prettier": "^3.2.5",
"turbo": "^2.0.9"
},
"prettier": "@hoarder/prettier-config",
Expand Down
28 changes: 18 additions & 10 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 0710147

Please sign in to comment.