@stoker-platform/web-app 0.5.140 → 0.5.142

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @stoker-platform/web-app
2
2
 
3
+ ## 0.5.142
4
+
5
+ ### Patch Changes
6
+
7
+ - feat: add bulk file rename feature
8
+
9
+ ## 0.5.141
10
+
11
+ ### Patch Changes
12
+
13
+ - fix: apply maxImageWidth processing to image file rename operation
14
+
3
15
  ## 0.5.140
4
16
 
5
17
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stoker-platform/web-app",
3
- "version": "0.5.140",
3
+ "version": "0.5.142",
4
4
  "type": "module",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "scripts": {
package/src/Files.tsx CHANGED
@@ -38,7 +38,7 @@ import {
38
38
  Edit,
39
39
  Trash2,
40
40
  Folder,
41
- File,
41
+ File as FileIcon,
42
42
  ChevronRight,
43
43
  ArrowLeft,
44
44
  Plus,
@@ -135,7 +135,7 @@ const FileImageThumbnail = ({ storage, fullPath, fileName, pathPrefix }: FileIma
135
135
  return <div className="h-12 w-12 shrink-0 rounded-md border bg-muted animate-pulse" aria-hidden />
136
136
  }
137
137
  if (phase === "fallback" || !url) {
138
- return <File className="h-5 w-5 shrink-0 text-gray-500" aria-hidden />
138
+ return <FileIcon className="h-5 w-5 shrink-0 text-gray-500" aria-hidden />
139
139
  }
140
140
  return (
141
141
  <div className="h-12 w-12 shrink-0 rounded-md flex items-center justify-center">
@@ -178,10 +178,15 @@ export const RecordFiles = ({ collection, record }: FilesProps) => {
178
178
  const [loading, setLoading] = useState(false)
179
179
  const [editingFile, setEditingFile] = useState<string | null>(null)
180
180
  const [newFileName, setNewFileName] = useState("")
181
+ const [bulkRenameMode, setBulkRenameMode] = useState(false)
182
+ const [bulkRenameNames, setBulkRenameNames] = useState<Record<string, string>>({})
183
+ const [bulkRenameInProgress, setBulkRenameInProgress] = useState(false)
181
184
  const [creatingFolder, setCreatingFolder] = useState(false)
182
185
  const [newFolderName, setNewFolderName] = useState("")
183
186
  const [deletingFiles, setDeletingFiles] = useState<Set<string>>(new Set())
184
187
  const [renamingFiles, setRenamingFiles] = useState<Set<string>>(new Set())
188
+ const [updatingPermissions, setUpdatingPermissions] = useState<Set<string>>(new Set())
189
+ const pendingFileOpsRef = useRef(0)
185
190
  const { setIsRouteLoading } = useRouteLoading()
186
191
 
187
192
  const [showFilenameDialog, setShowFilenameDialog] = useState(false)
@@ -213,6 +218,56 @@ export const RecordFiles = ({ collection, record }: FilesProps) => {
213
218
  }, 150)
214
219
  }, [])
215
220
 
221
+ const beginFileOperation = useCallback(() => {
222
+ if (pendingFileOpsRef.current === 0) {
223
+ setIsRouteLoading("+", location.pathname, true)
224
+ }
225
+ pendingFileOpsRef.current++
226
+ }, [location.pathname, setIsRouteLoading])
227
+
228
+ const endFileOperation = useCallback(() => {
229
+ pendingFileOpsRef.current = Math.max(0, pendingFileOpsRef.current - 1)
230
+ if (pendingFileOpsRef.current === 0) {
231
+ setIsRouteLoading("-", location.pathname)
232
+ }
233
+ }, [location.pathname, setIsRouteLoading])
234
+
235
+ const finishDeleteOperation = useCallback(
236
+ (fileName: string) => {
237
+ setDeletingFiles((prev) => {
238
+ const next = new Set(prev)
239
+ next.delete(fileName)
240
+ return next
241
+ })
242
+ endFileOperation()
243
+ },
244
+ [endFileOperation],
245
+ )
246
+
247
+ const finishRenameOperation = useCallback(
248
+ (fileName: string) => {
249
+ setRenamingFiles((prev) => {
250
+ const next = new Set(prev)
251
+ next.delete(fileName)
252
+ return next
253
+ })
254
+ endFileOperation()
255
+ },
256
+ [endFileOperation],
257
+ )
258
+
259
+ const finishPermissionsOperation = useCallback(
260
+ (fileName: string) => {
261
+ setUpdatingPermissions((prev) => {
262
+ const next = new Set(prev)
263
+ next.delete(fileName)
264
+ return next
265
+ })
266
+ endFileOperation()
267
+ },
268
+ [endFileOperation],
269
+ )
270
+
216
271
  const basePath = record ? `${tenantId}/${record.Collection_Path.join("/")}/${record.id}` : ""
217
272
 
218
273
  const totalPages = Math.ceil(items.length / itemsPerPage)
@@ -224,6 +279,12 @@ export const RecordFiles = ({ collection, record }: FilesProps) => {
224
279
  setCurrentPage(1)
225
280
  }, [items.length])
226
281
 
282
+ useEffect(() => {
283
+ setBulkRenameMode(false)
284
+ setBulkRenameNames({})
285
+ setBulkRenameInProgress(false)
286
+ }, [currentPath])
287
+
227
288
  useEffect(() => {
228
289
  const interval = setInterval(() => {
229
290
  setUploadProgress((prev) =>
@@ -572,8 +633,11 @@ export const RecordFiles = ({ collection, record }: FilesProps) => {
572
633
  async (permissions: FilePermissions) => {
573
634
  if (!selectedFileForPermissions || !record || !currentUser) return
574
635
 
636
+ const fileName = selectedFileForPermissions.name
637
+
575
638
  try {
576
- setIsRouteLoading("+", location.pathname, true)
639
+ beginFileOperation()
640
+ setUpdatingPermissions((prev) => new Set(prev).add(fileName))
577
641
 
578
642
  const targetRef = selectedFileForPermissions.isFolder
579
643
  ? ref(storage, `${selectedFileForPermissions.fullPath}/.placeholder`)
@@ -651,12 +715,12 @@ export const RecordFiles = ({ collection, record }: FilesProps) => {
651
715
  variant: "destructive",
652
716
  })
653
717
  } finally {
654
- setIsRouteLoading("-", location.pathname)
718
+ finishPermissionsOperation(fileName)
655
719
  setShowUpdatePermissionsDialog(false)
656
720
  setSelectedFileForPermissions(null)
657
721
  }
658
722
  },
659
- [selectedFileForPermissions, record, location.pathname, currentPath, currentUser],
723
+ [selectedFileForPermissions, record, currentPath, currentUser, beginFileOperation, finishPermissionsOperation],
660
724
  )
661
725
 
662
726
  const handleUpdatePermissionsCancel = useCallback(() => {
@@ -730,7 +794,7 @@ export const RecordFiles = ({ collection, record }: FilesProps) => {
730
794
  if (!itemToDelete || !record) return
731
795
 
732
796
  try {
733
- setIsRouteLoading("+", location.pathname, true)
797
+ beginFileOperation()
734
798
  setDeletingFiles((prev) => new Set(prev).add(itemToDelete.name))
735
799
 
736
800
  if (itemToDelete.isFolder) {
@@ -757,16 +821,11 @@ export const RecordFiles = ({ collection, record }: FilesProps) => {
757
821
  variant: "destructive",
758
822
  })
759
823
  } finally {
760
- setDeletingFiles((prev) => {
761
- const newSet = new Set(prev)
762
- newSet.delete(itemToDelete.name)
763
- return newSet
764
- })
765
- setIsRouteLoading("-", location.pathname)
824
+ finishDeleteOperation(itemToDelete.name)
766
825
  setShowDeleteDialog(false)
767
826
  setItemToDelete(null)
768
827
  }
769
- }, [itemToDelete, currentPath, location.pathname, record])
828
+ }, [itemToDelete, currentPath, record, beginFileOperation, finishDeleteOperation])
770
829
 
771
830
  const handleDeleteCancel = useCallback(() => {
772
831
  setShowDeleteDialog(false)
@@ -774,30 +833,56 @@ export const RecordFiles = ({ collection, record }: FilesProps) => {
774
833
  }, [])
775
834
 
776
835
  const handleEditName = useCallback(
777
- async (item: StorageItem, newName: string) => {
836
+ async (item: StorageItem, newName: string, options?: { skipReload?: boolean }) => {
778
837
  if (!record) return
779
838
  if (newName === item.name) {
780
839
  setEditingFile(null)
781
840
  return
782
841
  }
783
842
 
784
- const validationError = validateStorageName(newName.trim())
843
+ let finalName = newName.trim()
844
+ const validationError = validateStorageName(finalName)
785
845
  if (validationError) {
786
846
  toast({ title: "Invalid file name", description: validationError, variant: "destructive" })
787
847
  return
788
848
  }
789
849
 
790
850
  try {
791
- setIsRouteLoading("+", location.pathname, true)
851
+ beginFileOperation()
792
852
  setRenamingFiles((prev) => new Set(prev).add(item.name))
793
- const pathParts = item.fullPath.split("/")
794
- pathParts.pop()
795
- const newPath = [...pathParts, newName].join("/")
796
853
 
797
854
  const originalRef = ref(storage, item.fullPath)
798
855
  const downloadURL = await getDownloadURL(originalRef)
799
856
  const metadata = await getMetadata(originalRef)
800
857
 
858
+ const response = await fetch(downloadURL)
859
+ const blob = await response.blob()
860
+
861
+ let uploadContent: Blob = blob
862
+ if (fileOptions?.maxImageWidth) {
863
+ const sourceFile = new File([blob], finalName, {
864
+ type: blob.type || metadata.contentType || "",
865
+ })
866
+ const prepared = await prepareFile(sourceFile, finalName, fileOptions, true)
867
+ uploadContent = prepared.file
868
+ if (prepared.filename !== finalName) {
869
+ const preparedValidationError = validateStorageName(prepared.filename)
870
+ if (preparedValidationError) {
871
+ toast({
872
+ title: "Invalid file name",
873
+ description: preparedValidationError,
874
+ variant: "destructive",
875
+ })
876
+ return
877
+ }
878
+ finalName = prepared.filename
879
+ }
880
+ }
881
+
882
+ const pathParts = item.fullPath.split("/")
883
+ pathParts.pop()
884
+ const newPath = [...pathParts, finalName].join("/")
885
+
801
886
  try {
802
887
  await runHooks("preFileUpdate", globalConfig, customization, {
803
888
  record,
@@ -807,17 +892,14 @@ export const RecordFiles = ({ collection, record }: FilesProps) => {
807
892
  return
808
893
  }
809
894
 
810
- const response = await fetch(downloadURL)
811
- const blob = await response.blob()
812
-
813
895
  const newRef = ref(storage, newPath)
814
- await uploadBytesResumable(newRef, blob, { customMetadata: metadata.customMetadata })
896
+ await uploadBytesResumable(newRef, uploadContent, { customMetadata: metadata.customMetadata })
815
897
 
816
898
  await deleteObject(originalRef)
817
899
 
818
900
  toast({
819
901
  title: "File renamed",
820
- description: `${item.name} has been renamed to ${newName}`,
902
+ description: `${item.name} has been renamed to ${finalName}`,
821
903
  })
822
904
 
823
905
  try {
@@ -831,7 +913,9 @@ export const RecordFiles = ({ collection, record }: FilesProps) => {
831
913
 
832
914
  setEditingFile(null)
833
915
 
834
- loadDirectory(currentPath)
916
+ if (!options?.skipReload) {
917
+ loadDirectory(currentPath)
918
+ }
835
919
  } catch (error) {
836
920
  console.error((error as FirebaseError).message)
837
921
  toast({
@@ -840,33 +924,29 @@ export const RecordFiles = ({ collection, record }: FilesProps) => {
840
924
  variant: "destructive",
841
925
  })
842
926
  } finally {
843
- setRenamingFiles((prev) => {
844
- const newSet = new Set(prev)
845
- newSet.delete(item.name)
846
- return newSet
847
- })
848
- setIsRouteLoading("-", location.pathname)
927
+ finishRenameOperation(item.name)
849
928
  }
850
929
  },
851
- [currentPath],
930
+ [currentPath, fileOptions, beginFileOperation, finishRenameOperation, loadDirectory],
852
931
  )
853
932
 
854
933
  const navigateToFolder = useCallback(
855
934
  (folderName: string) => {
935
+ if (bulkRenameInProgress) return
856
936
  const newPath = currentPath ? `${currentPath}/${folderName}` : folderName
857
937
  loadDirectory(newPath)
858
938
  },
859
- [currentPath],
939
+ [currentPath, bulkRenameInProgress],
860
940
  )
861
941
 
862
942
  const navigateUp = useCallback(() => {
863
- if (!currentPath) return
943
+ if (!currentPath || bulkRenameInProgress) return
864
944
 
865
945
  const pathParts = currentPath.split("/")
866
946
  pathParts.pop()
867
947
  const newPath = pathParts.join("/")
868
948
  loadDirectory(newPath)
869
- }, [currentPath])
949
+ }, [currentPath, bulkRenameInProgress])
870
950
 
871
951
  const getPathBreadcrumbs = useCallback(() => {
872
952
  if (!currentPath) return []
@@ -947,6 +1027,59 @@ export const RecordFiles = ({ collection, record }: FilesProps) => {
947
1027
  setShowFolderPermissionsDialog(false)
948
1028
  }, [])
949
1029
 
1030
+ const canEditFile = useCallback(
1031
+ (item: StorageItem) => {
1032
+ if (item.isFolder) return false
1033
+ return (
1034
+ (permissions?.Role && item.metadata?.update?.includes(permissions.Role)) ||
1035
+ (currentUser && item.metadata?.createdBy === currentUser.uid)
1036
+ )
1037
+ },
1038
+ [permissions, currentUser],
1039
+ )
1040
+
1041
+ const startBulkRename = useCallback(() => {
1042
+ const editableFiles = items.filter(canEditFile)
1043
+ if (editableFiles.length === 0) return
1044
+ setEditingFile(null)
1045
+ setBulkRenameNames(Object.fromEntries(editableFiles.map((item) => [item.name, item.name])))
1046
+ setBulkRenameMode(true)
1047
+ }, [items, canEditFile])
1048
+
1049
+ const exitBulkRename = useCallback(() => {
1050
+ setBulkRenameMode(false)
1051
+ setBulkRenameNames({})
1052
+ setBulkRenameInProgress(false)
1053
+ }, [])
1054
+
1055
+ const cancelBulkRename = useCallback(() => {
1056
+ if (bulkRenameInProgress) return
1057
+ exitBulkRename()
1058
+ }, [bulkRenameInProgress, exitBulkRename])
1059
+
1060
+ const handleRenameAll = useCallback(async () => {
1061
+ const filesToRename = items
1062
+ .filter((item) => canEditFile(item) && bulkRenameNames[item.name] !== item.name)
1063
+ .map((item) => ({ item, newName: bulkRenameNames[item.name] }))
1064
+
1065
+ if (filesToRename.length === 0) {
1066
+ exitBulkRename()
1067
+ return
1068
+ }
1069
+
1070
+ setBulkRenameInProgress(true)
1071
+ try {
1072
+ await Promise.all(
1073
+ filesToRename.map(({ item, newName }) => handleEditName(item, newName, { skipReload: true })),
1074
+ )
1075
+ await loadDirectory(currentPath)
1076
+ } finally {
1077
+ exitBulkRename()
1078
+ }
1079
+ }, [items, bulkRenameNames, canEditFile, handleEditName, exitBulkRename, loadDirectory, currentPath])
1080
+
1081
+ const editableFileCount = items.filter(canEditFile).length
1082
+
950
1083
  let borderClass = "border-primary/40"
951
1084
  let textClass = "text-primary/50"
952
1085
  if (isDragOver) {
@@ -965,7 +1098,13 @@ export const RecordFiles = ({ collection, record }: FilesProps) => {
965
1098
 
966
1099
  <div className="flex items-center space-x-2 mb-4">
967
1100
  {currentPath && (
968
- <Button variant="outline" size="sm" onClick={navigateUp} className="flex items-center space-x-1">
1101
+ <Button
1102
+ variant="outline"
1103
+ size="sm"
1104
+ onClick={navigateUp}
1105
+ disabled={bulkRenameInProgress}
1106
+ className="flex items-center space-x-1"
1107
+ >
969
1108
  <ArrowLeft className="h-4 w-4" />
970
1109
  <span>Back</span>
971
1110
  </Button>
@@ -996,7 +1135,7 @@ export const RecordFiles = ({ collection, record }: FilesProps) => {
996
1135
  >
997
1136
  <div className={cn("text-center font-bold", textClass)}>Drop files here</div>
998
1137
  </div>
999
- <div className="flex items-center space-x-2 mt-4">
1138
+ <div className="flex flex-col gap-2 mt-4 sm:flex-row sm:items-center sm:gap-0 sm:space-x-2">
1000
1139
  <input
1001
1140
  type="file"
1002
1141
  multiple
@@ -1010,15 +1149,52 @@ export const RecordFiles = ({ collection, record }: FilesProps) => {
1010
1149
  cursor-pointer"
1011
1150
  onChange={handleFileUpload}
1012
1151
  />
1013
- <Button
1014
- variant="outline"
1015
- size="sm"
1016
- onClick={() => setCreatingFolder(true)}
1017
- className="flex items-center space-x-1 whitespace-nowrap"
1018
- >
1019
- <Plus className="h-4 w-4" />
1020
- <span>New Folder</span>
1021
- </Button>
1152
+ <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-0 sm:space-x-2 shrink-0">
1153
+ <Button
1154
+ variant="outline"
1155
+ size="sm"
1156
+ onClick={() => setCreatingFolder(true)}
1157
+ disabled={bulkRenameMode}
1158
+ className="flex items-center space-x-1 whitespace-nowrap"
1159
+ >
1160
+ <Plus className="h-4 w-4" />
1161
+ <span>New Folder</span>
1162
+ </Button>
1163
+ {bulkRenameMode ? (
1164
+ <>
1165
+ <Button
1166
+ size="sm"
1167
+ onClick={handleRenameAll}
1168
+ disabled={bulkRenameInProgress}
1169
+ className="flex items-center space-x-1 whitespace-nowrap"
1170
+ >
1171
+ <Edit className="h-4 w-4" />
1172
+ <span>Rename All</span>
1173
+ </Button>
1174
+ <Button
1175
+ variant="outline"
1176
+ size="sm"
1177
+ onClick={cancelBulkRename}
1178
+ disabled={bulkRenameInProgress}
1179
+ className="whitespace-nowrap"
1180
+ >
1181
+ Cancel
1182
+ </Button>
1183
+ </>
1184
+ ) : (
1185
+ editableFileCount > 0 && (
1186
+ <Button
1187
+ variant="outline"
1188
+ size="sm"
1189
+ onClick={startBulkRename}
1190
+ className="flex items-center space-x-2 whitespace-nowrap"
1191
+ >
1192
+ <Edit className="h-4 w-4" />
1193
+ <span>Rename Files</span>
1194
+ </Button>
1195
+ )
1196
+ )}
1197
+ </div>
1022
1198
  </div>
1023
1199
 
1024
1200
  {uploadProgress.length > 0 && (
@@ -1107,7 +1283,8 @@ export const RecordFiles = ({ collection, record }: FilesProps) => {
1107
1283
  {currentItems.map((item, index) => {
1108
1284
  const isDeleting = deletingFiles.has(item.name)
1109
1285
  const isRenaming = renamingFiles.has(item.name)
1110
- const isDisabled = isDeleting || isRenaming
1286
+ const isUpdatingPermissions = updatingPermissions.has(item.name)
1287
+ const isDisabled = isDeleting || isRenaming || isUpdatingPermissions
1111
1288
 
1112
1289
  return (
1113
1290
  <div
@@ -1132,43 +1309,71 @@ export const RecordFiles = ({ collection, record }: FilesProps) => {
1132
1309
  }
1133
1310
  />
1134
1311
  ) : (
1135
- <File className="h-5 w-5 shrink-0 text-gray-500" />
1312
+ <FileIcon className="h-5 w-5 shrink-0 text-gray-500" />
1136
1313
  )}
1137
1314
 
1138
- {editingFile === item.name && !isDisabled ? (
1315
+ {(bulkRenameMode && canEditFile(item)) ||
1316
+ (editingFile === item.name && !isDisabled) ? (
1139
1317
  <div className="flex items-center space-x-2 flex-1">
1140
1318
  <Input
1141
- value={newFileName}
1142
- onChange={(e) => setNewFileName(e.target.value)}
1319
+ value={
1320
+ bulkRenameMode
1321
+ ? bulkRenameNames[item.name]
1322
+ : newFileName
1323
+ }
1324
+ disabled={bulkRenameMode && bulkRenameInProgress}
1325
+ onChange={(event) => {
1326
+ if (bulkRenameMode) {
1327
+ setBulkRenameNames((prev) => ({
1328
+ ...prev,
1329
+ [item.name]: event.target.value,
1330
+ }))
1331
+ } else {
1332
+ setNewFileName(event.target.value)
1333
+ }
1334
+ }}
1143
1335
  className="flex-1"
1144
1336
  onKeyDown={(e) => {
1145
- if (e.key === "Enter") {
1146
- handleEditName(item, newFileName)
1147
- } else if (e.key === "Escape") {
1148
- setEditingFile(null)
1337
+ if (!bulkRenameMode) {
1338
+ if (e.key === "Enter") {
1339
+ handleEditName(item, newFileName)
1340
+ } else if (e.key === "Escape") {
1341
+ setEditingFile(null)
1342
+ }
1149
1343
  }
1150
1344
  }}
1151
1345
  />
1152
- <Button
1153
- size="sm"
1154
- onClick={() => handleEditName(item, newFileName)}
1155
- >
1156
- Save
1157
- </Button>
1158
- <Button
1159
- size="sm"
1160
- variant="outline"
1161
- onClick={() => setEditingFile(null)}
1162
- >
1163
- Cancel
1164
- </Button>
1346
+ {!bulkRenameMode && (
1347
+ <>
1348
+ <Button
1349
+ size="sm"
1350
+ onClick={() => handleEditName(item, newFileName)}
1351
+ >
1352
+ Save
1353
+ </Button>
1354
+ <Button
1355
+ size="sm"
1356
+ variant="outline"
1357
+ onClick={() => setEditingFile(null)}
1358
+ >
1359
+ Cancel
1360
+ </Button>
1361
+ </>
1362
+ )}
1165
1363
  </div>
1166
1364
  ) : (
1167
1365
  <div className="flex-1 min-w-0">
1168
1366
  {item.isFolder ? (
1169
1367
  <button
1368
+ type="button"
1170
1369
  onClick={() => navigateToFolder(item.name)}
1171
- className="text-left hover:underline block w-full"
1370
+ disabled={bulkRenameInProgress}
1371
+ className={cn(
1372
+ "text-left block w-full",
1373
+ bulkRenameInProgress
1374
+ ? "cursor-not-allowed opacity-50"
1375
+ : "hover:underline",
1376
+ )}
1172
1377
  >
1173
1378
  {item.name}
1174
1379
  </button>
@@ -1179,7 +1384,10 @@ export const RecordFiles = ({ collection, record }: FilesProps) => {
1179
1384
  )}
1180
1385
  </div>
1181
1386
 
1182
- {!(editingFile === item.name && !isDisabled) && (
1387
+ {!(
1388
+ (bulkRenameMode && canEditFile(item)) ||
1389
+ (editingFile === item.name && !isDisabled)
1390
+ ) && (
1183
1391
  <div className="flex items-center space-x-2">
1184
1392
  {!item.isFolder && (
1185
1393
  <>
@@ -1199,10 +1407,11 @@ export const RecordFiles = ({ collection, record }: FilesProps) => {
1199
1407
  size="sm"
1200
1408
  variant="outline"
1201
1409
  onClick={() => {
1410
+ cancelBulkRename()
1202
1411
  setEditingFile(item.name)
1203
1412
  setNewFileName(item.name)
1204
1413
  }}
1205
- disabled={isDisabled}
1414
+ disabled={isDisabled || bulkRenameMode}
1206
1415
  >
1207
1416
  <Edit className="h-4 w-4" />
1208
1417
  </Button>
@@ -33,6 +33,7 @@ export const prepareFile = async (
33
33
  file: File,
34
34
  preferredFileName: string,
35
35
  fileOptions: FileOptions,
36
+ rename: boolean = false,
36
37
  ): Promise<{ file: File; filename: string }> => {
37
38
  if (!file.type.startsWith("image/") || file.type === "image/svg+xml") {
38
39
  return { file, filename: preferredFileName }
@@ -107,7 +108,7 @@ export const prepareFile = async (
107
108
  blob.size >= file.size &&
108
109
  !didDownscale &&
109
110
  ((usePngOutput && file.type === "image/png") || (!usePngOutput && file.type === "image/jpeg"))
110
- if (noBenefit) {
111
+ if (noBenefit && !rename) {
111
112
  return { file, filename: preferredFileName }
112
113
  }
113
114