@64mb/freelens-power 1.2.1 → 1.2.2
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/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/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/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/preferences/dashboard-preferences.js +16 -16
- package/out/renderer/preferences/dashboard-preferences.js.map +1 -1
- package/out/renderer/preferences/settings-modal.js.map +1 -1
- package/out/renderer/src/common/dashboard-picker.js.map +1 -1
- package/out/renderer/src/common/dashboard-selector.js.map +1 -1
- package/package.json +1 -1
|
@@ -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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"}
|
|
@@ -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":";;OAGO;CACL,MAAM,aAAa,CACjB,CAAC,WAAW,GAAG,GACf,CAAC,kBAAkB,MAAM,CAC3B;CACA,MAAM,yBAAS,IAAI,IAAmE;CACtF,MAAM,UAAU,SAAS,cAAc,wBAAwB;CAC/D,MAAM,SAAS,SAAsB,WAAmC;EACtE,KAAK,MAAM,CAAC,UAAU,UAAU,OAAO,QAAQ,MAAM,GAAG,QAAQ,MAAM,YAAY,UAAU,OAAO,WAAW;CAChH;CACA,MAAM,OAAO,OAAO,aAAa,8BAA8B,CAAC,CAAC,WAAW;CAC5E,MAAM,SAAS;EACb,UAAU;EACV,OAAO;EACP,SAAS;EACT,WAAW;EACX,kBAAkB;EAClB,SAAS;EACT,YAAY,OAAO,YAAY;EAC/B,SAAS;EACT,cAAc;EACd,UAAU;CACZ,CAAC;CACD,MAAM,SAAS,QAAQ,aAAa,EAAE,MAAM,OAAO,CAAC;CACpD,KAAK,IAAI,QAAQ,GAAG,QAAQ,GAAG,SAAS;EACtC,MAAM,MAAM,SAAS,cAAc,KAAK;EACxC,MAAM,KAAK;GACT,SAAS;GACT,YAAY,OAAO,YAAY;GAC/B,iBAAiB;GACjB,OAAO,UAAU,IAAI,QAAQ;GAC7B,QAAQ,UAAU,IAAI,SAAS,UAAU,IAAI,wBAAwB;GACrE,cAAc,UAAU,IAAI,SAAS;GACrC,iBAAiB,UAAU,IAAI,SAAS;EAC1C,CAAC;EACD,OAAO,OAAO,GAAG;CACnB;CACA,MAAM,aAA0B,CAAC;CACjC,IAAI,YAAY;CAChB,MAAM,WAAW,YAAyB;EACxC,KAAK,MAAM,CAAC,UAAU,UAAU,YAAY;GAC1C,MAAM,QAAQ,OAAO,IAAI,OAAO,CAAC,EAAE,IAAI,QAAQ;GAC/C,IACE,SACA,QAAQ,MAAM,iBAAiB,QAAQ,MAAM,SAC7C,QAAQ,MAAM,oBAAoB,QAAQ,MAAM,aAEhD,IAAI,MAAM,OAAO,QAAQ,MAAM,YAAY,UAAU,MAAM,OAAO,MAAM,QAAQ;QAC3E,QAAQ,MAAM,eAAe,QAAQ;EAE9C;EACA,OAAO,OAAO,OAAO;CACvB;CACA,MAAM,cAAc;EAClB,IAAI,CAAC,aAAa,CAAC,SAAS,iBAAiB;EAC7C,IAAI,QAAQ,kBAAkB,SAAS,iBAAiB,SAAS,gBAAgB,OAAO,OAAO;EAC/F,KAAK,MAAM,WAAW,OAAO,KAAK,GAChC,IAAI,QAAQ,kBAAkB,SAAS,iBAAiB,QAAQ,OAAO;EAEzE,KAAK,MAAM,WAAW,MAAM,KAAK,SAAS,gBAAgB,QAAQ,GAAG;GACnE,IAAI,EAAE,mBAAmB,gBAAgB,YAAY,SAAS;GAC9D,IAAI,WAAW,OAAO,IAAI,OAAO;GACjC,IAAI,CAAC,UAAU;IACb,2BAAW,IAAI,IAAI;IACnB,OAAO,IAAI,SAAS,QAAQ;GAC9B;GACA,KAAK,MAAM,CAAC,UAAU,UAAU,YAAY;IAC1C,MAAM,UAAU,QAAQ,MAAM,iBAAiB,QAAQ;IACvD,MAAM,WAAW,QAAQ,MAAM,oBAAoB,QAAQ;IAC3D,IAAI,CAAC,SAAS,IAAI,QAAQ,KAAK,YAAY,SAAS,aAAa,aAAa;KAC5E,SAAS,IAAI,UAAU;MAAE,OAAO;MAAS;KAAS,CAAC;KACnD,QAAQ,MAAM,YAAY,UAAU,OAAO,WAAW;IACxD;GACF;EACF;CACF;CACA,MAAM,WAAW,IAAI,iBAAiB,KAAK;CAC3C,MAAM,gBAAgB;EACpB,IAAI,CAAC,aAAa,EAAE,OAAO,aAAa,kCAAkC,CAAC,CAAC,WAAW;QAChF,MAAM,WAAW,MAAM,KAAK,OAAO,QAAQ,GAC9C,IAAI,mBAAmB,eAAe,OAAO,QAAQ,YAAY,YAC/D,IAAI;IACF,WAAW,KACT,QAAQ,QAAQ,CAAC,EAAE,SAAS,IAAK,GAAG,EAAE,SAAS,EAAE,CAAC,GAAG;KACnD,UAAU;KACV,WAAW;KACX,YAAY;IACd,CAAC,CACH;GACF,QAAQ,CAAC;;EAIf,YAAY;EACZ,SAAS,QAAQ,UAAU;GAAE,WAAW;GAAM,SAAS;GAAM,YAAY;GAAM,iBAAiB,CAAC,OAAO;EAAE,CAAC;EAC3G,MAAM;CACR;CACA,MAAM,gBAAgB;EACpB,YAAY;EACZ,KAAK,MAAM,aAAa,YAAY,UAAU,OAAO;EACrD,WAAW,SAAS;EACpB,SAAS,WAAW;EACpB,KAAK,MAAM,WAAW,OAAO,KAAK,GAAG,QAAQ,OAAO;EACpD,QAAQ,OAAO;CACjB;CACA,SAAS,iBAAiB,sCAAsC,OAAO;CACvE,SAAS,iBAAiB,qCAAqC,OAAO;CACtE,OAAO,iBAAiB,kBAAkB;EACxC,QAAQ;EACR,SAAS,oBAAoB,sCAAsC,OAAO;EAC1E,SAAS,oBAAoB,qCAAqC,OAAO;CAC3E,CAAC;CACD,QAAQ;AACV,EAAA,CAAG"}
|