Skip to content

Commit

Permalink
feat:编辑挂载配置
Browse files Browse the repository at this point in the history
  • Loading branch information
VirtualHotBar committed May 17, 2024
1 parent f636705 commit 2f567d2
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 48 deletions.
2 changes: 2 additions & 0 deletions src/controller/language/pack/zh-cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@
"user": "用户",
"pass": "密码",
"save": "保存",
"save_successfully": "保存成功",
"step_back": "返回",
"step_next": "下一步",
"storage_introduce": "存储介绍",
"show_advanced_options": "显示高级选项",
"please_input": "请输入",
"optional": "可选",
"Input_and_press_enter": "输入并回车",
"missing_parameter": "缺少参数",
"StorageName": "存储名称",
Expand Down
20 changes: 12 additions & 8 deletions src/controller/storage/mount/mount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ParametersType } from "../../../type/defaults"
import { rclone_api_post } from "../../../utils/rclone/request"
import { fs_exist_dir, fs_make_dir } from "../../../utils/utils"
import { convertStoragePath, formatPathRclone } from "../storage"
import { MountOptions, VfsOptions } from "../../../type/rclone/storage/mount/parameters"


//列举存储
Expand All @@ -17,11 +18,11 @@ async function reupMount(noRefreshUI?: boolean) {
)).mountPoints || []

rcloneInfo.mountList = [];

mountPoints.forEach((tiem: any) => {
const name = tiem.Fs
rcloneInfo.mountList.push({
storageName:name, //name.substring(0, name.length - 1)
storageName: name, //name.substring(0, name.length - 1)
mountPath: tiem.MountPoint,
mountedTime: new Date(tiem.MountedOn),
})
Expand All @@ -37,7 +38,7 @@ function isMounted(mountPath: string): boolean {
return rcloneInfo.mountList.findIndex((item) => item.mountPath === mountPath) !== -1
}

async function addMountStorage(storageName: string, mountPath: string, parameters: ParametersType, autoMount?: boolean) {
async function addMountStorage(storageName: string, mountPath: string, parameters: { vfsOpt: VfsOptions, mountOpt: MountOptions }, autoMount?: boolean) {
if (getMountStorage(mountPath)) {
return false
}
Expand Down Expand Up @@ -71,20 +72,23 @@ async function delMountStorage(mountPath: string) {

async function editMountStorage(mountInfo: MountListItem) {

await reupMount()
//await reupMount()
//觉得这里是不必要的,就注释了
/*rcloneInfo.mountList.forEach((item) => {
if (item.mountPath === mountInfo.mountPath) {
return false
}
}) */

const index = nmConfig.mount.lists.findIndex((item) => item.mountPath === mountInfo.mountPath)

if (index !== -1) {
nmConfig.mount.lists[index] = mountInfo
for (let i = 0; i < nmConfig.mount.lists.length; i++) {
if (nmConfig.mount.lists[i].mountPath === mountInfo.mountPath) {
nmConfig.mount.lists[i] = mountInfo
break
}
}


await saveNmConfig()
}

Expand All @@ -94,7 +98,7 @@ async function mountStorage(mountInfo: MountListItem) {
}

const back = await rclone_api_post('/mount/mount', {
fs:convertStoragePath( mountInfo.storageName )|| mountInfo.storageName,
fs: convertStoragePath(mountInfo.storageName) || mountInfo.storageName,
mountPoint: mountInfo.mountPath,
...(mountInfo.parameters)
})
Expand Down
2 changes: 1 addition & 1 deletion src/controller/storage/mount/parameters/defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const vfsCacheModeParam: StorageParamItemType = {
name: 'CacheMode',
description: 'CacheMode',
type: 'string',
default: 'full',
default: 'minimal',
required: false,
advanced: false,
isPassword: false,
Expand Down
103 changes: 78 additions & 25 deletions src/page/mount/add.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@ import { ParametersType } from '../../type/defaults';
import { formatPath, getProperties, getURLSearchParam, getWinFspInstallState, showPathInExplorer } from '../../utils/utils';
import { defaultMountConfig, defaultVfsConfig, vfsCacheModeParam } from '../../controller/storage/mount/parameters/defaults';
import { rcloneInfo } from '../../services/rclone';
import { addMountStorage, getAvailableDriveLetter, getMountStorage, mountStorage } from '../../controller/storage/mount/mount';
import { addMountStorage, editMountStorage, getAvailableDriveLetter, getMountStorage, mountStorage } from '../../controller/storage/mount/mount';
import { osInfo } from '../../services/config';
import { homeDir } from '@tauri-apps/api/path';
import { InputForm_module, paramsType2FormItems } from '../other/InputForm';
import { filterHideStorage } from '../../controller/storage/storage';
import { MountOptions, VfsOptions } from '../../type/rclone/storage/mount/parameters';

const FormItem = Form.Item;

const CollapseItem = Collapse.Item;


export default function AddMount_page() {
const { t } = useTranslation()
const navigate = useNavigate();
Expand All @@ -25,15 +27,17 @@ export default function AddMount_page() {
const [autoMount, setAutoMount] = useState(true)
//const [autoMountPath, setAutoMountPath] = useState(true)//自动分配盘符
//const [notification, contextHolder] = Notification.useNotification();
const [parameters, setParameters] = useState<{ vfsOpt: VfsOptions, mountOpt: MountOptions }>({ mountOpt: defaultMountConfig, vfsOpt: defaultVfsConfig })
const [vfsOptFormHook, setVfsOptFormHook] = useState<FormInstance>();//表单实例
const [mountOptFormHook, setMountOptFormHook] = useState<FormInstance>();//表单实例
const RadioGroup = Radio.Group;
const storageList=filterHideStorage(rcloneInfo.storageList)

const RadioGroup = Radio.Group;
const storageList = filterHideStorage(rcloneInfo.storageList)
const isEditMode = (getURLSearchParam('edit') === 'true')
const isWindows = rcloneInfo.version.os.toLowerCase().includes('windows');

let parameters: ParametersType = { mountOpt: {}, vfsOpt: {} }

const isMountPathCustom = mountPath !== '*' && !mountPath.startsWith('~/Desktop/');
const mountPathuIsDriveLetter = isWindows && (mountPath === '*' || mountPath.endsWith(':') || mountPath.endsWith(':/'));


const checkWinFspState = async () => {
Expand All @@ -50,8 +54,22 @@ export default function AddMount_page() {
}
}

const editMode = () => {
let mountPathTemp = getURLSearchParam('mountPath')
const mount = getMountStorage(mountPathTemp)
if (mount) {
setStorageName(mount.storageName)
setMountPath(mount.mountPath)
setAutoMount(mount.autoMount)
setParameters(mount.parameters as { vfsOpt: VfsOptions, mountOpt: MountOptions })
}
}

useEffect(() => {
setMountPath(mountPath.replace(/\\/g, '/').replace(/\/+/g, '/'))
/* if (mountPathuIsDriveLetter) {
mountOptFormHook && mountOptFormHook.setFieldsValue({ VolumeName: storageName })
} */
}, [mountPath])

useEffect(() => {
Expand All @@ -70,13 +88,19 @@ export default function AddMount_page() {
} else if (!storageName) {
setStorageName(storageList[0].name)
}

if (isEditMode) {
editMode()
}
}, [])

useEffect(() => {
//默认挂载路径
if (isWindows) {
//setMountPath('*')
setMountPath('~/Desktop/' + storageName)


} else {
if (storageName) {
if (rcloneInfo.version.os.toLowerCase().includes('darwin')) {
Expand All @@ -88,7 +112,10 @@ export default function AddMount_page() {
}
}, [storageName])

const isMountPathCustom = mountPath !== '*' && !mountPath.startsWith('~/Desktop/');
useEffect(() => {
vfsOptFormHook && vfsOptFormHook.setFieldsValue(parameters.vfsOpt);
mountOptFormHook && mountOptFormHook.setFieldsValue(parameters.mountOpt)
}, [vfsOptFormHook, mountOptFormHook])


return (
Expand All @@ -110,8 +137,7 @@ export default function AddMount_page() {
</Select>
</FormItem>

<FormItem label={t('mount_path')}>

<FormItem label={t('mount_path')} hidden={isEditMode}>
{isMountPathCustom && (
<>
<Input
Expand All @@ -136,34 +162,50 @@ export default function AddMount_page() {

</FormItem>

<FormItem label={t('VolumeName') + '(' + t('optional') + ')'} hidden={!mountPathuIsDriveLetter}>
<Input /* bordered={false} */ value={parameters.mountOpt.VolumeName} placeholder={t('please_input')} onChange={(value) =>
setParameters({ ...parameters, mountOpt: { ...parameters.mountOpt, VolumeName: value } })
} />
</FormItem>

{!showAllOptions &&
<FormItem label={t('mount_options')}>
<Space>
<Checkbox defaultChecked={defaultVfsConfig.ReadOnly} onChange={(checked) => {
vfsOptFormHook?.setFieldValue('ReadOnly', checked)
}} >{t('read_only')}</Checkbox>
{(mountPath === '*' || mountPath.endsWith(':') || mountPath.endsWith(':/')) && isWindows && <Checkbox defaultChecked={!defaultMountConfig.NetworkMode} onChange={(checked) => {
mountOptFormHook?.setFieldValue('NetworkMode', !checked)
}} >{t('simulate_hard_drive')}</Checkbox>}
<Checkbox checked={parameters.vfsOpt.ReadOnly} onChange={(checked) => {
vfsOptFormHook?.setFieldValue('ReadOnly', checked)
}} >{t('read_only')}</Checkbox>
{mountPathuIsDriveLetter && <Checkbox checked={!parameters.mountOpt.NetworkMode} onChange={(checked) => {
mountOptFormHook?.setFieldValue('NetworkMode', !checked)
}} >{t('simulate_hard_drive')}</Checkbox>}
</Space>
</FormItem>
}

{
<div style={{ display: showAllOptions ? 'block' : 'none' }}>
<InputForm_module data={paramsType2FormItems(defaultMountConfig)} onChange={(data) => { parameters.mountOpt = data }} overwriteValues={defaultMountConfig} setFormHook={(form) => { setMountOptFormHook(form) }} />
<InputForm_module data={[vfsCacheModeParam,...paramsType2FormItems(defaultVfsConfig,undefined,['CacheMode'])]} onChange={(data) => { parameters.vfsOpt = data }} overwriteValues={defaultVfsConfig} setFormHook={(form) => { setVfsOptFormHook(form) }} />
<InputForm_module data={paramsType2FormItems(defaultMountConfig)} onChange={(data) => {
setParameters({ ...parameters, mountOpt: { ...parameters.mountOpt, ...data } })
}} overwriteValues={parameters.mountOpt} setFormHook={(form) => {
//form.setFieldsValue(parameters.mountOpt)
setMountOptFormHook(form)
}} />
<InputForm_module data={[vfsCacheModeParam, ...paramsType2FormItems(defaultVfsConfig, undefined, ['CacheMode'])]} onChange={(data) => {
setParameters({ ...parameters, vfsOpt: { ...parameters.vfsOpt, ...data } })
}} overwriteValues={{ ...parameters.vfsOpt, CacheMode: 'full' }} setFormHook={(form) => {
//form.setFieldsValue(parameters.vfsOpt);
setVfsOptFormHook(form)
}} />
</div>
}

{/* 按钮 */}
<div style={{ width: '100%', textAlign: 'right' }}>
<Space>
<Checkbox defaultChecked={autoMount} onChange={(checked) => { setAutoMount(checked) }} >{t('auto_mount')}</Checkbox>
<Checkbox checked={autoMount} onChange={(checked) => { setAutoMount(checked) }} >{t('auto_mount')}</Checkbox>
{!showAllOptions && <Button onClick={() => { setShowAllOptions(!showAllOptions) }} type='text'>{t('show_all_options')}</Button>}
<Button onClick={() => { navigate('/mount') }} >{t('step_back')}</Button>
<Button disabled={!storageName || !mountPath} onClick={async () => {
if (getMountStorage(mountPath)) {
if (!isEditMode && getMountStorage(mountPath)) {
Notification.error({
title: t('error'),
content: t('mount_path_already_exists'),
Expand All @@ -183,21 +225,32 @@ export default function AddMount_page() {
}

mountPathTemp = formatPath(mountPathTemp, isWindows)
if (isEditMode) {
console.log(parameters);

await addMountStorage(storageName!, mountPathTemp, parameters, autoMount)
await editMountStorage({ storageName: storageName!, mountPath: mountPathTemp, parameters: parameters, autoMount: autoMount })
} else {
await addMountStorage(storageName!, mountPathTemp, parameters, autoMount)
}

if (await mountStorage(getMountStorage(mountPathTemp)!)) {
if (isEditMode) {
Notification.success({
title: t('success'),
content: t('save_successfully'),
})
} else if (await mountStorage(getMountStorage(mountPathTemp)!)) {
Notification.success({
title: t('success'),
content: t('mount_storage_successfully'),
})
navigate('/mount')
if(isWindows&&rcloneInfo.endpoint.isLocal){
showPathInExplorer(mountPathTemp,true)
if (isWindows && rcloneInfo.endpoint.isLocal) {
showPathInExplorer(mountPathTemp, true)
}
}

}} type='primary'>{t('mount')}</Button>
navigate('/mount')
}} type='primary'>
{isEditMode ? t('save') : t('mount')}
</Button>
</Space>
</div>
</Form>
Expand Down
20 changes: 10 additions & 10 deletions src/page/mount/mount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,21 @@ function Mount_page() {
const [winFspInstalling, setWinFspInstalling] = useState<boolean>();

const columns: TableColumnProps[] = [
{
title: t('mount_path'),
dataIndex: 'mountPath_',
ellipsis: true,

},
{
title: t('storage_name'),
dataIndex: 'storageName',
width:'11rem',
width:'10rem',
ellipsis: true,
render: (text) => {
return <Typography.Ellipsis>{text}</Typography.Ellipsis>
},
},
{
title: t('mount_path'),
dataIndex: 'mountPath_',
ellipsis: true,

},
{
title: t('mount_status'),
dataIndex: 'mounted',
Expand All @@ -46,7 +46,7 @@ function Mount_page() {
title: t('actions'),
dataIndex: 'actions',
align: 'right',
width:'11rem'
width:'14.3rem'
}
]

Expand Down Expand Up @@ -107,7 +107,7 @@ function Mount_page() {
const mounted = isMounted(item.mountPath)
return {
...item,
mountPath_: <div style={{ display: 'flex', width:'100%',alignItems:'center' }}><Typography.Ellipsis className='singe-line' showTooltip>{item.mountPath}</Typography.Ellipsis>{rcloneInfo.endpoint.isLocal&&osInfo.osType==='Windows_NT' &&mounted&&
mountPath_: <div style={{ display: 'flex', alignItems:'center' }}><Typography.Ellipsis className='singe-line' showTooltip>{item.mountPath}</Typography.Ellipsis>{rcloneInfo.endpoint.isLocal&&osInfo.osType==='Windows_NT' &&mounted&&
<Button title={t('show_path_in_explorer')} onClick={async () => {
await showPathInExplorer(item.mountPath,true)
}} type='text' icon={<IconEye />}></Button>}</div>,
Expand All @@ -118,8 +118,8 @@ function Mount_page() {
<Button onClick={() => { unmountStorage(item.mountPath) }} status='danger' >{t('unmount')}</Button>
</> :
<>

<Button onClick={() => { delMountStorage(item.mountPath) }} status='danger' >{t('delete')}</Button>
<Button onClick={() => { navigate('./add?edit=true&mountPath='+item.mountPath) }} >{t('edit')}</Button>
<Button onClick={() => { mountStorage(item) }} type='primary' >{t('mount')}</Button>
</>
}
Expand Down
3 changes: 0 additions & 3 deletions src/page/other/InputForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,6 @@ function InputForm_module({ data, style, showAdvanced, footer, onChange, overwri
overwriteValues?: ParametersType;
setFormHook?: (form: FormInstance) => void;
}) {
console.log(data);

const { t } = useTranslation()
const [form] = Form.useForm();

Expand All @@ -218,7 +216,6 @@ function InputForm_module({ data, style, showAdvanced, footer, onChange, overwri
}, [])

useEffect(() => {
console.log(formValuesResult);
onChange && onChange(formValuesResult)
}, [formValuesResult])

Expand Down
2 changes: 1 addition & 1 deletion src/type/config.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ interface NMConfig {
interface MountListItem {
storageName: string,
mountPath: string,
parameters: ParametersType,//挂载配置
parameters: { vfsOpt: VfsOptions, mountOpt: MountOptions },//挂载配置
autoMount: boolean,//软件启动自动挂载
}

Expand Down

0 comments on commit 2f567d2

Please sign in to comment.