Also fixes a bug I just noticed in the Subscribe help page.
+70
-9
Diff
round #0
+1
-1
docs/docs/pages/subscribe.mdx
+1
-1
docs/docs/pages/subscribe.mdx
···
147
147
148
148
The component dispatches custom events you can listen to:
149
149
150
-
| Event | Description | `detail` |
150
+
| Event | Description | Detail |
151
151
|-------|-------------|----------|
152
152
| `sequoia-subscribed` | Fired when the subscription is created successfully. | `{ publicationUri: string, recordUri: string }` |
153
153
| `sequoia-subscribe-error` | Fired when the subscription fails. | `{ message: string }` |
+69
-8
docs/src/routes/subscribe.ts
+69
-8
docs/src/routes/subscribe.ts
···
35
35
const subscribe = new Hono<{ Bindings: Env }>();
36
36
37
37
const COLLECTION = "site.standard.graph.subscription";
38
+
const REDIRECT_DELAY_SECONDS = 5;
38
39
39
40
// ============================================================================
40
41
// Helpers
···
162
163
);
163
164
}
164
165
166
+
// Prefer an explicit returnTo query param (survives the OAuth round-trip);
167
+
// fall back to the Referer header on the first visit, ignoring self-referrals.
168
+
const referer = c.req.header("referer");
169
+
const returnTo =
170
+
c.req.query("returnTo") ??
171
+
(referer && !referer.includes("/subscribe") ? referer : undefined);
172
+
165
173
const did = getSessionDid(c);
166
174
if (!did) {
167
-
return c.html(renderHandleForm(publicationUri, styleHref));
175
+
return c.html(renderHandleForm(publicationUri, styleHref, returnTo));
168
176
}
169
177
170
178
try {
···
179
187
);
180
188
if (existingUri) {
181
189
return c.html(
182
-
renderSuccess(publicationUri, existingUri, true, styleHref),
190
+
renderSuccess(publicationUri, existingUri, true, styleHref, returnTo),
183
191
);
184
192
}
185
193
···
193
201
});
194
202
195
203
return c.html(
196
-
renderSuccess(publicationUri, result.data.uri, false, styleHref),
204
+
renderSuccess(
205
+
publicationUri,
206
+
result.data.uri,
207
+
false,
208
+
styleHref,
209
+
returnTo,
210
+
),
197
211
);
198
212
} catch (error) {
199
213
console.error("Subscribe GET error:", error);
···
202
216
renderHandleForm(
203
217
publicationUri,
204
218
styleHref,
219
+
returnTo,
205
220
"Session expired. Please sign in again.",
206
221
),
207
222
);
···
219
234
const body = await c.req.parseBody();
220
235
const handle = (body["handle"] as string | undefined)?.trim();
221
236
const publicationUri = body["publicationUri"] as string | undefined;
237
+
const formReturnTo = (body["returnTo"] as string | undefined) || undefined;
222
238
223
239
if (!handle || !publicationUri) {
224
240
const styleHref = await getVocsStyleHref(c.env.ASSETS, c.req.url);
···
228
244
);
229
245
}
230
246
231
-
const returnTo = `${c.env.CLIENT_URL}/subscribe?publicationUri=${encodeURIComponent(publicationUri)}`;
247
+
const returnTo =
248
+
`${c.env.CLIENT_URL}/subscribe?publicationUri=${encodeURIComponent(publicationUri)}` +
249
+
(formReturnTo ? `&returnTo=${encodeURIComponent(formReturnTo)}` : "");
232
250
setReturnToCookie(c, returnTo, c.env.CLIENT_URL);
233
251
234
252
return c.redirect(
···
243
261
function renderHandleForm(
244
262
publicationUri: string,
245
263
styleHref: string,
264
+
returnTo?: string,
246
265
error?: string,
247
266
): string {
248
267
const errorHtml = error
249
268
? `<p class="vocs_Paragraph error">${escapeHtml(error)}</p>`
250
269
: "";
270
+
const returnToInput = returnTo
271
+
? `<input type="hidden" name="returnTo" value="${escapeHtml(returnTo)}" />`
272
+
: "";
251
273
252
274
return page(
253
275
`
···
255
277
<p class="vocs_Paragraph">Enter your Bluesky handle to subscribe to this publication.</p>
256
278
${errorHtml}
257
279
<form method="POST" action="/subscribe/login">
258
-
<input type="hidden" name="publicationUri" value="${escapeHtml(publicationUri)}" />
280
+
<input type="hidden" name="publicationUri" value="${escapeHtml(publicationUri)}" />
281
+
${returnToInput}
259
282
<input
260
283
type="text"
261
284
name="handle"
···
276
299
recordUri: string,
277
300
existing: boolean,
278
301
styleHref: string,
302
+
returnTo?: string,
279
303
): string {
280
304
const msg = existing
281
305
? "You're already subscribed to this publication."
282
306
: "You've successfully subscribed!";
283
307
const escapedPublicationUri = escapeHtml(publicationUri);
284
308
const escapedRecordUri = escapeHtml(recordUri);
309
+
310
+
const redirectHtml = returnTo
311
+
? `<p class="vocs_Paragraph" id="redirect-msg">Redirecting to <a class="vocs_Anchor" href="${escapeHtml(returnTo)}">${escapeHtml(returnTo)}</a> in <span id="countdown">${REDIRECT_DELAY_SECONDS}</span>\u00a0seconds\u2026</p>
312
+
<script>
313
+
(function(){
314
+
var secs = ${REDIRECT_DELAY_SECONDS};
315
+
var el = document.getElementById('countdown');
316
+
var iv = setInterval(function(){
317
+
secs--;
318
+
if (el) el.textContent = String(secs);
319
+
if (secs <= 0) { clearInterval(iv); location.href = ${JSON.stringify(returnTo)}; }
320
+
}, 1000);
321
+
})();
322
+
</script>`
323
+
: "";
324
+
const headExtra = returnTo
325
+
? `<meta http-equiv="refresh" content="${REDIRECT_DELAY_SECONDS};url=${escapeHtml(returnTo)}" />`
326
+
: "";
327
+
285
328
return page(
286
329
`
287
330
<h1 class="vocs_H1 vocs_Heading">Subscribed โ</h1>
288
331
<p class="vocs_Paragraph">${msg}</p>
289
-
<p class="vocs_Paragraph"><small>Publication: <code class="vocs_Code"><a href="https://pds.ls/${escapedPublicationUri}">${escapedPublicationUri}</a></code></small></p>
290
-
<p class="vocs_Paragraph"><small>Record: <code class="vocs_Code"><a href="https://pds.ls/${escapedRecordUri}">${escapedRecordUri}</a></code></small></p>
332
+
${redirectHtml}
333
+
<table class="vocs_Table" style="display:table;table-layout:fixed;width:100%;overflow:hidden;">
334
+
<colgroup><col style="width:7rem;"><col></colgroup>
335
+
<tbody>
336
+
<tr class="vocs_TableRow">
337
+
<td class="vocs_TableCell">Publication</td>
338
+
<td class="vocs_TableCell" style="overflow:hidden;">
339
+
<div style="overflow-x:auto;white-space:nowrap;"><code class="vocs_Code"><a href="https://pds.ls/${escapedPublicationUri}">${escapedPublicationUri}</a></code></div>
340
+
</td>
341
+
</tr>
342
+
<tr class="vocs_TableRow">
343
+
<td class="vocs_TableCell">Record</td>
344
+
<td class="vocs_TableCell" style="overflow:hidden;">
345
+
<div style="overflow-x:auto;white-space:nowrap;"><code class="vocs_Code"><a href="https://pds.ls/${escapedRecordUri}">${escapedRecordUri}</a></code></div>
346
+
</td>
347
+
</tr>
348
+
</tbody>
349
+
</table>
291
350
`,
292
351
styleHref,
352
+
headExtra,
293
353
);
294
354
}
295
355
···
300
360
);
301
361
}
302
362
303
-
function page(body: string, styleHref: string): string {
363
+
function page(body: string, styleHref: string, headExtra = ""): string {
304
364
return `<!DOCTYPE html>
305
365
<html lang="en">
306
366
<head>
···
309
369
<title>Sequoia ยท Subscribe</title>
310
370
<link rel="stylesheet" href="${styleHref}" />
311
371
<script>if(window.matchMedia('(prefers-color-scheme: dark)').matches)document.documentElement.classList.add('dark')</script>
372
+
${headExtra}
312
373
<style>
313
374
.page-container {
314
375
max-width: calc(var(--vocs-content_width, 480px) / 1.6);
History
1 round
0 comments
heaths.dev
submitted
#0
1 commit
expand
collapse
Automatically redirect to referring page
Also fixes a bug I just noticed in the Subscribe help page.
expand 0 comments
pull request successfully merged