From 83cc2a0bf2502ef6cb7f99c35dd35bf0ec43e9f2 Mon Sep 17 00:00:00 2001 From: Tomas Dvorak Date: Sat, 19 Sep 2026 00:02:58 +0200 Subject: [PATCH] feat(share): remember last-used share settings (#2519) The share dialog now persists settings to localStorage on successful create and hydrates from them on next open. Password fields are never persisted; the site/user private-share default still applies on first use before any remembered state exists. Authored By: TDvorak Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../FileManager/Dialogs/Share/ShareDialog.tsx | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/frontend/src/component/FileManager/Dialogs/Share/ShareDialog.tsx b/frontend/src/component/FileManager/Dialogs/Share/ShareDialog.tsx index fabe3be3..8a457921 100644 --- a/frontend/src/component/FileManager/Dialogs/Share/ShareDialog.tsx +++ b/frontend/src/component/FileManager/Dialogs/Share/ShareDialog.tsx @@ -18,12 +18,37 @@ import Share from "../../../Icons/Share.tsx"; import { FileManagerIndex } from "../../FileManager.tsx"; import ShareSettingContent, { downloadOptions, expireOptions, ShareSetting } from "./ShareSetting.tsx"; +const shareSettingStorageKey = "cloudreve.share_setting"; + const initialSetting = (privateByDefault: boolean): ShareSetting => ({ is_private: privateByDefault || undefined, expires_val: expireOptions[2], downloads_val: downloadOptions[0], }); +// lastUsedSetting hydrates the dialog from the previously saved share +// settings (#2519). Password fields are never persisted. +const lastUsedSetting = (privateByDefault: boolean): ShareSetting => { + try { + const raw = localStorage.getItem(shareSettingStorageKey); + if (raw) { + return { ...initialSetting(privateByDefault), ...JSON.parse(raw) }; + } + } catch { + // corrupted or unavailable storage falls back to defaults + } + return initialSetting(privateByDefault); +}; + +const rememberSetting = (setting: ShareSetting) => { + try { + const { password, use_custom_password, ...rest } = setting; + localStorage.setItem(shareSettingStorageKey, JSON.stringify(rest)); + } catch { + // storage unavailable; remembering is best-effort + } +}; + interface ShareLinkPassword { shareLink: string; password?: string; @@ -104,7 +129,7 @@ const ShareDialog = () => { if (editTarget) { setSetting(shareToSetting(editTarget, t)); } else { - setSetting(initialSetting(privateByDefault)); + setSetting(lastUsedSetting(privateByDefault)); } setShareLink(""); setIncludePassword(true); @@ -135,6 +160,7 @@ const ShareDialog = () => { const shareLink = await dispatch( createOrUpdateShareLink(FileManagerIndex.main, target, setting, editTarget?.id), ); + rememberSetting(setting); setShareLink(shareLink); } catch (e) { } finally {