fix(settings): preserve stored logo + persist editor changes on save
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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 = "";
|
||||
|
||||
Reference in New Issue
Block a user