refactor: separate selectAndUploadFile and uploadFile functions (#2085)
This commit is contained in:
@@ -114,7 +114,7 @@ const ContentListView = forwardRef<HTMLDivElement, Props>(
|
|||||||
}, [selectedTag, application, onPanelWidthLoad])
|
}, [selectedTag, application, onPanelWidthLoad])
|
||||||
|
|
||||||
const fileDropCallback = useCallback(
|
const fileDropCallback = useCallback(
|
||||||
async (files: FileItem[]) => {
|
async (file: FileItem) => {
|
||||||
const currentTag = navigationController.selected
|
const currentTag = navigationController.selected
|
||||||
|
|
||||||
if (!currentTag) {
|
if (!currentTag) {
|
||||||
@@ -126,9 +126,7 @@ const ContentListView = forwardRef<HTMLDivElement, Props>(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
files.forEach(async (file) => {
|
await linkingController.linkItems(file, currentTag)
|
||||||
await linkingController.linkItems(file, currentTag)
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
[navigationController, linkingController],
|
[navigationController, linkingController],
|
||||||
)
|
)
|
||||||
@@ -170,7 +168,7 @@ const ContentListView = forwardRef<HTMLDivElement, Props>(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
void filesController.uploadNewFile()
|
void filesController.selectAndUploadNewFiles()
|
||||||
} else {
|
} else {
|
||||||
await createNewNote()
|
await createNewNote()
|
||||||
toggleAppPane(AppPaneId.Editor)
|
toggleAppPane(AppPaneId.Editor)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import Portal from './Portal/Portal'
|
|||||||
|
|
||||||
type FileDragTargetData = {
|
type FileDragTargetData = {
|
||||||
tooltipText: string
|
tooltipText: string
|
||||||
callback: (files: FileItem[]) => void
|
callback: (files: FileItem) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
type FileDnDContextData = {
|
type FileDnDContextData = {
|
||||||
@@ -203,14 +203,14 @@ const FileDragNDropProvider = ({ application, children, featuresController, file
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const uploadedFiles = await filesController.uploadNewFile(fileOrHandle)
|
const uploadedFile = await filesController.uploadNewFile(fileOrHandle)
|
||||||
|
|
||||||
if (!uploadedFiles) {
|
if (!uploadedFile) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (closestDragTarget && dragTargets.current.has(closestDragTarget)) {
|
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) {
|
if (target) {
|
||||||
addDragTarget(target, {
|
addDragTarget(target, {
|
||||||
tooltipText: 'Drop your files to upload and link them to the current file',
|
tooltipText: 'Drop your files to upload and link them to the current file',
|
||||||
callback(files) {
|
async callback(uploadedFile) {
|
||||||
files.forEach(async (uploadedFile) => {
|
await viewControllerManager.linkingController.linkItems(uploadedFile, file)
|
||||||
await viewControllerManager.linkingController.linkItems(uploadedFile, file)
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,13 +63,9 @@ const LinkedItemsPanel = ({
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const uploadedFiles = await filesController.uploadNewFile()
|
void filesController.selectAndUploadNewFiles((file) => {
|
||||||
|
void linkItemToSelectedItem(file)
|
||||||
if (uploadedFiles && uploadedFiles.length) {
|
})
|
||||||
uploadedFiles.forEach((file) => {
|
|
||||||
void linkItemToSelectedItem(file)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -20,11 +20,9 @@ const NoteViewFileDropTarget = ({ note, linkingController, noteViewElement, file
|
|||||||
if (target) {
|
if (target) {
|
||||||
addDragTarget(target, {
|
addDragTarget(target, {
|
||||||
tooltipText: 'Drop your files to upload and link them to the current note',
|
tooltipText: 'Drop your files to upload and link them to the current note',
|
||||||
callback: (files) => {
|
callback: async (uploadedFile) => {
|
||||||
files.forEach(async (uploadedFile) => {
|
await linkingController.linkItems(note, uploadedFile)
|
||||||
await linkingController.linkItems(note, uploadedFile)
|
filesController.notifyObserversOfUploadedFileLinkingToCurrentNote(uploadedFile.uuid)
|
||||||
filesController.notifyObserversOfUploadedFileLinkingToCurrentNote(uploadedFile.uuid)
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,11 +28,9 @@ export default function FilePlugin(): JSX.Element | null {
|
|||||||
const uploadFilesList = (files: FileList) => {
|
const uploadFilesList = (files: FileList) => {
|
||||||
Array.from(files).forEach(async (file) => {
|
Array.from(files).forEach(async (file) => {
|
||||||
try {
|
try {
|
||||||
const uploadedFiles = await filesController.uploadNewFile(file)
|
const uploadedFile = await filesController.uploadNewFile(file)
|
||||||
if (uploadedFiles) {
|
if (uploadedFile) {
|
||||||
uploadedFiles.forEach((uploadedFile) => {
|
editor.dispatchCommand(INSERT_FILE_COMMAND, uploadedFile.uuid)
|
||||||
editor.dispatchCommand(INSERT_FILE_COMMAND, uploadedFile.uuid)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
|
|||||||
@@ -178,10 +178,8 @@ export const TagsListItem: FunctionComponent<Props> = observer(
|
|||||||
if (target) {
|
if (target) {
|
||||||
addDragTarget(target, {
|
addDragTarget(target, {
|
||||||
tooltipText: `Drop your files to upload and link them to tag "${tag.title}"`,
|
tooltipText: `Drop your files to upload and link them to tag "${tag.title}"`,
|
||||||
callback(files) {
|
async callback(file) {
|
||||||
files.forEach(async (file) => {
|
await linkingController.linkItems(file, tag)
|
||||||
await linkingController.linkItems(file, tag)
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,10 @@ export class FilesController extends AbstractViewController<FilesControllerEvent
|
|||||||
showProtectedOverlay = false
|
showProtectedOverlay = false
|
||||||
fileContextMenuLocation: FileContextMenuLocation = { x: 0, y: 0 }
|
fileContextMenuLocation: FileContextMenuLocation = { x: 0, y: 0 }
|
||||||
|
|
||||||
|
shouldUseStreamingReader = StreamingFileSaver.available()
|
||||||
|
reader = this.shouldUseStreamingReader ? StreamingFileReader : ClassicFileReader
|
||||||
|
maxFileSize = this.reader.maximumFileSize()
|
||||||
|
|
||||||
override deinit(): void {
|
override deinit(): void {
|
||||||
super.deinit()
|
super.deinit()
|
||||||
;(this.notesController as unknown) = undefined
|
;(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 = ''
|
let toastId = ''
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const minimumChunkSize = this.application.files.minimumChunkSize()
|
const minimumChunkSize = this.application.files.minimumChunkSize()
|
||||||
|
|
||||||
const shouldUseStreamingReader = StreamingFileReader.available()
|
if (fileOrHandle instanceof FileSystemFileHandle && !this.shouldUseStreamingReader) {
|
||||||
|
|
||||||
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) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const uploadedFiles: FileItem[] = []
|
const fileToUpload = fileOrHandle instanceof File ? fileOrHandle : await fileOrHandle.getFile()
|
||||||
|
|
||||||
for (const file of selectedFiles) {
|
if (this.alertIfFileExceedsSizeLimit(fileToUpload)) {
|
||||||
if (!shouldUseStreamingReader && maxFileSize && file.size >= maxFileSize) {
|
return
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
const operation = await this.application.files.beginNewFileUpload(file.size)
|
const operation = await this.application.files.beginNewFileUpload(fileToUpload.size)
|
||||||
|
|
||||||
if (operation instanceof ClientDisplayableError) {
|
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)
|
|
||||||
addToast({
|
addToast({
|
||||||
type: ToastType.Success,
|
type: ToastType.Error,
|
||||||
message: `Uploaded file "${uploadedFile.name}"`,
|
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) {
|
} catch (error) {
|
||||||
console.error(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({
|
const toastId = addToast({
|
||||||
type: ToastType.Loading,
|
type: ToastType.Loading,
|
||||||
message: 'Capturing Moment...',
|
message: 'Capturing Moment...',
|
||||||
@@ -123,7 +123,7 @@ export class MomentsService extends AbstractViewController {
|
|||||||
|
|
||||||
const defaultTag = this.getDefaultTag()
|
const defaultTag = this.getDefaultTag()
|
||||||
if (defaultTag && uploadedFile) {
|
if (defaultTag && uploadedFile) {
|
||||||
void this.application.linkingController.linkItems(uploadedFile[0], defaultTag)
|
void this.application.linkingController.linkItems(uploadedFile, defaultTag)
|
||||||
}
|
}
|
||||||
|
|
||||||
stopCameraStream(canvas, video, stream)
|
stopCameraStream(canvas, video, stream)
|
||||||
|
|||||||
Reference in New Issue
Block a user