// Arcrun 桌面 App — 前端(t193) // // 全部畫面都在**同一個視窗**裡:狀態、清單、設定都用內嵌覆蓋層, // 不再像 fyne 版那樣「每個功能開一個小小的 popup」(leo 08-04 點破)。 import './style.css'; const go = window.go.main.App; const $ = (id) => document.getElementById(id); // 跟隨系統深淺色——CIS 兩套色票都定義好了,這裡只負責切 data-theme const mq = window.matchMedia('(prefers-color-scheme: dark)'); const applyTheme = () => document.documentElement.setAttribute('data-theme', mq.matches ? 'dark' : 'light'); mq.addEventListener('change', applyTheme); applyTheme(); // ── 覆蓋層(取代 popup 視窗)── function openSheet(html, wire) { $('sheet').innerHTML = html; $('overlay').classList.add('on'); if (wire) wire(); } function closeSheet() { $('overlay').classList.remove('on'); } $('overlay').addEventListener('click', (e) => { if (e.target.id === 'overlay') closeSheet(); }); document.addEventListener('keydown', (e) => { if (e.key === 'Escape') closeSheet(); }); const esc = (s) => String(s).replace(/[&<>"]/g, (c) => ({ '&': '&', '<': '<', '>': '>', '"': '"' }[c])); // ── 主畫面渲染 ── let state = null; function render(s) { state = s; $('ver').textContent = s.version ? '版本 ' + s.version : ''; $('statusBig').textContent = s.statusBig; $('statusBig').classList.toggle('syncing', !!s.syncing); $('statusSub').textContent = s.statusSub; const list = $('list'); if (!s.accounts || s.accounts.length === 0) { // 空狀態=onboarding,不是空白面板 list.innerHTML = `
先連上你的知識庫
Arcrun 會看守你指定的資料夾,
自動把文件整理成 AI 查得到的知識卡。
還沒有知識庫?先到 install.arcrun.dev 裝一個(免費)。
`; $('obConnect').onclick = showConnect; $('obInstall').onclick = () => go.OpenURL('https://install.arcrun.dev/'); return; } list.innerHTML = s.accounts.map((a) => `
${esc(a.name)}${esc(a.host)}
${(a.folders || []).map((f) => `
${esc(f.path)} 自動同步中
`).join('') || `
還沒有資料夾——按下面的「加入資料夾」
`} `).join(''); list.querySelectorAll('[data-rm]').forEach((b) => { b.onclick = () => confirmRemove(Number(b.dataset.acc), b.dataset.rm); }); } async function tick() { try { render(await go.GetState()); } catch (e) { /* 後端還沒起來,下一輪再試 */ } } // ── 動作 ── $('btnSync').onclick = async () => { await go.SyncNow(); tick(); }; $('btnAddFolder').onclick = async () => { if (!state || !state.accounts.length) { showConnect(); return; } const p = await go.PickFolder(); // 系統原生面板(macOS powerbox 會授權) if (!p) return; await go.AddFolder(0, p); tick(); }; function confirmRemove(accIdx, path) { openSheet(`

移除這個資料夾?

「${esc(path)}」不再自動同步。
已經上傳的知識卡不會被刪除。

`, () => { $('c1').onclick = closeSheet; $('c2').onclick = async () => { await go.RemoveFolder(accIdx, path); closeSheet(); tick(); }; }); } function showConnect() { openSheet(`

連上你的知識庫

貼上你的知識庫網址,再輸入你在網站上設定的帳號密碼。

`, () => { $('c1').onclick = closeSheet; $('c2').onclick = async () => { const err = $('err'); try { await go.Connect($('u').value.trim(), $('e').value.trim(), $('p').value); closeSheet(); tick(); } catch (ex) { err.textContent = String(ex); err.style.display = 'block'; } }; }); } $('btnAddAccount').onclick = showConnect; $('btnAI').onclick = () => { const gem = state && state.engine === 'gemma'; openSheet(`

用哪個 AI 幫你整理文件?

`, () => { $('c1').onclick = closeSheet; $('c2').onclick = async () => { const useGemini = document.querySelector('input[name=ai]:checked').value === 'gemini'; const err = $('err'); try { await go.SetAI(useGemini, $('k').value.trim()); closeSheet(); tick(); } catch (ex) { err.textContent = String(ex); err.style.display = 'block'; } }; }); }; $('btnUpdate').onclick = () => go.OpenURL('https://rag.arcrun.dev/docs/use/update/'); tick(); setInterval(tick, 1000); // 每秒刷新 ⇒ 同步中看得到在動