v1.2 - collections, etc
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
export let config = { embyUrl: '', apiKey: '', dbPath: '' };
|
||||
export let config = { embyUrl: '', apiKey: '', tmdbApiKey: '', dbPath: '' };
|
||||
|
||||
let localConfig = { ...config };
|
||||
let status = '';
|
||||
@@ -14,6 +14,19 @@
|
||||
statusType = type;
|
||||
}
|
||||
|
||||
async function fetchEmbyUsers() {
|
||||
const res = await fetch('/api/emby-users');
|
||||
if (!res.ok) {
|
||||
const err = await res.json().catch(() => ({ message: res.statusText }));
|
||||
throw new Error(err.message || res.statusText);
|
||||
}
|
||||
|
||||
const payload = await res.json();
|
||||
return Array.isArray(payload)
|
||||
? { users: payload, source: 'live', lastSyncedAt: null, message: '' }
|
||||
: payload;
|
||||
}
|
||||
|
||||
async function saveConfig() {
|
||||
busy = true;
|
||||
setStatus('Saving…');
|
||||
@@ -48,13 +61,15 @@
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(localConfig)
|
||||
});
|
||||
const res = await fetch('/api/emby-users');
|
||||
if (!res.ok) {
|
||||
const err = await res.json().catch(() => ({ message: res.statusText }));
|
||||
throw new Error(err.message || res.statusText);
|
||||
const payload = await fetchEmbyUsers();
|
||||
if (payload.source === 'cache') {
|
||||
setStatus(
|
||||
`${payload.message} Loaded ${payload.users.length} cached users from ${payload.lastSyncedAt || 'the last successful sync'}.`,
|
||||
'ok'
|
||||
);
|
||||
} else {
|
||||
setStatus(`Connected — ${payload.users.length} users found and cached locally.`, 'ok');
|
||||
}
|
||||
const users = await res.json();
|
||||
setStatus(`Connected — ${users.length} users found.`, 'ok');
|
||||
} catch (e) {
|
||||
setStatus(`Connection failed: ${e.message}`, 'error');
|
||||
} finally {
|
||||
@@ -66,14 +81,16 @@
|
||||
busy = true;
|
||||
setStatus('Fetching user names from Emby…');
|
||||
try {
|
||||
const res = await fetch('/api/emby-users');
|
||||
if (!res.ok) {
|
||||
const err = await res.json().catch(() => ({ message: res.statusText }));
|
||||
throw new Error(err.message || res.statusText);
|
||||
const payload = await fetchEmbyUsers();
|
||||
dispatch('namesRefreshed', payload);
|
||||
if (payload.source === 'cache') {
|
||||
setStatus(
|
||||
`${payload.message} Refreshed ${payload.users.length} users from the local cache.`,
|
||||
'ok'
|
||||
);
|
||||
} else {
|
||||
setStatus(`Names refreshed — ${payload.users.length} users from Emby and saved locally.`, 'ok');
|
||||
}
|
||||
const embyUsers = await res.json();
|
||||
dispatch('namesRefreshed', embyUsers);
|
||||
setStatus(`Names refreshed — ${embyUsers.length} users from Emby.`, 'ok');
|
||||
} catch (e) {
|
||||
setStatus(`Failed: ${e.message}`, 'error');
|
||||
} finally {
|
||||
@@ -148,6 +165,25 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h4>Recommendations</h4>
|
||||
<label>
|
||||
<span>TMDB API key</span>
|
||||
<input
|
||||
type="password"
|
||||
bind:value={localConfig.tmdbApiKey}
|
||||
placeholder="Paste your TMDB v3 API key"
|
||||
/>
|
||||
</label>
|
||||
<p class="hint">
|
||||
Stored locally in the app config so recommendation features can reuse it without re-entering
|
||||
the key each time.
|
||||
</p>
|
||||
<div class="row">
|
||||
<button class="btn ghost" on:click={saveConfig} disabled={busy}>Save TMDB key</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h4>Database file</h4>
|
||||
<label>
|
||||
@@ -182,9 +218,9 @@
|
||||
padding: 0 4px;
|
||||
}
|
||||
h3 {
|
||||
font-size: 15px;
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
margin: 0 0 16px;
|
||||
margin: 0 0 18px;
|
||||
color: var(--text);
|
||||
}
|
||||
h4 {
|
||||
@@ -196,12 +232,15 @@
|
||||
margin: 0 0 10px;
|
||||
}
|
||||
section {
|
||||
margin-bottom: 24px;
|
||||
padding-bottom: 20px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
margin-bottom: 18px;
|
||||
padding: 16px;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 18px;
|
||||
background: var(--surface);
|
||||
box-shadow: 0 16px 32px rgba(0, 0, 0, 0.16);
|
||||
}
|
||||
section:last-of-type {
|
||||
border-bottom: none;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
label {
|
||||
display: flex;
|
||||
@@ -215,10 +254,10 @@
|
||||
font-weight: 500;
|
||||
}
|
||||
input {
|
||||
background: var(--bg);
|
||||
background: #0b0f14;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 6px;
|
||||
padding: 7px 10px;
|
||||
border-radius: 12px;
|
||||
padding: 10px 12px;
|
||||
font-size: 13px;
|
||||
color: var(--text);
|
||||
font-family: inherit;
|
||||
@@ -227,7 +266,7 @@
|
||||
}
|
||||
input:focus {
|
||||
outline: none;
|
||||
border-color: var(--accent);
|
||||
border-color: var(--border-strong);
|
||||
}
|
||||
.hint {
|
||||
font-size: 11px;
|
||||
@@ -237,9 +276,9 @@
|
||||
}
|
||||
code {
|
||||
font-size: 11px;
|
||||
background: var(--bg);
|
||||
padding: 1px 4px;
|
||||
border-radius: 3px;
|
||||
background: #0b0f14;
|
||||
padding: 2px 5px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
.row {
|
||||
display: flex;
|
||||
@@ -249,16 +288,17 @@
|
||||
.btn {
|
||||
all: unset;
|
||||
cursor: pointer;
|
||||
padding: 6px 14px;
|
||||
border-radius: 6px;
|
||||
padding: 9px 14px;
|
||||
border-radius: 12px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
font-family: inherit;
|
||||
transition: all 0.12s;
|
||||
}
|
||||
.btn.ghost {
|
||||
color: var(--text-muted);
|
||||
color: #d9e7f8;
|
||||
border: 1px solid var(--border);
|
||||
background: var(--bg-secondary);
|
||||
}
|
||||
.btn.ghost:hover:not(:disabled) {
|
||||
background: var(--surface-hover);
|
||||
@@ -277,10 +317,10 @@
|
||||
}
|
||||
.status {
|
||||
margin-top: 8px;
|
||||
padding: 8px 12px;
|
||||
border-radius: 6px;
|
||||
padding: 10px 12px;
|
||||
border-radius: 14px;
|
||||
font-size: 12px;
|
||||
background: var(--surface-hover);
|
||||
background: var(--surface);
|
||||
color: var(--text-muted);
|
||||
border-left: 3px solid var(--border);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user