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 <info@tdvorak.dev>

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
pull/3582/head
Tomas Dvorak 2 weeks ago
parent 2ffb91a562
commit 83cc2a0bf2

@ -18,12 +18,37 @@ import Share from "../../../Icons/Share.tsx";
import { FileManagerIndex } from "../../FileManager.tsx"; import { FileManagerIndex } from "../../FileManager.tsx";
import ShareSettingContent, { downloadOptions, expireOptions, ShareSetting } from "./ShareSetting.tsx"; import ShareSettingContent, { downloadOptions, expireOptions, ShareSetting } from "./ShareSetting.tsx";
const shareSettingStorageKey = "cloudreve.share_setting";
const initialSetting = (privateByDefault: boolean): ShareSetting => ({ const initialSetting = (privateByDefault: boolean): ShareSetting => ({
is_private: privateByDefault || undefined, is_private: privateByDefault || undefined,
expires_val: expireOptions[2], expires_val: expireOptions[2],
downloads_val: downloadOptions[0], 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 { interface ShareLinkPassword {
shareLink: string; shareLink: string;
password?: string; password?: string;
@ -104,7 +129,7 @@ const ShareDialog = () => {
if (editTarget) { if (editTarget) {
setSetting(shareToSetting(editTarget, t)); setSetting(shareToSetting(editTarget, t));
} else { } else {
setSetting(initialSetting(privateByDefault)); setSetting(lastUsedSetting(privateByDefault));
} }
setShareLink(""); setShareLink("");
setIncludePassword(true); setIncludePassword(true);
@ -135,6 +160,7 @@ const ShareDialog = () => {
const shareLink = await dispatch( const shareLink = await dispatch(
createOrUpdateShareLink(FileManagerIndex.main, target, setting, editTarget?.id), createOrUpdateShareLink(FileManagerIndex.main, target, setting, editTarget?.id),
); );
rememberSetting(setting);
setShareLink(shareLink); setShareLink(shareLink);
} catch (e) { } catch (e) {
} finally { } finally {

Loading…
Cancel
Save