@64mb/freelens-power 1.2.1 → 1.3.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/README.md +3 -1
- package/out/main/common/dashboard-picker.js +4 -4
- package/out/main/common/dashboard-picker.js.map +1 -1
- package/out/main/common/dashboard-readiness.js +17 -47
- package/out/main/common/dashboard-readiness.js.map +1 -1
- package/out/main/common/dashboard-selector.js +40 -6
- package/out/main/common/dashboard-selector.js.map +1 -1
- package/out/main/common/store/monitoring-preferences-store.js +5 -0
- package/out/main/common/store/monitoring-preferences-store.js.map +1 -1
- package/out/main/dashboard-picker.js +1 -4
- package/out/main/dashboard-picker.js.map +1 -1
- package/out/main/dashboard-preload.js +110 -0
- package/out/main/dashboard-preload.js.map +1 -0
- package/out/main/dashboard-views.js +207 -62
- package/out/main/dashboard-views.js.map +1 -1
- package/out/main/dock-icon.js +25 -10
- package/out/main/dock-icon.js.map +1 -1
- package/out/main/index.js +2 -0
- package/out/main/index.js.map +1 -1
- package/out/main/splash-accent.js +84 -0
- package/out/main/splash-accent.js.map +1 -0
- package/out/renderer/ai-diagnostic-handoff.js +52 -0
- package/out/renderer/ai-diagnostic-handoff.js.map +1 -0
- package/out/renderer/ai-extras.js +40 -4
- package/out/renderer/ai-extras.js.map +1 -1
- package/out/renderer/ai.js +48 -56
- package/out/renderer/ai.js.map +1 -1
- package/out/renderer/appearance.js +6 -2
- package/out/renderer/appearance.js.map +1 -1
- package/out/renderer/dashboard.js +26 -6
- package/out/renderer/dashboard.js.map +1 -1
- package/out/renderer/details/hpa-diagnostics-details.js +46 -0
- package/out/renderer/details/hpa-diagnostics-details.js.map +1 -0
- package/out/renderer/details/namespace-health-details.js +91 -0
- package/out/renderer/details/namespace-health-details.js.map +1 -0
- package/out/renderer/details/resource-health-details.js +131 -0
- package/out/renderer/details/resource-health-details.js.map +1 -0
- package/out/renderer/details/service-diagnostics-details.js +163 -0
- package/out/renderer/details/service-diagnostics-details.js.map +1 -0
- package/out/renderer/diagnostic-explain-button.js +16 -0
- package/out/renderer/diagnostic-explain-button.js.map +1 -0
- package/out/renderer/diagnostics-state.js +51 -0
- package/out/renderer/diagnostics-state.js.map +1 -0
- package/out/renderer/diagnostics.css.js +9 -0
- package/out/renderer/diagnostics.css.js.map +1 -1
- package/out/renderer/diagnostics.js +369 -73
- package/out/renderer/diagnostics.js.map +1 -1
- package/out/renderer/incident-copy-button.js +50 -0
- package/out/renderer/incident-copy-button.js.map +1 -0
- package/out/renderer/index.js +91 -19
- package/out/renderer/index.js.map +1 -1
- package/out/renderer/monitoring-history-collection.js +1 -1
- package/out/renderer/preferences/dashboard-preferences.js +16 -16
- package/out/renderer/preferences/dashboard-preferences.js.map +1 -1
- package/out/renderer/preferences/monitoring-preferences.js +10 -0
- package/out/renderer/preferences/monitoring-preferences.js.map +1 -1
- package/out/renderer/preferences/preferences.js +88 -0
- package/out/renderer/preferences/preferences.js.map +1 -1
- package/out/renderer/preferences/settings-modal.js.map +1 -1
- package/out/renderer/resource-relationships.css.js +7 -0
- package/out/renderer/resource-relationships.css.js.map +1 -0
- package/out/renderer/resource-relationships.js +556 -0
- package/out/renderer/resource-relationships.js.map +1 -0
- package/out/renderer/resource-search-distance.js +24 -0
- package/out/renderer/resource-search-distance.js.map +1 -0
- package/out/renderer/resource-search-fields.js +55 -0
- package/out/renderer/resource-search-fields.js.map +1 -0
- package/out/renderer/resource-search-model.js +193 -0
- package/out/renderer/resource-search-model.js.map +1 -0
- package/out/renderer/resource-search.js +365 -0
- package/out/renderer/resource-search.js.map +1 -0
- package/out/renderer/src/common/dashboard-picker.js.map +1 -1
- package/out/renderer/src/common/dashboard-selector.js.map +1 -1
- package/out/renderer/src/common/hpa-diagnostics.js +24 -0
- package/out/renderer/src/common/hpa-diagnostics.js.map +1 -0
- package/out/renderer/src/common/incident-summary.js +73 -0
- package/out/renderer/src/common/incident-summary.js.map +1 -0
- package/out/renderer/src/common/resource-health.js +92 -0
- package/out/renderer/src/common/resource-health.js.map +1 -0
- package/out/renderer/src/common/resource-relationships.js +155 -0
- package/out/renderer/src/common/resource-relationships.js.map +1 -0
- package/out/renderer/src/common/service-diagnostics.js +50 -0
- package/out/renderer/src/common/service-diagnostics.js.map +1 -0
- package/out/renderer/src/common/store/monitoring-preferences-store.js +5 -0
- package/out/renderer/src/common/store/monitoring-preferences-store.js.map +1 -1
- package/out/renderer/src/common/timeline-groups.js +36 -0
- package/out/renderer/src/common/timeline-groups.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,7 +11,9 @@ Power tools and personal dashboards for Freelens. Built for Freelens 1.x and tes
|
|
|
11
11
|
- **macOS Dock icon:** optionally follows your accent, with a separate toggle to restore the original
|
|
12
12
|
- **Power Dashboard:** reorderable XS/S/M/L/XL website cards in a responsive grid, cached pages, loading skeletons, interactive element selection, expansion, pinned floating windows, shared website sessions, per-card 10-second refresh including pinned windows, and optional background refresh
|
|
13
13
|
- **Monitoring:** optional CPU and memory trends, allocation rings, pinned tooltips, and node/pod charts using metrics-server and Kubernetes APIs
|
|
14
|
-
- **Resource diagnostics:** CPU/memory consumers grouped
|
|
14
|
+
- **Resource diagnostics:** CPU/memory consumers, grouped warning timelines, Pending evidence, Service/HPA checks, operational resource and namespace summaries, scoped AI handoff, and incident-summary copying
|
|
15
|
+
- **Resource relationships:** a focused Service graph connects Ingress, selected Pods, published endpoints, owners and node references, with resource links and an optional menu switch
|
|
16
|
+
- **Fast resource search:** double Shift opens an indexed cross-kind search over names, namespaces, labels and safe status fields, with name-part and typo matching, keyboard navigation, resource links and explicit AI attachment; inventory is bounded and excludes Secrets, ConfigMaps and custom resources
|
|
15
17
|
- **Local metric history:** opt-in SQLite storage, up to seven days within a 100 MiB budget, with aggregated ranges and explicit collection gaps
|
|
16
18
|
- **AI assistant:** native Codex or Claude CLI, per-cluster conversations, read-only API discovery and resource summaries, model/effort/speed selection, editable prompts, quick-start commands, Markdown, cancellable replies, context preview, optional terminal attachments, resource links, resizable pinned chat, and a switch to disable all AI features
|
|
17
19
|
- **Read-only UI:** hides common mutation actions without changing Kubernetes permissions
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
//#region src/common/dashboard-picker.ts
|
|
2
2
|
var DASHBOARD_PICK_ELEMENT = "freelens-power:dashboard:pick-element";
|
|
3
|
-
function dashboardPickerAdapter(
|
|
3
|
+
function dashboardPickerAdapter() {
|
|
4
4
|
return new Promise((resolve) => {
|
|
5
5
|
const overlay = document.createElement("div");
|
|
6
6
|
overlay.style.cssText = "all:initial!important;position:fixed!important;inset:0!important;z-index:2147483647!important;pointer-events:auto!important";
|
|
7
7
|
const shadow = overlay.attachShadow({ mode: "open" });
|
|
8
8
|
const outline = document.createElement("div");
|
|
9
|
-
outline.style.cssText =
|
|
9
|
+
outline.style.cssText = "position:fixed;box-sizing:border-box;border:2px solid #00e5ff;border-radius:6px;box-shadow:0 0 0 1px #111,inset 0 0 0 1px #111;background:rgba(0,229,255,0.08);pointer-events:none;display:none";
|
|
10
10
|
const toolbar = document.createElement("div");
|
|
11
11
|
toolbar.style.cssText = "position:fixed;bottom:20px;left:50%;transform:translateX(-50%);padding:12px 16px;background:#202124;color:#fff;border-radius:8px;font:13px system-ui;pointer-events:auto;display:flex;gap:16px;align-items:center";
|
|
12
12
|
const hint = document.createElement("span");
|
|
@@ -122,8 +122,8 @@ function dashboardPickerAdapter(accent) {
|
|
|
122
122
|
window.addEventListener("resize", draw, true);
|
|
123
123
|
});
|
|
124
124
|
}
|
|
125
|
-
function dashboardPickerScript(
|
|
126
|
-
return `(${dashboardPickerAdapter.toString()})(
|
|
125
|
+
function dashboardPickerScript() {
|
|
126
|
+
return `(${dashboardPickerAdapter.toString()})()`;
|
|
127
127
|
}
|
|
128
128
|
//#endregion
|
|
129
129
|
exports.DASHBOARD_PICK_ELEMENT = DASHBOARD_PICK_ELEMENT;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard-picker.js","names":[],"sources":["../../../src/common/dashboard-picker.ts"],"sourcesContent":["export const DASHBOARD_PICK_ELEMENT = \"freelens-power:dashboard:pick-element\";\nexport type DashboardPickerResult = { status: \"selected\"; selector: string } | { status: \"canceled\" | \"error\" };\n\n// this function runs only in an isolated website world with no extension bridge\nexport function dashboardPickerAdapter(
|
|
1
|
+
{"version":3,"file":"dashboard-picker.js","names":[],"sources":["../../../src/common/dashboard-picker.ts"],"sourcesContent":["export const DASHBOARD_PICK_ELEMENT = \"freelens-power:dashboard:pick-element\";\nexport type DashboardPickerResult = { status: \"selected\"; selector: string } | { status: \"canceled\" | \"error\" };\n\n// this function runs only in an isolated website world with no extension bridge\nexport function dashboardPickerAdapter(): Promise<string | null> {\n return new Promise((resolve) => {\n const overlay = document.createElement(\"div\");\n overlay.style.cssText =\n \"all:initial!important;position:fixed!important;inset:0!important;z-index:2147483647!important;pointer-events:auto!important\";\n const shadow = overlay.attachShadow({ mode: \"open\" });\n const outline = document.createElement(\"div\");\n outline.style.cssText =\n \"position:fixed;box-sizing:border-box;border:2px solid #00e5ff;border-radius:6px;box-shadow:0 0 0 1px #111,inset 0 0 0 1px #111;background:rgba(0,229,255,0.08);pointer-events:none;display:none\";\n const toolbar = document.createElement(\"div\");\n toolbar.style.cssText =\n \"position:fixed;bottom:20px;left:50%;transform:translateX(-50%);padding:12px 16px;background:#202124;color:#fff;border-radius:8px;font:13px system-ui;pointer-events:auto;display:flex;gap:16px;align-items:center\";\n const hint = document.createElement(\"span\");\n hint.textContent = \"Hover an element, then click to select · Esc to cancel\";\n const cancel = document.createElement(\"button\");\n cancel.textContent = \"Cancel\";\n cancel.style.cssText =\n \"font:inherit;color:inherit;background:transparent;border:1px solid #888;border-radius:4px;padding:4px 10px;cursor:pointer\";\n toolbar.append(hint, cancel);\n shadow.append(outline, toolbar);\n document.documentElement.append(overlay);\n let hovered: Element | undefined;\n const escape = (value: string) => CSS.escape(value);\n function selectorFor(target: Element): string | undefined {\n const matches = (selector: string) => {\n try {\n return (\n selector.length <= 512 &&\n document.querySelectorAll(selector).length === 1 &&\n document.querySelector(selector) === target\n );\n } catch {\n return false;\n }\n };\n if (target.id) {\n const id = `#${escape(target.id)}`;\n if (matches(id)) return id;\n }\n const path: string[] = [];\n let element: Element | null = target;\n for (let depth = 0; element && depth < 64; depth++, element = element.parentElement) {\n const tag = escape(element.localName);\n const siblings = element.parentElement ? Array.from(element.parentElement.children) : [element];\n path.unshift(`${tag}:nth-child(${siblings.indexOf(element) + 1})`);\n const selector = path.join(\" > \");\n if (selector.length > 512) return;\n if (matches(selector)) return selector;\n }\n return undefined;\n }\n function finish(value: string | null) {\n window.removeEventListener(\"pointermove\", move, true);\n window.removeEventListener(\"pointerdown\", block, true);\n window.removeEventListener(\"pointerup\", block, true);\n window.removeEventListener(\"click\", click, true);\n window.removeEventListener(\"auxclick\", block, true);\n window.removeEventListener(\"dblclick\", block, true);\n window.removeEventListener(\"keydown\", key, true);\n window.removeEventListener(\"pagehide\", cancelSelection, true);\n window.removeEventListener(\"scroll\", draw, true);\n window.removeEventListener(\"resize\", draw, true);\n overlay.remove();\n resolve(value);\n }\n function block(event: Event) {\n event.preventDefault();\n event.stopImmediatePropagation();\n }\n function hit(event: Event): Element | undefined {\n if (event.composedPath().includes(toolbar)) return;\n let target = event.composedPath().find((node) => node instanceof Element);\n if (event.composedPath().includes(overlay) && event instanceof MouseEvent) {\n overlay.style.setProperty(\"pointer-events\", \"none\", \"important\");\n target = document.elementFromPoint(event.clientX, event.clientY) ?? undefined;\n overlay.style.setProperty(\"pointer-events\", \"auto\", \"important\");\n }\n return target instanceof Element && target.getRootNode() === document ? target : undefined;\n }\n function draw() {\n if (!hovered?.isConnected) {\n outline.style.display = \"none\";\n return;\n }\n const rect = hovered.getBoundingClientRect();\n Object.assign(outline.style, {\n display: \"block\",\n left: `${rect.left}px`,\n top: `${rect.top}px`,\n width: `${rect.width}px`,\n height: `${rect.height}px`,\n });\n }\n function move(event: PointerEvent) {\n hovered = hit(event);\n draw();\n }\n function click(event: MouseEvent) {\n const isCancel = event.composedPath().includes(cancel);\n block(event);\n if (isCancel) {\n finish(null);\n return;\n }\n const target = hit(event);\n if (!target) return;\n const selector = selectorFor(target);\n if (selector) finish(selector);\n else hint.textContent = \"This element cannot be selected. Choose a containing element or cancel.\";\n }\n function key(event: KeyboardEvent) {\n if (event.key === \"Escape\") {\n block(event);\n finish(null);\n } else block(event);\n }\n function cancelSelection() {\n finish(null);\n }\n window.addEventListener(\"pointermove\", move, true);\n window.addEventListener(\"pointerdown\", block, true);\n window.addEventListener(\"pointerup\", block, true);\n window.addEventListener(\"click\", click, true);\n window.addEventListener(\"auxclick\", block, true);\n window.addEventListener(\"dblclick\", block, true);\n window.addEventListener(\"keydown\", key, true);\n window.addEventListener(\"pagehide\", cancelSelection, true);\n window.addEventListener(\"scroll\", draw, true);\n window.addEventListener(\"resize\", draw, true);\n });\n}\n\nexport function dashboardPickerScript(): string {\n return `(${dashboardPickerAdapter.toString()})()`;\n}\n"],"mappings":"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"}
|
|
@@ -2,24 +2,23 @@ const require_dashboard_selector = require("./dashboard-selector.js");
|
|
|
2
2
|
//#region src/common/dashboard-readiness.ts
|
|
3
3
|
function dashboardReadinessAdapter(selector) {
|
|
4
4
|
return new Promise((resolve) => {
|
|
5
|
-
let lastChange = Date.now();
|
|
6
|
-
let lastLayout = "";
|
|
7
|
-
let painting = false;
|
|
8
5
|
let finished = false;
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
let painting = false;
|
|
7
|
+
const target = () => {
|
|
8
|
+
const projection = globalThis.powerSelectorState;
|
|
9
|
+
if (projection) selector = projection.selector;
|
|
10
|
+
let element = document.body;
|
|
11
|
+
if (selector) {
|
|
12
|
+
if (projection?.selector !== selector || !projection.isApplied()) return null;
|
|
13
|
+
element = projection.target;
|
|
14
|
+
}
|
|
15
|
+
if (!element || document.readyState === "loading") return null;
|
|
16
|
+
const bounds = element.getBoundingClientRect();
|
|
17
|
+
return bounds.width > 0 && bounds.height > 0 ? element : null;
|
|
11
18
|
};
|
|
12
|
-
const observer = new MutationObserver(changed);
|
|
13
|
-
observer.observe(document.documentElement, {
|
|
14
|
-
subtree: true,
|
|
15
|
-
childList: true,
|
|
16
|
-
attributes: true,
|
|
17
|
-
characterData: true
|
|
18
|
-
});
|
|
19
19
|
const finish = () => {
|
|
20
20
|
if (finished) return;
|
|
21
21
|
finished = true;
|
|
22
|
-
observer.disconnect();
|
|
23
22
|
clearInterval(interval);
|
|
24
23
|
clearTimeout(deadline);
|
|
25
24
|
resolve();
|
|
@@ -35,45 +34,16 @@ function dashboardReadinessAdapter(selector) {
|
|
|
35
34
|
painted();
|
|
36
35
|
});
|
|
37
36
|
});
|
|
38
|
-
const ready = () => {
|
|
39
|
-
let target = document.body;
|
|
40
|
-
if (selector) try {
|
|
41
|
-
target = document.querySelector(selector);
|
|
42
|
-
} catch {
|
|
43
|
-
target = null;
|
|
44
|
-
}
|
|
45
|
-
if (!target || document.readyState !== "complete" || document.fonts?.status === "loading") return false;
|
|
46
|
-
const bounds = target.getBoundingClientRect();
|
|
47
|
-
if (bounds.width <= 0 || bounds.height <= 0) return false;
|
|
48
|
-
const layout = [
|
|
49
|
-
bounds.x,
|
|
50
|
-
bounds.y,
|
|
51
|
-
bounds.width,
|
|
52
|
-
bounds.height,
|
|
53
|
-
target.scrollWidth,
|
|
54
|
-
target.scrollHeight
|
|
55
|
-
].join(",");
|
|
56
|
-
if (layout !== lastLayout) {
|
|
57
|
-
lastLayout = layout;
|
|
58
|
-
changed();
|
|
59
|
-
}
|
|
60
|
-
const images = Array.from(target.querySelectorAll("img"));
|
|
61
|
-
if (target instanceof HTMLImageElement) images.unshift(target);
|
|
62
|
-
return !images.some((image) => {
|
|
63
|
-
const rect = image.getBoundingClientRect();
|
|
64
|
-
const style = getComputedStyle(image);
|
|
65
|
-
return !image.complete && rect.width > 0 && rect.height > 0 && rect.bottom > 0 && rect.right > 0 && rect.top < window.innerHeight && rect.left < window.innerWidth && style.display !== "none" && style.visibility !== "hidden";
|
|
66
|
-
}) && Date.now() - lastChange >= 350;
|
|
67
|
-
};
|
|
68
37
|
const check = () => {
|
|
69
|
-
|
|
38
|
+
const element = target();
|
|
39
|
+
if (finished || painting || !element) return;
|
|
70
40
|
painting = true;
|
|
71
|
-
frame().then(frame).then(() =>
|
|
41
|
+
frame().then(frame).then(() => {
|
|
72
42
|
painting = false;
|
|
73
|
-
if (!finished &&
|
|
43
|
+
if (!finished && target() === element) finish();
|
|
74
44
|
});
|
|
75
45
|
};
|
|
76
|
-
const interval = setInterval(check,
|
|
46
|
+
const interval = setInterval(check, 50);
|
|
77
47
|
const deadline = setTimeout(finish, 8e3);
|
|
78
48
|
check();
|
|
79
49
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard-readiness.js","names":[],"sources":["../../../src/common/dashboard-readiness.ts"],"sourcesContent":["import { normalizeDashboardSelector } from \"./dashboard-selector\";\n\n// this function runs
|
|
1
|
+
{"version":3,"file":"dashboard-readiness.js","names":[],"sources":["../../../src/common/dashboard-readiness.ts"],"sourcesContent":["import { normalizeDashboardSelector } from \"./dashboard-selector\";\n\n// this function runs inside the website document\nexport function dashboardReadinessAdapter(selector: string): Promise<void> {\n return new Promise((resolve) => {\n let finished = false;\n let painting = false;\n const target = () => {\n const projection = (\n globalThis as typeof globalThis & {\n powerSelectorState?: { selector: string; target: Element | null; isApplied: () => boolean };\n }\n ).powerSelectorState;\n if (projection) selector = projection.selector;\n let element: Element | null = document.body;\n if (selector) {\n if (projection?.selector !== selector || !projection.isApplied()) return null;\n element = projection.target;\n }\n if (!element || document.readyState === \"loading\") return null;\n const bounds = element.getBoundingClientRect();\n return bounds.width > 0 && bounds.height > 0 ? element : null;\n };\n const finish = () => {\n if (finished) return;\n finished = true;\n clearInterval(interval);\n clearTimeout(deadline);\n resolve();\n };\n const frame = () =>\n new Promise<void>((painted) => {\n let id = 0;\n const timer = setTimeout(() => {\n cancelAnimationFrame(id);\n painted();\n }, 100);\n id = requestAnimationFrame(() => {\n clearTimeout(timer);\n painted();\n });\n });\n const check = () => {\n const element = target();\n if (finished || painting || !element) return;\n painting = true;\n void frame()\n .then(frame)\n .then(() => {\n painting = false;\n if (!finished && target() === element) finish();\n });\n };\n const interval = setInterval(check, 50);\n const deadline = setTimeout(finish, 8000);\n check();\n });\n}\n\nexport function dashboardReadinessScript(selector?: string): string {\n return `(${dashboardReadinessAdapter.toString()})(${JSON.stringify(normalizeDashboardSelector(selector) ?? \"\")})`;\n}\n"],"mappings":";;AAGA,SAAgB,0BAA0B,UAAiC;CACzE,OAAO,IAAI,SAAS,YAAY;EAC9B,IAAI,WAAW;EACf,IAAI,WAAW;EACf,MAAM,eAAe;GACnB,MAAM,aACJ,WAGA;GACF,IAAI,YAAY,WAAW,WAAW;GACtC,IAAI,UAA0B,SAAS;GACvC,IAAI,UAAU;IACZ,IAAI,YAAY,aAAa,YAAY,CAAC,WAAW,UAAU,GAAG,OAAO;IACzE,UAAU,WAAW;GACvB;GACA,IAAI,CAAC,WAAW,SAAS,eAAe,WAAW,OAAO;GAC1D,MAAM,SAAS,QAAQ,sBAAsB;GAC7C,OAAO,OAAO,QAAQ,KAAK,OAAO,SAAS,IAAI,UAAU;EAC3D;EACA,MAAM,eAAe;GACnB,IAAI,UAAU;GACd,WAAW;GACX,cAAc,QAAQ;GACtB,aAAa,QAAQ;GACrB,QAAQ;EACV;EACA,MAAM,cACJ,IAAI,SAAe,YAAY;GAC7B,IAAI,KAAK;GACT,MAAM,QAAQ,iBAAiB;IAC7B,qBAAqB,EAAE;IACvB,QAAQ;GACV,GAAG,GAAG;GACN,KAAK,4BAA4B;IAC/B,aAAa,KAAK;IAClB,QAAQ;GACV,CAAC;EACH,CAAC;EACH,MAAM,cAAc;GAClB,MAAM,UAAU,OAAO;GACvB,IAAI,YAAY,YAAY,CAAC,SAAS;GACtC,WAAW;GACX,MAAW,CAAC,CACT,KAAK,KAAK,CAAC,CACX,WAAW;IACV,WAAW;IACX,IAAI,CAAC,YAAY,OAAO,MAAM,SAAS,OAAO;GAChD,CAAC;EACL;EACA,MAAM,WAAW,YAAY,OAAO,EAAE;EACtC,MAAM,WAAW,WAAW,QAAQ,GAAI;EACxC,MAAM;CACR,CAAC;AACH;AAEA,SAAgB,yBAAyB,UAA2B;CAClE,OAAO,IAAI,0BAA0B,SAAS,EAAE,IAAI,KAAK,UAAU,2BAAA,2BAA2B,QAAQ,KAAK,EAAE,EAAE;AACjH"}
|
|
@@ -6,20 +6,30 @@ function normalizeDashboardSelector(value) {
|
|
|
6
6
|
function dashboardSelectorAdapter(selector) {
|
|
7
7
|
const state = globalThis;
|
|
8
8
|
state.powerSelectorCleanup?.();
|
|
9
|
-
if (!selector)
|
|
9
|
+
if (!selector) {
|
|
10
|
+
state.powerSelectorState = {
|
|
11
|
+
selector,
|
|
12
|
+
target: null,
|
|
13
|
+
isApplied: () => true
|
|
14
|
+
};
|
|
15
|
+
state.powerSelectorCleanup = () => {
|
|
16
|
+
delete state.powerSelectorState;
|
|
17
|
+
delete state.powerSelectorCleanup;
|
|
18
|
+
};
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
10
21
|
const hidden = "data-power-selector-hidden";
|
|
11
22
|
const path = "data-power-selector-path";
|
|
12
23
|
const inset = "data-power-selector-inset";
|
|
13
24
|
let insetRoot;
|
|
14
25
|
let marked = [];
|
|
15
|
-
let timer;
|
|
16
26
|
const style = document.createElement("style");
|
|
17
27
|
style.textContent = `[${hidden}] { display: none !important; } [${path}] { display: block !important; position: static !important; width: auto !important; height: auto !important; min-height: 0 !important; max-height: none !important; overflow: visible !important; margin: 0 !important; padding: 0 !important; transform: none !important; } body[${inset}] { padding: 12px !important; box-sizing: border-box !important; }`;
|
|
18
28
|
const notice = document.createElement("div");
|
|
19
29
|
notice.textContent = "Selected element unavailable. Showing the whole page. Clear CSS selector in card settings to reset.";
|
|
20
30
|
notice.style.cssText = "position:fixed;top:0;left:0;right:0;z-index:2147483647;padding:8px;background:#292929;color:white;font:12px sans-serif";
|
|
21
31
|
const observer = new MutationObserver(() => {
|
|
22
|
-
if (!
|
|
32
|
+
if (!projection.isApplied()) update();
|
|
23
33
|
});
|
|
24
34
|
function restore() {
|
|
25
35
|
for (const element of marked) {
|
|
@@ -32,8 +42,31 @@ function dashboardSelectorAdapter(selector) {
|
|
|
32
42
|
style.remove();
|
|
33
43
|
notice.remove();
|
|
34
44
|
}
|
|
45
|
+
const projection = {
|
|
46
|
+
selector,
|
|
47
|
+
target: null,
|
|
48
|
+
isApplied: () => {
|
|
49
|
+
const target = projection.target;
|
|
50
|
+
if (!target || !style.isConnected) return false;
|
|
51
|
+
try {
|
|
52
|
+
if (document.querySelector(selector) !== target) return false;
|
|
53
|
+
} catch {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
if (target === document.documentElement || target === document.body) return document.body?.hasAttribute(inset) ?? false;
|
|
57
|
+
let child = target;
|
|
58
|
+
let depth = 0;
|
|
59
|
+
while (child.parentElement) {
|
|
60
|
+
const parent = child.parentElement;
|
|
61
|
+
if (!parent.hasAttribute(path) || ++depth >= 128) return false;
|
|
62
|
+
for (const sibling of parent.children) if (sibling !== child && sibling !== style && sibling.localName !== "freelens-power-loading" && !sibling.hasAttribute(hidden)) return false;
|
|
63
|
+
child = parent;
|
|
64
|
+
}
|
|
65
|
+
return document.body?.hasAttribute(inset) ?? false;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
state.powerSelectorState = projection;
|
|
35
69
|
function update() {
|
|
36
|
-
timer = void 0;
|
|
37
70
|
observer.disconnect();
|
|
38
71
|
restore();
|
|
39
72
|
let target = null;
|
|
@@ -48,7 +81,7 @@ function dashboardSelectorAdapter(selector) {
|
|
|
48
81
|
const parent = child.parentElement;
|
|
49
82
|
ancestors.push(parent);
|
|
50
83
|
for (const sibling of parent.children) {
|
|
51
|
-
if (sibling !== child) branches.push(sibling);
|
|
84
|
+
if (sibling !== child && sibling.localName !== "freelens-power-loading") branches.push(sibling);
|
|
52
85
|
if (branches.length >= 2e3) break;
|
|
53
86
|
}
|
|
54
87
|
child = parent;
|
|
@@ -65,6 +98,7 @@ function dashboardSelectorAdapter(selector) {
|
|
|
65
98
|
}
|
|
66
99
|
document.documentElement.append(style);
|
|
67
100
|
} else document.documentElement.append(notice);
|
|
101
|
+
projection.target = target;
|
|
68
102
|
observer.observe(document.documentElement, {
|
|
69
103
|
subtree: true,
|
|
70
104
|
childList: true,
|
|
@@ -73,9 +107,9 @@ function dashboardSelectorAdapter(selector) {
|
|
|
73
107
|
}
|
|
74
108
|
state.powerSelectorCleanup = () => {
|
|
75
109
|
observer.disconnect();
|
|
76
|
-
clearTimeout(timer);
|
|
77
110
|
restore();
|
|
78
111
|
delete state.powerSelectorCleanup;
|
|
112
|
+
delete state.powerSelectorState;
|
|
79
113
|
};
|
|
80
114
|
update();
|
|
81
115
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard-selector.js","names":[],"sources":["../../../src/common/dashboard-selector.ts"],"sourcesContent":["export const dashboardSelectorLimit = 512;\n\nexport function normalizeDashboardSelector(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const selector = value.trim();\n return selector && selector.length <= dashboardSelectorLimit && !/[\\u0000-\\u001f\\u007f]/.test(selector)\n ? selector\n : undefined;\n}\n\n// this function runs
|
|
1
|
+
{"version":3,"file":"dashboard-selector.js","names":[],"sources":["../../../src/common/dashboard-selector.ts"],"sourcesContent":["export const dashboardSelectorLimit = 512;\n\nexport function normalizeDashboardSelector(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const selector = value.trim();\n return selector && selector.length <= dashboardSelectorLimit && !/[\\u0000-\\u001f\\u007f]/.test(selector)\n ? selector\n : undefined;\n}\n\n// this function runs inside the website document\nexport function dashboardSelectorAdapter(selector: string): void {\n const state = globalThis as typeof globalThis & {\n powerSelectorCleanup?: () => void;\n powerSelectorState?: { selector: string; target: Element | null; isApplied: () => boolean };\n };\n state.powerSelectorCleanup?.();\n if (!selector) {\n state.powerSelectorState = { selector, target: null, isApplied: () => true };\n state.powerSelectorCleanup = () => {\n delete state.powerSelectorState;\n delete state.powerSelectorCleanup;\n };\n return;\n }\n const hidden = \"data-power-selector-hidden\";\n const path = \"data-power-selector-path\";\n const inset = \"data-power-selector-inset\";\n let insetRoot: HTMLElement | undefined;\n let marked: Element[] = [];\n const style = document.createElement(\"style\");\n style.textContent = `[${hidden}] { display: none !important; } [${path}] { display: block !important; position: static !important; width: auto !important; height: auto !important; min-height: 0 !important; max-height: none !important; overflow: visible !important; margin: 0 !important; padding: 0 !important; transform: none !important; } body[${inset}] { padding: 12px !important; box-sizing: border-box !important; }`;\n const notice = document.createElement(\"div\");\n notice.textContent =\n \"Selected element unavailable. Showing the whole page. Clear CSS selector in card settings to reset.\";\n notice.style.cssText =\n \"position:fixed;top:0;left:0;right:0;z-index:2147483647;padding:8px;background:#292929;color:white;font:12px sans-serif\";\n const observer = new MutationObserver(() => {\n if (!projection.isApplied()) update();\n });\n function restore() {\n for (const element of marked) {\n element.removeAttribute(hidden);\n element.removeAttribute(path);\n }\n marked = [];\n insetRoot?.removeAttribute(inset);\n insetRoot = undefined;\n style.remove();\n notice.remove();\n }\n const projection = {\n selector,\n target: null as Element | null,\n isApplied: () => {\n const target = projection.target;\n if (!target || !style.isConnected) return false;\n try {\n if (document.querySelector(selector) !== target) return false;\n } catch {\n return false;\n }\n if (target === document.documentElement || target === document.body)\n return document.body?.hasAttribute(inset) ?? false;\n let child = target;\n let depth = 0;\n while (child.parentElement) {\n const parent = child.parentElement;\n if (!parent.hasAttribute(path) || ++depth >= 128) return false;\n for (const sibling of parent.children) {\n if (\n sibling !== child &&\n sibling !== style &&\n sibling.localName !== \"freelens-power-loading\" &&\n !sibling.hasAttribute(hidden)\n )\n return false;\n }\n child = parent;\n }\n return document.body?.hasAttribute(inset) ?? false;\n },\n };\n state.powerSelectorState = projection;\n function update() {\n observer.disconnect();\n restore();\n let target: Element | null = null;\n try {\n target = document.querySelector(selector);\n } catch {}\n const branches: Element[] = [];\n const ancestors: Element[] = [];\n if (target && target !== document.documentElement && target !== document.body) {\n let child: Element = target;\n while (child.parentElement && ancestors.length < 128 && branches.length < 2000) {\n const parent = child.parentElement;\n ancestors.push(parent);\n for (const sibling of parent.children) {\n if (sibling !== child && sibling.localName !== \"freelens-power-loading\") branches.push(sibling);\n if (branches.length >= 2000) break;\n }\n child = parent;\n }\n if (ancestors.length >= 128 || branches.length >= 2000) target = null;\n }\n if (target) {\n for (const element of branches) element.setAttribute(hidden, \"\");\n for (const element of ancestors) element.setAttribute(path, \"\");\n marked = [...branches, ...ancestors];\n if (document.body) {\n insetRoot = document.body;\n insetRoot.setAttribute(inset, \"\");\n }\n document.documentElement.append(style);\n } else {\n document.documentElement.append(notice);\n }\n projection.target = target;\n observer.observe(document.documentElement, { subtree: true, childList: true, attributes: true });\n }\n state.powerSelectorCleanup = () => {\n observer.disconnect();\n restore();\n delete state.powerSelectorCleanup;\n delete state.powerSelectorState;\n };\n update();\n}\n\nexport function dashboardSelectorScript(selector?: string): string {\n return `(${dashboardSelectorAdapter.toString()})(${JSON.stringify(normalizeDashboardSelector(selector) ?? \"\")})`;\n}\n"],"mappings":"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"}
|
|
@@ -5,6 +5,7 @@ const require_monitoring_history = require("../monitoring-history.js");
|
|
|
5
5
|
var MonitoringPreferencesStore = class extends require_extensions.Common.Store.ExtensionStore {
|
|
6
6
|
enabled = false;
|
|
7
7
|
diagnosticsVisible = true;
|
|
8
|
+
relationshipsVisible = true;
|
|
8
9
|
historyEnabled = false;
|
|
9
10
|
trackedHistory = [];
|
|
10
11
|
constructor() {
|
|
@@ -13,6 +14,7 @@ var MonitoringPreferencesStore = class extends require_extensions.Common.Store.E
|
|
|
13
14
|
defaults: {
|
|
14
15
|
enabled: false,
|
|
15
16
|
diagnosticsVisible: true,
|
|
17
|
+
relationshipsVisible: true,
|
|
16
18
|
historyEnabled: false,
|
|
17
19
|
trackedHistory: []
|
|
18
20
|
}
|
|
@@ -20,6 +22,7 @@ var MonitoringPreferencesStore = class extends require_extensions.Common.Store.E
|
|
|
20
22
|
require__global_external_mobx.makeObservable(this, {
|
|
21
23
|
enabled: require__global_external_mobx.observable,
|
|
22
24
|
diagnosticsVisible: require__global_external_mobx.observable,
|
|
25
|
+
relationshipsVisible: require__global_external_mobx.observable,
|
|
23
26
|
historyEnabled: require__global_external_mobx.observable,
|
|
24
27
|
trackedHistory: require__global_external_mobx.observable,
|
|
25
28
|
fromStore: require__global_external_mobx.action
|
|
@@ -28,6 +31,7 @@ var MonitoringPreferencesStore = class extends require_extensions.Common.Store.E
|
|
|
28
31
|
fromStore(data) {
|
|
29
32
|
this.enabled = data?.enabled === true;
|
|
30
33
|
this.diagnosticsVisible = data?.diagnosticsVisible !== false;
|
|
34
|
+
this.relationshipsVisible = data?.relationshipsVisible !== false;
|
|
31
35
|
this.historyEnabled = data?.historyEnabled === true;
|
|
32
36
|
this.trackedHistory = Array.isArray(data?.trackedHistory) ? data.trackedHistory.filter(require_monitoring_history.validHistoryIdentity).slice(0, 100).map(({ clusterId, scope, uid }) => ({
|
|
33
37
|
clusterId,
|
|
@@ -39,6 +43,7 @@ var MonitoringPreferencesStore = class extends require_extensions.Common.Store.E
|
|
|
39
43
|
return {
|
|
40
44
|
enabled: this.enabled,
|
|
41
45
|
diagnosticsVisible: this.diagnosticsVisible,
|
|
46
|
+
relationshipsVisible: this.relationshipsVisible,
|
|
42
47
|
historyEnabled: this.historyEnabled,
|
|
43
48
|
trackedHistory: this.trackedHistory.map(({ clusterId, scope, uid }) => ({
|
|
44
49
|
clusterId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"monitoring-preferences-store.js","names":[],"sources":["../../../../src/common/store/monitoring-preferences-store.ts"],"sourcesContent":["import { Common } from \"@freelensapp/extensions\";\nimport { action, makeObservable, observable } from \"mobx\";\nimport { type HistoryIdentity, validHistoryIdentity } from \"../monitoring-history\";\n\nexport class MonitoringPreferencesStore extends Common.Store.ExtensionStore<{\n enabled: boolean;\n diagnosticsVisible: boolean;\n historyEnabled: boolean;\n trackedHistory: HistoryIdentity[];\n}> {\n enabled = false;\n diagnosticsVisible = true;\n historyEnabled = false;\n trackedHistory: HistoryIdentity[] = [];\n\n constructor() {\n super({\n configName: \"monitoring-preferences\",\n defaults: {
|
|
1
|
+
{"version":3,"file":"monitoring-preferences-store.js","names":[],"sources":["../../../../src/common/store/monitoring-preferences-store.ts"],"sourcesContent":["import { Common } from \"@freelensapp/extensions\";\nimport { action, makeObservable, observable } from \"mobx\";\nimport { type HistoryIdentity, validHistoryIdentity } from \"../monitoring-history\";\n\nexport class MonitoringPreferencesStore extends Common.Store.ExtensionStore<{\n enabled: boolean;\n diagnosticsVisible: boolean;\n relationshipsVisible: boolean;\n historyEnabled: boolean;\n trackedHistory: HistoryIdentity[];\n}> {\n enabled = false;\n diagnosticsVisible = true;\n relationshipsVisible = true;\n historyEnabled = false;\n trackedHistory: HistoryIdentity[] = [];\n\n constructor() {\n super({\n configName: \"monitoring-preferences\",\n defaults: {\n enabled: false,\n diagnosticsVisible: true,\n relationshipsVisible: true,\n historyEnabled: false,\n trackedHistory: [],\n },\n });\n makeObservable(this, {\n enabled: observable,\n diagnosticsVisible: observable,\n relationshipsVisible: observable,\n historyEnabled: observable,\n trackedHistory: observable,\n fromStore: action,\n });\n }\n\n fromStore(data: {\n enabled?: boolean;\n diagnosticsVisible?: boolean;\n relationshipsVisible?: boolean;\n historyEnabled?: boolean;\n trackedHistory?: HistoryIdentity[];\n }): void {\n this.enabled = data?.enabled === true;\n this.diagnosticsVisible = data?.diagnosticsVisible !== false;\n this.relationshipsVisible = data?.relationshipsVisible !== false;\n this.historyEnabled = data?.historyEnabled === true;\n this.trackedHistory = Array.isArray(data?.trackedHistory)\n ? data.trackedHistory\n .filter(validHistoryIdentity)\n .slice(0, 100)\n .map(({ clusterId, scope, uid }) => ({ clusterId, scope, uid }))\n : [];\n }\n\n toJSON(): {\n enabled: boolean;\n diagnosticsVisible: boolean;\n relationshipsVisible: boolean;\n historyEnabled: boolean;\n trackedHistory: HistoryIdentity[];\n } {\n return {\n enabled: this.enabled,\n diagnosticsVisible: this.diagnosticsVisible,\n relationshipsVisible: this.relationshipsVisible,\n historyEnabled: this.historyEnabled,\n trackedHistory: this.trackedHistory.map(({ clusterId, scope, uid }) => ({ clusterId, scope, uid })),\n };\n }\n}\n"],"mappings":";;;;AAIA,IAAa,6BAAb,cAAgD,mBAAA,OAAO,MAAM,eAM1D;CACD,UAAU;CACV,qBAAqB;CACrB,uBAAuB;CACvB,iBAAiB;CACjB,iBAAoC,CAAC;CAErC,cAAc;EACZ,MAAM;GACJ,YAAY;GACZ,UAAU;IACR,SAAS;IACT,oBAAoB;IACpB,sBAAsB;IACtB,gBAAgB;IAChB,gBAAgB,CAAC;GACnB;EACF,CAAC;EACD,8BAAA,eAAe,MAAM;GACnB,SAAS,8BAAA;GACT,oBAAoB,8BAAA;GACpB,sBAAsB,8BAAA;GACtB,gBAAgB,8BAAA;GAChB,gBAAgB,8BAAA;GAChB,WAAW,8BAAA;EACb,CAAC;CACH;CAEA,UAAU,MAMD;EACP,KAAK,UAAU,MAAM,YAAY;EACjC,KAAK,qBAAqB,MAAM,uBAAuB;EACvD,KAAK,uBAAuB,MAAM,yBAAyB;EAC3D,KAAK,iBAAiB,MAAM,mBAAmB;EAC/C,KAAK,iBAAiB,MAAM,QAAQ,MAAM,cAAc,IACpD,KAAK,eACF,OAAO,2BAAA,oBAAoB,CAAC,CAC5B,MAAM,GAAG,GAAG,CAAC,CACb,KAAK,EAAE,WAAW,OAAO,WAAW;GAAE;GAAW;GAAO;EAAI,EAAE,IACjE,CAAC;CACP;CAEA,SAME;EACA,OAAO;GACL,SAAS,KAAK;GACd,oBAAoB,KAAK;GACzB,sBAAsB,KAAK;GAC3B,gBAAgB,KAAK;GACrB,gBAAgB,KAAK,eAAe,KAAK,EAAE,WAAW,OAAO,WAAW;IAAE;IAAW;IAAO;GAAI,EAAE;EACpG;CACF;AACF"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
const require_appearance_preferences_store = require("./common/store/appearance-preferences-store.js");
|
|
2
1
|
const require_dashboard_selector = require("./common/dashboard-selector.js");
|
|
3
2
|
const require_dashboard = require("./common/dashboard.js");
|
|
4
3
|
const require_dashboard_picker = require("./common/dashboard-picker.js");
|
|
@@ -98,9 +97,7 @@ function startDashboardPicker() {
|
|
|
98
97
|
cancel();
|
|
99
98
|
return;
|
|
100
99
|
}
|
|
101
|
-
|
|
102
|
-
const accent = preferences.enabled ? require_appearance_preferences_store.ACCENT_COLOR_OPTIONS.find((option) => option.value === preferences.accentColor)?.color : void 0;
|
|
103
|
-
picker.webContents.executeJavaScriptInIsolatedWorld(1007, [{ code: `globalThis.powerDashboardPickerSelection = ${require_dashboard_picker.dashboardPickerScript(accent ?? "#00a7a0")}; true` }]).then((installed) => {
|
|
100
|
+
picker.webContents.executeJavaScriptInIsolatedWorld(1007, [{ code: `globalThis.powerDashboardPickerSelection = ${require_dashboard_picker.dashboardPickerScript()}; true` }]).then((installed) => {
|
|
104
101
|
if (done) return null;
|
|
105
102
|
if (installed !== true) throw new Error("Picker could not start");
|
|
106
103
|
picker.contentView.setVisible(true);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard-picker.js","names":[],"sources":["../../src/main/dashboard-picker.ts"],"sourcesContent":["import { BrowserWindow, type IpcMainInvokeEvent, ipcMain, session } from \"electron\";\nimport { normalizeDashboardUrl } from \"../common/dashboard\";\nimport { DASHBOARD_PICK_ELEMENT, type DashboardPickerResult, dashboardPickerScript } from \"../common/dashboard-picker\";\nimport { normalizeDashboardSelector } from \"../common/dashboard-selector\";\nimport { ACCENT_COLOR_OPTIONS, AppearancePreferencesStore } from \"../common/store/appearance-preferences-store\";\n\nexport function trustedPickerSender(event: IpcMainInvokeEvent): boolean {\n const trusted = (value: string) => {\n try {\n const url = new URL(value);\n return (\n url.protocol === \"https:\" &&\n (url.hostname === \"renderer.freelens.app\" || url.hostname.endsWith(\".renderer.freelens.app\")) &&\n (url.pathname === \"/preferences\" || url.pathname.startsWith(\"/preferences/\"))\n );\n } catch {\n return false;\n }\n };\n return (\n event.senderFrame === event.sender.mainFrame &&\n trusted(event.senderFrame?.url ?? \"\") &&\n trusted(event.sender.getURL())\n );\n}\n\nexport function startDashboardPicker(): () => void {\n const active = new Map<BrowserWindow, () => void>();\n const pending = new WeakSet<object>();\n let running = true;\n ipcMain.handle(DASHBOARD_PICK_ELEMENT, async (event, payload: unknown): Promise<DashboardPickerResult> => {\n if (!running || !trustedPickerSender(event) || pending.has(event.sender) || !payload || typeof payload !== \"object\")\n return { status: \"error\" };\n const rawUrl = (payload as { url?: unknown }).url;\n const url = typeof rawUrl === \"string\" && rawUrl.length <= 8192 ? normalizeDashboardUrl(rawUrl) : undefined;\n const owner = BrowserWindow.fromWebContents(event.sender);\n if (!url || !owner || owner.isDestroyed()) return { status: \"error\" };\n pending.add(event.sender);\n try {\n const websiteSession = session.fromPartition(\"persist:freelens-power-websites\");\n websiteSession.setPermissionRequestHandler((_contents, _permission, callback) => callback(false));\n websiteSession.setPermissionCheckHandler(() => false);\n const picker = new BrowserWindow({\n parent: owner,\n modal: true,\n width: 1100,\n height: 800,\n show: false,\n title: \"Select website element · Click to select · Esc to cancel\",\n autoHideMenuBar: true,\n webPreferences: {\n nodeIntegration: false,\n contextIsolation: true,\n sandbox: true,\n webSecurity: true,\n partition: \"persist:freelens-power-websites\",\n },\n });\n picker.setMenu(null);\n picker.contentView.setVisible(false);\n return await new Promise<DashboardPickerResult>((resolve) => {\n let done = false;\n let loaded = false;\n const finish = (result: DashboardPickerResult) => {\n if (done) return;\n done = true;\n clearTimeout(timer);\n active.delete(picker);\n event.sender.removeListener(\"destroyed\", cancel);\n event.sender.removeListener(\"did-start-navigation\", cancel);\n if (!picker.isDestroyed()) picker.destroy();\n resolve(result);\n };\n const cancel = () => finish({ status: \"canceled\" });\n const timer = setTimeout(cancel, 5 * 60_000);\n active.set(picker, cancel);\n event.sender.once(\"destroyed\", cancel);\n event.sender.on(\"did-start-navigation\", cancel);\n picker.once(\"closed\", cancel);\n picker.webContents.setWindowOpenHandler(() => ({ action: \"deny\" }));\n picker.webContents.on(\"will-navigate\", (navigation, target) => {\n if (loaded || !normalizeDashboardUrl(target)) {\n navigation.preventDefault();\n cancel();\n }\n });\n picker.webContents.on(\"did-start-navigation\", (_navigation, _target, _inPlace, mainFrame) => {\n if (loaded && mainFrame) cancel();\n });\n picker.webContents.on(\"will-redirect\", (navigation, target) => {\n if (!normalizeDashboardUrl(target)) {\n navigation.preventDefault();\n cancel();\n }\n });\n picker.webContents.on(\"will-attach-webview\", (attach) => attach.preventDefault());\n picker.webContents.on(\"before-input-event\", (inputEvent, input) => {\n if (input.key === \"Escape\") {\n inputEvent.preventDefault();\n cancel();\n }\n });\n picker.webContents.once(\"render-process-gone\", () => finish({ status: \"error\" }));\n picker.webContents.once(\"did-finish-load\", () => {\n if (done) return;\n loaded = true;\n if (!normalizeDashboardUrl(picker.webContents.getURL())) {\n cancel();\n return;\n }\n const preferences = AppearancePreferencesStore.getInstanceOrCreate<AppearancePreferencesStore>();\n const accent = preferences.enabled\n ? ACCENT_COLOR_OPTIONS.find((option) => option.value === preferences.accentColor)?.color\n : undefined;\n void picker.webContents\n .executeJavaScriptInIsolatedWorld(1007, [\n {\n code: `globalThis.powerDashboardPickerSelection = ${dashboardPickerScript(accent ?? \"#00a7a0\")}; true`,\n },\n ])\n .then((installed: unknown) => {\n if (done) return null;\n if (installed !== true) throw new Error(\"Picker could not start\");\n picker.contentView.setVisible(true);\n return picker.webContents.executeJavaScriptInIsolatedWorld(1007, [\n {\n code: \"globalThis.powerDashboardPickerSelection.then((selection) => { delete globalThis.powerDashboardPickerSelection; return selection; })\",\n },\n ]);\n })\n .then((result: unknown) => {\n if (done) return;\n const selector = normalizeDashboardSelector(result);\n finish(selector ? { status: \"selected\", selector } : { status: \"canceled\" });\n })\n .catch(() => finish({ status: \"error\" }));\n });\n picker.show();\n void picker.loadURL(url).catch(() => finish({ status: \"error\" }));\n });\n } catch {\n return { status: \"error\" };\n } finally {\n pending.delete(event.sender);\n }\n });\n return () => {\n running = false;\n ipcMain.removeHandler(DASHBOARD_PICK_ELEMENT);\n for (const cancel of active.values()) cancel();\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"dashboard-picker.js","names":[],"sources":["../../src/main/dashboard-picker.ts"],"sourcesContent":["import { BrowserWindow, type IpcMainInvokeEvent, ipcMain, session } from \"electron\";\nimport { normalizeDashboardUrl } from \"../common/dashboard\";\nimport { DASHBOARD_PICK_ELEMENT, type DashboardPickerResult, dashboardPickerScript } from \"../common/dashboard-picker\";\nimport { normalizeDashboardSelector } from \"../common/dashboard-selector\";\n\nexport function trustedPickerSender(event: IpcMainInvokeEvent): boolean {\n const trusted = (value: string) => {\n try {\n const url = new URL(value);\n return (\n url.protocol === \"https:\" &&\n (url.hostname === \"renderer.freelens.app\" || url.hostname.endsWith(\".renderer.freelens.app\")) &&\n (url.pathname === \"/preferences\" || url.pathname.startsWith(\"/preferences/\"))\n );\n } catch {\n return false;\n }\n };\n return (\n event.senderFrame === event.sender.mainFrame &&\n trusted(event.senderFrame?.url ?? \"\") &&\n trusted(event.sender.getURL())\n );\n}\n\nexport function startDashboardPicker(): () => void {\n const active = new Map<BrowserWindow, () => void>();\n const pending = new WeakSet<object>();\n let running = true;\n ipcMain.handle(DASHBOARD_PICK_ELEMENT, async (event, payload: unknown): Promise<DashboardPickerResult> => {\n if (!running || !trustedPickerSender(event) || pending.has(event.sender) || !payload || typeof payload !== \"object\")\n return { status: \"error\" };\n const rawUrl = (payload as { url?: unknown }).url;\n const url = typeof rawUrl === \"string\" && rawUrl.length <= 8192 ? normalizeDashboardUrl(rawUrl) : undefined;\n const owner = BrowserWindow.fromWebContents(event.sender);\n if (!url || !owner || owner.isDestroyed()) return { status: \"error\" };\n pending.add(event.sender);\n try {\n const websiteSession = session.fromPartition(\"persist:freelens-power-websites\");\n websiteSession.setPermissionRequestHandler((_contents, _permission, callback) => callback(false));\n websiteSession.setPermissionCheckHandler(() => false);\n const picker = new BrowserWindow({\n parent: owner,\n modal: true,\n width: 1100,\n height: 800,\n show: false,\n title: \"Select website element · Click to select · Esc to cancel\",\n autoHideMenuBar: true,\n webPreferences: {\n nodeIntegration: false,\n contextIsolation: true,\n sandbox: true,\n webSecurity: true,\n partition: \"persist:freelens-power-websites\",\n },\n });\n picker.setMenu(null);\n picker.contentView.setVisible(false);\n return await new Promise<DashboardPickerResult>((resolve) => {\n let done = false;\n let loaded = false;\n const finish = (result: DashboardPickerResult) => {\n if (done) return;\n done = true;\n clearTimeout(timer);\n active.delete(picker);\n event.sender.removeListener(\"destroyed\", cancel);\n event.sender.removeListener(\"did-start-navigation\", cancel);\n if (!picker.isDestroyed()) picker.destroy();\n resolve(result);\n };\n const cancel = () => finish({ status: \"canceled\" });\n const timer = setTimeout(cancel, 5 * 60_000);\n active.set(picker, cancel);\n event.sender.once(\"destroyed\", cancel);\n event.sender.on(\"did-start-navigation\", cancel);\n picker.once(\"closed\", cancel);\n picker.webContents.setWindowOpenHandler(() => ({ action: \"deny\" }));\n picker.webContents.on(\"will-navigate\", (navigation, target) => {\n if (loaded || !normalizeDashboardUrl(target)) {\n navigation.preventDefault();\n cancel();\n }\n });\n picker.webContents.on(\"did-start-navigation\", (_navigation, _target, _inPlace, mainFrame) => {\n if (loaded && mainFrame) cancel();\n });\n picker.webContents.on(\"will-redirect\", (navigation, target) => {\n if (!normalizeDashboardUrl(target)) {\n navigation.preventDefault();\n cancel();\n }\n });\n picker.webContents.on(\"will-attach-webview\", (attach) => attach.preventDefault());\n picker.webContents.on(\"before-input-event\", (inputEvent, input) => {\n if (input.key === \"Escape\") {\n inputEvent.preventDefault();\n cancel();\n }\n });\n picker.webContents.once(\"render-process-gone\", () => finish({ status: \"error\" }));\n picker.webContents.once(\"did-finish-load\", () => {\n if (done) return;\n loaded = true;\n if (!normalizeDashboardUrl(picker.webContents.getURL())) {\n cancel();\n return;\n }\n void picker.webContents\n .executeJavaScriptInIsolatedWorld(1007, [\n {\n code: `globalThis.powerDashboardPickerSelection = ${dashboardPickerScript()}; true`,\n },\n ])\n .then((installed: unknown) => {\n if (done) return null;\n if (installed !== true) throw new Error(\"Picker could not start\");\n picker.contentView.setVisible(true);\n return picker.webContents.executeJavaScriptInIsolatedWorld(1007, [\n {\n code: \"globalThis.powerDashboardPickerSelection.then((selection) => { delete globalThis.powerDashboardPickerSelection; return selection; })\",\n },\n ]);\n })\n .then((result: unknown) => {\n if (done) return;\n const selector = normalizeDashboardSelector(result);\n finish(selector ? { status: \"selected\", selector } : { status: \"canceled\" });\n })\n .catch(() => finish({ status: \"error\" }));\n });\n picker.show();\n void picker.loadURL(url).catch(() => finish({ status: \"error\" }));\n });\n } catch {\n return { status: \"error\" };\n } finally {\n pending.delete(event.sender);\n }\n });\n return () => {\n running = false;\n ipcMain.removeHandler(DASHBOARD_PICK_ELEMENT);\n for (const cancel of active.values()) cancel();\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/main/dashboard-preload.ts
|
|
3
|
+
(() => {
|
|
4
|
+
const properties = [["opacity", "0"], ["pointer-events", "none"]];
|
|
5
|
+
const masked = /* @__PURE__ */ new Map();
|
|
6
|
+
const overlay = document.createElement("freelens-power-loading");
|
|
7
|
+
const style = (element, values) => {
|
|
8
|
+
for (const [property, value] of Object.entries(values)) element.style.setProperty(property, value, "important");
|
|
9
|
+
};
|
|
10
|
+
const dark = window.matchMedia?.("(prefers-color-scheme: dark)").matches ?? false;
|
|
11
|
+
style(overlay, {
|
|
12
|
+
position: "fixed",
|
|
13
|
+
inset: "0",
|
|
14
|
+
display: "block",
|
|
15
|
+
"z-index": "2147483647",
|
|
16
|
+
"pointer-events": "all",
|
|
17
|
+
opacity: "1",
|
|
18
|
+
background: dark ? "#202124" : "#ffffff",
|
|
19
|
+
padding: "20px",
|
|
20
|
+
"box-sizing": "border-box",
|
|
21
|
+
overflow: "hidden"
|
|
22
|
+
});
|
|
23
|
+
const shadow = overlay.attachShadow({ mode: "open" });
|
|
24
|
+
for (let index = 0; index < 4; index++) {
|
|
25
|
+
const bar = document.createElement("div");
|
|
26
|
+
style(bar, {
|
|
27
|
+
display: "block",
|
|
28
|
+
background: dark ? "#393b40" : "#e8e9eb",
|
|
29
|
+
"border-radius": "6px",
|
|
30
|
+
width: index === 0 ? "45%" : "100%",
|
|
31
|
+
height: index === 0 ? "20px" : index === 3 ? "calc(100vh - 148px)" : "12px",
|
|
32
|
+
"min-height": index === 3 ? "30px" : "0",
|
|
33
|
+
"margin-bottom": index === 0 ? "20px" : "12px"
|
|
34
|
+
});
|
|
35
|
+
shadow.append(bar);
|
|
36
|
+
}
|
|
37
|
+
const animations = [];
|
|
38
|
+
let preparing = false;
|
|
39
|
+
const restore = (element) => {
|
|
40
|
+
for (const [property, value] of properties) {
|
|
41
|
+
const saved = masked.get(element)?.get(property);
|
|
42
|
+
if (saved && element.style.getPropertyValue(property) === value && element.style.getPropertyPriority(property) === "important") if (saved.value) element.style.setProperty(property, saved.value, saved.priority);
|
|
43
|
+
else element.style.removeProperty(property);
|
|
44
|
+
}
|
|
45
|
+
masked.delete(element);
|
|
46
|
+
};
|
|
47
|
+
const apply = () => {
|
|
48
|
+
if (!preparing || !document.documentElement) return;
|
|
49
|
+
if (overlay.parentElement !== document.documentElement) document.documentElement.append(overlay);
|
|
50
|
+
for (const element of masked.keys()) if (element.parentElement !== document.documentElement) restore(element);
|
|
51
|
+
for (const element of Array.from(document.documentElement.children)) {
|
|
52
|
+
if (!(element instanceof HTMLElement) || element === overlay) continue;
|
|
53
|
+
let previous = masked.get(element);
|
|
54
|
+
if (!previous) {
|
|
55
|
+
previous = /* @__PURE__ */ new Map();
|
|
56
|
+
masked.set(element, previous);
|
|
57
|
+
}
|
|
58
|
+
for (const [property, value] of properties) {
|
|
59
|
+
const current = element.style.getPropertyValue(property);
|
|
60
|
+
const priority = element.style.getPropertyPriority(property);
|
|
61
|
+
if (!previous.has(property) || current !== value || priority !== "important") {
|
|
62
|
+
previous.set(property, {
|
|
63
|
+
value: current,
|
|
64
|
+
priority
|
|
65
|
+
});
|
|
66
|
+
element.style.setProperty(property, value, "important");
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
const observer = new MutationObserver(apply);
|
|
72
|
+
const prepare = () => {
|
|
73
|
+
if (!preparing && !(window.matchMedia?.("(prefers-reduced-motion: reduce)").matches ?? false)) {
|
|
74
|
+
for (const element of Array.from(shadow.children)) if (element instanceof HTMLElement && typeof element.animate === "function") try {
|
|
75
|
+
animations.push(element.animate([{ opacity: .55 }, { opacity: 1 }], {
|
|
76
|
+
duration: 1200,
|
|
77
|
+
direction: "alternate",
|
|
78
|
+
iterations: Infinity
|
|
79
|
+
}));
|
|
80
|
+
} catch {}
|
|
81
|
+
}
|
|
82
|
+
preparing = true;
|
|
83
|
+
observer.observe(document, {
|
|
84
|
+
childList: true,
|
|
85
|
+
subtree: true,
|
|
86
|
+
attributes: true,
|
|
87
|
+
attributeFilter: ["style"]
|
|
88
|
+
});
|
|
89
|
+
apply();
|
|
90
|
+
};
|
|
91
|
+
const release = () => {
|
|
92
|
+
preparing = false;
|
|
93
|
+
for (const animation of animations) animation.cancel();
|
|
94
|
+
animations.length = 0;
|
|
95
|
+
observer.disconnect();
|
|
96
|
+
for (const element of masked.keys()) restore(element);
|
|
97
|
+
overlay.remove();
|
|
98
|
+
};
|
|
99
|
+
document.addEventListener("freelens-power:dashboard:preparing", prepare);
|
|
100
|
+
document.addEventListener("freelens-power:dashboard:prepared", release);
|
|
101
|
+
window.addEventListener("pagehide", () => {
|
|
102
|
+
release();
|
|
103
|
+
document.removeEventListener("freelens-power:dashboard:preparing", prepare);
|
|
104
|
+
document.removeEventListener("freelens-power:dashboard:prepared", release);
|
|
105
|
+
});
|
|
106
|
+
prepare();
|
|
107
|
+
})();
|
|
108
|
+
//#endregion
|
|
109
|
+
|
|
110
|
+
//# sourceMappingURL=dashboard-preload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard-preload.js","names":[],"sources":["../../src/main/dashboard-preload.ts"],"sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n// this preload runs before website scripts without requiring modules in the sandbox\n(() => {\n const properties = [\n [\"opacity\", \"0\"],\n [\"pointer-events\", \"none\"],\n ] as const;\n const masked = new Map<HTMLElement, Map<string, { value: string; priority: string }>>();\n const overlay = document.createElement(\"freelens-power-loading\");\n const style = (element: HTMLElement, values: Record<string, string>) => {\n for (const [property, value] of Object.entries(values)) element.style.setProperty(property, value, \"important\");\n };\n const dark = window.matchMedia?.(\"(prefers-color-scheme: dark)\").matches ?? false;\n style(overlay, {\n position: \"fixed\",\n inset: \"0\",\n display: \"block\",\n \"z-index\": \"2147483647\",\n \"pointer-events\": \"all\",\n opacity: \"1\",\n background: dark ? \"#202124\" : \"#ffffff\",\n padding: \"20px\",\n \"box-sizing\": \"border-box\",\n overflow: \"hidden\",\n });\n const shadow = overlay.attachShadow({ mode: \"open\" });\n for (let index = 0; index < 4; index++) {\n const bar = document.createElement(\"div\");\n style(bar, {\n display: \"block\",\n background: dark ? \"#393b40\" : \"#e8e9eb\",\n \"border-radius\": \"6px\",\n width: index === 0 ? \"45%\" : \"100%\",\n height: index === 0 ? \"20px\" : index === 3 ? \"calc(100vh - 148px)\" : \"12px\",\n \"min-height\": index === 3 ? \"30px\" : \"0\",\n \"margin-bottom\": index === 0 ? \"20px\" : \"12px\",\n });\n shadow.append(bar);\n }\n const animations: Animation[] = [];\n let preparing = false;\n const restore = (element: HTMLElement) => {\n for (const [property, value] of properties) {\n const saved = masked.get(element)?.get(property);\n if (\n saved &&\n element.style.getPropertyValue(property) === value &&\n element.style.getPropertyPriority(property) === \"important\"\n ) {\n if (saved.value) element.style.setProperty(property, saved.value, saved.priority);\n else element.style.removeProperty(property);\n }\n }\n masked.delete(element);\n };\n const apply = () => {\n if (!preparing || !document.documentElement) return;\n if (overlay.parentElement !== document.documentElement) document.documentElement.append(overlay);\n for (const element of masked.keys()) {\n if (element.parentElement !== document.documentElement) restore(element);\n }\n for (const element of Array.from(document.documentElement.children)) {\n if (!(element instanceof HTMLElement) || element === overlay) continue;\n let previous = masked.get(element);\n if (!previous) {\n previous = new Map();\n masked.set(element, previous);\n }\n for (const [property, value] of properties) {\n const current = element.style.getPropertyValue(property);\n const priority = element.style.getPropertyPriority(property);\n if (!previous.has(property) || current !== value || priority !== \"important\") {\n previous.set(property, { value: current, priority });\n element.style.setProperty(property, value, \"important\");\n }\n }\n }\n };\n const observer = new MutationObserver(apply);\n const prepare = () => {\n if (!preparing && !(window.matchMedia?.(\"(prefers-reduced-motion: reduce)\").matches ?? false)) {\n for (const element of Array.from(shadow.children)) {\n if (element instanceof HTMLElement && typeof element.animate === \"function\") {\n try {\n animations.push(\n element.animate([{ opacity: 0.55 }, { opacity: 1 }], {\n duration: 1200,\n direction: \"alternate\",\n iterations: Infinity,\n }),\n );\n } catch {}\n }\n }\n }\n preparing = true;\n observer.observe(document, { childList: true, subtree: true, attributes: true, attributeFilter: [\"style\"] });\n apply();\n };\n const release = () => {\n preparing = false;\n for (const animation of animations) animation.cancel();\n animations.length = 0;\n observer.disconnect();\n for (const element of masked.keys()) restore(element);\n overlay.remove();\n };\n document.addEventListener(\"freelens-power:dashboard:preparing\", prepare);\n document.addEventListener(\"freelens-power:dashboard:prepared\", release);\n window.addEventListener(\"pagehide\", () => {\n release();\n document.removeEventListener(\"freelens-power:dashboard:preparing\", prepare);\n document.removeEventListener(\"freelens-power:dashboard:prepared\", release);\n });\n prepare();\n})();\n\nexport {};\n"],"mappings":"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"}
|