@64mb/freelens-power 1.0.3 → 1.1.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 (47) hide show
  1. package/README.md +5 -1
  2. package/out/main/common/monitoring-history.js +52 -0
  3. package/out/main/common/monitoring-history.js.map +1 -0
  4. package/out/main/common/store/monitoring-preferences-store.js +25 -2
  5. package/out/main/common/store/monitoring-preferences-store.js.map +1 -1
  6. package/out/main/dashboard-views.js +132 -28
  7. package/out/main/dashboard-views.js.map +1 -1
  8. package/out/main/index.js +2 -0
  9. package/out/main/index.js.map +1 -1
  10. package/out/main/monitoring-history-database.js +103 -0
  11. package/out/main/monitoring-history-database.js.map +1 -0
  12. package/out/main/monitoring-history-worker.js +61 -0
  13. package/out/main/monitoring-history-worker.js.map +1 -0
  14. package/out/main/monitoring-history.js +100 -0
  15. package/out/main/monitoring-history.js.map +1 -0
  16. package/out/renderer/_virtual/_global-external_mobx.js +2 -1
  17. package/out/renderer/diagnostics.js +647 -0
  18. package/out/renderer/diagnostics.js.map +1 -0
  19. package/out/renderer/index.js +28 -1
  20. package/out/renderer/index.js.map +1 -1
  21. package/out/renderer/monitoring-collector.js +202 -0
  22. package/out/renderer/monitoring-collector.js.map +1 -0
  23. package/out/renderer/monitoring-history-collection.js +184 -0
  24. package/out/renderer/monitoring-history-collection.js.map +1 -0
  25. package/out/renderer/monitoring-history-view.js +150 -0
  26. package/out/renderer/monitoring-history-view.js.map +1 -0
  27. package/out/renderer/monitoring-history.js +19 -0
  28. package/out/renderer/monitoring-history.js.map +1 -0
  29. package/out/renderer/monitoring.js +98 -125
  30. package/out/renderer/monitoring.js.map +1 -1
  31. package/out/renderer/node-monitoring.js +116 -0
  32. package/out/renderer/node-monitoring.js.map +1 -0
  33. package/out/renderer/pod-monitoring.js +39 -8
  34. package/out/renderer/pod-monitoring.js.map +1 -1
  35. package/out/renderer/preferences/monitoring-preferences.js +55 -10
  36. package/out/renderer/preferences/monitoring-preferences.js.map +1 -1
  37. package/out/renderer/src/common/monitoring-history.js +15 -0
  38. package/out/renderer/src/common/monitoring-history.js.map +1 -0
  39. package/out/renderer/src/common/monitoring-math.js +98 -0
  40. package/out/renderer/src/common/monitoring-math.js.map +1 -0
  41. package/out/renderer/src/common/resource-diagnostics.js +227 -0
  42. package/out/renderer/src/common/resource-diagnostics.js.map +1 -0
  43. package/out/renderer/src/common/store/monitoring-preferences-store.js +25 -2
  44. package/out/renderer/src/common/store/monitoring-preferences-store.js.map +1 -1
  45. package/out/renderer/welcome.js +3 -1
  46. package/out/renderer/welcome.js.map +1 -1
  47. package/package.json +1 -1
package/README.md CHANGED
@@ -9,7 +9,9 @@ Power tools and personal dashboards for Freelens. Built for Freelens 1.x and tes
9
9
  - **Accent themes:** Default, Purple, Blue, Green, Yellow, Orange, Red, and Pink for controls, text links, and the welcome logo
10
10
  - **macOS Dock icon:** optionally follows your accent, with a separate toggle to restore the original
11
11
  - **Power Dashboard:** reorderable S/M/L website cards, cached pages, loading skeletons, interactive element selection, expansion, pinned floating windows, shared website sessions, and optional background refresh
12
- - **Monitoring:** optional CPU and memory trends, allocation rings, pinned tooltips, and pod charts using metrics-server and Kubernetes APIs, with locally collected session samples
12
+ - **Monitoring:** optional CPU and memory trends, allocation rings, pinned tooltips, and node/pod charts using metrics-server and Kubernetes APIs
13
+ - **Resource diagnostics:** CPU/memory consumers grouped by namespace and workload, application event timelines, and evidence-based Pending pod diagnostics
14
+ - **Local metric history:** opt-in SQLite storage, up to seven days within a 100 MiB budget, with aggregated ranges and explicit collection gaps
13
15
  - **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, resource links, resizable pinned chat, and a switch to disable all AI features
14
16
  - **Read-only UI:** hides common mutation actions without changing Kubernetes permissions
15
17
  - **Master switch:** restores the native interface while preserving all settings
@@ -17,6 +19,8 @@ Power tools and personal dashboards for Freelens. Built for Freelens 1.x and tes
17
19
 
18
20
  AI tool results exclude environment values and Secret payloads; logs are reduced locally to numeric issue counters. Websites run in isolated Electron views. Every dashboard card also opens in your browser.
19
21
 
22
+ Monitoring history is collected while Freelens is running and the cluster view is active. Cluster/node series are retained automatically when enabled; pod/workload series require explicit tracking in Diagnostics. History cannot backfill periods without collection. Timelines combine retained Kubernetes events with changes observed while the diagnostics page is open. Local Pending checks explain available evidence and do not reproduce the full scheduler.
23
+
20
24
  ## Screenshots
21
25
 
22
26
  Real extension components with synthetic website content, prompts, and conversations.
@@ -0,0 +1,52 @@
1
+ //#region src/common/monitoring-history.ts
2
+ var MONITORING_HISTORY_CHANNEL = "freelens-power:monitoring-history";
3
+ var HISTORY_RETENTION = 10080 * 60 * 1e3;
4
+ var HISTORY_METRICS = [
5
+ "cpu",
6
+ "memory",
7
+ "cpuRequests",
8
+ "memoryRequests",
9
+ "cpuLimits",
10
+ "memoryLimits",
11
+ "cpuCapacity",
12
+ "memoryCapacity",
13
+ "cpuAllocatable",
14
+ "memoryAllocatable",
15
+ "restarts"
16
+ ];
17
+ function validHistoryIdentity(value) {
18
+ return !!value && [value.clusterId, value.uid].every((id) => typeof id === "string" && /^[a-zA-Z0-9_.:-]{1,128}$/.test(id)) && [
19
+ "cluster",
20
+ "node",
21
+ "pod",
22
+ "workload"
23
+ ].includes(value.scope);
24
+ }
25
+ function projectHistorySamples(input, now = Date.now()) {
26
+ if (!Array.isArray(input) || input.length > 512) throw new Error("Invalid history samples");
27
+ return input.map((sample) => {
28
+ if (!validHistoryIdentity(sample) || !Number.isSafeInteger(sample.time) || sample.time < now - 6048e5 || sample.time > now + 3e4 || !sample.values || typeof sample.values !== "object") throw new Error("Invalid history sample");
29
+ const values = {};
30
+ for (const metric of HISTORY_METRICS) {
31
+ const value = sample.values[metric];
32
+ if (value === void 0) continue;
33
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 0 || value > 1e30) throw new Error("Invalid history value");
34
+ values[metric] = value;
35
+ }
36
+ return {
37
+ clusterId: sample.clusterId,
38
+ scope: sample.scope,
39
+ uid: sample.uid,
40
+ time: sample.time,
41
+ values
42
+ };
43
+ });
44
+ }
45
+ //#endregion
46
+ exports.HISTORY_METRICS = HISTORY_METRICS;
47
+ exports.HISTORY_RETENTION = HISTORY_RETENTION;
48
+ exports.MONITORING_HISTORY_CHANNEL = MONITORING_HISTORY_CHANNEL;
49
+ exports.projectHistorySamples = projectHistorySamples;
50
+ exports.validHistoryIdentity = validHistoryIdentity;
51
+
52
+ //# sourceMappingURL=monitoring-history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monitoring-history.js","names":[],"sources":["../../../src/common/monitoring-history.ts"],"sourcesContent":["export const MONITORING_HISTORY_CHANNEL = \"freelens-power:monitoring-history\";\nexport const HISTORY_RETENTION = 7 * 24 * 60 * 60 * 1000;\nexport const HISTORY_MAX_BYTES = 100 * 1024 * 1024;\nexport type HistoryIdentity = {\n clusterId: string;\n scope: \"cluster\" | \"node\" | \"pod\" | \"workload\";\n uid: string;\n};\nexport const HISTORY_METRICS = [\n \"cpu\",\n \"memory\",\n \"cpuRequests\",\n \"memoryRequests\",\n \"cpuLimits\",\n \"memoryLimits\",\n \"cpuCapacity\",\n \"memoryCapacity\",\n \"cpuAllocatable\",\n \"memoryAllocatable\",\n \"restarts\",\n] as const;\nexport type HistoryMetric = (typeof HISTORY_METRICS)[number];\nexport type HistorySample = HistoryIdentity & { time: number; values: Partial<Record<HistoryMetric, number>> };\nexport type HistoryQuery = HistoryIdentity & { from: number; to: number };\nexport type HistoryPoint = {\n time: number;\n resolution: number;\n metric: HistoryMetric;\n min: number;\n avg: number;\n max: number;\n count: number;\n gap: boolean;\n};\nexport type HistoryStatus = { available: boolean; enabled: boolean; bytes: number; samples: number; error?: string };\nexport type HistoryRequest =\n | { operation: \"status\" | \"clear\" }\n | { operation: \"append\"; samples: HistorySample[] }\n | { operation: \"query\"; query: HistoryQuery };\nexport function validHistoryIdentity(value: HistoryIdentity): boolean {\n return (\n !!value &&\n [value.clusterId, value.uid].every((id) => typeof id === \"string\" && /^[a-zA-Z0-9_.:-]{1,128}$/.test(id)) &&\n [\"cluster\", \"node\", \"pod\", \"workload\"].includes(value.scope)\n );\n}\nexport function projectHistorySamples(input: unknown, now = Date.now()): HistorySample[] {\n if (!Array.isArray(input) || input.length > 512) throw new Error(\"Invalid history samples\");\n return input.map((sample) => {\n if (\n !validHistoryIdentity(sample) ||\n !Number.isSafeInteger(sample.time) ||\n sample.time < now - HISTORY_RETENTION ||\n sample.time > now + 30_000 ||\n !sample.values ||\n typeof sample.values !== \"object\"\n )\n throw new Error(\"Invalid history sample\");\n const values: HistorySample[\"values\"] = {};\n for (const metric of HISTORY_METRICS) {\n const value = sample.values[metric];\n if (value === undefined) continue;\n if (typeof value !== \"number\" || !Number.isFinite(value) || value < 0 || value > 1e30)\n throw new Error(\"Invalid history value\");\n values[metric] = value;\n }\n return { clusterId: sample.clusterId, scope: sample.scope, uid: sample.uid, time: sample.time, values };\n });\n}\n"],"mappings":";AAAA,IAAa,6BAA6B;AAC1C,IAAa,oBAAoB,QAAc,KAAK;AAOpD,IAAa,kBAAkB;CAC7B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAmBA,SAAgB,qBAAqB,OAAiC;CACpE,OACE,CAAC,CAAC,SACF,CAAC,MAAM,WAAW,MAAM,GAAG,CAAC,CAAC,OAAO,OAAO,OAAO,OAAO,YAAY,2BAA2B,KAAK,EAAE,CAAC,KACxG;EAAC;EAAW;EAAQ;EAAO;CAAU,CAAC,CAAC,SAAS,MAAM,KAAK;AAE/D;AACA,SAAgB,sBAAsB,OAAgB,MAAM,KAAK,IAAI,GAAoB;CACvF,IAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,MAAM,SAAS,KAAK,MAAM,IAAI,MAAM,yBAAyB;CAC1F,OAAO,MAAM,KAAK,WAAW;EAC3B,IACE,CAAC,qBAAqB,MAAM,KAC5B,CAAC,OAAO,cAAc,OAAO,IAAI,KACjC,OAAO,OAAO,MAAA,UACd,OAAO,OAAO,MAAM,OACpB,CAAC,OAAO,UACR,OAAO,OAAO,WAAW,UAEzB,MAAM,IAAI,MAAM,wBAAwB;EAC1C,MAAM,SAAkC,CAAC;EACzC,KAAK,MAAM,UAAU,iBAAiB;GACpC,MAAM,QAAQ,OAAO,OAAO;GAC5B,IAAI,UAAU,KAAA,GAAW;GACzB,IAAI,OAAO,UAAU,YAAY,CAAC,OAAO,SAAS,KAAK,KAAK,QAAQ,KAAK,QAAQ,MAC/E,MAAM,IAAI,MAAM,uBAAuB;GACzC,OAAO,UAAU;EACnB;EACA,OAAO;GAAE,WAAW,OAAO;GAAW,OAAO,OAAO;GAAO,KAAK,OAAO;GAAK,MAAM,OAAO;GAAM;EAAO;CACxG,CAAC;AACH"}
@@ -1,23 +1,46 @@
1
1
  const require_extensions = require("../../_virtual/_global-external_@freelensapp/extensions.js");
2
2
  const require__global_external_mobx = require("../../_virtual/_global-external_mobx.js");
3
+ const require_monitoring_history = require("../monitoring-history.js");
3
4
  //#region src/common/store/monitoring-preferences-store.ts
4
5
  var MonitoringPreferencesStore = class extends require_extensions.Common.Store.ExtensionStore {
5
6
  enabled = false;
7
+ historyEnabled = false;
8
+ trackedHistory = [];
6
9
  constructor() {
7
10
  super({
8
11
  configName: "monitoring-preferences",
9
- defaults: { enabled: false }
12
+ defaults: {
13
+ enabled: false,
14
+ historyEnabled: false,
15
+ trackedHistory: []
16
+ }
10
17
  });
11
18
  require__global_external_mobx.makeObservable(this, {
12
19
  enabled: require__global_external_mobx.observable,
20
+ historyEnabled: require__global_external_mobx.observable,
21
+ trackedHistory: require__global_external_mobx.observable,
13
22
  fromStore: require__global_external_mobx.action
14
23
  });
15
24
  }
16
25
  fromStore(data) {
17
26
  this.enabled = data?.enabled === true;
27
+ this.historyEnabled = data?.historyEnabled === true;
28
+ this.trackedHistory = Array.isArray(data?.trackedHistory) ? data.trackedHistory.filter(require_monitoring_history.validHistoryIdentity).slice(0, 100).map(({ clusterId, scope, uid }) => ({
29
+ clusterId,
30
+ scope,
31
+ uid
32
+ })) : [];
18
33
  }
19
34
  toJSON() {
20
- return { enabled: this.enabled };
35
+ return {
36
+ enabled: this.enabled,
37
+ historyEnabled: this.historyEnabled,
38
+ trackedHistory: this.trackedHistory.map(({ clusterId, scope, uid }) => ({
39
+ clusterId,
40
+ scope,
41
+ uid
42
+ }))
43
+ };
21
44
  }
22
45
  };
23
46
  //#endregion
@@ -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\";\n\nexport class MonitoringPreferencesStore extends Common.Store.ExtensionStore<{ enabled: boolean }> {\n enabled = false;\n\n constructor() {\n super({ configName: \"monitoring-preferences\", defaults: { enabled: false } });\n makeObservable(this, { enabled: observable, fromStore: action });\n }\n\n fromStore(data: { enabled?: boolean }): void {\n this.enabled = data?.enabled === true;\n }\n\n toJSON(): { enabled: boolean } {\n return { enabled: this.enabled };\n }\n}\n"],"mappings":";;;AAGA,IAAa,6BAAb,cAAgD,mBAAA,OAAO,MAAM,eAAqC;CAChG,UAAU;CAEV,cAAc;EACZ,MAAM;GAAE,YAAY;GAA0B,UAAU,EAAE,SAAS,MAAM;EAAE,CAAC;EAC5E,8BAAA,eAAe,MAAM;GAAE,SAAS,8BAAA;GAAY,WAAW,8BAAA;EAAO,CAAC;CACjE;CAEA,UAAU,MAAmC;EAC3C,KAAK,UAAU,MAAM,YAAY;CACnC;CAEA,SAA+B;EAC7B,OAAO,EAAE,SAAS,KAAK,QAAQ;CACjC;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 historyEnabled: boolean;\n trackedHistory: HistoryIdentity[];\n}> {\n enabled = false;\n historyEnabled = false;\n trackedHistory: HistoryIdentity[] = [];\n\n constructor() {\n super({\n configName: \"monitoring-preferences\",\n defaults: { enabled: false, historyEnabled: false, trackedHistory: [] },\n });\n makeObservable(this, {\n enabled: observable,\n historyEnabled: observable,\n trackedHistory: observable,\n fromStore: action,\n });\n }\n\n fromStore(data: { enabled?: boolean; historyEnabled?: boolean; trackedHistory?: HistoryIdentity[] }): void {\n this.enabled = data?.enabled === true;\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(): { enabled: boolean; historyEnabled: boolean; trackedHistory: HistoryIdentity[] } {\n return {\n enabled: this.enabled,\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,eAI1D;CACD,UAAU;CACV,iBAAiB;CACjB,iBAAoC,CAAC;CAErC,cAAc;EACZ,MAAM;GACJ,YAAY;GACZ,UAAU;IAAE,SAAS;IAAO,gBAAgB;IAAO,gBAAgB,CAAC;GAAE;EACxE,CAAC;EACD,8BAAA,eAAe,MAAM;GACnB,SAAS,8BAAA;GACT,gBAAgB,8BAAA;GAChB,gBAAgB,8BAAA;GAChB,WAAW,8BAAA;EACb,CAAC;CACH;CAEA,UAAU,MAAiG;EACzG,KAAK,UAAU,MAAM,YAAY;EACjC,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,SAA2F;EACzF,OAAO;GACL,SAAS,KAAK;GACd,gBAAgB,KAAK;GACrB,gBAAgB,KAAK,eAAe,KAAK,EAAE,WAAW,OAAO,WAAW;IAAE;IAAW;IAAO;GAAI,EAAE;EACpG;CACF;AACF"}
@@ -48,6 +48,26 @@ function rectangle(value) {
48
48
  height: rect.height
49
49
  };
50
50
  }
51
+ async function waitForReadiness(contents, network, selector, current) {
52
+ let deadline;
53
+ try {
54
+ await Promise.race([(async () => {
55
+ if (!current()) return;
56
+ await network.ready();
57
+ if (!current()) return;
58
+ await contents.executeJavaScriptInIsolatedWorld(1004, [{ code: require_dashboard_selector.dashboardSelectorScript(selector()) }]).catch(() => {});
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());
64
+ })().catch(() => new Promise((resolve) => setTimeout(resolve, 200))), new Promise((resolve) => {
65
+ deadline = setTimeout(resolve, 8500);
66
+ })]);
67
+ } finally {
68
+ clearTimeout(deadline);
69
+ }
70
+ }
51
71
  function startDashboardViews() {
52
72
  const websiteSession = electron.session.fromPartition("persist:freelens-power-websites");
53
73
  websiteSession.setPermissionRequestHandler((_contents, _permission, callback) => callback(false));
@@ -61,6 +81,7 @@ function startDashboardViews() {
61
81
  card.stopPreparation?.();
62
82
  card.faviconRequest?.abort();
63
83
  clearInterval(card.refreshTimer);
84
+ card.floatingPreparation?.stop();
64
85
  card.floating?.destroy();
65
86
  card.floating = void 0;
66
87
  if (!owner.window.isDestroyed()) owner.window.contentView.removeChildView(card.container);
@@ -149,25 +170,11 @@ function startDashboardViews() {
149
170
  return card.view.webContents.loadURL(target);
150
171
  };
151
172
  card.pending = load().then(async () => {
152
- let deadline;
153
173
  let preparing = true;
154
174
  const current = () => preparing && card.generation === generation && !card.view.webContents.isDestroyed() && [...owners.values()].some((owner) => [...owner.cards.values()].includes(card));
155
175
  try {
156
- await Promise.race([(async () => {
157
- if (!current()) return;
158
- await network.ready();
159
- if (!current()) return;
160
- await applySelector(card);
161
- do {
162
- await network.wait();
163
- if (!current()) return;
164
- await card.view.webContents.executeJavaScriptInIsolatedWorld(1004, [{ code: require_dashboard_readiness.dashboardReadinessScript(card.selector) }]);
165
- } while (current() && !network.quiet());
166
- })().catch(() => new Promise((resolve) => setTimeout(resolve, 200))), new Promise((resolve) => {
167
- deadline = setTimeout(resolve, 8500);
168
- })]);
176
+ await waitForReadiness(contents, network, () => card.selector, current);
169
177
  } finally {
170
- clearTimeout(deadline);
171
178
  preparing = false;
172
179
  stopPreparation();
173
180
  }
@@ -197,10 +204,7 @@ function startDashboardViews() {
197
204
  if (card.selector !== setting.selector) {
198
205
  card.selector = setting.selector;
199
206
  applySelector(card);
200
- if (card.floating && !card.floating.isDestroyed()) applySelector({
201
- view: { webContents: card.floating.webContents },
202
- selector: card.selector
203
- });
207
+ card.floatingPreparation?.selectorChanged();
204
208
  }
205
209
  if (card.floating && !card.floating.isDestroyed()) card.floating.setTitle(setting.title);
206
210
  if (!setting.autoRefresh) {
@@ -502,20 +506,123 @@ function startDashboardViews() {
502
506
  });
503
507
  contents.on("page-title-updated", (event) => event.preventDefault());
504
508
  contents.on("will-prevent-unload", (event) => event.preventDefault());
509
+ const skeleton = new electron.View();
510
+ skeleton.setBackgroundColor(electron.nativeTheme.shouldUseDarkColors ? "#202124" : "#ffffff");
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
+ });
518
+ const layoutSkeleton = () => {
519
+ const { width, height } = floating.getContentBounds();
520
+ skeleton.setBounds({
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
+ });
534
+ };
535
+ floating.contentView.addChildView(skeleton);
536
+ floating.on("resize", layoutSkeleton);
537
+ layoutSkeleton();
538
+ let generation = 0;
539
+ let stopPreparation = () => {};
540
+ let finishLoad;
541
+ const begin = () => {
542
+ stopPreparation();
543
+ const token = ++generation;
544
+ const backgroundThrottling = contents.getBackgroundThrottling();
545
+ if (backgroundThrottling) contents.setBackgroundThrottling(false);
546
+ const network = require_dashboard_network.observeDashboardNetwork(contents);
547
+ let active = true;
548
+ let finishing;
549
+ const current = () => active && generation === token && card.floating === floating && !contents.isDestroyed();
550
+ skeleton.setVisible(true);
551
+ stopPreparation = () => {
552
+ if (!active) return;
553
+ active = false;
554
+ network.dispose();
555
+ if (!contents.isDestroyed() && backgroundThrottling) contents.setBackgroundThrottling(true);
556
+ };
557
+ const stop = stopPreparation;
558
+ const finish = () => {
559
+ finishing ??= (async () => {
560
+ await waitForReadiness(contents, network, () => card.selector, current);
561
+ if (!current()) return false;
562
+ skeleton.setVisible(false);
563
+ stop();
564
+ return false;
565
+ })();
566
+ return finishing;
567
+ };
568
+ finishLoad = finish;
569
+ return {
570
+ finish,
571
+ fail: () => {
572
+ if (current()) {
573
+ skeleton.setVisible(false);
574
+ stop();
575
+ }
576
+ }
577
+ };
578
+ };
579
+ const refresh = () => {
580
+ const preparation = begin();
581
+ const current = contents.getURL();
582
+ return contents.loadURL(webUrl(current) ? current : configured.url).then(() => finishLoad?.() ?? false, () => {
583
+ preparation.fail();
584
+ return !contents.isDestroyed();
585
+ });
586
+ };
587
+ card.floatingPreparation = {
588
+ refresh,
589
+ selectorChanged: () => {
590
+ const preparation = begin();
591
+ if (!contents.isLoading()) preparation.finish();
592
+ },
593
+ stop: () => {
594
+ ++generation;
595
+ stopPreparation();
596
+ }
597
+ };
598
+ contents.on("did-start-navigation", (_event, _url, inPlace, mainFrame) => {
599
+ if (!mainFrame) return;
600
+ const preparation = begin();
601
+ if (inPlace) preparation.finish();
602
+ });
505
603
  contents.on("did-finish-load", () => {
506
604
  if (contents.isDestroyed()) return;
507
605
  contents.insertCSS(websiteStyles, { cssOrigin: "user" }).catch(() => {});
508
- applySelector({
509
- view: { webContents: contents },
510
- selector: card.selector
511
- });
606
+ finishLoad?.();
607
+ });
608
+ contents.on("did-fail-load", (_event, code, _description, _url, mainFrame) => {
609
+ if (!mainFrame || code === -3) return;
610
+ stopPreparation();
611
+ skeleton.setVisible(false);
612
+ });
613
+ contents.once("destroyed", () => {
614
+ ++generation;
615
+ stopPreparation();
512
616
  });
513
617
  floating.on("closed", () => {
514
618
  if (card.floating !== floating) return;
619
+ card.floatingPreparation?.stop();
620
+ card.floatingPreparation = void 0;
515
621
  card.floating = void 0;
516
622
  if (owner.cards.get(id) === card) publishPinned(event.sender, owner);
517
623
  });
518
- contents.loadURL(configured.url).catch(() => {});
624
+ const initial = begin();
625
+ contents.loadURL(configured.url).then(() => finishLoad?.(), initial.fail);
519
626
  floating.show();
520
627
  }
521
628
  publishPinned(event.sender, owner);
@@ -529,10 +636,7 @@ function startDashboardViews() {
529
636
  const card = owners.get(event.sender)?.cards.get(payload.id);
530
637
  const configured = require_dashboard.sanitizeDashboardCards(require_dashboard_preferences_store.DashboardPreferencesStore.getInstanceOrCreate().cards).find((item) => item.id === payload.id);
531
638
  if (!card || !configured || card.view.webContents.isDestroyed()) return;
532
- const floating = card.floating?.webContents;
533
- const current = floating?.getURL();
534
- const floatingReload = floating && !floating.isDestroyed() ? floating.loadURL(current && webUrl(current) ? current : configured.url).then(() => false, () => !floating.isDestroyed()) : Promise.resolve(false);
535
- const [, floatingFailed] = await Promise.all([reload(card, configured.url), floatingReload]);
639
+ const [, floatingFailed] = await Promise.all([reload(card, configured.url), card.floatingPreparation?.refresh() ?? Promise.resolve(false)]);
536
640
  return { failed: card.failed || floatingFailed ? [payload.id] : [] };
537
641
  });
538
642
  return () => {
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard-views.js","names":[],"sources":["../../src/main/dashboard-views.ts"],"sourcesContent":["// SPDX-License-Identifier: Apache-2.0\nimport { join } from \"node:path\";\nimport {\n app,\n BrowserWindow,\n type IpcMainInvokeEvent,\n ipcMain,\n type Rectangle,\n session,\n shell,\n View,\n type WebContents,\n WebContentsView,\n} from \"electron\";\nimport { reaction } from \"mobx\";\nimport { sanitizeDashboardCards } from \"../common/dashboard\";\nimport { dashboardReadinessScript } from \"../common/dashboard-readiness\";\nimport { dashboardSelectorScript } from \"../common/dashboard-selector\";\nimport {\n DASHBOARD_SITE_ICONS,\n DASHBOARD_VIEWS_LOADING,\n DASHBOARD_VIEWS_PIN,\n DASHBOARD_VIEWS_PINNED,\n type DashboardSiteIcon,\n} from \"../common/dashboard-views\";\nimport { DashboardPreferencesStore } from \"../common/store/dashboard-preferences-store\";\nimport { boundedDashboardIcons, loadDashboardIcons, saveDashboardIcons } from \"./dashboard-icon-cache\";\nimport { observeDashboardNetwork } from \"./dashboard-network\";\n\nconst syncChannel = \"freelens-power:dashboard-views:sync\";\nconst reloadChannel = \"freelens-power:dashboard-views:reload\";\nconst clearChannel = \"freelens-power:dashboard-views:clear\";\nconst dashboardPath = \"/extension/freelens-power/dashboard\";\nconst websiteStyles =\n \"* { scrollbar-width: none !important; } *::-webkit-scrollbar { display: none !important; width: 0 !important; height: 0 !important; }\";\n\nfunction rendererUrl(value: string, dashboardOnly = false): boolean {\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 (!dashboardOnly || url.pathname === dashboardPath)\n );\n } catch {\n return false;\n }\n}\nfunction dashboardUrl(value: string): boolean {\n return rendererUrl(value, true);\n}\nfunction webUrl(value: string): boolean {\n try {\n return [\"https:\", \"http:\"].includes(new URL(value).protocol);\n } catch {\n return false;\n }\n}\nfunction rectangle(value: unknown): Rectangle | undefined {\n if (!value || typeof value !== \"object\") return;\n const rect = value as Rectangle;\n if (\n ![rect.x, rect.y, rect.width, rect.height].every(\n (n) => Number.isFinite(n) && Number.isInteger(n) && Math.abs(n) <= 32768,\n ) ||\n rect.width <= 0 ||\n rect.height <= 0\n )\n return;\n return { x: rect.x, y: rect.y, width: rect.width, height: rect.height };\n}\n\ntype CardView = {\n container: View;\n view: WebContentsView;\n url: string;\n failed: boolean;\n loading: boolean;\n visible: boolean;\n generation: number;\n stopPreparation?: () => void;\n selector?: string;\n pending?: Promise<void>;\n favicon?: string;\n faviconRequest?: AbortController;\n refreshTimer?: ReturnType<typeof setInterval>;\n floating?: BrowserWindow;\n};\ntype Owner = { window: BrowserWindow; cards: Map<string, CardView>; cleanup: () => void };\n\nexport function startDashboardViews(): () => void {\n const websiteSession = session.fromPartition(\"persist:freelens-power-websites\");\n websiteSession.setPermissionRequestHandler((_contents, _permission, callback) => callback(false));\n websiteSession.setPermissionCheckHandler(() => false);\n const owners = new Map<WebContents, Owner>();\n const icons = new Map<string, DashboardSiteIcon>();\n const remove = (owner: Owner, id: string) => {\n const card = owner.cards.get(id);\n if (!card) return;\n owner.cards.delete(id);\n card.stopPreparation?.();\n card.faviconRequest?.abort();\n clearInterval(card.refreshTimer);\n card.floating?.destroy();\n card.floating = undefined;\n if (!owner.window.isDestroyed()) owner.window.contentView.removeChildView(card.container);\n if (!card.view.webContents.isDestroyed()) card.view.webContents.close();\n };\n const clear = (sender: WebContents) => {\n const owner = owners.get(sender);\n if (!owner) return;\n owners.delete(sender);\n for (const id of owner.cards.keys()) remove(owner, id);\n owner.cleanup();\n };\n const hide = (sender: WebContents) => {\n for (const card of owners.get(sender)?.cards.values() ?? []) {\n card.visible = false;\n card.container.setVisible(false);\n }\n };\n const configuredCards = () =>\n sanitizeDashboardCards(DashboardPreferencesStore.getInstanceOrCreate<DashboardPreferencesStore>().cards);\n const cachePath = join(app.getPath(\"userData\"), \"freelens-power\", \"dashboard-icons.json\");\n const ready = loadDashboardIcons(cachePath).then((saved) => {\n const configured = configuredCards();\n for (const icon of saved) {\n if (!icons.has(icon.id) && configured.some((card) => card.id === icon.id && card.url === icon.pageUrl))\n icons.set(icon.id, icon);\n }\n });\n let writes = ready;\n const persistIcons = () => {\n writes = writes\n .then(async () => {\n const configured = configuredCards();\n const bounded = boundedDashboardIcons(\n [...icons.values()].filter((icon) =>\n configured.some((card) => card.id === icon.id && card.url === icon.pageUrl),\n ),\n );\n icons.clear();\n for (const icon of bounded) icons.set(icon.id, icon);\n await saveDashboardIcons(cachePath, bounded);\n })\n .catch(() => {});\n };\n persistIcons();\n const publishLoading = (card: CardView) => {\n for (const [sender, owner] of owners) {\n const id = [...owner.cards].find(([, candidate]) => candidate === card)?.[0];\n if (\n !id ||\n sender.isDestroyed() ||\n !dashboardUrl(sender.mainFrame.url) ||\n !dashboardUrl(sender.getURL()) ||\n !configuredCards().some((configured) => configured.id === id && configured.url === card.url)\n )\n continue;\n sender.send(DASHBOARD_VIEWS_LOADING, { id, url: card.url, loading: card.loading, failed: card.failed });\n }\n };\n const reload = (card: CardView, configuredUrl: string, initial = false) => {\n const current = card.view.webContents.getURL();\n const target = !initial && card.url === configuredUrl && webUrl(current) ? current : configuredUrl;\n card.faviconRequest?.abort();\n card.url = configuredUrl;\n card.failed = false;\n card.loading = true;\n card.stopPreparation?.();\n const contents = card.view.webContents;\n const backgroundThrottling = contents.getBackgroundThrottling();\n if (backgroundThrottling) contents.setBackgroundThrottling(false);\n const network = observeDashboardNetwork(card.view.webContents);\n let stopped = false;\n const stopPreparation = () => {\n if (stopped) return;\n stopped = true;\n network.dispose();\n contents.removeListener(\"destroyed\", stopPreparation);\n if (!contents.isDestroyed() && backgroundThrottling && !contents.getBackgroundThrottling())\n contents.setBackgroundThrottling(backgroundThrottling);\n if (card.stopPreparation === stopPreparation) card.stopPreparation = undefined;\n };\n card.stopPreparation = stopPreparation;\n contents.once(\"destroyed\", stopPreparation);\n const generation = ++card.generation;\n card.container.setVisible(false);\n publishLoading(card);\n const settled = (failed: boolean) => {\n if (card.generation !== generation || card.view.webContents.isDestroyed()) return;\n card.failed = failed;\n card.loading = false;\n for (const [sender, owner] of owners) {\n if (![...owner.cards.values()].includes(card)) continue;\n card.container.setVisible(card.visible && !card.floating && !failed && dashboardUrl(sender.getURL()));\n }\n publishLoading(card);\n };\n const load = () => {\n if (\n card.generation !== generation ||\n card.view.webContents.isDestroyed() ||\n ![...owners.values()].some((owner) => [...owner.cards.values()].includes(card))\n )\n return Promise.resolve();\n return card.view.webContents.loadURL(target);\n };\n card.pending = load().then(\n async () => {\n let deadline: ReturnType<typeof setTimeout> | undefined;\n let preparing = true;\n const current = () =>\n preparing &&\n card.generation === generation &&\n !card.view.webContents.isDestroyed() &&\n [...owners.values()].some((owner) => [...owner.cards.values()].includes(card));\n try {\n await Promise.race([\n (async () => {\n if (!current()) return;\n await network.ready();\n if (!current()) return;\n await applySelector(card);\n do {\n await network.wait();\n if (!current()) return;\n await card.view.webContents.executeJavaScriptInIsolatedWorld(1004, [\n { code: dashboardReadinessScript(card.selector) },\n ]);\n } while (current() && !network.quiet());\n })().catch(() => new Promise<void>((resolve) => setTimeout(resolve, 200))),\n new Promise<void>((resolve) => {\n deadline = setTimeout(resolve, 8500);\n }),\n ]);\n } finally {\n clearTimeout(deadline);\n preparing = false;\n stopPreparation();\n }\n settled(false);\n },\n () => {\n stopPreparation();\n settled(true);\n },\n );\n return card.pending;\n };\n const applySelector = (card: { view: { webContents: WebContents }; selector?: string }) => {\n if (card.view.webContents.isDestroyed()) return Promise.resolve();\n return card.view.webContents\n .executeJavaScriptInIsolatedWorld(1004, [{ code: dashboardSelectorScript(card.selector) }])\n .catch(() => {});\n };\n const refreshTimers = () => {\n const configured = configuredCards();\n for (const [id, icon] of icons) {\n if (!configured.some((card) => card.id === id && card.url === icon.pageUrl)) {\n icons.delete(id);\n persistIcons();\n }\n }\n for (const [sender, owner] of owners) {\n for (const [id, card] of owner.cards) {\n const setting = configured.find((item) => item.id === id);\n if (!setting || setting.url !== card.url) {\n remove(owner, id);\n continue;\n }\n if (card.selector !== setting.selector) {\n card.selector = setting.selector;\n applySelector(card);\n if (card.floating && !card.floating.isDestroyed())\n applySelector({ view: { webContents: card.floating.webContents }, selector: card.selector });\n }\n if (card.floating && !card.floating.isDestroyed()) card.floating.setTitle(setting.title);\n if (!setting.autoRefresh) {\n clearInterval(card.refreshTimer);\n card.refreshTimer = undefined;\n continue;\n }\n if (card.refreshTimer) continue;\n card.refreshTimer = setInterval(() => {\n const latest = configuredCards().find((item) => item.id === id);\n if (\n owners.get(sender) !== owner ||\n card.floating ||\n dashboardUrl(sender.getURL()) ||\n owner.cards.get(id) !== card ||\n !latest?.autoRefresh ||\n latest.url !== card.url ||\n card.view.webContents.isDestroyed() ||\n card.view.webContents.isLoading()\n )\n return;\n void reload(card, latest.url);\n }, 600000);\n }\n }\n };\n const stopSettingsReaction = reaction(\n () =>\n JSON.stringify(\n configuredCards().map(({ id, title, url, autoRefresh, selector }) => ({\n id,\n title,\n url,\n autoRefresh,\n selector,\n })),\n ),\n refreshTimers,\n );\n const trusted = (event: IpcMainInvokeEvent) =>\n event.senderFrame === event.sender.mainFrame &&\n dashboardUrl(event.senderFrame?.url ?? \"\") &&\n dashboardUrl(event.sender.getURL());\n ipcMain.handle(DASHBOARD_SITE_ICONS, async (event) => {\n if (\n event.senderFrame !== event.sender.mainFrame ||\n !rendererUrl(event.senderFrame?.url ?? \"\") ||\n !rendererUrl(event.sender.getURL()) ||\n !BrowserWindow.fromWebContents(event.sender)\n )\n return [];\n await ready;\n return configuredCards().flatMap((card) => {\n const icon = icons.get(card.id);\n return icon?.pageUrl === card.url ? [icon] : [];\n });\n });\n ipcMain.handle(syncChannel, async (event, payload: unknown) => {\n if (!trusted(event)) return;\n const window = BrowserWindow.fromWebContents(event.sender);\n if (!window || window.isDestroyed()) return;\n const requested =\n payload && typeof payload === \"object\" && \"cards\" in payload && Array.isArray(payload.cards) ? payload.cards : [];\n const cards = sanitizeDashboardCards(\n DashboardPreferencesStore.getInstanceOrCreate<DashboardPreferencesStore>().cards,\n );\n let owner = owners.get(event.sender);\n if (!owner) {\n const sender = event.sender;\n const navigation = (_event: unknown, url: string) => {\n if (!dashboardUrl(url)) hide(sender);\n };\n const destroyed = () => clear(sender);\n sender.on(\"did-navigate\", navigation);\n sender.on(\"did-navigate-in-page\", navigation);\n sender.on(\"destroyed\", destroyed);\n owner = {\n window,\n cards: new Map(),\n cleanup: () => {\n sender.removeListener(\"did-navigate\", navigation);\n sender.removeListener(\"did-navigate-in-page\", navigation);\n sender.removeListener(\"destroyed\", destroyed);\n },\n };\n owners.set(sender, owner);\n }\n if (payload && typeof payload === \"object\" && \"hidden\" in payload && payload.hidden === true) {\n hide(event.sender);\n return { failed: [], pinned: [...owner.cards].filter(([, card]) => card.floating).map(([id]) => id) };\n }\n const visible = new Set<string>();\n for (const item of requested.slice(0, cards.length)) {\n if (!item || typeof item !== \"object\" || typeof item.id !== \"string\" || visible.has(item.id)) continue;\n const configured = cards.find((card) => card.id === item.id);\n const bounds = rectangle(item.bounds);\n const clip = rectangle(item.clip);\n if (\n !configured ||\n !bounds ||\n !clip ||\n clip.x < bounds.x ||\n clip.y < bounds.y ||\n clip.x + clip.width > bounds.x + bounds.width ||\n clip.y + clip.height > bounds.y + bounds.height\n )\n continue;\n visible.add(item.id);\n let card = owner.cards.get(item.id);\n if (card?.floating) {\n card.visible = false;\n card.container.setVisible(false);\n continue;\n }\n if (!card) {\n const container = new View();\n container.setBackgroundColor(\"#00000000\");\n const view = new WebContentsView({\n webPreferences: {\n nodeIntegration: false,\n nodeIntegrationInSubFrames: false,\n contextIsolation: true,\n sandbox: true,\n webSecurity: true,\n partition: \"persist:freelens-power-websites\",\n },\n });\n view.setBackgroundColor(\"#00000000\");\n view.webContents.on(\"did-finish-load\", () => {\n if (!view.webContents.isDestroyed())\n void view.webContents.insertCSS(websiteStyles, { cssOrigin: \"user\" }).catch(() => {});\n });\n view.webContents.setWindowOpenHandler(({ url }) => {\n if (webUrl(url)) void shell.openExternal(url).catch(() => {});\n return { action: \"deny\" };\n });\n const navigation = (event: Electron.Event, url: string) => {\n if (!webUrl(url)) event.preventDefault();\n };\n view.webContents.on(\"will-navigate\", navigation);\n view.webContents.on(\"will-redirect\", navigation);\n view.webContents.on(\"will-frame-navigate\", (event) => {\n if (!webUrl(event.url)) event.preventDefault();\n });\n container.addChildView(view);\n window.contentView.addChildView(container);\n card = { container, view, url: \"\", failed: false, loading: false, visible: false, generation: 0 };\n owner.cards.set(item.id, card);\n const created = card;\n view.webContents.on(\"before-input-event\", (_event, input: Electron.Input) => {\n if (\n input.type !== \"keyDown\" ||\n input.key !== \"Escape\" ||\n owners.get(event.sender) !== owner ||\n owner.cards.get(item.id) !== created ||\n !trusted(event)\n )\n return;\n event.sender.send(\"freelens-power:dashboard-escape\");\n });\n created.selector = configured.selector;\n view.webContents.on(\"did-finish-load\", () => applySelector(created));\n view.webContents.on(\"page-favicon-updated\", (_event, favicons: string[]) => {\n const favicon = favicons.find((value) => {\n if (!webUrl(value)) return false;\n const parsed = new URL(value);\n return !parsed.username && !parsed.password;\n });\n if (!favicon || owners.get(event.sender) !== owner || owner.cards.get(item.id) !== created) return;\n created.faviconRequest?.abort();\n const request = new AbortController();\n created.faviconRequest = request;\n created.favicon = favicon;\n const publish = (url: string) => {\n if (\n request.signal.aborted ||\n owners.get(event.sender) !== owner ||\n owner.cards.get(item.id) !== created ||\n event.senderFrame !== event.sender.mainFrame\n )\n return;\n created.favicon = url;\n if (\n url.startsWith(\"data:\") &&\n configuredCards().some((card) => card.id === item.id && card.url === created.url)\n ) {\n icons.set(item.id, { id: item.id, pageUrl: created.url, dataUrl: url });\n persistIcons();\n if (rendererUrl(event.senderFrame?.url ?? \"\") && rendererUrl(event.sender.getURL()))\n event.sender.send(DASHBOARD_SITE_ICONS);\n }\n if (!trusted(event)) return;\n event.sender.send(\"freelens-power:dashboard-site-icon\", { id: item.id, url });\n };\n publish(favicon);\n const timeout = setTimeout(() => request.abort(), 5000);\n void (async () => {\n let current = favicon;\n for (let redirects = 0; redirects <= 5; redirects++) {\n const response = await websiteSession.fetch(current, {\n signal: request.signal,\n redirect: \"manual\",\n credentials: \"include\",\n });\n if (response.status >= 300 && response.status < 400) {\n await response.body?.cancel();\n const location = response.headers.get(\"location\");\n if (!location) return;\n const next = new URL(location, current);\n if (!webUrl(next.href) || next.username || next.password) return;\n current = next.href;\n continue;\n }\n const mime = response.headers.get(\"content-type\")?.split(\";\")[0].trim().toLowerCase();\n if (\n !response.ok ||\n !mime ||\n ![\n \"image/png\",\n \"image/jpeg\",\n \"image/gif\",\n \"image/webp\",\n \"image/x-icon\",\n \"image/vnd.microsoft.icon\",\n \"image/svg+xml\",\n ].includes(mime) ||\n Number(response.headers.get(\"content-length\")) > 524288\n ) {\n await response.body?.cancel();\n return;\n }\n const reader = response.body?.getReader();\n if (!reader) return;\n const chunks: Uint8Array[] = [];\n let size = 0;\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n size += value.length;\n if (size > 524288) {\n await reader.cancel();\n return;\n }\n chunks.push(value);\n }\n if (size) publish(`data:${mime};base64,${Buffer.concat(chunks).toString(\"base64\")}`);\n return;\n }\n })()\n .catch(() => {})\n .finally(() => clearTimeout(timeout));\n });\n }\n card.visible = true;\n card.container.setVisible(!card.loading && !card.failed && card.url === configured.url);\n const zoom = event.sender.getZoomFactor();\n card.container.setBorderRadius(Math.round(12 * zoom));\n card.view.setBorderRadius(Math.round(12 * zoom));\n const scale = (rect: Rectangle): Rectangle => ({\n x: Math.round(rect.x * zoom),\n y: Math.round(rect.y * zoom),\n width: Math.round(rect.width * zoom),\n height: Math.round(rect.height * zoom),\n });\n card.container.setBounds(scale(clip));\n card.view.setBounds(\n scale({ x: bounds.x - clip.x, y: bounds.y - clip.y, width: bounds.width, height: bounds.height }),\n );\n if (card.url !== configured.url) {\n card.favicon = undefined;\n card.faviconRequest?.abort();\n void reload(card, configured.url, true);\n }\n publishLoading(card);\n if (card.favicon) event.sender.send(\"freelens-power:dashboard-site-icon\", { id: item.id, url: card.favicon });\n }\n for (const [id, card] of owner.cards) {\n if (!cards.some((configured) => configured.id === id)) remove(owner, id);\n else if (!visible.has(id)) {\n card.visible = false;\n card.container.setVisible(false);\n }\n }\n refreshTimers();\n await Promise.all([...owner.cards.values()].map((card) => card.pending));\n return {\n failed: [...owner.cards.entries()].filter(([, card]) => card.failed).map(([id]) => id),\n pinned: [...owner.cards].filter(([, card]) => card.floating).map(([id]) => id),\n };\n });\n const publishPinned = (sender: WebContents, owner: Owner) => {\n if (!sender.isDestroyed())\n sender.send(\n DASHBOARD_VIEWS_PINNED,\n [...owner.cards].filter(([, card]) => card.floating).map(([id]) => id),\n );\n };\n ipcMain.handle(DASHBOARD_VIEWS_PIN, (event, payload: unknown) => {\n if (\n !trusted(event) ||\n !payload ||\n typeof payload !== \"object\" ||\n !(\"id\" in payload) ||\n typeof payload.id !== \"string\" ||\n !((\"pinned\" in payload && typeof payload.pinned === \"boolean\") || (\"focus\" in payload && payload.focus === true))\n )\n return;\n const id = payload.id;\n const owner = owners.get(event.sender);\n const card = owner?.cards.get(payload.id);\n const configured = configuredCards().find((item) => item.id === payload.id);\n if (\n !owner ||\n !card ||\n !configured ||\n card.url !== configured.url ||\n owner.window.isDestroyed() ||\n BrowserWindow.fromWebContents(event.sender) !== owner.window ||\n card.view.webContents.isDestroyed()\n )\n return;\n if (\"focus\" in payload && payload.focus === true) {\n card.floating?.show();\n card.floating?.focus();\n } else if (!(\"pinned\" in payload) || !payload.pinned) {\n card.floating?.close();\n } else if (!card.floating) {\n const floating = new BrowserWindow({\n title: configured.title,\n width: 800,\n height: 600,\n minWidth: 240,\n minHeight: 160,\n resizable: true,\n alwaysOnTop: true,\n autoHideMenuBar: true,\n show: false,\n webPreferences: {\n nodeIntegration: false,\n nodeIntegrationInSubFrames: false,\n contextIsolation: true,\n sandbox: true,\n webSecurity: true,\n partition: \"persist:freelens-power-websites\",\n },\n });\n floating.setMenu(null);\n floating.setAlwaysOnTop(true, \"floating\");\n floating.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true });\n card.floating = floating;\n card.container.setVisible(false);\n const contents = floating.webContents;\n contents.setWindowOpenHandler(({ url }) => {\n if (webUrl(url)) void shell.openExternal(url).catch(() => {});\n return { action: \"deny\" };\n });\n const navigation = (event: Electron.Event, url: string) => {\n if (!webUrl(url)) event.preventDefault();\n };\n contents.on(\"will-navigate\", navigation);\n contents.on(\"will-redirect\", navigation);\n contents.on(\"will-frame-navigate\", (event) => {\n if (!webUrl(event.url)) event.preventDefault();\n });\n contents.on(\"page-title-updated\", (event) => event.preventDefault());\n contents.on(\"will-prevent-unload\", (event) => event.preventDefault());\n contents.on(\"did-finish-load\", () => {\n if (contents.isDestroyed()) return;\n void contents.insertCSS(websiteStyles, { cssOrigin: \"user\" }).catch(() => {});\n applySelector({ view: { webContents: contents }, selector: card.selector });\n });\n floating.on(\"closed\", () => {\n if (card.floating !== floating) return;\n card.floating = undefined;\n if (owner.cards.get(id) === card) publishPinned(event.sender, owner);\n });\n void contents.loadURL(configured.url).catch(() => {});\n floating.show();\n }\n publishPinned(event.sender, owner);\n return { pinned: [...owner.cards].filter(([, item]) => item.floating).map(([id]) => id) };\n });\n ipcMain.handle(clearChannel, (event) => {\n if (\n event.senderFrame === event.sender.mainFrame &&\n rendererUrl(event.senderFrame?.url ?? \"\") &&\n rendererUrl(event.sender.getURL())\n )\n hide(event.sender);\n });\n ipcMain.handle(reloadChannel, async (event, payload: unknown) => {\n if (\n !trusted(event) ||\n !payload ||\n typeof payload !== \"object\" ||\n !(\"id\" in payload) ||\n typeof payload.id !== \"string\"\n )\n return;\n const owner = owners.get(event.sender);\n const card = owner?.cards.get(payload.id);\n const configured = sanitizeDashboardCards(\n DashboardPreferencesStore.getInstanceOrCreate<DashboardPreferencesStore>().cards,\n ).find((item) => item.id === payload.id);\n if (!card || !configured || card.view.webContents.isDestroyed()) return;\n const floating = card.floating?.webContents;\n const current = floating?.getURL();\n const floatingReload =\n floating && !floating.isDestroyed()\n ? floating.loadURL(current && webUrl(current) ? current : configured.url).then(\n () => false,\n () => !floating.isDestroyed(),\n )\n : Promise.resolve(false);\n const [, floatingFailed] = await Promise.all([reload(card, configured.url), floatingReload]);\n return { failed: card.failed || floatingFailed ? [payload.id] : [] };\n });\n return () => {\n stopSettingsReaction();\n ipcMain.removeHandler(DASHBOARD_VIEWS_PIN);\n ipcMain.removeHandler(DASHBOARD_SITE_ICONS);\n ipcMain.removeHandler(syncChannel);\n ipcMain.removeHandler(clearChannel);\n ipcMain.removeHandler(reloadChannel);\n for (const sender of owners.keys()) clear(sender);\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"dashboard-views.js","names":[],"sources":["../../src/main/dashboard-views.ts"],"sourcesContent":["// SPDX-License-Identifier: Apache-2.0\nimport { join } from \"node:path\";\nimport {\n app,\n BrowserWindow,\n type IpcMainInvokeEvent,\n ipcMain,\n nativeTheme,\n type Rectangle,\n session,\n shell,\n View,\n type WebContents,\n WebContentsView,\n} from \"electron\";\nimport { reaction } from \"mobx\";\nimport { sanitizeDashboardCards } from \"../common/dashboard\";\nimport { dashboardReadinessScript } from \"../common/dashboard-readiness\";\nimport { dashboardSelectorScript } from \"../common/dashboard-selector\";\nimport {\n DASHBOARD_SITE_ICONS,\n DASHBOARD_VIEWS_LOADING,\n DASHBOARD_VIEWS_PIN,\n DASHBOARD_VIEWS_PINNED,\n type DashboardSiteIcon,\n} from \"../common/dashboard-views\";\nimport { DashboardPreferencesStore } from \"../common/store/dashboard-preferences-store\";\nimport { boundedDashboardIcons, loadDashboardIcons, saveDashboardIcons } from \"./dashboard-icon-cache\";\nimport { observeDashboardNetwork } from \"./dashboard-network\";\n\nconst syncChannel = \"freelens-power:dashboard-views:sync\";\nconst reloadChannel = \"freelens-power:dashboard-views:reload\";\nconst clearChannel = \"freelens-power:dashboard-views:clear\";\nconst dashboardPath = \"/extension/freelens-power/dashboard\";\nconst websiteStyles =\n \"* { scrollbar-width: none !important; } *::-webkit-scrollbar { display: none !important; width: 0 !important; height: 0 !important; }\";\n\nfunction rendererUrl(value: string, dashboardOnly = false): boolean {\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 (!dashboardOnly || url.pathname === dashboardPath)\n );\n } catch {\n return false;\n }\n}\nfunction dashboardUrl(value: string): boolean {\n return rendererUrl(value, true);\n}\nfunction webUrl(value: string): boolean {\n try {\n return [\"https:\", \"http:\"].includes(new URL(value).protocol);\n } catch {\n return false;\n }\n}\nfunction rectangle(value: unknown): Rectangle | undefined {\n if (!value || typeof value !== \"object\") return;\n const rect = value as Rectangle;\n if (\n ![rect.x, rect.y, rect.width, rect.height].every(\n (n) => Number.isFinite(n) && Number.isInteger(n) && Math.abs(n) <= 32768,\n ) ||\n rect.width <= 0 ||\n rect.height <= 0\n )\n return;\n return { x: rect.x, y: rect.y, width: rect.width, height: rect.height };\n}\n\ntype CardView = {\n container: View;\n view: WebContentsView;\n url: string;\n failed: boolean;\n loading: boolean;\n visible: boolean;\n generation: number;\n stopPreparation?: () => void;\n selector?: string;\n pending?: Promise<void>;\n favicon?: string;\n faviconRequest?: AbortController;\n refreshTimer?: ReturnType<typeof setInterval>;\n floating?: BrowserWindow;\n floatingPreparation?: { refresh: () => Promise<boolean>; selectorChanged: () => void; stop: () => void };\n};\ntype Owner = { window: BrowserWindow; cards: Map<string, CardView>; cleanup: () => void };\n\nasync function waitForReadiness(\n contents: WebContents,\n network: ReturnType<typeof observeDashboardNetwork>,\n selector: () => string | undefined,\n current: () => boolean,\n): Promise<void> {\n let deadline: ReturnType<typeof setTimeout> | undefined;\n try {\n await Promise.race([\n (async () => {\n if (!current()) return;\n await network.ready();\n if (!current()) return;\n await contents\n .executeJavaScriptInIsolatedWorld(1004, [{ code: dashboardSelectorScript(selector()) }])\n .catch(() => {});\n do {\n await network.wait();\n if (!current()) return;\n await contents.executeJavaScriptInIsolatedWorld(1004, [{ code: dashboardReadinessScript(selector()) }]);\n } while (current() && !network.quiet());\n })().catch(() => new Promise<void>((resolve) => setTimeout(resolve, 200))),\n new Promise<void>((resolve) => {\n deadline = setTimeout(resolve, 8500);\n }),\n ]);\n } finally {\n clearTimeout(deadline);\n }\n}\n\nexport function startDashboardViews(): () => void {\n const websiteSession = session.fromPartition(\"persist:freelens-power-websites\");\n websiteSession.setPermissionRequestHandler((_contents, _permission, callback) => callback(false));\n websiteSession.setPermissionCheckHandler(() => false);\n const owners = new Map<WebContents, Owner>();\n const icons = new Map<string, DashboardSiteIcon>();\n const remove = (owner: Owner, id: string) => {\n const card = owner.cards.get(id);\n if (!card) return;\n owner.cards.delete(id);\n card.stopPreparation?.();\n card.faviconRequest?.abort();\n clearInterval(card.refreshTimer);\n card.floatingPreparation?.stop();\n card.floating?.destroy();\n card.floating = undefined;\n if (!owner.window.isDestroyed()) owner.window.contentView.removeChildView(card.container);\n if (!card.view.webContents.isDestroyed()) card.view.webContents.close();\n };\n const clear = (sender: WebContents) => {\n const owner = owners.get(sender);\n if (!owner) return;\n owners.delete(sender);\n for (const id of owner.cards.keys()) remove(owner, id);\n owner.cleanup();\n };\n const hide = (sender: WebContents) => {\n for (const card of owners.get(sender)?.cards.values() ?? []) {\n card.visible = false;\n card.container.setVisible(false);\n }\n };\n const configuredCards = () =>\n sanitizeDashboardCards(DashboardPreferencesStore.getInstanceOrCreate<DashboardPreferencesStore>().cards);\n const cachePath = join(app.getPath(\"userData\"), \"freelens-power\", \"dashboard-icons.json\");\n const ready = loadDashboardIcons(cachePath).then((saved) => {\n const configured = configuredCards();\n for (const icon of saved) {\n if (!icons.has(icon.id) && configured.some((card) => card.id === icon.id && card.url === icon.pageUrl))\n icons.set(icon.id, icon);\n }\n });\n let writes = ready;\n const persistIcons = () => {\n writes = writes\n .then(async () => {\n const configured = configuredCards();\n const bounded = boundedDashboardIcons(\n [...icons.values()].filter((icon) =>\n configured.some((card) => card.id === icon.id && card.url === icon.pageUrl),\n ),\n );\n icons.clear();\n for (const icon of bounded) icons.set(icon.id, icon);\n await saveDashboardIcons(cachePath, bounded);\n })\n .catch(() => {});\n };\n persistIcons();\n const publishLoading = (card: CardView) => {\n for (const [sender, owner] of owners) {\n const id = [...owner.cards].find(([, candidate]) => candidate === card)?.[0];\n if (\n !id ||\n sender.isDestroyed() ||\n !dashboardUrl(sender.mainFrame.url) ||\n !dashboardUrl(sender.getURL()) ||\n !configuredCards().some((configured) => configured.id === id && configured.url === card.url)\n )\n continue;\n sender.send(DASHBOARD_VIEWS_LOADING, { id, url: card.url, loading: card.loading, failed: card.failed });\n }\n };\n const reload = (card: CardView, configuredUrl: string, initial = false) => {\n const current = card.view.webContents.getURL();\n const target = !initial && card.url === configuredUrl && webUrl(current) ? current : configuredUrl;\n card.faviconRequest?.abort();\n card.url = configuredUrl;\n card.failed = false;\n card.loading = true;\n card.stopPreparation?.();\n const contents = card.view.webContents;\n const backgroundThrottling = contents.getBackgroundThrottling();\n if (backgroundThrottling) contents.setBackgroundThrottling(false);\n const network = observeDashboardNetwork(card.view.webContents);\n let stopped = false;\n const stopPreparation = () => {\n if (stopped) return;\n stopped = true;\n network.dispose();\n contents.removeListener(\"destroyed\", stopPreparation);\n if (!contents.isDestroyed() && backgroundThrottling && !contents.getBackgroundThrottling())\n contents.setBackgroundThrottling(backgroundThrottling);\n if (card.stopPreparation === stopPreparation) card.stopPreparation = undefined;\n };\n card.stopPreparation = stopPreparation;\n contents.once(\"destroyed\", stopPreparation);\n const generation = ++card.generation;\n card.container.setVisible(false);\n publishLoading(card);\n const settled = (failed: boolean) => {\n if (card.generation !== generation || card.view.webContents.isDestroyed()) return;\n card.failed = failed;\n card.loading = false;\n for (const [sender, owner] of owners) {\n if (![...owner.cards.values()].includes(card)) continue;\n card.container.setVisible(card.visible && !card.floating && !failed && dashboardUrl(sender.getURL()));\n }\n publishLoading(card);\n };\n const load = () => {\n if (\n card.generation !== generation ||\n card.view.webContents.isDestroyed() ||\n ![...owners.values()].some((owner) => [...owner.cards.values()].includes(card))\n )\n return Promise.resolve();\n return card.view.webContents.loadURL(target);\n };\n card.pending = load().then(\n async () => {\n let preparing = true;\n const current = () =>\n preparing &&\n card.generation === generation &&\n !card.view.webContents.isDestroyed() &&\n [...owners.values()].some((owner) => [...owner.cards.values()].includes(card));\n try {\n await waitForReadiness(contents, network, () => card.selector, current);\n } finally {\n preparing = false;\n stopPreparation();\n }\n settled(false);\n },\n () => {\n stopPreparation();\n settled(true);\n },\n );\n return card.pending;\n };\n const applySelector = (card: { view: { webContents: WebContents }; selector?: string }) => {\n if (card.view.webContents.isDestroyed()) return Promise.resolve();\n return card.view.webContents\n .executeJavaScriptInIsolatedWorld(1004, [{ code: dashboardSelectorScript(card.selector) }])\n .catch(() => {});\n };\n const refreshTimers = () => {\n const configured = configuredCards();\n for (const [id, icon] of icons) {\n if (!configured.some((card) => card.id === id && card.url === icon.pageUrl)) {\n icons.delete(id);\n persistIcons();\n }\n }\n for (const [sender, owner] of owners) {\n for (const [id, card] of owner.cards) {\n const setting = configured.find((item) => item.id === id);\n if (!setting || setting.url !== card.url) {\n remove(owner, id);\n continue;\n }\n if (card.selector !== setting.selector) {\n card.selector = setting.selector;\n applySelector(card);\n card.floatingPreparation?.selectorChanged();\n }\n if (card.floating && !card.floating.isDestroyed()) card.floating.setTitle(setting.title);\n if (!setting.autoRefresh) {\n clearInterval(card.refreshTimer);\n card.refreshTimer = undefined;\n continue;\n }\n if (card.refreshTimer) continue;\n card.refreshTimer = setInterval(() => {\n const latest = configuredCards().find((item) => item.id === id);\n if (\n owners.get(sender) !== owner ||\n card.floating ||\n dashboardUrl(sender.getURL()) ||\n owner.cards.get(id) !== card ||\n !latest?.autoRefresh ||\n latest.url !== card.url ||\n card.view.webContents.isDestroyed() ||\n card.view.webContents.isLoading()\n )\n return;\n void reload(card, latest.url);\n }, 600000);\n }\n }\n };\n const stopSettingsReaction = reaction(\n () =>\n JSON.stringify(\n configuredCards().map(({ id, title, url, autoRefresh, selector }) => ({\n id,\n title,\n url,\n autoRefresh,\n selector,\n })),\n ),\n refreshTimers,\n );\n const trusted = (event: IpcMainInvokeEvent) =>\n event.senderFrame === event.sender.mainFrame &&\n dashboardUrl(event.senderFrame?.url ?? \"\") &&\n dashboardUrl(event.sender.getURL());\n ipcMain.handle(DASHBOARD_SITE_ICONS, async (event) => {\n if (\n event.senderFrame !== event.sender.mainFrame ||\n !rendererUrl(event.senderFrame?.url ?? \"\") ||\n !rendererUrl(event.sender.getURL()) ||\n !BrowserWindow.fromWebContents(event.sender)\n )\n return [];\n await ready;\n return configuredCards().flatMap((card) => {\n const icon = icons.get(card.id);\n return icon?.pageUrl === card.url ? [icon] : [];\n });\n });\n ipcMain.handle(syncChannel, async (event, payload: unknown) => {\n if (!trusted(event)) return;\n const window = BrowserWindow.fromWebContents(event.sender);\n if (!window || window.isDestroyed()) return;\n const requested =\n payload && typeof payload === \"object\" && \"cards\" in payload && Array.isArray(payload.cards) ? payload.cards : [];\n const cards = sanitizeDashboardCards(\n DashboardPreferencesStore.getInstanceOrCreate<DashboardPreferencesStore>().cards,\n );\n let owner = owners.get(event.sender);\n if (!owner) {\n const sender = event.sender;\n const navigation = (_event: unknown, url: string) => {\n if (!dashboardUrl(url)) hide(sender);\n };\n const destroyed = () => clear(sender);\n sender.on(\"did-navigate\", navigation);\n sender.on(\"did-navigate-in-page\", navigation);\n sender.on(\"destroyed\", destroyed);\n owner = {\n window,\n cards: new Map(),\n cleanup: () => {\n sender.removeListener(\"did-navigate\", navigation);\n sender.removeListener(\"did-navigate-in-page\", navigation);\n sender.removeListener(\"destroyed\", destroyed);\n },\n };\n owners.set(sender, owner);\n }\n if (payload && typeof payload === \"object\" && \"hidden\" in payload && payload.hidden === true) {\n hide(event.sender);\n return { failed: [], pinned: [...owner.cards].filter(([, card]) => card.floating).map(([id]) => id) };\n }\n const visible = new Set<string>();\n for (const item of requested.slice(0, cards.length)) {\n if (!item || typeof item !== \"object\" || typeof item.id !== \"string\" || visible.has(item.id)) continue;\n const configured = cards.find((card) => card.id === item.id);\n const bounds = rectangle(item.bounds);\n const clip = rectangle(item.clip);\n if (\n !configured ||\n !bounds ||\n !clip ||\n clip.x < bounds.x ||\n clip.y < bounds.y ||\n clip.x + clip.width > bounds.x + bounds.width ||\n clip.y + clip.height > bounds.y + bounds.height\n )\n continue;\n visible.add(item.id);\n let card = owner.cards.get(item.id);\n if (card?.floating) {\n card.visible = false;\n card.container.setVisible(false);\n continue;\n }\n if (!card) {\n const container = new View();\n container.setBackgroundColor(\"#00000000\");\n const view = new WebContentsView({\n webPreferences: {\n nodeIntegration: false,\n nodeIntegrationInSubFrames: false,\n contextIsolation: true,\n sandbox: true,\n webSecurity: true,\n partition: \"persist:freelens-power-websites\",\n },\n });\n view.setBackgroundColor(\"#00000000\");\n view.webContents.on(\"did-finish-load\", () => {\n if (!view.webContents.isDestroyed())\n void view.webContents.insertCSS(websiteStyles, { cssOrigin: \"user\" }).catch(() => {});\n });\n view.webContents.setWindowOpenHandler(({ url }) => {\n if (webUrl(url)) void shell.openExternal(url).catch(() => {});\n return { action: \"deny\" };\n });\n const navigation = (event: Electron.Event, url: string) => {\n if (!webUrl(url)) event.preventDefault();\n };\n view.webContents.on(\"will-navigate\", navigation);\n view.webContents.on(\"will-redirect\", navigation);\n view.webContents.on(\"will-frame-navigate\", (event) => {\n if (!webUrl(event.url)) event.preventDefault();\n });\n container.addChildView(view);\n window.contentView.addChildView(container);\n card = { container, view, url: \"\", failed: false, loading: false, visible: false, generation: 0 };\n owner.cards.set(item.id, card);\n const created = card;\n view.webContents.on(\"before-input-event\", (_event, input: Electron.Input) => {\n if (\n input.type !== \"keyDown\" ||\n input.key !== \"Escape\" ||\n owners.get(event.sender) !== owner ||\n owner.cards.get(item.id) !== created ||\n !trusted(event)\n )\n return;\n event.sender.send(\"freelens-power:dashboard-escape\");\n });\n created.selector = configured.selector;\n view.webContents.on(\"did-finish-load\", () => applySelector(created));\n view.webContents.on(\"page-favicon-updated\", (_event, favicons: string[]) => {\n const favicon = favicons.find((value) => {\n if (!webUrl(value)) return false;\n const parsed = new URL(value);\n return !parsed.username && !parsed.password;\n });\n if (!favicon || owners.get(event.sender) !== owner || owner.cards.get(item.id) !== created) return;\n created.faviconRequest?.abort();\n const request = new AbortController();\n created.faviconRequest = request;\n created.favicon = favicon;\n const publish = (url: string) => {\n if (\n request.signal.aborted ||\n owners.get(event.sender) !== owner ||\n owner.cards.get(item.id) !== created ||\n event.senderFrame !== event.sender.mainFrame\n )\n return;\n created.favicon = url;\n if (\n url.startsWith(\"data:\") &&\n configuredCards().some((card) => card.id === item.id && card.url === created.url)\n ) {\n icons.set(item.id, { id: item.id, pageUrl: created.url, dataUrl: url });\n persistIcons();\n if (rendererUrl(event.senderFrame?.url ?? \"\") && rendererUrl(event.sender.getURL()))\n event.sender.send(DASHBOARD_SITE_ICONS);\n }\n if (!trusted(event)) return;\n event.sender.send(\"freelens-power:dashboard-site-icon\", { id: item.id, url });\n };\n publish(favicon);\n const timeout = setTimeout(() => request.abort(), 5000);\n void (async () => {\n let current = favicon;\n for (let redirects = 0; redirects <= 5; redirects++) {\n const response = await websiteSession.fetch(current, {\n signal: request.signal,\n redirect: \"manual\",\n credentials: \"include\",\n });\n if (response.status >= 300 && response.status < 400) {\n await response.body?.cancel();\n const location = response.headers.get(\"location\");\n if (!location) return;\n const next = new URL(location, current);\n if (!webUrl(next.href) || next.username || next.password) return;\n current = next.href;\n continue;\n }\n const mime = response.headers.get(\"content-type\")?.split(\";\")[0].trim().toLowerCase();\n if (\n !response.ok ||\n !mime ||\n ![\n \"image/png\",\n \"image/jpeg\",\n \"image/gif\",\n \"image/webp\",\n \"image/x-icon\",\n \"image/vnd.microsoft.icon\",\n \"image/svg+xml\",\n ].includes(mime) ||\n Number(response.headers.get(\"content-length\")) > 524288\n ) {\n await response.body?.cancel();\n return;\n }\n const reader = response.body?.getReader();\n if (!reader) return;\n const chunks: Uint8Array[] = [];\n let size = 0;\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n size += value.length;\n if (size > 524288) {\n await reader.cancel();\n return;\n }\n chunks.push(value);\n }\n if (size) publish(`data:${mime};base64,${Buffer.concat(chunks).toString(\"base64\")}`);\n return;\n }\n })()\n .catch(() => {})\n .finally(() => clearTimeout(timeout));\n });\n }\n card.visible = true;\n card.container.setVisible(!card.loading && !card.failed && card.url === configured.url);\n const zoom = event.sender.getZoomFactor();\n card.container.setBorderRadius(Math.round(12 * zoom));\n card.view.setBorderRadius(Math.round(12 * zoom));\n const scale = (rect: Rectangle): Rectangle => ({\n x: Math.round(rect.x * zoom),\n y: Math.round(rect.y * zoom),\n width: Math.round(rect.width * zoom),\n height: Math.round(rect.height * zoom),\n });\n card.container.setBounds(scale(clip));\n card.view.setBounds(\n scale({ x: bounds.x - clip.x, y: bounds.y - clip.y, width: bounds.width, height: bounds.height }),\n );\n if (card.url !== configured.url) {\n card.favicon = undefined;\n card.faviconRequest?.abort();\n void reload(card, configured.url, true);\n }\n publishLoading(card);\n if (card.favicon) event.sender.send(\"freelens-power:dashboard-site-icon\", { id: item.id, url: card.favicon });\n }\n for (const [id, card] of owner.cards) {\n if (!cards.some((configured) => configured.id === id)) remove(owner, id);\n else if (!visible.has(id)) {\n card.visible = false;\n card.container.setVisible(false);\n }\n }\n refreshTimers();\n await Promise.all([...owner.cards.values()].map((card) => card.pending));\n return {\n failed: [...owner.cards.entries()].filter(([, card]) => card.failed).map(([id]) => id),\n pinned: [...owner.cards].filter(([, card]) => card.floating).map(([id]) => id),\n };\n });\n const publishPinned = (sender: WebContents, owner: Owner) => {\n if (!sender.isDestroyed())\n sender.send(\n DASHBOARD_VIEWS_PINNED,\n [...owner.cards].filter(([, card]) => card.floating).map(([id]) => id),\n );\n };\n ipcMain.handle(DASHBOARD_VIEWS_PIN, (event, payload: unknown) => {\n if (\n !trusted(event) ||\n !payload ||\n typeof payload !== \"object\" ||\n !(\"id\" in payload) ||\n typeof payload.id !== \"string\" ||\n !((\"pinned\" in payload && typeof payload.pinned === \"boolean\") || (\"focus\" in payload && payload.focus === true))\n )\n return;\n const id = payload.id;\n const owner = owners.get(event.sender);\n const card = owner?.cards.get(payload.id);\n const configured = configuredCards().find((item) => item.id === payload.id);\n if (\n !owner ||\n !card ||\n !configured ||\n card.url !== configured.url ||\n owner.window.isDestroyed() ||\n BrowserWindow.fromWebContents(event.sender) !== owner.window ||\n card.view.webContents.isDestroyed()\n )\n return;\n if (\"focus\" in payload && payload.focus === true) {\n card.floating?.show();\n card.floating?.focus();\n } else if (!(\"pinned\" in payload) || !payload.pinned) {\n card.floating?.close();\n } else if (!card.floating) {\n const floating = new BrowserWindow({\n title: configured.title,\n width: 800,\n height: 600,\n minWidth: 240,\n minHeight: 160,\n resizable: true,\n alwaysOnTop: true,\n autoHideMenuBar: true,\n show: false,\n webPreferences: {\n nodeIntegration: false,\n nodeIntegrationInSubFrames: false,\n contextIsolation: true,\n sandbox: true,\n webSecurity: true,\n partition: \"persist:freelens-power-websites\",\n },\n });\n floating.setMenu(null);\n floating.setAlwaysOnTop(true, \"floating\");\n floating.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true });\n card.floating = floating;\n card.container.setVisible(false);\n const contents = floating.webContents;\n contents.setWindowOpenHandler(({ url }) => {\n if (webUrl(url)) void shell.openExternal(url).catch(() => {});\n return { action: \"deny\" };\n });\n const navigation = (event: Electron.Event, url: string) => {\n if (!webUrl(url)) event.preventDefault();\n };\n contents.on(\"will-navigate\", navigation);\n contents.on(\"will-redirect\", navigation);\n contents.on(\"will-frame-navigate\", (event) => {\n if (!webUrl(event.url)) event.preventDefault();\n });\n contents.on(\"page-title-updated\", (event) => event.preventDefault());\n contents.on(\"will-prevent-unload\", (event) => event.preventDefault());\n const skeleton = new View();\n skeleton.setBackgroundColor(nativeTheme.shouldUseDarkColors ? \"#202124\" : \"#ffffff\");\n const bars = Array.from({ length: 4 }, () => {\n const bar = new View();\n bar.setBackgroundColor(nativeTheme.shouldUseDarkColors ? \"#393b40\" : \"#e8e9eb\");\n bar.setBorderRadius(6);\n skeleton.addChildView(bar);\n return bar;\n });\n const layoutSkeleton = () => {\n const { width, height } = floating.getContentBounds();\n skeleton.setBounds({ x: 0, y: 0, width, height });\n bars.forEach((bar, index) => {\n bar.setBounds({\n x: 20,\n y: index === 0 ? 20 : 60 + (index - 1) * 24,\n width: Math.max(1, Math.round((width - 40) * (index === 0 ? 0.45 : 1))),\n height: index === 0 ? 20 : index === 3 ? Math.max(30, height - 128) : 12,\n });\n });\n };\n floating.contentView.addChildView(skeleton);\n floating.on(\"resize\", layoutSkeleton);\n layoutSkeleton();\n let generation = 0;\n let stopPreparation = () => {};\n let finishLoad: (() => Promise<boolean>) | undefined;\n const begin = () => {\n stopPreparation();\n const token = ++generation;\n const backgroundThrottling = contents.getBackgroundThrottling();\n if (backgroundThrottling) contents.setBackgroundThrottling(false);\n const network = observeDashboardNetwork(contents);\n let active = true;\n let finishing: Promise<boolean> | undefined;\n const current = () => active && generation === token && card.floating === floating && !contents.isDestroyed();\n skeleton.setVisible(true);\n stopPreparation = () => {\n if (!active) return;\n active = false;\n network.dispose();\n if (!contents.isDestroyed() && backgroundThrottling) contents.setBackgroundThrottling(true);\n };\n const stop = stopPreparation;\n const finish = () => {\n finishing ??= (async () => {\n await waitForReadiness(contents, network, () => card.selector, current);\n if (!current()) return false;\n skeleton.setVisible(false);\n stop();\n return false;\n })();\n return finishing;\n };\n finishLoad = finish;\n return {\n finish,\n fail: () => {\n if (current()) {\n skeleton.setVisible(false);\n stop();\n }\n },\n };\n };\n const refresh = () => {\n const preparation = begin();\n const current = contents.getURL();\n return contents.loadURL(webUrl(current) ? current : configured.url).then(\n () => finishLoad?.() ?? false,\n () => {\n preparation.fail();\n return !contents.isDestroyed();\n },\n );\n };\n card.floatingPreparation = {\n refresh,\n selectorChanged: () => {\n const preparation = begin();\n if (!contents.isLoading()) void preparation.finish();\n },\n stop: () => {\n ++generation;\n stopPreparation();\n },\n };\n contents.on(\"did-start-navigation\", (_event, _url, inPlace, mainFrame) => {\n if (!mainFrame) return;\n const preparation = begin();\n if (inPlace) void preparation.finish();\n });\n contents.on(\"did-finish-load\", () => {\n if (contents.isDestroyed()) return;\n void contents.insertCSS(websiteStyles, { cssOrigin: \"user\" }).catch(() => {});\n void finishLoad?.();\n });\n contents.on(\"did-fail-load\", (_event, code, _description, _url, mainFrame) => {\n if (!mainFrame || code === -3) return;\n stopPreparation();\n skeleton.setVisible(false);\n });\n contents.once(\"destroyed\", () => {\n ++generation;\n stopPreparation();\n });\n floating.on(\"closed\", () => {\n if (card.floating !== floating) return;\n card.floatingPreparation?.stop();\n card.floatingPreparation = undefined;\n card.floating = undefined;\n if (owner.cards.get(id) === card) publishPinned(event.sender, owner);\n });\n const initial = begin();\n void contents.loadURL(configured.url).then(() => finishLoad?.(), initial.fail);\n floating.show();\n }\n publishPinned(event.sender, owner);\n return { pinned: [...owner.cards].filter(([, item]) => item.floating).map(([id]) => id) };\n });\n ipcMain.handle(clearChannel, (event) => {\n if (\n event.senderFrame === event.sender.mainFrame &&\n rendererUrl(event.senderFrame?.url ?? \"\") &&\n rendererUrl(event.sender.getURL())\n )\n hide(event.sender);\n });\n ipcMain.handle(reloadChannel, async (event, payload: unknown) => {\n if (\n !trusted(event) ||\n !payload ||\n typeof payload !== \"object\" ||\n !(\"id\" in payload) ||\n typeof payload.id !== \"string\"\n )\n return;\n const owner = owners.get(event.sender);\n const card = owner?.cards.get(payload.id);\n const configured = sanitizeDashboardCards(\n DashboardPreferencesStore.getInstanceOrCreate<DashboardPreferencesStore>().cards,\n ).find((item) => item.id === payload.id);\n if (!card || !configured || card.view.webContents.isDestroyed()) return;\n const [, floatingFailed] = await Promise.all([\n reload(card, configured.url),\n card.floatingPreparation?.refresh() ?? Promise.resolve(false),\n ]);\n return { failed: card.failed || floatingFailed ? [payload.id] : [] };\n });\n return () => {\n stopSettingsReaction();\n ipcMain.removeHandler(DASHBOARD_VIEWS_PIN);\n ipcMain.removeHandler(DASHBOARD_SITE_ICONS);\n ipcMain.removeHandler(syncChannel);\n ipcMain.removeHandler(clearChannel);\n ipcMain.removeHandler(reloadChannel);\n for (const sender of owners.keys()) clear(sender);\n };\n}\n"],"mappings":"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"}
package/out/main/index.js CHANGED
@@ -19,6 +19,7 @@ const require_dashboard_catalog = require("./dashboard-catalog.js");
19
19
  const require_dashboard_picker = require("./dashboard-picker.js");
20
20
  const require_dashboard_views = require("./dashboard-views.js");
21
21
  const require_dock_icon = require("./dock-icon.js");
22
+ const require_monitoring_history = require("./monitoring-history.js");
22
23
  const require_settings_export = require("./settings-export.js");
23
24
  //#region src/main/index.ts
24
25
  var FreelensPowerMain = class extends require_extensions.Main.LensExtension {
@@ -48,6 +49,7 @@ var FreelensPowerMain = class extends require_extensions.Main.LensExtension {
48
49
  const stop = require__global_external_mobx.reaction(() => power.enabled, (enabled) => {
49
50
  for (const dispose of disposers) dispose();
50
51
  disposers = enabled ? [
52
+ require_monitoring_history.startMonitoringHistory(this),
51
53
  require_ai_ipc.startAiIpc(),
52
54
  require_ai_models.startAiModels(),
53
55
  require_dock_icon.startDockIconOverride(),
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/main/index.ts"],"sourcesContent":["import { Main } from \"@freelensapp/extensions\";\nimport { reaction } from \"mobx\";\nimport { EXTENSION_DISPLAY_NAME, EXTENSION_ID } from \"../common/extension-info\";\nimport { AiPreferencesStore } from \"../common/store/ai-preferences-store\";\nimport { AiShortcutsStore } from \"../common/store/ai-shortcuts-store\";\nimport { AppearancePreferencesStore } from \"../common/store/appearance-preferences-store\";\nimport { DashboardPreferencesStore } from \"../common/store/dashboard-preferences-store\";\nimport { MonitoringPreferencesStore } from \"../common/store/monitoring-preferences-store\";\nimport { NodeShellPreferencesStore } from \"../common/store/node-shell-preferences-store\";\nimport { PowerPreferencesStore } from \"../common/store/power-preferences-store\";\nimport { ReadOnlyPreferencesStore } from \"../common/store/read-only-preferences-store\";\nimport { startAiIpc } from \"./ai-ipc\";\nimport { startAiModels } from \"./ai-models\";\nimport { registerDashboardCatalog } from \"./dashboard-catalog\";\nimport { startDashboardPicker } from \"./dashboard-picker\";\nimport { startDashboardViews } from \"./dashboard-views\";\nimport { startDockIconOverride } from \"./dock-icon\";\nimport { startSettingsExport } from \"./settings-export\";\n\nexport default class FreelensPowerMain extends Main.LensExtension {\n private stopFeatures?: () => void;\n\n get name() {\n return EXTENSION_DISPLAY_NAME;\n }\n get sanitizedExtensionId() {\n return EXTENSION_ID;\n }\n get storeName() {\n return this.manifest.storeName || EXTENSION_ID;\n }\n\n onActivate() {\n const power = PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>();\n power.loadExtension(this);\n AiPreferencesStore.getInstanceOrCreate().loadExtension(this);\n AiShortcutsStore.getInstanceOrCreate().loadExtension(this);\n ReadOnlyPreferencesStore.getInstanceOrCreate().loadExtension(this);\n NodeShellPreferencesStore.getInstanceOrCreate().loadExtension(this);\n MonitoringPreferencesStore.getInstanceOrCreate().loadExtension(this);\n AppearancePreferencesStore.getInstanceOrCreate().loadExtension(this);\n DashboardPreferencesStore.getInstanceOrCreate().loadExtension(this);\n this.stopFeatures?.();\n const stopExport = startSettingsExport();\n let disposers: (() => void)[] = [];\n const stop = reaction(\n () => power.enabled,\n (enabled) => {\n for (const dispose of disposers) dispose();\n disposers = enabled\n ? [\n startAiIpc(),\n startAiModels(),\n startDockIconOverride(),\n startDashboardViews(),\n startDashboardPicker(),\n registerDashboardCatalog(this),\n ]\n : [];\n },\n { fireImmediately: true },\n );\n this.stopFeatures = () => {\n stop();\n stopExport();\n for (const dispose of disposers) dispose();\n disposers = [];\n };\n }\n\n onDeactivate() {\n this.stopFeatures?.();\n this.stopFeatures = undefined;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAmBA,IAAqB,oBAArB,cAA+C,mBAAA,KAAK,cAAc;CAChE;CAEA,IAAI,OAAO;EACT,OAAO,uBAAA;CACT;CACA,IAAI,uBAAuB;EACzB,OAAO,uBAAA;CACT;CACA,IAAI,YAAY;EACd,OAAO,KAAK,SAAS,aAAA;CACvB;CAEA,aAAa;EACX,MAAM,QAAQ,gCAAA,sBAAsB,oBAA2C;EAC/E,MAAM,cAAc,IAAI;EACxB,6BAAA,mBAAmB,oBAAoB,CAAC,CAAC,cAAc,IAAI;EAC3D,2BAAA,iBAAiB,oBAAoB,CAAC,CAAC,cAAc,IAAI;EACzD,oCAAA,yBAAyB,oBAAoB,CAAC,CAAC,cAAc,IAAI;EACjE,qCAAA,0BAA0B,oBAAoB,CAAC,CAAC,cAAc,IAAI;EAClE,qCAAA,2BAA2B,oBAAoB,CAAC,CAAC,cAAc,IAAI;EACnE,qCAAA,2BAA2B,oBAAoB,CAAC,CAAC,cAAc,IAAI;EACnE,oCAAA,0BAA0B,oBAAoB,CAAC,CAAC,cAAc,IAAI;EAClE,KAAK,eAAe;EACpB,MAAM,aAAa,wBAAA,oBAAoB;EACvC,IAAI,YAA4B,CAAC;EACjC,MAAM,OAAO,8BAAA,eACL,MAAM,UACX,YAAY;GACX,KAAK,MAAM,WAAW,WAAW,QAAQ;GACzC,YAAY,UACR;IACE,eAAA,WAAW;IACX,kBAAA,cAAc;IACd,kBAAA,sBAAsB;IACtB,wBAAA,oBAAoB;IACpB,yBAAA,qBAAqB;IACrB,0BAAA,yBAAyB,IAAI;GAC/B,IACA,CAAC;EACP,GACA,EAAE,iBAAiB,KAAK,CAC1B;EACA,KAAK,qBAAqB;GACxB,KAAK;GACL,WAAW;GACX,KAAK,MAAM,WAAW,WAAW,QAAQ;GACzC,YAAY,CAAC;EACf;CACF;CAEA,eAAe;EACb,KAAK,eAAe;EACpB,KAAK,eAAe,KAAA;CACtB;AACF"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/main/index.ts"],"sourcesContent":["import { Main } from \"@freelensapp/extensions\";\nimport { reaction } from \"mobx\";\nimport { EXTENSION_DISPLAY_NAME, EXTENSION_ID } from \"../common/extension-info\";\nimport { AiPreferencesStore } from \"../common/store/ai-preferences-store\";\nimport { AiShortcutsStore } from \"../common/store/ai-shortcuts-store\";\nimport { AppearancePreferencesStore } from \"../common/store/appearance-preferences-store\";\nimport { DashboardPreferencesStore } from \"../common/store/dashboard-preferences-store\";\nimport { MonitoringPreferencesStore } from \"../common/store/monitoring-preferences-store\";\nimport { NodeShellPreferencesStore } from \"../common/store/node-shell-preferences-store\";\nimport { PowerPreferencesStore } from \"../common/store/power-preferences-store\";\nimport { ReadOnlyPreferencesStore } from \"../common/store/read-only-preferences-store\";\nimport { startAiIpc } from \"./ai-ipc\";\nimport { startAiModels } from \"./ai-models\";\nimport { registerDashboardCatalog } from \"./dashboard-catalog\";\nimport { startDashboardPicker } from \"./dashboard-picker\";\nimport { startDashboardViews } from \"./dashboard-views\";\nimport { startDockIconOverride } from \"./dock-icon\";\nimport { startMonitoringHistory } from \"./monitoring-history\";\nimport { startSettingsExport } from \"./settings-export\";\n\nexport default class FreelensPowerMain extends Main.LensExtension {\n private stopFeatures?: () => void;\n\n get name() {\n return EXTENSION_DISPLAY_NAME;\n }\n get sanitizedExtensionId() {\n return EXTENSION_ID;\n }\n get storeName() {\n return this.manifest.storeName || EXTENSION_ID;\n }\n\n onActivate() {\n const power = PowerPreferencesStore.getInstanceOrCreate<PowerPreferencesStore>();\n power.loadExtension(this);\n AiPreferencesStore.getInstanceOrCreate().loadExtension(this);\n AiShortcutsStore.getInstanceOrCreate().loadExtension(this);\n ReadOnlyPreferencesStore.getInstanceOrCreate().loadExtension(this);\n NodeShellPreferencesStore.getInstanceOrCreate().loadExtension(this);\n MonitoringPreferencesStore.getInstanceOrCreate().loadExtension(this);\n AppearancePreferencesStore.getInstanceOrCreate().loadExtension(this);\n DashboardPreferencesStore.getInstanceOrCreate().loadExtension(this);\n this.stopFeatures?.();\n const stopExport = startSettingsExport();\n let disposers: (() => void)[] = [];\n const stop = reaction(\n () => power.enabled,\n (enabled) => {\n for (const dispose of disposers) dispose();\n disposers = enabled\n ? [\n startMonitoringHistory(this),\n startAiIpc(),\n startAiModels(),\n startDockIconOverride(),\n startDashboardViews(),\n startDashboardPicker(),\n registerDashboardCatalog(this),\n ]\n : [];\n },\n { fireImmediately: true },\n );\n this.stopFeatures = () => {\n stop();\n stopExport();\n for (const dispose of disposers) dispose();\n disposers = [];\n };\n }\n\n onDeactivate() {\n this.stopFeatures?.();\n this.stopFeatures = undefined;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAoBA,IAAqB,oBAArB,cAA+C,mBAAA,KAAK,cAAc;CAChE;CAEA,IAAI,OAAO;EACT,OAAO,uBAAA;CACT;CACA,IAAI,uBAAuB;EACzB,OAAO,uBAAA;CACT;CACA,IAAI,YAAY;EACd,OAAO,KAAK,SAAS,aAAA;CACvB;CAEA,aAAa;EACX,MAAM,QAAQ,gCAAA,sBAAsB,oBAA2C;EAC/E,MAAM,cAAc,IAAI;EACxB,6BAAA,mBAAmB,oBAAoB,CAAC,CAAC,cAAc,IAAI;EAC3D,2BAAA,iBAAiB,oBAAoB,CAAC,CAAC,cAAc,IAAI;EACzD,oCAAA,yBAAyB,oBAAoB,CAAC,CAAC,cAAc,IAAI;EACjE,qCAAA,0BAA0B,oBAAoB,CAAC,CAAC,cAAc,IAAI;EAClE,qCAAA,2BAA2B,oBAAoB,CAAC,CAAC,cAAc,IAAI;EACnE,qCAAA,2BAA2B,oBAAoB,CAAC,CAAC,cAAc,IAAI;EACnE,oCAAA,0BAA0B,oBAAoB,CAAC,CAAC,cAAc,IAAI;EAClE,KAAK,eAAe;EACpB,MAAM,aAAa,wBAAA,oBAAoB;EACvC,IAAI,YAA4B,CAAC;EACjC,MAAM,OAAO,8BAAA,eACL,MAAM,UACX,YAAY;GACX,KAAK,MAAM,WAAW,WAAW,QAAQ;GACzC,YAAY,UACR;IACE,2BAAA,uBAAuB,IAAI;IAC3B,eAAA,WAAW;IACX,kBAAA,cAAc;IACd,kBAAA,sBAAsB;IACtB,wBAAA,oBAAoB;IACpB,yBAAA,qBAAqB;IACrB,0BAAA,yBAAyB,IAAI;GAC/B,IACA,CAAC;EACP,GACA,EAAE,iBAAiB,KAAK,CAC1B;EACA,KAAK,qBAAqB;GACxB,KAAK;GACL,WAAW;GACX,KAAK,MAAM,WAAW,WAAW,QAAQ;GACzC,YAAY,CAAC;EACf;CACF;CAEA,eAAe;EACb,KAAK,eAAe;EACpB,KAAK,eAAe,KAAA;CACtB;AACF"}