fix(sources): preserve deep-linked provider selection

This commit is contained in:
joshpatra committed 2026-08-06 19:12:52 -04:00
1 parent d39ede8e32
commit b231769ddd
5 files changed
+16 -6

No files matched your search

@@ -11,12 +11,14 @@
providers,
administrator,
account = null,
initialProviderId = "",
onSaved,
}: {
open: boolean;
providers: ProviderDefinition[];
administrator: boolean;
account?: ProviderAccount | null;
initialProviderId?: string;
onSaved: (message: string) => void | Promise<void>;
} = $props();
@@ -30,7 +32,7 @@
);
$effect(() => {
if (open && !providerId && choices[0]) providerId = account?.providerId ?? choices[0].id;
if (open && choices[0]) providerId = account?.providerId || initialProviderId || choices[0].id;
if (!open) error = "";
});
+5 -4
View File
@@ -58,6 +58,7 @@
let feedback = $state("");
let action = $state("");
let connectOpen = $state(false);
let connectProviderId = $state("");
let appleDownloadOpen = $state(false);
let configureOpen = $state(false);
let accessOpen = $state(false);
@@ -352,7 +353,7 @@
<div><p class="eyebrow">Provider-neutral routing</p><h2>Sources</h2><p>Capabilities describe what a Source can do. Latency appears after a health or click-to-stream check reports timing.</p></div>
<div class="sources-heading-actions">
<button class="button-secondary" type="button" onclick={() => void refresh()}>Refresh</button>
{#if canManage}<button class="button-primary" type="button" onclick={() => connectOpen = true}>Connect Source</button>{/if}
{#if canManage}<button class="button-primary" type="button" onclick={() => { connectProviderId = ""; connectOpen = true; }}>Connect Source</button>{/if}
</div>
</header>
{#if feedback}<p class="action-feedback" role="status">{feedback}</p>{/if}
@@ -456,7 +457,7 @@
<tr><td colspan="7"><div class="compact-empty connections-empty">
<strong>{canManage ? "No Source accounts yet" : "Accounts are administrator-managed"}</strong>
<p>{canManage ? "Connect an account to activate personal or shared Source capabilities." : "Available shared Sources appear without exposing credentials."}</p>
{#if canManage}<button class="button-primary" type="button" onclick={() => connectOpen = true}>Connect Source</button>{/if}
{#if canManage}<button class="button-primary" type="button" onclick={() => { connectProviderId = ""; connectOpen = true; }}>Connect Source</button>{/if}
</div></td></tr>
{/each}
</tbody>
@@ -543,7 +544,7 @@
<button class="button-primary" type="button" onclick={() => { detailOpen = false; appleDownloadOpen = true; }}>Manage Apple Music - Gamdl</button>
{/if}
{#if accountSettings(selectedSource).length}
<button class="button-primary" type="button" onclick={() => { detailOpen = false; connectOpen = true; }}>Connect account</button>
<button class="button-primary" type="button" onclick={() => { connectProviderId = selectedSource!.id; detailOpen = false; connectOpen = true; }}>Connect account</button>
{:else if selectedSource.connectionKind !== "operator_managed"}
<p>No account configuration is required for this extension capability.</p>
{/if}
@@ -615,7 +616,7 @@
</Dialog.Portal>
</Dialog.Root>
<ConnectSourceDialog bind:open={connectOpen} {providers} {administrator} onSaved={completed} />
<ConnectSourceDialog bind:open={connectOpen} {providers} {administrator} initialProviderId={connectProviderId} onSaved={completed} />
<ConnectSourceDialog bind:open={configureOpen} {providers} {administrator} account={selectedAccount} onSaved={completed} />
<AppleDownloadDialog bind:open={appleDownloadOpen} />
<AccountAccessDialog bind:open={accessOpen} account={selectedAccount} users={audienceUsers} onSaved={completed} />
+1
View File
@@ -29,6 +29,7 @@ const provider: ProviderDefinition = { id: "future-extension", name: "Future Ext
describe("source presentation", () => {
it("humanizes camel-case lifecycle labels", () => {
expect(humanize("reviewRequired")).toBe("Review Required");
expect(humanize("reviewrequired")).toBe("Review Required");
});
it("uses manifest defaults without exposing sensitive values", () => {
+1 -1
View File
@@ -8,7 +8,7 @@ import type {
} from "./api";
export const humanize = (value: string) =>
value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replaceAll("_", " ").replaceAll("-", " ")
value.replace(/reviewrequired/gi, "review required").replace(/([a-z0-9])([A-Z])/g, "$1 $2").replaceAll("_", " ").replaceAll("-", " ")
.replace(/\b\w/g, (character) => character.toUpperCase());
export function audienceLabel(account: ProviderAccount) {
+6
View File
@@ -766,6 +766,12 @@ for (const viewport of viewports) {
await page.keyboard.press("Escape");
await page.goto("#/settings/accounts");
await expect(page.getByRole("heading", { name: "Sources", level: 1 })).toBeVisible();
await page.goto("#/sources?source=lumen-audio&section=configuration");
await page.getByRole("button", { name: "Connect account" }).click();
const sourceDialog = page.getByRole("dialog", { name: "Connect a Source" });
await expect(sourceDialog.getByRole("button", { name: "Source", exact: true })).toContainText("Lumen Audio");
await expect(sourceDialog.getByLabel("Access token")).toHaveValue("");
await sourceDialog.getByRole("button", { name: "Cancel" }).click();
await page.goto("#/settings/routing");
await expect(page.getByText("Local · fixed")).toBeVisible();
await expect(page.getByRole("button", { name: "Move Jellyfin up" })).toHaveCount(0);