@64mb/freelens-power 2.2.0 → 2.2.1

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.
@@ -84,6 +84,7 @@ var styles = `
84
84
  padding: 40px 24px; border: 1px solid var(--borderFaintColor); border-radius: 12px;
85
85
  background: var(--contentColor); text-align: center;
86
86
  }
87
+ .freelens-power-dashboard .power-dashboard-empty > button { display:inline-flex; align-items:center; gap:7px; }
87
88
  .freelens-power-dashboard .power-dashboard-empty p { color: var(--textColorSecondary); margin: 12px 0 24px; }
88
89
  @media (max-width: 700px) {
89
90
  .ClusterManager main.freelens-power-dashboard, .freelens-power-dashboard { display: block; position: relative; z-index: 2; flex: 1; background: var(--mainBackground); padding: 18px; }
@@ -416,7 +417,7 @@ var DashboardPage = require__global_external_mobx_react.observer(({ onOpenPrefer
416
417
  /* @__PURE__ */ require_jsx_runtime.jsx("span", {
417
418
  "aria-hidden": "true",
418
419
  children: /* @__PURE__ */ require_jsx_runtime.jsx(require_extensions.Renderer.Component.Icon, {
419
- material: "tune",
420
+ material: "dashboard",
420
421
  size: 16
421
422
  })
422
423
  }),
@@ -431,10 +432,16 @@ var DashboardPage = require__global_external_mobx_react.observer(({ onOpenPrefer
431
432
  children: [
432
433
  /* @__PURE__ */ require_jsx_runtime.jsx("h2", { children: "Build your dashboard" }),
433
434
  /* @__PURE__ */ require_jsx_runtime.jsx("p", { children: "Add your favorite tools and pages in Settings." }),
434
- /* @__PURE__ */ require_jsx_runtime.jsx("button", {
435
+ /* @__PURE__ */ require_jsx_runtime.jsxs("button", {
435
436
  type: "button",
436
437
  onClick: onOpenPreferences,
437
- children: "Add cards"
438
+ children: [/* @__PURE__ */ require_jsx_runtime.jsx("span", {
439
+ "aria-hidden": "true",
440
+ children: /* @__PURE__ */ require_jsx_runtime.jsx(require_extensions.Renderer.Component.Icon, {
441
+ material: "add",
442
+ size: 16
443
+ })
444
+ }), "Add cards"]
438
445
  })
439
446
  ]
440
447
  }) : /* @__PURE__ */ require_jsx_runtime.jsxs(require_jsx_runtime.Fragment, { children: [/* @__PURE__ */ require_jsx_runtime.jsx("div", {
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard.js","names":[],"sources":["../../src/renderer/dashboard.tsx"],"sourcesContent":["import { Renderer } from \"@freelensapp/extensions\";\n// SPDX-License-Identifier: Apache-2.0\nimport { ipcRenderer, shell } from \"electron\";\nimport { observer } from \"mobx-react\";\nimport { type CSSProperties, useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport { normalizeDashboardUrl } from \"../common/dashboard\";\nimport {\n DASHBOARD_VIEWS_CLEAR,\n DASHBOARD_VIEWS_LOADING,\n DASHBOARD_VIEWS_PIN,\n DASHBOARD_VIEWS_PINNED,\n DASHBOARD_VIEWS_RELOAD,\n DASHBOARD_VIEWS_SYNC,\n type DashboardViewLoading,\n} from \"../common/dashboard-views\";\nimport { DashboardPreferencesStore } from \"../common/store/dashboard-preferences-store\";\n\nconst styles = `\n .freelens-power-dashboard .power-dashboard-card-pinned .power-dashboard-embed { opacity: .65; }\n .freelens-power-dashboard .power-dashboard-pin-placeholder { display: flex; width: 100%; height: 100%; flex-direction: column; align-items: center; justify-content: center; gap: 12px; border: 0; background: var(--mainBackground); color: var(--textColorSecondary); cursor: pointer; font: inherit; }\n .freelens-power-dashboard .power-dashboard-pin-placeholder:hover { color: var(--textColorAccent); }\n\n .ClusterManager main.freelens-power-dashboard, .freelens-power-dashboard { display: block; position: relative; z-index: 2; flex: 1; background: var(--mainBackground); padding: 28px; color: var(--textColorPrimary); min-width: 0; min-height: 0; height: auto; overflow: auto; box-sizing: border-box; }\n .freelens-power-dashboard .power-dashboard-header {\n display: flex; align-items: center; justify-content: space-between; gap: 20px; margin-bottom: 24px;\n }\n .freelens-power-dashboard h1 { margin: 0; color: var(--textColorAccent); font-size: 24px; }\n .freelens-power-dashboard .power-dashboard-subtitle,\n .freelens-power-dashboard .power-dashboard-hint { color: var(--textColorSecondary); line-height: 1.5; }\n .freelens-power-dashboard .power-dashboard-subtitle { margin: 6px 0 0; }\n .freelens-power-dashboard button {\n padding: 9px 16px; border: 1px solid var(--borderFaintColor); border-radius: 8px;\n background: var(--contentColor); color: var(--textColorAccent); cursor: pointer;\n }\n .freelens-power-dashboard .power-dashboard-header .power-dashboard-action { display: inline-flex; align-items: center; gap: 7px; min-height: 32px; padding: 6px 12px; font-size: 13px; background: transparent; color: var(--textColorSecondary); }\n .freelens-power-dashboard .power-dashboard-header .power-dashboard-action { transition: background-color 140ms, border-color 140ms, color 140ms; }\n .freelens-power-dashboard .power-dashboard-header .power-dashboard-action:hover { background: var(--contentColor); border-color: var(--borderColor); color: var(--textColorAccent); }\n .freelens-power-dashboard .power-dashboard-header .power-dashboard-action:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }\n .freelens-power-dashboard .power-dashboard-header .power-dashboard-action .Icon { color: inherit; transition: color 160ms ease; }\n .freelens-power-dashboard .power-dashboard-header .power-dashboard-refresh { width: 32px; height: 32px; padding: 0; justify-content: center; border-color: transparent; border-radius: 8px; }\n .freelens-power-dashboard .power-dashboard-header .power-dashboard-refresh:hover { border-color: transparent; background: color-mix(in srgb, var(--primary) 10%, transparent); color: var(--primary); }\n .power-dashboard-actions { display: flex; align-items: center; gap: 8px; }\n .power-dashboard-action:disabled { opacity: 0.5; cursor: wait; }\n .freelens-power-dashboard .power-dashboard-grid {\n display: grid; grid-template-columns: repeat(var(--power-columns, 4), minmax(0, 1fr)); grid-auto-rows: 220px; grid-auto-flow: row; gap: 20px;\n }\n .freelens-power-dashboard .power-dashboard-card {\n display: flex; flex-direction: column; min-width: 0; overflow: hidden;\n border: 1px solid var(--borderFaintColor); border-radius: 12px; background: var(--contentColor);\n }\n .freelens-power-dashboard.power-dashboard-expanded { display: flex !important; flex-direction: column; overflow: hidden; }\n .freelens-power-dashboard.power-dashboard-expanded .power-dashboard-grid { display: block; flex: 1; min-height: 0; }\n .freelens-power-dashboard.power-dashboard-expanded .power-dashboard-card:not([hidden]) { height: 100%; box-sizing: border-box; }\n .freelens-power-dashboard .power-dashboard-card[hidden] { display: none; }\n .freelens-power-dashboard .power-dashboard-card-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }\n .freelens-power-dashboard button.power-dashboard-expand { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; padding: 0; border: 0; border-radius: 5px; background: transparent; color: var(--textColorSecondary); transition: color 160ms ease, background-color 160ms ease; }\n .freelens-power-dashboard button.power-dashboard-expand:hover { color: var(--textColorAccent); background: var(--mainBackground); }\n .freelens-power-dashboard button.power-dashboard-expand[aria-pressed=\"true\"],\n .freelens-power-dashboard button.power-dashboard-expand[aria-pressed=\"true\"] .Icon { color: var(--primary); }\n .freelens-power-dashboard button.power-dashboard-expand[aria-pressed=\"true\"]:hover { background: color-mix(in srgb, var(--primary) 12%, transparent); }\n .freelens-power-dashboard button.power-dashboard-expand:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }\n .freelens-power-dashboard .power-dashboard-card-xs { grid-column: span 1; grid-row: span 1; }\n .freelens-power-dashboard .power-dashboard-card-s { grid-column: span var(--power-small-span, 2); grid-row: span 2; }\n .freelens-power-dashboard .power-dashboard-card-m { grid-column: span var(--power-medium-span, 4); grid-row: span 2; }\n .freelens-power-dashboard .power-dashboard-card-l { grid-column: span var(--power-large-span, 4); grid-row: span 3; }\n .freelens-power-dashboard .power-dashboard-card-xl { grid-column: span var(--power-columns, 4); grid-row: span 3; }\n .freelens-power-dashboard .power-dashboard-card-header {\n display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 6px 12px;\n }\n .freelens-power-dashboard h2 { margin: 0; font-size: 14px; overflow-wrap: anywhere; }\n .freelens-power-dashboard .power-dashboard-card-title { display: flex; align-items: center; gap: 8px; min-width: 0; }\n .freelens-power-dashboard .power-dashboard-card-title h2 { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .freelens-power-dashboard .power-dashboard-card-xs .power-dashboard-card-header { flex-wrap: wrap; row-gap: 4px; }\n .freelens-power-dashboard .power-dashboard-card-xs .power-dashboard-card-title { flex-basis: 100%; }\n .freelens-power-dashboard .power-dashboard-card-xs .power-dashboard-card-actions { margin-left: auto; }\n .freelens-power-dashboard .power-dashboard-site-icon { width: 16px; height: 16px; border-radius: 4px; object-fit: contain; flex-shrink: 0; }\n .freelens-power-dashboard .power-dashboard-card-header a {\n flex-shrink: 0; color: var(--textColorPrimary); font-size: 12px; transition: color 160ms ease;\n }\n .freelens-power-dashboard .power-dashboard-card-header a .Icon { color: inherit; transition: color 160ms ease; }\n .freelens-power-dashboard .power-dashboard-card-header a:hover { color: var(--textColorAccent); }\n .freelens-power-dashboard .power-dashboard-embed { width: 100%; flex: 1; min-height: 0; overflow: hidden; }\n .freelens-power-dashboard .power-dashboard-skeleton { height: 100%; box-sizing: border-box; padding: 20px; display: flex; flex-direction: column; gap: 12px; background: var(--contentColor); }\n .freelens-power-dashboard .power-dashboard-skeleton span { height: 12px; border-radius: 6px; background: color-mix(in srgb, var(--textColorSecondary) 12%, transparent); animation: power-dashboard-loading 1.8s ease-in-out infinite; }\n .freelens-power-dashboard .power-dashboard-skeleton span:first-child { width: 45%; height: 20px; margin-bottom: 8px; }\n .freelens-power-dashboard .power-dashboard-skeleton span:last-child { flex: 1; min-height: 30px; }\n @keyframes power-dashboard-loading { 50% { opacity: .45; } }\n @media (prefers-reduced-motion: reduce) { .freelens-power-dashboard .power-dashboard-skeleton span { animation: none; } }\n .freelens-power-dashboard .power-dashboard-hint { margin: 16px 0 0; font-size: 12px; }\n .power-dashboard-right-tooltip { position: fixed !important; left: calc(anchor(right) + 8px) !important; top: anchor(center) !important; right: auto !important; bottom: auto !important; translate: 0 -50%; white-space: nowrap !important; max-width: none !important; }\n .freelens-power-dashboard .power-dashboard-empty {\n padding: 40px 24px; border: 1px solid var(--borderFaintColor); border-radius: 12px;\n background: var(--contentColor); text-align: center;\n }\n .freelens-power-dashboard .power-dashboard-empty p { color: var(--textColorSecondary); margin: 12px 0 24px; }\n @media (max-width: 700px) {\n .ClusterManager main.freelens-power-dashboard, .freelens-power-dashboard { display: block; position: relative; z-index: 2; flex: 1; background: var(--mainBackground); padding: 18px; }\n .freelens-power-dashboard .power-dashboard-header { flex-wrap: wrap; }\n }\n`;\n\nfunction DashboardActionIcon({ material, tooltip }: { material: string; tooltip: string }) {\n const [anchor] = useState(() => `--power-dashboard-action-${crypto.randomUUID()}`);\n return (\n <Renderer.Component.Icon\n material={material}\n size={18}\n style={{ anchorName: anchor, \"--size\": \"18px\" } as CSSProperties}\n tooltip={{ children: tooltip, className: \"power-dashboard-right-tooltip\", style: { positionAnchor: anchor } }}\n />\n );\n}\n\nfunction WebsiteIcon({ url, favicon }: { url: string; favicon?: string }) {\n const [failed, setFailed] = useState(false);\n if (failed)\n return (\n <span className=\"power-dashboard-site-icon\" aria-hidden=\"true\">\n 🌐\n </span>\n );\n return (\n <img\n className=\"power-dashboard-site-icon\"\n src={favicon || new URL(\"/favicon.ico\", url).href}\n alt=\"\"\n loading=\"lazy\"\n referrerPolicy=\"no-referrer\"\n onError={() => setFailed(true)}\n />\n );\n}\n\nexport const DashboardPage = observer(({ onOpenPreferences }: { onOpenPreferences: () => void }) => {\n const preferences = DashboardPreferencesStore.getInstanceOrCreate<DashboardPreferencesStore>();\n const cards = preferences.cards.flatMap((card) => {\n const url = normalizeDashboardUrl(card.url);\n return url ? [{ ...card, url }] : [];\n });\n const root = useRef<HTMLElement>(null);\n const [expandedId, setExpandedId] = useState<string | null>(null);\n const expanded = cards.some((card) => card.id === expandedId) ? expandedId : null;\n const expandedRef = useRef<string | null>(null);\n const gridScrollTop = useRef<number | null>(null);\n expandedRef.current = expanded;\n useLayoutEffect(() => {\n const container = root.current;\n if (!container) return;\n if (expanded) container.scrollTop = 0;\n else if (gridScrollTop.current !== null) {\n container.scrollTop = gridScrollTop.current;\n gridScrollTop.current = null;\n }\n }, [expanded]);\n useEffect(() => {\n if (expandedId && !expanded) setExpandedId(null);\n }, [expandedId, expanded]);\n useEffect(() => {\n const restore = () => setExpandedId(null);\n const escape = (event: KeyboardEvent) => {\n if (event.key === \"Escape\" && expandedRef.current) {\n event.preventDefault();\n event.stopPropagation();\n restore();\n }\n };\n document.addEventListener(\"keydown\", escape, true);\n ipcRenderer.on(\"freelens-power:dashboard-escape\", restore);\n return () => {\n document.removeEventListener(\"keydown\", escape, true);\n ipcRenderer.removeListener(\"freelens-power:dashboard-escape\", restore);\n };\n }, []);\n const [loadFailed, setLoadFailed] = useState(false);\n const [loadingCards, setLoadingCards] = useState<Record<string, DashboardViewLoading>>({});\n useEffect(() => {\n const update = (_event: unknown, value: DashboardViewLoading) => {\n if (\n !value ||\n typeof value.id !== \"string\" ||\n typeof value.url !== \"string\" ||\n typeof value.loading !== \"boolean\" ||\n typeof value.failed !== \"boolean\" ||\n !preferences.cards.some((card) => card.id === value.id && normalizeDashboardUrl(card.url) === value.url)\n )\n return;\n setLoadingCards((previous) => {\n const existing = previous[value.id];\n return existing?.url === value.url && existing.loading === value.loading && existing.failed === value.failed\n ? previous\n : { ...previous, [value.id]: value };\n });\n if (value.failed) setLoadFailed(true);\n };\n ipcRenderer.on(DASHBOARD_VIEWS_LOADING, update);\n return () => {\n ipcRenderer.removeListener(DASHBOARD_VIEWS_LOADING, update);\n };\n }, [preferences]);\n const [reloading, setReloading] = useState(false);\n const [reloadBlocked, setReloadBlocked] = useState(false);\n const reloadRequest = useRef(0);\n const reloadCooldown = useRef<ReturnType<typeof setTimeout>>();\n useEffect(\n () => () => {\n ++reloadRequest.current;\n clearTimeout(reloadCooldown.current);\n },\n [],\n );\n const reloadCards = async () => {\n if (reloadCooldown.current) return;\n const request = ++reloadRequest.current;\n setReloading(true);\n setReloadBlocked(true);\n reloadCooldown.current = setTimeout(() => {\n reloadCooldown.current = undefined;\n setReloadBlocked(false);\n }, 1000);\n try {\n const results = await Promise.all(cards.map(({ id }) => ipcRenderer.invoke(DASHBOARD_VIEWS_RELOAD, { id })));\n if (reloadRequest.current === request) setLoadFailed(results.some((result) => result?.failed?.length));\n } catch {\n if (reloadRequest.current === request) setLoadFailed(true);\n } finally {\n if (reloadRequest.current === request) {\n clearTimeout(reloadCooldown.current);\n reloadCooldown.current = undefined;\n setReloadBlocked(false);\n setReloading(false);\n }\n }\n };\n const focusPinned = (id: string) => {\n void ipcRenderer.invoke(DASHBOARD_VIEWS_PIN, { id, focus: true }).catch(() => setLoadFailed(true));\n };\n const [pinnedCards, setPinnedCards] = useState<string[]>([]);\n useEffect(() => {\n const update = (_event: unknown, ids: unknown) => {\n if (Array.isArray(ids)) setPinnedCards(ids.filter((id): id is string => typeof id === \"string\"));\n };\n ipcRenderer.on(DASHBOARD_VIEWS_PINNED, update);\n return () => {\n ipcRenderer.removeListener(DASHBOARD_VIEWS_PINNED, update);\n };\n }, []);\n const togglePinned = async (id: string) => {\n try {\n const result = await ipcRenderer.invoke(DASHBOARD_VIEWS_PIN, { id, pinned: !pinnedCards.includes(id) });\n if (Array.isArray(result?.pinned))\n setPinnedCards(result.pinned.filter((value: unknown): value is string => typeof value === \"string\"));\n } catch {\n setLoadFailed(true);\n }\n };\n const [siteIcons, setSiteIcons] = useState<Record<string, string>>({});\n useEffect(() => {\n const update = (_event: unknown, icon: { id?: unknown; url?: unknown }) => {\n if (typeof icon?.id !== \"string\" || typeof icon.url !== \"string\") return;\n const imageData =\n icon.url.length <= 720_000 &&\n /^data:image\\/(?:png|jpeg|gif|webp|x-icon|vnd\\.microsoft\\.icon|svg\\+xml);base64,[A-Za-z0-9+/]+={0,2}$/.test(\n icon.url,\n );\n const url = imageData ? icon.url : normalizeDashboardUrl(icon.url);\n if (!url) return;\n const id = icon.id;\n setSiteIcons((previous) => (previous[id] === url ? previous : { ...previous, [id]: url }));\n };\n ipcRenderer.on(\"freelens-power:dashboard-site-icon\", update);\n return () => {\n ipcRenderer.removeListener(\"freelens-power:dashboard-site-icon\", update);\n };\n }, []);\n const cardIdentity = JSON.stringify(cards.map(({ id, url, size }) => ({ id, url, size })));\n useEffect(() => {\n setSiteIcons({});\n }, [cardIdentity]);\n useEffect(() => {\n const container = root.current;\n if (!container) return;\n let active = true;\n let frame = 0;\n const sync = () => {\n frame = 0;\n const containerStyle = window.getComputedStyle(container);\n const contentWidth =\n container.clientWidth -\n (Number.parseFloat(containerStyle.paddingLeft) || 0) -\n (Number.parseFloat(containerStyle.paddingRight) || 0);\n const columns = contentWidth >= 1200 ? 6 : contentWidth >= 800 ? 4 : contentWidth >= 520 ? 2 : 1;\n for (const [property, value] of Object.entries({\n \"--power-columns\": columns,\n \"--power-small-span\": Math.min(2, columns),\n \"--power-medium-span\": Math.min(4, columns),\n \"--power-large-span\": Math.min(4, columns),\n })) {\n if (container.style.getPropertyValue(property) !== String(value))\n container.style.setProperty(property, String(value));\n }\n const containerBounds = container.getBoundingClientRect();\n const viewport = {\n left: Math.max(0, containerBounds.left),\n top: Math.max(0, containerBounds.top),\n right: Math.min(window.innerWidth, containerBounds.right),\n bottom: Math.min(window.innerHeight, containerBounds.bottom),\n };\n for (let ancestor = container.parentElement; ancestor; ancestor = ancestor.parentElement) {\n const style = window.getComputedStyle(ancestor);\n const rect = ancestor.getBoundingClientRect();\n if (/^(auto|scroll|hidden|clip)$/.test(style.overflowX || style.overflow)) {\n viewport.left = Math.max(viewport.left, rect.left + ancestor.clientLeft);\n viewport.right = Math.min(viewport.right, rect.left + ancestor.clientLeft + ancestor.clientWidth);\n }\n if (/^(auto|scroll|hidden|clip)$/.test(style.overflowY || style.overflow)) {\n viewport.top = Math.max(viewport.top, rect.top + ancestor.clientTop);\n viewport.bottom = Math.min(viewport.bottom, rect.top + ancestor.clientTop + ancestor.clientHeight);\n }\n }\n const overlayOpen = Array.from(\n document.querySelectorAll<HTMLElement>('.Dialog, [role=\"dialog\"], [role=\"menu\"], .Menu, .power-ai-panel'),\n ).some((element) => {\n const rect = element.getBoundingClientRect();\n const style = window.getComputedStyle(element);\n return rect.width > 0 && rect.height > 0 && style.display !== \"none\" && style.visibility !== \"hidden\";\n });\n const visible = overlayOpen\n ? []\n : Array.from(container.querySelectorAll<HTMLElement>(\".power-dashboard-embed\")).flatMap((element) => {\n if (expandedRef.current && element.dataset.cardId !== expandedRef.current) return [];\n const rect = element.getBoundingClientRect();\n const x = Math.ceil(Math.max(rect.left, viewport.left));\n const y = Math.ceil(Math.max(rect.top, viewport.top));\n const right = Math.floor(Math.min(rect.right, viewport.right));\n const bottom = Math.floor(Math.min(rect.bottom, viewport.bottom));\n const bounds = {\n x: Math.floor(rect.left),\n y: Math.floor(rect.top),\n width: Math.ceil(rect.right) - Math.floor(rect.left),\n height: Math.ceil(rect.bottom) - Math.floor(rect.top),\n };\n const clip = { x, y, width: right - x, height: bottom - y };\n if (\n ![...Object.values(bounds), ...Object.values(clip)].every(Number.isFinite) ||\n rect.width <= 0 ||\n rect.height <= 0 ||\n clip.width <= 0 ||\n clip.height <= 0\n )\n return [];\n return [\n {\n id: element.dataset.cardId,\n bounds,\n clip,\n ...(expandedRef.current === element.dataset.cardId ? { scrollbars: true } : {}),\n },\n ];\n });\n void ipcRenderer\n .invoke(DASHBOARD_VIEWS_SYNC, {\n cards: visible,\n ...(overlayOpen ? { hidden: true } : {}),\n })\n .then(\n (result) => {\n if (active) {\n setLoadFailed(Boolean(result?.failed?.length));\n if (Array.isArray(result?.pinned)) setPinnedCards(result.pinned);\n }\n },\n () => {\n if (active) setLoadFailed(true);\n },\n );\n };\n const schedule = () => {\n if (!frame) frame = window.requestAnimationFrame(sync);\n };\n const activate = () => {\n if (document.visibilityState === \"hidden\") return;\n schedule();\n };\n const mutations = new MutationObserver(schedule);\n mutations.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: [\"class\", \"style\", \"hidden\"],\n });\n const observer = new ResizeObserver(schedule);\n observer.observe(container);\n for (let ancestor = container.parentElement; ancestor; ancestor = ancestor.parentElement)\n observer.observe(ancestor);\n for (const element of container.querySelectorAll(\".power-dashboard-embed\")) observer.observe(element);\n document.addEventListener(\"scroll\", schedule, true);\n window.addEventListener(\"resize\", schedule);\n window.addEventListener(\"focus\", activate);\n document.addEventListener(\"visibilitychange\", activate);\n schedule();\n return () => {\n active = false;\n window.cancelAnimationFrame(frame);\n observer.disconnect();\n mutations.disconnect();\n document.removeEventListener(\"scroll\", schedule, true);\n window.removeEventListener(\"resize\", schedule);\n window.removeEventListener(\"focus\", activate);\n document.removeEventListener(\"visibilitychange\", activate);\n void ipcRenderer.invoke(DASHBOARD_VIEWS_CLEAR).catch(() => {});\n };\n }, [cardIdentity]);\n\n return (\n <main ref={root} className={`freelens-power-dashboard${expanded ? \" power-dashboard-expanded\" : \"\"}`}>\n <style>{styles}</style>\n <header className=\"power-dashboard-header\">\n <div>\n <h1>🔋 Power Dashboard</h1>\n </div>\n <div className=\"power-dashboard-actions\">\n <button\n type=\"button\"\n className=\"power-dashboard-action power-dashboard-refresh\"\n aria-label=\"Refresh\"\n aria-busy={reloading}\n disabled={reloadBlocked || cards.length === 0}\n onClick={() => {\n void reloadCards();\n }}\n >\n <Renderer.Component.Icon material=\"refresh\" size={18} tooltip=\"Refresh\" />\n </button>\n <button type=\"button\" className=\"power-dashboard-action\" onClick={onOpenPreferences}>\n <span aria-hidden=\"true\">\n <Renderer.Component.Icon material=\"tune\" size={16} />\n </span>{\" \"}\n Settings\n </button>\n </div>\n </header>\n {cards.length === 0 ? (\n <section className=\"power-dashboard-empty\">\n <h2>Build your dashboard</h2>\n <p>Add your favorite tools and pages in Settings.</p>\n <button type=\"button\" onClick={onOpenPreferences}>\n Add cards\n </button>\n </section>\n ) : (\n <>\n <div className=\"power-dashboard-grid\">\n {cards.map((card) => (\n <section\n key={card.id}\n hidden={Boolean(expanded && expanded !== card.id)}\n className={`power-dashboard-card power-dashboard-card-${card.size}${pinnedCards.includes(card.id) ? \" power-dashboard-card-pinned\" : \"\"}`}\n >\n <header className=\"power-dashboard-card-header\">\n <div className=\"power-dashboard-card-title\">\n <WebsiteIcon\n key={`${card.url}:${siteIcons[card.id] || \"\"}`}\n url={card.url}\n favicon={siteIcons[card.id]}\n />\n <h2>{card.title}</h2>\n </div>\n <div className=\"power-dashboard-card-actions\">\n <button\n type=\"button\"\n className=\"power-dashboard-expand\"\n aria-label={`Auto-refresh ${card.title} every 10 seconds`}\n aria-pressed={card.refreshEvery10Seconds === true}\n onClick={() => {\n preferences.upsertCard({ ...card, refreshEvery10Seconds: !card.refreshEvery10Seconds });\n }}\n >\n <DashboardActionIcon\n material=\"autorenew\"\n tooltip={card.refreshEvery10Seconds ? \"Disable refresh\" : \"Enable refresh (10s)\"}\n />\n </button>\n <button\n type=\"button\"\n className=\"power-dashboard-expand\"\n aria-label={`${pinnedCards.includes(card.id) ? \"Unpin\" : \"Pin\"} ${card.title}`}\n aria-pressed={pinnedCards.includes(card.id)}\n onClick={() => {\n void togglePinned(card.id);\n }}\n >\n <DashboardActionIcon\n material=\"push_pin\"\n tooltip={pinnedCards.includes(card.id) ? \"Unpin\" : \"Pin\"}\n />\n </button>\n <button\n type=\"button\"\n className=\"power-dashboard-expand\"\n aria-label={`${expanded === card.id ? \"Restore\" : \"Expand\"} ${card.title}`}\n aria-pressed={expanded === card.id}\n onClick={() => {\n if (!expanded) gridScrollTop.current = root.current?.scrollTop ?? 0;\n setExpandedId(expanded === card.id ? null : card.id);\n }}\n >\n <DashboardActionIcon\n material={expanded === card.id ? \"fullscreen_exit\" : \"fullscreen\"}\n tooltip={expanded === card.id ? \"Restore\" : \"Expand\"}\n />\n </button>\n <a\n href={card.url}\n onClick={(event) => {\n event.preventDefault();\n void shell.openExternal(card.url);\n }}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label={`Open ${card.title} in browser`}\n >\n <DashboardActionIcon material=\"open_in_new\" tooltip=\"Open\" />\n </a>\n </div>\n </header>\n <div\n className=\"power-dashboard-embed\"\n data-card-id={card.id}\n role=\"region\"\n aria-label={card.title}\n aria-busy={loadingCards[card.id]?.url === card.url && loadingCards[card.id]?.loading}\n >\n {!pinnedCards.includes(card.id) &&\n loadingCards[card.id]?.url === card.url &&\n loadingCards[card.id]?.loading && (\n <div className=\"power-dashboard-skeleton\" role=\"status\" aria-label={`Loading ${card.title}`}>\n <span aria-hidden=\"true\" />\n <span aria-hidden=\"true\" />\n <span aria-hidden=\"true\" />\n </div>\n )}\n {pinnedCards.includes(card.id) && (\n <button\n type=\"button\"\n className=\"power-dashboard-pin-placeholder\"\n onClick={() => focusPinned(card.id)}\n aria-label={`Focus pinned ${card.title}`}\n >\n <Renderer.Component.Icon material=\"push_pin\" size={28} />\n <span>Pinned above other windows</span>\n <span>Focus window</span>\n </button>\n )}\n </div>\n </section>\n ))}\n </div>\n {loadFailed && (\n <p role=\"alert\" className=\"power-dashboard-hint\">\n Unable to load dashboard cards. Open them in your browser.\n </p>\n )}\n </>\n )}\n </main>\n );\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"dashboard.js","names":[],"sources":["../../src/renderer/dashboard.tsx"],"sourcesContent":["import { Renderer } from \"@freelensapp/extensions\";\n// SPDX-License-Identifier: Apache-2.0\nimport { ipcRenderer, shell } from \"electron\";\nimport { observer } from \"mobx-react\";\nimport { type CSSProperties, useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport { normalizeDashboardUrl } from \"../common/dashboard\";\nimport {\n DASHBOARD_VIEWS_CLEAR,\n DASHBOARD_VIEWS_LOADING,\n DASHBOARD_VIEWS_PIN,\n DASHBOARD_VIEWS_PINNED,\n DASHBOARD_VIEWS_RELOAD,\n DASHBOARD_VIEWS_SYNC,\n type DashboardViewLoading,\n} from \"../common/dashboard-views\";\nimport { DashboardPreferencesStore } from \"../common/store/dashboard-preferences-store\";\n\nconst styles = `\n .freelens-power-dashboard .power-dashboard-card-pinned .power-dashboard-embed { opacity: .65; }\n .freelens-power-dashboard .power-dashboard-pin-placeholder { display: flex; width: 100%; height: 100%; flex-direction: column; align-items: center; justify-content: center; gap: 12px; border: 0; background: var(--mainBackground); color: var(--textColorSecondary); cursor: pointer; font: inherit; }\n .freelens-power-dashboard .power-dashboard-pin-placeholder:hover { color: var(--textColorAccent); }\n\n .ClusterManager main.freelens-power-dashboard, .freelens-power-dashboard { display: block; position: relative; z-index: 2; flex: 1; background: var(--mainBackground); padding: 28px; color: var(--textColorPrimary); min-width: 0; min-height: 0; height: auto; overflow: auto; box-sizing: border-box; }\n .freelens-power-dashboard .power-dashboard-header {\n display: flex; align-items: center; justify-content: space-between; gap: 20px; margin-bottom: 24px;\n }\n .freelens-power-dashboard h1 { margin: 0; color: var(--textColorAccent); font-size: 24px; }\n .freelens-power-dashboard .power-dashboard-subtitle,\n .freelens-power-dashboard .power-dashboard-hint { color: var(--textColorSecondary); line-height: 1.5; }\n .freelens-power-dashboard .power-dashboard-subtitle { margin: 6px 0 0; }\n .freelens-power-dashboard button {\n padding: 9px 16px; border: 1px solid var(--borderFaintColor); border-radius: 8px;\n background: var(--contentColor); color: var(--textColorAccent); cursor: pointer;\n }\n .freelens-power-dashboard .power-dashboard-header .power-dashboard-action { display: inline-flex; align-items: center; gap: 7px; min-height: 32px; padding: 6px 12px; font-size: 13px; background: transparent; color: var(--textColorSecondary); }\n .freelens-power-dashboard .power-dashboard-header .power-dashboard-action { transition: background-color 140ms, border-color 140ms, color 140ms; }\n .freelens-power-dashboard .power-dashboard-header .power-dashboard-action:hover { background: var(--contentColor); border-color: var(--borderColor); color: var(--textColorAccent); }\n .freelens-power-dashboard .power-dashboard-header .power-dashboard-action:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }\n .freelens-power-dashboard .power-dashboard-header .power-dashboard-action .Icon { color: inherit; transition: color 160ms ease; }\n .freelens-power-dashboard .power-dashboard-header .power-dashboard-refresh { width: 32px; height: 32px; padding: 0; justify-content: center; border-color: transparent; border-radius: 8px; }\n .freelens-power-dashboard .power-dashboard-header .power-dashboard-refresh:hover { border-color: transparent; background: color-mix(in srgb, var(--primary) 10%, transparent); color: var(--primary); }\n .power-dashboard-actions { display: flex; align-items: center; gap: 8px; }\n .power-dashboard-action:disabled { opacity: 0.5; cursor: wait; }\n .freelens-power-dashboard .power-dashboard-grid {\n display: grid; grid-template-columns: repeat(var(--power-columns, 4), minmax(0, 1fr)); grid-auto-rows: 220px; grid-auto-flow: row; gap: 20px;\n }\n .freelens-power-dashboard .power-dashboard-card {\n display: flex; flex-direction: column; min-width: 0; overflow: hidden;\n border: 1px solid var(--borderFaintColor); border-radius: 12px; background: var(--contentColor);\n }\n .freelens-power-dashboard.power-dashboard-expanded { display: flex !important; flex-direction: column; overflow: hidden; }\n .freelens-power-dashboard.power-dashboard-expanded .power-dashboard-grid { display: block; flex: 1; min-height: 0; }\n .freelens-power-dashboard.power-dashboard-expanded .power-dashboard-card:not([hidden]) { height: 100%; box-sizing: border-box; }\n .freelens-power-dashboard .power-dashboard-card[hidden] { display: none; }\n .freelens-power-dashboard .power-dashboard-card-actions { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }\n .freelens-power-dashboard button.power-dashboard-expand { display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; padding: 0; border: 0; border-radius: 5px; background: transparent; color: var(--textColorSecondary); transition: color 160ms ease, background-color 160ms ease; }\n .freelens-power-dashboard button.power-dashboard-expand:hover { color: var(--textColorAccent); background: var(--mainBackground); }\n .freelens-power-dashboard button.power-dashboard-expand[aria-pressed=\"true\"],\n .freelens-power-dashboard button.power-dashboard-expand[aria-pressed=\"true\"] .Icon { color: var(--primary); }\n .freelens-power-dashboard button.power-dashboard-expand[aria-pressed=\"true\"]:hover { background: color-mix(in srgb, var(--primary) 12%, transparent); }\n .freelens-power-dashboard button.power-dashboard-expand:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }\n .freelens-power-dashboard .power-dashboard-card-xs { grid-column: span 1; grid-row: span 1; }\n .freelens-power-dashboard .power-dashboard-card-s { grid-column: span var(--power-small-span, 2); grid-row: span 2; }\n .freelens-power-dashboard .power-dashboard-card-m { grid-column: span var(--power-medium-span, 4); grid-row: span 2; }\n .freelens-power-dashboard .power-dashboard-card-l { grid-column: span var(--power-large-span, 4); grid-row: span 3; }\n .freelens-power-dashboard .power-dashboard-card-xl { grid-column: span var(--power-columns, 4); grid-row: span 3; }\n .freelens-power-dashboard .power-dashboard-card-header {\n display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 6px 12px;\n }\n .freelens-power-dashboard h2 { margin: 0; font-size: 14px; overflow-wrap: anywhere; }\n .freelens-power-dashboard .power-dashboard-card-title { display: flex; align-items: center; gap: 8px; min-width: 0; }\n .freelens-power-dashboard .power-dashboard-card-title h2 { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .freelens-power-dashboard .power-dashboard-card-xs .power-dashboard-card-header { flex-wrap: wrap; row-gap: 4px; }\n .freelens-power-dashboard .power-dashboard-card-xs .power-dashboard-card-title { flex-basis: 100%; }\n .freelens-power-dashboard .power-dashboard-card-xs .power-dashboard-card-actions { margin-left: auto; }\n .freelens-power-dashboard .power-dashboard-site-icon { width: 16px; height: 16px; border-radius: 4px; object-fit: contain; flex-shrink: 0; }\n .freelens-power-dashboard .power-dashboard-card-header a {\n flex-shrink: 0; color: var(--textColorPrimary); font-size: 12px; transition: color 160ms ease;\n }\n .freelens-power-dashboard .power-dashboard-card-header a .Icon { color: inherit; transition: color 160ms ease; }\n .freelens-power-dashboard .power-dashboard-card-header a:hover { color: var(--textColorAccent); }\n .freelens-power-dashboard .power-dashboard-embed { width: 100%; flex: 1; min-height: 0; overflow: hidden; }\n .freelens-power-dashboard .power-dashboard-skeleton { height: 100%; box-sizing: border-box; padding: 20px; display: flex; flex-direction: column; gap: 12px; background: var(--contentColor); }\n .freelens-power-dashboard .power-dashboard-skeleton span { height: 12px; border-radius: 6px; background: color-mix(in srgb, var(--textColorSecondary) 12%, transparent); animation: power-dashboard-loading 1.8s ease-in-out infinite; }\n .freelens-power-dashboard .power-dashboard-skeleton span:first-child { width: 45%; height: 20px; margin-bottom: 8px; }\n .freelens-power-dashboard .power-dashboard-skeleton span:last-child { flex: 1; min-height: 30px; }\n @keyframes power-dashboard-loading { 50% { opacity: .45; } }\n @media (prefers-reduced-motion: reduce) { .freelens-power-dashboard .power-dashboard-skeleton span { animation: none; } }\n .freelens-power-dashboard .power-dashboard-hint { margin: 16px 0 0; font-size: 12px; }\n .power-dashboard-right-tooltip { position: fixed !important; left: calc(anchor(right) + 8px) !important; top: anchor(center) !important; right: auto !important; bottom: auto !important; translate: 0 -50%; white-space: nowrap !important; max-width: none !important; }\n .freelens-power-dashboard .power-dashboard-empty {\n padding: 40px 24px; border: 1px solid var(--borderFaintColor); border-radius: 12px;\n background: var(--contentColor); text-align: center;\n }\n .freelens-power-dashboard .power-dashboard-empty > button { display:inline-flex; align-items:center; gap:7px; }\n .freelens-power-dashboard .power-dashboard-empty p { color: var(--textColorSecondary); margin: 12px 0 24px; }\n @media (max-width: 700px) {\n .ClusterManager main.freelens-power-dashboard, .freelens-power-dashboard { display: block; position: relative; z-index: 2; flex: 1; background: var(--mainBackground); padding: 18px; }\n .freelens-power-dashboard .power-dashboard-header { flex-wrap: wrap; }\n }\n`;\n\nfunction DashboardActionIcon({ material, tooltip }: { material: string; tooltip: string }) {\n const [anchor] = useState(() => `--power-dashboard-action-${crypto.randomUUID()}`);\n return (\n <Renderer.Component.Icon\n material={material}\n size={18}\n style={{ anchorName: anchor, \"--size\": \"18px\" } as CSSProperties}\n tooltip={{ children: tooltip, className: \"power-dashboard-right-tooltip\", style: { positionAnchor: anchor } }}\n />\n );\n}\n\nfunction WebsiteIcon({ url, favicon }: { url: string; favicon?: string }) {\n const [failed, setFailed] = useState(false);\n if (failed)\n return (\n <span className=\"power-dashboard-site-icon\" aria-hidden=\"true\">\n 🌐\n </span>\n );\n return (\n <img\n className=\"power-dashboard-site-icon\"\n src={favicon || new URL(\"/favicon.ico\", url).href}\n alt=\"\"\n loading=\"lazy\"\n referrerPolicy=\"no-referrer\"\n onError={() => setFailed(true)}\n />\n );\n}\n\nexport const DashboardPage = observer(({ onOpenPreferences }: { onOpenPreferences: () => void }) => {\n const preferences = DashboardPreferencesStore.getInstanceOrCreate<DashboardPreferencesStore>();\n const cards = preferences.cards.flatMap((card) => {\n const url = normalizeDashboardUrl(card.url);\n return url ? [{ ...card, url }] : [];\n });\n const root = useRef<HTMLElement>(null);\n const [expandedId, setExpandedId] = useState<string | null>(null);\n const expanded = cards.some((card) => card.id === expandedId) ? expandedId : null;\n const expandedRef = useRef<string | null>(null);\n const gridScrollTop = useRef<number | null>(null);\n expandedRef.current = expanded;\n useLayoutEffect(() => {\n const container = root.current;\n if (!container) return;\n if (expanded) container.scrollTop = 0;\n else if (gridScrollTop.current !== null) {\n container.scrollTop = gridScrollTop.current;\n gridScrollTop.current = null;\n }\n }, [expanded]);\n useEffect(() => {\n if (expandedId && !expanded) setExpandedId(null);\n }, [expandedId, expanded]);\n useEffect(() => {\n const restore = () => setExpandedId(null);\n const escape = (event: KeyboardEvent) => {\n if (event.key === \"Escape\" && expandedRef.current) {\n event.preventDefault();\n event.stopPropagation();\n restore();\n }\n };\n document.addEventListener(\"keydown\", escape, true);\n ipcRenderer.on(\"freelens-power:dashboard-escape\", restore);\n return () => {\n document.removeEventListener(\"keydown\", escape, true);\n ipcRenderer.removeListener(\"freelens-power:dashboard-escape\", restore);\n };\n }, []);\n const [loadFailed, setLoadFailed] = useState(false);\n const [loadingCards, setLoadingCards] = useState<Record<string, DashboardViewLoading>>({});\n useEffect(() => {\n const update = (_event: unknown, value: DashboardViewLoading) => {\n if (\n !value ||\n typeof value.id !== \"string\" ||\n typeof value.url !== \"string\" ||\n typeof value.loading !== \"boolean\" ||\n typeof value.failed !== \"boolean\" ||\n !preferences.cards.some((card) => card.id === value.id && normalizeDashboardUrl(card.url) === value.url)\n )\n return;\n setLoadingCards((previous) => {\n const existing = previous[value.id];\n return existing?.url === value.url && existing.loading === value.loading && existing.failed === value.failed\n ? previous\n : { ...previous, [value.id]: value };\n });\n if (value.failed) setLoadFailed(true);\n };\n ipcRenderer.on(DASHBOARD_VIEWS_LOADING, update);\n return () => {\n ipcRenderer.removeListener(DASHBOARD_VIEWS_LOADING, update);\n };\n }, [preferences]);\n const [reloading, setReloading] = useState(false);\n const [reloadBlocked, setReloadBlocked] = useState(false);\n const reloadRequest = useRef(0);\n const reloadCooldown = useRef<ReturnType<typeof setTimeout>>();\n useEffect(\n () => () => {\n ++reloadRequest.current;\n clearTimeout(reloadCooldown.current);\n },\n [],\n );\n const reloadCards = async () => {\n if (reloadCooldown.current) return;\n const request = ++reloadRequest.current;\n setReloading(true);\n setReloadBlocked(true);\n reloadCooldown.current = setTimeout(() => {\n reloadCooldown.current = undefined;\n setReloadBlocked(false);\n }, 1000);\n try {\n const results = await Promise.all(cards.map(({ id }) => ipcRenderer.invoke(DASHBOARD_VIEWS_RELOAD, { id })));\n if (reloadRequest.current === request) setLoadFailed(results.some((result) => result?.failed?.length));\n } catch {\n if (reloadRequest.current === request) setLoadFailed(true);\n } finally {\n if (reloadRequest.current === request) {\n clearTimeout(reloadCooldown.current);\n reloadCooldown.current = undefined;\n setReloadBlocked(false);\n setReloading(false);\n }\n }\n };\n const focusPinned = (id: string) => {\n void ipcRenderer.invoke(DASHBOARD_VIEWS_PIN, { id, focus: true }).catch(() => setLoadFailed(true));\n };\n const [pinnedCards, setPinnedCards] = useState<string[]>([]);\n useEffect(() => {\n const update = (_event: unknown, ids: unknown) => {\n if (Array.isArray(ids)) setPinnedCards(ids.filter((id): id is string => typeof id === \"string\"));\n };\n ipcRenderer.on(DASHBOARD_VIEWS_PINNED, update);\n return () => {\n ipcRenderer.removeListener(DASHBOARD_VIEWS_PINNED, update);\n };\n }, []);\n const togglePinned = async (id: string) => {\n try {\n const result = await ipcRenderer.invoke(DASHBOARD_VIEWS_PIN, { id, pinned: !pinnedCards.includes(id) });\n if (Array.isArray(result?.pinned))\n setPinnedCards(result.pinned.filter((value: unknown): value is string => typeof value === \"string\"));\n } catch {\n setLoadFailed(true);\n }\n };\n const [siteIcons, setSiteIcons] = useState<Record<string, string>>({});\n useEffect(() => {\n const update = (_event: unknown, icon: { id?: unknown; url?: unknown }) => {\n if (typeof icon?.id !== \"string\" || typeof icon.url !== \"string\") return;\n const imageData =\n icon.url.length <= 720_000 &&\n /^data:image\\/(?:png|jpeg|gif|webp|x-icon|vnd\\.microsoft\\.icon|svg\\+xml);base64,[A-Za-z0-9+/]+={0,2}$/.test(\n icon.url,\n );\n const url = imageData ? icon.url : normalizeDashboardUrl(icon.url);\n if (!url) return;\n const id = icon.id;\n setSiteIcons((previous) => (previous[id] === url ? previous : { ...previous, [id]: url }));\n };\n ipcRenderer.on(\"freelens-power:dashboard-site-icon\", update);\n return () => {\n ipcRenderer.removeListener(\"freelens-power:dashboard-site-icon\", update);\n };\n }, []);\n const cardIdentity = JSON.stringify(cards.map(({ id, url, size }) => ({ id, url, size })));\n useEffect(() => {\n setSiteIcons({});\n }, [cardIdentity]);\n useEffect(() => {\n const container = root.current;\n if (!container) return;\n let active = true;\n let frame = 0;\n const sync = () => {\n frame = 0;\n const containerStyle = window.getComputedStyle(container);\n const contentWidth =\n container.clientWidth -\n (Number.parseFloat(containerStyle.paddingLeft) || 0) -\n (Number.parseFloat(containerStyle.paddingRight) || 0);\n const columns = contentWidth >= 1200 ? 6 : contentWidth >= 800 ? 4 : contentWidth >= 520 ? 2 : 1;\n for (const [property, value] of Object.entries({\n \"--power-columns\": columns,\n \"--power-small-span\": Math.min(2, columns),\n \"--power-medium-span\": Math.min(4, columns),\n \"--power-large-span\": Math.min(4, columns),\n })) {\n if (container.style.getPropertyValue(property) !== String(value))\n container.style.setProperty(property, String(value));\n }\n const containerBounds = container.getBoundingClientRect();\n const viewport = {\n left: Math.max(0, containerBounds.left),\n top: Math.max(0, containerBounds.top),\n right: Math.min(window.innerWidth, containerBounds.right),\n bottom: Math.min(window.innerHeight, containerBounds.bottom),\n };\n for (let ancestor = container.parentElement; ancestor; ancestor = ancestor.parentElement) {\n const style = window.getComputedStyle(ancestor);\n const rect = ancestor.getBoundingClientRect();\n if (/^(auto|scroll|hidden|clip)$/.test(style.overflowX || style.overflow)) {\n viewport.left = Math.max(viewport.left, rect.left + ancestor.clientLeft);\n viewport.right = Math.min(viewport.right, rect.left + ancestor.clientLeft + ancestor.clientWidth);\n }\n if (/^(auto|scroll|hidden|clip)$/.test(style.overflowY || style.overflow)) {\n viewport.top = Math.max(viewport.top, rect.top + ancestor.clientTop);\n viewport.bottom = Math.min(viewport.bottom, rect.top + ancestor.clientTop + ancestor.clientHeight);\n }\n }\n const overlayOpen = Array.from(\n document.querySelectorAll<HTMLElement>('.Dialog, [role=\"dialog\"], [role=\"menu\"], .Menu, .power-ai-panel'),\n ).some((element) => {\n const rect = element.getBoundingClientRect();\n const style = window.getComputedStyle(element);\n return rect.width > 0 && rect.height > 0 && style.display !== \"none\" && style.visibility !== \"hidden\";\n });\n const visible = overlayOpen\n ? []\n : Array.from(container.querySelectorAll<HTMLElement>(\".power-dashboard-embed\")).flatMap((element) => {\n if (expandedRef.current && element.dataset.cardId !== expandedRef.current) return [];\n const rect = element.getBoundingClientRect();\n const x = Math.ceil(Math.max(rect.left, viewport.left));\n const y = Math.ceil(Math.max(rect.top, viewport.top));\n const right = Math.floor(Math.min(rect.right, viewport.right));\n const bottom = Math.floor(Math.min(rect.bottom, viewport.bottom));\n const bounds = {\n x: Math.floor(rect.left),\n y: Math.floor(rect.top),\n width: Math.ceil(rect.right) - Math.floor(rect.left),\n height: Math.ceil(rect.bottom) - Math.floor(rect.top),\n };\n const clip = { x, y, width: right - x, height: bottom - y };\n if (\n ![...Object.values(bounds), ...Object.values(clip)].every(Number.isFinite) ||\n rect.width <= 0 ||\n rect.height <= 0 ||\n clip.width <= 0 ||\n clip.height <= 0\n )\n return [];\n return [\n {\n id: element.dataset.cardId,\n bounds,\n clip,\n ...(expandedRef.current === element.dataset.cardId ? { scrollbars: true } : {}),\n },\n ];\n });\n void ipcRenderer\n .invoke(DASHBOARD_VIEWS_SYNC, {\n cards: visible,\n ...(overlayOpen ? { hidden: true } : {}),\n })\n .then(\n (result) => {\n if (active) {\n setLoadFailed(Boolean(result?.failed?.length));\n if (Array.isArray(result?.pinned)) setPinnedCards(result.pinned);\n }\n },\n () => {\n if (active) setLoadFailed(true);\n },\n );\n };\n const schedule = () => {\n if (!frame) frame = window.requestAnimationFrame(sync);\n };\n const activate = () => {\n if (document.visibilityState === \"hidden\") return;\n schedule();\n };\n const mutations = new MutationObserver(schedule);\n mutations.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: [\"class\", \"style\", \"hidden\"],\n });\n const observer = new ResizeObserver(schedule);\n observer.observe(container);\n for (let ancestor = container.parentElement; ancestor; ancestor = ancestor.parentElement)\n observer.observe(ancestor);\n for (const element of container.querySelectorAll(\".power-dashboard-embed\")) observer.observe(element);\n document.addEventListener(\"scroll\", schedule, true);\n window.addEventListener(\"resize\", schedule);\n window.addEventListener(\"focus\", activate);\n document.addEventListener(\"visibilitychange\", activate);\n schedule();\n return () => {\n active = false;\n window.cancelAnimationFrame(frame);\n observer.disconnect();\n mutations.disconnect();\n document.removeEventListener(\"scroll\", schedule, true);\n window.removeEventListener(\"resize\", schedule);\n window.removeEventListener(\"focus\", activate);\n document.removeEventListener(\"visibilitychange\", activate);\n void ipcRenderer.invoke(DASHBOARD_VIEWS_CLEAR).catch(() => {});\n };\n }, [cardIdentity]);\n\n return (\n <main ref={root} className={`freelens-power-dashboard${expanded ? \" power-dashboard-expanded\" : \"\"}`}>\n <style>{styles}</style>\n <header className=\"power-dashboard-header\">\n <div>\n <h1>🔋 Power Dashboard</h1>\n </div>\n <div className=\"power-dashboard-actions\">\n <button\n type=\"button\"\n className=\"power-dashboard-action power-dashboard-refresh\"\n aria-label=\"Refresh\"\n aria-busy={reloading}\n disabled={reloadBlocked || cards.length === 0}\n onClick={() => {\n void reloadCards();\n }}\n >\n <Renderer.Component.Icon material=\"refresh\" size={18} tooltip=\"Refresh\" />\n </button>\n <button type=\"button\" className=\"power-dashboard-action\" onClick={onOpenPreferences}>\n <span aria-hidden=\"true\">\n <Renderer.Component.Icon material=\"dashboard\" size={16} />\n </span>{\" \"}\n Settings\n </button>\n </div>\n </header>\n {cards.length === 0 ? (\n <section className=\"power-dashboard-empty\">\n <h2>Build your dashboard</h2>\n <p>Add your favorite tools and pages in Settings.</p>\n <button type=\"button\" onClick={onOpenPreferences}>\n <span aria-hidden=\"true\">\n <Renderer.Component.Icon material=\"add\" size={16} />\n </span>\n Add cards\n </button>\n </section>\n ) : (\n <>\n <div className=\"power-dashboard-grid\">\n {cards.map((card) => (\n <section\n key={card.id}\n hidden={Boolean(expanded && expanded !== card.id)}\n className={`power-dashboard-card power-dashboard-card-${card.size}${pinnedCards.includes(card.id) ? \" power-dashboard-card-pinned\" : \"\"}`}\n >\n <header className=\"power-dashboard-card-header\">\n <div className=\"power-dashboard-card-title\">\n <WebsiteIcon\n key={`${card.url}:${siteIcons[card.id] || \"\"}`}\n url={card.url}\n favicon={siteIcons[card.id]}\n />\n <h2>{card.title}</h2>\n </div>\n <div className=\"power-dashboard-card-actions\">\n <button\n type=\"button\"\n className=\"power-dashboard-expand\"\n aria-label={`Auto-refresh ${card.title} every 10 seconds`}\n aria-pressed={card.refreshEvery10Seconds === true}\n onClick={() => {\n preferences.upsertCard({ ...card, refreshEvery10Seconds: !card.refreshEvery10Seconds });\n }}\n >\n <DashboardActionIcon\n material=\"autorenew\"\n tooltip={card.refreshEvery10Seconds ? \"Disable refresh\" : \"Enable refresh (10s)\"}\n />\n </button>\n <button\n type=\"button\"\n className=\"power-dashboard-expand\"\n aria-label={`${pinnedCards.includes(card.id) ? \"Unpin\" : \"Pin\"} ${card.title}`}\n aria-pressed={pinnedCards.includes(card.id)}\n onClick={() => {\n void togglePinned(card.id);\n }}\n >\n <DashboardActionIcon\n material=\"push_pin\"\n tooltip={pinnedCards.includes(card.id) ? \"Unpin\" : \"Pin\"}\n />\n </button>\n <button\n type=\"button\"\n className=\"power-dashboard-expand\"\n aria-label={`${expanded === card.id ? \"Restore\" : \"Expand\"} ${card.title}`}\n aria-pressed={expanded === card.id}\n onClick={() => {\n if (!expanded) gridScrollTop.current = root.current?.scrollTop ?? 0;\n setExpandedId(expanded === card.id ? null : card.id);\n }}\n >\n <DashboardActionIcon\n material={expanded === card.id ? \"fullscreen_exit\" : \"fullscreen\"}\n tooltip={expanded === card.id ? \"Restore\" : \"Expand\"}\n />\n </button>\n <a\n href={card.url}\n onClick={(event) => {\n event.preventDefault();\n void shell.openExternal(card.url);\n }}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label={`Open ${card.title} in browser`}\n >\n <DashboardActionIcon material=\"open_in_new\" tooltip=\"Open\" />\n </a>\n </div>\n </header>\n <div\n className=\"power-dashboard-embed\"\n data-card-id={card.id}\n role=\"region\"\n aria-label={card.title}\n aria-busy={loadingCards[card.id]?.url === card.url && loadingCards[card.id]?.loading}\n >\n {!pinnedCards.includes(card.id) &&\n loadingCards[card.id]?.url === card.url &&\n loadingCards[card.id]?.loading && (\n <div className=\"power-dashboard-skeleton\" role=\"status\" aria-label={`Loading ${card.title}`}>\n <span aria-hidden=\"true\" />\n <span aria-hidden=\"true\" />\n <span aria-hidden=\"true\" />\n </div>\n )}\n {pinnedCards.includes(card.id) && (\n <button\n type=\"button\"\n className=\"power-dashboard-pin-placeholder\"\n onClick={() => focusPinned(card.id)}\n aria-label={`Focus pinned ${card.title}`}\n >\n <Renderer.Component.Icon material=\"push_pin\" size={28} />\n <span>Pinned above other windows</span>\n <span>Focus window</span>\n </button>\n )}\n </div>\n </section>\n ))}\n </div>\n {loadFailed && (\n <p role=\"alert\" className=\"power-dashboard-hint\">\n Unable to load dashboard cards. Open them in your browser.\n </p>\n )}\n </>\n )}\n </main>\n );\n});\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@64mb/freelens-power",
3
- "version": "2.2.0",
3
+ "version": "2.2.1",
4
4
  "description": "Power tools for Freelens Kubernetes IDE",
5
5
  "main": "out/main/index.js",
6
6
  "renderer": "out/renderer/index.js",