refactor: separate selectAndUploadFile and uploadFile functions (#2085)
This commit is contained in:
@@ -114,7 +114,7 @@ const ContentListView = forwardRef<HTMLDivElement, Props>(
|
||||
}, [selectedTag, application, onPanelWidthLoad])
|
||||
|
||||
const fileDropCallback = useCallback(
|
||||
async (files: FileItem[]) => {
|
||||
async (file: FileItem) => {
|
||||
const currentTag = navigationController.selected
|
||||
|
||||
if (!currentTag) {
|
||||
@@ -126,9 +126,7 @@ const ContentListView = forwardRef<HTMLDivElement, Props>(
|
||||
return
|
||||
}
|
||||
|
||||
files.forEach(async (file) => {
|
||||
await linkingController.linkItems(file, currentTag)
|
||||
})
|
||||
await linkingController.linkItems(file, currentTag)
|
||||
},
|
||||
[navigationController, linkingController],
|
||||
)
|
||||
@@ -170,7 +168,7 @@ const ContentListView = forwardRef<HTMLDivElement, Props>(
|
||||
return
|
||||
}
|
||||
|
||||
void filesController.uploadNewFile()
|
||||
void filesController.selectAndUploadNewFiles()
|
||||
} else {
|
||||
await createNewNote()
|
||||
toggleAppPane(AppPaneId.Editor)
|
||||
|
||||
@@ -11,7 +11,7 @@ import Portal from './Portal/Portal'
|
||||
|
||||
type FileDragTargetData = {
|
||||
tooltipText: string
|
||||
callback: (files: FileItem[]) => void
|
||||
callback: (files: FileItem) => void
|
||||
}
|
||||
|
||||
type FileDnDContextData = {
|
||||
@@ -203,14 +203,14 @@ const FileDragNDropProvider = ({ application, children, featuresController, file
|
||||
return
|
||||
}
|
||||
|
||||
const uploadedFiles = await filesController.uploadNewFile(fileOrHandle)
|
||||
const uploadedFile = await filesController.uploadNewFile(fileOrHandle)
|
||||
|
||||
if (!uploadedFiles) {
|
||||
if (!uploadedFile) {
|
||||
return
|
||||
}
|
||||
|
||||
if (closestDragTarget && dragTargets.current.has(closestDragTarget)) {
|
||||
dragTargets.current.get(closestDragTarget)?.callback(uploadedFiles)
|
||||
dragTargets.current.get(closestDragTarget)?.callback(uploadedFile)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -51,10 +51,8 @@ const FileViewWithoutProtection = ({ application, viewControllerManager, file }:
|
||||
if (target) {
|
||||
addDragTarget(target, {
|
||||
tooltipText: 'Drop your files to upload and link them to the current file',
|
||||
callback(files) {
|
||||
files.forEach(async (uploadedFile) => {
|
||||
await viewControllerManager.linkingController.linkItems(uploadedFile, file)
|
||||
})
|
||||
async callback(uploadedFile) {
|
||||
await viewControllerManager.linkingController.linkItems(uploadedFile, file)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -63,13 +63,9 @@ const LinkedItemsPanel = ({
|
||||
return
|
||||
}
|
||||
|
||||
const uploadedFiles = await filesController.uploadNewFile()
|
||||
|
||||
if (uploadedFiles && uploadedFiles.length) {
|
||||
uploadedFiles.forEach((file) => {
|
||||
void linkItemToSelectedItem(file)
|
||||
})
|
||||
}
|
||||
void filesController.selectAndUploadNewFiles((file) => {
|
||||
void linkItemToSelectedItem(file)
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -20,11 +20,9 @@ const NoteViewFileDropTarget = ({ note, linkingController, noteViewElement, file
|
||||
if (target) {
|
||||
addDragTarget(target, {
|
||||
tooltipText: 'Drop your files to upload and link them to the current note',
|
||||
callback: (files) => {
|
||||
files.forEach(async (uploadedFile) => {
|
||||
await linkingController.linkItems(note, uploadedFile)
|
||||
filesController.notifyObserversOfUploadedFileLinkingToCurrentNote(uploadedFile.uuid)
|
||||
})
|
||||
callback: async (uploadedFile) => {
|
||||
await linkingController.linkItems(note, uploadedFile)
|
||||
filesController.notifyObserversOfUploadedFileLinkingToCurrentNote(uploadedFile.uuid)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -28,11 +28,9 @@ export default function FilePlugin(): JSX.Element | null {
|
||||
const uploadFilesList = (files: FileList) => {
|
||||
Array.from(files).forEach(async (file) => {
|
||||
try {
|
||||
const uploadedFiles = await filesController.uploadNewFile(file)
|
||||
if (uploadedFiles) {
|
||||
uploadedFiles.forEach((uploadedFile) => {
|
||||
editor.dispatchCommand(INSERT_FILE_COMMAND, uploadedFile.uuid)
|
||||
})
|
||||
const uploadedFile = await filesController.uploadNewFile(file)
|
||||
if (uploadedFile) {
|
||||
editor.dispatchCommand(INSERT_FILE_COMMAND, uploadedFile.uuid)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
|
||||
@@ -178,10 +178,8 @@ export const TagsListItem: FunctionComponent<Props> = observer(
|
||||
if (target) {
|
||||
addDragTarget(target, {
|
||||
tooltipText: `Drop your files to upload and link them to tag "${tag.title}"`,
|
||||
callback(files) {
|
||||
files.forEach(async (file) => {
|
||||
await linkingController.linkItems(file, tag)
|
||||
})
|
||||
async callback(file) {
|
||||
await linkingController.linkItems(file, tag)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -56,6 +56,10 @@ export class FilesController extends AbstractViewController<FilesControllerEvent
|
||||
showProtectedOverlay = false
|
||||
fileContextMenuLocation: FileContextMenuLocation = { x: 0, y: 0 }
|
||||
|
||||
shouldUseStreamingReader = StreamingFileSaver.available()
|
||||
reader = this.shouldUseStreamingReader ? StreamingFileReader : ClassicFileReader
|
||||
maxFileSize = this.reader.maximumFileSize()
|
||||
|
||||
override deinit(): void {
|
||||
super.deinit()
|
||||
;(this.notesController as unknown) = undefined
|
||||
@@ -318,98 +322,103 @@ export class FilesController extends AbstractViewController<FilesControllerEvent
|
||||
}
|
||||
}
|
||||
|
||||
public async uploadNewFile(fileOrHandle?: File | FileSystemFileHandle) {
|
||||
alertIfFileExceedsSizeLimit = (file: File): boolean => {
|
||||
if (!this.shouldUseStreamingReader && this.maxFileSize && file.size >= this.maxFileSize) {
|
||||
this.application.alertService
|
||||
.alert(
|
||||
`This file exceeds the limits supported in this browser. To upload files greater than ${
|
||||
this.maxFileSize / BYTES_IN_ONE_MEGABYTE
|
||||
}MB, please use the desktop application or the Chrome browser.`,
|
||||
`Cannot upload file "${file.name}"`,
|
||||
)
|
||||
.catch(console.error)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
public async selectAndUploadNewFiles(callback?: (file: FileItem) => void) {
|
||||
const selectedFiles = await this.reader.selectFiles()
|
||||
|
||||
selectedFiles.forEach(async (file) => {
|
||||
if (this.alertIfFileExceedsSizeLimit(file)) {
|
||||
return
|
||||
}
|
||||
const uploadedFile = await this.uploadNewFile(file)
|
||||
if (uploadedFile && callback) {
|
||||
callback(uploadedFile)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
public async uploadNewFile(fileOrHandle: File | FileSystemFileHandle): Promise<FileItem | undefined> {
|
||||
let toastId = ''
|
||||
|
||||
try {
|
||||
const minimumChunkSize = this.application.files.minimumChunkSize()
|
||||
|
||||
const shouldUseStreamingReader = StreamingFileReader.available()
|
||||
|
||||
const picker = shouldUseStreamingReader ? StreamingFileReader : ClassicFileReader
|
||||
const maxFileSize = picker.maximumFileSize()
|
||||
|
||||
const selectedFiles =
|
||||
fileOrHandle instanceof File
|
||||
? [fileOrHandle]
|
||||
: shouldUseStreamingReader && fileOrHandle instanceof FileSystemFileHandle
|
||||
? await StreamingFileReader.getFilesFromHandles([fileOrHandle])
|
||||
: await picker.selectFiles()
|
||||
|
||||
if (selectedFiles.length === 0) {
|
||||
if (fileOrHandle instanceof FileSystemFileHandle && !this.shouldUseStreamingReader) {
|
||||
return
|
||||
}
|
||||
|
||||
const uploadedFiles: FileItem[] = []
|
||||
const fileToUpload = fileOrHandle instanceof File ? fileOrHandle : await fileOrHandle.getFile()
|
||||
|
||||
for (const file of selectedFiles) {
|
||||
if (!shouldUseStreamingReader && maxFileSize && file.size >= maxFileSize) {
|
||||
this.application.alertService
|
||||
.alert(
|
||||
`This file exceeds the limits supported in this browser. To upload files greater than ${
|
||||
maxFileSize / BYTES_IN_ONE_MEGABYTE
|
||||
}MB, please use the desktop application or the Chrome browser.`,
|
||||
`Cannot upload file "${file.name}"`,
|
||||
)
|
||||
.catch(console.error)
|
||||
continue
|
||||
}
|
||||
if (this.alertIfFileExceedsSizeLimit(fileToUpload)) {
|
||||
return
|
||||
}
|
||||
|
||||
const operation = await this.application.files.beginNewFileUpload(file.size)
|
||||
const operation = await this.application.files.beginNewFileUpload(fileToUpload.size)
|
||||
|
||||
if (operation instanceof ClientDisplayableError) {
|
||||
addToast({
|
||||
type: ToastType.Error,
|
||||
message: 'Unable to start upload session',
|
||||
})
|
||||
throw new Error('Unable to start upload session')
|
||||
}
|
||||
|
||||
const initialProgress = operation.getProgress().percentComplete
|
||||
|
||||
toastId = addToast({
|
||||
type: ToastType.Progress,
|
||||
message: `Uploading file "${file.name}" (${initialProgress}%)`,
|
||||
progress: initialProgress,
|
||||
})
|
||||
|
||||
const onChunk: OnChunkCallbackNoProgress = async ({ data, index, isLast }) => {
|
||||
await this.application.files.pushBytesForUpload(operation, data, index, isLast)
|
||||
|
||||
const percentComplete = Math.round(operation.getProgress().percentComplete)
|
||||
updateToast(toastId, {
|
||||
message: `Uploading file "${file.name}" (${percentComplete}%)`,
|
||||
progress: percentComplete,
|
||||
})
|
||||
}
|
||||
|
||||
const fileResult = await picker.readFile(file, minimumChunkSize, onChunk)
|
||||
|
||||
if (!fileResult.mimeType) {
|
||||
const { ext } = parseFileName(file.name)
|
||||
fileResult.mimeType = await this.application.getArchiveService().getMimeType(ext)
|
||||
}
|
||||
|
||||
const uploadedFile = await this.application.files.finishUpload(operation, fileResult)
|
||||
|
||||
if (uploadedFile instanceof ClientDisplayableError) {
|
||||
addToast({
|
||||
type: ToastType.Error,
|
||||
message: 'Unable to close upload session',
|
||||
})
|
||||
throw new Error('Unable to close upload session')
|
||||
}
|
||||
|
||||
uploadedFiles.push(uploadedFile)
|
||||
|
||||
dismissToast(toastId)
|
||||
if (operation instanceof ClientDisplayableError) {
|
||||
addToast({
|
||||
type: ToastType.Success,
|
||||
message: `Uploaded file "${uploadedFile.name}"`,
|
||||
type: ToastType.Error,
|
||||
message: 'Unable to start upload session',
|
||||
})
|
||||
throw new Error('Unable to start upload session')
|
||||
}
|
||||
|
||||
const initialProgress = operation.getProgress().percentComplete
|
||||
|
||||
toastId = addToast({
|
||||
type: ToastType.Progress,
|
||||
message: `Uploading file "${fileToUpload.name}" (${initialProgress}%)`,
|
||||
progress: initialProgress,
|
||||
})
|
||||
|
||||
const onChunk: OnChunkCallbackNoProgress = async ({ data, index, isLast }) => {
|
||||
await this.application.files.pushBytesForUpload(operation, data, index, isLast)
|
||||
|
||||
const percentComplete = Math.round(operation.getProgress().percentComplete)
|
||||
updateToast(toastId, {
|
||||
message: `Uploading file "${fileToUpload.name}" (${percentComplete}%)`,
|
||||
progress: percentComplete,
|
||||
})
|
||||
}
|
||||
|
||||
return uploadedFiles
|
||||
const fileResult = await this.reader.readFile(fileToUpload, minimumChunkSize, onChunk)
|
||||
|
||||
if (!fileResult.mimeType) {
|
||||
const { ext } = parseFileName(fileToUpload.name)
|
||||
fileResult.mimeType = await this.application.getArchiveService().getMimeType(ext)
|
||||
}
|
||||
|
||||
const uploadedFile = await this.application.files.finishUpload(operation, fileResult)
|
||||
|
||||
if (uploadedFile instanceof ClientDisplayableError) {
|
||||
addToast({
|
||||
type: ToastType.Error,
|
||||
message: 'Unable to close upload session',
|
||||
})
|
||||
throw new Error('Unable to close upload session')
|
||||
}
|
||||
|
||||
dismissToast(toastId)
|
||||
addToast({
|
||||
type: ToastType.Success,
|
||||
message: `Uploaded file "${uploadedFile.name}"`,
|
||||
})
|
||||
|
||||
return uploadedFile
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ export class MomentsService extends AbstractViewController {
|
||||
}
|
||||
}
|
||||
|
||||
public async takePhoto(): Promise<FileItem[] | undefined> {
|
||||
public async takePhoto(): Promise<FileItem | undefined> {
|
||||
const toastId = addToast({
|
||||
type: ToastType.Loading,
|
||||
message: 'Capturing Moment...',
|
||||
@@ -123,7 +123,7 @@ export class MomentsService extends AbstractViewController {
|
||||
|
||||
const defaultTag = this.getDefaultTag()
|
||||
if (defaultTag && uploadedFile) {
|
||||
void this.application.linkingController.linkItems(uploadedFile[0], defaultTag)
|
||||
void this.application.linkingController.linkItems(uploadedFile, defaultTag)
|
||||
}
|
||||
|
||||
stopCameraStream(canvas, video, stream)
|
||||
|
||||
Reference in New Issue
Block a user