5 Commits

Author SHA1 Message Date
6e49516962 Merge branch 'master' into dev
# Conflicts:
#	frontend/package-lock.json
2026-01-03 23:22:50 +08:00
b6c325198d 🎨 Removed support for Gitea and optimized update timeouts 2026-01-03 23:19:43 +08:00
532d30aa93 Added code collapse state persistence 2026-01-03 23:06:08 +08:00
0b91447b05 Merge pull request #21 from landaiqing/dependabot/npm_and_yarn/frontend/npm_and_yarn-2b901f0e0d
⬆️ Bump qs from 6.14.0 to 6.14.1 in /frontend in the npm_and_yarn group across 1 directory
2026-01-03 00:33:48 +08:00
dependabot[bot]
aa5ce2b038 ⬆️ Bump qs
Bumps the npm_and_yarn group with 1 update in the /frontend directory: [qs](https://github.com/ljharb/qs).


Updates `qs` from 6.14.0 to 6.14.1
- [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ljharb/qs/compare/v6.14.0...v6.14.1)

---
updated-dependencies:
- dependency-name: qs
  dependency-version: 6.14.1
  dependency-type: indirect
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-01-01 20:12:07 +00:00
13 changed files with 339 additions and 382 deletions

View File

@@ -564,49 +564,6 @@ export class GitBackupConfig {
} }
} }
/**
* GiteaConfig Gitea配置
*/
export class GiteaConfig {
/**
* Gitea服务器URL
*/
"baseURL": string;
/**
* 仓库所有者
*/
"owner": string;
/**
* 仓库名称
*/
"repo": string;
/** Creates a new GiteaConfig instance. */
constructor($$source: Partial<GiteaConfig> = {}) {
if (!("baseURL" in $$source)) {
this["baseURL"] = "";
}
if (!("owner" in $$source)) {
this["owner"] = "";
}
if (!("repo" in $$source)) {
this["repo"] = "";
}
Object.assign(this, $$source);
}
/**
* Creates a new GiteaConfig instance from a string or object.
*/
static createFrom($$source: any = {}): GiteaConfig {
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
return new GiteaConfig($$parsedSource as Partial<GiteaConfig>);
}
}
/** /**
* GithubConfig GitHub配置 * GithubConfig GitHub配置
*/ */
@@ -1272,26 +1229,6 @@ export enum TabType {
TabTypeTab = "tab", TabTypeTab = "tab",
}; };
/**
* UpdateSourceType 更新源类型
*/
export enum UpdateSourceType {
/**
* The Go zero value for the underlying type of the enum.
*/
$zero = "",
/**
* UpdateSourceGithub GitHub更新源
*/
UpdateSourceGithub = "github",
/**
* UpdateSourceGitea Gitea更新源
*/
UpdateSourceGitea = "gitea",
};
/** /**
* UpdatesConfig 更新设置配置 * UpdatesConfig 更新设置配置
*/ */
@@ -1306,16 +1243,6 @@ export class UpdatesConfig {
*/ */
"autoUpdate": boolean; "autoUpdate": boolean;
/**
* 主要更新源
*/
"primarySource": UpdateSourceType;
/**
* 备用更新源
*/
"backupSource": UpdateSourceType;
/** /**
* 更新前是否备份 * 更新前是否备份
*/ */
@@ -1331,11 +1258,6 @@ export class UpdatesConfig {
*/ */
"github": GithubConfig; "github": GithubConfig;
/**
* Gitea配置
*/
"gitea": GiteaConfig;
/** Creates a new UpdatesConfig instance. */ /** Creates a new UpdatesConfig instance. */
constructor($$source: Partial<UpdatesConfig> = {}) { constructor($$source: Partial<UpdatesConfig> = {}) {
if (!("version" in $$source)) { if (!("version" in $$source)) {
@@ -1344,12 +1266,6 @@ export class UpdatesConfig {
if (!("autoUpdate" in $$source)) { if (!("autoUpdate" in $$source)) {
this["autoUpdate"] = false; this["autoUpdate"] = false;
} }
if (!("primarySource" in $$source)) {
this["primarySource"] = ("" as UpdateSourceType);
}
if (!("backupSource" in $$source)) {
this["backupSource"] = ("" as UpdateSourceType);
}
if (!("backupBeforeUpdate" in $$source)) { if (!("backupBeforeUpdate" in $$source)) {
this["backupBeforeUpdate"] = false; this["backupBeforeUpdate"] = false;
} }
@@ -1359,9 +1275,6 @@ export class UpdatesConfig {
if (!("github" in $$source)) { if (!("github" in $$source)) {
this["github"] = (new GithubConfig()); this["github"] = (new GithubConfig());
} }
if (!("gitea" in $$source)) {
this["gitea"] = (new GiteaConfig());
}
Object.assign(this, $$source); Object.assign(this, $$source);
} }
@@ -1370,14 +1283,10 @@ export class UpdatesConfig {
* Creates a new UpdatesConfig instance from a string or object. * Creates a new UpdatesConfig instance from a string or object.
*/ */
static createFrom($$source: any = {}): UpdatesConfig { static createFrom($$source: any = {}): UpdatesConfig {
const $$createField6_0 = $$createType9; const $$createField4_0 = $$createType9;
const $$createField7_0 = $$createType10;
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
if ("github" in $$parsedSource) { if ("github" in $$parsedSource) {
$$parsedSource["github"] = $$createField6_0($$parsedSource["github"]); $$parsedSource["github"] = $$createField4_0($$parsedSource["github"]);
}
if ("gitea" in $$parsedSource) {
$$parsedSource["gitea"] = $$createField7_0($$parsedSource["gitea"]);
} }
return new UpdatesConfig($$parsedSource as Partial<UpdatesConfig>); return new UpdatesConfig($$parsedSource as Partial<UpdatesConfig>);
} }
@@ -1399,4 +1308,3 @@ var $$createType6 = (function $$initCreateType6(...args): any {
const $$createType7 = $Create.Map($Create.Any, $Create.Any); const $$createType7 = $Create.Map($Create.Any, $Create.Any);
const $$createType8 = HotkeyCombo.createFrom; const $$createType8 = HotkeyCombo.createFrom;
const $$createType9 = GithubConfig.createFrom; const $$createType9 = GithubConfig.createFrom;
const $$createType10 = GiteaConfig.createFrom;

View File

@@ -285,7 +285,7 @@ export class SelfUpdateResult {
"error": string; "error": string;
/** /**
* 更新源github/gitea * 更新源github
*/ */
"source": string; "source": string;

View File

@@ -42,8 +42,8 @@
"@lezer/lr": "^1.4.5", "@lezer/lr": "^1.4.5",
"@prettier/plugin-xml": "^3.4.2", "@prettier/plugin-xml": "^3.4.2",
"@replit/codemirror-lang-svelte": "^6.0.0", "@replit/codemirror-lang-svelte": "^6.0.0",
"@toml-tools/lexer": "^1.0.0", "@toml-tools/lexer": "^1.0.1",
"@toml-tools/parser": "^1.0.0", "@toml-tools/parser": "^1.0.1",
"@types/katex": "^0.16.7", "@types/katex": "^0.16.7",
"@zumer/snapdom": "^2.0.1", "@zumer/snapdom": "^2.0.1",
"codemirror": "^6.0.2", "codemirror": "^6.0.2",
@@ -78,7 +78,7 @@
"eslint-plugin-vue": "^10.6.2", "eslint-plugin-vue": "^10.6.2",
"globals": "^16.5.0", "globals": "^16.5.0",
"typescript": "^5.9.3", "typescript": "^5.9.3",
"typescript-eslint": "^8.51.0", "typescript-eslint": "^8.50.1",
"unplugin-vue-components": "^30.0.0", "unplugin-vue-components": "^30.0.0",
"vite": "npm:rolldown-vite@latest", "vite": "npm:rolldown-vite@latest",
"vite-plugin-node-polyfills": "^0.24.0", "vite-plugin-node-polyfills": "^0.24.0",
@@ -142,6 +142,7 @@
"resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.28.5.tgz", "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.28.5.tgz",
"integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@babel/types": "^7.28.5" "@babel/types": "^7.28.5"
}, },
@@ -609,9 +610,9 @@
} }
}, },
"node_modules/@codemirror/view": { "node_modules/@codemirror/view": {
"version": "6.39.8", "version": "6.39.6",
"resolved": "https://registry.npmmirror.com/@codemirror/view/-/view-6.39.8.tgz", "resolved": "https://registry.npmmirror.com/@codemirror/view/-/view-6.39.6.tgz",
"integrity": "sha512-1rASYd9Z/mE3tkbC9wInRlCNyCkSn+nLsiQKZhEDUUJiUfs/5FHDpCUDaQpoTIaNGeDc6/bhaEAyLmeEucEFPw==", "integrity": "sha512-/N+SoP5NndJjkGInp3BwlUa3KQKD6bDo0TV6ep37ueAdQ7BVu/PqlZNywmgjCq0MQoZadZd8T+MZucSr7fktyQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@codemirror/state": "^6.5.0", "@codemirror/state": "^6.5.0",
@@ -1340,13 +1341,13 @@
} }
}, },
"node_modules/@intlify/core-base": { "node_modules/@intlify/core-base": {
"version": "11.2.8", "version": "11.2.7",
"resolved": "https://registry.npmmirror.com/@intlify/core-base/-/core-base-11.2.8.tgz", "resolved": "https://registry.npmmirror.com/@intlify/core-base/-/core-base-11.2.7.tgz",
"integrity": "sha512-nBq6Y1tVkjIUsLsdOjDSJj4AsjvD0UG3zsg9Fyc+OivwlA/oMHSKooUy9tpKj0HqZ+NWFifweHavdljlBLTwdA==", "integrity": "sha512-+Ra9I/LAzXDnmv/IrTO03WMCiLya7pHRmGJvNl9fKwx/W4REJ0xaMk2PxCRqnxcBsX443amEMdebQ3R1geiuIw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@intlify/message-compiler": "11.2.8", "@intlify/message-compiler": "11.2.7",
"@intlify/shared": "11.2.8" "@intlify/shared": "11.2.7"
}, },
"engines": { "engines": {
"node": ">= 16" "node": ">= 16"
@@ -1356,12 +1357,12 @@
} }
}, },
"node_modules/@intlify/message-compiler": { "node_modules/@intlify/message-compiler": {
"version": "11.2.8", "version": "11.2.7",
"resolved": "https://registry.npmmirror.com/@intlify/message-compiler/-/message-compiler-11.2.8.tgz", "resolved": "https://registry.npmmirror.com/@intlify/message-compiler/-/message-compiler-11.2.7.tgz",
"integrity": "sha512-A5n33doOjmHsBtCN421386cG1tWp5rpOjOYPNsnpjIJbQ4POF0QY2ezhZR9kr0boKwaHjbOifvyQvHj2UTrDFQ==", "integrity": "sha512-TFamC+GzJAotAFwUNvbtRVBgvuSn2nCwKNresmPUHv3IIVMmXJt7QQJj/DORI1h8hs46ZF6L0Fs2xBohSOE4iQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@intlify/shared": "11.2.8", "@intlify/shared": "11.2.7",
"source-map-js": "^1.0.2" "source-map-js": "^1.0.2"
}, },
"engines": { "engines": {
@@ -1372,9 +1373,9 @@
} }
}, },
"node_modules/@intlify/shared": { "node_modules/@intlify/shared": {
"version": "11.2.8", "version": "11.2.7",
"resolved": "https://registry.npmmirror.com/@intlify/shared/-/shared-11.2.8.tgz", "resolved": "https://registry.npmmirror.com/@intlify/shared/-/shared-11.2.7.tgz",
"integrity": "sha512-l6e4NZyUgv8VyXXH4DbuucFOBmxLF56C/mqh2tvApbzl2Hrhi1aTDcuv5TKdxzfHYmpO3UB0Cz04fgDT9vszfw==", "integrity": "sha512-uvlkvc/0uQ4FDlHQZccpUnmcOwNcaI3i+69ck2YJ+GqM35AoVbuS63b+YfirV4G0SZh64Ij2UMcFRMmB4nr95w==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 16" "node": ">= 16"
@@ -2864,25 +2865,23 @@
"resolved": "https://registry.npmmirror.com/@types/whatwg-mimetype/-/whatwg-mimetype-3.0.2.tgz", "resolved": "https://registry.npmmirror.com/@types/whatwg-mimetype/-/whatwg-mimetype-3.0.2.tgz",
"integrity": "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==", "integrity": "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT"
"optional": true,
"peer": true
}, },
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.51.0", "version": "8.50.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.51.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.50.1.tgz",
"integrity": "sha512-XtssGWJvypyM2ytBnSnKtHYOGT+4ZwTnBVl36TA4nRO2f4PRNGz5/1OszHzcZCvcBMh+qb7I06uoCmLTRdR9og==", "integrity": "sha512-PKhLGDq3JAg0Jk/aK890knnqduuI/Qj+udH7wCf0217IGi4gt+acgCyPVe79qoT+qKUvHMDQkwJeKW9fwl8Cyw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/regexpp": "^4.10.0", "@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "8.51.0", "@typescript-eslint/scope-manager": "8.50.1",
"@typescript-eslint/type-utils": "8.51.0", "@typescript-eslint/type-utils": "8.50.1",
"@typescript-eslint/utils": "8.51.0", "@typescript-eslint/utils": "8.50.1",
"@typescript-eslint/visitor-keys": "8.51.0", "@typescript-eslint/visitor-keys": "8.50.1",
"ignore": "^7.0.0", "ignore": "^7.0.0",
"natural-compare": "^1.4.0", "natural-compare": "^1.4.0",
"ts-api-utils": "^2.2.0" "ts-api-utils": "^2.1.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2892,7 +2891,7 @@
"url": "https://opencollective.com/typescript-eslint" "url": "https://opencollective.com/typescript-eslint"
}, },
"peerDependencies": { "peerDependencies": {
"@typescript-eslint/parser": "^8.51.0", "@typescript-eslint/parser": "^8.50.1",
"eslint": "^8.57.0 || ^9.0.0", "eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <6.0.0" "typescript": ">=4.8.4 <6.0.0"
} }
@@ -2908,16 +2907,16 @@
} }
}, },
"node_modules/@typescript-eslint/parser": { "node_modules/@typescript-eslint/parser": {
"version": "8.51.0", "version": "8.50.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.51.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-8.50.1.tgz",
"integrity": "sha512-3xP4XzzDNQOIqBMWogftkwxhg5oMKApqY0BAflmLZiFYHqyhSOxv/cd/zPQLTcCXr4AkaKb25joocY0BD1WC6A==", "integrity": "sha512-hM5faZwg7aVNa819m/5r7D0h0c9yC4DUlWAOvHAtISdFTc8xB86VmX5Xqabrama3wIPJ/q9RbGS1worb6JfnMg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "8.51.0", "@typescript-eslint/scope-manager": "8.50.1",
"@typescript-eslint/types": "8.51.0", "@typescript-eslint/types": "8.50.1",
"@typescript-eslint/typescript-estree": "8.51.0", "@typescript-eslint/typescript-estree": "8.50.1",
"@typescript-eslint/visitor-keys": "8.51.0", "@typescript-eslint/visitor-keys": "8.50.1",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"engines": { "engines": {
@@ -2933,14 +2932,14 @@
} }
}, },
"node_modules/@typescript-eslint/project-service": { "node_modules/@typescript-eslint/project-service": {
"version": "8.51.0", "version": "8.50.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/project-service/-/project-service-8.51.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/project-service/-/project-service-8.50.1.tgz",
"integrity": "sha512-Luv/GafO07Z7HpiI7qeEW5NW8HUtZI/fo/kE0YbtQEFpJRUuR0ajcWfCE5bnMvL7QQFrmT/odMe8QZww8X2nfQ==", "integrity": "sha512-E1ur1MCVf+YiP89+o4Les/oBAVzmSbeRB0MQLfSlYtbWU17HPxZ6Bhs5iYmKZRALvEuBoXIZMOIRRc/P++Ortg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/tsconfig-utils": "^8.51.0", "@typescript-eslint/tsconfig-utils": "^8.50.1",
"@typescript-eslint/types": "^8.51.0", "@typescript-eslint/types": "^8.50.1",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"engines": { "engines": {
@@ -2955,14 +2954,14 @@
} }
}, },
"node_modules/@typescript-eslint/scope-manager": { "node_modules/@typescript-eslint/scope-manager": {
"version": "8.51.0", "version": "8.50.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.51.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-8.50.1.tgz",
"integrity": "sha512-JhhJDVwsSx4hiOEQPeajGhCWgBMBwVkxC/Pet53EpBVs7zHHtayKefw1jtPaNRXpI9RA2uocdmpdfE7T+NrizA==", "integrity": "sha512-mfRx06Myt3T4vuoHaKi8ZWNTPdzKPNBhiblze5N50//TSHOAQQevl/aolqA/BcqqbJ88GUnLqjjcBc8EWdBcVw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.51.0", "@typescript-eslint/types": "8.50.1",
"@typescript-eslint/visitor-keys": "8.51.0" "@typescript-eslint/visitor-keys": "8.50.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2973,9 +2972,9 @@
} }
}, },
"node_modules/@typescript-eslint/tsconfig-utils": { "node_modules/@typescript-eslint/tsconfig-utils": {
"version": "8.51.0", "version": "8.50.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.51.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.50.1.tgz",
"integrity": "sha512-Qi5bSy/vuHeWyir2C8u/uqGMIlIDu8fuiYWv48ZGlZ/k+PRPHtaAu7erpc7p5bzw2WNNSniuxoMSO4Ar6V9OXw==", "integrity": "sha512-ooHmotT/lCWLXi55G4mvaUF60aJa012QzvLK0Y+Mp4WdSt17QhMhWOaBWeGTFVkb2gDgBe19Cxy1elPXylslDw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -2990,17 +2989,17 @@
} }
}, },
"node_modules/@typescript-eslint/type-utils": { "node_modules/@typescript-eslint/type-utils": {
"version": "8.51.0", "version": "8.50.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.51.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-8.50.1.tgz",
"integrity": "sha512-0XVtYzxnobc9K0VU7wRWg1yiUrw4oQzexCG2V2IDxxCxhqBMSMbjB+6o91A+Uc0GWtgjCa3Y8bi7hwI0Tu4n5Q==", "integrity": "sha512-7J3bf022QZE42tYMO6SL+6lTPKFk/WphhRPe9Tw/el+cEwzLz1Jjz2PX3GtGQVxooLDKeMVmMt7fWpYRdG5Etg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.51.0", "@typescript-eslint/types": "8.50.1",
"@typescript-eslint/typescript-estree": "8.51.0", "@typescript-eslint/typescript-estree": "8.50.1",
"@typescript-eslint/utils": "8.51.0", "@typescript-eslint/utils": "8.50.1",
"debug": "^4.3.4", "debug": "^4.3.4",
"ts-api-utils": "^2.2.0" "ts-api-utils": "^2.1.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -3015,9 +3014,9 @@
} }
}, },
"node_modules/@typescript-eslint/types": { "node_modules/@typescript-eslint/types": {
"version": "8.51.0", "version": "8.50.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.51.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/types/-/types-8.50.1.tgz",
"integrity": "sha512-TizAvWYFM6sSscmEakjY3sPqGwxZRSywSsPEiuZF6d5GmGD9Gvlsv0f6N8FvAAA0CD06l3rIcWNbsN1e5F/9Ag==", "integrity": "sha512-v5lFIS2feTkNyMhd7AucE/9j/4V9v5iIbpVRncjk/K0sQ6Sb+Np9fgYS/63n6nwqahHQvbmujeBL7mp07Q9mlA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -3029,21 +3028,21 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree": { "node_modules/@typescript-eslint/typescript-estree": {
"version": "8.51.0", "version": "8.50.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.51.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.50.1.tgz",
"integrity": "sha512-1qNjGqFRmlq0VW5iVlcyHBbCjPB7y6SxpBkrbhNWMy/65ZoncXCEPJxkRZL8McrseNH6lFhaxCIaX+vBuFnRng==", "integrity": "sha512-woHPdW+0gj53aM+cxchymJCrh0cyS7BTIdcDxWUNsclr9VDkOSbqC13juHzxOmQ22dDkMZEpZB+3X1WpUvzgVQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/project-service": "8.51.0", "@typescript-eslint/project-service": "8.50.1",
"@typescript-eslint/tsconfig-utils": "8.51.0", "@typescript-eslint/tsconfig-utils": "8.50.1",
"@typescript-eslint/types": "8.51.0", "@typescript-eslint/types": "8.50.1",
"@typescript-eslint/visitor-keys": "8.51.0", "@typescript-eslint/visitor-keys": "8.50.1",
"debug": "^4.3.4", "debug": "^4.3.4",
"minimatch": "^9.0.4", "minimatch": "^9.0.4",
"semver": "^7.6.0", "semver": "^7.6.0",
"tinyglobby": "^0.2.15", "tinyglobby": "^0.2.15",
"ts-api-utils": "^2.2.0" "ts-api-utils": "^2.1.0"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -3083,16 +3082,16 @@
} }
}, },
"node_modules/@typescript-eslint/utils": { "node_modules/@typescript-eslint/utils": {
"version": "8.51.0", "version": "8.50.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.51.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-8.50.1.tgz",
"integrity": "sha512-11rZYxSe0zabiKaCP2QAwRf/dnmgFgvTmeDTtZvUvXG3UuAdg/GU02NExmmIXzz3vLGgMdtrIosI84jITQOxUA==", "integrity": "sha512-lCLp8H1T9T7gPbEuJSnHwnSuO9mDf8mfK/Nion5mZmiEaQD9sWf9W4dfeFqRyqRjF06/kBuTmAqcs9sewM2NbQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.7.0", "@eslint-community/eslint-utils": "^4.7.0",
"@typescript-eslint/scope-manager": "8.51.0", "@typescript-eslint/scope-manager": "8.50.1",
"@typescript-eslint/types": "8.51.0", "@typescript-eslint/types": "8.50.1",
"@typescript-eslint/typescript-estree": "8.51.0" "@typescript-eslint/typescript-estree": "8.50.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -3107,13 +3106,13 @@
} }
}, },
"node_modules/@typescript-eslint/visitor-keys": { "node_modules/@typescript-eslint/visitor-keys": {
"version": "8.51.0", "version": "8.50.1",
"resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.51.0.tgz", "resolved": "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.50.1.tgz",
"integrity": "sha512-mM/JRQOzhVN1ykejrvwnBRV3+7yTKK8tVANVN3o1O0t0v7o+jqdVu9crPy5Y9dov15TJk/FTIgoUGHrTOVL3Zg==", "integrity": "sha512-IrDKrw7pCRUR94zeuCSUWQ+w8JEf5ZX5jl/e6AHGSLi1/zIr0lgutfn/7JpfCey+urpgQEdrZVYzCaVVKiTwhQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.51.0", "@typescript-eslint/types": "8.50.1",
"eslint-visitor-keys": "^4.2.1" "eslint-visitor-keys": "^4.2.1"
}, },
"engines": { "engines": {
@@ -5734,8 +5733,6 @@
"integrity": "sha512-QsCdAUHAmiDeKeaNojb1OHOPF7NjcWPBR7obdu3NwH2a/oyQaLg5d0aaCy/9My6CdPChYF07dvz5chaXBGaD4g==", "integrity": "sha512-QsCdAUHAmiDeKeaNojb1OHOPF7NjcWPBR7obdu3NwH2a/oyQaLg5d0aaCy/9My6CdPChYF07dvz5chaXBGaD4g==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"optional": true,
"peer": true,
"dependencies": { "dependencies": {
"@types/node": "^20.0.0", "@types/node": "^20.0.0",
"@types/whatwg-mimetype": "^3.0.2", "@types/whatwg-mimetype": "^3.0.2",
@@ -5751,8 +5748,6 @@
"integrity": "sha512-ZsJzA5thDQMSQO788d7IocwwQbI8B5OPzmqNvpf3NY/+MHDAS759Wo0gd2WQeXYt5AAAQjzcrTVC6SKCuYgoCQ==", "integrity": "sha512-ZsJzA5thDQMSQO788d7IocwwQbI8B5OPzmqNvpf3NY/+MHDAS759Wo0gd2WQeXYt5AAAQjzcrTVC6SKCuYgoCQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"optional": true,
"peer": true,
"dependencies": { "dependencies": {
"undici-types": "~6.21.0" "undici-types": "~6.21.0"
} }
@@ -5762,9 +5757,7 @@
"resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz", "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT"
"optional": true,
"peer": true
}, },
"node_modules/has-flag": { "node_modules/has-flag": {
"version": "4.0.0", "version": "4.0.0",
@@ -8167,9 +8160,9 @@
} }
}, },
"node_modules/ts-api-utils": { "node_modules/ts-api-utils": {
"version": "2.3.0", "version": "2.1.0",
"resolved": "https://registry.npmmirror.com/ts-api-utils/-/ts-api-utils-2.3.0.tgz", "resolved": "https://registry.npmmirror.com/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
"integrity": "sha512-6eg3Y9SF7SsAvGzRHQvvc1skDAhwI4YQ32ui1scxD1Ccr0G5qIIbUBT3pFTKX8kmWIQClHobtUdNuaBgwdfdWg==", "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@@ -8238,16 +8231,16 @@
} }
}, },
"node_modules/typescript-eslint": { "node_modules/typescript-eslint": {
"version": "8.51.0", "version": "8.50.1",
"resolved": "https://registry.npmmirror.com/typescript-eslint/-/typescript-eslint-8.51.0.tgz", "resolved": "https://registry.npmmirror.com/typescript-eslint/-/typescript-eslint-8.50.1.tgz",
"integrity": "sha512-jh8ZuM5oEh2PSdyQG9YAEM1TCGuWenLSuSUhf/irbVUNW9O5FhbFVONviN2TgMTBnUmyHv7E56rYnfLZK6TkiA==", "integrity": "sha512-ytTHO+SoYSbhAH9CrYnMhiLx8To6PSSvqnvXyPUgPETCvB6eBKmTI9w6XMPS3HsBRGkwTVBX+urA8dYQx6bHfQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/eslint-plugin": "8.51.0", "@typescript-eslint/eslint-plugin": "8.50.1",
"@typescript-eslint/parser": "8.51.0", "@typescript-eslint/parser": "8.50.1",
"@typescript-eslint/typescript-estree": "8.51.0", "@typescript-eslint/typescript-estree": "8.50.1",
"@typescript-eslint/utils": "8.51.0" "@typescript-eslint/utils": "8.50.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -8953,13 +8946,13 @@
} }
}, },
"node_modules/vue-i18n": { "node_modules/vue-i18n": {
"version": "11.2.8", "version": "11.2.7",
"resolved": "https://registry.npmmirror.com/vue-i18n/-/vue-i18n-11.2.8.tgz", "resolved": "https://registry.npmmirror.com/vue-i18n/-/vue-i18n-11.2.7.tgz",
"integrity": "sha512-vJ123v/PXCZntd6Qj5Jumy7UBmIuE92VrtdX+AXr+1WzdBHojiBxnAxdfctUFL+/JIN+VQH4BhsfTtiGsvVObg==", "integrity": "sha512-LPv8bAY5OA0UvFEXl4vBQOBqJzRrlExy92tWgRuwW7tbykHf7CH71G2Y4TM2OwGcIS4+hyqKHS2EVBqaYwPY9Q==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@intlify/core-base": "11.2.8", "@intlify/core-base": "11.2.7",
"@intlify/shared": "11.2.8", "@intlify/shared": "11.2.7",
"@vue/devtools-api": "^6.5.0" "@vue/devtools-api": "^6.5.0"
}, },
"engines": { "engines": {
@@ -9048,8 +9041,6 @@
"integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"optional": true,
"peer": true,
"engines": { "engines": {
"node": ">=12" "node": ">=12"
} }

View File

@@ -5,7 +5,6 @@ import {
LanguageType, LanguageType,
SystemThemeType, SystemThemeType,
TabType, TabType,
UpdateSourceType
} from '@/../bindings/voidraft/internal/models/models'; } from '@/../bindings/voidraft/internal/models/models';
import {FONT_OPTIONS} from './fonts'; import {FONT_OPTIONS} from './fonts';
@@ -110,19 +109,12 @@ export const DEFAULT_CONFIG: AppConfig = {
updates: { updates: {
version: "1.0.0", version: "1.0.0",
autoUpdate: true, autoUpdate: true,
primarySource: UpdateSourceType.UpdateSourceGithub,
backupSource: UpdateSourceType.UpdateSourceGitea,
backupBeforeUpdate: true, backupBeforeUpdate: true,
updateTimeout: 30, updateTimeout: 120,
github: { github: {
owner: "landaiqing", owner: "landaiqing",
repo: "voidraft", repo: "voidraft",
}, },
gitea: {
baseURL: "https://git.landaiqing.cn",
owner: "landaiqing",
repo: "voidraft",
}
}, },
backup: { backup: {
enabled: false, enabled: false,

View File

@@ -35,7 +35,6 @@ class TomlBeautifierVisitor extends BaseTomlCstVisitor {
// Helper methods // Helper methods
public mapVisit: (elements: TomlCstNode[] | undefined) => (Doc | string)[]; public mapVisit: (elements: TomlCstNode[] | undefined) => (Doc | string)[];
public visitSingle: (ctx: TomlContext) => Doc | string; public visitSingle: (ctx: TomlContext) => Doc | string;
public visit: (ctx: TomlCstNode, inParam?: any) => Doc | string;
constructor() { constructor() {
super(); super();
@@ -57,26 +56,38 @@ class TomlBeautifierVisitor extends BaseTomlCstVisitor {
const singleElement = getSingle(ctx); const singleElement = getSingle(ctx);
return this.visit(singleElement); return this.visit(singleElement);
}; };
}
// Store reference to inherited visit method and override it /**
const originalVisit = Object.getPrototypeOf(this).visit?.bind(this); * Override visit method to handle TOML CST nodes
this.visit = (ctx: TomlCstNode, inParam?: any): Doc | string => { * Accepts both single node and array of nodes as per base class signature
*/
visit(cstNode: any, param?: any): any {
// Handle array of nodes
if (Array.isArray(cstNode)) {
return cstNode.map(node => this.visit(node, param));
}
const ctx = cstNode;
if (!ctx) { if (!ctx) {
return ''; return '';
} }
// 确保节点有name属性才调用基类方法
if (ctx.name) {
// Try to use the inherited visit method first // Try to use the inherited visit method first
const originalVisit = super.visit;
if (originalVisit) { if (originalVisit) {
try { try {
return originalVisit(ctx, inParam); return originalVisit.call(this, ctx, param);
} catch (error) { } catch (error) {
console.warn('Original visit method failed:', error); // Fallback to manual dispatch
} }
} }
// Fallback: manually dispatch based on node name/type // Fallback: manually dispatch based on node name/type
const methodName = ctx.name; const methodName = ctx.name;
if (methodName && typeof (this as any)[methodName] === 'function') { if (typeof (this as any)[methodName] === 'function') {
const visitMethod = (this as any)[methodName]; const visitMethod = (this as any)[methodName];
try { try {
if (ctx.children) { if (ctx.children) {
@@ -88,16 +99,16 @@ class TomlBeautifierVisitor extends BaseTomlCstVisitor {
console.warn(`Visit method ${methodName} failed:`, error); console.warn(`Visit method ${methodName} failed:`, error);
} }
} }
}
// Final fallback: return image if available // Final fallback: return image if available
return ctx.image || ''; return ctx.image || '';
};
} }
/** /**
* Visit the root TOML document * Visit the root TOML document
*/ */
toml(ctx: TomlDocument): Doc { toml(ctx: any): Doc {
// Handle empty toml document // Handle empty toml document
if (!ctx.expression) { if (!ctx.expression) {
return [line]; return [line];
@@ -164,7 +175,7 @@ class TomlBeautifierVisitor extends BaseTomlCstVisitor {
/** /**
* Visit an expression (keyval, table, or comment) * Visit an expression (keyval, table, or comment)
*/ */
expression(ctx: TomlExpression): Doc | string { expression(ctx: any): Doc | string {
if (ctx.keyval) { if (ctx.keyval) {
let keyValDoc = this.visit(ctx.keyval[0]); let keyValDoc = this.visit(ctx.keyval[0]);
if (ctx.Comment) { if (ctx.Comment) {
@@ -189,7 +200,7 @@ class TomlBeautifierVisitor extends BaseTomlCstVisitor {
/** /**
* Visit a key-value pair * Visit a key-value pair
*/ */
keyval(ctx: TomlKeyVal): Doc { keyval(ctx: any): Doc {
const keyDoc = this.visit(ctx.key[0]); const keyDoc = this.visit(ctx.key[0]);
const valueDoc = this.visit(ctx.val[0]); const valueDoc = this.visit(ctx.val[0]);
return [keyDoc, ' = ', valueDoc]; return [keyDoc, ' = ', valueDoc];

View File

@@ -7,6 +7,16 @@ export interface DocumentStats {
selectedCharacters: number; selectedCharacters: number;
} }
export interface FoldRange {
// 字符偏移(备用)
from: number;
to: number;
// 行号
fromLine: number;
toLine: number;
}
export const useEditorStateStore = defineStore('editorState', () => { export const useEditorStateStore = defineStore('editorState', () => {
// 光标位置存储 Record<docId, cursorPosition> // 光标位置存储 Record<docId, cursorPosition>
const cursorPositions = ref<Record<number, number>>({}); const cursorPositions = ref<Record<number, number>>({});
@@ -14,6 +24,9 @@ export const useEditorStateStore = defineStore('editorState', () => {
// 文档统计数据存储 Record<docId, DocumentStats> // 文档统计数据存储 Record<docId, DocumentStats>
const documentStats = ref<Record<number, DocumentStats>>({}); const documentStats = ref<Record<number, DocumentStats>>({});
// 折叠状态存储 Record<docId, FoldRange[]>
const foldStates = ref<Record<number, FoldRange[]>>({});
// 保存光标位置 // 保存光标位置
const saveCursorPosition = (docId: number, position: number) => { const saveCursorPosition = (docId: number, position: number) => {
cursorPositions.value[docId] = position; cursorPositions.value[docId] = position;
@@ -38,25 +51,40 @@ export const useEditorStateStore = defineStore('editorState', () => {
}; };
}; };
// 保存折叠状态
const saveFoldState = (docId: number, foldRanges: FoldRange[]) => {
foldStates.value[docId] = foldRanges;
};
// 获取折叠状态
const getFoldState = (docId: number): FoldRange[] => {
return foldStates.value[docId] || [];
};
// 清除文档状态 // 清除文档状态
const clearDocumentState = (docId: number) => { const clearDocumentState = (docId: number) => {
delete cursorPositions.value[docId]; delete cursorPositions.value[docId];
delete documentStats.value[docId]; delete documentStats.value[docId];
delete foldStates.value[docId];
}; };
// 清除所有状态 // 清除所有状态
const clearAllStates = () => { const clearAllStates = () => {
cursorPositions.value = {}; cursorPositions.value = {};
documentStats.value = {}; documentStats.value = {};
foldStates.value = {};
}; };
return { return {
cursorPositions, cursorPositions,
documentStats, documentStats,
foldStates,
saveCursorPosition, saveCursorPosition,
getCursorPosition, getCursorPosition,
saveDocumentStats, saveDocumentStats,
getDocumentStats, getDocumentStats,
saveFoldState,
getFoldState,
clearDocumentState, clearDocumentState,
clearAllStates clearAllStates
}; };
@@ -64,7 +92,7 @@ export const useEditorStateStore = defineStore('editorState', () => {
persist: { persist: {
key: 'voidraft-editor-state', key: 'voidraft-editor-state',
storage: localStorage, storage: localStorage,
pick: ['cursorPositions'] pick: ['cursorPositions', 'foldStates']
} }
}); });

View File

@@ -13,6 +13,7 @@ import {createStatsUpdateExtension} from '@/views/editor/basic/statsExtension';
import {createContentChangePlugin} from '@/views/editor/basic/contentChangeExtension'; import {createContentChangePlugin} from '@/views/editor/basic/contentChangeExtension';
import {createWheelZoomExtension} from '@/views/editor/basic/wheelZoomExtension'; import {createWheelZoomExtension} from '@/views/editor/basic/wheelZoomExtension';
import {createCursorPositionExtension, scrollToCursor} from '@/views/editor/basic/cursorPositionExtension'; import {createCursorPositionExtension, scrollToCursor} from '@/views/editor/basic/cursorPositionExtension';
import {createFoldStateExtension, restoreFoldState} from '@/views/editor/basic/foldStateExtension';
import {createDynamicKeymapExtension, updateKeymapExtension} from '@/views/editor/keymap'; import {createDynamicKeymapExtension, updateKeymapExtension} from '@/views/editor/keymap';
import { import {
createDynamicExtensions, createDynamicExtensions,
@@ -118,6 +119,9 @@ export const useEditorStore = defineStore('editor', () => {
// 光标位置持久化扩展 // 光标位置持久化扩展
const cursorPositionExtension = createCursorPositionExtension(docId); const cursorPositionExtension = createCursorPositionExtension(docId);
// 折叠状态持久化扩展
const foldStateExtension = createFoldStateExtension(docId);
// 快捷键扩展 // 快捷键扩展
const keymapExtension = await createDynamicKeymapExtension(); const keymapExtension = await createDynamicKeymapExtension();
@@ -136,6 +140,7 @@ export const useEditorStore = defineStore('editor', () => {
contentChangeExtension, contentChangeExtension,
codeBlockExtension, codeBlockExtension,
cursorPositionExtension, cursorPositionExtension,
foldStateExtension,
...dynamicExtensions, ...dynamicExtensions,
]; ];
@@ -227,6 +232,12 @@ export const useEditorStore = defineStore('editor', () => {
requestAnimationFrame(() => { requestAnimationFrame(() => {
scrollToCursor(instance.view); scrollToCursor(instance.view);
instance.view.focus(); instance.view.focus();
// 恢复折叠状态
const savedFoldState = editorStateStore.getFoldState(instance.documentId);
if (savedFoldState.length > 0) {
restoreFoldState(instance.view, savedFoldState);
}
}); });
} catch (error) { } catch (error) {
console.error('Error showing editor:', error); console.error('Error showing editor:', error);

View File

@@ -0,0 +1,113 @@
import {EditorView, ViewPlugin, ViewUpdate} from '@codemirror/view';
import {foldedRanges, foldEffect, unfoldEffect} from '@codemirror/language';
import {StateEffect} from '@codemirror/state';
import {useEditorStateStore, type FoldRange} from '@/stores/editorStateStore';
import {createDebounce} from '@/common/utils/debounce';
/**
* 折叠状态持久化扩展
*/
export function createFoldStateExtension(documentId: number) {
return ViewPlugin.fromClass(
class FoldStatePlugin {
private readonly editorStateStore = useEditorStateStore();
private readonly debouncedSave;
constructor(private view: EditorView) {
const {debouncedFn, flush} = createDebounce(
() => this.saveFoldState(),
{delay: 500}
);
this.debouncedSave = {fn: debouncedFn, flush};
}
update(update: ViewUpdate) {
// 检查是否有折叠/展开操作
const hasFoldChange = update.transactions.some(tr =>
tr.effects.some(effect =>
effect.is(foldEffect) || effect.is(unfoldEffect)
)
);
if (hasFoldChange) {
this.debouncedSave.fn();
}
}
destroy() {
// 销毁时立即执行待保存的操作
this.debouncedSave.flush();
// 再保存一次确保最新状态
this.saveFoldState();
}
private saveFoldState() {
const foldRanges: FoldRange[] = [];
const foldCursor = foldedRanges(this.view.state).iter();
const doc = this.view.state.doc;
// 遍历所有折叠区间
while (foldCursor.value !== null) {
const from = foldCursor.from;
const to = foldCursor.to;
// 同时记录字符偏移和行号
const fromLine = doc.lineAt(from).number;
const toLine = doc.lineAt(to).number;
foldRanges.push({
from,
to,
fromLine,
toLine
});
foldCursor.next();
}
this.editorStateStore.saveFoldState(documentId, foldRanges);
}
}
);
}
/**
* 恢复折叠状态(基于行号,更稳定)
* @param view 编辑器视图
* @param foldRanges 要恢复的折叠区间
*/
export function restoreFoldState(view: EditorView, foldRanges: FoldRange[]) {
if (foldRanges.length === 0) return;
const doc = view.state.doc;
const effects: StateEffect<any>[] = [];
for (const range of foldRanges) {
try {
// 优先使用行号恢复
if (range.fromLine && range.toLine) {
// 确保行号在有效范围内
if (range.fromLine >= 1 && range.toLine <= doc.lines && range.fromLine <= range.toLine) {
const fromPos = doc.line(range.fromLine).from;
const toPos = doc.line(range.toLine).to;
effects.push(foldEffect.of({from: fromPos, to: toPos}));
continue;
}
}
// 使用字符偏移
if (range.from >= 0 && range.to <= doc.length && range.from < range.to) {
effects.push(foldEffect.of({from: range.from, to: range.to}));
}
} catch (error) {
// 忽略无效的折叠区间
console.warn('Failed to restore fold range:', range, error);
}
}
if (effects.length > 0) {
view.dispatch({effects});
}
}

View File

@@ -89,7 +89,6 @@ export function createCodeBlockExtension(options: CodeBlockOptions = {}): Extens
showBackground = true, showBackground = true,
enableAutoDetection = true, enableAutoDetection = true,
defaultLanguage = 'text', defaultLanguage = 'text',
separatorHeight = 12,
} = options; } = options;
return [ return [
@@ -108,8 +107,7 @@ export function createCodeBlockExtension(options: CodeBlockOptions = {}): Extens
// 视觉装饰系统 // 视觉装饰系统
...getBlockDecorationExtensions({ ...getBlockDecorationExtensions({
showBackground, showBackground
separatorHeight
}), }),
// 光标保护(防止方向键移动到分隔符上) // 光标保护(防止方向键移动到分隔符上)

7
go.mod
View File

@@ -11,9 +11,9 @@ require (
github.com/knadh/koanf/providers/file v1.2.1 github.com/knadh/koanf/providers/file v1.2.1
github.com/knadh/koanf/providers/structs v1.0.0 github.com/knadh/koanf/providers/structs v1.0.0
github.com/knadh/koanf/v2 v2.3.0 github.com/knadh/koanf/v2 v2.3.0
github.com/mattn/go-sqlite3 v1.14.32 github.com/mattn/go-sqlite3 v1.14.33
github.com/stretchr/testify v1.11.1 github.com/stretchr/testify v1.11.1
github.com/wailsapp/wails/v3 v3.0.0-alpha.54 github.com/wailsapp/wails/v3 v3.0.0-alpha.55
golang.org/x/net v0.48.0 golang.org/x/net v0.48.0
golang.org/x/sys v0.39.0 golang.org/x/sys v0.39.0
golang.org/x/text v0.32.0 golang.org/x/text v0.32.0
@@ -48,6 +48,7 @@ require (
github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-openapi/inflect v0.21.5 // indirect github.com/go-openapi/inflect v0.21.5 // indirect
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/goccy/go-json v0.10.5 // indirect
github.com/godbus/dbus/v5 v5.2.2 // indirect github.com/godbus/dbus/v5 v5.2.2 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/google/go-cmp v0.7.0 // indirect github.com/google/go-cmp v0.7.0 // indirect
@@ -79,7 +80,6 @@ require (
github.com/skeema/knownhosts v1.3.2 // indirect github.com/skeema/knownhosts v1.3.2 // indirect
github.com/ulikunitz/xz v0.5.15 // indirect github.com/ulikunitz/xz v0.5.15 // indirect
github.com/wailsapp/go-webview2 v1.0.23 // indirect github.com/wailsapp/go-webview2 v1.0.23 // indirect
github.com/wailsapp/mimetype v1.4.1 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect
github.com/zclconf/go-cty v1.17.0 // indirect github.com/zclconf/go-cty v1.17.0 // indirect
github.com/zclconf/go-cty-yaml v1.2.0 // indirect github.com/zclconf/go-cty-yaml v1.2.0 // indirect
@@ -92,7 +92,6 @@ require (
golang.org/x/sync v0.19.0 // indirect golang.org/x/sync v0.19.0 // indirect
golang.org/x/time v0.14.0 // indirect golang.org/x/time v0.14.0 // indirect
golang.org/x/tools v0.40.0 // indirect golang.org/x/tools v0.40.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )

35
go.sum
View File

@@ -33,8 +33,16 @@ github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY=
github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0=
github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0= github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0=
github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE= github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M=
github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM=
github.com/bytedance/sonic v1.14.2 h1:k1twIoe97C1DtYUo+fZQy865IuHia4PR5RPiuGPPIIE=
github.com/bytedance/sonic v1.14.2/go.mod h1:T80iDELeHiHKSc0C9tubFygiuXoGzrkjKzX2quAx980=
github.com/bytedance/sonic/loader v0.4.0 h1:olZ7lEqcxtZygCK9EKYKADnpQoYkRQxaeY2NYzevs+o=
github.com/bytedance/sonic/loader v0.4.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo=
github.com/cloudflare/circl v1.6.2 h1:hL7VBpHHKzrV5WTfHCaBsgx/HGbBYlgrwvNXEVDYYsQ= github.com/cloudflare/circl v1.6.2 h1:hL7VBpHHKzrV5WTfHCaBsgx/HGbBYlgrwvNXEVDYYsQ=
github.com/cloudflare/circl v1.6.2/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= github.com/cloudflare/circl v1.6.2/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4=
github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
github.com/creativeprojects/go-selfupdate v1.5.2 h1:3KR3JLrq70oplb9yZzbmJ89qRP78D1AN/9u+l3k0LJ4= github.com/creativeprojects/go-selfupdate v1.5.2 h1:3KR3JLrq70oplb9yZzbmJ89qRP78D1AN/9u+l3k0LJ4=
github.com/creativeprojects/go-selfupdate v1.5.2/go.mod h1:BCOuwIl1dRRCmPNRPH0amULeZqayhKyY2mH/h4va7Dk= github.com/creativeprojects/go-selfupdate v1.5.2/go.mod h1:BCOuwIl1dRRCmPNRPH0amULeZqayhKyY2mH/h4va7Dk=
github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE=
@@ -68,6 +76,8 @@ github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMj
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
github.com/go-git/go-git/v5 v5.16.4 h1:7ajIEZHZJULcyJebDLo99bGgS0jRrOxzZG4uCk2Yb2Y= github.com/go-git/go-git/v5 v5.16.4 h1:7ajIEZHZJULcyJebDLo99bGgS0jRrOxzZG4uCk2Yb2Y=
github.com/go-git/go-git/v5 v5.16.4/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= github.com/go-git/go-git/v5 v5.16.4/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8=
github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e h1:Lf/gRkoycfOBPa42vU2bbgPurFong6zXeFtPoxholzU=
github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e/go.mod h1:uNVvRXArCGbZ508SxYYTC5v1JWoz2voff5pm25jU1Ok=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/go-openapi/inflect v0.21.5 h1:M2RCq6PPS3YbIaL7CXosGL3BbzAcmfBAT0nC3YfesZA= github.com/go-openapi/inflect v0.21.5 h1:M2RCq6PPS3YbIaL7CXosGL3BbzAcmfBAT0nC3YfesZA=
@@ -76,6 +86,8 @@ github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ= github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ=
github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c= github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c=
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
@@ -103,6 +115,8 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 h1:njuLRcjAuMKr7kI3D85AXWkw6/+v9PwtV6M6o11sWHQ= github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 h1:njuLRcjAuMKr7kI3D85AXWkw6/+v9PwtV6M6o11sWHQ=
github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PWkxoFkQ= github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PWkxoFkQ=
github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M= github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M=
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
@@ -137,14 +151,18 @@ github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHP
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs= github.com/mattn/go-sqlite3 v1.14.33 h1:A5blZ5ulQo2AtayQ9/limgHEkFreKj1Dv226a1K73s0=
github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mattn/go-sqlite3 v1.14.33/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0= github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0=
@@ -172,14 +190,14 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY=
github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/wailsapp/go-webview2 v1.0.23 h1:jmv8qhz1lHibCc79bMM/a/FqOnnzOGEisLav+a0b9P0= github.com/wailsapp/go-webview2 v1.0.23 h1:jmv8qhz1lHibCc79bMM/a/FqOnnzOGEisLav+a0b9P0=
github.com/wailsapp/go-webview2 v1.0.23/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc= github.com/wailsapp/go-webview2 v1.0.23/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc=
github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs= github.com/wailsapp/wails/v3 v3.0.0-alpha.55 h1:Wxwxc4EN6axDAvH/O5n3uoZQ+XRY/HQZ5rMdn0npq78=
github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o= github.com/wailsapp/wails/v3 v3.0.0-alpha.55/go.mod h1:AyH9vRcseorpL3p5XvxKgK0Lv/agJ7pTmcPdy25xZPo=
github.com/wailsapp/wails/v3 v3.0.0-alpha.54 h1:XlQ+9dwDtOyfxIyA0h1AeT0zdUP3SFdhLkpIgPjWnWc=
github.com/wailsapp/wails/v3 v3.0.0-alpha.54/go.mod h1:yaz8baG0+YzoiN8J6osn0wKiEi0iUux0ZU5NsZFu6OQ=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
github.com/zclconf/go-cty v1.17.0 h1:seZvECve6XX4tmnvRzWtJNHdscMtYEx5R7bnnVyd/d0= github.com/zclconf/go-cty v1.17.0 h1:seZvECve6XX4tmnvRzWtJNHdscMtYEx5R7bnnVyd/d0=
@@ -190,6 +208,8 @@ github.com/zclconf/go-cty-yaml v1.2.0 h1:GDyL4+e/Qe/S0B7YaecMLbVvAR/Mp21CXMOSiCT
github.com/zclconf/go-cty-yaml v1.2.0/go.mod h1:9YLUH4g7lOhVWqUbctnVlZ5KLpg7JAprQNgxSZ1Gyxs= github.com/zclconf/go-cty-yaml v1.2.0/go.mod h1:9YLUH4g7lOhVWqUbctnVlZ5KLpg7JAprQNgxSZ1Gyxs=
gitlab.com/gitlab-org/api/client-go v1.10.0 h1:VlB9gXQdG6w643lH53VduUHVnCWQG5Ty86VbXnyi70A= gitlab.com/gitlab-org/api/client-go v1.10.0 h1:VlB9gXQdG6w643lH53VduUHVnCWQG5Ty86VbXnyi70A=
gitlab.com/gitlab-org/api/client-go v1.10.0/go.mod h1:U3QKvjbT1J1FrgLsA7w/XlhoBIendUqB4o3/Ht3UhEQ= gitlab.com/gitlab-org/api/client-go v1.10.0/go.mod h1:U3QKvjbT1J1FrgLsA7w/XlhoBIendUqB4o3/Ht3UhEQ=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
@@ -204,7 +224,6 @@ golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg= golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
@@ -242,8 +261,6 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@@ -39,29 +39,12 @@ const (
SystemThemeAuto SystemThemeType = "auto" SystemThemeAuto SystemThemeType = "auto"
) )
// UpdateSourceType 更新源类型
type UpdateSourceType string
const (
// UpdateSourceGithub GitHub更新源
UpdateSourceGithub UpdateSourceType = "github"
// UpdateSourceGitea Gitea更新源
UpdateSourceGitea UpdateSourceType = "gitea"
)
// GithubConfig GitHub配置 // GithubConfig GitHub配置
type GithubConfig struct { type GithubConfig struct {
Owner string `json:"owner"` // 仓库所有者 Owner string `json:"owner"` // 仓库所有者
Repo string `json:"repo"` // 仓库名称 Repo string `json:"repo"` // 仓库名称
} }
// GiteaConfig Gitea配置
type GiteaConfig struct {
BaseURL string `json:"baseURL"` // Gitea服务器URL
Owner string `json:"owner"` // 仓库所有者
Repo string `json:"repo"` // 仓库名称
}
// GeneralConfig 通用设置配置 // GeneralConfig 通用设置配置
type GeneralConfig struct { type GeneralConfig struct {
AlwaysOnTop bool `json:"alwaysOnTop"` // 窗口是否置顶 AlwaysOnTop bool `json:"alwaysOnTop"` // 窗口是否置顶
@@ -122,12 +105,9 @@ type AppearanceConfig struct {
type UpdatesConfig struct { type UpdatesConfig struct {
Version string `json:"version"` // 当前版本号 Version string `json:"version"` // 当前版本号
AutoUpdate bool `json:"autoUpdate"` // 是否自动更新 AutoUpdate bool `json:"autoUpdate"` // 是否自动更新
PrimarySource UpdateSourceType `json:"primarySource"` // 主要更新源
BackupSource UpdateSourceType `json:"backupSource"` // 备用更新源
BackupBeforeUpdate bool `json:"backupBeforeUpdate"` // 更新前是否备份 BackupBeforeUpdate bool `json:"backupBeforeUpdate"` // 更新前是否备份
UpdateTimeout int `json:"updateTimeout"` // 更新超时时间(秒) UpdateTimeout int `json:"updateTimeout"` // 更新超时时间(秒)
Github GithubConfig `json:"github"` // GitHub配置 Github GithubConfig `json:"github"` // GitHub配置
Gitea GiteaConfig `json:"gitea"` // Gitea配置
} }
// Git备份相关类型定义 // Git备份相关类型定义
@@ -221,19 +201,12 @@ func NewDefaultAppConfig() *AppConfig {
Updates: UpdatesConfig{ Updates: UpdatesConfig{
Version: version.Version, Version: version.Version,
AutoUpdate: true, AutoUpdate: true,
PrimarySource: UpdateSourceGitea,
BackupSource: UpdateSourceGithub,
BackupBeforeUpdate: true, BackupBeforeUpdate: true,
UpdateTimeout: 30, UpdateTimeout: 120,
Github: GithubConfig{ Github: GithubConfig{
Owner: "landaiqing", Owner: "landaiqing",
Repo: "voidraft", Repo: "voidraft",
}, },
Gitea: GiteaConfig{
BaseURL: "https://git.landaiqing.cn",
Owner: "landaiqing",
Repo: "voidraft",
},
}, },
Backup: GitBackupConfig{ Backup: GitBackupConfig{
Enabled: false, Enabled: false,

View File

@@ -25,7 +25,7 @@ type SelfUpdateResult struct {
AssetURL string `json:"assetURL"` // 下载链接 AssetURL string `json:"assetURL"` // 下载链接
ReleaseNotes string `json:"releaseNotes"` // 发布说明 ReleaseNotes string `json:"releaseNotes"` // 发布说明
Error string `json:"error"` // 错误信息 Error string `json:"error"` // 错误信息
Source string `json:"source"` // 更新源github/gitea Source string `json:"source"` // 更新源github
} }
// SelfUpdateService 自我更新服务 // SelfUpdateService 自我更新服务
@@ -66,33 +66,6 @@ func (s *SelfUpdateService) CheckForUpdates(ctx context.Context) (*SelfUpdateRes
return nil, err return nil, err
} }
result := &SelfUpdateResult{
CurrentVersion: config.Updates.Version,
HasUpdate: false,
UpdateApplied: false,
}
// 尝试主要更新源
primaryResult, err := s.checkSourceForUpdates(ctx, config.Updates.PrimarySource, config)
if err == nil && primaryResult != nil {
s.handleUpdateBadge(primaryResult)
return primaryResult, nil
}
// 尝试备用更新源
backupResult, backupErr := s.checkSourceForUpdates(ctx, config.Updates.BackupSource, config)
if backupErr != nil {
result.Error = fmt.Sprintf("both sources failed: %v; %v", err, backupErr)
s.handleUpdateBadge(result)
return result, errors.New(result.Error)
}
s.handleUpdateBadge(backupResult)
return backupResult, nil
}
// checkSourceForUpdates 根据更新源类型检查更新
func (s *SelfUpdateService) checkSourceForUpdates(ctx context.Context, sourceType models.UpdateSourceType, config *models.AppConfig) (*SelfUpdateResult, error) {
timeout := config.Updates.UpdateTimeout timeout := config.Updates.UpdateTimeout
if timeout <= 0 { if timeout <= 0 {
timeout = 30 timeout = 30
@@ -104,28 +77,21 @@ func (s *SelfUpdateService) checkSourceForUpdates(ctx context.Context, sourceTyp
CurrentVersion: config.Updates.Version, CurrentVersion: config.Updates.Version,
HasUpdate: false, HasUpdate: false,
UpdateApplied: false, UpdateApplied: false,
Source: string(sourceType), Source: "github",
}
var release *selfupdate.Release
var found bool
var err error
switch sourceType {
case models.UpdateSourceGithub:
release, found, err = s.checkGithubUpdates(timeoutCtx, config)
case models.UpdateSourceGitea:
release, found, err = s.checkGiteaUpdates(timeoutCtx, config)
default:
return nil, fmt.Errorf("unsupported source: %s", sourceType)
} }
// 检查 GitHub 更新
release, found, err := s.checkGithubUpdates(timeoutCtx, config)
if err != nil { if err != nil {
return result, fmt.Errorf("check failed: %w", err) result.Error = fmt.Sprintf("check github updates failed: %v", err)
s.handleUpdateBadge(result)
return result, err
} }
if !found { if !found {
return result, fmt.Errorf("no release for %s/%s", runtime.GOOS, runtime.GOARCH) result.Error = fmt.Sprintf("no release for %s/%s", runtime.GOOS, runtime.GOARCH)
s.handleUpdateBadge(result)
return result, errors.New(result.Error)
} }
result.LatestVersion = release.Version() result.LatestVersion = release.Version()
@@ -133,6 +99,7 @@ func (s *SelfUpdateService) checkSourceForUpdates(ctx context.Context, sourceTyp
result.ReleaseNotes = release.ReleaseNotes result.ReleaseNotes = release.ReleaseNotes
result.HasUpdate = release.GreaterThan(config.Updates.Version) result.HasUpdate = release.GreaterThan(config.Updates.Version)
s.handleUpdateBadge(result)
return result, nil return result, nil
} }
@@ -141,18 +108,6 @@ func (s *SelfUpdateService) createGithubUpdater() (*selfupdate.Updater, error) {
return selfupdate.NewUpdater(selfupdate.Config{}) return selfupdate.NewUpdater(selfupdate.Config{})
} }
// createGiteaUpdater 创建Gitea更新器
func (s *SelfUpdateService) createGiteaUpdater(config *models.AppConfig) (*selfupdate.Updater, error) {
source, err := selfupdate.NewGiteaSource(selfupdate.GiteaConfig{
BaseURL: config.Updates.Gitea.BaseURL,
})
if err != nil {
return nil, fmt.Errorf("create gitea source failed: %w", err)
}
return selfupdate.NewUpdater(selfupdate.Config{Source: source})
}
// checkGithubUpdates 检查GitHub更新 // checkGithubUpdates 检查GitHub更新
func (s *SelfUpdateService) checkGithubUpdates(ctx context.Context, config *models.AppConfig) (*selfupdate.Release, bool, error) { func (s *SelfUpdateService) checkGithubUpdates(ctx context.Context, config *models.AppConfig) (*selfupdate.Release, bool, error) {
updater, err := s.createGithubUpdater() updater, err := s.createGithubUpdater()
@@ -164,17 +119,6 @@ func (s *SelfUpdateService) checkGithubUpdates(ctx context.Context, config *mode
return updater.DetectLatest(ctx, repo) return updater.DetectLatest(ctx, repo)
} }
// checkGiteaUpdates 检查Gitea更新
func (s *SelfUpdateService) checkGiteaUpdates(ctx context.Context, config *models.AppConfig) (*selfupdate.Release, bool, error) {
updater, err := s.createGiteaUpdater(config)
if err != nil {
return nil, false, err
}
repo := selfupdate.NewRepositorySlug(config.Updates.Gitea.Owner, config.Updates.Gitea.Repo)
return updater.DetectLatest(ctx, repo)
}
// ApplyUpdate 应用更新 // ApplyUpdate 应用更新
func (s *SelfUpdateService) ApplyUpdate(ctx context.Context) (*SelfUpdateResult, error) { func (s *SelfUpdateService) ApplyUpdate(ctx context.Context) (*SelfUpdateResult, error) {
s.mu.Lock() s.mu.Lock()
@@ -201,23 +145,17 @@ func (s *SelfUpdateService) ApplyUpdate(ctx context.Context) (*SelfUpdateResult,
return nil, fmt.Errorf("locate executable failed: %w", err) return nil, fmt.Errorf("locate executable failed: %w", err)
} }
// 尝试主要源 // 执行 GitHub 更新
result, err := s.performUpdate(ctx, config.Updates.PrimarySource, exe, config) result, err := s.performUpdate(ctx, exe, config)
if err == nil {
return result, nil
}
// 尝试备用源
result, err = s.performUpdate(ctx, config.Updates.BackupSource, exe, config)
if err != nil { if err != nil {
return nil, fmt.Errorf("update failed from both sources: %w", err) return nil, fmt.Errorf("update failed: %w", err)
} }
return result, nil return result, nil
} }
// performUpdate 执行更新操作(包括检测、备份、下载、应用) // performUpdate 执行更新操作(包括检测、备份、下载、应用)
func (s *SelfUpdateService) performUpdate(ctx context.Context, sourceType models.UpdateSourceType, exe string, config *models.AppConfig) (*SelfUpdateResult, error) { func (s *SelfUpdateService) performUpdate(ctx context.Context, exe string, config *models.AppConfig) (*SelfUpdateResult, error) {
timeout := config.Updates.UpdateTimeout timeout := config.Updates.UpdateTimeout
if timeout <= 0 { if timeout <= 0 {
timeout = 30 timeout = 30
@@ -225,8 +163,13 @@ func (s *SelfUpdateService) performUpdate(ctx context.Context, sourceType models
checkCtx, cancel := context.WithTimeout(ctx, time.Duration(timeout)*time.Second) checkCtx, cancel := context.WithTimeout(ctx, time.Duration(timeout)*time.Second)
defer cancel() defer cancel()
// 获取更新器和版本信息 // 获取 GitHub 更新信息
updater, release, found, err := s.getUpdateFromSource(checkCtx, sourceType, config) updater, err := s.createGithubUpdater()
if err != nil {
return nil, fmt.Errorf("create github updater failed: %w", err)
}
release, found, err := s.checkGithubUpdates(checkCtx, config)
if err != nil || !found { if err != nil || !found {
return nil, fmt.Errorf("detect release failed: %w", err) return nil, fmt.Errorf("detect release failed: %w", err)
} }
@@ -236,7 +179,7 @@ func (s *SelfUpdateService) performUpdate(ctx context.Context, sourceType models
LatestVersion: release.Version(), LatestVersion: release.Version(),
AssetURL: release.AssetURL, AssetURL: release.AssetURL,
ReleaseNotes: release.ReleaseNotes, ReleaseNotes: release.ReleaseNotes,
Source: string(sourceType), Source: "github",
HasUpdate: release.GreaterThan(config.Updates.Version), HasUpdate: release.GreaterThan(config.Updates.Version),
} }
@@ -269,33 +212,6 @@ func (s *SelfUpdateService) performUpdate(ctx context.Context, sourceType models
return result, nil return result, nil
} }
// getUpdateFromSource 从指定源获取更新信息
func (s *SelfUpdateService) getUpdateFromSource(ctx context.Context, sourceType models.UpdateSourceType, config *models.AppConfig) (*selfupdate.Updater, *selfupdate.Release, bool, error) {
var updater *selfupdate.Updater
var release *selfupdate.Release
var found bool
var err error
switch sourceType {
case models.UpdateSourceGithub:
updater, err = s.createGithubUpdater()
if err != nil {
return nil, nil, false, err
}
release, found, err = s.checkGithubUpdates(ctx, config)
case models.UpdateSourceGitea:
updater, err = s.createGiteaUpdater(config)
if err != nil {
return nil, nil, false, err
}
release, found, err = s.checkGiteaUpdates(ctx, config)
default:
return nil, nil, false, fmt.Errorf("unsupported source: %s", sourceType)
}
return updater, release, found, err
}
// handleUpdateSuccess 处理更新成功后的操作 // handleUpdateSuccess 处理更新成功后的操作
func (s *SelfUpdateService) handleUpdateSuccess(result *SelfUpdateResult) { func (s *SelfUpdateService) handleUpdateSuccess(result *SelfUpdateResult) {
// 更新配置版本 // 更新配置版本