mirror of
https://github.com/notion-enhancer/notion-enhancer.git
synced 2025-04-11 15:59:03 +00:00
fix(browser): handle port disconnection b/w client and worker
This commit is contained in:
parent
025bbca44c
commit
9a1b35afd9
@ -116,11 +116,12 @@ const initMenu = async (db) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async (api, db) => {
|
export default async (api, db) => {
|
||||||
|
const { sendMessage } = globalThis.__enhancerApi;
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
overrideThemes(db),
|
overrideThemes(db),
|
||||||
insertCustomStyles(db),
|
insertCustomStyles(db),
|
||||||
initMenu(db),
|
initMenu(db),
|
||||||
sendTelemetryPing(),
|
sendTelemetryPing(),
|
||||||
]);
|
]);
|
||||||
api.sendMessage("notion-enhancer", "load-complete");
|
sendMessage("notion-enhancer", "load-complete");
|
||||||
};
|
};
|
||||||
|
@ -33,17 +33,24 @@ const platform = IS_ELECTRON
|
|||||||
IS_ELECTRON && !IS_RENDERER ? require(`../../../${target}`) : undefined;
|
IS_ELECTRON && !IS_RENDERER ? require(`../../../${target}`) : undefined;
|
||||||
|
|
||||||
let __port;
|
let __port;
|
||||||
const onMessage = (channel, listener) => {
|
const connectToPort = () => {
|
||||||
|
if (__port) return;
|
||||||
|
__port = chrome.runtime.connect();
|
||||||
|
__port.onDisconnect.addListener(() => (__port = null));
|
||||||
|
},
|
||||||
|
onMessage = (channel, listener) => {
|
||||||
// from worker to client
|
// from worker to client
|
||||||
if (IS_RENDERER) {
|
if (IS_RENDERER) {
|
||||||
const { ipcRenderer } = require("electron");
|
const { ipcRenderer } = require("electron");
|
||||||
ipcRenderer.on(channel, listener);
|
ipcRenderer.on(channel, listener);
|
||||||
} else if (!IS_ELECTRON) {
|
} else if (!IS_ELECTRON) {
|
||||||
__port ??= chrome.runtime.connect();
|
const onMessage = (msg) => {
|
||||||
__port.onMessage.addListener((msg) => {
|
|
||||||
if (msg?.channel !== channel || msg?.invocation) return;
|
if (msg?.channel !== channel || msg?.invocation) return;
|
||||||
listener(msg.message);
|
listener(msg.message);
|
||||||
});
|
};
|
||||||
|
connectToPort();
|
||||||
|
__port.onMessage.addListener(onMessage);
|
||||||
|
chrome.runtime.onMessage.addListener(onMessage);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
sendMessage = (channel, message) => {
|
sendMessage = (channel, message) => {
|
||||||
@ -52,7 +59,7 @@ const onMessage = (channel, listener) => {
|
|||||||
const { ipcRenderer } = require("electron");
|
const { ipcRenderer } = require("electron");
|
||||||
ipcRenderer.send(channel, message);
|
ipcRenderer.send(channel, message);
|
||||||
} else if (!IS_ELECTRON) {
|
} else if (!IS_ELECTRON) {
|
||||||
__port ??= chrome.runtime.connect();
|
connectToPort();
|
||||||
__port.postMessage({ channel, message });
|
__port.postMessage({ channel, message });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -67,7 +74,7 @@ const onMessage = (channel, listener) => {
|
|||||||
// the browser: uses a long-lived ipc connection to
|
// the browser: uses a long-lived ipc connection to
|
||||||
// pass messages and handle responses asynchronously
|
// pass messages and handle responses asynchronously
|
||||||
let fulfilled;
|
let fulfilled;
|
||||||
__port ??= chrome.runtime.connect();
|
connectToPort();
|
||||||
const id = crypto.randomUUID();
|
const id = crypto.randomUUID();
|
||||||
return new Promise((res, rej) => {
|
return new Promise((res, rej) => {
|
||||||
__port.onMessage.addListener((msg) => {
|
__port.onMessage.addListener((msg) => {
|
||||||
@ -118,7 +125,7 @@ const initDatabase = (namespace, fallbacks = {}) => {
|
|||||||
const query = (query, args = {}) =>
|
const query = (query, args = {}) =>
|
||||||
IS_ELECTRON && !IS_RENDERER
|
IS_ELECTRON && !IS_RENDERER
|
||||||
? globalThis.__enhancerApi.queryDatabase(namespace, query, args)
|
? globalThis.__enhancerApi.queryDatabase(namespace, query, args)
|
||||||
: invokeInWorker("notion-enhancer:db", {
|
: invokeInWorker("notion-enhancer", {
|
||||||
action: "query-database",
|
action: "query-database",
|
||||||
data: { namespace, query, args },
|
data: { namespace, query, args },
|
||||||
});
|
});
|
||||||
|
@ -116,7 +116,7 @@ const initDatabase = async () => {
|
|||||||
if (IS_ELECTRON) {
|
if (IS_ELECTRON) {
|
||||||
const { ipcMain } = require("electron"),
|
const { ipcMain } = require("electron"),
|
||||||
{ reloadApp } = globalThis.__enhancerApi;
|
{ reloadApp } = globalThis.__enhancerApi;
|
||||||
ipcMain.handle("notion-enhancer:db", ({}, message) => {
|
ipcMain.handle("notion-enhancer", ({}, message) => {
|
||||||
if (message?.action !== "query-database") return;
|
if (message?.action !== "query-database") return;
|
||||||
const { namespace, query, args } = message.data;
|
const { namespace, query, args } = message.data;
|
||||||
return queryDatabase(namespace, query, args);
|
return queryDatabase(namespace, query, args);
|
||||||
@ -128,19 +128,19 @@ if (IS_ELECTRON) {
|
|||||||
const notionUrl = "https://www.notion.so/",
|
const notionUrl = "https://www.notion.so/",
|
||||||
isNotionTab = (tab) => tab?.url?.startsWith(notionUrl);
|
isNotionTab = (tab) => tab?.url?.startsWith(notionUrl);
|
||||||
|
|
||||||
const tabQueue = new Set(),
|
const connectedTabs = new Set(),
|
||||||
|
openMenuInTabs = new Set(),
|
||||||
openMenu = { channel: "notion-enhancer", message: "open-menu" },
|
openMenu = { channel: "notion-enhancer", message: "open-menu" },
|
||||||
openEnhancerMenu = async (tab) => {
|
openEnhancerMenu = async (tab) => {
|
||||||
if (!isNotionTab(tab)) {
|
if (!isNotionTab(tab)) {
|
||||||
const windowId = chrome.windows.WINDOW_ID_CURRENT,
|
const windowId = chrome.windows.WINDOW_ID_CURRENT;
|
||||||
windowTabs = await chrome.tabs.query({ windowId });
|
tab = (await chrome.tabs.query({ windowId })).find(isNotionTab);
|
||||||
tab = windowTabs.find(isNotionTab);
|
|
||||||
tab ??= await chrome.tabs.create({ url: notionUrl });
|
tab ??= await chrome.tabs.create({ url: notionUrl });
|
||||||
}
|
}
|
||||||
chrome.tabs.highlight({ tabs: [tab.index] });
|
chrome.tabs.highlight({ tabs: [tab.index] });
|
||||||
if (tab.status === "complete") {
|
if (connectedTabs.has(tab.id)) {
|
||||||
chrome.tabs.sendMessage(tab.id, openMenu);
|
chrome.tabs.sendMessage(tab.id, openMenu);
|
||||||
} else tabQueue.add(tab.id);
|
} else openMenuInTabs.add(tab.id);
|
||||||
},
|
},
|
||||||
reloadNotionTabs = async () => {
|
reloadNotionTabs = async () => {
|
||||||
const windowId = chrome.windows.WINDOW_ID_CURRENT;
|
const windowId = chrome.windows.WINDOW_ID_CURRENT;
|
||||||
@ -149,24 +149,29 @@ if (IS_ELECTRON) {
|
|||||||
.forEach((tab) => chrome.tabs.reload(tab.id));
|
.forEach((tab) => chrome.tabs.reload(tab.id));
|
||||||
};
|
};
|
||||||
|
|
||||||
// listen for invoke: https://developer.chrome.com/docs/extensions/mv3/messaging/
|
|
||||||
chrome.action.onClicked.addListener(openEnhancerMenu);
|
chrome.action.onClicked.addListener(openEnhancerMenu);
|
||||||
|
// long-lived connection for rapid two-way messaging
|
||||||
|
// b/w client and worker, primarily used for db wrapper:
|
||||||
|
// https://developer.chrome.com/docs/extensions/mv3/messaging/
|
||||||
chrome.runtime.onConnect.addListener((port) => {
|
chrome.runtime.onConnect.addListener((port) => {
|
||||||
port.onMessage.addListener((msg, sender) => {
|
const tabId = port.sender.tab.id;
|
||||||
|
connectedTabs.add(tabId);
|
||||||
|
port.onMessage.addListener(async (msg) => {
|
||||||
if (msg?.channel !== "notion-enhancer") return;
|
if (msg?.channel !== "notion-enhancer") return;
|
||||||
const { message, invocation } = msg;
|
const { message, invocation } = msg;
|
||||||
if (message.action === "query-database") {
|
if (message.action === "query-database") {
|
||||||
const { namespace, query, args } = message.data,
|
const { namespace, query, args } = message.data,
|
||||||
res = queryDatabase(namespace, query, args);
|
res = await queryDatabase(namespace, query, args);
|
||||||
if (invocation) port.postMessage({ invocation, message: res });
|
if (invocation) port.postMessage({ invocation, message: res });
|
||||||
}
|
}
|
||||||
if (message === "load-complete") {
|
if (message === "load-complete") {
|
||||||
if (!tabQueue.has(sender?.tab?.id)) return;
|
if (!openMenuInTabs.has(tabId)) return;
|
||||||
chrome.tabs.sendMessage(sender.tab.id, openMenu);
|
openMenuInTabs.delete(tabId);
|
||||||
tabQueue.delete(sender.tab.id);
|
port.postMessage(openMenu);
|
||||||
}
|
}
|
||||||
if (message === "reload-app") reloadNotionTabs();
|
if (message === "reload-app") reloadNotionTabs();
|
||||||
});
|
});
|
||||||
|
port.onDisconnect.addListener(() => connectedTabs.delete(tabId));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user