179 lines
4.8 KiB
Svelte
179 lines
4.8 KiB
Svelte
<script>
|
|
import { t } from './i18n'
|
|
|
|
export let onRefresh = null
|
|
|
|
let info = null
|
|
let errorMsg = ''
|
|
|
|
function wailsCall(method, ...args) {
|
|
try {
|
|
if (window['go'] && window['go']['main'] && window['go']['main']['App']) {
|
|
const fn = window['go']['main']['App'][method]
|
|
if (typeof fn === 'function') return fn(...args)
|
|
}
|
|
} catch (e) { console.error('Wails error:', method, e) }
|
|
return Promise.reject(new Error('Wails not connected: ' + method))
|
|
}
|
|
|
|
async function load() {
|
|
try {
|
|
info = await wailsCall('GetVaultInfo')
|
|
} catch (e) { info = null }
|
|
}
|
|
|
|
load()
|
|
|
|
async function openVaultFolder() {
|
|
try { await wailsCall('OpenVaultFolder') } catch (e) { errorMsg = String(e) }
|
|
}
|
|
|
|
async function checkIntegrity() {
|
|
try {
|
|
const result = await wailsCall('VaultCheck')
|
|
if (result.healthy) {
|
|
errorMsg = 'Vault healthy'
|
|
} else {
|
|
errorMsg = 'Issues found: ' + (result.errors || []).join('; ')
|
|
}
|
|
} catch (e) { errorMsg = String(e) }
|
|
}
|
|
|
|
async function chooseVault() {
|
|
try {
|
|
const chosen = await wailsCall('PickDirectory')
|
|
if (!chosen) return
|
|
const status = await wailsCall('OpenVault', chosen)
|
|
if (status && status.status === 'ready') {
|
|
info = await wailsCall('GetVaultInfo')
|
|
if (onRefresh) onRefresh()
|
|
}
|
|
} catch (e) { errorMsg = String(e) }
|
|
}
|
|
|
|
function formatSize(bytes) {
|
|
if (!bytes) return '—'
|
|
if (bytes < 1024) return bytes + ' B'
|
|
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB'
|
|
return (bytes / (1024 * 1024)).toFixed(1) + ' MB'
|
|
}
|
|
</script>
|
|
|
|
<div class="settings-section">
|
|
<h2>{t('settings.workspace')}</h2>
|
|
<p class="section-desc">{t('settings.workspaceDesc')}</p>
|
|
|
|
{#if errorMsg}
|
|
<div class="notice">{errorMsg}</div>
|
|
{/if}
|
|
|
|
<div class="settings-card">
|
|
{#if info}
|
|
<div class="vault-info">
|
|
<div class="info-row">
|
|
<span class="info-label">{t('settings.vaultPath')}</span>
|
|
<span class="info-value mono">{info.path}</span>
|
|
</div>
|
|
<div class="info-row">
|
|
<span class="info-label">DB</span>
|
|
<span class="info-value mono small">{info.dbPath}</span>
|
|
</div>
|
|
{#if info.nodeCount !== undefined}
|
|
<div class="info-row">
|
|
<span class="info-label">Nodes</span>
|
|
<span class="info-value">{info.nodeCount}</span>
|
|
</div>
|
|
{/if}
|
|
{#if info.fileCount !== undefined}
|
|
<div class="info-row">
|
|
<span class="info-label">Files</span>
|
|
<span class="info-value">{info.fileCount}</span>
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
{:else}
|
|
<p class="no-data">{t('settings.noVaultInfo')}</p>
|
|
{/if}
|
|
</div>
|
|
|
|
<div class="workspace-actions">
|
|
<button class="btn" on:click={openVaultFolder}>{t('settings.openVault')}</button>
|
|
<button class="btn" on:click={chooseVault}>{t('settings.changeVault')}</button>
|
|
<button class="btn" on:click={checkIntegrity}>{t('settings.checkIntegrity')}</button>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
.settings-section {
|
|
padding: 1.5rem;
|
|
max-width: 600px;
|
|
}
|
|
.settings-section h2 {
|
|
margin: 0 0 0.25rem 0;
|
|
font-size: 1.2rem;
|
|
color: var(--text, #e0e0e0);
|
|
}
|
|
.section-desc {
|
|
color: var(--text-dim, #888);
|
|
font-size: 0.85rem;
|
|
margin-bottom: 1.25rem;
|
|
line-height: 1.4;
|
|
}
|
|
.settings-card {
|
|
background: var(--surface-alt, #1e1e30);
|
|
border: 1px solid var(--border, #2a2a3e);
|
|
border-radius: 8px;
|
|
padding: 1rem 1.25rem;
|
|
margin-bottom: 1rem;
|
|
}
|
|
.notice {
|
|
padding: 0.5rem 0.75rem;
|
|
margin-bottom: 0.75rem;
|
|
background: rgba(255, 107, 107, 0.1);
|
|
border: 1px solid rgba(255, 107, 107, 0.3);
|
|
border-radius: 6px;
|
|
color: #ff6b6b;
|
|
font-size: 0.85rem;
|
|
}
|
|
.vault-info {}
|
|
.info-row {
|
|
display: flex;
|
|
padding: 0.4rem 0;
|
|
border-bottom: 1px solid var(--border, #2a2a3e);
|
|
font-size: 0.9rem;
|
|
}
|
|
.info-row:last-child { border-bottom: none; }
|
|
.info-label {
|
|
width: 120px;
|
|
min-width: 120px;
|
|
color: var(--text-dim, #888);
|
|
}
|
|
.info-value { color: var(--text, #e0e0e0); word-break: break-all; }
|
|
.info-value.mono { font-family: monospace; font-size: 0.85rem; }
|
|
.info-value.small { font-size: 0.8rem; }
|
|
.workspace-actions {
|
|
display: flex;
|
|
gap: 0.5rem;
|
|
flex-wrap: wrap;
|
|
margin-top: 0.5rem;
|
|
}
|
|
.btn {
|
|
padding: 0.45rem 0.8rem;
|
|
border: 1px solid var(--border, #2a2a3e);
|
|
border-radius: 6px;
|
|
background: var(--surface-light, #232338);
|
|
color: var(--text, #e0e0e0);
|
|
font-size: 0.85rem;
|
|
cursor: pointer;
|
|
}
|
|
.btn:hover {
|
|
background: var(--accent, #4a7c59);
|
|
border-color: var(--accent, #4a7c59);
|
|
}
|
|
.no-data {
|
|
color: var(--text-dim, #888);
|
|
font-style: italic;
|
|
margin: 0;
|
|
}
|
|
</style>
|