@64mb/freelens-power 1.1.0 → 1.2.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.
- package/README.md +5 -4
- package/THIRD_PARTY_LICENSES +1707 -0
- package/out/main/ai.js +63 -23
- package/out/main/ai.js.map +1 -1
- package/out/main/cluster-icons-catalog.js +28 -0
- package/out/main/cluster-icons-catalog.js.map +1 -0
- package/out/main/cluster-icons.js +125 -0
- package/out/main/cluster-icons.js.map +1 -0
- package/out/main/common/ai-terminal-context.js +51 -0
- package/out/main/common/ai-terminal-context.js.map +1 -0
- package/out/main/common/ai.js.map +1 -1
- package/out/main/common/cluster-icon-ipc.js +6 -0
- package/out/main/common/cluster-icon-ipc.js.map +1 -0
- package/out/main/common/cluster-icons.js +121 -0
- package/out/main/common/cluster-icons.js.map +1 -0
- package/out/main/common/dashboard.js +1 -1
- package/out/main/common/dashboard.js.map +1 -1
- package/out/main/common/settings-export.js +3 -1
- package/out/main/common/settings-export.js.map +1 -1
- package/out/main/common/store/cluster-icons-store.js +32 -0
- package/out/main/common/store/cluster-icons-store.js.map +1 -0
- package/out/main/common/store/monitoring-preferences-store.js +5 -0
- package/out/main/common/store/monitoring-preferences-store.js.map +1 -1
- package/out/main/diagnostics-menu-order.js +57 -0
- package/out/main/diagnostics-menu-order.js.map +1 -0
- package/out/main/index.js +9 -1
- package/out/main/index.js.map +1 -1
- package/out/main/monitoring-history.js +13 -3
- package/out/main/monitoring-history.js.map +1 -1
- package/out/renderer/_virtual/_global-external_react-dom.js +2 -1
- package/out/renderer/_virtual/_global-external_react.js +10 -5
- package/out/renderer/_virtual/_rolldown/runtime.js +22 -0
- package/out/renderer/ai-terminal-context.js +200 -0
- package/out/renderer/ai-terminal-context.js.map +1 -0
- package/out/renderer/ai.js +90 -9
- package/out/renderer/ai.js.map +1 -1
- package/out/renderer/appearance.js +1 -0
- package/out/renderer/appearance.js.map +1 -1
- package/out/renderer/cluster-icon-colors.js +188 -0
- package/out/renderer/cluster-icon-colors.js.map +1 -0
- package/out/renderer/cluster-icons.js +304 -0
- package/out/renderer/cluster-icons.js.map +1 -0
- package/out/renderer/dashboard.js +8 -5
- package/out/renderer/dashboard.js.map +1 -1
- package/out/renderer/details/secret-certificate-details.js +9 -2
- package/out/renderer/details/secret-certificate-details.js.map +1 -1
- package/out/renderer/diagnostics.css.js +39 -0
- package/out/renderer/diagnostics.css.js.map +1 -0
- package/out/renderer/diagnostics.js +796 -343
- package/out/renderer/diagnostics.js.map +1 -1
- package/out/renderer/index.js +9 -4
- package/out/renderer/index.js.map +1 -1
- package/out/renderer/monitoring-details-chart.js +42 -0
- package/out/renderer/monitoring-details-chart.js.map +1 -0
- package/out/renderer/monitoring-history-collection.js +2 -18
- package/out/renderer/monitoring-history-collection.js.map +1 -1
- package/out/renderer/monitoring-history-view.js +111 -34
- package/out/renderer/monitoring-history-view.js.map +1 -1
- package/out/renderer/monitoring.js +68 -27
- package/out/renderer/monitoring.js.map +1 -1
- package/out/renderer/node-monitoring.js +23 -12
- package/out/renderer/node-monitoring.js.map +1 -1
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/arrayLikeToArray.js +10 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/arrayLikeToArray.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/arrayWithHoles.js +8 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/arrayWithHoles.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/arrayWithoutHoles.js +9 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/arrayWithoutHoles.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/assertThisInitialized.js +9 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/assertThisInitialized.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/classCallCheck.js +8 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/classCallCheck.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/createClass.js +15 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/createClass.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/createSuper.js +19 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/createSuper.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/defineProperty.js +14 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/defineProperty.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/extends.js +19 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/extends.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/getPrototypeOf.js +15 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/getPrototypeOf.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/inherits.js +14 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/inherits.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/isNativeReflectConstruct.js +18 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/isNativeReflectConstruct.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/iterableToArray.js +8 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/iterableToArray.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/iterableToArrayLimit.js +26 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/iterableToArrayLimit.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/nonIterableRest.js +8 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/nonIterableRest.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/nonIterableSpread.js +8 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/nonIterableSpread.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/objectSpread2.js +27 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/objectSpread2.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/objectWithoutProperties.js +15 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/objectWithoutProperties.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js +14 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/possibleConstructorReturn.js +12 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/possibleConstructorReturn.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js +15 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/slicedToArray.js +12 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/slicedToArray.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/taggedTemplateLiteral.js +8 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/taggedTemplateLiteral.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/toConsumableArray.js +12 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/toConsumableArray.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/toPrimitive.js +16 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/toPrimitive.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/toPropertyKey.js +11 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/toPropertyKey.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/typeof.js +18 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/typeof.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/unsupportedIterableToArray.js +13 -0
- package/out/renderer/node_modules/.pnpm/@babel_runtime@7.27.6/node_modules/@babel/runtime/helpers/esm/unsupportedIterableToArray.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@emotion_cache@11.14.0/node_modules/@emotion/cache/dist/emotion-cache.browser.esm.js +237 -0
- package/out/renderer/node_modules/.pnpm/@emotion_cache@11.14.0/node_modules/@emotion/cache/dist/emotion-cache.browser.esm.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@emotion_hash@0.9.2/node_modules/@emotion/hash/dist/emotion-hash.esm.js +25 -0
- package/out/renderer/node_modules/.pnpm/@emotion_hash@0.9.2/node_modules/@emotion/hash/dist/emotion-hash.esm.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@emotion_memoize@0.9.0/node_modules/@emotion/memoize/dist/emotion-memoize.esm.js +12 -0
- package/out/renderer/node_modules/.pnpm/@emotion_memoize@0.9.0/node_modules/@emotion/memoize/dist/emotion-memoize.esm.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@emotion_react@11.14.0_@types_react@17.0.93_react@17.0.2/node_modules/@emotion/react/dist/emotion-element-f0de968e.browser.esm.js +58 -0
- package/out/renderer/node_modules/.pnpm/@emotion_react@11.14.0_@types_react@17.0.93_react@17.0.2/node_modules/@emotion/react/dist/emotion-element-f0de968e.browser.esm.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@emotion_react@11.14.0_@types_react@17.0.93_react@17.0.2/node_modules/@emotion/react/dist/emotion-react.browser.esm.js +54 -0
- package/out/renderer/node_modules/.pnpm/@emotion_react@11.14.0_@types_react@17.0.93_react@17.0.2/node_modules/@emotion/react/dist/emotion-react.browser.esm.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@emotion_serialize@1.3.3/node_modules/@emotion/serialize/dist/emotion-serialize.esm.js +133 -0
- package/out/renderer/node_modules/.pnpm/@emotion_serialize@1.3.3/node_modules/@emotion/serialize/dist/emotion-serialize.esm.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@emotion_sheet@1.4.0/node_modules/@emotion/sheet/dist/emotion-sheet.esm.js +65 -0
- package/out/renderer/node_modules/.pnpm/@emotion_sheet@1.4.0/node_modules/@emotion/sheet/dist/emotion-sheet.esm.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@emotion_unitless@0.10.0/node_modules/@emotion/unitless/dist/emotion-unitless.esm.js +54 -0
- package/out/renderer/node_modules/.pnpm/@emotion_unitless@0.10.0/node_modules/@emotion/unitless/dist/emotion-unitless.esm.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@emotion_use-insertion-effect-with-fallbacks@1.2.0_react@17.0.2/node_modules/@emotion/use-insertion-effect-with-fallbacks/dist/emotion-use-insertion-effect-with-fallbacks.browser.esm.js +12 -0
- package/out/renderer/node_modules/.pnpm/@emotion_use-insertion-effect-with-fallbacks@1.2.0_react@17.0.2/node_modules/@emotion/use-insertion-effect-with-fallbacks/dist/emotion-use-insertion-effect-with-fallbacks.browser.esm.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@emotion_utils@1.4.2/node_modules/@emotion/utils/dist/emotion-utils.browser.esm.js +30 -0
- package/out/renderer/node_modules/.pnpm/@emotion_utils@1.4.2/node_modules/@emotion/utils/dist/emotion-utils.browser.esm.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@floating-ui_dom@1.7.2/node_modules/@floating-ui/dom/dist/floating-ui.dom.js +211 -0
- package/out/renderer/node_modules/.pnpm/@floating-ui_dom@1.7.2/node_modules/@floating-ui/dom/dist/floating-ui.dom.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@floating-ui_utils@0.2.10/node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.js +97 -0
- package/out/renderer/node_modules/.pnpm/@floating-ui_utils@0.2.10/node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/@floating-ui_utils@0.2.10/node_modules/@floating-ui/utils/dist/floating-ui.utils.js +31 -0
- package/out/renderer/node_modules/.pnpm/@floating-ui_utils@0.2.10/node_modules/@floating-ui/utils/dist/floating-ui.utils.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/hoist-non-react-statics@3.3.2/node_modules/hoist-non-react-statics/dist/hoist-non-react-statics.cjs.js +93 -0
- package/out/renderer/node_modules/.pnpm/hoist-non-react-statics@3.3.2/node_modules/hoist-non-react-statics/dist/hoist-non-react-statics.cjs.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/memoize-one@6.0.0/node_modules/memoize-one/dist/memoize-one.esm.js +38 -0
- package/out/renderer/node_modules/.pnpm/memoize-one@6.0.0/node_modules/memoize-one/dist/memoize-one.esm.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/cjs/react-is.development.js +159 -0
- package/out/renderer/node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/cjs/react-is.development.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/cjs/react-is.production.min.js +103 -0
- package/out/renderer/node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/cjs/react-is.production.min.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/index.js +18 -0
- package/out/renderer/node_modules/.pnpm/react-is@16.13.1/node_modules/react-is/index.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/react-select@5.10.2_@types_react@17.0.93_react-dom@17.0.2_react@17.0.2__react@17.0.2/node_modules/react-select/dist/Select-ef7c0426.esm.js +2200 -0
- package/out/renderer/node_modules/.pnpm/react-select@5.10.2_@types_react@17.0.93_react-dom@17.0.2_react@17.0.2__react@17.0.2/node_modules/react-select/dist/Select-ef7c0426.esm.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/react-select@5.10.2_@types_react@17.0.93_react-dom@17.0.2_react@17.0.2__react@17.0.2/node_modules/react-select/dist/index-641ee5b8.esm.js +992 -0
- package/out/renderer/node_modules/.pnpm/react-select@5.10.2_@types_react@17.0.93_react-dom@17.0.2_react@17.0.2__react@17.0.2/node_modules/react-select/dist/index-641ee5b8.esm.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/react-select@5.10.2_@types_react@17.0.93_react-dom@17.0.2_react@17.0.2__react@17.0.2/node_modules/react-select/dist/react-select.esm.js +14 -0
- package/out/renderer/node_modules/.pnpm/react-select@5.10.2_@types_react@17.0.93_react-dom@17.0.2_react@17.0.2__react@17.0.2/node_modules/react-select/dist/react-select.esm.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/react-select@5.10.2_@types_react@17.0.93_react-dom@17.0.2_react@17.0.2__react@17.0.2/node_modules/react-select/dist/useStateManager-7e1e8489.esm.js +56 -0
- package/out/renderer/node_modules/.pnpm/react-select@5.10.2_@types_react@17.0.93_react-dom@17.0.2_react@17.0.2__react@17.0.2/node_modules/react-select/dist/useStateManager-7e1e8489.esm.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Enum.js +22 -0
- package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Enum.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Middleware.js +30 -0
- package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Middleware.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Parser.js +164 -0
- package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Parser.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Serializer.js +37 -0
- package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Serializer.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Tokenizer.js +245 -0
- package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Tokenizer.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Utility.js +120 -0
- package/out/renderer/node_modules/.pnpm/stylis@4.2.0/node_modules/stylis/src/Utility.js.map +1 -0
- package/out/renderer/node_modules/.pnpm/use-isomorphic-layout-effect@1.2.1_@types_react@17.0.93_react@17.0.2/node_modules/use-isomorphic-layout-effect/dist/use-isomorphic-layout-effect.browser.esm.js +6 -0
- package/out/renderer/node_modules/.pnpm/use-isomorphic-layout-effect@1.2.1_@types_react@17.0.93_react@17.0.2/node_modules/use-isomorphic-layout-effect/dist/use-isomorphic-layout-effect.browser.esm.js.map +1 -0
- package/out/renderer/pod-monitoring.js +15 -19
- package/out/renderer/pod-monitoring.js.map +1 -1
- package/out/renderer/preferences/ai-shortcuts-preferences.js +12 -4
- package/out/renderer/preferences/ai-shortcuts-preferences.js.map +1 -1
- package/out/renderer/preferences/dashboard-preferences.js +20 -4
- package/out/renderer/preferences/dashboard-preferences.js.map +1 -1
- package/out/renderer/preferences/monitoring-preferences.js +131 -44
- package/out/renderer/preferences/monitoring-preferences.js.map +1 -1
- package/out/renderer/preferences/preferences.js +31 -7
- package/out/renderer/preferences/preferences.js.map +1 -1
- package/out/renderer/read-only.js +2 -2
- package/out/renderer/read-only.js.map +1 -1
- package/out/renderer/src/common/ai-terminal-context.js +51 -0
- package/out/renderer/src/common/ai-terminal-context.js.map +1 -0
- package/out/renderer/src/common/ai.js.map +1 -1
- package/out/renderer/src/common/cluster-icon-ipc.js +6 -0
- package/out/renderer/src/common/cluster-icon-ipc.js.map +1 -0
- package/out/renderer/src/common/cluster-icons.js +133 -0
- package/out/renderer/src/common/cluster-icons.js.map +1 -0
- package/out/renderer/src/common/dashboard.js +1 -1
- package/out/renderer/src/common/dashboard.js.map +1 -1
- package/out/renderer/src/common/date-time.js +11 -0
- package/out/renderer/src/common/date-time.js.map +1 -0
- package/out/renderer/src/common/monitoring-history.js +2 -0
- package/out/renderer/src/common/monitoring-history.js.map +1 -1
- package/out/renderer/src/common/resource-diagnostics.js.map +1 -1
- package/out/renderer/src/common/settings-export.js.map +1 -1
- package/out/renderer/src/common/store/monitoring-preferences-store.js +5 -0
- package/out/renderer/src/common/store/monitoring-preferences-store.js.map +1 -1
- package/out/renderer/welcome.js +28 -6
- package/out/renderer/welcome.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
const require_extensions = require("./_virtual/_global-external_@freelensapp/extensions.js");
|
|
2
|
+
const require__global_external_react = require("./_virtual/_global-external_react.js");
|
|
3
|
+
const require_jsx_runtime = require("./_virtual/_global-external_react/jsx-runtime.js");
|
|
4
|
+
const require_cluster_icon_ipc = require("./src/common/cluster-icon-ipc.js");
|
|
5
|
+
const require_cluster_icons = require("./src/common/cluster-icons.js");
|
|
6
|
+
const require_cluster_icon_colors = require("./cluster-icon-colors.js");
|
|
7
|
+
const require_settings_modal = require("./preferences/settings-modal.js");
|
|
8
|
+
let electron = require("electron");
|
|
9
|
+
//#region src/renderer/cluster-icons.tsx
|
|
10
|
+
var styles = `
|
|
11
|
+
.ClusterManager main.power-icon-studio, .power-icon-studio { display: block; position: relative; z-index: 2; flex: 1; min-width: 0; height: 100%; overflow: auto; padding: 32px; box-sizing: border-box; background: var(--mainBackground); color: var(--textColorPrimary); }
|
|
12
|
+
.power-icon-studio > .power-icon-content { max-width: 1000px; margin: 0 auto; }
|
|
13
|
+
.power-icon-header { display: flex; align-items: center; justify-content: space-between; gap: 24px; margin-bottom: 28px; }
|
|
14
|
+
.power-icon-header h1 { font-size: 24px; font-weight: 600; margin: 0 0 8px; color: var(--textColorAccent); }
|
|
15
|
+
.power-icon-header p { margin: 0; color: var(--textColorSecondary); }
|
|
16
|
+
.power-icon-search { width: 240px; }
|
|
17
|
+
.power-icon-grid { display: grid; grid-template-columns: repeat(5,minmax(0,1fr)); gap: 16px; }
|
|
18
|
+
.power-icon-card { display: flex; flex-direction: column; align-items: center; gap: 12px; position: relative; padding: 20px 14px 16px; min-width: 0; border: 1px solid var(--borderFaintColor); border-radius: 14px; background: var(--contentColor); color: var(--textColorPrimary); font: inherit; cursor: pointer; transition: border-color 150ms ease, background-color 150ms ease, transform 150ms ease; }
|
|
19
|
+
.power-icon-card:hover { border-color: var(--primary); background: color-mix(in srgb,var(--primary) 4%,var(--contentColor)); transform: translateY(-2px); }
|
|
20
|
+
.power-icon-card:focus-visible, .power-icon-glyph:focus-visible, .power-icon-swatch:focus-visible { outline: 2px solid var(--primary); outline-offset: 3px; }
|
|
21
|
+
.power-icon-card > img, .power-icon-card .power-icon-current-avatar { width: 64px; height: 64px; object-fit: contain; border-radius: 16px; }
|
|
22
|
+
.power-icon-card-name { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
|
|
23
|
+
.power-icon-empty { padding: 64px 24px; text-align: center; border: 1px dashed var(--borderFaintColor); border-radius: 14px; color: var(--textColorSecondary); }
|
|
24
|
+
.power-icon-editor { display: grid; grid-template-columns: 144px minmax(0,1fr); gap: 24px; }
|
|
25
|
+
.power-icon-preview { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 22px; padding: 24px 12px; border: 1px solid var(--borderFaintColor); border-radius: 12px; background: var(--contentColor); }
|
|
26
|
+
.power-icon-preview-main { width: 96px; height: 96px; }
|
|
27
|
+
.power-icon-preview-sizes { display: flex; align-items: center; gap: 14px; }
|
|
28
|
+
.power-icon-preview-caption { font-size: 11px; color: var(--textColorSecondary); }
|
|
29
|
+
.power-icon-fields { display: grid; gap: 16px; }
|
|
30
|
+
.power-icon-field { display: flex; align-items: center; justify-content: space-between; gap: 12px; font-size: 13px; }
|
|
31
|
+
.power-icon-field input[type=text] { width: 100px; padding: 8px 10px; border: 1px solid var(--borderFaintColor); border-radius: 6px; background: var(--contentColor); color: var(--textColorPrimary); font: inherit; }
|
|
32
|
+
.power-icon-field input:focus-visible { outline: 1px solid var(--primary); }
|
|
33
|
+
.power-icon-section-label { color: var(--textColorSecondary); font-size: 12px; margin-bottom: 10px; }
|
|
34
|
+
.power-icon-glyphs { display: grid; grid-template-columns: repeat(5,minmax(0,1fr)); gap: 8px; }
|
|
35
|
+
.power-icon-glyph { display: flex; align-items: center; justify-content: center; min-height: 54px; padding: 6px; border: 1px solid var(--borderFaintColor); border-radius: 8px; background: var(--contentColor); cursor: pointer; transition: border-color 150ms ease, background-color 150ms ease; }
|
|
36
|
+
.power-icon-glyph:hover, .power-icon-glyph[aria-pressed=true] { border-color: var(--primary); background: color-mix(in srgb,var(--primary) 8%,var(--contentColor)); }
|
|
37
|
+
.power-icon-glyph img { width: 38px; height: 38px; }
|
|
38
|
+
.power-icon-swatches { display: flex; align-items: center; gap: 8px; }
|
|
39
|
+
.power-icon-swatch { width: 22px; height: 22px; border: 2px solid transparent; border-radius: 50%; cursor: pointer; }
|
|
40
|
+
.power-icon-swatch[aria-pressed=true] { box-shadow: 0 0 0 2px var(--mainBackground),0 0 0 3px var(--primary); }
|
|
41
|
+
.power-icon-footer { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding-top: 12px; border-top: 1px solid var(--borderFaintColor); }
|
|
42
|
+
.power-icon-footer-actions { display: flex; gap: 8px; margin-left: auto; }
|
|
43
|
+
.power-icon-error { color: var(--colorError); font-size: 12px; line-height: 1.5; }
|
|
44
|
+
@media (max-width: 900px) { .power-icon-grid { grid-template-columns: repeat(4,minmax(0,1fr)); } }
|
|
45
|
+
@media (max-width: 700px) { .power-icon-header { align-items: stretch; flex-direction: column; } .power-icon-search { width: 100%; } .power-icon-grid { grid-template-columns: repeat(3,minmax(0,1fr)); } .ClusterManager main.power-icon-studio, .power-icon-studio { padding: 20px; } }
|
|
46
|
+
@media (max-width: 480px) { .power-icon-grid { grid-template-columns: repeat(2,minmax(0,1fr)); } .power-icon-editor { grid-template-columns: 1fr; } .power-icon-preview { flex-direction: row; padding: 16px; } .power-icon-preview-main { width: 72px; height: 72px; } }
|
|
47
|
+
@media (prefers-reduced-motion: reduce) { .power-icon-card { transition: none; transform: none; } }
|
|
48
|
+
`;
|
|
49
|
+
function IconEditor({ entry, onClose, onSaved }) {
|
|
50
|
+
const [design, setDesign] = require__global_external_react.useState(() => entry.design ?? require_cluster_icons.defaultClusterIconDesign(entry.name));
|
|
51
|
+
const [busy, setBusy] = require__global_external_react.useState(false);
|
|
52
|
+
const [error, setError] = require__global_external_react.useState("");
|
|
53
|
+
const paletteOpen = require__global_external_react.useRef(false);
|
|
54
|
+
const onPaletteOpenChange = require__global_external_react.useCallback((open) => {
|
|
55
|
+
paletteOpen.current = open;
|
|
56
|
+
}, []);
|
|
57
|
+
const update = (key, value) => setDesign((previous) => ({
|
|
58
|
+
...previous,
|
|
59
|
+
[key]: value
|
|
60
|
+
}));
|
|
61
|
+
const save = async () => {
|
|
62
|
+
setBusy(true);
|
|
63
|
+
setError("");
|
|
64
|
+
try {
|
|
65
|
+
onSaved(await electron.ipcRenderer.invoke(require_cluster_icon_ipc.CLUSTER_ICONS_CHANNEL, {
|
|
66
|
+
operation: "apply",
|
|
67
|
+
id: entry.id,
|
|
68
|
+
design
|
|
69
|
+
}));
|
|
70
|
+
} catch {
|
|
71
|
+
setError("Unable to save this cluster icon. Try again.");
|
|
72
|
+
} finally {
|
|
73
|
+
setBusy(false);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
let validDesign;
|
|
77
|
+
try {
|
|
78
|
+
validDesign = require_cluster_icons.normalizeClusterIconDesign(design);
|
|
79
|
+
} catch {
|
|
80
|
+
validDesign = void 0;
|
|
81
|
+
}
|
|
82
|
+
const previewDesign = validDesign ?? require_cluster_icons.defaultClusterIconDesign(entry.name);
|
|
83
|
+
const preview = require_cluster_icons.clusterIconDataUrl(previewDesign);
|
|
84
|
+
return /* @__PURE__ */ require_jsx_runtime.jsxs(require_settings_modal.SettingsModal, {
|
|
85
|
+
id: "power-cluster-icon-editor",
|
|
86
|
+
title: entry.name,
|
|
87
|
+
onClose: () => {
|
|
88
|
+
if (!busy && !paletteOpen.current) onClose();
|
|
89
|
+
},
|
|
90
|
+
children: [
|
|
91
|
+
/* @__PURE__ */ require_jsx_runtime.jsx("style", { children: styles }),
|
|
92
|
+
/* @__PURE__ */ require_jsx_runtime.jsxs("div", {
|
|
93
|
+
className: "power-icon-editor",
|
|
94
|
+
children: [/* @__PURE__ */ require_jsx_runtime.jsxs("div", {
|
|
95
|
+
className: "power-icon-preview",
|
|
96
|
+
children: [
|
|
97
|
+
/* @__PURE__ */ require_jsx_runtime.jsx("img", {
|
|
98
|
+
className: "power-icon-preview-main",
|
|
99
|
+
src: preview,
|
|
100
|
+
alt: "Cluster icon preview"
|
|
101
|
+
}),
|
|
102
|
+
/* @__PURE__ */ require_jsx_runtime.jsx("div", {
|
|
103
|
+
className: "power-icon-preview-sizes",
|
|
104
|
+
children: /* @__PURE__ */ require_jsx_runtime.jsx("img", {
|
|
105
|
+
src: preview,
|
|
106
|
+
width: 36,
|
|
107
|
+
height: 36,
|
|
108
|
+
alt: ""
|
|
109
|
+
})
|
|
110
|
+
}),
|
|
111
|
+
/* @__PURE__ */ require_jsx_runtime.jsx("span", {
|
|
112
|
+
className: "power-icon-preview-caption",
|
|
113
|
+
children: "Sidebar preview"
|
|
114
|
+
})
|
|
115
|
+
]
|
|
116
|
+
}), /* @__PURE__ */ require_jsx_runtime.jsxs("div", {
|
|
117
|
+
className: "power-icon-fields",
|
|
118
|
+
children: [
|
|
119
|
+
/* @__PURE__ */ require_jsx_runtime.jsxs("label", {
|
|
120
|
+
className: "power-icon-field",
|
|
121
|
+
htmlFor: "power-icon-label",
|
|
122
|
+
children: ["Label", /* @__PURE__ */ require_jsx_runtime.jsx("input", {
|
|
123
|
+
id: "power-icon-label",
|
|
124
|
+
type: "text",
|
|
125
|
+
value: design.label,
|
|
126
|
+
onChange: (event) => update("label", Array.from(event.target.value).slice(0, 3).join("")),
|
|
127
|
+
disabled: busy,
|
|
128
|
+
autoFocus: true
|
|
129
|
+
})]
|
|
130
|
+
}),
|
|
131
|
+
[
|
|
132
|
+
["outlineColor", "Outline"],
|
|
133
|
+
["labelColor", "Label color"],
|
|
134
|
+
["iconColor", "Icon color"]
|
|
135
|
+
].map(([key, label]) => /* @__PURE__ */ require_jsx_runtime.jsxs("div", {
|
|
136
|
+
className: "power-icon-field",
|
|
137
|
+
children: [/* @__PURE__ */ require_jsx_runtime.jsx("span", { children: label }), /* @__PURE__ */ require_jsx_runtime.jsx(require_cluster_icon_colors.IconColorPicker, {
|
|
138
|
+
label,
|
|
139
|
+
value: design[key],
|
|
140
|
+
onChange: (color) => update(key, color),
|
|
141
|
+
disabled: busy,
|
|
142
|
+
onOpenChange: onPaletteOpenChange
|
|
143
|
+
})]
|
|
144
|
+
}, key)),
|
|
145
|
+
/* @__PURE__ */ require_jsx_runtime.jsxs("div", { children: [/* @__PURE__ */ require_jsx_runtime.jsx("div", {
|
|
146
|
+
className: "power-icon-section-label",
|
|
147
|
+
children: "Matching outline & label"
|
|
148
|
+
}), /* @__PURE__ */ require_jsx_runtime.jsx("div", {
|
|
149
|
+
className: "power-icon-swatches",
|
|
150
|
+
children: require_cluster_icon_colors.MATCHING_ICON_COLORS.map(({ name, color }) => /* @__PURE__ */ require_jsx_runtime.jsx("button", {
|
|
151
|
+
type: "button",
|
|
152
|
+
className: "power-icon-swatch",
|
|
153
|
+
style: { background: color },
|
|
154
|
+
title: `${name} · ${color}`,
|
|
155
|
+
"aria-label": `Use ${color} for outline and label`,
|
|
156
|
+
"aria-pressed": design.outlineColor === color && design.labelColor === color,
|
|
157
|
+
disabled: busy,
|
|
158
|
+
onClick: () => setDesign((previous) => ({
|
|
159
|
+
...previous,
|
|
160
|
+
outlineColor: color,
|
|
161
|
+
labelColor: color
|
|
162
|
+
}))
|
|
163
|
+
}, color))
|
|
164
|
+
})] })
|
|
165
|
+
]
|
|
166
|
+
})]
|
|
167
|
+
}),
|
|
168
|
+
/* @__PURE__ */ require_jsx_runtime.jsxs("div", { children: [/* @__PURE__ */ require_jsx_runtime.jsx("div", {
|
|
169
|
+
className: "power-icon-section-label",
|
|
170
|
+
children: "Choose an icon"
|
|
171
|
+
}), /* @__PURE__ */ require_jsx_runtime.jsx("div", {
|
|
172
|
+
className: "power-icon-glyphs",
|
|
173
|
+
children: require_cluster_icons.GLYPHS.map((glyph) => /* @__PURE__ */ require_jsx_runtime.jsx("button", {
|
|
174
|
+
type: "button",
|
|
175
|
+
className: "power-icon-glyph",
|
|
176
|
+
title: glyph.label,
|
|
177
|
+
"aria-label": glyph.label,
|
|
178
|
+
"aria-pressed": design.glyph === glyph.id,
|
|
179
|
+
disabled: busy,
|
|
180
|
+
onClick: () => update("glyph", glyph.id),
|
|
181
|
+
children: /* @__PURE__ */ require_jsx_runtime.jsx("img", {
|
|
182
|
+
src: require_cluster_icons.clusterIconDataUrl({
|
|
183
|
+
...previewDesign,
|
|
184
|
+
glyph: glyph.id
|
|
185
|
+
}),
|
|
186
|
+
alt: ""
|
|
187
|
+
})
|
|
188
|
+
}, glyph.id))
|
|
189
|
+
})] }),
|
|
190
|
+
!validDesign && /* @__PURE__ */ require_jsx_runtime.jsx("div", {
|
|
191
|
+
role: "alert",
|
|
192
|
+
className: "power-icon-error",
|
|
193
|
+
children: "Use up to three visible characters for the label."
|
|
194
|
+
}),
|
|
195
|
+
error && /* @__PURE__ */ require_jsx_runtime.jsx("div", {
|
|
196
|
+
role: "alert",
|
|
197
|
+
className: "power-icon-error",
|
|
198
|
+
children: error
|
|
199
|
+
}),
|
|
200
|
+
/* @__PURE__ */ require_jsx_runtime.jsx("div", {
|
|
201
|
+
className: "power-icon-footer",
|
|
202
|
+
children: /* @__PURE__ */ require_jsx_runtime.jsxs("div", {
|
|
203
|
+
className: "power-icon-footer-actions",
|
|
204
|
+
children: [/* @__PURE__ */ require_jsx_runtime.jsx(require_extensions.Renderer.Component.Button, {
|
|
205
|
+
label: "Cancel",
|
|
206
|
+
disabled: busy,
|
|
207
|
+
onClick: onClose
|
|
208
|
+
}), /* @__PURE__ */ require_jsx_runtime.jsx(require_extensions.Renderer.Component.Button, {
|
|
209
|
+
primary: true,
|
|
210
|
+
label: busy ? "Applying…" : "Apply",
|
|
211
|
+
disabled: busy || !validDesign,
|
|
212
|
+
onClick: () => void save()
|
|
213
|
+
})]
|
|
214
|
+
})
|
|
215
|
+
})
|
|
216
|
+
]
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
function ClusterIconsPage() {
|
|
220
|
+
const [entries, setEntries] = require__global_external_react.useState([]);
|
|
221
|
+
const [loading, setLoading] = require__global_external_react.useState(true);
|
|
222
|
+
const [error, setError] = require__global_external_react.useState("");
|
|
223
|
+
const [query, setQuery] = require__global_external_react.useState("");
|
|
224
|
+
const [editing, setEditing] = require__global_external_react.useState();
|
|
225
|
+
const load = () => {
|
|
226
|
+
setLoading(true);
|
|
227
|
+
setError("");
|
|
228
|
+
return electron.ipcRenderer.invoke(require_cluster_icon_ipc.CLUSTER_ICONS_CHANNEL, { operation: "list" }).then(setEntries).catch(() => setError("Unable to load saved clusters. Try again.")).finally(() => setLoading(false));
|
|
229
|
+
};
|
|
230
|
+
require__global_external_react.useEffect(() => {
|
|
231
|
+
load();
|
|
232
|
+
}, []);
|
|
233
|
+
const visible = entries.filter((entry) => entry.name.toLocaleLowerCase().includes(query.trim().toLocaleLowerCase()));
|
|
234
|
+
return /* @__PURE__ */ require_jsx_runtime.jsxs("main", {
|
|
235
|
+
className: "power-icon-studio",
|
|
236
|
+
children: [/* @__PURE__ */ require_jsx_runtime.jsx("style", { children: styles }), /* @__PURE__ */ require_jsx_runtime.jsxs("div", {
|
|
237
|
+
className: "power-icon-content",
|
|
238
|
+
children: [
|
|
239
|
+
/* @__PURE__ */ require_jsx_runtime.jsxs("header", {
|
|
240
|
+
className: "power-icon-header",
|
|
241
|
+
children: [/* @__PURE__ */ require_jsx_runtime.jsxs("div", { children: [/* @__PURE__ */ require_jsx_runtime.jsx("h1", { children: "Cluster icons" }), /* @__PURE__ */ require_jsx_runtime.jsx("p", { children: "A shared style. A distinct identity for every cluster." })] }), /* @__PURE__ */ require_jsx_runtime.jsx("div", {
|
|
242
|
+
className: "power-icon-search",
|
|
243
|
+
children: /* @__PURE__ */ require_jsx_runtime.jsx(require_extensions.Renderer.Component.Input, {
|
|
244
|
+
value: query,
|
|
245
|
+
onChange: setQuery,
|
|
246
|
+
placeholder: "Find a cluster…",
|
|
247
|
+
"aria-label": "Find a cluster"
|
|
248
|
+
})
|
|
249
|
+
})]
|
|
250
|
+
}),
|
|
251
|
+
error ? /* @__PURE__ */ require_jsx_runtime.jsxs("div", {
|
|
252
|
+
className: "power-icon-empty",
|
|
253
|
+
role: "alert",
|
|
254
|
+
children: [
|
|
255
|
+
error,
|
|
256
|
+
" ",
|
|
257
|
+
/* @__PURE__ */ require_jsx_runtime.jsx(require_extensions.Renderer.Component.Button, {
|
|
258
|
+
label: "Retry",
|
|
259
|
+
onClick: () => void load()
|
|
260
|
+
})
|
|
261
|
+
]
|
|
262
|
+
}) : loading ? /* @__PURE__ */ require_jsx_runtime.jsx("div", {
|
|
263
|
+
className: "power-icon-empty",
|
|
264
|
+
role: "status",
|
|
265
|
+
children: "Loading clusters…"
|
|
266
|
+
}) : visible.length === 0 ? /* @__PURE__ */ require_jsx_runtime.jsx("div", {
|
|
267
|
+
className: "power-icon-empty",
|
|
268
|
+
children: entries.length ? "No matching clusters" : "Your saved clusters will appear here"
|
|
269
|
+
}) : /* @__PURE__ */ require_jsx_runtime.jsx("div", {
|
|
270
|
+
className: "power-icon-grid",
|
|
271
|
+
children: visible.map((entry) => /* @__PURE__ */ require_jsx_runtime.jsxs("button", {
|
|
272
|
+
type: "button",
|
|
273
|
+
className: "power-icon-card",
|
|
274
|
+
title: `Edit icon for ${entry.name}`,
|
|
275
|
+
onClick: () => setEditing(entry),
|
|
276
|
+
children: [/* @__PURE__ */ require_jsx_runtime.jsx(require_extensions.Renderer.Component.Avatar, {
|
|
277
|
+
title: entry.name,
|
|
278
|
+
size: 64,
|
|
279
|
+
src: entry.icon?.startsWith("data:image/") ? entry.icon : void 0,
|
|
280
|
+
background: entry.icon && !entry.icon.startsWith("data:") ? entry.icon : void 0,
|
|
281
|
+
colorHash: `${entry.name}-${require_extensions.Renderer.Catalog.catalogEntities.getById(entry.id)?.metadata.source ?? ""}`,
|
|
282
|
+
className: "power-icon-current-avatar"
|
|
283
|
+
}), /* @__PURE__ */ require_jsx_runtime.jsx("span", {
|
|
284
|
+
className: "power-icon-card-name",
|
|
285
|
+
children: entry.name
|
|
286
|
+
})]
|
|
287
|
+
}, entry.id))
|
|
288
|
+
}),
|
|
289
|
+
editing && /* @__PURE__ */ require_jsx_runtime.jsx(IconEditor, {
|
|
290
|
+
entry: editing,
|
|
291
|
+
onClose: () => setEditing(void 0),
|
|
292
|
+
onSaved: (next) => {
|
|
293
|
+
setEntries(next);
|
|
294
|
+
setEditing(void 0);
|
|
295
|
+
}
|
|
296
|
+
}, editing.id)
|
|
297
|
+
]
|
|
298
|
+
})]
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
//#endregion
|
|
302
|
+
exports.ClusterIconsPage = ClusterIconsPage;
|
|
303
|
+
|
|
304
|
+
//# sourceMappingURL=cluster-icons.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cluster-icons.js","names":[],"sources":["../../src/renderer/cluster-icons.tsx"],"sourcesContent":["import { Renderer } from \"@freelensapp/extensions\";\nimport { ipcRenderer } from \"electron\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { CLUSTER_ICONS_CHANNEL, type ClusterIconEntry } from \"../common/cluster-icon-ipc\";\nimport {\n type ClusterIconDesign,\n clusterIconDataUrl,\n defaultClusterIconDesign,\n GLYPHS,\n normalizeClusterIconDesign,\n} from \"../common/cluster-icons\";\nimport { IconColorPicker, MATCHING_ICON_COLORS } from \"./cluster-icon-colors\";\nimport { SettingsModal } from \"./preferences/settings-modal\";\n\nconst styles = `\n.ClusterManager main.power-icon-studio, .power-icon-studio { display: block; position: relative; z-index: 2; flex: 1; min-width: 0; height: 100%; overflow: auto; padding: 32px; box-sizing: border-box; background: var(--mainBackground); color: var(--textColorPrimary); }\n.power-icon-studio > .power-icon-content { max-width: 1000px; margin: 0 auto; }\n.power-icon-header { display: flex; align-items: center; justify-content: space-between; gap: 24px; margin-bottom: 28px; }\n.power-icon-header h1 { font-size: 24px; font-weight: 600; margin: 0 0 8px; color: var(--textColorAccent); }\n.power-icon-header p { margin: 0; color: var(--textColorSecondary); }\n.power-icon-search { width: 240px; }\n.power-icon-grid { display: grid; grid-template-columns: repeat(5,minmax(0,1fr)); gap: 16px; }\n.power-icon-card { display: flex; flex-direction: column; align-items: center; gap: 12px; position: relative; padding: 20px 14px 16px; min-width: 0; border: 1px solid var(--borderFaintColor); border-radius: 14px; background: var(--contentColor); color: var(--textColorPrimary); font: inherit; cursor: pointer; transition: border-color 150ms ease, background-color 150ms ease, transform 150ms ease; }\n.power-icon-card:hover { border-color: var(--primary); background: color-mix(in srgb,var(--primary) 4%,var(--contentColor)); transform: translateY(-2px); }\n.power-icon-card:focus-visible, .power-icon-glyph:focus-visible, .power-icon-swatch:focus-visible { outline: 2px solid var(--primary); outline-offset: 3px; }\n.power-icon-card > img, .power-icon-card .power-icon-current-avatar { width: 64px; height: 64px; object-fit: contain; border-radius: 16px; }\n.power-icon-card-name { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }\n.power-icon-empty { padding: 64px 24px; text-align: center; border: 1px dashed var(--borderFaintColor); border-radius: 14px; color: var(--textColorSecondary); }\n.power-icon-editor { display: grid; grid-template-columns: 144px minmax(0,1fr); gap: 24px; }\n.power-icon-preview { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 22px; padding: 24px 12px; border: 1px solid var(--borderFaintColor); border-radius: 12px; background: var(--contentColor); }\n.power-icon-preview-main { width: 96px; height: 96px; }\n.power-icon-preview-sizes { display: flex; align-items: center; gap: 14px; }\n.power-icon-preview-caption { font-size: 11px; color: var(--textColorSecondary); }\n.power-icon-fields { display: grid; gap: 16px; }\n.power-icon-field { display: flex; align-items: center; justify-content: space-between; gap: 12px; font-size: 13px; }\n.power-icon-field input[type=text] { width: 100px; padding: 8px 10px; border: 1px solid var(--borderFaintColor); border-radius: 6px; background: var(--contentColor); color: var(--textColorPrimary); font: inherit; }\n.power-icon-field input:focus-visible { outline: 1px solid var(--primary); }\n.power-icon-section-label { color: var(--textColorSecondary); font-size: 12px; margin-bottom: 10px; }\n.power-icon-glyphs { display: grid; grid-template-columns: repeat(5,minmax(0,1fr)); gap: 8px; }\n.power-icon-glyph { display: flex; align-items: center; justify-content: center; min-height: 54px; padding: 6px; border: 1px solid var(--borderFaintColor); border-radius: 8px; background: var(--contentColor); cursor: pointer; transition: border-color 150ms ease, background-color 150ms ease; }\n.power-icon-glyph:hover, .power-icon-glyph[aria-pressed=true] { border-color: var(--primary); background: color-mix(in srgb,var(--primary) 8%,var(--contentColor)); }\n.power-icon-glyph img { width: 38px; height: 38px; }\n.power-icon-swatches { display: flex; align-items: center; gap: 8px; }\n.power-icon-swatch { width: 22px; height: 22px; border: 2px solid transparent; border-radius: 50%; cursor: pointer; }\n.power-icon-swatch[aria-pressed=true] { box-shadow: 0 0 0 2px var(--mainBackground),0 0 0 3px var(--primary); }\n.power-icon-footer { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding-top: 12px; border-top: 1px solid var(--borderFaintColor); }\n.power-icon-footer-actions { display: flex; gap: 8px; margin-left: auto; }\n.power-icon-error { color: var(--colorError); font-size: 12px; line-height: 1.5; }\n@media (max-width: 900px) { .power-icon-grid { grid-template-columns: repeat(4,minmax(0,1fr)); } }\n@media (max-width: 700px) { .power-icon-header { align-items: stretch; flex-direction: column; } .power-icon-search { width: 100%; } .power-icon-grid { grid-template-columns: repeat(3,minmax(0,1fr)); } .ClusterManager main.power-icon-studio, .power-icon-studio { padding: 20px; } }\n@media (max-width: 480px) { .power-icon-grid { grid-template-columns: repeat(2,minmax(0,1fr)); } .power-icon-editor { grid-template-columns: 1fr; } .power-icon-preview { flex-direction: row; padding: 16px; } .power-icon-preview-main { width: 72px; height: 72px; } }\n@media (prefers-reduced-motion: reduce) { .power-icon-card { transition: none; transform: none; } }\n`;\n\nfunction IconEditor({\n entry,\n onClose,\n onSaved,\n}: {\n entry: ClusterIconEntry;\n onClose: () => void;\n onSaved: (entries: ClusterIconEntry[]) => void;\n}) {\n const [design, setDesign] = useState<ClusterIconDesign>(() => entry.design ?? defaultClusterIconDesign(entry.name));\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState(\"\");\n const paletteOpen = useRef(false);\n const onPaletteOpenChange = useCallback((open: boolean) => {\n paletteOpen.current = open;\n }, []);\n const update = (key: keyof ClusterIconDesign, value: string) =>\n setDesign((previous) => ({ ...previous, [key]: value }));\n const save = async () => {\n setBusy(true);\n setError(\"\");\n try {\n const entries = await ipcRenderer.invoke(CLUSTER_ICONS_CHANNEL, {\n operation: \"apply\",\n id: entry.id,\n design,\n });\n onSaved(entries);\n } catch {\n setError(\"Unable to save this cluster icon. Try again.\");\n } finally {\n setBusy(false);\n }\n };\n let validDesign: ClusterIconDesign | undefined;\n try {\n validDesign = normalizeClusterIconDesign(design);\n } catch {\n validDesign = undefined;\n }\n const previewDesign = validDesign ?? defaultClusterIconDesign(entry.name);\n const preview = clusterIconDataUrl(previewDesign);\n return (\n <SettingsModal\n id=\"power-cluster-icon-editor\"\n title={entry.name}\n onClose={() => {\n if (!busy && !paletteOpen.current) onClose();\n }}\n >\n <style>{styles}</style>\n <div className=\"power-icon-editor\">\n <div className=\"power-icon-preview\">\n <img className=\"power-icon-preview-main\" src={preview} alt=\"Cluster icon preview\" />\n <div className=\"power-icon-preview-sizes\">\n <img src={preview} width={36} height={36} alt=\"\" />\n </div>\n <span className=\"power-icon-preview-caption\">Sidebar preview</span>\n </div>\n <div className=\"power-icon-fields\">\n <label className=\"power-icon-field\" htmlFor=\"power-icon-label\">\n Label\n <input\n id=\"power-icon-label\"\n type=\"text\"\n value={design.label}\n onChange={(event) => update(\"label\", Array.from(event.target.value).slice(0, 3).join(\"\"))}\n disabled={busy}\n autoFocus\n />\n </label>\n {(\n [\n [\"outlineColor\", \"Outline\"],\n [\"labelColor\", \"Label color\"],\n [\"iconColor\", \"Icon color\"],\n ] as const\n ).map(([key, label]) => (\n <div className=\"power-icon-field\" key={key}>\n <span>{label}</span>\n <IconColorPicker\n label={label}\n value={design[key]}\n onChange={(color) => update(key, color)}\n disabled={busy}\n onOpenChange={onPaletteOpenChange}\n />\n </div>\n ))}\n <div>\n <div className=\"power-icon-section-label\">Matching outline & label</div>\n <div className=\"power-icon-swatches\">\n {MATCHING_ICON_COLORS.map(({ name, color }) => (\n <button\n key={color}\n type=\"button\"\n className=\"power-icon-swatch\"\n style={{ background: color }}\n title={`${name} · ${color}`}\n aria-label={`Use ${color} for outline and label`}\n aria-pressed={design.outlineColor === color && design.labelColor === color}\n disabled={busy}\n onClick={() => setDesign((previous) => ({ ...previous, outlineColor: color, labelColor: color }))}\n />\n ))}\n </div>\n </div>\n </div>\n </div>\n <div>\n <div className=\"power-icon-section-label\">Choose an icon</div>\n <div className=\"power-icon-glyphs\">\n {GLYPHS.map((glyph) => (\n <button\n type=\"button\"\n key={glyph.id}\n className=\"power-icon-glyph\"\n title={glyph.label}\n aria-label={glyph.label}\n aria-pressed={design.glyph === glyph.id}\n disabled={busy}\n onClick={() => update(\"glyph\", glyph.id)}\n >\n <img src={clusterIconDataUrl({ ...previewDesign, glyph: glyph.id })} alt=\"\" />\n </button>\n ))}\n </div>\n </div>\n {!validDesign && (\n <div role=\"alert\" className=\"power-icon-error\">\n Use up to three visible characters for the label.\n </div>\n )}\n {error && (\n <div role=\"alert\" className=\"power-icon-error\">\n {error}\n </div>\n )}\n <div className=\"power-icon-footer\">\n <div className=\"power-icon-footer-actions\">\n <Renderer.Component.Button label=\"Cancel\" disabled={busy} onClick={onClose} />\n <Renderer.Component.Button\n primary\n label={busy ? \"Applying…\" : \"Apply\"}\n disabled={busy || !validDesign}\n onClick={() => void save()}\n />\n </div>\n </div>\n </SettingsModal>\n );\n}\n\nexport function ClusterIconsPage() {\n const [entries, setEntries] = useState<ClusterIconEntry[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState(\"\");\n const [query, setQuery] = useState(\"\");\n const [editing, setEditing] = useState<ClusterIconEntry>();\n const load = () => {\n setLoading(true);\n setError(\"\");\n return ipcRenderer\n .invoke(CLUSTER_ICONS_CHANNEL, { operation: \"list\" })\n .then(setEntries)\n .catch(() => setError(\"Unable to load saved clusters. Try again.\"))\n .finally(() => setLoading(false));\n };\n useEffect(() => {\n void load();\n }, []);\n const visible = entries.filter((entry) => entry.name.toLocaleLowerCase().includes(query.trim().toLocaleLowerCase()));\n return (\n <main className=\"power-icon-studio\">\n <style>{styles}</style>\n <div className=\"power-icon-content\">\n <header className=\"power-icon-header\">\n <div>\n <h1>Cluster icons</h1>\n <p>A shared style. A distinct identity for every cluster.</p>\n </div>\n <div className=\"power-icon-search\">\n <Renderer.Component.Input\n value={query}\n onChange={setQuery}\n placeholder=\"Find a cluster…\"\n aria-label=\"Find a cluster\"\n />\n </div>\n </header>\n {error ? (\n <div className=\"power-icon-empty\" role=\"alert\">\n {error} <Renderer.Component.Button label=\"Retry\" onClick={() => void load()} />\n </div>\n ) : loading ? (\n <div className=\"power-icon-empty\" role=\"status\">\n Loading clusters…\n </div>\n ) : visible.length === 0 ? (\n <div className=\"power-icon-empty\">\n {entries.length ? \"No matching clusters\" : \"Your saved clusters will appear here\"}\n </div>\n ) : (\n <div className=\"power-icon-grid\">\n {visible.map((entry) => (\n <button\n type=\"button\"\n key={entry.id}\n className=\"power-icon-card\"\n title={`Edit icon for ${entry.name}`}\n onClick={() => setEditing(entry)}\n >\n <Renderer.Component.Avatar\n title={entry.name}\n size={64}\n src={entry.icon?.startsWith(\"data:image/\") ? entry.icon : undefined}\n background={entry.icon && !entry.icon.startsWith(\"data:\") ? entry.icon : undefined}\n colorHash={`${entry.name}-${Renderer.Catalog.catalogEntities.getById(entry.id)?.metadata.source ?? \"\"}`}\n className=\"power-icon-current-avatar\"\n />\n <span className=\"power-icon-card-name\">{entry.name}</span>\n </button>\n ))}\n </div>\n )}\n {editing && (\n <IconEditor\n key={editing.id}\n entry={editing}\n onClose={() => setEditing(undefined)}\n onSaved={(next) => {\n setEntries(next);\n setEditing(undefined);\n }}\n />\n )}\n </div>\n </main>\n );\n}\n"],"mappings":"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"}
|
|
@@ -51,9 +51,11 @@ var styles = `
|
|
|
51
51
|
.freelens-power-dashboard button.power-dashboard-expand[aria-pressed="true"] .Icon { color: var(--primary); }
|
|
52
52
|
.freelens-power-dashboard button.power-dashboard-expand[aria-pressed="true"]:hover { background: color-mix(in srgb, var(--primary) 12%, transparent); }
|
|
53
53
|
.freelens-power-dashboard button.power-dashboard-expand:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
|
|
54
|
-
.freelens-power-dashboard .power-dashboard-card-
|
|
55
|
-
.freelens-power-dashboard .power-dashboard-card-
|
|
56
|
-
.freelens-power-dashboard .power-dashboard-card-
|
|
54
|
+
.freelens-power-dashboard .power-dashboard-card-xs { grid-column: span 1; grid-row: span 1; }
|
|
55
|
+
.freelens-power-dashboard .power-dashboard-card-s { grid-column: span var(--power-small-span, 2); grid-row: span 2; }
|
|
56
|
+
.freelens-power-dashboard .power-dashboard-card-m { grid-column: span var(--power-medium-span, 4); grid-row: span 2; }
|
|
57
|
+
.freelens-power-dashboard .power-dashboard-card-l { grid-column: span var(--power-large-span, 4); grid-row: span 3; }
|
|
58
|
+
.freelens-power-dashboard .power-dashboard-card-xl { grid-column: span var(--power-columns, 4); grid-row: span 3; }
|
|
57
59
|
.freelens-power-dashboard .power-dashboard-card-header {
|
|
58
60
|
display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 6px 12px;
|
|
59
61
|
}
|
|
@@ -234,10 +236,11 @@ var DashboardPage = require__global_external_mobx_react.observer(({ onOpenPrefer
|
|
|
234
236
|
frame = 0;
|
|
235
237
|
const containerStyle = window.getComputedStyle(container);
|
|
236
238
|
const contentWidth = container.clientWidth - (Number.parseFloat(containerStyle.paddingLeft) || 0) - (Number.parseFloat(containerStyle.paddingRight) || 0);
|
|
237
|
-
const columns =
|
|
239
|
+
const columns = contentWidth >= 1200 ? 6 : contentWidth >= 800 ? 4 : contentWidth >= 520 ? 2 : 1;
|
|
238
240
|
for (const [property, value] of Object.entries({
|
|
239
241
|
"--power-columns": columns,
|
|
240
|
-
"--power-
|
|
242
|
+
"--power-small-span": Math.min(2, columns),
|
|
243
|
+
"--power-medium-span": Math.min(4, columns),
|
|
241
244
|
"--power-large-span": Math.min(4, columns)
|
|
242
245
|
})) if (container.style.getPropertyValue(property) !== String(value)) container.style.setProperty(property, String(value));
|
|
243
246
|
const containerBounds = container.getBoundingClientRect();
|
|
@@ -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 { 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; height: 100%; 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-s { grid-column: span 1; grid-row: span 1; }\n .freelens-power-dashboard .power-dashboard-card-m { grid-column: span var(--power-medium-span, 2); grid-row: span 2; }\n .freelens-power-dashboard .power-dashboard-card-l { grid-column: span var(--power-large-span, 4); grid-row: span 4; }\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-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 .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 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 reloadCards = async () => {\n if (reloading) return;\n setReloading(true);\n try {\n const results = await Promise.all(cards.map(({ id }) => ipcRenderer.invoke(DASHBOARD_VIEWS_RELOAD, { id })));\n setLoadFailed(results.some((result) => result?.failed?.length));\n } catch {\n setLoadFailed(true);\n } finally {\n setReloading(false);\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 = Math.max(1, Math.min(12, Math.floor((contentWidth + 20) / 260)));\n for (const [property, value] of Object.entries({\n \"--power-columns\": columns,\n \"--power-medium-span\": Math.min(2, 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 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(0, rect.left, containerBounds.left));\n const y = Math.ceil(Math.max(0, rect.top, containerBounds.top));\n const right = Math.floor(Math.min(window.innerWidth, rect.right, containerBounds.right));\n const bottom = Math.floor(Math.min(window.innerHeight, rect.bottom, containerBounds.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 [{ id: element.dataset.cardId, bounds, clip }];\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 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 (const element of container.querySelectorAll(\".power-dashboard-embed\")) observer.observe(element);\n container.addEventListener(\"scroll\", schedule);\n window.addEventListener(\"resize\", schedule);\n schedule();\n return () => {\n active = false;\n window.cancelAnimationFrame(frame);\n observer.disconnect();\n mutations.disconnect();\n container.removeEventListener(\"scroll\", schedule);\n window.removeEventListener(\"resize\", schedule);\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={reloading || 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=\"settings\" 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={`${pinnedCards.includes(card.id) ? \"Unpin\" : \"Pin\"} ${card.title}`}\n aria-pressed={pinnedCards.includes(card.id)}\n title={pinnedCards.includes(card.id) ? \"Close pinned window\" : \"Pin above other windows\"}\n onClick={() => {\n void togglePinned(card.id);\n }}\n >\n <Renderer.Component.Icon material=\"push_pin\" size={18} />\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 title={expanded === card.id ? \"Restore\" : \"Expand\"}\n onClick={() => {\n if (!expanded) gridScrollTop.current = root.current?.scrollTop ?? 0;\n setExpandedId(expanded === card.id ? null : card.id);\n }}\n >\n <Renderer.Component.Icon\n material={expanded === card.id ? \"fullscreen_exit\" : \"fullscreen\"}\n size={18}\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 <Renderer.Component.Icon material=\"open_in_new\" size={18} tooltip=\"Open in browser\" />\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 { 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; height: 100%; 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-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 .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 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 reloadCards = async () => {\n if (reloading) return;\n setReloading(true);\n try {\n const results = await Promise.all(cards.map(({ id }) => ipcRenderer.invoke(DASHBOARD_VIEWS_RELOAD, { id })));\n setLoadFailed(results.some((result) => result?.failed?.length));\n } catch {\n setLoadFailed(true);\n } finally {\n setReloading(false);\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 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(0, rect.left, containerBounds.left));\n const y = Math.ceil(Math.max(0, rect.top, containerBounds.top));\n const right = Math.floor(Math.min(window.innerWidth, rect.right, containerBounds.right));\n const bottom = Math.floor(Math.min(window.innerHeight, rect.bottom, containerBounds.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 [{ id: element.dataset.cardId, bounds, clip }];\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 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 (const element of container.querySelectorAll(\".power-dashboard-embed\")) observer.observe(element);\n container.addEventListener(\"scroll\", schedule);\n window.addEventListener(\"resize\", schedule);\n schedule();\n return () => {\n active = false;\n window.cancelAnimationFrame(frame);\n observer.disconnect();\n mutations.disconnect();\n container.removeEventListener(\"scroll\", schedule);\n window.removeEventListener(\"resize\", schedule);\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={reloading || 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=\"settings\" 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={`${pinnedCards.includes(card.id) ? \"Unpin\" : \"Pin\"} ${card.title}`}\n aria-pressed={pinnedCards.includes(card.id)}\n title={pinnedCards.includes(card.id) ? \"Close pinned window\" : \"Pin above other windows\"}\n onClick={() => {\n void togglePinned(card.id);\n }}\n >\n <Renderer.Component.Icon material=\"push_pin\" size={18} />\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 title={expanded === card.id ? \"Restore\" : \"Expand\"}\n onClick={() => {\n if (!expanded) gridScrollTop.current = root.current?.scrollTop ?? 0;\n setExpandedId(expanded === card.id ? null : card.id);\n }}\n >\n <Renderer.Component.Icon\n material={expanded === card.id ? \"fullscreen_exit\" : \"fullscreen\"}\n size={18}\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 <Renderer.Component.Icon material=\"open_in_new\" size={18} tooltip=\"Open in browser\" />\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,6 +1,7 @@
|
|
|
1
1
|
const require_extensions = require("../_virtual/_global-external_@freelensapp/extensions.js");
|
|
2
2
|
const require__global_external_mobx_react = require("../_virtual/_global-external_mobx-react.js");
|
|
3
3
|
const require_jsx_runtime = require("../_virtual/_global-external_react/jsx-runtime.js");
|
|
4
|
+
const require_date_time = require("../src/common/date-time.js");
|
|
4
5
|
const require_secret_certificates = require("../src/common/secret-certificates.js");
|
|
5
6
|
//#region src/renderer/details/secret-certificate-details.tsx
|
|
6
7
|
var { DrawerTitle, DrawerItem } = require_extensions.Renderer.Component;
|
|
@@ -38,14 +39,20 @@ var SecretCertificateDetails = require__global_external_mobx_react.observer(({ o
|
|
|
38
39
|
}),
|
|
39
40
|
/* @__PURE__ */ require_jsx_runtime.jsx(DrawerItem, {
|
|
40
41
|
name: "Not before",
|
|
41
|
-
children:
|
|
42
|
+
children: /* @__PURE__ */ require_jsx_runtime.jsx("span", {
|
|
43
|
+
style: { whiteSpace: "pre-wrap" },
|
|
44
|
+
children: require_date_time.formatDateTime(certificate.validFrom)
|
|
45
|
+
})
|
|
42
46
|
}),
|
|
43
47
|
/* @__PURE__ */ require_jsx_runtime.jsx(DrawerItem, {
|
|
44
48
|
name: "Expires",
|
|
45
49
|
children: /* @__PURE__ */ require_jsx_runtime.jsxs("span", {
|
|
46
50
|
style: expired ? { color: "red" } : void 0,
|
|
47
51
|
children: [
|
|
48
|
-
|
|
52
|
+
/* @__PURE__ */ require_jsx_runtime.jsx("span", {
|
|
53
|
+
style: { whiteSpace: "pre-wrap" },
|
|
54
|
+
children: require_date_time.formatDateTime(certificate.validTo)
|
|
55
|
+
}),
|
|
49
56
|
" (",
|
|
50
57
|
expired ? `Expired ${Math.ceil(-remaining / 864e5)} days ago` : `${days} days remaining`,
|
|
51
58
|
")"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secret-certificate-details.js","names":[],"sources":["../../../src/renderer/details/secret-certificate-details.tsx"],"sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\nimport { Renderer } from \"@freelensapp/extensions\";\nimport { observer } from \"mobx-react\";\nimport { parseSecretCertificates } from \"../../common/secret-certificates\";\n\nconst { DrawerTitle, DrawerItem } = Renderer.Component;\n\nexport const SecretCertificateDetails = observer(\n ({ object }: Renderer.Component.KubeObjectDetailsProps<Renderer.K8sApi.Secret>) => {\n const certificates = parseSecretCertificates(object.data);\n const now = Date.now();\n\n if (certificates.length === 0) return null;\n\n return (\n <>\n {certificates.map((certificate) => {\n const remaining = new Date(certificate.validTo).getTime() - now;\n const days = Math.ceil(remaining / 86_400_000);\n const expired = remaining <= 0;\n\n return (\n <div key={`${certificate.key}:${certificate.index}`}>\n <DrawerTitle>\n Certificate Info - {certificate.key} ({certificate.index})\n </DrawerTitle>\n <DrawerItem name=\"CN\">{certificate.commonName}</DrawerItem>\n <DrawerItem name=\"SAN\">{certificate.subjectAltName ?? \"—\"}</DrawerItem>\n <DrawerItem name=\"Serial Number\">{certificate.serialNumber}</DrawerItem>\n <DrawerItem name=\"Issuer\">{certificate.issuer}</DrawerItem>\n <DrawerItem name=\"Not before\">{certificate.validFrom}</DrawerItem>\n <DrawerItem name=\"Expires\">\n <span style={expired ? { color: \"red\" } : undefined}>\n {certificate.validTo} (\n {expired ? `Expired ${Math.ceil(-remaining / 86_400_000)} days ago` : `${days} days remaining`})\n </span>\n </DrawerItem>\n </div>\n );\n })}\n </>\n );\n },\n);\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"secret-certificate-details.js","names":[],"sources":["../../../src/renderer/details/secret-certificate-details.tsx"],"sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\nimport { Renderer } from \"@freelensapp/extensions\";\nimport { observer } from \"mobx-react\";\nimport { formatDateTime } from \"../../common/date-time\";\nimport { parseSecretCertificates } from \"../../common/secret-certificates\";\n\nconst { DrawerTitle, DrawerItem } = Renderer.Component;\n\nexport const SecretCertificateDetails = observer(\n ({ object }: Renderer.Component.KubeObjectDetailsProps<Renderer.K8sApi.Secret>) => {\n const certificates = parseSecretCertificates(object.data);\n const now = Date.now();\n\n if (certificates.length === 0) return null;\n\n return (\n <>\n {certificates.map((certificate) => {\n const remaining = new Date(certificate.validTo).getTime() - now;\n const days = Math.ceil(remaining / 86_400_000);\n const expired = remaining <= 0;\n\n return (\n <div key={`${certificate.key}:${certificate.index}`}>\n <DrawerTitle>\n Certificate Info - {certificate.key} ({certificate.index})\n </DrawerTitle>\n <DrawerItem name=\"CN\">{certificate.commonName}</DrawerItem>\n <DrawerItem name=\"SAN\">{certificate.subjectAltName ?? \"—\"}</DrawerItem>\n <DrawerItem name=\"Serial Number\">{certificate.serialNumber}</DrawerItem>\n <DrawerItem name=\"Issuer\">{certificate.issuer}</DrawerItem>\n <DrawerItem name=\"Not before\">\n <span style={{ whiteSpace: \"pre-wrap\" }}>{formatDateTime(certificate.validFrom)}</span>\n </DrawerItem>\n <DrawerItem name=\"Expires\">\n <span style={expired ? { color: \"red\" } : undefined}>\n <span style={{ whiteSpace: \"pre-wrap\" }}>{formatDateTime(certificate.validTo)}</span> (\n {expired ? `Expired ${Math.ceil(-remaining / 86_400_000)} days ago` : `${days} days remaining`})\n </span>\n </DrawerItem>\n </div>\n );\n })}\n </>\n );\n },\n);\n"],"mappings":";;;;;;AAOA,IAAM,EAAE,aAAa,eAAe,mBAAA,SAAS;AAE7C,IAAa,2BAA2B,oCAAA,UACrC,EAAE,aAAgF;CACjF,MAAM,eAAe,4BAAA,wBAAwB,OAAO,IAAI;CACxD,MAAM,MAAM,KAAK,IAAI;CAErB,IAAI,aAAa,WAAW,GAAG,OAAO;CAEtC,OACE,oCAAA,IAAA,oBAAA,UAAA,EAAA,UACG,aAAa,KAAK,gBAAgB;EACjC,MAAM,YAAY,IAAI,KAAK,YAAY,OAAO,CAAC,CAAC,QAAQ,IAAI;EAC5D,MAAM,OAAO,KAAK,KAAK,YAAY,KAAU;EAC7C,MAAM,UAAU,aAAa;EAE7B,OACE,oCAAA,KAAC,OAAD,EAAA,UAAA;GACE,oCAAA,KAAC,aAAD,EAAA,UAAA;IAAa;IACS,YAAY;IAAI;IAAG,YAAY;IAAM;GAC9C,EAAA,CAAA;GACb,oCAAA,IAAC,YAAD;IAAY,MAAK;cAAM,YAAY;GAAuB,CAAA;GAC1D,oCAAA,IAAC,YAAD;IAAY,MAAK;cAAO,YAAY,kBAAkB;GAAgB,CAAA;GACtE,oCAAA,IAAC,YAAD;IAAY,MAAK;cAAiB,YAAY;GAAyB,CAAA;GACvE,oCAAA,IAAC,YAAD;IAAY,MAAK;cAAU,YAAY;GAAmB,CAAA;GAC1D,oCAAA,IAAC,YAAD;IAAY,MAAK;cACf,oCAAA,IAAC,QAAD;KAAM,OAAO,EAAE,YAAY,WAAW;eAAI,kBAAA,eAAe,YAAY,SAAS;IAAQ,CAAA;GAC5E,CAAA;GACZ,oCAAA,IAAC,YAAD;IAAY,MAAK;cACf,oCAAA,KAAC,QAAD;KAAM,OAAO,UAAU,EAAE,OAAO,MAAM,IAAI,KAAA;eAA1C;MACE,oCAAA,IAAC,QAAD;OAAM,OAAO,EAAE,YAAY,WAAW;iBAAI,kBAAA,eAAe,YAAY,OAAO;MAAQ,CAAA;MAAC;MACpF,UAAU,WAAW,KAAK,KAAK,CAAC,YAAY,KAAU,EAAE,aAAa,GAAG,KAAK;MAAiB;KAC3F;;GACI,CAAA;EACT,EAAA,GAjBK,GAAG,YAAY,IAAI,GAAG,YAAY,OAiBvC;CAET,CAAC,EACD,CAAA;AAEN,CACF"}
|