feat: remember main window position and size (#44)

* feat: remember window position and size

Signed-off-by: Innei <i@innei.in>

* chore: cleanup

Signed-off-by: Innei <i@innei.in>

---------

Signed-off-by: Innei <i@innei.in>
This commit is contained in:
Innei 2024-06-06 16:57:37 +08:00 committed by GitHub
parent 9deadc61fd
commit 6dba13d751
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 278 additions and 86 deletions

View File

@ -53,6 +53,7 @@
"cmdk": "1.0.0",
"dayjs": "1.11.11",
"dotenv": "16.4.5",
"electron-store": "8.2.0",
"electron-updater": "^6.1.7",
"framer-motion": "11.2.9",
"hast-util-to-jsx-runtime": "2.3.0",

View File

@ -98,6 +98,9 @@ importers:
dotenv:
specifier: 16.4.5
version: 16.4.5
electron-store:
specifier: 8.2.0
version: 8.2.0
electron-updater:
specifier: ^6.1.7
version: 6.1.8
@ -2087,6 +2090,14 @@ packages:
resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==}
engines: {node: '>=8'}
ajv-formats@2.1.1:
resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==}
peerDependencies:
ajv: ^8.0.0
peerDependenciesMeta:
ajv:
optional: true
ajv-keywords@3.5.2:
resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==}
peerDependencies:
@ -2095,6 +2106,9 @@ packages:
ajv@6.12.6:
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
ajv@8.16.0:
resolution: {integrity: sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==}
ansi-escapes@6.2.1:
resolution: {integrity: sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==}
engines: {node: '>=14.16'}
@ -2202,6 +2216,10 @@ packages:
resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==}
engines: {node: '>= 4.0.0'}
atomically@1.7.0:
resolution: {integrity: sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==}
engines: {node: '>=10.12.0'}
bail@2.0.2:
resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==}
@ -2483,6 +2501,10 @@ packages:
concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
conf@10.2.0:
resolution: {integrity: sha512-8fLl9F04EJqjSqH+QjITQfJF8BrOVaYr1jewVgSRAEWePfxT0sku4w2hrGQ60BC/TNLGQ2pgxNlTbWQmMPFvXg==}
engines: {node: '>=12'}
confbox@0.1.7:
resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==}
@ -2570,6 +2592,10 @@ packages:
dayjs@1.11.11:
resolution: {integrity: sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==}
debounce-fn@4.0.0:
resolution: {integrity: sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ==}
engines: {node: '>=10'}
debug@3.2.7:
resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
peerDependencies:
@ -2687,6 +2713,10 @@ packages:
resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
engines: {node: '>=6.0.0'}
dot-prop@6.0.1:
resolution: {integrity: sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==}
engines: {node: '>=10'}
dotenv-expand@11.0.6:
resolution: {integrity: sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==}
engines: {node: '>=12'}
@ -2729,6 +2759,9 @@ packages:
electron-publish@25.0.0-alpha.7:
resolution: {integrity: sha512-d9R6Jnds3PjzBM4Wt3nRn9ramkbM3kBzt9a6WHQL4/09ByyZGZ1Cu9GS9atRCkH3tBJlOIotUYVhVO36lk3sAA==}
electron-store@8.2.0:
resolution: {integrity: sha512-ukLL5Bevdil6oieAOXz3CMy+OgaItMiVBg701MNlG6W5RaC0AHN7rvlqTCmeb6O7jP0Qa1KKYTE0xV0xbhF4Hw==}
electron-to-chromium@1.4.731:
resolution: {integrity: sha512-+TqVfZjpRz2V/5SPpmJxq9qK620SC5SqCnxQIOi7i/U08ZDcTpKbT7Xjj9FU5CbXTMUb4fywbIr8C7cGv4hcjw==}
@ -3075,6 +3108,10 @@ packages:
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
engines: {node: '>=8'}
find-up@3.0.0:
resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==}
engines: {node: '>=6'}
find-up@4.1.0:
resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
engines: {node: '>=8'}
@ -3519,6 +3556,10 @@ packages:
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
engines: {node: '>=0.12.0'}
is-obj@2.0.0:
resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==}
engines: {node: '>=8'}
is-path-inside@3.0.3:
resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
engines: {node: '>=8'}
@ -3653,6 +3694,12 @@ packages:
json-schema-traverse@0.4.1:
resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
json-schema-traverse@1.0.0:
resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==}
json-schema-typed@7.0.3:
resolution: {integrity: sha512-7DE8mpG+/fVw+dTpjbxnx47TaMnDfOI1jwft9g1VybltZCduyRQPJPvc+zzKY9WPHxhPWczyFuYa6I8Mw4iU5A==}
json-stable-stringify-without-jsonify@1.0.1:
resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
@ -3718,6 +3765,10 @@ packages:
resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==}
engines: {node: '>=14'}
locate-path@3.0.0:
resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==}
engines: {node: '>=6'}
locate-path@5.0.0:
resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
engines: {node: '>=8'}
@ -3942,6 +3993,10 @@ packages:
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
engines: {node: '>=6'}
mimic-fn@3.1.0:
resolution: {integrity: sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==}
engines: {node: '>=8'}
mimic-fn@4.0.0:
resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==}
engines: {node: '>=12'}
@ -4156,6 +4211,10 @@ packages:
resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
p-locate@3.0.0:
resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==}
engines: {node: '>=6'}
p-locate@4.1.0:
resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
engines: {node: '>=8'}
@ -4202,6 +4261,10 @@ packages:
parse5@7.1.2:
resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==}
path-exists@3.0.0:
resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==}
engines: {node: '>=4'}
path-exists@4.0.0:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'}
@ -4273,6 +4336,10 @@ packages:
pkg-types@1.1.1:
resolution: {integrity: sha512-ko14TjmDuQJ14zsotODv7dBlwxKhUKQEhuhmbqo1uCi9BB0Z2alo/wAXg6q1dTR5TyuqYyWhjtfe/Tsh+X28jQ==}
pkg-up@3.1.0:
resolution: {integrity: sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==}
engines: {node: '>=8'}
plist@3.1.0:
resolution: {integrity: sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==}
engines: {node: '>=10.4.0'}
@ -4545,6 +4612,10 @@ packages:
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
engines: {node: '>=0.10.0'}
require-from-string@2.0.2:
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
engines: {node: '>=0.10.0'}
resolve-alpn@1.2.1:
resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==}
@ -4944,6 +5015,10 @@ packages:
resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==}
engines: {node: '>=8'}
type-fest@2.19.0:
resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==}
engines: {node: '>=12.20'}
typescript-eslint@8.0.0-alpha.20:
resolution: {integrity: sha512-/cx37A2S+AOne5uFpD8GzHzV5b/7wncAh4agmIRieAZWXJWbRcue7e8RI6LnpQ7CHy9IHPmALcHcXPXogM6jcQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@ -7254,6 +7329,10 @@ snapshots:
clean-stack: 2.2.0
indent-string: 4.0.0
ajv-formats@2.1.1(ajv@8.16.0):
optionalDependencies:
ajv: 8.16.0
ajv-keywords@3.5.2(ajv@6.12.6):
dependencies:
ajv: 6.12.6
@ -7265,6 +7344,13 @@ snapshots:
json-schema-traverse: 0.4.1
uri-js: 4.4.1
ajv@8.16.0:
dependencies:
fast-deep-equal: 3.1.3
json-schema-traverse: 1.0.0
require-from-string: 2.0.2
uri-js: 4.4.1
ansi-escapes@6.2.1: {}
ansi-regex@5.0.1: {}
@ -7429,6 +7515,8 @@ snapshots:
at-least-node@1.0.0: {}
atomically@1.7.0: {}
bail@2.0.2: {}
balanced-match@1.0.2: {}
@ -7763,6 +7851,19 @@ snapshots:
concat-map@0.0.1: {}
conf@10.2.0:
dependencies:
ajv: 8.16.0
ajv-formats: 2.1.1(ajv@8.16.0)
atomically: 1.7.0
debounce-fn: 4.0.0
dot-prop: 6.0.1
env-paths: 2.2.1
json-schema-typed: 7.0.3
onetime: 5.1.2
pkg-up: 3.1.0
semver: 7.6.2
confbox@0.1.7: {}
config-file-ts@0.2.6:
@ -7874,6 +7975,10 @@ snapshots:
dayjs@1.11.11: {}
debounce-fn@4.0.0:
dependencies:
mimic-fn: 3.1.0
debug@3.2.7:
dependencies:
ms: 2.1.3
@ -7989,6 +8094,10 @@ snapshots:
dependencies:
esutils: 2.0.3
dot-prop@6.0.1:
dependencies:
is-obj: 2.0.0
dotenv-expand@11.0.6:
dependencies:
dotenv: 16.4.5
@ -8061,6 +8170,11 @@ snapshots:
transitivePeerDependencies:
- supports-color
electron-store@8.2.0:
dependencies:
conf: 10.2.0
type-fest: 2.19.0
electron-to-chromium@1.4.731: {}
electron-updater@6.1.8:
@ -8618,6 +8732,10 @@ snapshots:
dependencies:
to-regex-range: 5.0.1
find-up@3.0.0:
dependencies:
locate-path: 3.0.0
find-up@4.1.0:
dependencies:
locate-path: 5.0.0
@ -9174,6 +9292,8 @@ snapshots:
is-number@7.0.0: {}
is-obj@2.0.0: {}
is-path-inside@3.0.3: {}
is-plain-obj@2.1.0: {}
@ -9261,6 +9381,10 @@ snapshots:
json-schema-traverse@0.4.1: {}
json-schema-traverse@1.0.0: {}
json-schema-typed@7.0.3: {}
json-stable-stringify-without-jsonify@1.0.1: {}
json-stringify-safe@5.0.1:
@ -9339,6 +9463,11 @@ snapshots:
mlly: 1.7.0
pkg-types: 1.1.1
locate-path@3.0.0:
dependencies:
p-locate: 3.0.0
path-exists: 3.0.0
locate-path@5.0.0:
dependencies:
p-locate: 4.1.0
@ -9693,6 +9822,8 @@ snapshots:
mimic-fn@2.1.0: {}
mimic-fn@3.1.0: {}
mimic-fn@4.0.0: {}
mimic-response@1.0.1: {}
@ -9916,6 +10047,10 @@ snapshots:
dependencies:
yocto-queue: 1.0.0
p-locate@3.0.0:
dependencies:
p-limit: 2.3.0
p-locate@4.1.0:
dependencies:
p-limit: 2.3.0
@ -9970,6 +10105,8 @@ snapshots:
dependencies:
entities: 4.5.0
path-exists@3.0.0: {}
path-exists@4.0.0: {}
path-exists@5.0.0: {}
@ -10018,6 +10155,10 @@ snapshots:
mlly: 1.7.0
pathe: 1.1.2
pkg-up@3.1.0:
dependencies:
find-up: 3.0.0
plist@3.1.0:
dependencies:
'@xmldom/xmldom': 0.8.10
@ -10297,6 +10438,8 @@ snapshots:
require-directory@2.1.1: {}
require-from-string@2.0.2: {}
resolve-alpn@1.2.1: {}
resolve-from@4.0.0: {}
@ -10723,6 +10866,8 @@ snapshots:
type-fest@0.8.1: {}
type-fest@2.19.0: {}
typescript-eslint@8.0.0-alpha.20(eslint@9.3.0)(typescript@5.4.5):
dependencies:
'@typescript-eslint/eslint-plugin': 8.0.0-alpha.20(@typescript-eslint/parser@8.0.0-alpha.20(eslint@9.3.0)(typescript@5.4.5))(eslint@9.3.0)(typescript@5.4.5)

View File

@ -5,11 +5,14 @@ import path from "node:path"
import { registerIpcMain } from "@egoist/tipc/main"
import { electronApp, optimizer } from "@electron-toolkit/utils"
import { extractElectronWindowOptions } from "@shared/electron"
import { app, BrowserWindow, Menu } from "electron"
import { app, BrowserWindow } from "electron"
import { registerAppMenu } from "./menu"
import { router } from "./tipc"
import { createWindow } from "./window"
import { createMainWindow, createWindow } from "./window"
let mainWindow: BrowserWindow
export const getMainWindow = () => mainWindow
registerIpcMain(router)
if (process.defaultApp) {
@ -24,10 +27,6 @@ if (process.defaultApp) {
app.dock.setIcon(path.join(__dirname, "../../resources/icon.png"))
let mainWindow: BrowserWindow
export const getMainWindow = () => mainWindow
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
@ -42,13 +41,13 @@ app.whenReady().then(() => {
optimizer.watchWindowShortcuts(window)
})
mainWindow = createWindow()
mainWindow = createMainWindow()
app.on("activate", () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) {
mainWindow = createWindow()
mainWindow = createMainWindow()
}
})
@ -69,15 +68,14 @@ app.whenReady().then(() => {
mainWindow.reload()
}
} else {
console.log("open-url", url)
const options = extractElectronWindowOptions(url)
const { height, resizeable, width } = options || {}
const { height, resizable, width } = options || {}
createWindow({
extraPath: url.replace("follow:/", ""),
width: width ?? 800,
height: height ?? 600,
resizeable,
resizable,
})
}
}
@ -112,67 +110,4 @@ app.on("window-all-closed", () => {
// In this file you can include the rest of your app"s specific main process
// code. You can also put them in separate files and require them here.
Menu.setApplicationMenu(
Menu.buildFromTemplate([
{
role: "appMenu",
submenu: [
{ role: "about" },
{ type: "separator" },
{
label: "Settings...",
accelerator: "CmdOrCtrl+,",
click: () => {
createWindow({
extraPath: "/settings",
width: 800,
height: 600,
})
},
},
{ type: "separator" },
{ role: "services" },
{ type: "separator" },
{ role: "hide" },
{ role: "hideOthers" },
{ type: "separator" },
{ role: "quit" },
],
},
{ role: "fileMenu" },
{ role: "editMenu" },
{ role: "viewMenu" },
{ role: "windowMenu" },
{ role: "help" },
{
label: "Dev",
submenu: [
{
label: "follow https://rsshub.app/twitter/user/DIYgod",
click: () => {
createWindow({
extraPath: `/add?url=${encodeURIComponent(
"https://rsshub.app/twitter/user/DIYgod",
)}`,
width: 800,
height: 600,
})
},
},
{
label: "follow https://diygod.me/feed",
click: () => {
createWindow({
extraPath: `/add?url=${encodeURIComponent(
"https://diygod.me/feed",
)}`,
width: 800,
height: 600,
})
},
},
],
},
]),
)
registerAppMenu()

72
src/main/menu.ts Normal file
View File

@ -0,0 +1,72 @@
import type { MenuItem, MenuItemConstructorOptions } from "electron"
import { Menu } from "electron"
import { createWindow } from "./window"
export const registerAppMenu = () => {
const menus: Array<MenuItemConstructorOptions | MenuItem> = [
{
role: "appMenu",
submenu: [
{ role: "about" },
{ type: "separator" },
{
label: "Settings...",
accelerator: "CmdOrCtrl+,",
click: () => {
createWindow({
extraPath: "/settings",
width: 800,
height: 600,
})
},
},
{ type: "separator" },
{ role: "services" },
{ type: "separator" },
{ role: "hide" },
{ role: "hideOthers" },
{ type: "separator" },
{ role: "quit" },
],
},
{ role: "fileMenu" },
{ role: "editMenu" },
{ role: "viewMenu" },
{ role: "windowMenu" },
{ role: "help" },
]
if (import.meta.env.DEV) {
menus.push({
label: "Dev",
submenu: [
{
label: "follow https://rsshub.app/twitter/user/DIYgod",
click: () => {
createWindow({
extraPath: `/add?url=${encodeURIComponent(
"https://rsshub.app/twitter/user/DIYgod",
)}`,
width: 800,
height: 600,
})
},
},
{
label: "follow https://diygod.me/feed",
click: () => {
createWindow({
extraPath: `/add?url=${encodeURIComponent(
"https://diygod.me/feed",
)}`,
width: 800,
height: 600,
})
},
},
],
})
}
Menu.setApplicationMenu(Menu.buildFromTemplate(menus))
}

3
src/main/store.ts Normal file
View File

@ -0,0 +1,3 @@
import Store from "electron-store"
export const store = new Store()

View File

@ -1,22 +1,26 @@
import path from "node:path"
import { is } from "@electron-toolkit/utils"
import type { BrowserWindowConstructorOptions } from "electron"
import { BrowserWindow, shell } from "electron"
import icon from "../../resources/icon.png?asset"
import { store } from "./store"
export function createWindow(options?: {
extraPath?: string
width?: number
height?: number
resizeable?: boolean
}) {
export function createWindow(
options: {
extraPath?: string
height: number
width: number
} & BrowserWindowConstructorOptions,
) {
const { extraPath, height, width, ...configs } = options
// Create the browser window.
const window = new BrowserWindow({
width: options?.width || 1200,
height: options?.height || 900,
width,
height,
show: false,
resizable: options?.resizeable ?? true,
resizable: configs?.resizable ?? true,
autoHideMenuBar: true,
...(process.platform === "linux" ? { icon } : {}),
webPreferences: {
@ -34,6 +38,7 @@ export function createWindow(options?: {
backgroundColor: "#00000000", // transparent hexadecimal or anything with transparency,
vibrancy: "sidebar",
visualEffectState: "active",
...configs,
})
window.on("ready-to-show", () => {
@ -91,3 +96,34 @@ export function createWindow(options?: {
return window
}
export const createMainWindow = () => {
const storeKey = "windowState"
const windowState = store.get(storeKey) as {
height: number
width: number
x: number
y: number
} | null
const window = createWindow({
width: windowState?.width || 1200,
height: windowState?.height || 900,
x: windowState?.x,
y: windowState?.y,
minWidth: 1024,
minHeight: 500,
})
window.on("close", () => {
const bounds = window.getBounds()
store.set(storeKey, {
width: bounds.width,
height: bounds.height,
x: bounds.x,
y: bounds.y,
})
})
return window
}

View File

@ -195,7 +195,7 @@ export function DiscoverForm({ type }: { type: string }) {
`?url=${item.feed.url}`
}`,
{
resizeable: false,
resizable: false,
height: 550,
},
)

View File

@ -2,7 +2,7 @@ import { DEEPLINK_SCHEME } from "@shared/constants"
const ELECTRON_QUERY_KEY = "__electron"
export interface OpenElectronWindowOptions {
resizeable?: boolean
resizable?: boolean
height?: number
width?: number
}