From 00245c5c9877f306423807657c225bcfc8affe83 Mon Sep 17 00:00:00 2001 From: Loren Segal Date: Sat, 3 Oct 2026 14:12:05 -0700 Subject: [PATCH 1/2] Start work on issue #2 [skip ci] From 710055c21103255d8b3bb7333423a043fb680db1 Mon Sep 17 00:00:00 2001 From: Loren Segal Date: Sat, 3 Oct 2026 14:13:23 -0700 Subject: [PATCH 2/2] Fix Get Feedback redirect to use the canonical subscript.to origin Closes #2 Co-Authored-By: Claude Opus 5.5 --- app/src/App.tsx | 5 +++- app/src/lib/feedback.test.ts | 47 ++++++++++++++++++++++++++++++++++++ app/src/lib/feedback.ts | 15 ++++++++++++ 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 app/src/lib/feedback.test.ts create mode 100644 app/src/lib/feedback.ts diff --git a/app/src/App.tsx b/app/src/App.tsx index 6f3fd22..cc94ce5 100644 --- a/app/src/App.tsx +++ b/app/src/App.tsx @@ -29,6 +29,7 @@ import { type ScreenplayParagraph, serializeFdx, } from "./lib/fdx"; +import { feedbackRedirectUrl } from "./lib/feedback"; import { type DeviceIdentity, loadIdentity, renameIdentity } from "./lib/identity"; import { paginateScreenplay } from "./lib/pagination"; import { loadPanelPreferences, savePanelPreferences } from "./lib/panel_preferences"; @@ -528,7 +529,9 @@ function App({ config: configOverrides }: { config?: Partial } = {} }); const result = (await response.json()) as { redirect_url?: string; error?: string }; if (!response.ok || !result.redirect_url) throw new Error(result.error || "Upload failed"); - window.location.assign(result.redirect_url); + window.location.assign( + feedbackRedirectUrl(result.redirect_url, config.homepage, window.location.origin), + ); } catch { setFeedbackStatus("error"); } diff --git a/app/src/lib/feedback.test.ts b/app/src/lib/feedback.test.ts new file mode 100644 index 0000000..657c383 --- /dev/null +++ b/app/src/lib/feedback.test.ts @@ -0,0 +1,47 @@ +import { describe, expect, it } from "vitest"; +import { feedbackRedirectUrl } from "./feedback"; + +describe("feedback redirect", () => { + it("resolves relative redirects against the Subscript homepage", () => { + expect( + feedbackRedirectUrl( + "/scripts/42/feedback?x=1", + "https://subscript.to", + "https://write.subscript.to", + ), + ).toBe("https://subscript.to/scripts/42/feedback?x=1"); + }); + + it("moves redirects built from the editor host onto the Subscript homepage", () => { + expect( + feedbackRedirectUrl( + "https://write.subscript.to/scripts/42/feedback#top", + "https://subscript.to", + "https://write.subscript.to", + ), + ).toBe("https://subscript.to/scripts/42/feedback#top"); + }); + + it("keeps redirects that already point at another origin", () => { + expect( + feedbackRedirectUrl( + "https://subscript.to/scripts/42", + "https://subscript.to", + "https://write.subscript.to", + ), + ).toBe("https://subscript.to/scripts/42"); + expect( + feedbackRedirectUrl( + "https://auth.example.com/login", + "https://subscript.to", + "https://write.subscript.to", + ), + ).toBe("https://auth.example.com/login"); + }); + + it("leaves redirects alone when the editor is embedded on the homepage", () => { + expect(feedbackRedirectUrl("/scripts/42", "https://subscript.to", "https://subscript.to")).toBe( + "https://subscript.to/scripts/42", + ); + }); +}); diff --git a/app/src/lib/feedback.ts b/app/src/lib/feedback.ts new file mode 100644 index 0000000..4b07b88 --- /dev/null +++ b/app/src/lib/feedback.ts @@ -0,0 +1,15 @@ +// Get Feedback must land on the canonical Subscript site, where SSO works, +// even when the editor is served from another host such as write.subscript.to. +export const feedbackRedirectUrl = ( + redirectUrl: string, + homepage: string, + currentOrigin: string, +): string => { + const canonical = new URL(homepage); + const target = new URL(redirectUrl, canonical); + if (target.origin === currentOrigin && currentOrigin !== canonical.origin) { + target.protocol = canonical.protocol; + target.host = canonical.host; + } + return target.toString(); +};