aboutsummaryrefslogtreecommitdiffstats
path: root/apps/browser-extension/src/background/background.ts
blob: 6d8a6ecd03c10c8078d09f9372423c7ae753b3db (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import {
  BookmarkTypes,
  ZNewBookmarkRequest,
} from "@karakeep/shared/types/bookmarks.ts";

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

const OPEN_KARAKEEP_ID = "open-karakeep";
const ADD_LINK_TO_KARAKEEP_ID = "add-link";

function checkSettingsState(settings: Settings) {
  if (settings?.address) {
    registerContextMenus();
  } else {
    removeContextMenus();
  }
}

function removeContextMenus() {
  chrome.contextMenus.remove(OPEN_KARAKEEP_ID);
  chrome.contextMenus.remove(ADD_LINK_TO_KARAKEEP_ID);
}

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

/**
 * Reads the current settings and opens a new tab with karakeep
 * @param info the information about the click in the context menu
 */
async function handleContextMenuClick(info: chrome.contextMenus.OnClickData) {
  const { menuItemId } = info;
  if (menuItemId === OPEN_KARAKEEP_ID) {
    getPluginSettings().then((settings: Settings) => {
      chrome.tabs.create({ url: settings.address, active: true });
    });
  } else if (menuItemId === ADD_LINK_TO_KARAKEEP_ID) {
    let newBookmark: ZNewBookmarkRequest | null = null;
    if (info.selectionText) {
      newBookmark = {
        type: BookmarkTypes.TEXT,
        text: info.selectionText,
        sourceUrl: info.pageUrl,
      };
    } else if (info.srcUrl ?? info.linkUrl ?? info.pageUrl) {
      newBookmark = {
        type: BookmarkTypes.LINK,
        url: info.srcUrl ?? info.linkUrl ?? info.pageUrl,
      };
    }
    if (newBookmark) {
      chrome.storage.session.set({
        [NEW_BOOKMARK_REQUEST_KEY_NAME]: newBookmark,
      });
      // NOTE: Firefox only allows opening context menus if it's triggered by a user action.
      // awaiting on any promise before calling this function will lose the "user action" context.
      await chrome.action.openPopup();
    }
  }
}

getPluginSettings().then((settings: Settings) => {
  checkSettingsState(settings);
});

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);