From 011ce8e5a399ac4e34288947f221c863749ca3bd Mon Sep 17 00:00:00 2001 From: Thomas Date: Sat, 22 Aug 2026 09:13:32 +0200 Subject: [PATCH] fix: preserve board drafts and widget scroll state (#6637) --- .../boards/[name]/settings/_layout.tsx | 3 +-- .../widgets/src/media-missing/component.tsx | 24 ++++++++++++++----- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/apps/nextjs/src/app/[locale]/boards/[name]/settings/_layout.tsx b/apps/nextjs/src/app/[locale]/boards/[name]/settings/_layout.tsx index 0b5498a49..20bd78ba3 100644 --- a/apps/nextjs/src/app/[locale]/boards/[name]/settings/_layout.tsx +++ b/apps/nextjs/src/app/[locale]/boards/[name]/settings/_layout.tsx @@ -93,8 +93,7 @@ export const LayoutSettingsContent = ({ board, form, isSaving, saveSettingsAsync setResettingLayoutId(layout.id); void (async () => { try { - const savedValues = form.isDirty() ? await saveSettingsAsync() : form.values; - const canonicalLayout = savedValues ? findCanonicalLayout(savedValues.layouts, layout) : undefined; + const canonicalLayout = board.layouts.find((candidate) => candidate.id === layout.id); if (!canonicalLayout) return; await resetLayout({ boardId: board.id, layoutId: canonicalLayout.id }); diff --git a/packages/widgets/src/media-missing/component.tsx b/packages/widgets/src/media-missing/component.tsx index 69fb1c623..ce09142a6 100644 --- a/packages/widgets/src/media-missing/component.tsx +++ b/packages/widgets/src/media-missing/component.tsx @@ -1,7 +1,7 @@ "use client"; import type { ReactNode } from "react"; -import { useEffect, useState } from "react"; +import { useEffect, useRef, useState } from "react"; import { Badge, Box, @@ -58,6 +58,10 @@ export default function MediaMissingWidget({ }); const data = getUsableWidgetQueryData(mediaQuery); const [selectedTab, setSelectedTab] = useState(showMissing ? "missing" : "queued"); + const tabScrollPositionsRef = useRef>({ + missing: { x: 0, y: 0 }, + queued: { x: 0, y: 0 }, + }); const activeTab = resolveMediaMissingTab(selectedTab, showMissing, showQueued); useEffect(() => { @@ -92,10 +96,18 @@ export default function MediaMissingWidget({ const tabLabel = (label: string, shown: number, total: number) => (isThin ? total : `${label} (${shown}/${total})`); const renderPanel = ( + tab: MediaMissingTab, entries: { item: MissingMediaItem | QueuedMediaItem; integrationId: string }[], emptyLabel: string, ) => ( - + { + tabScrollPositionsRef.current[tab] = position; + }} + > {entries.length === 0 ? ( @@ -146,7 +158,7 @@ export default function MediaMissingWidget({ {tabLabel(t("tab.missing"), missing.length, missingCount)} - {renderPanel(missing, t("empty.missing"))} + {renderPanel("missing", missing, t("empty.missing"))} )} {showQueued && ( @@ -157,7 +169,7 @@ export default function MediaMissingWidget({ {tabLabel(t("tab.queued"), queued.length, queuedCount)} - {renderPanel(queued, t("empty.queued"))} + {renderPanel("queued", queued, t("empty.queued"))} )} @@ -202,12 +214,12 @@ export default function MediaMissingWidget({ {showMissing && ( - {activeTab === "missing" && renderPanel(missing, t("empty.missing"))} + {activeTab === "missing" && renderPanel("missing", missing, t("empty.missing"))} )} {showQueued && ( - {activeTab === "queued" && renderPanel(queued, t("empty.queued"))} + {activeTab === "queued" && renderPanel("queued", queued, t("empty.queued"))} )}