11import { File } from '@/lib/db/models/file' ;
22import { fetchApi } from '@/lib/fetchApi' ;
3+ import useObjectState from '@/lib/hooks/useObjectState' ;
34import { Button , Divider , Modal , NumberInput , PasswordInput , Stack , TextInput } from '@mantine/core' ;
45import { showNotification } from '@mantine/notifications' ;
56import { IconEye , IconKey , IconPencil , IconPencilOff , IconTrashFilled } from '@tabler/icons-react' ;
6- import { useEffect , useState } from 'react' ;
7+ import { useEffect } from 'react' ;
78import { mutateFiles } from '../actions' ;
89
910export default function EditFileDetailsModal ( {
@@ -15,13 +16,41 @@ export default function EditFileDetailsModal({
1516 file : File | null ;
1617 onClose : ( ) => void ;
1718} ) {
18- if ( ! file ) return null ;
19+ const [ formData , setFormData ] = useObjectState < {
20+ name : string ;
21+ maxViews : number | null ;
22+ password : string | null ;
23+ originalName : string | null ;
24+ type : string | null ;
25+ } > ( {
26+ name : file ?. name ?? '' ,
27+ maxViews : file ?. maxViews ?? null ,
28+ password : file ?. password ? '' : null ,
29+ originalName : file ?. originalName ?? null ,
30+ type : file ?. type ?? null ,
31+ } ) ;
1932
20- const [ name , setName ] = useState < string > ( file . name ?? '' ) ;
21- const [ maxViews , setMaxViews ] = useState < number | null > ( file ?. maxViews ?? null ) ;
22- const [ password , setPassword ] = useState < string | null > ( '' ) ;
23- const [ originalName , setOriginalName ] = useState < string | null > ( file ?. originalName ?? null ) ;
24- const [ type , setType ] = useState < string | null > ( file ?. type ?? null ) ;
33+ useEffect ( ( ) => {
34+ if ( open ) {
35+ setFormData ( {
36+ name : file ?. name ?? '' ,
37+ maxViews : file ?. maxViews ?? null ,
38+ password : file ?. password ? '' : null ,
39+ originalName : file ?. originalName ?? null ,
40+ type : file ?. type ?? null ,
41+ } ) ;
42+ } else {
43+ setFormData ( {
44+ name : '' ,
45+ maxViews : null ,
46+ password : null ,
47+ originalName : null ,
48+ type : null ,
49+ } ) ;
50+ }
51+ } , [ open , file ] ) ;
52+
53+ if ( ! file ) return null ;
2554
2655 const handleRemovePassword = async ( ) => {
2756 if ( ! file . password ) return ;
@@ -58,12 +87,12 @@ export default function EditFileDetailsModal({
5887 name ?: string ;
5988 } = { } ;
6089
61- if ( maxViews !== null ) data [ 'maxViews' ] = maxViews ;
62- if ( originalName !== null ) data [ 'originalName' ] = originalName ?. trim ( ) ;
63- if ( type !== null ) data [ 'type' ] = type ?. trim ( ) ;
64- if ( name !== file . name ) data [ 'name' ] = name . trim ( ) ;
90+ if ( formData . maxViews !== null ) data [ 'maxViews' ] = formData . maxViews ;
91+ if ( formData . originalName !== null ) data [ 'originalName' ] = formData . originalName ?. trim ( ) ;
92+ if ( formData . type !== null ) data [ 'type' ] = formData . type ?. trim ( ) ;
93+ if ( formData . name !== file . name ) data [ 'name' ] = formData . name . trim ( ) ;
6594
66- const passwordTrimmed = password ?. trim ( ) ;
95+ const passwordTrimmed = formData . password ?. trim ( ) ;
6796 if ( passwordTrimmed !== '' ) data [ 'password' ] = passwordTrimmed ;
6897
6998 const { error } = await fetchApi ( `/api/user/files/${ file . id } ` , 'PATCH' , data ) ;
@@ -85,47 +114,40 @@ export default function EditFileDetailsModal({
85114
86115 onClose ( ) ;
87116
88- setPassword ( null ) ;
117+ setFormData ( 'password' , null ) ;
89118 mutateFiles ( ) ;
90119 }
91120 } ;
92121
93- useEffect ( ( ) => {
94- if ( open ) {
95- setName ( file . name ?? '' ) ;
96- setMaxViews ( file . maxViews ?? null ) ;
97- setPassword ( file . password ? '' : null ) ;
98- setOriginalName ( file . originalName ?? null ) ;
99- setType ( file . type ?? null ) ;
100- }
101- } , [ open , file ] ) ;
102-
103122 return (
104123 < Modal zIndex = { 300 } title = { `Editing "${ file . name } "` } onClose = { onClose } opened = { open } >
105124 < Stack gap = 'xs' my = 'sm' >
106125 < TextInput
107126 label = 'Name'
108127 description = 'Rename the file.'
109- value = { name }
110- onChange = { ( event ) => setName ( event . currentTarget . value . trim ( ) ) }
128+ value = { formData . name }
129+ onChange = { ( event ) => setFormData ( 'name' , event . currentTarget . value . trim ( ) ) }
111130 />
112131
113132 < NumberInput
114133 label = 'Max Views'
115134 placeholder = 'Unlimited'
116135 description = 'The maximum number of views this file can have before it is deleted. Leave blank to allow as many views as you want.'
117136 min = { 0 }
118- value = { maxViews || '' }
119- onChange = { ( value ) => setMaxViews ( value === '' ? null : Number ( value ) ) }
137+ value = { formData . maxViews || '' }
138+ onChange = { ( value ) => setFormData ( 'maxViews' , value === '' ? null : Number ( value ) ) }
120139 leftSection = { < IconEye size = '1rem' /> }
121140 />
122141
123142 < TextInput
124143 label = 'Original Name'
125144 description = 'Add an original name. When downloading this file, instead of using the generated file name (if chosen), it will download with this "original name" instead.'
126- value = { originalName ?? '' }
145+ value = { formData . originalName ?? '' }
127146 onChange = { ( event ) =>
128- setOriginalName ( event . currentTarget . value . trim ( ) === '' ? null : event . currentTarget . value . trim ( ) )
147+ setFormData (
148+ 'originalName' ,
149+ event . currentTarget . value . trim ( ) === '' ? null : event . currentTarget . value . trim ( ) ,
150+ )
129151 }
130152 />
131153
@@ -137,9 +159,12 @@ export default function EditFileDetailsModal({
137159 doing, this can mess with how Zipline renders specific file types.
138160 </ >
139161 }
140- value = { type ?? '' }
162+ value = { formData . type ?? '' }
141163 onChange = { ( event ) =>
142- setType ( event . currentTarget . value . trim ( ) === '' ? null : event . currentTarget . value . trim ( ) )
164+ setFormData (
165+ 'type' ,
166+ event . currentTarget . value . trim ( ) === '' ? null : event . currentTarget . value . trim ( ) ,
167+ )
143168 }
144169 c = 'red'
145170 />
@@ -159,10 +184,13 @@ export default function EditFileDetailsModal({
159184 < PasswordInput
160185 label = 'Password'
161186 description = 'Set a password for this file. Leave blank to disable password protection.'
162- value = { password ?? '' }
187+ value = { formData . password ?? '' }
163188 autoComplete = 'off'
164189 onChange = { ( event ) =>
165- setPassword ( event . currentTarget . value . trim ( ) === '' ? null : event . currentTarget . value . trim ( ) )
190+ setFormData (
191+ 'password' ,
192+ event . currentTarget . value . trim ( ) === '' ? null : event . currentTarget . value . trim ( ) ,
193+ )
166194 }
167195 leftSection = { < IconKey size = '1rem' /> }
168196 />
0 commit comments