@btraut/browser-bridge 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/README.md +41 -0
- package/dist/api.js +878 -128
- package/dist/api.js.map +4 -4
- package/dist/index.js +861 -378
- package/dist/index.js.map +4 -4
- package/extension/assets/ui.css +108 -1
- package/extension/dist/background.js +164 -23
- package/extension/dist/background.js.map +4 -4
- package/extension/dist/popup-ui.js +110 -3
- package/extension/dist/popup-ui.js.map +2 -2
- package/extension/manifest.json +1 -1
- package/package.json +1 -1
- package/skills/browser-bridge/skill.json +1 -1
|
@@ -6,11 +6,72 @@
|
|
|
6
6
|
if (!el) {
|
|
7
7
|
throw new Error(`Missing element: ${id}`);
|
|
8
8
|
}
|
|
9
|
-
if (!(el instanceof HTMLAnchorElement)) {
|
|
10
|
-
throw new Error(`Expected <a> element: ${id}`);
|
|
11
|
-
}
|
|
12
9
|
return el;
|
|
13
10
|
};
|
|
11
|
+
var formatTime = (iso) => {
|
|
12
|
+
if (!iso) {
|
|
13
|
+
return "Never";
|
|
14
|
+
}
|
|
15
|
+
const parsed = new Date(iso);
|
|
16
|
+
if (Number.isNaN(parsed.getTime())) {
|
|
17
|
+
return iso;
|
|
18
|
+
}
|
|
19
|
+
return parsed.toLocaleString();
|
|
20
|
+
};
|
|
21
|
+
var setText = (id, value) => {
|
|
22
|
+
byId(id).textContent = value;
|
|
23
|
+
};
|
|
24
|
+
var setStateBadge = (state) => {
|
|
25
|
+
const badge = byId("bb-conn-state");
|
|
26
|
+
badge.textContent = state;
|
|
27
|
+
badge.setAttribute("data-state", state);
|
|
28
|
+
};
|
|
29
|
+
var getConnectionStatus = async () => {
|
|
30
|
+
const response = await new Promise(
|
|
31
|
+
(resolve) => {
|
|
32
|
+
chrome.runtime.sendMessage(
|
|
33
|
+
{ action: "drive.connection_status" },
|
|
34
|
+
(message) => {
|
|
35
|
+
resolve(message);
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
if (!response?.ok || !response.result) {
|
|
41
|
+
throw new Error("Connection status is unavailable.");
|
|
42
|
+
}
|
|
43
|
+
return response.result;
|
|
44
|
+
};
|
|
45
|
+
var copyToClipboard = async (text) => {
|
|
46
|
+
if (navigator.clipboard?.writeText) {
|
|
47
|
+
await navigator.clipboard.writeText(text);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const area = document.createElement("textarea");
|
|
51
|
+
area.value = text;
|
|
52
|
+
area.setAttribute("readonly", "true");
|
|
53
|
+
area.style.position = "fixed";
|
|
54
|
+
area.style.left = "-9999px";
|
|
55
|
+
document.body.appendChild(area);
|
|
56
|
+
area.select();
|
|
57
|
+
document.execCommand("copy");
|
|
58
|
+
document.body.removeChild(area);
|
|
59
|
+
};
|
|
60
|
+
var renderStatus = (status) => {
|
|
61
|
+
setStateBadge(status.state);
|
|
62
|
+
setText(
|
|
63
|
+
"bb-conn-endpoint",
|
|
64
|
+
status.ws_url ?? (status.endpoint ? `ws://${status.endpoint.host}:${status.endpoint.port}/drive` : "Unknown")
|
|
65
|
+
);
|
|
66
|
+
const source = status.endpoint?.portSource ?? "unknown";
|
|
67
|
+
setText("bb-conn-source", source);
|
|
68
|
+
const lastConnected = formatTime(status.last_connected_at);
|
|
69
|
+
setText("bb-conn-last-ok", lastConnected);
|
|
70
|
+
const lastFailure = status.last_error_message ? `${status.last_error_message} (${formatTime(status.last_error_at)})` : "None";
|
|
71
|
+
setText("bb-conn-last-fail", lastFailure);
|
|
72
|
+
const nextRetry = status.retry_at ? formatTime(status.retry_at) : "n/a";
|
|
73
|
+
setText("bb-conn-next-retry", nextRetry);
|
|
74
|
+
};
|
|
14
75
|
var openOptionsPopupWindow = async () => {
|
|
15
76
|
const chromeAny = chrome;
|
|
16
77
|
const url = chromeAny.runtime.getURL("options.html");
|
|
@@ -53,6 +114,51 @@
|
|
|
53
114
|
window.open(url, "_blank", "noopener");
|
|
54
115
|
};
|
|
55
116
|
var main = () => {
|
|
117
|
+
const copyButton = byId("bb-copy-diagnostics");
|
|
118
|
+
let latestStatus = null;
|
|
119
|
+
const refreshStatus = async () => {
|
|
120
|
+
try {
|
|
121
|
+
const status = await getConnectionStatus();
|
|
122
|
+
latestStatus = status;
|
|
123
|
+
renderStatus(status);
|
|
124
|
+
setText("bb-conn-error", "");
|
|
125
|
+
} catch (error) {
|
|
126
|
+
const message = error instanceof Error ? error.message : "Failed to read connection status.";
|
|
127
|
+
latestStatus = null;
|
|
128
|
+
renderStatus({
|
|
129
|
+
state: "disconnected",
|
|
130
|
+
consecutive_failures: 0
|
|
131
|
+
});
|
|
132
|
+
setStateBadge("disconnected");
|
|
133
|
+
setText("bb-conn-error", message);
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
const interval = window.setInterval(() => {
|
|
137
|
+
void refreshStatus();
|
|
138
|
+
}, 1500);
|
|
139
|
+
window.addEventListener("unload", () => {
|
|
140
|
+
clearInterval(interval);
|
|
141
|
+
});
|
|
142
|
+
copyButton.addEventListener("click", () => {
|
|
143
|
+
void (async () => {
|
|
144
|
+
if (!latestStatus) {
|
|
145
|
+
setText("bb-copy-status", "Connection status unavailable.");
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const payload = {
|
|
149
|
+
generated_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
150
|
+
extension_version: chrome.runtime.getManifest().version,
|
|
151
|
+
connection: latestStatus,
|
|
152
|
+
user_agent: navigator.userAgent
|
|
153
|
+
};
|
|
154
|
+
try {
|
|
155
|
+
await copyToClipboard(JSON.stringify(payload, null, 2));
|
|
156
|
+
setText("bb-copy-status", "Copied diagnostics.");
|
|
157
|
+
} catch {
|
|
158
|
+
setText("bb-copy-status", "Copy failed.");
|
|
159
|
+
}
|
|
160
|
+
})();
|
|
161
|
+
});
|
|
56
162
|
byId("bb-settings").addEventListener("click", (e) => {
|
|
57
163
|
e.preventDefault();
|
|
58
164
|
void openOptionsPopupWindow().finally(() => window.close());
|
|
@@ -61,6 +167,7 @@
|
|
|
61
167
|
e.preventDefault();
|
|
62
168
|
void openGithub().finally(() => window.close());
|
|
63
169
|
});
|
|
170
|
+
void refreshStatus();
|
|
64
171
|
};
|
|
65
172
|
main();
|
|
66
173
|
})();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/popup-ui.ts"],
|
|
4
|
-
"sourcesContent": ["
|
|
5
|
-
"mappings": ";;;
|
|
4
|
+
"sourcesContent": ["type DriveConnectionState =\n | 'connecting'\n | 'connected'\n | 'disconnected'\n | 'backoff';\n\ntype DriveConnectionStatus = {\n state: DriveConnectionState;\n endpoint?: {\n host: string;\n port: number;\n portSource: 'default' | 'storage';\n };\n ws_url?: string;\n reconnect_delay_ms?: number;\n retry_at?: string;\n last_connected_at?: string;\n last_disconnected_at?: string;\n last_error_at?: string;\n last_error_message?: string;\n consecutive_failures: number;\n};\n\ntype DriveConnectionStatusResponse = {\n ok: boolean;\n result?: DriveConnectionStatus;\n};\n\nconst byId = <T extends HTMLElement>(id: string): T => {\n const el = document.getElementById(id);\n if (!el) {\n throw new Error(`Missing element: ${id}`);\n }\n return el as T;\n};\n\nconst formatTime = (iso?: string): string => {\n if (!iso) {\n return 'Never';\n }\n const parsed = new Date(iso);\n if (Number.isNaN(parsed.getTime())) {\n return iso;\n }\n return parsed.toLocaleString();\n};\n\nconst setText = (id: string, value: string): void => {\n byId<HTMLElement>(id).textContent = value;\n};\n\nconst setStateBadge = (state: DriveConnectionState): void => {\n const badge = byId<HTMLElement>('bb-conn-state');\n badge.textContent = state;\n badge.setAttribute('data-state', state);\n};\n\nconst getConnectionStatus = async (): Promise<DriveConnectionStatus> => {\n const response = await new Promise<DriveConnectionStatusResponse>(\n (resolve) => {\n chrome.runtime.sendMessage(\n { action: 'drive.connection_status' },\n (message: DriveConnectionStatusResponse) => {\n resolve(message);\n }\n );\n }\n );\n\n if (!response?.ok || !response.result) {\n throw new Error('Connection status is unavailable.');\n }\n\n return response.result;\n};\n\nconst copyToClipboard = async (text: string): Promise<void> => {\n if (navigator.clipboard?.writeText) {\n await navigator.clipboard.writeText(text);\n return;\n }\n\n const area = document.createElement('textarea');\n area.value = text;\n area.setAttribute('readonly', 'true');\n area.style.position = 'fixed';\n area.style.left = '-9999px';\n document.body.appendChild(area);\n area.select();\n document.execCommand('copy');\n document.body.removeChild(area);\n};\n\nconst renderStatus = (status: DriveConnectionStatus): void => {\n setStateBadge(status.state);\n setText(\n 'bb-conn-endpoint',\n status.ws_url ??\n (status.endpoint\n ? `ws://${status.endpoint.host}:${status.endpoint.port}/drive`\n : 'Unknown')\n );\n\n const source = status.endpoint?.portSource ?? 'unknown';\n setText('bb-conn-source', source);\n\n const lastConnected = formatTime(status.last_connected_at);\n setText('bb-conn-last-ok', lastConnected);\n\n const lastFailure = status.last_error_message\n ? `${status.last_error_message} (${formatTime(status.last_error_at)})`\n : 'None';\n setText('bb-conn-last-fail', lastFailure);\n\n const nextRetry = status.retry_at ? formatTime(status.retry_at) : 'n/a';\n setText('bb-conn-next-retry', nextRetry);\n};\n\nconst openOptionsPopupWindow = async (): Promise<void> => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const chromeAny = chrome as any;\n const url = chromeAny.runtime.getURL('options.html');\n\n if (chromeAny.windows?.create) {\n await new Promise<void>((resolve) => {\n chromeAny.windows.create(\n {\n type: 'popup',\n url,\n focused: true,\n width: 900,\n height: 720,\n },\n () => resolve()\n );\n });\n return;\n }\n\n if (chromeAny.runtime?.openOptionsPage) {\n await chromeAny.runtime.openOptionsPage();\n return;\n }\n if (chromeAny.tabs?.create) {\n await new Promise<void>((resolve) => {\n chromeAny.tabs.create({ url }, () => resolve());\n });\n return;\n }\n\n window.open(url, '_blank', 'noopener');\n};\n\nconst openGithub = async (): Promise<void> => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const chromeAny = chrome as any;\n const url = 'https://github.com/btraut/browser-bridge';\n if (chromeAny.tabs?.create) {\n await new Promise<void>((resolve) => {\n chromeAny.tabs.create({ url }, () => resolve());\n });\n return;\n }\n window.open(url, '_blank', 'noopener');\n};\n\nconst main = (): void => {\n const copyButton = byId<HTMLButtonElement>('bb-copy-diagnostics');\n let latestStatus: DriveConnectionStatus | null = null;\n\n const refreshStatus = async (): Promise<void> => {\n try {\n const status = await getConnectionStatus();\n latestStatus = status;\n renderStatus(status);\n setText('bb-conn-error', '');\n } catch (error) {\n const message =\n error instanceof Error\n ? error.message\n : 'Failed to read connection status.';\n latestStatus = null;\n renderStatus({\n state: 'disconnected',\n consecutive_failures: 0,\n });\n setStateBadge('disconnected');\n setText('bb-conn-error', message);\n }\n };\n\n const interval = window.setInterval(() => {\n void refreshStatus();\n }, 1500);\n\n window.addEventListener('unload', () => {\n clearInterval(interval);\n });\n\n copyButton.addEventListener('click', () => {\n void (async () => {\n if (!latestStatus) {\n setText('bb-copy-status', 'Connection status unavailable.');\n return;\n }\n const payload = {\n generated_at: new Date().toISOString(),\n extension_version: chrome.runtime.getManifest().version,\n connection: latestStatus,\n user_agent: navigator.userAgent,\n };\n try {\n await copyToClipboard(JSON.stringify(payload, null, 2));\n setText('bb-copy-status', 'Copied diagnostics.');\n } catch {\n setText('bb-copy-status', 'Copy failed.');\n }\n })();\n });\n\n byId<HTMLAnchorElement>('bb-settings').addEventListener('click', (e) => {\n e.preventDefault();\n void openOptionsPopupWindow().finally(() => window.close());\n });\n\n byId<HTMLAnchorElement>('bb-about').addEventListener('click', (e) => {\n e.preventDefault();\n void openGithub().finally(() => window.close());\n });\n\n void refreshStatus();\n};\n\nmain();\n\nexport {};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/extension/manifest.json
CHANGED
package/package.json
CHANGED