feat: custom password checkbox & password display box

This commit is contained in:
wintbit 2025-06-15 21:49:57 +08:00
parent 5b9fb5828c
commit 13ddb74aca
6 changed files with 93 additions and 33 deletions

View File

@ -307,6 +307,7 @@
"createShareLink": "Share",
"viewDetails": "View details",
"copy": "Copy",
"copyLinkAlongWithPassword": "Copy link and password",
"bytes": " ({{bytes}} Bytes)",
"storagePolicy": "Storage policy",
"childFolders": "Child folders",
@ -469,7 +470,7 @@
"createShareLink": "Create share link",
"privateShare": "Hide from public",
"privateShareDes": "If selected, other people cannot see this share link on your homepage.",
"passwordPrefix": "Share link password: ",
"useCustomPassword": "Custom share link password",
"passwordAutoGenerate": "Auto generate",
"shareView": "Share view setting",
"shareViewDes": "If selected, other users can see your view setting (layout, sorting, etc.) saved on the server server when accessing this shared folder.",

View File

@ -308,6 +308,7 @@
"createShareLink": "共有リンクの作成",
"viewDetails": "詳細情報",
"copy": "コピー",
"copyLinkAlongWithPassword": "パスワード付きリンクをコピー",
"bytes": " ({{bytes}} バイト)",
"storagePolicy": "ストレージポリシー",
"childFolders": "ディレクトリの内容",
@ -470,7 +471,7 @@
"createShareLink": "共有リンク作成",
"privateShare": "共有を非表示",
"privateShareDes": "チェックを入れると他の人はあなたのプロフィールページでこの共有リンクを見ることができません。",
"passwordPrefix": "共有リンクパスワード:",
"useCustomPassword": "カスタムパスワードを使用",
"passwordAutoGenerate": "自動生成",
"expireAfterDownload": "ダウンロード後に自動的に期限切れ",
"sharePassword": "共有パスワード",

View File

@ -307,6 +307,7 @@
"createShareLink": "创建分享链接",
"viewDetails": "详细信息",
"copy": "复制",
"copyLinkAlongWithPassword": "复制链接和密码",
"bytes": " ({{bytes}} 字节)",
"storagePolicy": "存储策略",
"childFolders": "包含目录",
@ -469,7 +470,7 @@
"createShareLink": "创建分享链接",
"privateShare": "隐藏分享",
"privateShareDes": "勾选后,其他人无法在你的个人主页看到此分享链接。",
"passwordPrefix": "分享密码: ",
"useCustomPassword": "自定义分享密码",
"passwordAutoGenerate": "自动生成",
"expireAfterDownload": "下载后自动过期",
"sharePassword": "分享密码",

View File

@ -307,6 +307,7 @@
"createShareLink": "建立分享連結",
"viewDetails": "詳細資訊",
"copy": "復制",
"copyLinkAlongWithPassword": "復制連結和密碼",
"bytes": " ({{bytes}} 位元組)",
"storagePolicy": "儲存策略",
"childFolders": "包含目錄",
@ -465,7 +466,7 @@
"createShareLink": "建立分享連結",
"privateShare": "隱藏分享",
"privateShareDes": "勾選後,其他人無法在你的個人主頁看到此分享連結。",
"passwordPrefix": "分享密碼:",
"useCustomPassword": "使用自定義密碼",
"passwordAutoGenerate": "自動生成",
"expireAfterDownload": "下載後自動過期",
"sharePassword": "分享密碼",

View File

@ -1,4 +1,4 @@
import { Box, DialogContent, IconButton, Tooltip, useTheme } from "@mui/material";
import {Box, DialogContent, IconButton, List, Tooltip, useTheme} from "@mui/material";
import dayjs from "dayjs";
import { TFunction } from "i18next";
import React, { useCallback, useEffect, useState } from "react";
@ -15,6 +15,7 @@ import DraggableDialog from "../../../Dialogs/DraggableDialog.tsx";
import Share from "../../../Icons/Share.tsx";
import { FileManagerIndex } from "../../FileManager.tsx";
import ShareSettingContent, { downloadOptions, expireOptions, ShareSetting } from "./ShareSetting.tsx";
import {CopyAll} from "@mui/icons-material";
const initialSetting: ShareSetting = {
@ -25,6 +26,8 @@ const initialSetting: ShareSetting = {
const shareToSetting = (share: ShareModel, t: TFunction): ShareSetting => {
const res: ShareSetting = {
is_private: share.is_private,
password: share.password,
use_custom_password: true,
share_view: share.share_view,
downloads: share.remain_downloads != undefined && share.remain_downloads > 0,
@ -129,7 +132,7 @@ const ShareDialog = () => {
maxWidth: "xs",
}}
cancelText={shareLink ? "common:close" : undefined}
okText={shareLink ? "fileManager.copy" : undefined}
okText={shareLink ? "fileManager.copyLinkAlongWithPassword" : undefined}
secondaryAction={
shareLink
? // @ts-ignore
@ -161,15 +164,55 @@ const ShareDialog = () => {
/>
)}
{shareLink && (
<FilledTextField
variant={"filled"}
autoFocus
inputProps={{ readonly: true }}
label={t("modals.shareLink")}
fullWidth
value={shareLink}
onFocus={(e) => e.target.select()}
/>
<List sx={{
display: "flex",
flexDirection: "column",
gap: theme.spacing(1),
padding: theme.spacing(1),
}}>
<FilledTextField
variant={"filled"}
inputProps={{ readonly: true }}
label={t("modals.shareLink")}
fullWidth
value={shareLink.substring(0, shareLink.lastIndexOf("/"))}
onFocus={(e) => e.target.select()}
slotProps={{
input: {
endAdornment: (
<IconButton
onClick={() => copyToClipboard(shareLink.substring(0, shareLink.lastIndexOf("/")))}
size="small"
sx={{ marginRight: -1 }}
>
<CopyAll />
</IconButton>
)
}
}}
/>
<FilledTextField
variant={"filled"}
inputProps={{ readonly: true }}
label={t("modals.sharePassword")}
fullWidth
value={setting.password}
onFocus={(e) => e.target.select()}
slotProps={{
input: {
endAdornment: (
<IconButton
onClick={() => copyToClipboard(setting.password ?? "")}
size="small"
sx={{ marginRight: -1 }}
>
<CopyAll />
</IconButton>
)
}
}}
/>
</List>
)}
</Box>
</CSSTransition>

View File

@ -71,6 +71,7 @@ const StyledListItemButton = styled(ListItemButton)(() => ({}));
export interface ShareSetting {
is_private?: boolean;
use_custom_password?: boolean;
password?: string;
share_view?: boolean;
downloads?: boolean;
@ -154,25 +155,37 @@ const ShareSettingContent = ({ setting, file, editing, onSettingChange }: ShareS
</AccordionSummary>
<AccordionDetails sx={{ display: "flex", flexDirection: "column", alignItems: "center" }}>
<Typography>{t("application:modals.privateShareDes")}</Typography>
{setting.is_private && (
{setting.is_private &&
<Box sx={{ display: "flex", alignItems: "center", width: "100%" }}>
<Typography>{t("application:modals.passwordPrefix")}</Typography>
<FormControl
variant="standard"
sx={{ mx: 1, flex: 1 }}
>
<TextField
variant="standard"
value={setting.password ?? ""}
onChange={(e) => {
onSettingChange({ ...setting, password: e.target.value });
}}
placeholder={t("application:modals.passwordAutoGenerate")}
fullWidth
/>
</FormControl>
</Box>
)}
{!editing && (
<Checkbox checked={setting.use_custom_password} onChange={() => {
onSettingChange({ ...setting, use_custom_password: !setting.use_custom_password });
}} />
)}
{!setting.use_custom_password && (
<Typography sx={{ flex: 1 }}>{t("application:modals.useCustomPassword")}</Typography>
)}
{setting.use_custom_password && (
<FormControl
variant="standard"
sx={{ mx: 1, flex: 1 }}
>
<TextField
label={t("application:modals.sharePassword")}
variant="standard"
disabled={editing}
value={setting.password ?? ""}
onChange={(e) => {
const value = e.target.value.trim();
if (!/^[a-zA-Z0-9]*$/.test(value) || value.length > 32) return;
onSettingChange({ ...setting, password: value });
}}
placeholder={t("application:modals.passwordAutoGenerate")}
fullWidth
/>
</FormControl>
)}
</Box> }
</AccordionDetails>
</Accordion>
{file?.type == FileType.folder && (