fix(devices): pairing input moves into the Add Device modal
The pairing field sat at the bottom of the Devices page, below the device grid — unreachable on any account with more than a screenful of devices (the user's dev account has ~480 accumulated test devices; scrolling 224k px to reach the field is a non-starter). The Add Device button at the top of the page is where pairing intent already lives, so the code input and Find device button now sit inside the Connect a KOReader Device modal as instruction step 6, with the confirm card swapping into the same modal (container keeps the pairing-lookup ids; the htmx error-toast listener scopes to #add-device-modal now). Verified live: modal renders the full instruction list + input, a wrong code swaps the templ error partial inside the modal, and claim still HX-Refreshes on success (modal state resets with the reload, paired device appears in the grid). ui-controls glossary where-fields and the COVERAGE row updated with the control's new home.
This commit is contained in:
1 parent
5211edf264
commit
d15f115505
5 files changed
+47
-55
No files matched your search
@@ -183,11 +183,11 @@ where: All Books / Podcasts page → toolbar
|
|||||||
does: Opens the filter drawer for building and applying rules.
|
does: Opens the filter drawer for building and applying rules.
|
||||||
|
|
||||||
label: Find device
|
label: Find device
|
||||||
where: Devices page → Pair a Device
|
where: Devices page → Add New Device modal
|
||||||
does: Looks up the pairing code shown on the registering e-reader and renders the confirm card.
|
does: Looks up the pairing code shown on the registering e-reader and renders the confirm card.
|
||||||
|
|
||||||
label: Pair device
|
label: Pair device
|
||||||
where: Devices page → Pair a Device → confirm card
|
where: Devices page → Add New Device modal → confirm card
|
||||||
does: Binds the device behind the pairing code to the signed-in account.
|
does: Binds the device behind the pairing code to the signed-in account.
|
||||||
|
|
||||||
label: Download All
|
label: Download All
|
||||||
|
|||||||
+20
-28
@@ -157,33 +157,6 @@ templ Devices(user User, devices []handlers.DeviceInfo, errorMessage string, bas
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div id="pairing-section" class="mt-12">
|
|
||||||
<h2 class="text-lg font-bold tracking-tight mb-1" style="color: var(--text-primary)">Pair a Device</h2>
|
|
||||||
<p class="text-sm mb-3" style="color: var(--text-secondary)">
|
|
||||||
On your e-reader, open the Bookhoard sync menu and tap <strong>Register device</strong> — then enter the
|
|
||||||
6-digit code it shows below. Only someone holding the device can see the code, so nobody
|
|
||||||
else can claim (or interfere with) your registration.
|
|
||||||
</p>
|
|
||||||
<form hx-post="/devices/pairing/lookup" hx-target="#pairing-lookup-result" hx-swap="innerHTML" class="flex items-center gap-2 flex-wrap">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
name="pairing_code"
|
|
||||||
inputmode="numeric"
|
|
||||||
maxlength="7"
|
|
||||||
pattern="[0-9 ]*"
|
|
||||||
autocomplete="off"
|
|
||||||
placeholder="e.g. 583 912"
|
|
||||||
required
|
|
||||||
class="input max-w-44 font-mono text-base tracking-widest"
|
|
||||||
aria-label="Pairing code"
|
|
||||||
/>
|
|
||||||
<button type="submit" class="btn btn-primary text-sm">
|
|
||||||
@Icon("search", "h-4 w-4")
|
|
||||||
Find device
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
<div id="pairing-lookup-result" class="mt-2" aria-live="polite"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div id="add-device-modal" class="hidden fixed inset-0 z-50 flex items-center justify-center p-4" style="background-color: var(--surface-overlay);">
|
<div id="add-device-modal" class="hidden fixed inset-0 z-50 flex items-center justify-center p-4" style="background-color: var(--surface-overlay);">
|
||||||
<div class="card p-6 w-full max-w-md" style="box-shadow: var(--shadow-pop);">
|
<div class="card p-6 w-full max-w-md" style="box-shadow: var(--shadow-pop);">
|
||||||
@@ -233,9 +206,28 @@ templ Devices(user User, devices []handlers.DeviceInfo, errorMessage string, bas
|
|||||||
</li>
|
</li>
|
||||||
<li class="flex gap-3">
|
<li class="flex gap-3">
|
||||||
<span class="flex-shrink-0 grid place-items-center h-5 w-5 rounded-full text-xs font-bold" style="background-color: var(--accent-muted); color: var(--accent);">6</span>
|
<span class="flex-shrink-0 grid place-items-center h-5 w-5 rounded-full text-xs font-bold" style="background-color: var(--accent-muted); color: var(--accent);">6</span>
|
||||||
<span>Type that code into the <strong>Pair a Device</strong> field on this page and confirm — the device finishes connecting by itself.</span>
|
<span>Enter the code below and click <strong>Find device</strong>, then confirm on the card that appears — the device finishes connecting by itself.</span>
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
<form hx-post="/devices/pairing/lookup" hx-target="#pairing-lookup-result" hx-swap="innerHTML" class="flex items-center gap-2 flex-wrap">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="pairing_code"
|
||||||
|
inputmode="numeric"
|
||||||
|
maxlength="7"
|
||||||
|
pattern="[0-9 ]*"
|
||||||
|
autocomplete="off"
|
||||||
|
placeholder="e.g. 583 912"
|
||||||
|
required
|
||||||
|
class="input max-w-44 font-mono text-base tracking-widest"
|
||||||
|
aria-label="Pairing code"
|
||||||
|
/>
|
||||||
|
<button type="submit" class="btn btn-primary text-sm">
|
||||||
|
@Icon("search", "h-4 w-4")
|
||||||
|
Find device
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
<div id="pairing-lookup-result" aria-live="polite"></div>
|
||||||
<div class="rounded-md p-3 text-xs flex items-start gap-2" style="background-color: var(--accent-muted); color: var(--text-secondary);">
|
<div class="rounded-md p-3 text-xs flex items-start gap-2" style="background-color: var(--accent-muted); color: var(--text-secondary);">
|
||||||
@Icon("info", "h-4 w-4 flex-shrink-0 mt-0.5")
|
@Icon("info", "h-4 w-4 flex-shrink-0 mt-0.5")
|
||||||
<span>Only someone holding the device can read the code, so only the right account can claim it. Codes expire after 5 minutes.</span>
|
<span>Only someone holding the device can read the code, so only the right account can claim it. Codes expire after 5 minutes.</span>
|
||||||
|
|||||||
+19
-19
@@ -406,15 +406,7 @@ func Devices(user User, devices []handlers.DeviceInfo, errorMessage string, base
|
|||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "</div><div id=\"pairing-section\" class=\"mt-12\"><h2 class=\"text-lg font-bold tracking-tight mb-1\" style=\"color: var(--text-primary)\">Pair a Device</h2><p class=\"text-sm mb-3\" style=\"color: var(--text-secondary)\">On your e-reader, open the Bookhoard sync menu and tap <strong>Register device</strong> — then enter the 6-digit code it shows below. Only someone holding the device can see the code, so nobody else can claim (or interfere with) your registration.</p><form hx-post=\"/devices/pairing/lookup\" hx-target=\"#pairing-lookup-result\" hx-swap=\"innerHTML\" class=\"flex items-center gap-2 flex-wrap\"><input type=\"text\" name=\"pairing_code\" inputmode=\"numeric\" maxlength=\"7\" pattern=\"[0-9 ]*\" autocomplete=\"off\" placeholder=\"e.g. 583 912\" required class=\"input max-w-44 font-mono text-base tracking-widest\" aria-label=\"Pairing code\"> <button type=\"submit\" class=\"btn btn-primary text-sm\">")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 43, "</div></div><div id=\"add-device-modal\" class=\"hidden fixed inset-0 z-50 flex items-center justify-center p-4\" style=\"background-color: var(--surface-overlay);\"><div class=\"card p-6 w-full max-w-md\" style=\"box-shadow: var(--shadow-pop);\"><div class=\"flex justify-between items-center mb-6\"><h2 class=\"text-xl font-bold\" style=\"color: var(--text-primary)\">Connect a KOReader Device</h2><button @click=\"hideAddDeviceModal()\" class=\"icon-btn\" aria-label=\"Close\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = Icon("search", "h-4 w-4").Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "Find device</button></form><div id=\"pairing-lookup-result\" class=\"mt-2\" aria-live=\"polite\"></div></div></div><div id=\"add-device-modal\" class=\"hidden fixed inset-0 z-50 flex items-center justify-center p-4\" style=\"background-color: var(--surface-overlay);\"><div class=\"card p-6 w-full max-w-md\" style=\"box-shadow: var(--shadow-pop);\"><div class=\"flex justify-between items-center mb-6\"><h2 class=\"text-xl font-bold\" style=\"color: var(--text-primary)\">Connect a KOReader Device</h2><button @click=\"hideAddDeviceModal()\" class=\"icon-btn\" aria-label=\"Close\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@@ -422,7 +414,7 @@ func Devices(user User, devices []handlers.DeviceInfo, errorMessage string, base
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "</button></div><div class=\"space-y-4\"><div class=\"rounded-lg p-4 space-y-4\" style=\"background-color: var(--surface-secondary);\"><h3 class=\"text-sm font-semibold flex items-center gap-2\" style=\"color: var(--text-primary)\">")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 44, "</button></div><div class=\"space-y-4\"><div class=\"rounded-lg p-4 space-y-4\" style=\"background-color: var(--surface-secondary);\"><h3 class=\"text-sm font-semibold flex items-center gap-2\" style=\"color: var(--text-primary)\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@@ -430,33 +422,33 @@ func Devices(user User, devices []handlers.DeviceInfo, errorMessage string, base
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "KOReader Plugin Setup</h3><ol class=\"space-y-3 text-sm\" style=\"color: var(--text-secondary)\"><li class=\"flex gap-3\"><span class=\"flex-shrink-0 grid place-items-center h-5 w-5 rounded-full text-xs font-bold\" style=\"background-color: var(--accent-muted); color: var(--accent);\">1</span> <span>Clone the <a href=\"https://git.linuxhg.com/Bookhoard/bookhoard.koplugin\" class=\"underline\" style=\"color: var(--accent);\">Bookhoard plugin</a> to your KOReader <code class=\"px-1 py-0.5 rounded\" style=\"background-color: var(--bg-primary);\">plugins/</code> directory</span></li><li class=\"flex gap-3\"><span class=\"flex-shrink-0 grid place-items-center h-5 w-5 rounded-full text-xs font-bold\" style=\"background-color: var(--accent-muted); color: var(--accent);\">2</span> <span>Open KOReader, tap the <strong>wrench icon</strong> at the top</span></li><li class=\"flex gap-3\"><span class=\"flex-shrink-0 grid place-items-center h-5 w-5 rounded-full text-xs font-bold\" style=\"background-color: var(--accent-muted); color: var(--accent);\">3</span> <span>Find and tap <strong>Bookhoard sync</strong></span></li><li class=\"flex gap-3\"><span class=\"flex-shrink-0 grid place-items-center h-5 w-5 rounded-full text-xs font-bold\" style=\"background-color: var(--accent-muted); color: var(--accent);\">4</span> <span>Tap <strong>Server URL</strong>, enter your server address, then tap <strong>OK</strong>:</span></li><li class=\"ml-8\"><div class=\"flex items-center gap-2\"><code class=\"text-xs px-2 py-1 rounded font-mono flex-1\" style=\"background-color: var(--bg-primary); color: var(--text-primary);\">")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 45, "KOReader Plugin Setup</h3><ol class=\"space-y-3 text-sm\" style=\"color: var(--text-secondary)\"><li class=\"flex gap-3\"><span class=\"flex-shrink-0 grid place-items-center h-5 w-5 rounded-full text-xs font-bold\" style=\"background-color: var(--accent-muted); color: var(--accent);\">1</span> <span>Clone the <a href=\"https://git.linuxhg.com/Bookhoard/bookhoard.koplugin\" class=\"underline\" style=\"color: var(--accent);\">Bookhoard plugin</a> to your KOReader <code class=\"px-1 py-0.5 rounded\" style=\"background-color: var(--bg-primary);\">plugins/</code> directory</span></li><li class=\"flex gap-3\"><span class=\"flex-shrink-0 grid place-items-center h-5 w-5 rounded-full text-xs font-bold\" style=\"background-color: var(--accent-muted); color: var(--accent);\">2</span> <span>Open KOReader, tap the <strong>wrench icon</strong> at the top</span></li><li class=\"flex gap-3\"><span class=\"flex-shrink-0 grid place-items-center h-5 w-5 rounded-full text-xs font-bold\" style=\"background-color: var(--accent-muted); color: var(--accent);\">3</span> <span>Find and tap <strong>Bookhoard sync</strong></span></li><li class=\"flex gap-3\"><span class=\"flex-shrink-0 grid place-items-center h-5 w-5 rounded-full text-xs font-bold\" style=\"background-color: var(--accent-muted); color: var(--accent);\">4</span> <span>Tap <strong>Server URL</strong>, enter your server address, then tap <strong>OK</strong>:</span></li><li class=\"ml-8\"><div class=\"flex items-center gap-2\"><code class=\"text-xs px-2 py-1 rounded font-mono flex-1\" style=\"background-color: var(--bg-primary); color: var(--text-primary);\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var17 string
|
var templ_7745c5c3_Var17 string
|
||||||
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(baseURL)
|
templ_7745c5c3_Var17, templ_7745c5c3_Err = templ.JoinStringErrs(baseURL)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `devices.templ`, Line: 221, Col: 148}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `devices.templ`, Line: 194, Col: 148}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var17))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "</code> <button @click=\"")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 46, "</code> <button @click=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var18 string
|
var templ_7745c5c3_Var18 string
|
||||||
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.ResolveAttributeValue("copyToClipboard('" + baseURL + "', 'Server URL')")
|
templ_7745c5c3_Var18, templ_7745c5c3_Err = templ.ResolveAttributeValue("copyToClipboard('" + baseURL + "', 'Server URL')")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `devices.templ`, Line: 223, Col: 68}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `devices.templ`, Line: 196, Col: 68}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var18)
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var18)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "\" class=\"btn btn-secondary text-xs px-3\">")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 47, "\" class=\"btn btn-secondary text-xs px-3\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@@ -464,7 +456,15 @@ func Devices(user User, devices []handlers.DeviceInfo, errorMessage string, base
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "</button></div></li><li class=\"flex gap-3\"><span class=\"flex-shrink-0 grid place-items-center h-5 w-5 rounded-full text-xs font-bold\" style=\"background-color: var(--accent-muted); color: var(--accent);\">5</span> <span>Tap <strong>Register device</strong> — your e-reader shows a <strong>6-digit pairing code</strong>.</span></li><li class=\"flex gap-3\"><span class=\"flex-shrink-0 grid place-items-center h-5 w-5 rounded-full text-xs font-bold\" style=\"background-color: var(--accent-muted); color: var(--accent);\">6</span> <span>Type that code into the <strong>Pair a Device</strong> field on this page and confirm — the device finishes connecting by itself.</span></li></ol><div class=\"rounded-md p-3 text-xs flex items-start gap-2\" style=\"background-color: var(--accent-muted); color: var(--text-secondary);\">")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 48, "</button></div></li><li class=\"flex gap-3\"><span class=\"flex-shrink-0 grid place-items-center h-5 w-5 rounded-full text-xs font-bold\" style=\"background-color: var(--accent-muted); color: var(--accent);\">5</span> <span>Tap <strong>Register device</strong> — your e-reader shows a <strong>6-digit pairing code</strong>.</span></li><li class=\"flex gap-3\"><span class=\"flex-shrink-0 grid place-items-center h-5 w-5 rounded-full text-xs font-bold\" style=\"background-color: var(--accent-muted); color: var(--accent);\">6</span> <span>Enter the code below and click <strong>Find device</strong>, then confirm on the card that appears — the device finishes connecting by itself.</span></li></ol><form hx-post=\"/devices/pairing/lookup\" hx-target=\"#pairing-lookup-result\" hx-swap=\"innerHTML\" class=\"flex items-center gap-2 flex-wrap\"><input type=\"text\" name=\"pairing_code\" inputmode=\"numeric\" maxlength=\"7\" pattern=\"[0-9 ]*\" autocomplete=\"off\" placeholder=\"e.g. 583 912\" required class=\"input max-w-44 font-mono text-base tracking-widest\" aria-label=\"Pairing code\"> <button type=\"submit\" class=\"btn btn-primary text-sm\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = Icon("search", "h-4 w-4").Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 49, "Find device</button></form><div id=\"pairing-lookup-result\" aria-live=\"polite\"></div><div class=\"rounded-md p-3 text-xs flex items-start gap-2\" style=\"background-color: var(--accent-muted); color: var(--text-secondary);\">")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@@ -552,7 +552,7 @@ func PairingLookupResult(deviceName string, deviceType string, pairingCode strin
|
|||||||
var templ_7745c5c3_Var20 string
|
var templ_7745c5c3_Var20 string
|
||||||
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(deviceName)
|
templ_7745c5c3_Var20, templ_7745c5c3_Err = templ.JoinStringErrs(deviceName)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `devices.templ`, Line: 462, Col: 84}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `devices.templ`, Line: 454, Col: 84}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var20))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -565,7 +565,7 @@ func PairingLookupResult(deviceName string, deviceType string, pairingCode strin
|
|||||||
var templ_7745c5c3_Var21 string
|
var templ_7745c5c3_Var21 string
|
||||||
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(deviceType)
|
templ_7745c5c3_Var21, templ_7745c5c3_Err = templ.JoinStringErrs(deviceType)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `devices.templ`, Line: 464, Col: 17}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `devices.templ`, Line: 456, Col: 17}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var21))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -578,7 +578,7 @@ func PairingLookupResult(deviceName string, deviceType string, pairingCode strin
|
|||||||
var templ_7745c5c3_Var22 string
|
var templ_7745c5c3_Var22 string
|
||||||
templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.ResolveAttributeValue(pairingCode)
|
templ_7745c5c3_Var22, templ_7745c5c3_Err = templ.ResolveAttributeValue(pairingCode)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `devices.templ`, Line: 468, Col: 64}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `devices.templ`, Line: 460, Col: 64}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var22)
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var22)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ Gate: every line below executes for BOTH personas unless marked
|
|||||||
| 21 | Podcasts: cross-user invisibility — own feed only (RLS §20 surfaces) | 🔲 | 🔲 |
|
| 21 | Podcasts: cross-user invisibility — own feed only (RLS §20 surfaces) | 🔲 | 🔲 |
|
||||||
| 22 | Podcasts: order selector re-renders episode list; serial suggestion shown only for serial/audiobook feeds | 🔲 | 🔲 |
|
| 22 | Podcasts: order selector re-renders episode list; serial suggestion shown only for serial/audiobook feeds | 🔲 | 🔲 |
|
||||||
| 23 | Podcasts: audio reader "Ep N/M" + prev/next episode; chain-advance to next episode | 🔲 | 🔲 |
|
| 23 | Podcasts: audio reader "Ep N/M" + prev/next episode; chain-advance to next episode | 🔲 | 🔲 |
|
||||||
| 24 | Devices: Pair a Device — code lookup renders templ confirm card, claim binds + page refresh; wrong/expired code renders inline error partial (not a toast-only path) | 🔲 | 🔲 (registration invisible by design) |
|
| 24 | Devices: Add New Device modal — pairing-code lookup renders templ confirm card in the modal, claim binds + page refresh; wrong/expired code renders inline error partial (not a toast-only path) | 🔲 | 🔲 (registration invisible by design) |
|
||||||
|
|
||||||
### Podcast-specific sweep notes (plan task 1.10)
|
### Podcast-specific sweep notes (plan task 1.10)
|
||||||
|
|
||||||
|
|||||||
@@ -463,13 +463,13 @@ function setupEventDelegation(): void {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Pairing section: htmx only swaps 2xx bodies, so claim/lookup failures
|
// Pairing (Add Device modal): htmx only swaps 2xx bodies, so claim/lookup
|
||||||
// (wrong code, rate limit, expired) would otherwise fail silently.
|
// failures (wrong code, rate limit, expired) would otherwise fail
|
||||||
// Content-level answers come from the templ partial; this toast covers
|
// silently. Content-level answers come from the templ partial; this
|
||||||
// the non-swap error path.
|
// toast covers the non-swap error path.
|
||||||
document.body.addEventListener("htmx:responseError", (e) => {
|
document.body.addEventListener("htmx:responseError", (e) => {
|
||||||
const detail = (e as CustomEvent<{ requestConfig?: { elt?: Element } }>).detail;
|
const detail = (e as CustomEvent<{ requestConfig?: { elt?: Element } }>).detail;
|
||||||
if (detail?.requestConfig?.elt?.closest("#pairing-section")) {
|
if (detail?.requestConfig?.elt?.closest("#add-device-modal")) {
|
||||||
showToast("Pairing failed — check the code and try again.", "error");
|
showToast("Pairing failed — check the code and try again.", "error");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in new issue
Block a user