Skip to content

Commit 79ac81a

Browse files
author
User
committed
feat: 使用 GitHub API 实现更新检查
- 移除 Tauri updater 插件(不需要签名) - 通过 GitHub API 获取最新 Release - 版本比较和更新提示 - 支持直接下载安装包 - 24小时跳过提醒功能
1 parent 53647cb commit 79ac81a

File tree

6 files changed

+76
-131
lines changed

6 files changed

+76
-131
lines changed

package-lock.json

Lines changed: 1 addition & 21 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@
1717
"license": "MIT",
1818
"type": "commonjs",
1919
"dependencies": {
20-
"@tauri-apps/api": "^2.0.0",
21-
"@tauri-apps/plugin-updater": "^2.0.0",
22-
"@tauri-apps/plugin-process": "^2.0.0"
20+
"@tauri-apps/api": "^2.0.0"
2321
},
2422
"devDependencies": {
2523
"@tauri-apps/cli": "^2.0.0"

src-tauri/Cargo.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,3 @@ tauri = { version = "2", features = [] }
2323
tauri-plugin-log = "2"
2424
tauri-plugin-shell = "2"
2525
tauri-plugin-dialog = "2"
26-
tauri-plugin-updater = "2"
27-
tauri-plugin-process = "2"

src-tauri/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ pub fn run() {
1010
tauri::Builder::default()
1111
.plugin(tauri_plugin_shell::init())
1212
.plugin(tauri_plugin_dialog::init())
13-
.plugin(tauri_plugin_updater::Builder::new().build())
14-
.plugin(tauri_plugin_process::init())
1513
.setup(|app| {
1614
let app_handle = app.handle().clone();
1715

src-tauri/tauri.conf.json

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,6 @@
5454
"plugins": {
5555
"shell": {
5656
"open": true
57-
},
58-
"updater": {
59-
"endpoints": [
60-
"https://github.com/Yar1991-Translation/LoArchive/releases/latest/download/latest.json"
61-
],
62-
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDE0MkZGMzQ3ODkzQkUwQTIKUldTaTREdUpSL012RkxDQnJBc0RvZVlQa0ttYmdubVh0MWpuNkN3YlcxZ09oaDV1Z0daaTlTT0sK"
6357
}
6458
}
6559
}

templates/index.html

Lines changed: 74 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -787,143 +787,120 @@ <h3 class="settings-title">
787787
}
788788
}
789789

790-
/* ========== 自动更新功能 ========== */
791-
let updateAvailable = null;
790+
/* ========== 自动更新功能(GitHub API) ========== */
791+
const APP_VERSION = '1.0.0';
792+
const GITHUB_REPO = 'Yar1991-Translation/LoArchive';
793+
let latestRelease = null;
792794

793795
async function checkForUpdates(silent = false) {
794-
const isTauri = window.__TAURI__ !== undefined || window.__TAURI_INTERNALS__ !== undefined;
795-
if (!isTauri) {
796-
if (!silent) showNotification('浏览器模式不支持自动更新', 'info');
797-
return;
798-
}
799-
800796
try {
801797
if (!silent) showNotification('正在检查更新...', 'info');
802798

803-
let updater;
804-
if (window.__TAURI__ && window.__TAURI__.updater) {
805-
updater = window.__TAURI__.updater;
806-
} else {
807-
updater = await import('@tauri-apps/plugin-updater');
799+
const res = await fetch(`https://api.github.com/repos/${GITHUB_REPO}/releases/latest`);
800+
if (!res.ok) {
801+
if (res.status === 404) {
802+
if (!silent) showNotification('暂无发布版本', 'info');
803+
return;
804+
}
805+
throw new Error('GitHub API 请求失败');
808806
}
809807

810-
const update = await updater.check();
808+
const release = await res.json();
809+
latestRelease = release;
810+
const latestVersion = release.tag_name.replace(/^v/, '');
811811

812-
if (update && update.available) {
813-
updateAvailable = update;
814-
showUpdateDialog(update);
812+
if (isNewerVersion(latestVersion, APP_VERSION)) {
813+
showUpdateDialog(release, latestVersion);
815814
} else {
816-
if (!silent) showNotification('当前已是最新版本 ✓', 'success');
815+
if (!silent) showNotification(`当前已是最新版本 v${APP_VERSION} ✓`, 'success');
817816
}
818817
} catch (e) {
819818
console.error('检查更新失败:', e);
820-
if (!silent) showNotification('检查更新失败: ' + e.message, 'error');
819+
if (!silent) showNotification('检查更新失败,请检查网络连接', 'error');
820+
}
821+
}
822+
823+
function isNewerVersion(latest, current) {
824+
const l = latest.split('.').map(Number);
825+
const c = current.split('.').map(Number);
826+
for (let i = 0; i < Math.max(l.length, c.length); i++) {
827+
if ((l[i]||0) > (c[i]||0)) return true;
828+
if ((l[i]||0) < (c[i]||0)) return false;
821829
}
830+
return false;
822831
}
823832

824-
function showUpdateDialog(update) {
825-
// 创建更新弹窗
833+
function showUpdateDialog(release, newVersion) {
834+
const existing = document.getElementById('update-overlay');
835+
if (existing) existing.remove();
836+
826837
const overlay = document.createElement('div');
827838
overlay.id = 'update-overlay';
828-
overlay.style.cssText = `
829-
position: fixed; inset: 0; background: rgba(0,0,0,0.6);
830-
display: flex; align-items: center; justify-content: center;
831-
z-index: 20000; backdrop-filter: blur(4px);
832-
`;
839+
overlay.style.cssText = `position:fixed;inset:0;background:rgba(0,0,0,0.6);display:flex;align-items:center;justify-content:center;z-index:20000;backdrop-filter:blur(4px);`;
840+
841+
const msiAsset = release.assets.find(a => a.name.endsWith('.msi'));
842+
const exeAsset = release.assets.find(a => a.name.endsWith('-setup.exe'));
843+
const downloadUrl = msiAsset?.browser_download_url || exeAsset?.browser_download_url || release.html_url;
833844

834845
const dialog = document.createElement('div');
835-
dialog.style.cssText = `
836-
background: var(--bg-card); border-radius: 16px; padding: 32px;
837-
max-width: 450px; width: 90%; box-shadow: 0 20px 60px rgba(0,0,0,0.3);
838-
animation: slideUp 0.3s ease;
839-
`;
846+
dialog.style.cssText = `background:var(--bg-card);border-radius:16px;padding:32px;max-width:500px;width:90%;box-shadow:0 20px 60px rgba(0,0,0,0.3);animation:slideUp 0.3s ease;`;
847+
848+
const bodyHtml = release.body ? release.body
849+
.replace(/^### (.+)$/gm, '<strong style="display:block;margin:8px 0 4px;">$1</strong>')
850+
.replace(/^## (.+)$/gm, '<strong style="display:block;margin:12px 0 6px;">$1</strong>')
851+
.replace(/^- (.+)$/gm, '• $1<br>')
852+
.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
853+
.replace(/\n\n/g, '<br>') : '';
840854

841855
dialog.innerHTML = `
842856
<div style="text-align:center;margin-bottom:24px;">
843857
<div style="font-size:48px;margin-bottom:16px;">🎉</div>
844-
<h2 style="margin:0 0 8px;font-size:20px;color:var(--text-primary);">发现新版本</h2>
845-
<p style="margin:0;color:var(--text-muted);font-size:14px;">
846-
${update.currentVersion || '当前版本'} → <strong style="color:var(--primary);">${update.version || '新版本'}</strong>
847-
</p>
858+
<h2 style="margin:0 0 8px;font-size:20px;color:var(--text-primary);">发现新版本!</h2>
859+
<p style="margin:0;color:var(--text-muted);font-size:14px;">v${APP_VERSION} → <strong style="color:var(--primary);">v${newVersion}</strong></p>
848860
</div>
849-
${update.body ? `
850-
<div style="background:var(--bg-secondary);border-radius:8px;padding:16px;margin-bottom:24px;max-height:200px;overflow-y:auto;">
851-
<h4 style="margin:0 0 8px;font-size:14px;color:var(--text-primary);">📝 更新内容</h4>
852-
<div style="font-size:13px;color:var(--text-secondary);line-height:1.6;white-space:pre-wrap;">${update.body}</div>
861+
${bodyHtml ? `<div style="background:var(--bg-secondary);border-radius:8px;padding:16px;margin-bottom:24px;max-height:200px;overflow-y:auto;">
862+
<h4 style="margin:0 0 12px;font-size:14px;color:var(--text-primary);">📝 更新内容</h4>
863+
<div style="font-size:13px;color:var(--text-secondary);line-height:1.8;">${bodyHtml}</div>
853864
</div>` : ''}
854-
<div style="display:flex;gap:12px;">
855-
<button id="update-later" style="
856-
flex:1;padding:12px;border:1px solid var(--border);border-radius:8px;
857-
background:transparent;color:var(--text-secondary);cursor:pointer;font-size:14px;
858-
">稍后更新</button>
859-
<button id="update-now" style="
860-
flex:1;padding:12px;border:none;border-radius:8px;
861-
background:var(--primary);color:white;cursor:pointer;font-size:14px;font-weight:600;
862-
">立即更新</button>
863-
</div>
864-
`;
865+
<div style="display:flex;gap:12px;flex-wrap:wrap;">
866+
<button id="update-later" style="flex:1;min-width:100px;padding:12px;border:1px solid var(--border);border-radius:8px;background:transparent;color:var(--text-secondary);cursor:pointer;font-size:14px;">稍后提醒</button>
867+
<button id="update-github" style="flex:1;min-width:100px;padding:12px;border:none;border-radius:8px;background:var(--bg-secondary);color:var(--text-primary);cursor:pointer;font-size:14px;">📋 GitHub</button>
868+
<button id="update-download" style="flex:1;min-width:100px;padding:12px;border:none;border-radius:8px;background:var(--primary);color:white;cursor:pointer;font-size:14px;font-weight:600;">⬇️ 下载</button>
869+
</div>`;
865870

866871
overlay.appendChild(dialog);
867872
document.body.appendChild(overlay);
868873

869-
// 添加动画样式
870-
const style = document.createElement('style');
871-
style.textContent = `@keyframes slideUp{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}`;
872-
document.head.appendChild(style);
874+
if (!document.getElementById('update-anim-style')) {
875+
const style = document.createElement('style');
876+
style.id = 'update-anim-style';
877+
style.textContent = `@keyframes slideUp{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}`;
878+
document.head.appendChild(style);
879+
}
873880

874-
// 绑定事件
875881
document.getElementById('update-later').onclick = () => {
876882
overlay.remove();
877-
style.remove();
883+
localStorage.setItem('loarchive_update_skip', Date.now().toString());
878884
};
879-
880-
document.getElementById('update-now').onclick = async () => {
881-
const btn = document.getElementById('update-now');
882-
btn.textContent = '下载中...';
883-
btn.disabled = true;
884-
885-
try {
886-
await installUpdate();
887-
} catch (e) {
888-
showNotification('更新失败: ' + e.message, 'error');
889-
overlay.remove();
890-
style.remove();
891-
}
885+
document.getElementById('update-github').onclick = () => window.open(release.html_url, '_blank');
886+
document.getElementById('update-download').onclick = () => {
887+
window.open(downloadUrl, '_blank');
888+
showNotification('下载已开始,安装后请重启应用', 'success');
889+
overlay.remove();
892890
};
891+
overlay.onclick = (e) => { if (e.target === overlay) overlay.remove(); };
893892
}
894893

895-
async function installUpdate() {
896-
if (!updateAvailable) return;
897-
898-
try {
899-
showNotification('正在下载更新...', 'info');
900-
901-
// 下载并安装更新
902-
await updateAvailable.downloadAndInstall();
903-
904-
showNotification('更新完成,正在重启应用...', 'success');
905-
906-
// 重启应用
907-
let process;
908-
if (window.__TAURI__ && window.__TAURI__.process) {
909-
process = window.__TAURI__.process;
910-
} else {
911-
process = await import('@tauri-apps/plugin-process');
912-
}
913-
await process.relaunch();
914-
} catch (e) {
915-
console.error('安装更新失败:', e);
916-
throw e;
917-
}
918-
}
919-
920-
// 应用启动时静默检查更新
894+
// 应用启动时检查更新
921895
setTimeout(() => {
922-
checkForUpdates(true);
896+
const skipTime = localStorage.getItem('loarchive_update_skip');
897+
if (!skipTime || (Date.now() - parseInt(skipTime)) > 86400000) {
898+
checkForUpdates(true);
899+
}
923900
}, 3000);
924901

925-
// 暴露给全局使用
926902
window.checkForUpdates = checkForUpdates;
903+
window.APP_VERSION = APP_VERSION;
927904
</script>
928905
</body>
929906
</html>

0 commit comments

Comments
 (0)