Feat: Manual Binary-Selection (CSS-WIP) (#91)

This commit is contained in:
Youwes09
2026-05-21 14:37:53 -05:00
parent 3dad4bc729
commit da788e90ba
6 changed files with 258 additions and 193 deletions
@@ -1,6 +1,7 @@
<script lang="ts">
import { store, updateSettings } from "@store/state.svelte";
import { selectPortal } from "@core/actions/selectPortal";
import { invoke } from "@tauri-apps/api/core";
interface Props {
selectOpen: string | null;
@@ -12,6 +13,12 @@
let { selectOpen, closingSelect, toggleSelect, anims }: Props = $props();
let triggerIdleTimeout = $state<HTMLButtonElement>(null!);
let serverAdvancedOpen = $state(false);
async function pickServerBinary() {
const picked = await invoke<string | null>("pick_server_binary");
if (picked) updateSettings({ serverBinary: picked });
}
</script>
<div class="s-panel">
@@ -43,18 +50,70 @@
<div class="s-section">
<p class="s-section-title">Server</p>
<div class="s-section-body">
<div class="s-row">
<div class="s-row-info"><span class="s-label">Server URL</span><span class="s-desc">Base URL of your Suwayomi instance</span></div>
<input class="s-input" value={store.settings.serverUrl ?? "http://localhost:4567"} oninput={(e) => updateSettings({ serverUrl: e.currentTarget.value })} placeholder="http://localhost:4567" spellcheck="false" />
<div class="s-row-info">
<span class="s-label">Server URL</span>
<span class="s-desc">Base URL of your Suwayomi instance</span>
</div>
<div class="srv-url-group">
<input class="s-input" value={store.settings.serverUrl ?? "http://localhost:4567"}
oninput={(e) => updateSettings({ serverUrl: e.currentTarget.value })}
placeholder="http://localhost:4567" spellcheck="false" />
<button
class="srv-adv-btn"
class:open={serverAdvancedOpen}
onclick={() => serverAdvancedOpen = !serverAdvancedOpen}
title="Server launch options"
aria-expanded={serverAdvancedOpen}
>
<svg width="10" height="6" viewBox="0 0 10 6" fill="none">
<path d="M1 1l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
</div>
</div>
<label class="s-row">
<div class="s-row-info"><span class="s-label">Auto-start server</span><span class="s-desc">Launch tachidesk-server when Moku opens</span></div>
<button role="switch" aria-checked={store.settings.autoStartServer} aria-label="Auto-start server" class="s-toggle" class:on={store.settings.autoStartServer} onclick={() => updateSettings({ autoStartServer: !store.settings.autoStartServer })}><span class="s-toggle-thumb"></span></button>
<button role="switch" aria-checked={store.settings.autoStartServer} aria-label="Auto-start server"
class="s-toggle" class:on={store.settings.autoStartServer}
onclick={() => updateSettings({ autoStartServer: !store.settings.autoStartServer })}>
<span class="s-toggle-thumb"></span>
</button>
</label>
<label class="s-row">
<div class="s-row-info"><span class="s-label">Suwayomi Web UI</span><span class="s-desc">Enable the built-in Suwayomi web interface alongside Moku</span></div>
<button role="switch" aria-checked={store.settings.suwayomiWebUI ?? false} aria-label="Suwayomi Web UI" class="s-toggle" class:on={store.settings.suwayomiWebUI ?? false} onclick={() => updateSettings({ suwayomiWebUI: !(store.settings.suwayomiWebUI ?? false) })}><span class="s-toggle-thumb"></span></button>
<button role="switch" aria-checked={store.settings.suwayomiWebUI ?? false} aria-label="Suwayomi Web UI"
class="s-toggle" class:on={store.settings.suwayomiWebUI ?? false}
onclick={() => updateSettings({ suwayomiWebUI: !(store.settings.suwayomiWebUI ?? false) })}>
<span class="s-toggle-thumb"></span>
</button>
</label>
{#if serverAdvancedOpen}
<div class="srv-adv-panel">
<div class="srv-adv-row">
<div class="s-row-info">
<span class="s-label">Server binary</span>
<span class="s-desc">Path to server executable — leave blank to use bundled</span>
</div>
<div class="srv-file-group">
<input class="s-input srv-path-input" value={store.settings.serverBinary ?? ""}
oninput={(e) => updateSettings({ serverBinary: e.currentTarget.value })}
placeholder="auto-detect" spellcheck="false" />
<button class="srv-file-btn" onclick={pickServerBinary} title="Browse">
<svg width="14" height="14" viewBox="0 0 14 14" fill="none">
<path d="M1.5 4.5h11v7a1 1 0 01-1 1h-9a1 1 0 01-1-1v-7z" stroke="currentColor" stroke-width="1.3" stroke-linejoin="round"/>
<path d="M1.5 4.5l1.8-2.5h3.4l1.3 2.5" stroke="currentColor" stroke-width="1.3" stroke-linejoin="round"/>
</svg>
</button>
</div>
</div>
</div>
{/if}
</div>
</div>
@@ -87,7 +146,7 @@
<div class="s-row-info"><span class="s-label">Close button behavior</span><span class="s-desc">What happens when you click the X button</span></div>
<div class="s-seg">
{#each [["ask","Ask"],["tray","Tray"],["quit","Quit"]] as [v, l]}
<button class="s-seg-btn" class:active={( store.settings.closeAction ?? "ask") === v} onclick={() => updateSettings({ closeAction: v as "ask" | "tray" | "quit" })}>{l}</button>
<button class="s-seg-btn" class:active={(store.settings.closeAction ?? "ask") === v} onclick={() => updateSettings({ closeAction: v as "ask" | "tray" | "quit" })}>{l}</button>
{/each}
</div>
</div>
@@ -137,4 +196,70 @@
.s-seg-btn:not(:last-child) { border-right: 1px solid var(--border-strong); }
.s-seg-btn.active { background: var(--accent-muted); color: var(--accent-fg); }
.s-seg-btn:not(.active):hover { background: var(--bg-raised); color: var(--text-secondary); }
.srv-url-group {
display: flex;
align-items: center;
gap: 6px;
flex-shrink: 0;
}
.srv-adv-btn {
display: flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
flex-shrink: 0;
border-radius: var(--radius-md);
border: 1px solid var(--border-dim);
background: var(--bg-surface);
color: var(--text-faint);
cursor: pointer;
transition: background var(--t-base), color var(--t-base), border-color var(--t-base);
}
.srv-adv-btn:hover { background: var(--bg-overlay); color: var(--text-muted); border-color: var(--border-strong); }
.srv-adv-btn.open { background: var(--bg-overlay); color: var(--text-secondary); border-color: var(--border-strong); }
.srv-adv-btn svg { transition: transform var(--t-base); }
.srv-adv-btn.open svg { transform: rotate(180deg); }
.srv-adv-panel {
border-top: 1px solid var(--border-dim);
background: var(--bg-base);
}
.srv-adv-row {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px var(--sp-4);
gap: var(--sp-4);
}
.srv-file-group {
display: flex;
align-items: center;
gap: 6px;
flex-shrink: 0;
}
.srv-path-input {
width: 160px;
}
.srv-file-btn {
display: flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
flex-shrink: 0;
border-radius: var(--radius-md);
border: 1px solid var(--border-dim);
background: var(--bg-surface);
color: var(--text-faint);
cursor: pointer;
transition: background var(--t-base), color var(--t-base), border-color var(--t-base);
}
.srv-file-btn:hover { background: var(--bg-overlay); color: var(--text-muted); border-color: var(--border-strong); }
</style>