@64mb/freelens-power 1.2.0 → 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/README.md +1 -1
- package/out/main/common/dashboard-picker.js +4 -4
- package/out/main/common/dashboard-picker.js.map +1 -1
- package/out/main/common/dashboard-readiness.js +17 -47
- package/out/main/common/dashboard-readiness.js.map +1 -1
- package/out/main/common/dashboard-selector.js +40 -6
- package/out/main/common/dashboard-selector.js.map +1 -1
- package/out/main/common/dashboard.js +1 -0
- package/out/main/common/dashboard.js.map +1 -1
- package/out/main/common/settings-export.js +1 -1
- package/out/main/common/settings-export.js.map +1 -1
- package/out/main/common/store/dashboard-preferences-store.js +2 -1
- package/out/main/common/store/dashboard-preferences-store.js.map +1 -1
- package/out/main/dashboard-picker.js +1 -4
- package/out/main/dashboard-picker.js.map +1 -1
- package/out/main/dashboard-preload.js +110 -0
- package/out/main/dashboard-preload.js.map +1 -0
- package/out/main/dashboard-views.js +216 -61
- 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 +69 -15
- package/out/renderer/dashboard.js.map +1 -1
- package/out/renderer/preferences/dashboard-preferences.js +16 -1
- 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/out/renderer/src/common/dashboard.js +1 -0
- package/out/renderer/src/common/dashboard.js.map +1 -1
- package/out/renderer/src/common/settings-export.js.map +1 -1
- package/out/renderer/src/common/store/dashboard-preferences-store.js +2 -1
- package/out/renderer/src/common/store/dashboard-preferences-store.js.map +1 -1
- package/package.json +1 -1
|
@@ -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"}
|
|
@@ -14,6 +14,7 @@ var reloadChannel = "freelens-power:dashboard-views:reload";
|
|
|
14
14
|
var clearChannel = "freelens-power:dashboard-views:clear";
|
|
15
15
|
var dashboardPath = "/extension/freelens-power/dashboard";
|
|
16
16
|
var websiteStyles = "* { scrollbar-width: none !important; } *::-webkit-scrollbar { display: none !important; width: 0 !important; height: 0 !important; }";
|
|
17
|
+
var expandedWebsiteStyles = "* { scrollbar-width: auto !important; } *::-webkit-scrollbar { display: revert !important; width: revert !important; height: revert !important; }";
|
|
17
18
|
function rendererUrl(value, dashboardOnly = false) {
|
|
18
19
|
try {
|
|
19
20
|
const url = new URL(value);
|
|
@@ -48,19 +49,58 @@ function rectangle(value) {
|
|
|
48
49
|
height: rect.height
|
|
49
50
|
};
|
|
50
51
|
}
|
|
51
|
-
|
|
52
|
+
function createDashboardSkeleton() {
|
|
53
|
+
const view = new electron.View();
|
|
54
|
+
view.setBackgroundColor(electron.nativeTheme.shouldUseDarkColors ? "#202124" : "#ffffff");
|
|
55
|
+
const bars = Array.from({ length: 4 }, () => {
|
|
56
|
+
const bar = new electron.View();
|
|
57
|
+
bar.setBackgroundColor(electron.nativeTheme.shouldUseDarkColors ? "#393b40" : "#e8e9eb");
|
|
58
|
+
bar.setBorderRadius(6);
|
|
59
|
+
view.addChildView(bar);
|
|
60
|
+
return bar;
|
|
61
|
+
});
|
|
62
|
+
return {
|
|
63
|
+
view,
|
|
64
|
+
layout: (width, height) => {
|
|
65
|
+
view.setBounds({
|
|
66
|
+
x: 0,
|
|
67
|
+
y: 0,
|
|
68
|
+
width,
|
|
69
|
+
height
|
|
70
|
+
});
|
|
71
|
+
bars.forEach((bar, index) => {
|
|
72
|
+
bar.setBounds({
|
|
73
|
+
x: 20,
|
|
74
|
+
y: index === 0 ? 20 : 60 + (index - 1) * 24,
|
|
75
|
+
width: Math.max(1, Math.round((width - 40) * (index === 0 ? .45 : 1))),
|
|
76
|
+
height: index === 0 ? 20 : index === 3 ? Math.max(30, height - 128) : 12
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
async function applyWebsiteStyles(card) {
|
|
83
|
+
const contents = card.view.webContents;
|
|
84
|
+
const generation = (card.websiteStylesGeneration ?? 0) + 1;
|
|
85
|
+
card.websiteStylesGeneration = generation;
|
|
86
|
+
const previous = card.websiteStylesKey;
|
|
87
|
+
card.websiteStylesKey = void 0;
|
|
88
|
+
if (contents.isDestroyed()) return;
|
|
89
|
+
if (previous) await contents.removeInsertedCSS(previous).catch(() => {});
|
|
90
|
+
if (card.websiteStylesGeneration !== generation || contents.isDestroyed()) return;
|
|
91
|
+
const key = await contents.insertCSS(card.scrollbars ? expandedWebsiteStyles : websiteStyles, { cssOrigin: "user" }).catch(() => void 0);
|
|
92
|
+
if (!key) return;
|
|
93
|
+
if (card.websiteStylesGeneration === generation && !contents.isDestroyed()) card.websiteStylesKey = key;
|
|
94
|
+
else if (!contents.isDestroyed()) await contents.removeInsertedCSS(key).catch(() => {});
|
|
95
|
+
}
|
|
96
|
+
async function waitForReadiness(contents, _network, selector, current) {
|
|
52
97
|
let deadline;
|
|
53
98
|
try {
|
|
54
99
|
await Promise.race([(async () => {
|
|
55
100
|
if (!current()) return;
|
|
56
|
-
await
|
|
101
|
+
await contents.mainFrame.executeJavaScript(require_dashboard_selector.dashboardSelectorScript(selector())).catch(() => {});
|
|
57
102
|
if (!current()) return;
|
|
58
|
-
await contents.
|
|
59
|
-
do {
|
|
60
|
-
await network.wait();
|
|
61
|
-
if (!current()) return;
|
|
62
|
-
await contents.executeJavaScriptInIsolatedWorld(1004, [{ code: require_dashboard_readiness.dashboardReadinessScript(selector()) }]);
|
|
63
|
-
} while (current() && !network.quiet());
|
|
103
|
+
await contents.mainFrame.executeJavaScript(require_dashboard_readiness.dashboardReadinessScript(selector()));
|
|
64
104
|
})().catch(() => new Promise((resolve) => setTimeout(resolve, 200))), new Promise((resolve) => {
|
|
65
105
|
deadline = setTimeout(resolve, 8500);
|
|
66
106
|
})]);
|
|
@@ -68,6 +108,21 @@ async function waitForReadiness(contents, network, selector, current) {
|
|
|
68
108
|
clearTimeout(deadline);
|
|
69
109
|
}
|
|
70
110
|
}
|
|
111
|
+
async function prepareDashboardPage(contents) {
|
|
112
|
+
if (contents.isDestroyed()) return;
|
|
113
|
+
let deadline;
|
|
114
|
+
try {
|
|
115
|
+
await Promise.race([contents.mainFrame.executeJavaScript("document.dispatchEvent(new Event(\"freelens-power:dashboard:preparing\"))").catch(() => {}), new Promise((resolve) => {
|
|
116
|
+
deadline = setTimeout(resolve, 250);
|
|
117
|
+
})]);
|
|
118
|
+
} finally {
|
|
119
|
+
clearTimeout(deadline);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function releaseDashboardPage(contents) {
|
|
123
|
+
if (contents.isDestroyed()) return Promise.resolve();
|
|
124
|
+
return contents.mainFrame.executeJavaScript("document.dispatchEvent(new Event(\"freelens-power:dashboard:prepared\"))").catch(() => {});
|
|
125
|
+
}
|
|
71
126
|
function startDashboardViews() {
|
|
72
127
|
const websiteSession = electron.session.fromPartition("persist:freelens-power-websites");
|
|
73
128
|
websiteSession.setPermissionRequestHandler((_contents, _permission, callback) => callback(false));
|
|
@@ -78,9 +133,11 @@ function startDashboardViews() {
|
|
|
78
133
|
const card = owner.cards.get(id);
|
|
79
134
|
if (!card) return;
|
|
80
135
|
owner.cards.delete(id);
|
|
136
|
+
card.nativeNavigation?.fail();
|
|
81
137
|
card.stopPreparation?.();
|
|
138
|
+
card.websiteStylesGeneration = (card.websiteStylesGeneration ?? 0) + 1;
|
|
82
139
|
card.faviconRequest?.abort();
|
|
83
|
-
|
|
140
|
+
clearTimeout(card.refreshTimer);
|
|
84
141
|
card.floatingPreparation?.stop();
|
|
85
142
|
card.floating?.destroy();
|
|
86
143
|
card.floating = void 0;
|
|
@@ -129,10 +186,12 @@ function startDashboardViews() {
|
|
|
129
186
|
});
|
|
130
187
|
}
|
|
131
188
|
};
|
|
132
|
-
const reload = (card, configuredUrl, initial = false) => {
|
|
189
|
+
const reload = (card, configuredUrl, initial = false, navigation) => {
|
|
133
190
|
const current = card.view.webContents.getURL();
|
|
134
191
|
const target = !initial && card.url === configuredUrl && webUrl(current) ? current : configuredUrl;
|
|
192
|
+
const prepareExisting = !initial && !navigation && !card.loading && !card.failed && webUrl(current);
|
|
135
193
|
card.faviconRequest?.abort();
|
|
194
|
+
if (!navigation) card.nativeNavigation?.fail();
|
|
136
195
|
card.url = configuredUrl;
|
|
137
196
|
card.failed = false;
|
|
138
197
|
card.loading = true;
|
|
@@ -142,23 +201,27 @@ function startDashboardViews() {
|
|
|
142
201
|
if (backgroundThrottling) contents.setBackgroundThrottling(false);
|
|
143
202
|
const network = require_dashboard_network.observeDashboardNetwork(card.view.webContents);
|
|
144
203
|
let stopped = false;
|
|
204
|
+
let documentReady;
|
|
145
205
|
const stopPreparation = () => {
|
|
146
206
|
if (stopped) return;
|
|
147
207
|
stopped = true;
|
|
148
208
|
network.dispose();
|
|
149
209
|
contents.removeListener("destroyed", stopPreparation);
|
|
210
|
+
if (documentReady) contents.removeListener("dom-ready", documentReady);
|
|
150
211
|
if (!contents.isDestroyed() && backgroundThrottling && !contents.getBackgroundThrottling()) contents.setBackgroundThrottling(backgroundThrottling);
|
|
151
212
|
if (card.stopPreparation === stopPreparation) card.stopPreparation = void 0;
|
|
152
213
|
};
|
|
153
214
|
card.stopPreparation = stopPreparation;
|
|
154
215
|
contents.once("destroyed", stopPreparation);
|
|
155
216
|
const generation = ++card.generation;
|
|
156
|
-
card.
|
|
217
|
+
card.skeleton.view.setVisible(true);
|
|
218
|
+
card.container.setVisible(card.visible && !card.floating);
|
|
157
219
|
publishLoading(card);
|
|
158
220
|
const settled = (failed) => {
|
|
159
221
|
if (card.generation !== generation || card.view.webContents.isDestroyed()) return;
|
|
160
222
|
card.failed = failed;
|
|
161
223
|
card.loading = false;
|
|
224
|
+
card.skeleton.view.setVisible(false);
|
|
162
225
|
for (const [sender, owner] of owners) {
|
|
163
226
|
if (![...owner.cards.values()].includes(card)) continue;
|
|
164
227
|
card.container.setVisible(card.visible && !card.floating && !failed && dashboardUrl(sender.getURL()));
|
|
@@ -167,19 +230,33 @@ function startDashboardViews() {
|
|
|
167
230
|
};
|
|
168
231
|
const load = () => {
|
|
169
232
|
if (card.generation !== generation || card.view.webContents.isDestroyed() || ![...owners.values()].some((owner) => [...owner.cards.values()].includes(card))) return Promise.resolve();
|
|
170
|
-
|
|
233
|
+
if (navigation) return navigation;
|
|
234
|
+
const navigate = () => {
|
|
235
|
+
if (card.generation !== generation || contents.isDestroyed()) return Promise.resolve();
|
|
236
|
+
card.requestedNavigation = true;
|
|
237
|
+
return contents.loadURL(target).finally(() => {
|
|
238
|
+
if (card.generation === generation) card.requestedNavigation = false;
|
|
239
|
+
});
|
|
240
|
+
};
|
|
241
|
+
return prepareExisting ? prepareDashboardPage(contents).then(navigate) : navigate();
|
|
171
242
|
};
|
|
172
|
-
|
|
243
|
+
const ready = new Promise((resolve) => {
|
|
244
|
+
documentReady = resolve;
|
|
245
|
+
contents.once("dom-ready", documentReady);
|
|
246
|
+
});
|
|
247
|
+
card.pending = Promise.race([load(), ready]).then(async () => {
|
|
173
248
|
let preparing = true;
|
|
174
249
|
const current = () => preparing && card.generation === generation && !card.view.webContents.isDestroyed() && [...owners.values()].some((owner) => [...owner.cards.values()].includes(card));
|
|
175
250
|
try {
|
|
176
251
|
await waitForReadiness(contents, network, () => card.selector, current);
|
|
252
|
+
if (current()) await releaseDashboardPage(contents);
|
|
177
253
|
} finally {
|
|
178
254
|
preparing = false;
|
|
179
255
|
stopPreparation();
|
|
180
256
|
}
|
|
181
257
|
settled(false);
|
|
182
258
|
}, () => {
|
|
259
|
+
if (card.generation === generation) releaseDashboardPage(contents);
|
|
183
260
|
stopPreparation();
|
|
184
261
|
settled(true);
|
|
185
262
|
});
|
|
@@ -187,7 +264,7 @@ function startDashboardViews() {
|
|
|
187
264
|
};
|
|
188
265
|
const applySelector = (card) => {
|
|
189
266
|
if (card.view.webContents.isDestroyed()) return Promise.resolve();
|
|
190
|
-
return card.view.webContents.
|
|
267
|
+
return card.view.webContents.mainFrame.executeJavaScript(require_dashboard_selector.dashboardSelectorScript(card.selector)).catch(() => {});
|
|
191
268
|
};
|
|
192
269
|
const refreshTimers = () => {
|
|
193
270
|
const configured = configuredCards();
|
|
@@ -207,24 +284,57 @@ function startDashboardViews() {
|
|
|
207
284
|
card.floatingPreparation?.selectorChanged();
|
|
208
285
|
}
|
|
209
286
|
if (card.floating && !card.floating.isDestroyed()) card.floating.setTitle(setting.title);
|
|
210
|
-
if (
|
|
211
|
-
|
|
212
|
-
card.
|
|
213
|
-
|
|
287
|
+
if (card.floatingStyles) {
|
|
288
|
+
const scrollbars = setting.size === "l" || setting.size === "xl";
|
|
289
|
+
if (card.floatingStyles.scrollbars !== scrollbars) {
|
|
290
|
+
card.floatingStyles.scrollbars = scrollbars;
|
|
291
|
+
applyWebsiteStyles(card.floatingStyles);
|
|
292
|
+
}
|
|
214
293
|
}
|
|
215
|
-
|
|
216
|
-
card.
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
294
|
+
const interval = setting.refreshEvery10Seconds ? 1e4 : setting.autoRefresh ? 6e5 : void 0;
|
|
295
|
+
if (card.refreshInterval === interval) continue;
|
|
296
|
+
clearTimeout(card.refreshTimer);
|
|
297
|
+
card.refreshTimer = void 0;
|
|
298
|
+
card.refreshInterval = interval;
|
|
299
|
+
const refreshGeneration = (card.refreshGeneration ?? 0) + 1;
|
|
300
|
+
card.refreshGeneration = refreshGeneration;
|
|
301
|
+
if (!interval) continue;
|
|
302
|
+
const schedule = () => {
|
|
303
|
+
if (owners.get(sender) !== owner || owner.cards.get(id) !== card || card.refreshGeneration !== refreshGeneration) return;
|
|
304
|
+
if (card.loading && card.pending) {
|
|
305
|
+
card.pending.then(schedule);
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
card.refreshTimer = setTimeout(tick, interval);
|
|
309
|
+
};
|
|
310
|
+
const tick = async () => {
|
|
311
|
+
try {
|
|
312
|
+
const latest = configuredCards().find((item) => item.id === id);
|
|
313
|
+
if (owners.get(sender) !== owner || owner.cards.get(id) !== card || !latest || latest.url !== card.url || (latest.refreshEvery10Seconds ? 1e4 : latest.autoRefresh ? 6e5 : void 0) !== interval || card.view.webContents.isDestroyed()) return;
|
|
314
|
+
if (card.loading) {
|
|
315
|
+
await card.pending;
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
if (latest.refreshEvery10Seconds) {
|
|
319
|
+
if (card.floating) {
|
|
320
|
+
if (card.floating.isDestroyed() || card.floatingPreparation?.isPreparing()) return;
|
|
321
|
+
await Promise.all([reload(card, latest.url), card.floatingPreparation?.refresh()]);
|
|
322
|
+
} else if (card.visible && dashboardUrl(sender.getURL())) await reload(card, latest.url);
|
|
323
|
+
} else if (!card.floating && !dashboardUrl(sender.getURL())) await reload(card, latest.url);
|
|
324
|
+
} finally {
|
|
325
|
+
schedule();
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
schedule();
|
|
221
329
|
}
|
|
222
330
|
};
|
|
223
|
-
const stopSettingsReaction = require__global_external_mobx.reaction(() => JSON.stringify(configuredCards().map(({ id, title, url, autoRefresh, selector }) => ({
|
|
331
|
+
const stopSettingsReaction = require__global_external_mobx.reaction(() => JSON.stringify(configuredCards().map(({ id, title, url, size, autoRefresh, refreshEvery10Seconds, selector }) => ({
|
|
224
332
|
id,
|
|
225
333
|
title,
|
|
226
334
|
url,
|
|
335
|
+
size,
|
|
227
336
|
autoRefresh,
|
|
337
|
+
refreshEvery10Seconds,
|
|
228
338
|
selector
|
|
229
339
|
}))), refreshTimers);
|
|
230
340
|
const trusted = (event) => event.senderFrame === event.sender.mainFrame && dashboardUrl(event.senderFrame?.url ?? "") && dashboardUrl(event.sender.getURL());
|
|
@@ -293,12 +403,10 @@ function startDashboardViews() {
|
|
|
293
403
|
contextIsolation: true,
|
|
294
404
|
sandbox: true,
|
|
295
405
|
webSecurity: true,
|
|
296
|
-
partition: "persist:freelens-power-websites"
|
|
406
|
+
partition: "persist:freelens-power-websites",
|
|
407
|
+
preload: (0, node_path.join)(__dirname, "dashboard-preload.js")
|
|
297
408
|
} });
|
|
298
409
|
view.setBackgroundColor("#00000000");
|
|
299
|
-
view.webContents.on("did-finish-load", () => {
|
|
300
|
-
if (!view.webContents.isDestroyed()) view.webContents.insertCSS(websiteStyles, { cssOrigin: "user" }).catch(() => {});
|
|
301
|
-
});
|
|
302
410
|
view.webContents.setWindowOpenHandler(({ url }) => {
|
|
303
411
|
if (webUrl(url)) electron.shell.openExternal(url).catch(() => {});
|
|
304
412
|
return { action: "deny" };
|
|
@@ -312,9 +420,12 @@ function startDashboardViews() {
|
|
|
312
420
|
if (!webUrl(event.url)) event.preventDefault();
|
|
313
421
|
});
|
|
314
422
|
container.addChildView(view);
|
|
423
|
+
const skeleton = createDashboardSkeleton();
|
|
424
|
+
container.addChildView(skeleton.view);
|
|
315
425
|
window.contentView.addChildView(container);
|
|
316
426
|
card = {
|
|
317
427
|
container,
|
|
428
|
+
skeleton,
|
|
318
429
|
view,
|
|
319
430
|
url: "",
|
|
320
431
|
failed: false,
|
|
@@ -329,7 +440,38 @@ function startDashboardViews() {
|
|
|
329
440
|
event.sender.send("freelens-power:dashboard-escape");
|
|
330
441
|
});
|
|
331
442
|
created.selector = configured.selector;
|
|
332
|
-
view.webContents.on("did-
|
|
443
|
+
view.webContents.on("did-start-navigation", (_event, _url, inPlace, mainFrame) => {
|
|
444
|
+
if (!mainFrame) return;
|
|
445
|
+
if (created.requestedNavigation) {
|
|
446
|
+
created.requestedNavigation = false;
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
created.nativeNavigation?.fail();
|
|
450
|
+
const navigation = new Promise((resolve, reject) => {
|
|
451
|
+
created.nativeNavigation = {
|
|
452
|
+
finish: () => {
|
|
453
|
+
created.nativeNavigation = void 0;
|
|
454
|
+
resolve();
|
|
455
|
+
},
|
|
456
|
+
fail: () => {
|
|
457
|
+
created.nativeNavigation = void 0;
|
|
458
|
+
reject(/* @__PURE__ */ new Error("dashboard navigation failed"));
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
});
|
|
462
|
+
if (inPlace) view.webContents.mainFrame.executeJavaScript("document.dispatchEvent(new Event(\"freelens-power:dashboard:preparing\"))").catch(() => {});
|
|
463
|
+
reload(created, created.url, false, navigation);
|
|
464
|
+
if (inPlace) created.nativeNavigation?.finish();
|
|
465
|
+
});
|
|
466
|
+
view.webContents.on("did-finish-load", () => {
|
|
467
|
+
applyWebsiteStyles(created);
|
|
468
|
+
applySelector(created);
|
|
469
|
+
created.nativeNavigation?.finish();
|
|
470
|
+
});
|
|
471
|
+
view.webContents.on("did-fail-load", (_event, code, _description, _url, mainFrame) => {
|
|
472
|
+
if (!mainFrame || code === -3 && view.webContents.isLoading()) return;
|
|
473
|
+
created.nativeNavigation?.fail();
|
|
474
|
+
});
|
|
333
475
|
view.webContents.on("page-favicon-updated", (_event, favicons) => {
|
|
334
476
|
const favicon = favicons.find((value) => {
|
|
335
477
|
if (!webUrl(value)) return false;
|
|
@@ -411,8 +553,12 @@ function startDashboardViews() {
|
|
|
411
553
|
})().catch(() => {}).finally(() => clearTimeout(timeout));
|
|
412
554
|
});
|
|
413
555
|
}
|
|
556
|
+
if (card.scrollbars !== (item.scrollbars === true)) {
|
|
557
|
+
card.scrollbars = item.scrollbars === true;
|
|
558
|
+
applyWebsiteStyles(card);
|
|
559
|
+
}
|
|
414
560
|
card.visible = true;
|
|
415
|
-
card.container.setVisible(!card.
|
|
561
|
+
card.container.setVisible(!card.failed && (card.loading || card.url === configured.url));
|
|
416
562
|
const zoom = event.sender.getZoomFactor();
|
|
417
563
|
card.container.setBorderRadius(Math.round(12 * zoom));
|
|
418
564
|
card.view.setBorderRadius(Math.round(12 * zoom));
|
|
@@ -423,6 +569,7 @@ function startDashboardViews() {
|
|
|
423
569
|
height: Math.round(rect.height * zoom)
|
|
424
570
|
});
|
|
425
571
|
card.container.setBounds(scale(clip));
|
|
572
|
+
card.skeleton.layout(Math.round(clip.width * zoom), Math.round(clip.height * zoom));
|
|
426
573
|
card.view.setBounds(scale({
|
|
427
574
|
x: bounds.x - clip.x,
|
|
428
575
|
y: bounds.y - clip.y,
|
|
@@ -483,7 +630,8 @@ function startDashboardViews() {
|
|
|
483
630
|
contextIsolation: true,
|
|
484
631
|
sandbox: true,
|
|
485
632
|
webSecurity: true,
|
|
486
|
-
partition: "persist:freelens-power-websites"
|
|
633
|
+
partition: "persist:freelens-power-websites",
|
|
634
|
+
preload: (0, node_path.join)(__dirname, "dashboard-preload.js")
|
|
487
635
|
}
|
|
488
636
|
});
|
|
489
637
|
floating.setMenu(null);
|
|
@@ -492,6 +640,11 @@ function startDashboardViews() {
|
|
|
492
640
|
card.floating = floating;
|
|
493
641
|
card.container.setVisible(false);
|
|
494
642
|
const contents = floating.webContents;
|
|
643
|
+
const floatingStyles = {
|
|
644
|
+
view: { webContents: contents },
|
|
645
|
+
scrollbars: configured.size === "l" || configured.size === "xl"
|
|
646
|
+
};
|
|
647
|
+
card.floatingStyles = floatingStyles;
|
|
495
648
|
contents.setWindowOpenHandler(({ url }) => {
|
|
496
649
|
if (webUrl(url)) electron.shell.openExternal(url).catch(() => {});
|
|
497
650
|
return { action: "deny" };
|
|
@@ -506,40 +659,22 @@ function startDashboardViews() {
|
|
|
506
659
|
});
|
|
507
660
|
contents.on("page-title-updated", (event) => event.preventDefault());
|
|
508
661
|
contents.on("will-prevent-unload", (event) => event.preventDefault());
|
|
509
|
-
const
|
|
510
|
-
skeleton
|
|
511
|
-
const bars = Array.from({ length: 4 }, () => {
|
|
512
|
-
const bar = new electron.View();
|
|
513
|
-
bar.setBackgroundColor(electron.nativeTheme.shouldUseDarkColors ? "#393b40" : "#e8e9eb");
|
|
514
|
-
bar.setBorderRadius(6);
|
|
515
|
-
skeleton.addChildView(bar);
|
|
516
|
-
return bar;
|
|
517
|
-
});
|
|
662
|
+
const loadingSkeleton = createDashboardSkeleton();
|
|
663
|
+
const skeleton = loadingSkeleton.view;
|
|
518
664
|
const layoutSkeleton = () => {
|
|
519
665
|
const { width, height } = floating.getContentBounds();
|
|
520
|
-
|
|
521
|
-
x: 0,
|
|
522
|
-
y: 0,
|
|
523
|
-
width,
|
|
524
|
-
height
|
|
525
|
-
});
|
|
526
|
-
bars.forEach((bar, index) => {
|
|
527
|
-
bar.setBounds({
|
|
528
|
-
x: 20,
|
|
529
|
-
y: index === 0 ? 20 : 60 + (index - 1) * 24,
|
|
530
|
-
width: Math.max(1, Math.round((width - 40) * (index === 0 ? .45 : 1))),
|
|
531
|
-
height: index === 0 ? 20 : index === 3 ? Math.max(30, height - 128) : 12
|
|
532
|
-
});
|
|
533
|
-
});
|
|
666
|
+
loadingSkeleton.layout(width, height);
|
|
534
667
|
};
|
|
535
668
|
floating.contentView.addChildView(skeleton);
|
|
536
669
|
floating.on("resize", layoutSkeleton);
|
|
537
670
|
layoutSkeleton();
|
|
538
671
|
let generation = 0;
|
|
672
|
+
let floatingPreparing = false;
|
|
539
673
|
let stopPreparation = () => {};
|
|
540
674
|
let finishLoad;
|
|
541
675
|
const begin = () => {
|
|
542
676
|
stopPreparation();
|
|
677
|
+
floatingPreparing = true;
|
|
543
678
|
const token = ++generation;
|
|
544
679
|
const backgroundThrottling = contents.getBackgroundThrottling();
|
|
545
680
|
if (backgroundThrottling) contents.setBackgroundThrottling(false);
|
|
@@ -551,6 +686,7 @@ function startDashboardViews() {
|
|
|
551
686
|
stopPreparation = () => {
|
|
552
687
|
if (!active) return;
|
|
553
688
|
active = false;
|
|
689
|
+
floatingPreparing = false;
|
|
554
690
|
network.dispose();
|
|
555
691
|
if (!contents.isDestroyed() && backgroundThrottling) contents.setBackgroundThrottling(true);
|
|
556
692
|
};
|
|
@@ -559,6 +695,8 @@ function startDashboardViews() {
|
|
|
559
695
|
finishing ??= (async () => {
|
|
560
696
|
await waitForReadiness(contents, network, () => card.selector, current);
|
|
561
697
|
if (!current()) return false;
|
|
698
|
+
await releaseDashboardPage(contents);
|
|
699
|
+
if (!current()) return false;
|
|
562
700
|
skeleton.setVisible(false);
|
|
563
701
|
stop();
|
|
564
702
|
return false;
|
|
@@ -570,6 +708,7 @@ function startDashboardViews() {
|
|
|
570
708
|
finish,
|
|
571
709
|
fail: () => {
|
|
572
710
|
if (current()) {
|
|
711
|
+
releaseDashboardPage(contents);
|
|
573
712
|
skeleton.setVisible(false);
|
|
574
713
|
stop();
|
|
575
714
|
}
|
|
@@ -579,16 +718,26 @@ function startDashboardViews() {
|
|
|
579
718
|
const refresh = () => {
|
|
580
719
|
const preparation = begin();
|
|
581
720
|
const current = contents.getURL();
|
|
582
|
-
|
|
721
|
+
let documentReady;
|
|
722
|
+
const ready = new Promise((resolve) => {
|
|
723
|
+
documentReady = () => {
|
|
724
|
+
(finishLoad?.() ?? Promise.resolve(false)).then(resolve);
|
|
725
|
+
};
|
|
726
|
+
contents.once("dom-ready", documentReady);
|
|
727
|
+
});
|
|
728
|
+
const loading = prepareDashboardPage(contents).then(() => contents.loadURL(webUrl(current) ? current : configured.url)).then(() => finishLoad?.() ?? false, () => {
|
|
583
729
|
preparation.fail();
|
|
584
730
|
return !contents.isDestroyed();
|
|
585
731
|
});
|
|
732
|
+
return Promise.race([loading, ready]).finally(() => {
|
|
733
|
+
contents.removeListener("dom-ready", documentReady);
|
|
734
|
+
});
|
|
586
735
|
};
|
|
587
736
|
card.floatingPreparation = {
|
|
588
737
|
refresh,
|
|
738
|
+
isPreparing: () => floatingPreparing,
|
|
589
739
|
selectorChanged: () => {
|
|
590
|
-
|
|
591
|
-
if (!contents.isLoading()) preparation.finish();
|
|
740
|
+
begin().finish();
|
|
592
741
|
},
|
|
593
742
|
stop: () => {
|
|
594
743
|
++generation;
|
|
@@ -600,14 +749,18 @@ function startDashboardViews() {
|
|
|
600
749
|
const preparation = begin();
|
|
601
750
|
if (inPlace) preparation.finish();
|
|
602
751
|
});
|
|
752
|
+
contents.on("dom-ready", () => {
|
|
753
|
+
applyWebsiteStyles(floatingStyles);
|
|
754
|
+
if (!contents.isDestroyed()) finishLoad?.();
|
|
755
|
+
});
|
|
603
756
|
contents.on("did-finish-load", () => {
|
|
604
|
-
|
|
605
|
-
contents.
|
|
606
|
-
finishLoad?.();
|
|
757
|
+
applyWebsiteStyles(floatingStyles);
|
|
758
|
+
if (!contents.isDestroyed()) finishLoad?.();
|
|
607
759
|
});
|
|
608
760
|
contents.on("did-fail-load", (_event, code, _description, _url, mainFrame) => {
|
|
609
761
|
if (!mainFrame || code === -3) return;
|
|
610
762
|
stopPreparation();
|
|
763
|
+
releaseDashboardPage(contents);
|
|
611
764
|
skeleton.setVisible(false);
|
|
612
765
|
});
|
|
613
766
|
contents.once("destroyed", () => {
|
|
@@ -618,6 +771,8 @@ function startDashboardViews() {
|
|
|
618
771
|
if (card.floating !== floating) return;
|
|
619
772
|
card.floatingPreparation?.stop();
|
|
620
773
|
card.floatingPreparation = void 0;
|
|
774
|
+
floatingStyles.websiteStylesGeneration = (floatingStyles.websiteStylesGeneration ?? 0) + 1;
|
|
775
|
+
card.floatingStyles = void 0;
|
|
621
776
|
card.floating = void 0;
|
|
622
777
|
if (owner.cards.get(id) === card) publishPinned(event.sender, owner);
|
|
623
778
|
});
|