@overdeck/desktop 0.30.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/bin/overdeck.mjs +100 -0
- package/dist-electron/main.js +1155 -0
- package/dist-electron/main.js.map +1 -0
- package/dist-electron/preload.js +60 -0
- package/dist-electron/preload.js.map +1 -0
- package/package.json +127 -0
- package/resources/icon.ico +0 -0
- package/resources/icon.png +0 -0
- package/server/public/assets/Assistant-Bold-gm-uSS1B.woff2 +0 -0
- package/server/public/assets/Assistant-Medium-DrcxCXg3.woff2 +0 -0
- package/server/public/assets/Assistant-Regular-DVxZuzxb.woff2 +0 -0
- package/server/public/assets/Assistant-SemiBold-SCI4bEL9.woff2 +0 -0
- package/server/public/assets/abap-CSornMch.js +1 -0
- package/server/public/assets/actionscript-3-DO0KTCRG.js +1 -0
- package/server/public/assets/ada-BiVQDEcw.js +1 -0
- package/server/public/assets/andromeeda-C3L68gAk.js +1 -0
- package/server/public/assets/angular-html-YFZ-qEo2.js +1 -0
- package/server/public/assets/angular-ts-B54r7V_n.js +1 -0
- package/server/public/assets/apache-DW1Ehg7v.js +1 -0
- package/server/public/assets/apex-B3HU-03W.js +1 -0
- package/server/public/assets/apl-CbIltIfi.js +1 -0
- package/server/public/assets/applescript-miwww557.js +1 -0
- package/server/public/assets/ar-SA-G6X2FPQ2-CaxO8BkJ.js +10 -0
- package/server/public/assets/ara-Bv6FSEJm.js +1 -0
- package/server/public/assets/arc-C4lQ9KeB.js +1 -0
- package/server/public/assets/architecture-7EHR7CIX-DsNlnOJW.js +1 -0
- package/server/public/assets/architectureDiagram-3BPJPVTR-ChsmqVL-.js +36 -0
- package/server/public/assets/array-DJTPhb84.js +1 -0
- package/server/public/assets/asciidoc-C51s3pqQ.js +1 -0
- package/server/public/assets/asm-Ca0hbaMT.js +1 -0
- package/server/public/assets/astro-kQmek0SS.js +1 -0
- package/server/public/assets/aurora-x-29H3Sbu_.js +1 -0
- package/server/public/assets/awk-_-xiweeU.js +1 -0
- package/server/public/assets/ayu-dark-DIa75zsR.js +1 -0
- package/server/public/assets/ayu-light-C_WQgzKS.js +1 -0
- package/server/public/assets/ayu-mirage-DXHXdSvo.js +1 -0
- package/server/public/assets/az-AZ-76LH7QW2-svH-oCAD.js +1 -0
- package/server/public/assets/ballerina-Caqwj4cL.js +1 -0
- package/server/public/assets/bat-Dbrs5tc0.js +1 -0
- package/server/public/assets/beancount-BVYIGnHL.js +1 -0
- package/server/public/assets/berry-DiPKqHwL.js +1 -0
- package/server/public/assets/bg-BG-XCXSNQG7-QT3AsUMq.js +5 -0
- package/server/public/assets/bibtex-DgZHzt54.js +1 -0
- package/server/public/assets/bicep-DIAEClCE.js +1 -0
- package/server/public/assets/bird2-CL87YNcv.js +1 -0
- package/server/public/assets/blade-_Uc4zzSO.js +1 -0
- package/server/public/assets/blockDiagram-GPEHLZMM-50C7YJe3.js +132 -0
- package/server/public/assets/bn-BD-2XOGV67Q-BUQZQImC.js +5 -0
- package/server/public/assets/bsl-tWlfQbW2.js +1 -0
- package/server/public/assets/c-W33irP5E.js +1 -0
- package/server/public/assets/c3-BybjL6B5.js +1 -0
- package/server/public/assets/c4Diagram-AAUBKEIU-CQiPOBBk.js +10 -0
- package/server/public/assets/ca-ES-6MX7JW3Y-z4w6HdDJ.js +8 -0
- package/server/public/assets/cadence-G2PoJE4W.js +1 -0
- package/server/public/assets/cairo-Cv4i2rVj.js +1 -0
- package/server/public/assets/catppuccin-frappe-DenhEhc7.js +1 -0
- package/server/public/assets/catppuccin-latte-DBjZqKjK.js +1 -0
- package/server/public/assets/catppuccin-macchiato-DsXr7TPP.js +1 -0
- package/server/public/assets/catppuccin-mocha-DmPmnX9r.js +1 -0
- package/server/public/assets/channel-BQq0JfsM.js +1 -0
- package/server/public/assets/chunk-2J33WTMH-BtHjg07Z.js +1 -0
- package/server/public/assets/chunk-3OPIFGDE-DG0GaB8K.js +62 -0
- package/server/public/assets/chunk-4BX2VUAB-xpGve5oU.js +1 -0
- package/server/public/assets/chunk-4EGX6M5U-CiS26EEN.js +1 -0
- package/server/public/assets/chunk-55IACEB6-_2lFlbAe.js +1 -0
- package/server/public/assets/chunk-5DO6E6H7-lgBBKvfQ.js +1 -0
- package/server/public/assets/chunk-5ZQYHXKU-CdFB-YdJ.js +2 -0
- package/server/public/assets/chunk-6U3AYISY-WI_aJXfI.js +12 -0
- package/server/public/assets/chunk-727SXJPM-MOVXW-HL.js +206 -0
- package/server/public/assets/chunk-AQP2D5EJ-CPUkX7J9.js +231 -0
- package/server/public/assets/chunk-BO2N2NFS-CjzCvQMQ.js +103 -0
- package/server/public/assets/chunk-BR22UD5L-BHrRrQ_A.js +1 -0
- package/server/public/assets/chunk-BSJP7CBP-DNZJE3LD.js +1 -0
- package/server/public/assets/chunk-CSCIHK7Q-BnLPDrJd.js +123 -0
- package/server/public/assets/chunk-EIO257PC-DnXo63uH.js +22 -0
- package/server/public/assets/chunk-FHYWG6QK-w5ZsBS_x.js +1 -0
- package/server/public/assets/chunk-FMBD7UC4-BCMOtjng.js +15 -0
- package/server/public/assets/chunk-K2UTITRG--5Jdo2C5.js +35 -0
- package/server/public/assets/chunk-KSCS5N6A-tMUJfohw.js +10 -0
- package/server/public/assets/chunk-L5ZTLDWV-Ce66KY73.js +1 -0
- package/server/public/assets/chunk-LZXEDZCA-BDEyNL-r.js +2 -0
- package/server/public/assets/chunk-MPE355IW-ZJroAKOx.js +1 -0
- package/server/public/assets/chunk-MZUSXYTE-CPiP3mIY.js +1 -0
- package/server/public/assets/chunk-N66VUXT2-DzdJ5yH2.js +1 -0
- package/server/public/assets/chunk-ND2GUHAM-ByOiohQo.js +1 -0
- package/server/public/assets/chunk-NNHCCRGN-oonlRMkZ.js +159 -0
- package/server/public/assets/chunk-NZK2D7GU-BvUMWguh.js +1 -0
- package/server/public/assets/chunk-O5CBEL6O-aY0cJG0b.js +70 -0
- package/server/public/assets/chunk-PUPMXCY4-DIDwrazO.js +1 -0
- package/server/public/assets/chunk-QZHKN3VN-zpNB_C8l.js +1 -0
- package/server/public/assets/chunk-SRAX5OIU-BDhmsJ9Z.js +1 -0
- package/server/public/assets/chunk-UIBZB4QT-Dpa6DPt7.js +1 -0
- package/server/public/assets/chunk-WCWK7LTN-DTN9FBzj.js +1 -0
- package/server/public/assets/chunk-WU5MYG2G-sFam7st8.js +1 -0
- package/server/public/assets/chunk-XPW4576I-D4sOPQ12.js +32 -0
- package/server/public/assets/chunk-Z3N5DIM6-eUM55sD5.js +1 -0
- package/server/public/assets/chunk-ZUYEQ4TG-B82Qm37l.js +7 -0
- package/server/public/assets/chunk-jRWAZmH_.js +1 -0
- package/server/public/assets/clarity-BGYIjv40.js +1 -0
- package/server/public/assets/classDiagram-4FO5ZUOK-DuK3LZFb.js +1 -0
- package/server/public/assets/classDiagram-v2-Q7XG4LA2-C4BVzdqQ.js +1 -0
- package/server/public/assets/clojure-CP0XX85g.js +1 -0
- package/server/public/assets/cmake-DbRlIs2B.js +1 -0
- package/server/public/assets/cobol-Bc0FYmxA.js +1 -0
- package/server/public/assets/codeowners-B4GKogVq.js +1 -0
- package/server/public/assets/codeql-p68Qr5WI.js +1 -0
- package/server/public/assets/coffee-BBgjALtO.js +1 -0
- package/server/public/assets/common-lisp-qi5mkLqb.js +1 -0
- package/server/public/assets/coq-BXhsv9Ce.js +1 -0
- package/server/public/assets/cose-bilkent-S5V4N54A-DbIsCp9l.js +1 -0
- package/server/public/assets/cpp-_HuA19qD.js +1 -0
- package/server/public/assets/crystal-BDsQiQxo.js +1 -0
- package/server/public/assets/cs-CZ-2BRQDIVT-DssJvsM3.js +11 -0
- package/server/public/assets/csharp-CcF8oQ2Z.js +1 -0
- package/server/public/assets/css-U8jIwd7B.js +1 -0
- package/server/public/assets/csv-7edT5GDb.js +1 -0
- package/server/public/assets/cue-tQM6hMPc.js +1 -0
- package/server/public/assets/cypher-DZb7ZuRm.js +1 -0
- package/server/public/assets/cytoscape.esm-CgPZ79mq.js +321 -0
- package/server/public/assets/d-DuVI2Djl.js +1 -0
- package/server/public/assets/da-DK-5WZEPLOC-C1TGpc9X.js +5 -0
- package/server/public/assets/dagre-BM42HDAG-7-zhwxSb.js +4 -0
- package/server/public/assets/dagre-CHhR9TOh.js +1 -0
- package/server/public/assets/dark-plus-CR_9xkOf.js +1 -0
- package/server/public/assets/dart-CP9uby4g.js +1 -0
- package/server/public/assets/dax-EvwTJp75.js +1 -0
- package/server/public/assets/de-DE-XR44H4JA-9y64ISjN.js +8 -0
- package/server/public/assets/defaultLocale-C8-LtqXU.js +1 -0
- package/server/public/assets/desktop-DRnTExuo.js +1 -0
- package/server/public/assets/diagram-2AECGRRQ-Dhy0imKj.js +43 -0
- package/server/public/assets/diagram-5GNKFQAL-Dv9dNX5V.js +10 -0
- package/server/public/assets/diagram-KO2AKTUF-1PQSM3Yy.js +3 -0
- package/server/public/assets/diagram-LMA3HP47-KncwjgK2.js +24 -0
- package/server/public/assets/diagram-OG6HWLK6-B1mpK1Bv.js +24 -0
- package/server/public/assets/diff-B0RdNoYb.js +1 -0
- package/server/public/assets/directory-open-01563666--kNiCgjP.js +1 -0
- package/server/public/assets/directory-open-4ed118d0-BisFQCkV.js +1 -0
- package/server/public/assets/dist-Bjux0aN_.js +27 -0
- package/server/public/assets/dist-CExM6BC8.js +1 -0
- package/server/public/assets/dist-D6NF8U3N.js +1 -0
- package/server/public/assets/docker-BstEB5VO.js +1 -0
- package/server/public/assets/dotenv-DX8WM8yj.js +1 -0
- package/server/public/assets/dracula-CxQ11msU.js +1 -0
- package/server/public/assets/dracula-soft-DZQDoc4v.js +1 -0
- package/server/public/assets/dream-maker-Bv13kzyR.js +1 -0
- package/server/public/assets/edge-44NINB_l.js +1 -0
- package/server/public/assets/el-GR-BZB4AONW-DYNAk_Yt.js +10 -0
- package/server/public/assets/elixir-BvFudoM5.js +1 -0
- package/server/public/assets/elm-Bcvevfeb.js +1 -0
- package/server/public/assets/emacs-lisp-DytKCnk1.js +1 -0
- package/server/public/assets/en-B4ZKOASM-8whZRZod.js +1 -0
- package/server/public/assets/erDiagram-TEJ5UH35-BlwaM9d1.js +85 -0
- package/server/public/assets/erb-BOi8y-XV.js +1 -0
- package/server/public/assets/erlang-BX7w0Ok9.js +1 -0
- package/server/public/assets/es-ES-U4NZUMDT-1AokUfzg.js +9 -0
- package/server/public/assets/eu-ES-A7QVB2H4-CRFZSk8j.js +11 -0
- package/server/public/assets/eventmodeling-FCH6USID-s8Gw-Woo.js +1 -0
- package/server/public/assets/everforest-dark-B5yeWra_.js +1 -0
- package/server/public/assets/everforest-light-B4NKIpuT.js +1 -0
- package/server/public/assets/fa-IR-HGAKTJCU-bIhYz0gL.js +8 -0
- package/server/public/assets/fennel-CJijd1SE.js +1 -0
- package/server/public/assets/fi-FI-Z5N7JZ37-COjNAxAK.js +6 -0
- package/server/public/assets/file-open-002ab408-DCq64wqY.js +1 -0
- package/server/public/assets/file-open-7c801643-D0hBn9_F.js +1 -0
- package/server/public/assets/file-save-3189631c-DPU_1tin.js +1 -0
- package/server/public/assets/file-save-745eba88-tuwYaBMk.js +1 -0
- package/server/public/assets/fish-DSB2gTRd.js +1 -0
- package/server/public/assets/flowDiagram-I6XJVG4X-CplHo_56.js +162 -0
- package/server/public/assets/fluent-BJcPDodh.js +1 -0
- package/server/public/assets/fortran-fixed-form-Ctf_ysKA.js +1 -0
- package/server/public/assets/fortran-free-form-BtoOII28.js +1 -0
- package/server/public/assets/fr-FR-RHASNOE6-CvDNldKo.js +9 -0
- package/server/public/assets/fsharp-AvjR9D4f.js +1 -0
- package/server/public/assets/ganttDiagram-6RSMTGT7-CMztT_U2.js +292 -0
- package/server/public/assets/gdresource-Dgj9cWOp.js +1 -0
- package/server/public/assets/gdscript-Cd6RKS1c.js +1 -0
- package/server/public/assets/gdshader-CwGO0jWu.js +1 -0
- package/server/public/assets/genie-DifOltrc.js +1 -0
- package/server/public/assets/gherkin-N2h4hJry.js +1 -0
- package/server/public/assets/git-commit-A3P_opqa.js +1 -0
- package/server/public/assets/git-rebase-BCNwX-BV.js +1 -0
- package/server/public/assets/gitGraph-WXDBUCRP-BEnPDGeW.js +1 -0
- package/server/public/assets/gitGraphDiagram-PVQCEYII-C7gh9_16.js +106 -0
- package/server/public/assets/github-dark-BNWfKer2.js +1 -0
- package/server/public/assets/github-dark-default-Dd3JR36E.js +1 -0
- package/server/public/assets/github-dark-dimmed-CtNE8tZH.js +1 -0
- package/server/public/assets/github-dark-high-contrast-DmAdH_w8.js +1 -0
- package/server/public/assets/github-light-CUv7VR5J.js +1 -0
- package/server/public/assets/github-light-default-CZlC_y8X.js +1 -0
- package/server/public/assets/github-light-high-contrast-Cpzf_dNN.js +1 -0
- package/server/public/assets/gl-ES-HMX3MZ6V-DpXg7EFh.js +10 -0
- package/server/public/assets/gleam-B2rRUehk.js +1 -0
- package/server/public/assets/glimmer-js-JE9OX7en.js +1 -0
- package/server/public/assets/glimmer-ts-BlJ_q6LG.js +1 -0
- package/server/public/assets/glsl-DB7rO3Hv.js +1 -0
- package/server/public/assets/gn-CEKH5LbK.js +1 -0
- package/server/public/assets/gnuplot-D1ry687e.js +1 -0
- package/server/public/assets/go-CfRdqiLh.js +1 -0
- package/server/public/assets/graphlib-BC99DIRv.js +1 -0
- package/server/public/assets/graphql-DtareNVU.js +1 -0
- package/server/public/assets/groovy-CxzQ9MxI.js +1 -0
- package/server/public/assets/gruvbox-dark-hard-Dlubl6r4.js +1 -0
- package/server/public/assets/gruvbox-dark-medium-Bys2crvl.js +1 -0
- package/server/public/assets/gruvbox-dark-soft-D5JVdD_T.js +1 -0
- package/server/public/assets/gruvbox-light-hard-okzwij0Q.js +1 -0
- package/server/public/assets/gruvbox-light-medium-CKptZdRG.js +1 -0
- package/server/public/assets/gruvbox-light-soft-DVSSH44h.js +1 -0
- package/server/public/assets/hack-DxMpTO_4.js +1 -0
- package/server/public/assets/haml-B_eT_igf.js +1 -0
- package/server/public/assets/handlebars-CSFAnckr.js +1 -0
- package/server/public/assets/haskell-YCXH9qQq.js +1 -0
- package/server/public/assets/haxe-Bn69brdB.js +1 -0
- package/server/public/assets/hcl-CbZ1J22I.js +1 -0
- package/server/public/assets/he-IL-6SHJWFNN-BMSTSBvN.js +10 -0
- package/server/public/assets/hi-IN-IWLTKZ5I-DMhFQkOg.js +4 -0
- package/server/public/assets/highlighted-body-OFNGDK62-DFxe8Imf.js +1 -0
- package/server/public/assets/hjson-BQ8GzPPh.js +1 -0
- package/server/public/assets/hlsl-D98WkMKb.js +1 -0
- package/server/public/assets/horizon-DmShg3vP.js +1 -0
- package/server/public/assets/horizon-bright-Bd1Bl5O4.js +1 -0
- package/server/public/assets/houston-BKDA2pkW.js +1 -0
- package/server/public/assets/html-CUX3CWXm.js +1 -0
- package/server/public/assets/html-derivative-UiwgJSUF.js +1 -0
- package/server/public/assets/html-void-elements-QR3T3anA.js +1 -0
- package/server/public/assets/http-ggBV9BA7.js +1 -0
- package/server/public/assets/hu-HU-A5ZG7DT2-BD6vejvV.js +7 -0
- package/server/public/assets/hurl-Bo3fRJZD.js +1 -0
- package/server/public/assets/hxml-Y8hs-mDA.js +1 -0
- package/server/public/assets/hy-TQqVQLOm.js +1 -0
- package/server/public/assets/id-ID-SAP4L64H-DA3wkF_H.js +10 -0
- package/server/public/assets/image-GAAHSSAO-2UqQdVes.js +1 -0
- package/server/public/assets/image-blob-reduce.esm-BzeMsgWI.js +2 -0
- package/server/public/assets/imba-CwiMffo5.js +1 -0
- package/server/public/assets/index--mf7PRYx.css +1 -0
- package/server/public/assets/index-DtYTWOQ8.js +800 -0
- package/server/public/assets/info-J43DQDTF-CprmKodF.js +1 -0
- package/server/public/assets/infoDiagram-5YYISTIA-Bx9nY_uH.js +2 -0
- package/server/public/assets/ini-C967Bhky.js +1 -0
- package/server/public/assets/ishikawaDiagram-YF4QCWOH-DSeZGBiW.js +70 -0
- package/server/public/assets/it-IT-JPQ66NNP-D0yvY2jL.js +11 -0
- package/server/public/assets/ja-JP-DBVTYXUO-CfAjOu6t.js +8 -0
- package/server/public/assets/java-DwXGFxfd.js +1 -0
- package/server/public/assets/javascript-CMCEf6AT.js +1 -0
- package/server/public/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
- package/server/public/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff +0 -0
- package/server/public/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff +0 -0
- package/server/public/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
- package/server/public/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
- package/server/public/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
- package/server/public/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
- package/server/public/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff +0 -0
- package/server/public/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff +0 -0
- package/server/public/assets/jinja-BNgjwVV6.js +1 -0
- package/server/public/assets/jison-DJFHLmTv.js +1 -0
- package/server/public/assets/journeyDiagram-JHISSGLW-CpX6Ib-L.js +139 -0
- package/server/public/assets/json-C8nZKV3Z.js +1 -0
- package/server/public/assets/json5-lR98ZZok.js +1 -0
- package/server/public/assets/jsonc-DNYlSUsn.js +1 -0
- package/server/public/assets/jsonl-D9To9SlS.js +1 -0
- package/server/public/assets/jsonnet-Cft9xrDn.js +1 -0
- package/server/public/assets/jssm-iTI9PnSI.js +1 -0
- package/server/public/assets/jsx-7jEc9fS2.js +1 -0
- package/server/public/assets/jsx-runtime-CEixWuwE.js +1 -0
- package/server/public/assets/julia-CHAVw5nA.js +1 -0
- package/server/public/assets/just-DA7G4JJf.js +1 -0
- package/server/public/assets/kaa-6HZHGXH3-COQgw87F.js +1 -0
- package/server/public/assets/kab-KAB-ZGHBKWFO-BZhynvkV.js +8 -0
- package/server/public/assets/kanagawa-dragon-Bv6wp9iT.js +1 -0
- package/server/public/assets/kanagawa-lotus-CfOCfV4r.js +1 -0
- package/server/public/assets/kanagawa-wave-C8qTY0oB.js +1 -0
- package/server/public/assets/kanban-definition-UN3LZRKU-BEIiq959.js +89 -0
- package/server/public/assets/katex-CaPXO6Cc.js +257 -0
- package/server/public/assets/kdl-Bg7ZsUQG.js +1 -0
- package/server/public/assets/kk-KZ-P5N5QNE5-CawfIzOI.js +1 -0
- package/server/public/assets/km-KH-HSX4SM5Z-DloCSYoL.js +11 -0
- package/server/public/assets/ko-KR-MTYHY66A-pWdDCwlQ.js +9 -0
- package/server/public/assets/kotlin-q11cQQcy.js +1 -0
- package/server/public/assets/ku-TR-6OUDTVRD-Vq1URHZO.js +9 -0
- package/server/public/assets/kusto-_HfEALGY.js +1 -0
- package/server/public/assets/laserwave-CLNi_EUT.js +1 -0
- package/server/public/assets/latex-BBzosFBn.js +1 -0
- package/server/public/assets/lean-BOHZ4erQ.js +1 -0
- package/server/public/assets/less-10_el3T9.js +1 -0
- package/server/public/assets/light-plus-MuY4-yps.js +1 -0
- package/server/public/assets/line-ClHTS57e.js +1 -0
- package/server/public/assets/linear-DwYwoRdv.js +1 -0
- package/server/public/assets/liquid-C5QiuOs4.js +1 -0
- package/server/public/assets/llvm-Dq13G_VQ.js +1 -0
- package/server/public/assets/log-BHYZjBq-.js +1 -0
- package/server/public/assets/logo-c9pDEXL9.js +1 -0
- package/server/public/assets/lt-LT-XHIRWOB4-Ci8fQTWw.js +3 -0
- package/server/public/assets/lua-DUN8k3vI.js +1 -0
- package/server/public/assets/luau-Dawg3iVU.js +1 -0
- package/server/public/assets/lv-LV-5QDEKY6T-CKmAdQS7.js +7 -0
- package/server/public/assets/make-VyMojFZ9.js +1 -0
- package/server/public/assets/markdown-hvmaQbLY.js +1 -0
- package/server/public/assets/marko-DyeIi_wM.js +1 -0
- package/server/public/assets/material-theme-ED1VM4I9.js +1 -0
- package/server/public/assets/material-theme-darker-Bo70gaS5.js +1 -0
- package/server/public/assets/material-theme-lighter-rol9O-pJ.js +1 -0
- package/server/public/assets/material-theme-ocean-CDxsWl9n.js +1 -0
- package/server/public/assets/material-theme-palenight-D_Uye1xT.js +1 -0
- package/server/public/assets/matlab-DBG_t28C.js +1 -0
- package/server/public/assets/mdc-B7Bu1-dB.js +1 -0
- package/server/public/assets/mdx-DNcn2HFE.js +1 -0
- package/server/public/assets/mermaid-Cj7l1Jnj.js +1 -0
- package/server/public/assets/mermaid-GHXKKRXX-YYK67xv6.js +1 -0
- package/server/public/assets/mermaid-parser.core-BzIw2UoH.js +4 -0
- package/server/public/assets/min-dark-CMC1i68i.js +1 -0
- package/server/public/assets/min-light-CGJ7QqK3.js +1 -0
- package/server/public/assets/mindmap-definition-RKZ34NQL-D-hHsm92.js +96 -0
- package/server/public/assets/mipsasm-BLhEWidU.js +1 -0
- package/server/public/assets/mojo-DuS6JQbd.js +1 -0
- package/server/public/assets/monokai-BM5hqI7Q.js +1 -0
- package/server/public/assets/moonbit-CypUTukE.js +1 -0
- package/server/public/assets/move-BdQj4Tu_.js +1 -0
- package/server/public/assets/mr-IN-CRQNXWMA-DKVSQLNT.js +13 -0
- package/server/public/assets/my-MM-5M5IBNSE-BtWTkP31.js +1 -0
- package/server/public/assets/narrat-TMow1kc5.js +1 -0
- package/server/public/assets/nb-NO-T6EIAALU-Cdl2Nal6.js +10 -0
- package/server/public/assets/nextflow-1Nm7UTNp.js +1 -0
- package/server/public/assets/nextflow-groovy-Dlq_Tqm0.js +1 -0
- package/server/public/assets/nginx-BGk8nZGn.js +1 -0
- package/server/public/assets/night-owl-WgTI24JO.js +1 -0
- package/server/public/assets/night-owl-light-CWVQct1q.js +1 -0
- package/server/public/assets/nim-Bpgzjh-p.js +1 -0
- package/server/public/assets/nix-BiVJI49R.js +1 -0
- package/server/public/assets/nl-NL-IS3SIHDZ-D6CmYQUO.js +8 -0
- package/server/public/assets/nn-NO-6E72VCQL-BmxNzxtk.js +8 -0
- package/server/public/assets/nord-Uod98grW.js +1 -0
- package/server/public/assets/nushell-CejIGGbd.js +1 -0
- package/server/public/assets/objective-c-XImYcMVq.js +1 -0
- package/server/public/assets/objective-cpp-kStprhux.js +1 -0
- package/server/public/assets/oc-FR-POXYY2M6-CNlxd8gp.js +8 -0
- package/server/public/assets/ocaml-Cr8pc87i.js +1 -0
- package/server/public/assets/odin-CVAMstyz.js +1 -0
- package/server/public/assets/one-dark-pro-BlJJ_2h-.js +1 -0
- package/server/public/assets/one-light-DITMDUtn.js +1 -0
- package/server/public/assets/openscad-Ard4jfu8.js +1 -0
- package/server/public/assets/pa-IN-N4M65BXN-BhCk8tTz.js +4 -0
- package/server/public/assets/packet-YPE3B663-0qfSeEud.js +1 -0
- package/server/public/assets/pascal-qvXe8Xyy.js +1 -0
- package/server/public/assets/path-C0I-eoZY.js +1 -0
- package/server/public/assets/percentages-BXMCSKIN-CVoXL5-O.js +1 -0
- package/server/public/assets/perl-DJbpw6Wl.js +1 -0
- package/server/public/assets/php-DQ9BfS13.js +1 -0
- package/server/public/assets/pica-CgYEdS5s.js +2 -0
- package/server/public/assets/pie-LRSECV5Y-CgigMslL.js +1 -0
- package/server/public/assets/pieDiagram-4H26LBE5-BkjaiAxk.js +30 -0
- package/server/public/assets/pierre-dark-C6upavPg.js +1 -0
- package/server/public/assets/pierre-light-BiHtkl9W.js +1 -0
- package/server/public/assets/pkl-tZEgYmWv.js +1 -0
- package/server/public/assets/pl-PL-T2D74RX3-C5s-gmAN.js +9 -0
- package/server/public/assets/plastic-C1N3UJD8.js +1 -0
- package/server/public/assets/plsql-Ci3tqSis.js +1 -0
- package/server/public/assets/po-CiH8Msme.js +1 -0
- package/server/public/assets/poimandres-DqOOqTCi.js +1 -0
- package/server/public/assets/polar-CAFK6zYn.js +1 -0
- package/server/public/assets/postcss-BnjjGg21.js +1 -0
- package/server/public/assets/powerquery-CC3qIj51.js +1 -0
- package/server/public/assets/powershell-CfgS0S56.js +1 -0
- package/server/public/assets/preload-helper-DWTEM3RW.js +1 -0
- package/server/public/assets/prisma-Db7HVlXd.js +1 -0
- package/server/public/assets/prod-D5kET3Ov.js +109 -0
- package/server/public/assets/prolog-BDaoaHHW.js +1 -0
- package/server/public/assets/proto-D-Y4LWho.js +1 -0
- package/server/public/assets/pt-BR-5N22H2LF-BBx5EFfr.js +9 -0
- package/server/public/assets/pt-PT-UZXXM6DQ-Bw9VnloL.js +9 -0
- package/server/public/assets/pug-QFMWku9O.js +1 -0
- package/server/public/assets/puppet-DMxR6cCH.js +1 -0
- package/server/public/assets/purescript-ZQ_pLtrD.js +1 -0
- package/server/public/assets/python-D2TsaySt.js +1 -0
- package/server/public/assets/qml-DbNxxmb8.js +1 -0
- package/server/public/assets/qmldir-xGiOQcKN.js +1 -0
- package/server/public/assets/qss-DBUbSQ_t.js +1 -0
- package/server/public/assets/quadrantDiagram-W4KKPZXB-CwMk2BkV.js +7 -0
- package/server/public/assets/r-CFG-KSi0.js +1 -0
- package/server/public/assets/racket-5E6g40ay.js +1 -0
- package/server/public/assets/radar-GUYGQ44K-C2YC03tx.js +1 -0
- package/server/public/assets/raku-DSzo8BtJ.js +1 -0
- package/server/public/assets/razor-Bm_20ylP.js +1 -0
- package/server/public/assets/react-dom-DnbdNgHn.js +8 -0
- package/server/public/assets/red-BNJbwk9a.js +1 -0
- package/server/public/assets/reg-CTs5PN1b.js +1 -0
- package/server/public/assets/regexp-Cg9yhs1s.js +1 -0
- package/server/public/assets/rel-Ci2NfjKT.js +1 -0
- package/server/public/assets/requirementDiagram-4Y6WPE33-DW2QqhGU.js +84 -0
- package/server/public/assets/riscv-CD1sZafl.js +1 -0
- package/server/public/assets/ro-RO-JPDTUUEW-BznvT6Jr.js +11 -0
- package/server/public/assets/ron-5_okGRNe.js +1 -0
- package/server/public/assets/rose-pine-BGsqMv1j.js +1 -0
- package/server/public/assets/rose-pine-dawn-Dg-GUtdp.js +1 -0
- package/server/public/assets/rose-pine-moon-QGu8mKO2.js +1 -0
- package/server/public/assets/rosmsg-B-5Pf0kq.js +1 -0
- package/server/public/assets/rough.esm-ec8xsRC7.js +1 -0
- package/server/public/assets/roundRect-BzxbcNlg.js +1 -0
- package/server/public/assets/rst-DiKxgtQw.js +1 -0
- package/server/public/assets/ru-RU-B4JR7IUQ-CPNTI_q0.js +9 -0
- package/server/public/assets/ruby-DXW7M0u6.js +1 -0
- package/server/public/assets/rust-DDguLp-f.js +1 -0
- package/server/public/assets/sankeyDiagram-5OEKKPKP-CA549BVM.js +40 -0
- package/server/public/assets/sas-CHMyqMwI.js +1 -0
- package/server/public/assets/sass-DoExAd5N.js +1 -0
- package/server/public/assets/scala-r-gO7bU0.js +1 -0
- package/server/public/assets/scheme-DNefl1Un.js +1 -0
- package/server/public/assets/scss-B9l_DMkG.js +1 -0
- package/server/public/assets/sdbl-Djwdbzuv.js +1 -0
- package/server/public/assets/sequenceDiagram-3UESZ5HK-B-D_wEPM.js +162 -0
- package/server/public/assets/shaderlab-BfgwlY9N.js +1 -0
- package/server/public/assets/shellscript-CtJe2GoF.js +1 -0
- package/server/public/assets/shellsession-XD3n0AXo.js +1 -0
- package/server/public/assets/si-LK-N5RQ5JYF-CSJIF5cK.js +1 -0
- package/server/public/assets/sk-SK-C5VTKIMK-BKox76Y8.js +6 -0
- package/server/public/assets/sl-SI-NN7IZMDC-BRCy-AXr.js +6 -0
- package/server/public/assets/slack-dark-CZecJMEg.js +1 -0
- package/server/public/assets/slack-ochin-D_H-mkkW.js +1 -0
- package/server/public/assets/smalltalk-CWfWFmRM.js +1 -0
- package/server/public/assets/snazzy-light-cBupjfAy.js +1 -0
- package/server/public/assets/solarized-dark-gdvQlSAp.js +1 -0
- package/server/public/assets/solarized-light-B2oQAAcd.js +1 -0
- package/server/public/assets/solidity-Cv-QJjnG.js +1 -0
- package/server/public/assets/soy-B4SQpYLQ.js +1 -0
- package/server/public/assets/space-grotesk-latin-400-normal-BnQMeOim.woff +0 -0
- package/server/public/assets/space-grotesk-latin-400-normal-CJ-V5oYT.woff2 +0 -0
- package/server/public/assets/space-grotesk-latin-600-normal-BflQw4A9.woff +0 -0
- package/server/public/assets/space-grotesk-latin-600-normal-DjKNqYRj.woff2 +0 -0
- package/server/public/assets/space-grotesk-latin-700-normal-CwsQ-cCU.woff +0 -0
- package/server/public/assets/space-grotesk-latin-700-normal-RjhwGPKo.woff2 +0 -0
- package/server/public/assets/space-grotesk-latin-ext-400-normal-CfP_5XZW.woff2 +0 -0
- package/server/public/assets/space-grotesk-latin-ext-400-normal-DRPE3kg4.woff +0 -0
- package/server/public/assets/space-grotesk-latin-ext-600-normal-DxxdqCpr.woff2 +0 -0
- package/server/public/assets/space-grotesk-latin-ext-600-normal-VcznFIpX.woff +0 -0
- package/server/public/assets/space-grotesk-latin-ext-700-normal-BQnZhY3m.woff2 +0 -0
- package/server/public/assets/space-grotesk-latin-ext-700-normal-HVCqSBdx.woff +0 -0
- package/server/public/assets/space-grotesk-vietnamese-400-normal-B7xT_GF5.woff2 +0 -0
- package/server/public/assets/space-grotesk-vietnamese-400-normal-BIWiOVfw.woff +0 -0
- package/server/public/assets/space-grotesk-vietnamese-600-normal-D6zpsUhD.woff +0 -0
- package/server/public/assets/space-grotesk-vietnamese-600-normal-DUi7WF5p.woff2 +0 -0
- package/server/public/assets/space-grotesk-vietnamese-700-normal-DMty7AZE.woff2 +0 -0
- package/server/public/assets/space-grotesk-vietnamese-700-normal-Duxec5Rn.woff +0 -0
- package/server/public/assets/sparql-C3_E314U.js +1 -0
- package/server/public/assets/splunk-BerPEoGB.js +1 -0
- package/server/public/assets/sql-BoZjwy0s.js +1 -0
- package/server/public/assets/src-CsT-wIyx.js +1 -0
- package/server/public/assets/src-Csh0f24o.js +1 -0
- package/server/public/assets/ssh-config-Dj2fR7If.js +1 -0
- package/server/public/assets/stata-Dco15DDQ.js +1 -0
- package/server/public/assets/stateDiagram-AJRCARHV-ChTlvt6P.js +1 -0
- package/server/public/assets/stateDiagram-v2-BHNVJYJU-Diy8wLR6.js +1 -0
- package/server/public/assets/styles-DkK0ymA2.css +1 -0
- package/server/public/assets/stylus-DbiVYBZ3.js +1 -0
- package/server/public/assets/subset-shared.chunk-CI_8ZxgI.js +1 -0
- package/server/public/assets/subset-worker.chunk-DsFtco9z.js +1 -0
- package/server/public/assets/surrealql-DyNEi36w.js +1 -0
- package/server/public/assets/sv-SE-XGPEYMSR-G5L3U9t1.js +10 -0
- package/server/public/assets/svelte-CQE0K2YM.js +1 -0
- package/server/public/assets/swift-ot2k6t9R.js +1 -0
- package/server/public/assets/synthwave-84-D8UnynWH.js +1 -0
- package/server/public/assets/system-verilog-DiHTDeZ9.js +1 -0
- package/server/public/assets/systemd-w284dYvQ.js +1 -0
- package/server/public/assets/ta-IN-2NMHFXQM-BkJ_MoSw.js +9 -0
- package/server/public/assets/talonscript-BBQueGlS.js +1 -0
- package/server/public/assets/tasl-CWvSTHrG.js +1 -0
- package/server/public/assets/tcl-DGfZtktM.js +1 -0
- package/server/public/assets/templ-DBGKqxq2.js +1 -0
- package/server/public/assets/terraform-BvTRGW3C.js +1 -0
- package/server/public/assets/tex-Djb_8T3k.js +1 -0
- package/server/public/assets/th-TH-HPSO5L25-BOfscuf4.js +2 -0
- package/server/public/assets/timeline-definition-PNZ67QCA-Bq2WthSB.js +120 -0
- package/server/public/assets/tokyo-night-Ds5z6Zya.js +1 -0
- package/server/public/assets/toml-klzYdovv.js +1 -0
- package/server/public/assets/tr-TR-DEFEU3FU-CnE-2iPO.js +7 -0
- package/server/public/assets/treeView-BLDUP644-CW4NArqw.js +1 -0
- package/server/public/assets/treemap-LRROVOQU-CzJuFU5-.js +1 -0
- package/server/public/assets/ts-tags-BMQuJI7H.js +1 -0
- package/server/public/assets/tsv-D8US9LMe.js +1 -0
- package/server/public/assets/tsx-BNeRNgay.js +1 -0
- package/server/public/assets/turtle-BQazhbah.js +1 -0
- package/server/public/assets/twig-CO1mu8ZY.js +1 -0
- package/server/public/assets/typescript-IaFVOaio.js +1 -0
- package/server/public/assets/typespec-CsKPE17r.js +1 -0
- package/server/public/assets/typst-Fqd_dMtJ.js +1 -0
- package/server/public/assets/uk-UA-QMV73CPH-DerbDK4Z.js +6 -0
- package/server/public/assets/v-CqGPWQNg.js +1 -0
- package/server/public/assets/vala-CxlcY90g.js +1 -0
- package/server/public/assets/vb-Cbnw9gCO.js +1 -0
- package/server/public/assets/vennDiagram-CIIHVFJN-DoNYRIIB.js +34 -0
- package/server/public/assets/verilog-C6wkj-Ol.js +1 -0
- package/server/public/assets/vesper-TJDWy4tc.js +1 -0
- package/server/public/assets/vhdl-D-BxAYkR.js +1 -0
- package/server/public/assets/vi-VN-M7AON7JQ-C3o-OP7n.js +5 -0
- package/server/public/assets/viml-OR_l3-uc.js +1 -0
- package/server/public/assets/vitesse-black-Copvu6kY.js +1 -0
- package/server/public/assets/vitesse-dark-y09Q6P8m.js +1 -0
- package/server/public/assets/vitesse-light-mwqNHWUx.js +1 -0
- package/server/public/assets/vue-BRWc8zFO.js +1 -0
- package/server/public/assets/vue-html-DeoYv0pp.js +1 -0
- package/server/public/assets/vue-vine-DCaC4v_2.js +1 -0
- package/server/public/assets/vyper-BmC8C5hl.js +1 -0
- package/server/public/assets/wardley-L42UT6IY-Bn20_tWr.js +1 -0
- package/server/public/assets/wardleyDiagram-YWT4CUSO-jP4te9Sj.js +78 -0
- package/server/public/assets/wasm-3ES34QOA.js +1 -0
- package/server/public/assets/wasm-DNrvLWf-.js +1 -0
- package/server/public/assets/wenyan-Bl366nQd.js +1 -0
- package/server/public/assets/wgsl-bWPfFtTb.js +1 -0
- package/server/public/assets/wikitext-DwZ2L4m4.js +1 -0
- package/server/public/assets/wit-Cs0_8FrO.js +1 -0
- package/server/public/assets/wolfram-Dn23U3bT.js +1 -0
- package/server/public/assets/worker-C-69Fj6S.js +160 -0
- package/server/public/assets/xml-DuJ43izn.js +1 -0
- package/server/public/assets/xsl-gLKQE284.js +1 -0
- package/server/public/assets/xychartDiagram-2RQKCTM6-WyNBIQBE.js +7 -0
- package/server/public/assets/yaml-C_3EjdK_.js +1 -0
- package/server/public/assets/zenscript-DgYQK0Xn.js +1 -0
- package/server/public/assets/zh-CN-LNUGB5OW-CbkS4H4v.js +10 -0
- package/server/public/assets/zh-HK-E62DVLB3-Ch8IEAI6.js +1 -0
- package/server/public/assets/zh-TW-RAJ6MFWO-CeOf11gb.js +9 -0
- package/server/public/assets/zig-BmM40npt.js +1 -0
- package/server/public/index.html +116 -0
- package/server/server.js +56107 -0
|
@@ -0,0 +1,1155 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region \0rolldown/runtime.js
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
+
key = keys[i];
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
13
|
+
get: ((k) => from[k]).bind(null, key),
|
|
14
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
20
|
+
value: mod,
|
|
21
|
+
enumerable: true
|
|
22
|
+
}) : target, mod));
|
|
23
|
+
//#endregion
|
|
24
|
+
let node_fs = require("node:fs");
|
|
25
|
+
node_fs = __toESM(node_fs);
|
|
26
|
+
let node_path = require("node:path");
|
|
27
|
+
node_path = __toESM(node_path);
|
|
28
|
+
let electron = require("electron");
|
|
29
|
+
let node_child_process = require("node:child_process");
|
|
30
|
+
node_child_process = __toESM(node_child_process);
|
|
31
|
+
let node_crypto = require("node:crypto");
|
|
32
|
+
node_crypto = __toESM(node_crypto);
|
|
33
|
+
let electron_updater = require("electron-updater");
|
|
34
|
+
//#region src/settings.ts
|
|
35
|
+
/**
|
|
36
|
+
* Desktop-specific settings, persisted to userData/desktop-settings.json.
|
|
37
|
+
*
|
|
38
|
+
* Covers: tray appearance, per-event notification toggles, auto-start config.
|
|
39
|
+
* Loaded at app startup; updated via IPC from renderer.
|
|
40
|
+
*/
|
|
41
|
+
const DEFAULTS = {
|
|
42
|
+
tray: {
|
|
43
|
+
showBadge: true,
|
|
44
|
+
tooltipDetail: "full"
|
|
45
|
+
},
|
|
46
|
+
notifications: {
|
|
47
|
+
inputNeeded: true,
|
|
48
|
+
stuckAgents: true,
|
|
49
|
+
mergeFailures: true,
|
|
50
|
+
workComplete: true,
|
|
51
|
+
planningDone: false,
|
|
52
|
+
mergeReady: true
|
|
53
|
+
},
|
|
54
|
+
autoStart: {
|
|
55
|
+
enabled: false,
|
|
56
|
+
nagCount: 0,
|
|
57
|
+
nagDismissed: false
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
let settings = deepClone(DEFAULTS);
|
|
61
|
+
function deepClone(obj) {
|
|
62
|
+
return JSON.parse(JSON.stringify(obj));
|
|
63
|
+
}
|
|
64
|
+
function settingsPath() {
|
|
65
|
+
return node_path.join(electron.app.getPath("userData"), "desktop-settings.json");
|
|
66
|
+
}
|
|
67
|
+
function loadDesktopSettings() {
|
|
68
|
+
try {
|
|
69
|
+
const raw = node_fs.readFileSync(settingsPath(), "utf8");
|
|
70
|
+
const parsed = JSON.parse(raw);
|
|
71
|
+
settings = {
|
|
72
|
+
tray: {
|
|
73
|
+
...DEFAULTS.tray,
|
|
74
|
+
...parsed.tray
|
|
75
|
+
},
|
|
76
|
+
notifications: {
|
|
77
|
+
...DEFAULTS.notifications,
|
|
78
|
+
...parsed.notifications
|
|
79
|
+
},
|
|
80
|
+
autoStart: {
|
|
81
|
+
...DEFAULTS.autoStart,
|
|
82
|
+
...parsed.autoStart
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
} catch {
|
|
86
|
+
settings = deepClone(DEFAULTS);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function saveDesktopSettings() {
|
|
90
|
+
try {
|
|
91
|
+
node_fs.writeFileSync(settingsPath(), JSON.stringify(settings, null, 2));
|
|
92
|
+
} catch {
|
|
93
|
+
console.error("[desktop] failed to save desktop settings");
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function getDesktopSettings() {
|
|
97
|
+
return settings;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Update a single setting by dotted key (e.g. "notifications.inputNeeded").
|
|
101
|
+
* Returns true if the key was found and updated.
|
|
102
|
+
*/
|
|
103
|
+
function updateDesktopSetting(key, value) {
|
|
104
|
+
const [section, field] = key.split(".");
|
|
105
|
+
if (!section || !field) return false;
|
|
106
|
+
const s = settings;
|
|
107
|
+
if (!s[section] || !(field in s[section])) return false;
|
|
108
|
+
s[section][field] = value;
|
|
109
|
+
saveDesktopSettings();
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
//#endregion
|
|
113
|
+
//#region src/tray.ts
|
|
114
|
+
let tray = null;
|
|
115
|
+
let pollTimer = null;
|
|
116
|
+
const STATUS_COLORS = {
|
|
117
|
+
idle: "#22c55e",
|
|
118
|
+
working: "#f59e0b",
|
|
119
|
+
attention: "#ef4444"
|
|
120
|
+
};
|
|
121
|
+
function createTrayIcon(status) {
|
|
122
|
+
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16">
|
|
123
|
+
<circle cx="8" cy="8" r="7" fill="${STATUS_COLORS[status]}" stroke="#00000033" stroke-width="0.5"/>
|
|
124
|
+
<ellipse cx="8" cy="8" rx="5.5" ry="3.8" stroke="#ffffff44" stroke-width="0.5" fill="none"/>
|
|
125
|
+
<circle cx="8" cy="8" r="2" fill="#ffffff99"/>
|
|
126
|
+
<circle cx="8" cy="8" r="1" fill="#00000066"/>
|
|
127
|
+
</svg>`;
|
|
128
|
+
return electron.nativeImage.createFromBuffer(Buffer.from(svg));
|
|
129
|
+
}
|
|
130
|
+
function buildTooltip(agentCount, attentionCount, lastActivity) {
|
|
131
|
+
if (getDesktopSettings().tray.tooltipDetail === "minimal") return `Overdeck — ${agentCount} agent${agentCount !== 1 ? "s" : ""}`;
|
|
132
|
+
const lines = ["Overdeck"];
|
|
133
|
+
lines.push(`${agentCount} agent${agentCount !== 1 ? "s" : ""} running`);
|
|
134
|
+
if (attentionCount > 0) lines.push(`⚠ ${attentionCount} need${attentionCount !== 1 ? "" : "s"} attention`);
|
|
135
|
+
if (lastActivity) lines.push(`Last: ${lastActivity}`);
|
|
136
|
+
return lines.join("\n");
|
|
137
|
+
}
|
|
138
|
+
function buildContextMenu() {
|
|
139
|
+
return electron.Menu.buildFromTemplate([
|
|
140
|
+
{
|
|
141
|
+
label: "Show Dashboard",
|
|
142
|
+
click: () => showOrCreateWindow()
|
|
143
|
+
},
|
|
144
|
+
{ type: "separator" },
|
|
145
|
+
{
|
|
146
|
+
label: "Start Cloister",
|
|
147
|
+
click: () => callServerApi("/api/cloister/start", "POST")
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
label: "Stop Cloister",
|
|
151
|
+
click: () => callServerApi("/api/cloister/stop", "POST")
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
label: "Emergency Stop All",
|
|
155
|
+
click: () => callServerApi("/api/agents/emergency-stop", "POST")
|
|
156
|
+
},
|
|
157
|
+
{ type: "separator" },
|
|
158
|
+
{
|
|
159
|
+
label: "Settings",
|
|
160
|
+
click: () => {
|
|
161
|
+
showOrCreateWindow();
|
|
162
|
+
dispatchMenuAction("open-settings");
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
{ type: "separator" },
|
|
166
|
+
{
|
|
167
|
+
label: "Quit",
|
|
168
|
+
click: () => {
|
|
169
|
+
electron.app.quit();
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
]);
|
|
173
|
+
}
|
|
174
|
+
async function refreshTrayStatus() {
|
|
175
|
+
if (!tray || isQuitting) return;
|
|
176
|
+
const url = serverUrl;
|
|
177
|
+
if (!url) return;
|
|
178
|
+
try {
|
|
179
|
+
const resp = await fetch(`${url}/api/health`, { signal: AbortSignal.timeout(3e3) });
|
|
180
|
+
if (!resp.ok) return;
|
|
181
|
+
const data = await resp.json();
|
|
182
|
+
const agentCount = data.agentCount ?? 0;
|
|
183
|
+
const attentionCount = data.attentionCount ?? 0;
|
|
184
|
+
const lastActivity = data.lastActivity ?? null;
|
|
185
|
+
const status = attentionCount > 0 ? "attention" : agentCount > 0 ? "working" : "idle";
|
|
186
|
+
tray.setImage(createTrayIcon(status));
|
|
187
|
+
tray.setToolTip(buildTooltip(agentCount, attentionCount, lastActivity));
|
|
188
|
+
tray.setContextMenu(buildContextMenu());
|
|
189
|
+
if (getDesktopSettings().tray.showBadge && process.platform === "darwin" && electron.app.dock) electron.app.dock.setBadge(agentCount > 0 ? String(agentCount) : "");
|
|
190
|
+
} catch {}
|
|
191
|
+
}
|
|
192
|
+
function createTray() {
|
|
193
|
+
if (tray) return;
|
|
194
|
+
tray = new electron.Tray(createTrayIcon("idle"));
|
|
195
|
+
tray.setToolTip("Overdeck");
|
|
196
|
+
tray.setContextMenu(buildContextMenu());
|
|
197
|
+
tray.on("click", () => showOrCreateWindow());
|
|
198
|
+
pollTimer = setInterval(() => void refreshTrayStatus(), 5e3);
|
|
199
|
+
refreshTrayStatus();
|
|
200
|
+
}
|
|
201
|
+
function destroyTray() {
|
|
202
|
+
if (pollTimer) {
|
|
203
|
+
clearInterval(pollTimer);
|
|
204
|
+
pollTimer = null;
|
|
205
|
+
}
|
|
206
|
+
tray?.destroy();
|
|
207
|
+
tray = null;
|
|
208
|
+
}
|
|
209
|
+
//#endregion
|
|
210
|
+
//#region src/server.ts
|
|
211
|
+
/**
|
|
212
|
+
* Embedded dashboard server management.
|
|
213
|
+
*
|
|
214
|
+
* Spawns dist/dashboard/server.js (or the packaged equivalent) as a child
|
|
215
|
+
* process, passing config via environment variables. Supports exponential-
|
|
216
|
+
* backoff restart on crash. Graceful shutdown on app quit.
|
|
217
|
+
*
|
|
218
|
+
* Bootstrap config passed via env vars:
|
|
219
|
+
* OVERDECK_PORT — TCP port for HTTP + WS
|
|
220
|
+
* OVERDECK_AUTH_TOKEN — random hex token (future: auth middleware)
|
|
221
|
+
* OVERDECK_MODE — "desktop" (enables desktop-specific behaviours)
|
|
222
|
+
* OVERDECK_NO_BROWSER — "1" (suppresses auto browser open)
|
|
223
|
+
*/
|
|
224
|
+
const BASE_PORT = 7825;
|
|
225
|
+
const MAX_RESTART_DELAY_MS = 3e4;
|
|
226
|
+
const SIGTERM_GRACE_MS = 3e3;
|
|
227
|
+
let serverProcess = null;
|
|
228
|
+
let restartAttempt = 0;
|
|
229
|
+
let restartTimer = null;
|
|
230
|
+
let quitting = false;
|
|
231
|
+
let onReadyCallback = null;
|
|
232
|
+
function randomHex(bytes) {
|
|
233
|
+
return node_crypto.randomBytes(bytes).toString("hex");
|
|
234
|
+
}
|
|
235
|
+
function resolvePort() {
|
|
236
|
+
return BASE_PORT + restartAttempt % 10;
|
|
237
|
+
}
|
|
238
|
+
function startServer(onReady) {
|
|
239
|
+
quitting = false;
|
|
240
|
+
onReadyCallback = onReady;
|
|
241
|
+
spawnServer();
|
|
242
|
+
}
|
|
243
|
+
function spawnServer() {
|
|
244
|
+
if (quitting) return;
|
|
245
|
+
const entry = resolveServerEntry();
|
|
246
|
+
if (!node_fs.existsSync(entry)) {
|
|
247
|
+
console.error(`[desktop/server] Server entry not found: ${entry}`);
|
|
248
|
+
console.error("[desktop/server] Run 'npm run build' to build the dashboard server first.");
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
const port = resolvePort();
|
|
252
|
+
const authToken = randomHex(32);
|
|
253
|
+
const child = node_child_process.spawn(process.execPath, [entry], {
|
|
254
|
+
env: {
|
|
255
|
+
...process.env,
|
|
256
|
+
OVERDECK_PORT: String(port),
|
|
257
|
+
OVERDECK_AUTH_TOKEN: authToken,
|
|
258
|
+
OVERDECK_MODE: "desktop",
|
|
259
|
+
OVERDECK_NO_BROWSER: "1",
|
|
260
|
+
TERM: process.env.TERM || "xterm-256color",
|
|
261
|
+
COLORTERM: process.env.COLORTERM || "truecolor",
|
|
262
|
+
LANG: process.env.LANG || "en_US.UTF-8",
|
|
263
|
+
ELECTRON_RUN_AS_NODE: void 0
|
|
264
|
+
},
|
|
265
|
+
stdio: [
|
|
266
|
+
"ignore",
|
|
267
|
+
"pipe",
|
|
268
|
+
"pipe"
|
|
269
|
+
]
|
|
270
|
+
});
|
|
271
|
+
serverProcess = child;
|
|
272
|
+
child.stdout?.on("data", (chunk) => {
|
|
273
|
+
process.stdout.write(`[server] ${chunk}`);
|
|
274
|
+
});
|
|
275
|
+
child.stderr?.on("data", (chunk) => {
|
|
276
|
+
process.stderr.write(`[server] ${chunk}`);
|
|
277
|
+
});
|
|
278
|
+
child.on("spawn", () => {
|
|
279
|
+
console.log(`[desktop/server] spawned pid=${child.pid} port=${port}`);
|
|
280
|
+
waitForServer(`http://127.0.0.1:${port}`, () => {
|
|
281
|
+
console.log(`[desktop/server] ready on port ${port}`);
|
|
282
|
+
onReadyCallback?.(port, `ws://127.0.0.1:${port}`);
|
|
283
|
+
});
|
|
284
|
+
});
|
|
285
|
+
child.on("exit", (code, signal) => {
|
|
286
|
+
serverProcess = null;
|
|
287
|
+
console.warn(`[desktop/server] exited code=${String(code)} signal=${String(signal)}`);
|
|
288
|
+
if (!quitting) scheduleRestart();
|
|
289
|
+
});
|
|
290
|
+
child.on("error", (err) => {
|
|
291
|
+
console.error("[desktop/server] spawn error:", err);
|
|
292
|
+
serverProcess = null;
|
|
293
|
+
if (!quitting) scheduleRestart();
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
function waitForServer(url, callback, maxMs = 3e4) {
|
|
297
|
+
const start = Date.now();
|
|
298
|
+
const interval = setInterval(() => {
|
|
299
|
+
if (Date.now() - start > maxMs) {
|
|
300
|
+
clearInterval(interval);
|
|
301
|
+
callback();
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
fetch(url + "/api/health", { signal: AbortSignal.timeout(1e3) }).then((r) => {
|
|
305
|
+
if (r.ok) {
|
|
306
|
+
clearInterval(interval);
|
|
307
|
+
callback();
|
|
308
|
+
}
|
|
309
|
+
}).catch(() => {});
|
|
310
|
+
}, 500);
|
|
311
|
+
}
|
|
312
|
+
function scheduleRestart() {
|
|
313
|
+
if (quitting) return;
|
|
314
|
+
restartAttempt++;
|
|
315
|
+
const delay = Math.min(1e3 * Math.pow(2, restartAttempt - 1), MAX_RESTART_DELAY_MS);
|
|
316
|
+
console.log(`[desktop/server] restarting in ${delay}ms (attempt ${restartAttempt})`);
|
|
317
|
+
restartTimer = setTimeout(() => {
|
|
318
|
+
restartTimer = null;
|
|
319
|
+
spawnServer();
|
|
320
|
+
}, delay);
|
|
321
|
+
}
|
|
322
|
+
function stopServer() {
|
|
323
|
+
quitting = true;
|
|
324
|
+
if (restartTimer) {
|
|
325
|
+
clearTimeout(restartTimer);
|
|
326
|
+
restartTimer = null;
|
|
327
|
+
}
|
|
328
|
+
const child = serverProcess;
|
|
329
|
+
if (!child) return;
|
|
330
|
+
serverProcess = null;
|
|
331
|
+
child.kill("SIGTERM");
|
|
332
|
+
setTimeout(() => {
|
|
333
|
+
try {
|
|
334
|
+
child.kill("SIGKILL");
|
|
335
|
+
} catch {}
|
|
336
|
+
}, SIGTERM_GRACE_MS).unref();
|
|
337
|
+
}
|
|
338
|
+
//#endregion
|
|
339
|
+
//#region src/updater.ts
|
|
340
|
+
/**
|
|
341
|
+
* Auto-updater service using electron-updater.
|
|
342
|
+
*
|
|
343
|
+
* Handles automatic background checks for updates, downloads, and installation.
|
|
344
|
+
* Uses GitHub Releases as the update server.
|
|
345
|
+
*/
|
|
346
|
+
const FOUR_HOURS_MS = 14400 * 1e3;
|
|
347
|
+
let checkIntervalId = null;
|
|
348
|
+
let initialized = false;
|
|
349
|
+
let currentStatus = {
|
|
350
|
+
checking: false,
|
|
351
|
+
available: false,
|
|
352
|
+
downloaded: false,
|
|
353
|
+
version: null,
|
|
354
|
+
error: null
|
|
355
|
+
};
|
|
356
|
+
let statusCallbacks = [];
|
|
357
|
+
/**
|
|
358
|
+
* Register a callback to receive update status changes.
|
|
359
|
+
*/
|
|
360
|
+
function onUpdateStatusChange(callback) {
|
|
361
|
+
statusCallbacks.push(callback);
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Notify all listeners of status change
|
|
365
|
+
*/
|
|
366
|
+
function notifyStatusChange() {
|
|
367
|
+
for (const cb of statusCallbacks) cb(currentStatus);
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Send update event to all browser windows
|
|
371
|
+
*/
|
|
372
|
+
function broadcastToRenderers(channel, ...args) {
|
|
373
|
+
for (const win of electron.BrowserWindow.getAllWindows()) if (!win.isDestroyed()) win.webContents.send(channel, ...args);
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Initialize the auto-updater service.
|
|
377
|
+
* Sets up event handlers and starts periodic update checks.
|
|
378
|
+
*/
|
|
379
|
+
function initializeAutoUpdater(channel = "latest") {
|
|
380
|
+
if (initialized) {
|
|
381
|
+
console.log("[updater] Already initialized, skipping...");
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
initialized = true;
|
|
385
|
+
electron_updater.autoUpdater.setFeedURL({
|
|
386
|
+
provider: "github",
|
|
387
|
+
owner: "eltmon",
|
|
388
|
+
repo: "overdeck"
|
|
389
|
+
});
|
|
390
|
+
electron_updater.autoUpdater.channel = channel;
|
|
391
|
+
electron_updater.autoUpdater.autoDownload = false;
|
|
392
|
+
electron_updater.autoUpdater.autoInstallOnAppQuit = true;
|
|
393
|
+
electron_updater.autoUpdater.on("checking-for-update", () => {
|
|
394
|
+
currentStatus = {
|
|
395
|
+
...currentStatus,
|
|
396
|
+
checking: true,
|
|
397
|
+
error: null
|
|
398
|
+
};
|
|
399
|
+
notifyStatusChange();
|
|
400
|
+
broadcastToRenderers("update-status", currentStatus);
|
|
401
|
+
console.log("[updater] Checking for update...");
|
|
402
|
+
});
|
|
403
|
+
electron_updater.autoUpdater.on("update-available", (info) => {
|
|
404
|
+
currentStatus = {
|
|
405
|
+
checking: false,
|
|
406
|
+
available: true,
|
|
407
|
+
downloaded: false,
|
|
408
|
+
version: info.version,
|
|
409
|
+
error: null
|
|
410
|
+
};
|
|
411
|
+
notifyStatusChange();
|
|
412
|
+
broadcastToRenderers("update-status", currentStatus);
|
|
413
|
+
console.log(`[updater] Update available: ${info.version}`);
|
|
414
|
+
});
|
|
415
|
+
electron_updater.autoUpdater.on("update-not-available", (info) => {
|
|
416
|
+
currentStatus = {
|
|
417
|
+
checking: false,
|
|
418
|
+
available: false,
|
|
419
|
+
downloaded: false,
|
|
420
|
+
version: info.version,
|
|
421
|
+
error: null
|
|
422
|
+
};
|
|
423
|
+
notifyStatusChange();
|
|
424
|
+
broadcastToRenderers("update-status", currentStatus);
|
|
425
|
+
console.log(`[updater] Update not available. Current version: ${info.version}`);
|
|
426
|
+
});
|
|
427
|
+
electron_updater.autoUpdater.on("download-progress", (progressObj) => {
|
|
428
|
+
const percent = progressObj.percent.toFixed(1);
|
|
429
|
+
currentStatus = {
|
|
430
|
+
...currentStatus,
|
|
431
|
+
checking: false
|
|
432
|
+
};
|
|
433
|
+
notifyStatusChange();
|
|
434
|
+
broadcastToRenderers("update-download-progress", {
|
|
435
|
+
percent,
|
|
436
|
+
transferred: progressObj.transferred,
|
|
437
|
+
total: progressObj.total
|
|
438
|
+
});
|
|
439
|
+
console.log(`[updater] Download progress: ${percent}%`);
|
|
440
|
+
});
|
|
441
|
+
electron_updater.autoUpdater.on("update-downloaded", (info) => {
|
|
442
|
+
currentStatus = {
|
|
443
|
+
checking: false,
|
|
444
|
+
available: true,
|
|
445
|
+
downloaded: true,
|
|
446
|
+
version: info.version,
|
|
447
|
+
error: null
|
|
448
|
+
};
|
|
449
|
+
notifyStatusChange();
|
|
450
|
+
broadcastToRenderers("update-status", currentStatus);
|
|
451
|
+
broadcastToRenderers("update-downloaded", { version: info.version });
|
|
452
|
+
console.log(`[updater] Update downloaded: ${info.version}`);
|
|
453
|
+
});
|
|
454
|
+
electron_updater.autoUpdater.on("error", (err) => {
|
|
455
|
+
currentStatus = {
|
|
456
|
+
checking: false,
|
|
457
|
+
available: false,
|
|
458
|
+
downloaded: false,
|
|
459
|
+
version: null,
|
|
460
|
+
error: err.message
|
|
461
|
+
};
|
|
462
|
+
notifyStatusChange();
|
|
463
|
+
broadcastToRenderers("update-status", currentStatus);
|
|
464
|
+
console.error("[updater] Error:", err.message);
|
|
465
|
+
});
|
|
466
|
+
setTimeout(() => {
|
|
467
|
+
checkForUpdates();
|
|
468
|
+
}, 3e3);
|
|
469
|
+
startPeriodicChecks();
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Start periodic update checks every 4 hours.
|
|
473
|
+
*/
|
|
474
|
+
function startPeriodicChecks() {
|
|
475
|
+
if (checkIntervalId !== null) return;
|
|
476
|
+
checkIntervalId = setInterval(() => {
|
|
477
|
+
checkForUpdates();
|
|
478
|
+
}, FOUR_HOURS_MS);
|
|
479
|
+
console.log("[updater] Started periodic update checks (every 4 hours)");
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Check for updates manually.
|
|
483
|
+
* Returns a promise that resolves when the check completes.
|
|
484
|
+
*/
|
|
485
|
+
async function checkForUpdates() {
|
|
486
|
+
if (currentStatus.checking) {
|
|
487
|
+
console.log("[updater] Already checking for update, skipping...");
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
try {
|
|
491
|
+
console.log("[updater] Starting update check...");
|
|
492
|
+
await electron_updater.autoUpdater.checkForUpdates();
|
|
493
|
+
} catch (err) {
|
|
494
|
+
console.error("[updater] Check for updates failed:", err);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* Download the available update.
|
|
499
|
+
*/
|
|
500
|
+
async function downloadUpdate() {
|
|
501
|
+
if (!currentStatus.available) {
|
|
502
|
+
console.log("[updater] No update available to download");
|
|
503
|
+
return;
|
|
504
|
+
}
|
|
505
|
+
try {
|
|
506
|
+
console.log("[updater] Starting update download...");
|
|
507
|
+
await electron_updater.autoUpdater.downloadUpdate();
|
|
508
|
+
} catch (err) {
|
|
509
|
+
console.error("[updater] Download update failed:", err);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* Quit and install the downloaded update.
|
|
514
|
+
*/
|
|
515
|
+
function quitAndInstall() {
|
|
516
|
+
if (!currentStatus.downloaded) {
|
|
517
|
+
console.log("[updater] No update downloaded to install");
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
console.log("[updater] Quitting and installing update...");
|
|
521
|
+
electron_updater.autoUpdater.quitAndInstall();
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* Get current update status.
|
|
525
|
+
*/
|
|
526
|
+
function getUpdateStatus() {
|
|
527
|
+
return currentStatus;
|
|
528
|
+
}
|
|
529
|
+
//#endregion
|
|
530
|
+
//#region src/menu.ts
|
|
531
|
+
/**
|
|
532
|
+
* Application menu bar for the Overdeck desktop app.
|
|
533
|
+
*
|
|
534
|
+
* Standard Electron menus: File, Edit, View, Window, Help
|
|
535
|
+
* Plus a Overdeck menu with all orchestration actions.
|
|
536
|
+
*
|
|
537
|
+
* macOS: app name menu with About, Settings, Services etc.
|
|
538
|
+
* Linux/Windows: Settings in File menu.
|
|
539
|
+
*/
|
|
540
|
+
async function fetchActiveWorkspaces() {
|
|
541
|
+
if (!serverUrl) return [];
|
|
542
|
+
try {
|
|
543
|
+
const resp = await fetch(`${serverUrl}/api/workspaces`, { signal: AbortSignal.timeout(2e3) });
|
|
544
|
+
if (!resp.ok) return [];
|
|
545
|
+
return (await resp.json()).workspaces?.slice(0, 10) ?? [];
|
|
546
|
+
} catch {
|
|
547
|
+
return [];
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
let updateDownloaded = false;
|
|
551
|
+
function rebuildMenu() {
|
|
552
|
+
const menu = electron.Menu.buildFromTemplate(buildMenuTemplate());
|
|
553
|
+
electron.Menu.setApplicationMenu(menu);
|
|
554
|
+
const overdeckMenu = menu.items.find((item) => item.label === "Overdeck");
|
|
555
|
+
if (overdeckMenu?.submenu) overdeckMenu.submenu.on("menu-will-show", () => {
|
|
556
|
+
fetchActiveWorkspaces().then((workspaces) => {
|
|
557
|
+
const wsItem = overdeckMenu.submenu?.items.find((i) => i.id === "open-workspace-submenu");
|
|
558
|
+
if (wsItem) wsItem.label = workspaces.length ? `Open Workspace (${workspaces.length})` : "Open Workspace";
|
|
559
|
+
});
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
function buildMenuTemplate() {
|
|
563
|
+
const template = [];
|
|
564
|
+
if (process.platform === "darwin") template.push({
|
|
565
|
+
label: electron.app.name,
|
|
566
|
+
submenu: [
|
|
567
|
+
{ role: "about" },
|
|
568
|
+
{ type: "separator" },
|
|
569
|
+
{
|
|
570
|
+
label: "Settings...",
|
|
571
|
+
accelerator: "CmdOrCtrl+,",
|
|
572
|
+
click: () => {
|
|
573
|
+
showOrCreateWindow();
|
|
574
|
+
dispatchMenuAction("open-settings");
|
|
575
|
+
}
|
|
576
|
+
},
|
|
577
|
+
{ type: "separator" },
|
|
578
|
+
{ role: "services" },
|
|
579
|
+
{ type: "separator" },
|
|
580
|
+
{ role: "hide" },
|
|
581
|
+
{ role: "hideOthers" },
|
|
582
|
+
{ role: "unhide" },
|
|
583
|
+
{ type: "separator" },
|
|
584
|
+
{ role: "quit" }
|
|
585
|
+
]
|
|
586
|
+
});
|
|
587
|
+
template.push({
|
|
588
|
+
label: "File",
|
|
589
|
+
submenu: [...process.platform !== "darwin" ? [{
|
|
590
|
+
label: "Settings...",
|
|
591
|
+
accelerator: "CmdOrCtrl+,",
|
|
592
|
+
click: () => {
|
|
593
|
+
showOrCreateWindow();
|
|
594
|
+
dispatchMenuAction("open-settings");
|
|
595
|
+
}
|
|
596
|
+
}, { type: "separator" }] : [], { role: process.platform === "darwin" ? "close" : "quit" }]
|
|
597
|
+
});
|
|
598
|
+
template.push({ role: "editMenu" });
|
|
599
|
+
template.push({
|
|
600
|
+
label: "View",
|
|
601
|
+
submenu: [
|
|
602
|
+
{ role: "reload" },
|
|
603
|
+
{ role: "forceReload" },
|
|
604
|
+
{ role: "toggleDevTools" },
|
|
605
|
+
{ type: "separator" },
|
|
606
|
+
{ role: "resetZoom" },
|
|
607
|
+
{
|
|
608
|
+
role: "zoomIn",
|
|
609
|
+
accelerator: "CmdOrCtrl+="
|
|
610
|
+
},
|
|
611
|
+
{ role: "zoomOut" },
|
|
612
|
+
{ type: "separator" },
|
|
613
|
+
{ role: "togglefullscreen" }
|
|
614
|
+
]
|
|
615
|
+
});
|
|
616
|
+
template.push({ role: "windowMenu" });
|
|
617
|
+
template.push({
|
|
618
|
+
label: "Overdeck",
|
|
619
|
+
submenu: [
|
|
620
|
+
{
|
|
621
|
+
label: "Start Cloister",
|
|
622
|
+
click: () => callServerApi("/api/cloister/start", "POST")
|
|
623
|
+
},
|
|
624
|
+
{
|
|
625
|
+
label: "Stop Cloister",
|
|
626
|
+
click: () => callServerApi("/api/cloister/stop", "POST")
|
|
627
|
+
},
|
|
628
|
+
{
|
|
629
|
+
label: "Emergency Stop All Agents",
|
|
630
|
+
click: () => callServerApi("/api/agents/emergency-stop", "POST")
|
|
631
|
+
},
|
|
632
|
+
{ type: "separator" },
|
|
633
|
+
{
|
|
634
|
+
label: "Open Workspace",
|
|
635
|
+
id: "open-workspace-submenu",
|
|
636
|
+
submenu: [{
|
|
637
|
+
label: "Loading...",
|
|
638
|
+
enabled: false
|
|
639
|
+
}]
|
|
640
|
+
},
|
|
641
|
+
{ type: "separator" },
|
|
642
|
+
{
|
|
643
|
+
label: "Settings...",
|
|
644
|
+
accelerator: process.platform !== "darwin" ? "CmdOrCtrl+," : void 0,
|
|
645
|
+
click: () => {
|
|
646
|
+
showOrCreateWindow();
|
|
647
|
+
dispatchMenuAction("open-settings");
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
]
|
|
651
|
+
});
|
|
652
|
+
template.push({
|
|
653
|
+
role: "help",
|
|
654
|
+
submenu: [
|
|
655
|
+
{
|
|
656
|
+
label: "Check for Updates...",
|
|
657
|
+
click: () => {
|
|
658
|
+
checkForUpdates();
|
|
659
|
+
}
|
|
660
|
+
},
|
|
661
|
+
{ type: "separator" },
|
|
662
|
+
{
|
|
663
|
+
label: "Flywheel Documentation",
|
|
664
|
+
click: () => void electron.shell.openExternal("https://github.com/eltmon/overdeck/blob/main/docs/FLYWHEEL.md")
|
|
665
|
+
},
|
|
666
|
+
{
|
|
667
|
+
label: "Overdeck on GitHub",
|
|
668
|
+
click: () => void electron.shell.openExternal("https://github.com/eltmon/overdeck")
|
|
669
|
+
},
|
|
670
|
+
{
|
|
671
|
+
label: "Report an Issue",
|
|
672
|
+
click: () => void electron.shell.openExternal("https://github.com/eltmon/overdeck/issues")
|
|
673
|
+
}
|
|
674
|
+
]
|
|
675
|
+
});
|
|
676
|
+
if (updateDownloaded) {
|
|
677
|
+
const helpMenu = template[template.length - 1];
|
|
678
|
+
if (helpMenu && helpMenu.submenu && Array.isArray(helpMenu.submenu)) helpMenu.submenu.push({ type: "separator" }, {
|
|
679
|
+
label: "Install Update and Restart",
|
|
680
|
+
click: () => {
|
|
681
|
+
quitAndInstall();
|
|
682
|
+
}
|
|
683
|
+
});
|
|
684
|
+
}
|
|
685
|
+
return template;
|
|
686
|
+
}
|
|
687
|
+
function configureApplicationMenu() {
|
|
688
|
+
const menu = electron.Menu.buildFromTemplate(buildMenuTemplate());
|
|
689
|
+
electron.Menu.setApplicationMenu(menu);
|
|
690
|
+
const overdeckMenu = menu.items.find((item) => item.label === "Overdeck");
|
|
691
|
+
if (overdeckMenu?.submenu) overdeckMenu.submenu.on("menu-will-show", () => {
|
|
692
|
+
fetchActiveWorkspaces().then((workspaces) => {
|
|
693
|
+
const wsItem = overdeckMenu.submenu?.items.find((i) => i.id === "open-workspace-submenu");
|
|
694
|
+
if (wsItem) wsItem.label = workspaces.length ? `Open Workspace (${workspaces.length})` : "Open Workspace";
|
|
695
|
+
});
|
|
696
|
+
});
|
|
697
|
+
onUpdateStatusChange((status) => {
|
|
698
|
+
if (status.downloaded && !updateDownloaded) {
|
|
699
|
+
updateDownloaded = true;
|
|
700
|
+
rebuildMenu();
|
|
701
|
+
}
|
|
702
|
+
});
|
|
703
|
+
}
|
|
704
|
+
//#endregion
|
|
705
|
+
//#region src/notifications.ts
|
|
706
|
+
/**
|
|
707
|
+
* Native desktop notifications for Overdeck events.
|
|
708
|
+
*
|
|
709
|
+
* Event types and their default enabled state (all configurable in Settings):
|
|
710
|
+
* inputNeeded — Agent needs user input (default: on)
|
|
711
|
+
* stuckAgents — Agent has been stuck > threshold (default: on)
|
|
712
|
+
* mergeFailures — Merge specialist failed (default: on)
|
|
713
|
+
* workComplete — Agent signalled work done (default: on)
|
|
714
|
+
* planningDone — Planning session complete (default: off)
|
|
715
|
+
* mergeReady — PR ready for human merge (default: on)
|
|
716
|
+
*
|
|
717
|
+
* Notifications are sent from:
|
|
718
|
+
* 1. Renderer → main via IPC (pan:notify) — for events the frontend detects
|
|
719
|
+
* 2. Main process directly — in future when subscribing to domain events via WS
|
|
720
|
+
*/
|
|
721
|
+
function sendNotification(eventType, title, body) {
|
|
722
|
+
if (!getDesktopSettings().notifications[eventType]) return;
|
|
723
|
+
if (!electron.Notification.isSupported()) return;
|
|
724
|
+
const notification = new electron.Notification({
|
|
725
|
+
title,
|
|
726
|
+
body,
|
|
727
|
+
icon: resolveResourcePath("icon.png") ?? void 0,
|
|
728
|
+
silent: false
|
|
729
|
+
});
|
|
730
|
+
notification.on("click", () => showOrCreateWindow());
|
|
731
|
+
notification.show();
|
|
732
|
+
}
|
|
733
|
+
function registerNotificationHandlers() {
|
|
734
|
+
electron.ipcMain.handle(IPC.NOTIFY, (_event, eventType, title, body) => {
|
|
735
|
+
if (typeof eventType === "string" && typeof title === "string" && typeof body === "string") sendNotification(eventType, title, body);
|
|
736
|
+
});
|
|
737
|
+
}
|
|
738
|
+
/**
|
|
739
|
+
* Called at app.ready to request notification permission on macOS.
|
|
740
|
+
* On Linux/Windows, Notification.isSupported() handles availability.
|
|
741
|
+
*/
|
|
742
|
+
function initializeNotifications() {
|
|
743
|
+
if (!electron.Notification.isSupported()) console.log("[desktop/notifications] native notifications not supported on this platform");
|
|
744
|
+
}
|
|
745
|
+
//#endregion
|
|
746
|
+
//#region src/autostart.ts
|
|
747
|
+
/**
|
|
748
|
+
* Auto-start nag flow for the Overdeck desktop app.
|
|
749
|
+
*
|
|
750
|
+
* Flow:
|
|
751
|
+
* Launch 1: Full explanation dialog (warm, inviting)
|
|
752
|
+
* Launch 2-5: In-app toasts dispatched to renderer via "auto-start-nag:<n>:<max>" menu action
|
|
753
|
+
* - Shows: "Reminder N of 5", Enable button (prominent), Not Yet, Stop Reminding Me
|
|
754
|
+
* After 5 or "Stop reminding me": never prompt again (nagDismissed = true)
|
|
755
|
+
* Once enabled: auto-start registered via app.setLoginItemSettings
|
|
756
|
+
*
|
|
757
|
+
* State tracked in DesktopSettings.autoStart via settings.ts.
|
|
758
|
+
*/
|
|
759
|
+
const NAG_MAX = 5;
|
|
760
|
+
function enableAutoStart() {
|
|
761
|
+
updateDesktopSetting("autoStart.enabled", true);
|
|
762
|
+
updateDesktopSetting("autoStart.nagDismissed", true);
|
|
763
|
+
electron.app.setLoginItemSettings({ openAtLogin: true });
|
|
764
|
+
}
|
|
765
|
+
function handleAutoStartNag() {
|
|
766
|
+
const { autoStart } = getDesktopSettings();
|
|
767
|
+
if (autoStart.enabled || autoStart.nagDismissed) return;
|
|
768
|
+
if (autoStart.nagCount >= NAG_MAX) {
|
|
769
|
+
updateDesktopSetting("autoStart.nagDismissed", true);
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
const count = autoStart.nagCount + 1;
|
|
773
|
+
updateDesktopSetting("autoStart.nagCount", count);
|
|
774
|
+
if (count === 1) showFirstLaunchDialog();
|
|
775
|
+
else setTimeout(() => {
|
|
776
|
+
dispatchMenuAction(`auto-start-nag:${count}:${NAG_MAX}`);
|
|
777
|
+
}, 3500);
|
|
778
|
+
}
|
|
779
|
+
function showFirstLaunchDialog() {
|
|
780
|
+
setTimeout(() => {
|
|
781
|
+
electron.dialog.showMessageBox({
|
|
782
|
+
type: "info",
|
|
783
|
+
title: "Start Overdeck automatically?",
|
|
784
|
+
message: "Keep an eye on your agents — even when you forget to open the app.",
|
|
785
|
+
detail: "Overdeck can start automatically when you log in, so you never miss an agent asking for help or a merge that's ready to ship.\n\nYou can change this at any time in Settings → Desktop → Auto-start.",
|
|
786
|
+
buttons: ["Enable Auto-start", "Not Yet"],
|
|
787
|
+
defaultId: 0,
|
|
788
|
+
cancelId: 1
|
|
789
|
+
}).then(({ response }) => {
|
|
790
|
+
if (response === 0) enableAutoStart();
|
|
791
|
+
});
|
|
792
|
+
}, 2e3);
|
|
793
|
+
}
|
|
794
|
+
//#endregion
|
|
795
|
+
//#region src/protocol.ts
|
|
796
|
+
/**
|
|
797
|
+
* overdeck:// custom protocol for serving static frontend assets in packaged builds.
|
|
798
|
+
*
|
|
799
|
+
* In dev mode:
|
|
800
|
+
* BrowserWindow loads from Vite dev server URL (VITE_DEV_SERVER_URL env var).
|
|
801
|
+
* HMR and source maps work normally.
|
|
802
|
+
*
|
|
803
|
+
* In packaged builds:
|
|
804
|
+
* BrowserWindow loads overdeck://app/index.html.
|
|
805
|
+
* This protocol handler serves files from the bundled dist/dashboard/public/.
|
|
806
|
+
* WebSocket connections (ws/rpc, ws/terminal) go to the embedded server port
|
|
807
|
+
* on localhost — the protocol handler only serves static assets.
|
|
808
|
+
*
|
|
809
|
+
* Security:
|
|
810
|
+
* - Path traversal protection: rejects paths containing ".."
|
|
811
|
+
* - Only files within the static root are served
|
|
812
|
+
* - Non-existent asset requests return -6 (net::ERR_FILE_NOT_FOUND)
|
|
813
|
+
* - HTML routes (no extension) fall back to index.html for SPA routing
|
|
814
|
+
*
|
|
815
|
+
* CSP:
|
|
816
|
+
* Renderer CSP is configured via vite.config.ts in the frontend.
|
|
817
|
+
* In packaged mode, connect-src must include ws://127.0.0.1:* for WebSocket.
|
|
818
|
+
*/
|
|
819
|
+
let registered = false;
|
|
820
|
+
function resolveStaticPath(staticRoot, requestUrl) {
|
|
821
|
+
const fallbackIndex = node_path.join(staticRoot, "index.html");
|
|
822
|
+
let url;
|
|
823
|
+
try {
|
|
824
|
+
url = new URL(requestUrl);
|
|
825
|
+
} catch {
|
|
826
|
+
return fallbackIndex;
|
|
827
|
+
}
|
|
828
|
+
const rawPath = decodeURIComponent(url.pathname);
|
|
829
|
+
const normalized = node_path.posix.normalize(rawPath).replace(/^\/+/, "");
|
|
830
|
+
if (normalized.includes("..")) return fallbackIndex;
|
|
831
|
+
const requestedPath = normalized.length > 0 ? normalized : "index.html";
|
|
832
|
+
const resolved = node_path.resolve(staticRoot, requestedPath);
|
|
833
|
+
const staticRootResolved = node_path.resolve(staticRoot);
|
|
834
|
+
if (!(resolved === staticRootResolved || resolved.startsWith(staticRootResolved + node_path.sep))) return fallbackIndex;
|
|
835
|
+
if (node_path.extname(resolved)) return resolved;
|
|
836
|
+
const nestedIndex = node_path.join(resolved, "index.html");
|
|
837
|
+
if (node_fs.existsSync(nestedIndex)) return nestedIndex;
|
|
838
|
+
return fallbackIndex;
|
|
839
|
+
}
|
|
840
|
+
/**
|
|
841
|
+
* Register the overdeck:// protocol handler.
|
|
842
|
+
* Must be called after app.ready (but registration via registerSchemesAsPrivileged
|
|
843
|
+
* must happen before app.ready — done in main.ts).
|
|
844
|
+
*/
|
|
845
|
+
function registerDesktopProtocol() {
|
|
846
|
+
if (registered) return;
|
|
847
|
+
const staticRoot = resolveServerStaticDir();
|
|
848
|
+
if (!staticRoot) {
|
|
849
|
+
console.error("[desktop/protocol] Static bundle not found — packaged frontend assets missing. Run 'npm run build:dashboard' first.");
|
|
850
|
+
return;
|
|
851
|
+
}
|
|
852
|
+
const fallbackIndex = node_path.join(staticRoot, "index.html");
|
|
853
|
+
electron.protocol.registerFileProtocol(DESKTOP_SCHEME, (request, callback) => {
|
|
854
|
+
const candidate = resolveStaticPath(staticRoot, request.url);
|
|
855
|
+
const hasExt = node_path.extname(candidate).length > 0;
|
|
856
|
+
if (!node_fs.existsSync(candidate)) {
|
|
857
|
+
if (hasExt) callback({ error: -6 });
|
|
858
|
+
else callback({ path: fallbackIndex });
|
|
859
|
+
return;
|
|
860
|
+
}
|
|
861
|
+
callback({ path: candidate });
|
|
862
|
+
});
|
|
863
|
+
registered = true;
|
|
864
|
+
console.log(`[desktop/protocol] registered ${DESKTOP_SCHEME}:// serving from ${staticRoot}`);
|
|
865
|
+
}
|
|
866
|
+
//#endregion
|
|
867
|
+
//#region src/main.ts
|
|
868
|
+
const ROOT_DIR = node_path.resolve(__dirname, "../../..");
|
|
869
|
+
const isDevelopment = Boolean(process.env.VITE_DEV_SERVER_URL);
|
|
870
|
+
const APP_DISPLAY_NAME = isDevelopment ? "Overdeck (Dev)" : "Overdeck";
|
|
871
|
+
const APP_ID = "com.overdeck.app";
|
|
872
|
+
const LINUX_WM_CLASS = isDevelopment ? "overdeck-dev" : "overdeck";
|
|
873
|
+
const DESKTOP_SCHEME = "overdeck";
|
|
874
|
+
const IPC = {
|
|
875
|
+
GET_SERVER_URL: "pan:get-server-url",
|
|
876
|
+
GET_WS_URL: "pan:get-ws-url",
|
|
877
|
+
PICK_FOLDER: "pan:pick-folder",
|
|
878
|
+
OPEN_EXTERNAL: "pan:open-external",
|
|
879
|
+
OPEN_TERMINAL_WINDOW: "pan:open-terminal-window",
|
|
880
|
+
SET_ALWAYS_ON_TOP: "pan:set-always-on-top",
|
|
881
|
+
MENU_ACTION: "pan:menu-action",
|
|
882
|
+
GET_DESKTOP_SETTINGS: "pan:get-desktop-settings",
|
|
883
|
+
UPDATE_DESKTOP_SETTING: "pan:update-desktop-setting",
|
|
884
|
+
NOTIFY: "pan:notify",
|
|
885
|
+
GET_UPDATE_STATUS: "pan:get-update-status",
|
|
886
|
+
CHECK_FOR_UPDATES: "pan:check-for-updates",
|
|
887
|
+
DOWNLOAD_UPDATE: "pan:download-update",
|
|
888
|
+
QUIT_AND_INSTALL: "pan:quit-and-install",
|
|
889
|
+
RESTART_DASHBOARD: "pan:restart-dashboard"
|
|
890
|
+
};
|
|
891
|
+
let mainWindow = null;
|
|
892
|
+
let serverPort = 0;
|
|
893
|
+
let serverUrl = "";
|
|
894
|
+
let serverWsUrl = "";
|
|
895
|
+
let isQuitting = false;
|
|
896
|
+
const terminalWindows = /* @__PURE__ */ new Map();
|
|
897
|
+
function resolveResourcePath(fileName) {
|
|
898
|
+
const candidates = [
|
|
899
|
+
node_path.join(process.resourcesPath ?? "", "resources", fileName),
|
|
900
|
+
node_path.join(__dirname, "../resources", fileName),
|
|
901
|
+
node_path.join(ROOT_DIR, "apps/desktop/resources", fileName)
|
|
902
|
+
];
|
|
903
|
+
for (const candidate of candidates) if (node_fs.existsSync(candidate)) return candidate;
|
|
904
|
+
return null;
|
|
905
|
+
}
|
|
906
|
+
function resolveServerEntry() {
|
|
907
|
+
if (electron.app.isPackaged) return node_path.join(process.resourcesPath ?? "", "server/server.js");
|
|
908
|
+
const npxBundle = node_path.join(__dirname, "../server/server.js");
|
|
909
|
+
if (node_fs.existsSync(npxBundle)) return npxBundle;
|
|
910
|
+
return node_path.join(ROOT_DIR, "dist/dashboard/server.js");
|
|
911
|
+
}
|
|
912
|
+
function resolveServerStaticDir() {
|
|
913
|
+
const candidates = [];
|
|
914
|
+
if (electron.app.isPackaged) candidates.push(node_path.join(process.resourcesPath ?? "", "server/public"));
|
|
915
|
+
else {
|
|
916
|
+
candidates.push(node_path.join(__dirname, "../server/public"));
|
|
917
|
+
candidates.push(node_path.join(ROOT_DIR, "dist/dashboard/public"));
|
|
918
|
+
}
|
|
919
|
+
for (const candidate of candidates) if (node_fs.existsSync(node_path.join(candidate, "index.html"))) return candidate;
|
|
920
|
+
return null;
|
|
921
|
+
}
|
|
922
|
+
function resolveWindowUrl() {
|
|
923
|
+
if (isDevelopment) return process.env.VITE_DEV_SERVER_URL;
|
|
924
|
+
return `${DESKTOP_SCHEME}://app/index.html`;
|
|
925
|
+
}
|
|
926
|
+
function createTerminalWindow(sessionName, title) {
|
|
927
|
+
const win = new electron.BrowserWindow({
|
|
928
|
+
width: 900,
|
|
929
|
+
height: 650,
|
|
930
|
+
title,
|
|
931
|
+
webPreferences: {
|
|
932
|
+
preload: node_path.join(__dirname, "preload.js"),
|
|
933
|
+
contextIsolation: true,
|
|
934
|
+
nodeIntegration: false,
|
|
935
|
+
sandbox: false
|
|
936
|
+
},
|
|
937
|
+
show: false
|
|
938
|
+
});
|
|
939
|
+
win.once("ready-to-show", () => win.show());
|
|
940
|
+
win.loadURL(`${resolveWindowUrl()}?terminal=${encodeURIComponent(sessionName)}&title=${encodeURIComponent(title)}`);
|
|
941
|
+
return win;
|
|
942
|
+
}
|
|
943
|
+
function registerIpcHandlers() {
|
|
944
|
+
electron.ipcMain.on(IPC.GET_SERVER_URL, (event) => {
|
|
945
|
+
event.returnValue = serverUrl;
|
|
946
|
+
});
|
|
947
|
+
electron.ipcMain.on(IPC.GET_WS_URL, (event) => {
|
|
948
|
+
event.returnValue = serverWsUrl;
|
|
949
|
+
});
|
|
950
|
+
electron.ipcMain.handle(IPC.PICK_FOLDER, async () => {
|
|
951
|
+
const { dialog } = await import("electron");
|
|
952
|
+
const result = await dialog.showOpenDialog({ properties: ["openDirectory"] });
|
|
953
|
+
return result.canceled ? null : result.filePaths[0] ?? null;
|
|
954
|
+
});
|
|
955
|
+
electron.ipcMain.handle(IPC.OPEN_EXTERNAL, async (_event, url) => {
|
|
956
|
+
if (typeof url !== "string") return;
|
|
957
|
+
let parsed;
|
|
958
|
+
try {
|
|
959
|
+
parsed = new URL(url);
|
|
960
|
+
} catch {
|
|
961
|
+
return;
|
|
962
|
+
}
|
|
963
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") return;
|
|
964
|
+
await electron.shell.openExternal(parsed.toString());
|
|
965
|
+
});
|
|
966
|
+
electron.ipcMain.handle(IPC.GET_DESKTOP_SETTINGS, () => getDesktopSettings());
|
|
967
|
+
electron.ipcMain.on(IPC.OPEN_TERMINAL_WINDOW, (_event, sessionName, title) => {
|
|
968
|
+
if (typeof sessionName !== "string" || typeof title !== "string") return;
|
|
969
|
+
const existing = terminalWindows.get(sessionName);
|
|
970
|
+
if (existing && !existing.isDestroyed()) {
|
|
971
|
+
if (!existing.isVisible()) existing.show();
|
|
972
|
+
existing.focus();
|
|
973
|
+
return;
|
|
974
|
+
}
|
|
975
|
+
const win = createTerminalWindow(sessionName, title);
|
|
976
|
+
terminalWindows.set(sessionName, win);
|
|
977
|
+
win.on("closed", () => terminalWindows.delete(sessionName));
|
|
978
|
+
});
|
|
979
|
+
electron.ipcMain.on(IPC.SET_ALWAYS_ON_TOP, (_event, value) => {
|
|
980
|
+
const focused = electron.BrowserWindow.getFocusedWindow();
|
|
981
|
+
if (focused) focused.setAlwaysOnTop(value === true);
|
|
982
|
+
});
|
|
983
|
+
electron.ipcMain.handle(IPC.UPDATE_DESKTOP_SETTING, (_event, key, value) => {
|
|
984
|
+
if (typeof key !== "string") return;
|
|
985
|
+
if (updateDesktopSetting(key, value) && key === "autoStart.enabled") electron.app.setLoginItemSettings({ openAtLogin: value === true });
|
|
986
|
+
});
|
|
987
|
+
electron.ipcMain.handle(IPC.GET_UPDATE_STATUS, () => getUpdateStatus());
|
|
988
|
+
electron.ipcMain.handle(IPC.CHECK_FOR_UPDATES, async () => {
|
|
989
|
+
try {
|
|
990
|
+
await checkForUpdates();
|
|
991
|
+
} catch (err) {
|
|
992
|
+
console.error("[main] checkForUpdates failed:", err);
|
|
993
|
+
}
|
|
994
|
+
return getUpdateStatus();
|
|
995
|
+
});
|
|
996
|
+
electron.ipcMain.handle(IPC.DOWNLOAD_UPDATE, async () => {
|
|
997
|
+
try {
|
|
998
|
+
await downloadUpdate();
|
|
999
|
+
} catch (err) {
|
|
1000
|
+
console.error("[main] downloadUpdate failed:", err);
|
|
1001
|
+
}
|
|
1002
|
+
return getUpdateStatus();
|
|
1003
|
+
});
|
|
1004
|
+
electron.ipcMain.on(IPC.QUIT_AND_INSTALL, () => {
|
|
1005
|
+
quitAndInstall();
|
|
1006
|
+
});
|
|
1007
|
+
electron.ipcMain.handle(IPC.RESTART_DASHBOARD, async () => {
|
|
1008
|
+
console.log("[main] manual dashboard restart requested");
|
|
1009
|
+
stopServer();
|
|
1010
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
1011
|
+
startServer((port, wsUrl) => {
|
|
1012
|
+
serverPort = port;
|
|
1013
|
+
serverUrl = `http://127.0.0.1:${port}`;
|
|
1014
|
+
serverWsUrl = wsUrl;
|
|
1015
|
+
console.log(`[main] dashboard restarted on ${serverUrl}`);
|
|
1016
|
+
});
|
|
1017
|
+
});
|
|
1018
|
+
}
|
|
1019
|
+
function createWindow() {
|
|
1020
|
+
const win = new electron.BrowserWindow({
|
|
1021
|
+
width: 1400,
|
|
1022
|
+
height: 900,
|
|
1023
|
+
minWidth: 900,
|
|
1024
|
+
minHeight: 600,
|
|
1025
|
+
title: APP_DISPLAY_NAME,
|
|
1026
|
+
webPreferences: {
|
|
1027
|
+
preload: node_path.join(__dirname, "preload.js"),
|
|
1028
|
+
contextIsolation: true,
|
|
1029
|
+
nodeIntegration: false,
|
|
1030
|
+
sandbox: false
|
|
1031
|
+
},
|
|
1032
|
+
show: false
|
|
1033
|
+
});
|
|
1034
|
+
win.once("ready-to-show", () => win.show());
|
|
1035
|
+
win.on("close", (event) => {
|
|
1036
|
+
if (!isQuitting && process.platform === "darwin") {
|
|
1037
|
+
event.preventDefault();
|
|
1038
|
+
win.hide();
|
|
1039
|
+
}
|
|
1040
|
+
});
|
|
1041
|
+
win.loadURL(resolveWindowUrl());
|
|
1042
|
+
return win;
|
|
1043
|
+
}
|
|
1044
|
+
function showOrCreateWindow() {
|
|
1045
|
+
const existing = electron.BrowserWindow.getFocusedWindow() ?? mainWindow ?? electron.BrowserWindow.getAllWindows()[0];
|
|
1046
|
+
if (existing) {
|
|
1047
|
+
if (!existing.isVisible()) existing.show();
|
|
1048
|
+
existing.focus();
|
|
1049
|
+
return;
|
|
1050
|
+
}
|
|
1051
|
+
mainWindow = createWindow();
|
|
1052
|
+
}
|
|
1053
|
+
function dispatchMenuAction(action) {
|
|
1054
|
+
const win = electron.BrowserWindow.getFocusedWindow() ?? mainWindow ?? electron.BrowserWindow.getAllWindows()[0];
|
|
1055
|
+
if (!win) {
|
|
1056
|
+
showOrCreateWindow();
|
|
1057
|
+
setTimeout(() => dispatchMenuAction(action), 500);
|
|
1058
|
+
return;
|
|
1059
|
+
}
|
|
1060
|
+
const send = () => {
|
|
1061
|
+
if (win.isDestroyed()) return;
|
|
1062
|
+
win.webContents.send(IPC.MENU_ACTION, action);
|
|
1063
|
+
if (!win.isVisible()) win.show();
|
|
1064
|
+
win.focus();
|
|
1065
|
+
};
|
|
1066
|
+
if (win.webContents.isLoadingMainFrame()) win.webContents.once("did-finish-load", send);
|
|
1067
|
+
else send();
|
|
1068
|
+
}
|
|
1069
|
+
function callServerApi(path, method) {
|
|
1070
|
+
if (!serverUrl) return;
|
|
1071
|
+
fetch(`${serverUrl}${path}`, { method }).catch((err) => {
|
|
1072
|
+
console.error("[desktop] server API call failed:", err);
|
|
1073
|
+
});
|
|
1074
|
+
}
|
|
1075
|
+
electron.protocol.registerSchemesAsPrivileged([{
|
|
1076
|
+
scheme: DESKTOP_SCHEME,
|
|
1077
|
+
privileges: {
|
|
1078
|
+
standard: true,
|
|
1079
|
+
secure: true,
|
|
1080
|
+
supportFetchAPI: true,
|
|
1081
|
+
corsEnabled: true
|
|
1082
|
+
}
|
|
1083
|
+
}]);
|
|
1084
|
+
if (process.platform === "linux") electron.app.commandLine.appendSwitch("class", LINUX_WM_CLASS);
|
|
1085
|
+
electron.app.on("ready", () => {
|
|
1086
|
+
loadDesktopSettings();
|
|
1087
|
+
registerIpcHandlers();
|
|
1088
|
+
registerNotificationHandlers();
|
|
1089
|
+
initializeNotifications();
|
|
1090
|
+
configureApplicationMenu();
|
|
1091
|
+
registerDesktopProtocol();
|
|
1092
|
+
initializeAutoUpdater(electron.app.getVersion().includes("-canary") ? "beta" : "latest");
|
|
1093
|
+
if (process.platform === "win32") electron.app.setAppUserModelId(APP_ID);
|
|
1094
|
+
if (process.platform === "darwin" && electron.app.dock) {
|
|
1095
|
+
const iconPath = resolveResourcePath("icon.png");
|
|
1096
|
+
if (iconPath) electron.app.dock.setIcon(iconPath);
|
|
1097
|
+
}
|
|
1098
|
+
createTray();
|
|
1099
|
+
startServer((port, wsUrl) => {
|
|
1100
|
+
serverPort = port;
|
|
1101
|
+
serverUrl = `http://127.0.0.1:${port}`;
|
|
1102
|
+
serverWsUrl = wsUrl;
|
|
1103
|
+
mainWindow = createWindow();
|
|
1104
|
+
handleAutoStartNag();
|
|
1105
|
+
});
|
|
1106
|
+
});
|
|
1107
|
+
electron.app.on("window-all-closed", () => {
|
|
1108
|
+
if (process.platform !== "darwin") {
|
|
1109
|
+
isQuitting = true;
|
|
1110
|
+
electron.app.quit();
|
|
1111
|
+
}
|
|
1112
|
+
});
|
|
1113
|
+
electron.app.on("activate", () => showOrCreateWindow());
|
|
1114
|
+
electron.app.on("before-quit", () => {
|
|
1115
|
+
isQuitting = true;
|
|
1116
|
+
destroyTray();
|
|
1117
|
+
stopServer();
|
|
1118
|
+
});
|
|
1119
|
+
//#endregion
|
|
1120
|
+
exports.DESKTOP_SCHEME = DESKTOP_SCHEME;
|
|
1121
|
+
exports.IPC = IPC;
|
|
1122
|
+
exports.callServerApi = callServerApi;
|
|
1123
|
+
exports.createWindow = createWindow;
|
|
1124
|
+
exports.dispatchMenuAction = dispatchMenuAction;
|
|
1125
|
+
Object.defineProperty(exports, "isQuitting", {
|
|
1126
|
+
enumerable: true,
|
|
1127
|
+
get: function() {
|
|
1128
|
+
return isQuitting;
|
|
1129
|
+
}
|
|
1130
|
+
});
|
|
1131
|
+
exports.resolveResourcePath = resolveResourcePath;
|
|
1132
|
+
exports.resolveServerEntry = resolveServerEntry;
|
|
1133
|
+
exports.resolveServerStaticDir = resolveServerStaticDir;
|
|
1134
|
+
exports.resolveWindowUrl = resolveWindowUrl;
|
|
1135
|
+
Object.defineProperty(exports, "serverPort", {
|
|
1136
|
+
enumerable: true,
|
|
1137
|
+
get: function() {
|
|
1138
|
+
return serverPort;
|
|
1139
|
+
}
|
|
1140
|
+
});
|
|
1141
|
+
Object.defineProperty(exports, "serverUrl", {
|
|
1142
|
+
enumerable: true,
|
|
1143
|
+
get: function() {
|
|
1144
|
+
return serverUrl;
|
|
1145
|
+
}
|
|
1146
|
+
});
|
|
1147
|
+
Object.defineProperty(exports, "serverWsUrl", {
|
|
1148
|
+
enumerable: true,
|
|
1149
|
+
get: function() {
|
|
1150
|
+
return serverWsUrl;
|
|
1151
|
+
}
|
|
1152
|
+
});
|
|
1153
|
+
exports.showOrCreateWindow = showOrCreateWindow;
|
|
1154
|
+
|
|
1155
|
+
//# sourceMappingURL=main.js.map
|