fix(settings): preserve stored logo + persist editor changes on save

This commit is contained in:
Gerhard Scheikl
2026-05-09 17:17:55 +02:00
parent d454843856
commit 85a56cac59
2 changed files with 21 additions and 3 deletions
+11 -2
View File
@@ -58,6 +58,12 @@ export function RichTextEditor({
const [mounted, setMounted] = useState(false);
useEffect(() => setMounted(true), []);
// Mirror editor HTML into local state so the hidden <input> always
// reflects the latest content. Without this, React doesn't re-render
// when TipTap's content changes and the form submits stale HTML.
const initialHtml = swapCidToLogo(defaultValue || "<p></p>", logoDataUrl);
const [html, setHtml] = useState(initialHtml);
const editor = useEditor({
immediatelyRender: false,
extensions: [
@@ -85,6 +91,9 @@ export function RichTextEditor({
Color,
],
content: swapCidToLogo(defaultValue || "<p></p>", logoDataUrl),
onUpdate: ({ editor }) => {
setHtml(editor.getHTML());
},
editorProps: {
attributes: {
class: "wysiwyg-editor",
@@ -96,7 +105,7 @@ export function RichTextEditor({
// Keep editor disposed cleanly on unmount.
useEffect(() => () => editor?.destroy(), [editor]);
const html = swapLogoToCid(editor?.getHTML() ?? defaultValue, logoDataUrl);
const submittedHtml = swapLogoToCid(html, logoDataUrl);
if (!mounted) {
// Server / pre-hydration fallback: a textarea so the value is still
@@ -219,7 +228,7 @@ export function RichTextEditor({
/>
</div>
<EditorContent editor={editor} />
<input type="hidden" name={name} value={html} />
<input type="hidden" name={name} value={submittedHtml} />
{variables.length > 0 ? (
<div style={{ marginTop: 6, display: "flex", flexWrap: "wrap", gap: 4, alignItems: "center" }}>
<span style={{ fontSize: 12, color: "#6d7175", marginRight: 4 }}>Insert variable:</span>
+10 -1
View File
@@ -101,12 +101,21 @@ export const action = async ({ request }: ActionFunctionArgs) => {
// 2. Remove the current logo (`removeLogo=on`).
// 3. Provide an external URL via the `logoUrl` field.
// If a file is uploaded it wins over a manually-entered URL.
let resolvedLogoUrl = str("logoUrl");
// Look up the existing logoUrl so we don't accidentally clear it when
// the user just edited unrelated fields (the visible URL field is hidden
// for stored uploads, so it submits empty in that case).
const existing = await db.shopSettings.findUnique({
where: { shopDomain: session.shop },
select: { logoUrl: true },
});
const submittedLogoUrl = str("logoUrl");
const removeLogo = bool("removeLogo");
const logoFile = form.get("logoFile");
const hasUpload =
logoFile && typeof logoFile === "object" && "size" in logoFile && (logoFile as File).size > 0;
let resolvedLogoUrl = submittedLogoUrl || existing?.logoUrl || "";
if (removeLogo && !hasUpload) {
await deleteStoredLogo(session.shop);
resolvedLogoUrl = "";