@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.
Files changed (88) hide show
  1. package/README.md +3 -1
  2. package/out/main/common/dashboard-picker.js +4 -4
  3. package/out/main/common/dashboard-picker.js.map +1 -1
  4. package/out/main/common/dashboard-readiness.js +17 -47
  5. package/out/main/common/dashboard-readiness.js.map +1 -1
  6. package/out/main/common/dashboard-selector.js +40 -6
  7. package/out/main/common/dashboard-selector.js.map +1 -1
  8. package/out/main/common/store/monitoring-preferences-store.js +5 -0
  9. package/out/main/common/store/monitoring-preferences-store.js.map +1 -1
  10. package/out/main/dashboard-picker.js +1 -4
  11. package/out/main/dashboard-picker.js.map +1 -1
  12. package/out/main/dashboard-preload.js +110 -0
  13. package/out/main/dashboard-preload.js.map +1 -0
  14. package/out/main/dashboard-views.js +207 -62
  15. package/out/main/dashboard-views.js.map +1 -1
  16. package/out/main/dock-icon.js +25 -10
  17. package/out/main/dock-icon.js.map +1 -1
  18. package/out/main/index.js +2 -0
  19. package/out/main/index.js.map +1 -1
  20. package/out/main/splash-accent.js +84 -0
  21. package/out/main/splash-accent.js.map +1 -0
  22. package/out/renderer/ai-diagnostic-handoff.js +52 -0
  23. package/out/renderer/ai-diagnostic-handoff.js.map +1 -0
  24. package/out/renderer/ai-extras.js +40 -4
  25. package/out/renderer/ai-extras.js.map +1 -1
  26. package/out/renderer/ai.js +48 -56
  27. package/out/renderer/ai.js.map +1 -1
  28. package/out/renderer/appearance.js +6 -2
  29. package/out/renderer/appearance.js.map +1 -1
  30. package/out/renderer/dashboard.js +26 -6
  31. package/out/renderer/dashboard.js.map +1 -1
  32. package/out/renderer/details/hpa-diagnostics-details.js +46 -0
  33. package/out/renderer/details/hpa-diagnostics-details.js.map +1 -0
  34. package/out/renderer/details/namespace-health-details.js +91 -0
  35. package/out/renderer/details/namespace-health-details.js.map +1 -0
  36. package/out/renderer/details/resource-health-details.js +131 -0
  37. package/out/renderer/details/resource-health-details.js.map +1 -0
  38. package/out/renderer/details/service-diagnostics-details.js +163 -0
  39. package/out/renderer/details/service-diagnostics-details.js.map +1 -0
  40. package/out/renderer/diagnostic-explain-button.js +16 -0
  41. package/out/renderer/diagnostic-explain-button.js.map +1 -0
  42. package/out/renderer/diagnostics-state.js +51 -0
  43. package/out/renderer/diagnostics-state.js.map +1 -0
  44. package/out/renderer/diagnostics.css.js +9 -0
  45. package/out/renderer/diagnostics.css.js.map +1 -1
  46. package/out/renderer/diagnostics.js +369 -73
  47. package/out/renderer/diagnostics.js.map +1 -1
  48. package/out/renderer/incident-copy-button.js +50 -0
  49. package/out/renderer/incident-copy-button.js.map +1 -0
  50. package/out/renderer/index.js +91 -19
  51. package/out/renderer/index.js.map +1 -1
  52. package/out/renderer/monitoring-history-collection.js +1 -1
  53. package/out/renderer/preferences/dashboard-preferences.js +16 -16
  54. package/out/renderer/preferences/dashboard-preferences.js.map +1 -1
  55. package/out/renderer/preferences/monitoring-preferences.js +10 -0
  56. package/out/renderer/preferences/monitoring-preferences.js.map +1 -1
  57. package/out/renderer/preferences/preferences.js +88 -0
  58. package/out/renderer/preferences/preferences.js.map +1 -1
  59. package/out/renderer/preferences/settings-modal.js.map +1 -1
  60. package/out/renderer/resource-relationships.css.js +7 -0
  61. package/out/renderer/resource-relationships.css.js.map +1 -0
  62. package/out/renderer/resource-relationships.js +556 -0
  63. package/out/renderer/resource-relationships.js.map +1 -0
  64. package/out/renderer/resource-search-distance.js +24 -0
  65. package/out/renderer/resource-search-distance.js.map +1 -0
  66. package/out/renderer/resource-search-fields.js +55 -0
  67. package/out/renderer/resource-search-fields.js.map +1 -0
  68. package/out/renderer/resource-search-model.js +193 -0
  69. package/out/renderer/resource-search-model.js.map +1 -0
  70. package/out/renderer/resource-search.js +365 -0
  71. package/out/renderer/resource-search.js.map +1 -0
  72. package/out/renderer/src/common/dashboard-picker.js.map +1 -1
  73. package/out/renderer/src/common/dashboard-selector.js.map +1 -1
  74. package/out/renderer/src/common/hpa-diagnostics.js +24 -0
  75. package/out/renderer/src/common/hpa-diagnostics.js.map +1 -0
  76. package/out/renderer/src/common/incident-summary.js +73 -0
  77. package/out/renderer/src/common/incident-summary.js.map +1 -0
  78. package/out/renderer/src/common/resource-health.js +92 -0
  79. package/out/renderer/src/common/resource-health.js.map +1 -0
  80. package/out/renderer/src/common/resource-relationships.js +155 -0
  81. package/out/renderer/src/common/resource-relationships.js.map +1 -0
  82. package/out/renderer/src/common/service-diagnostics.js +50 -0
  83. package/out/renderer/src/common/service-diagnostics.js.map +1 -0
  84. package/out/renderer/src/common/store/monitoring-preferences-store.js +5 -0
  85. package/out/renderer/src/common/store/monitoring-preferences-store.js.map +1 -1
  86. package/out/renderer/src/common/timeline-groups.js +36 -0
  87. package/out/renderer/src/common/timeline-groups.js.map +1 -0
  88. 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 by namespace and workload, application event timelines, and evidence-based Pending pod diagnostics
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(accent) {
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 = `position:fixed;box-sizing:border-box;border:2px solid ${accent};pointer-events:none;display:none`;
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(accent) {
126
- return `(${dashboardPickerAdapter.toString()})(${JSON.stringify(/^#[0-9a-f]{6}$/i.test(accent) ? accent : "#00a7a0")})`;
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(accent: string): 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 = `position:fixed;box-sizing:border-box;border:2px solid ${accent};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(accent: string): string {\n return `(${dashboardPickerAdapter.toString()})(${JSON.stringify(/^#[0-9a-f]{6}$/i.test(accent) ? accent : \"#00a7a0\")})`;\n}\n"],"mappings":"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"}
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
- const changed = () => {
10
- lastChange = Date.now();
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
- if (finished || painting || !ready()) return;
38
+ const element = target();
39
+ if (finished || painting || !element) return;
70
40
  painting = true;
71
- frame().then(frame).then(() => new Promise((settled) => setTimeout(settled, 200))).then(() => {
41
+ frame().then(frame).then(() => {
72
42
  painting = false;
73
- if (!finished && ready() && Date.now() - lastChange >= 550) finish();
43
+ if (!finished && target() === element) finish();
74
44
  });
75
45
  };
76
- const interval = setInterval(check, 100);
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 only inside the isolated website world\nexport function dashboardReadinessAdapter(selector: string): Promise<void> {\n return new Promise((resolve) => {\n let lastChange = Date.now();\n let lastLayout = \"\";\n let painting = false;\n let finished = false;\n const changed = () => {\n lastChange = Date.now();\n };\n const observer = new MutationObserver(changed);\n observer.observe(document.documentElement, {\n subtree: true,\n childList: true,\n attributes: true,\n characterData: true,\n });\n const finish = () => {\n if (finished) return;\n finished = true;\n observer.disconnect();\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 ready = () => {\n let target: Element | null = document.body;\n if (selector) {\n try {\n target = document.querySelector(selector);\n } catch {\n target = null;\n }\n }\n if (!target || document.readyState !== \"complete\" || document.fonts?.status === \"loading\") return false;\n const bounds = target.getBoundingClientRect();\n if (bounds.width <= 0 || bounds.height <= 0) return false;\n const layout = [bounds.x, bounds.y, bounds.width, bounds.height, target.scrollWidth, target.scrollHeight].join(\n \",\",\n );\n if (layout !== lastLayout) {\n lastLayout = layout;\n changed();\n }\n const images = Array.from(target.querySelectorAll(\"img\"));\n if (target instanceof HTMLImageElement) images.unshift(target);\n const pendingImages = images.some((image) => {\n const rect = image.getBoundingClientRect();\n const style = getComputedStyle(image);\n return (\n !image.complete &&\n rect.width > 0 &&\n rect.height > 0 &&\n rect.bottom > 0 &&\n rect.right > 0 &&\n rect.top < window.innerHeight &&\n rect.left < window.innerWidth &&\n style.display !== \"none\" &&\n style.visibility !== \"hidden\"\n );\n });\n return !pendingImages && Date.now() - lastChange >= 350;\n };\n const check = () => {\n if (finished || painting || !ready()) return;\n painting = true;\n void frame()\n .then(frame)\n .then(() => new Promise<void>((settled) => setTimeout(settled, 200)))\n .then(() => {\n painting = false;\n if (!finished && ready() && Date.now() - lastChange >= 550) finish();\n });\n };\n const interval = setInterval(check, 100);\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,aAAa,KAAK,IAAI;EAC1B,IAAI,aAAa;EACjB,IAAI,WAAW;EACf,IAAI,WAAW;EACf,MAAM,gBAAgB;GACpB,aAAa,KAAK,IAAI;EACxB;EACA,MAAM,WAAW,IAAI,iBAAiB,OAAO;EAC7C,SAAS,QAAQ,SAAS,iBAAiB;GACzC,SAAS;GACT,WAAW;GACX,YAAY;GACZ,eAAe;EACjB,CAAC;EACD,MAAM,eAAe;GACnB,IAAI,UAAU;GACd,WAAW;GACX,SAAS,WAAW;GACpB,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,IAAI,SAAyB,SAAS;GACtC,IAAI,UACF,IAAI;IACF,SAAS,SAAS,cAAc,QAAQ;GAC1C,QAAQ;IACN,SAAS;GACX;GAEF,IAAI,CAAC,UAAU,SAAS,eAAe,cAAc,SAAS,OAAO,WAAW,WAAW,OAAO;GAClG,MAAM,SAAS,OAAO,sBAAsB;GAC5C,IAAI,OAAO,SAAS,KAAK,OAAO,UAAU,GAAG,OAAO;GACpD,MAAM,SAAS;IAAC,OAAO;IAAG,OAAO;IAAG,OAAO;IAAO,OAAO;IAAQ,OAAO;IAAa,OAAO;GAAY,CAAC,CAAC,KACxG,GACF;GACA,IAAI,WAAW,YAAY;IACzB,aAAa;IACb,QAAQ;GACV;GACA,MAAM,SAAS,MAAM,KAAK,OAAO,iBAAiB,KAAK,CAAC;GACxD,IAAI,kBAAkB,kBAAkB,OAAO,QAAQ,MAAM;GAgB7D,OAAO,CAfe,OAAO,MAAM,UAAU;IAC3C,MAAM,OAAO,MAAM,sBAAsB;IACzC,MAAM,QAAQ,iBAAiB,KAAK;IACpC,OACE,CAAC,MAAM,YACP,KAAK,QAAQ,KACb,KAAK,SAAS,KACd,KAAK,SAAS,KACd,KAAK,QAAQ,KACb,KAAK,MAAM,OAAO,eAClB,KAAK,OAAO,OAAO,cACnB,MAAM,YAAY,UAClB,MAAM,eAAe;GAEzB,CACQ,KAAiB,KAAK,IAAI,IAAI,cAAc;EACtD;EACA,MAAM,cAAc;GAClB,IAAI,YAAY,YAAY,CAAC,MAAM,GAAG;GACtC,WAAW;GACX,MAAW,CAAC,CACT,KAAK,KAAK,CAAC,CACX,WAAW,IAAI,SAAe,YAAY,WAAW,SAAS,GAAG,CAAC,CAAC,CAAC,CACpE,WAAW;IACV,WAAW;IACX,IAAI,CAAC,YAAY,MAAM,KAAK,KAAK,IAAI,IAAI,cAAc,KAAK,OAAO;GACrE,CAAC;EACL;EACA,MAAM,WAAW,YAAY,OAAO,GAAG;EACvC,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"}
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) return;
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 (!timer) timer = setTimeout(update, 200);
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 only inside the isolated website world\nexport function dashboardSelectorAdapter(selector: string): void {\n const state = globalThis as typeof globalThis & { powerSelectorCleanup?: () => void };\n state.powerSelectorCleanup?.();\n if (!selector) return;\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 let timer: ReturnType<typeof setTimeout> | undefined;\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 (!timer) timer = setTimeout(update, 200);\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 function update() {\n timer = undefined;\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) 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 observer.observe(document.documentElement, { subtree: true, childList: true, attributes: true });\n }\n state.powerSelectorCleanup = () => {\n observer.disconnect();\n clearTimeout(timer);\n restore();\n delete state.powerSelectorCleanup;\n };\n update();\n}\n\nexport function dashboardSelectorScript(selector?: string): string {\n return `(${dashboardSelectorAdapter.toString()})(${JSON.stringify(normalizeDashboardSelector(selector) ?? \"\")})`;\n}\n"],"mappings":"AAEA,SAAgB,2BAA2B,OAAoC;CAC7E,IAAI,OAAO,UAAU,UAAU,OAAO,KAAA;CACtC,MAAM,WAAW,MAAM,KAAK;CAC5B,OAAO,YAAY,SAAS,UAAA,OAAoC,CAAC,wBAAwB,KAAK,QAAQ,IAClG,WACA,KAAA;AACN;AAGA,SAAgB,yBAAyB,UAAwB;CAC/D,MAAM,QAAQ;CACd,MAAM,uBAAuB;CAC7B,IAAI,CAAC,UAAU;CACf,MAAM,SAAS;CACf,MAAM,OAAO;CACb,MAAM,QAAQ;CACd,IAAI;CACJ,IAAI,SAAoB,CAAC;CACzB,IAAI;CACJ,MAAM,QAAQ,SAAS,cAAc,OAAO;CAC5C,MAAM,cAAc,IAAI,OAAO,mCAAmC,KAAK,oRAAoR,MAAM;CACjW,MAAM,SAAS,SAAS,cAAc,KAAK;CAC3C,OAAO,cACL;CACF,OAAO,MAAM,UACX;CACF,MAAM,WAAW,IAAI,uBAAuB;EAC1C,IAAI,CAAC,OAAO,QAAQ,WAAW,QAAQ,GAAG;CAC5C,CAAC;CACD,SAAS,UAAU;EACjB,KAAK,MAAM,WAAW,QAAQ;GAC5B,QAAQ,gBAAgB,MAAM;GAC9B,QAAQ,gBAAgB,IAAI;EAC9B;EACA,SAAS,CAAC;EACV,WAAW,gBAAgB,KAAK;EAChC,YAAY,KAAA;EACZ,MAAM,OAAO;EACb,OAAO,OAAO;CAChB;CACA,SAAS,SAAS;EAChB,QAAQ,KAAA;EACR,SAAS,WAAW;EACpB,QAAQ;EACR,IAAI,SAAyB;EAC7B,IAAI;GACF,SAAS,SAAS,cAAc,QAAQ;EAC1C,QAAQ,CAAC;EACT,MAAM,WAAsB,CAAC;EAC7B,MAAM,YAAuB,CAAC;EAC9B,IAAI,UAAU,WAAW,SAAS,mBAAmB,WAAW,SAAS,MAAM;GAC7E,IAAI,QAAiB;GACrB,OAAO,MAAM,iBAAiB,UAAU,SAAS,OAAO,SAAS,SAAS,KAAM;IAC9E,MAAM,SAAS,MAAM;IACrB,UAAU,KAAK,MAAM;IACrB,KAAK,MAAM,WAAW,OAAO,UAAU;KACrC,IAAI,YAAY,OAAO,SAAS,KAAK,OAAO;KAC5C,IAAI,SAAS,UAAU,KAAM;IAC/B;IACA,QAAQ;GACV;GACA,IAAI,UAAU,UAAU,OAAO,SAAS,UAAU,KAAM,SAAS;EACnE;EACA,IAAI,QAAQ;GACV,KAAK,MAAM,WAAW,UAAU,QAAQ,aAAa,QAAQ,EAAE;GAC/D,KAAK,MAAM,WAAW,WAAW,QAAQ,aAAa,MAAM,EAAE;GAC9D,SAAS,CAAC,GAAG,UAAU,GAAG,SAAS;GACnC,IAAI,SAAS,MAAM;IACjB,YAAY,SAAS;IACrB,UAAU,aAAa,OAAO,EAAE;GAClC;GACA,SAAS,gBAAgB,OAAO,KAAK;EACvC,OACE,SAAS,gBAAgB,OAAO,MAAM;EAExC,SAAS,QAAQ,SAAS,iBAAiB;GAAE,SAAS;GAAM,WAAW;GAAM,YAAY;EAAK,CAAC;CACjG;CACA,MAAM,6BAA6B;EACjC,SAAS,WAAW;EACpB,aAAa,KAAK;EAClB,QAAQ;EACR,OAAO,MAAM;CACf;CACA,OAAO;AACT;AAEA,SAAgB,wBAAwB,UAA2B;CACjE,OAAO,IAAI,yBAAyB,SAAS,EAAE,IAAI,KAAK,UAAU,2BAA2B,QAAQ,KAAK,EAAE,EAAE;AAChH"}
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: { enabled: false, diagnosticsVisible: true, historyEnabled: false, trackedHistory: [] },\n });\n makeObservable(this, {\n enabled: observable,\n diagnosticsVisible: observable,\n historyEnabled: observable,\n trackedHistory: observable,\n fromStore: action,\n });\n }\n\n fromStore(data: {\n enabled?: boolean;\n diagnosticsVisible?: boolean;\n historyEnabled?: boolean;\n trackedHistory?: HistoryIdentity[];\n }): void {\n this.enabled = data?.enabled === true;\n this.diagnosticsVisible = data?.diagnosticsVisible !== 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 historyEnabled: boolean;\n trackedHistory: HistoryIdentity[];\n } {\n return {\n enabled: this.enabled,\n diagnosticsVisible: this.diagnosticsVisible,\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,eAK1D;CACD,UAAU;CACV,qBAAqB;CACrB,iBAAiB;CACjB,iBAAoC,CAAC;CAErC,cAAc;EACZ,MAAM;GACJ,YAAY;GACZ,UAAU;IAAE,SAAS;IAAO,oBAAoB;IAAM,gBAAgB;IAAO,gBAAgB,CAAC;GAAE;EAClG,CAAC;EACD,8BAAA,eAAe,MAAM;GACnB,SAAS,8BAAA;GACT,oBAAoB,8BAAA;GACpB,gBAAgB,8BAAA;GAChB,gBAAgB,8BAAA;GAChB,WAAW,8BAAA;EACb,CAAC;CACH;CAEA,UAAU,MAKD;EACP,KAAK,UAAU,MAAM,YAAY;EACjC,KAAK,qBAAqB,MAAM,uBAAuB;EACvD,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,SAKE;EACA,OAAO;GACL,SAAS,KAAK;GACd,oBAAoB,KAAK;GACzB,gBAAgB,KAAK;GACrB,gBAAgB,KAAK,eAAe,KAAK,EAAE,WAAW,OAAO,WAAW;IAAE;IAAW;IAAO;GAAI,EAAE;EACpG;CACF;AACF"}
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
- const preferences = require_appearance_preferences_store.AppearancePreferencesStore.getInstanceOrCreate();
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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"}