feat: remove attached files button from files view (#1193)
This commit is contained in:
@@ -24,6 +24,7 @@ import FileContextMenuWrapper from '@/Components/FileContextMenu/FileContextMenu
|
|||||||
import PermissionsModalWrapper from '@/Components/PermissionsModal/PermissionsModalWrapper'
|
import PermissionsModalWrapper from '@/Components/PermissionsModal/PermissionsModalWrapper'
|
||||||
import { PanelResizedData } from '@/Types/PanelResizedData'
|
import { PanelResizedData } from '@/Types/PanelResizedData'
|
||||||
import TagContextMenuWrapper from '@/Components/Tags/TagContextMenuWrapper'
|
import TagContextMenuWrapper from '@/Components/Tags/TagContextMenuWrapper'
|
||||||
|
import FileDragNDropProvider from '../FileDragNDropProvider/FileDragNDropProvider'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
application: WebApplication
|
application: WebApplication
|
||||||
@@ -176,19 +177,25 @@ const ApplicationView: FunctionComponent<Props> = ({ application, mainApplicatio
|
|||||||
<PremiumModalProvider application={application} viewControllerManager={viewControllerManager}>
|
<PremiumModalProvider application={application} viewControllerManager={viewControllerManager}>
|
||||||
<div className={platformString + ' main-ui-view sn-component'}>
|
<div className={platformString + ' main-ui-view sn-component'}>
|
||||||
<div id="app" className={appClass + ' app app-column-container'}>
|
<div id="app" className={appClass + ' app app-column-container'}>
|
||||||
<Navigation application={application} />
|
<FileDragNDropProvider
|
||||||
<ContentListView
|
|
||||||
application={application}
|
application={application}
|
||||||
accountMenuController={viewControllerManager.accountMenuController}
|
featuresController={viewControllerManager.featuresController}
|
||||||
filesController={viewControllerManager.filesController}
|
filesController={viewControllerManager.filesController}
|
||||||
itemListController={viewControllerManager.itemListController}
|
>
|
||||||
navigationController={viewControllerManager.navigationController}
|
<Navigation application={application} />
|
||||||
noAccountWarningController={viewControllerManager.noAccountWarningController}
|
<ContentListView
|
||||||
noteTagsController={viewControllerManager.noteTagsController}
|
application={application}
|
||||||
notesController={viewControllerManager.notesController}
|
accountMenuController={viewControllerManager.accountMenuController}
|
||||||
selectionController={viewControllerManager.selectionController}
|
filesController={viewControllerManager.filesController}
|
||||||
/>
|
itemListController={viewControllerManager.itemListController}
|
||||||
<NoteGroupView application={application} />
|
navigationController={viewControllerManager.navigationController}
|
||||||
|
noAccountWarningController={viewControllerManager.noAccountWarningController}
|
||||||
|
noteTagsController={viewControllerManager.noteTagsController}
|
||||||
|
notesController={viewControllerManager.notesController}
|
||||||
|
selectionController={viewControllerManager.selectionController}
|
||||||
|
/>
|
||||||
|
<NoteGroupView application={application} />
|
||||||
|
</FileDragNDropProvider>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -6,19 +6,18 @@ import { observer } from 'mobx-react-lite'
|
|||||||
import { FunctionComponent, useCallback, useEffect, useRef, useState } from 'react'
|
import { FunctionComponent, useCallback, useEffect, useRef, useState } from 'react'
|
||||||
import Icon from '@/Components/Icon/Icon'
|
import Icon from '@/Components/Icon/Icon'
|
||||||
import { useCloseOnBlur } from '@/Hooks/useCloseOnBlur'
|
import { useCloseOnBlur } from '@/Hooks/useCloseOnBlur'
|
||||||
import { FileItem, SNNote } from '@standardnotes/snjs'
|
|
||||||
import { addToast, ToastType } from '@standardnotes/toast'
|
|
||||||
import { StreamingFileReader } from '@standardnotes/filepicker'
|
|
||||||
import AttachedFilesPopover from './AttachedFilesPopover'
|
import AttachedFilesPopover from './AttachedFilesPopover'
|
||||||
import { usePremiumModal } from '@/Hooks/usePremiumModal'
|
import { usePremiumModal } from '@/Hooks/usePremiumModal'
|
||||||
import { PopoverTabs } from './PopoverTabs'
|
import { PopoverTabs } from './PopoverTabs'
|
||||||
import { isHandlingFileDrag } from '@/Utils/DragTypeCheck'
|
|
||||||
import { NotesController } from '@/Controllers/NotesController'
|
import { NotesController } from '@/Controllers/NotesController'
|
||||||
import { FilePreviewModalController } from '@/Controllers/FilePreviewModalController'
|
import { FilePreviewModalController } from '@/Controllers/FilePreviewModalController'
|
||||||
import { NavigationController } from '@/Controllers/Navigation/NavigationController'
|
import { NavigationController } from '@/Controllers/Navigation/NavigationController'
|
||||||
import { FeaturesController } from '@/Controllers/FeaturesController'
|
import { FeaturesController } from '@/Controllers/FeaturesController'
|
||||||
import { FilesController } from '@/Controllers/FilesController'
|
import { FilesController } from '@/Controllers/FilesController'
|
||||||
import { SelectedItemsController } from '@/Controllers/SelectedItemsController'
|
import { SelectedItemsController } from '@/Controllers/SelectedItemsController'
|
||||||
|
import { useFileDragNDrop } from '@/Components/FileDragNDropProvider/FileDragNDropProvider'
|
||||||
|
import { FileItem, SNNote } from '@standardnotes/snjs'
|
||||||
|
import { addToast, ToastType } from '@standardnotes/toast'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
application: WebApplication
|
application: WebApplication
|
||||||
@@ -120,7 +119,7 @@ const AttachedFilesButton: FunctionComponent<Props> = ({
|
|||||||
if (!note) {
|
if (!note) {
|
||||||
addToast({
|
addToast({
|
||||||
type: ToastType.Error,
|
type: ToastType.Error,
|
||||||
message: 'Could not attach file because selected note was deleted',
|
message: 'Could not attach file because selected note was unselected or deleted',
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -130,135 +129,36 @@ const AttachedFilesButton: FunctionComponent<Props> = ({
|
|||||||
[application.items, note],
|
[application.items, note],
|
||||||
)
|
)
|
||||||
|
|
||||||
const [isDraggingFiles, setIsDraggingFiles] = useState(false)
|
const { isDraggingFiles, addFilesDragInCallback, addFilesDropCallback } = useFileDragNDrop()
|
||||||
const dragCounter = useRef(0)
|
|
||||||
|
|
||||||
const handleDrag = useCallback(
|
useEffect(() => {
|
||||||
(event: DragEvent) => {
|
if (isDraggingFiles && !open) {
|
||||||
if (isHandlingFileDrag(event, application)) {
|
void toggleAttachedFilesMenu()
|
||||||
event.preventDefault()
|
}
|
||||||
event.stopPropagation()
|
}, [isDraggingFiles, open, toggleAttachedFilesMenu])
|
||||||
}
|
|
||||||
},
|
|
||||||
[application],
|
|
||||||
)
|
|
||||||
|
|
||||||
const handleDragIn = useCallback(
|
const filesDragInCallback = useCallback((tab: PopoverTabs) => {
|
||||||
(event: DragEvent) => {
|
setCurrentTab(tab)
|
||||||
if (!isHandlingFileDrag(event, application)) {
|
}, [])
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
event.preventDefault()
|
useEffect(() => {
|
||||||
event.stopPropagation()
|
addFilesDragInCallback(filesDragInCallback)
|
||||||
|
}, [addFilesDragInCallback, filesDragInCallback])
|
||||||
|
|
||||||
switch ((event.target as HTMLElement).id) {
|
const filesDropCallback = useCallback(
|
||||||
case PopoverTabs.AllFiles:
|
(uploadedFiles: FileItem[]) => {
|
||||||
setCurrentTab(PopoverTabs.AllFiles)
|
if (currentTab === PopoverTabs.AttachedFiles) {
|
||||||
break
|
uploadedFiles.forEach((file) => {
|
||||||
case PopoverTabs.AttachedFiles:
|
attachFileToNote(file).catch(console.error)
|
||||||
setCurrentTab(PopoverTabs.AttachedFiles)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
dragCounter.current = dragCounter.current + 1
|
|
||||||
|
|
||||||
if (event.dataTransfer?.items.length) {
|
|
||||||
setIsDraggingFiles(true)
|
|
||||||
if (!open) {
|
|
||||||
toggleAttachedFilesMenu().catch(console.error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[open, toggleAttachedFilesMenu, application],
|
|
||||||
)
|
|
||||||
|
|
||||||
const handleDragOut = useCallback(
|
|
||||||
(event: DragEvent) => {
|
|
||||||
if (!isHandlingFileDrag(event, application)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
event.preventDefault()
|
|
||||||
event.stopPropagation()
|
|
||||||
|
|
||||||
dragCounter.current = dragCounter.current - 1
|
|
||||||
|
|
||||||
if (dragCounter.current > 0) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsDraggingFiles(false)
|
|
||||||
},
|
|
||||||
[application],
|
|
||||||
)
|
|
||||||
|
|
||||||
const handleDrop = useCallback(
|
|
||||||
(event: DragEvent) => {
|
|
||||||
if (!isHandlingFileDrag(event, application)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
event.preventDefault()
|
|
||||||
event.stopPropagation()
|
|
||||||
|
|
||||||
setIsDraggingFiles(false)
|
|
||||||
|
|
||||||
if (!featuresController.hasFiles) {
|
|
||||||
prospectivelyShowFilesPremiumModal()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.dataTransfer?.items.length) {
|
|
||||||
Array.from(event.dataTransfer.items).forEach(async (item) => {
|
|
||||||
const fileOrHandle = StreamingFileReader.available()
|
|
||||||
? ((await item.getAsFileSystemHandle()) as FileSystemFileHandle)
|
|
||||||
: item.getAsFile()
|
|
||||||
|
|
||||||
if (!fileOrHandle) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const uploadedFiles = await filesController.uploadNewFile(fileOrHandle)
|
|
||||||
|
|
||||||
if (!uploadedFiles) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentTab === PopoverTabs.AttachedFiles) {
|
|
||||||
uploadedFiles.forEach((file) => {
|
|
||||||
attachFileToNote(file).catch(console.error)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
event.dataTransfer.clearData()
|
|
||||||
dragCounter.current = 0
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[
|
[attachFileToNote, currentTab],
|
||||||
filesController,
|
|
||||||
featuresController.hasFiles,
|
|
||||||
attachFileToNote,
|
|
||||||
currentTab,
|
|
||||||
application,
|
|
||||||
prospectivelyShowFilesPremiumModal,
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.addEventListener('dragenter', handleDragIn)
|
addFilesDropCallback(filesDropCallback)
|
||||||
window.addEventListener('dragleave', handleDragOut)
|
}, [addFilesDropCallback, filesDropCallback])
|
||||||
window.addEventListener('dragover', handleDrag)
|
|
||||||
window.addEventListener('drop', handleDrop)
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
window.removeEventListener('dragenter', handleDragIn)
|
|
||||||
window.removeEventListener('dragleave', handleDragOut)
|
|
||||||
window.removeEventListener('dragover', handleDrag)
|
|
||||||
window.removeEventListener('drop', handleDrop)
|
|
||||||
}
|
|
||||||
}, [handleDragIn, handleDrop, handleDrag, handleDragOut])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={containerRef}>
|
<div ref={containerRef}>
|
||||||
|
|||||||
@@ -0,0 +1,181 @@
|
|||||||
|
import { WebApplication } from '@/Application/Application'
|
||||||
|
import { FeaturesController } from '@/Controllers/FeaturesController'
|
||||||
|
import { FilesController } from '@/Controllers/FilesController'
|
||||||
|
import { usePremiumModal } from '@/Hooks/usePremiumModal'
|
||||||
|
import { isHandlingFileDrag } from '@/Utils/DragTypeCheck'
|
||||||
|
import { StreamingFileReader } from '@standardnotes/filepicker'
|
||||||
|
import { FileItem } from '@standardnotes/snjs'
|
||||||
|
import { useMemo, useState, createContext, ReactNode, useRef, useCallback, useEffect, useContext } from 'react'
|
||||||
|
import { PopoverTabs } from '../AttachedFilesPopover/PopoverTabs'
|
||||||
|
|
||||||
|
type FilesDragInCallback = (tab: PopoverTabs) => void
|
||||||
|
type FilesDropCallback = (uploadedFiles: FileItem[]) => void
|
||||||
|
|
||||||
|
type FileDnDContextData = {
|
||||||
|
isDraggingFiles: boolean
|
||||||
|
addFilesDragInCallback: (callback: FilesDragInCallback) => void
|
||||||
|
addFilesDropCallback: (callback: FilesDropCallback) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export const FileDnDContext = createContext<FileDnDContextData | null>(null)
|
||||||
|
|
||||||
|
export const useFileDragNDrop = () => {
|
||||||
|
const value = useContext(FileDnDContext)
|
||||||
|
|
||||||
|
if (!value) {
|
||||||
|
throw new Error('Current component must be a child of <FileDragNDropProvider />')
|
||||||
|
}
|
||||||
|
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
application: WebApplication
|
||||||
|
featuresController: FeaturesController
|
||||||
|
filesController: FilesController
|
||||||
|
children: ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
const FileDragNDropProvider = ({ application, children, featuresController, filesController }: Props) => {
|
||||||
|
const premiumModal = usePremiumModal()
|
||||||
|
const [isDraggingFiles, setIsDraggingFiles] = useState(false)
|
||||||
|
|
||||||
|
const filesDragInCallbackRef = useRef<FilesDragInCallback>()
|
||||||
|
const filesDropCallbackRef = useRef<FilesDropCallback>()
|
||||||
|
|
||||||
|
const addFilesDragInCallback = useCallback((callback: FilesDragInCallback) => {
|
||||||
|
filesDragInCallbackRef.current = callback
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const addFilesDropCallback = useCallback((callback: FilesDropCallback) => {
|
||||||
|
filesDropCallbackRef.current = callback
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const dragCounter = useRef(0)
|
||||||
|
|
||||||
|
const handleDrag = useCallback(
|
||||||
|
(event: DragEvent) => {
|
||||||
|
if (isHandlingFileDrag(event, application)) {
|
||||||
|
event.preventDefault()
|
||||||
|
event.stopPropagation()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[application],
|
||||||
|
)
|
||||||
|
|
||||||
|
const handleDragIn = useCallback(
|
||||||
|
(event: DragEvent) => {
|
||||||
|
if (!isHandlingFileDrag(event, application)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
event.preventDefault()
|
||||||
|
event.stopPropagation()
|
||||||
|
|
||||||
|
switch ((event.target as HTMLElement).id) {
|
||||||
|
case PopoverTabs.AllFiles:
|
||||||
|
filesDragInCallbackRef.current?.(PopoverTabs.AllFiles)
|
||||||
|
break
|
||||||
|
case PopoverTabs.AttachedFiles:
|
||||||
|
filesDragInCallbackRef.current?.(PopoverTabs.AttachedFiles)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
dragCounter.current = dragCounter.current + 1
|
||||||
|
|
||||||
|
if (event.dataTransfer?.items.length) {
|
||||||
|
setIsDraggingFiles(true)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[application],
|
||||||
|
)
|
||||||
|
|
||||||
|
const handleDragOut = useCallback(
|
||||||
|
(event: DragEvent) => {
|
||||||
|
if (!isHandlingFileDrag(event, application)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
event.preventDefault()
|
||||||
|
event.stopPropagation()
|
||||||
|
|
||||||
|
dragCounter.current = dragCounter.current - 1
|
||||||
|
|
||||||
|
if (dragCounter.current > 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setIsDraggingFiles(false)
|
||||||
|
},
|
||||||
|
[application],
|
||||||
|
)
|
||||||
|
|
||||||
|
const handleDrop = useCallback(
|
||||||
|
(event: DragEvent) => {
|
||||||
|
if (!isHandlingFileDrag(event, application)) {
|
||||||
|
setIsDraggingFiles(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
event.preventDefault()
|
||||||
|
event.stopPropagation()
|
||||||
|
|
||||||
|
setIsDraggingFiles(false)
|
||||||
|
|
||||||
|
if (!featuresController.hasFiles) {
|
||||||
|
premiumModal.activate('Files')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.dataTransfer?.items.length) {
|
||||||
|
Array.from(event.dataTransfer.items).forEach(async (item) => {
|
||||||
|
const fileOrHandle = StreamingFileReader.available()
|
||||||
|
? ((await item.getAsFileSystemHandle()) as FileSystemFileHandle)
|
||||||
|
: item.getAsFile()
|
||||||
|
|
||||||
|
if (!fileOrHandle) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const uploadedFiles = await filesController.uploadNewFile(fileOrHandle)
|
||||||
|
|
||||||
|
if (!uploadedFiles) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
filesDropCallbackRef.current?.(uploadedFiles)
|
||||||
|
})
|
||||||
|
|
||||||
|
event.dataTransfer.clearData()
|
||||||
|
dragCounter.current = 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[application, featuresController.hasFiles, filesController, premiumModal],
|
||||||
|
)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
window.addEventListener('dragenter', handleDragIn)
|
||||||
|
window.addEventListener('dragleave', handleDragOut)
|
||||||
|
window.addEventListener('dragover', handleDrag)
|
||||||
|
window.addEventListener('drop', handleDrop)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('dragenter', handleDragIn)
|
||||||
|
window.removeEventListener('dragleave', handleDragOut)
|
||||||
|
window.removeEventListener('dragover', handleDrag)
|
||||||
|
window.removeEventListener('drop', handleDrop)
|
||||||
|
}
|
||||||
|
}, [handleDragIn, handleDrop, handleDrag, handleDragOut])
|
||||||
|
|
||||||
|
const contextValue = useMemo(() => {
|
||||||
|
return {
|
||||||
|
isDraggingFiles,
|
||||||
|
addFilesDragInCallback,
|
||||||
|
addFilesDropCallback,
|
||||||
|
}
|
||||||
|
}, [addFilesDragInCallback, addFilesDropCallback, isDraggingFiles])
|
||||||
|
|
||||||
|
return <FileDnDContext.Provider value={contextValue}>{children}</FileDnDContext.Provider>
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FileDragNDropProvider
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
import { ElementIds } from '@/Constants/ElementIDs'
|
import { ElementIds } from '@/Constants/ElementIDs'
|
||||||
import { observer } from 'mobx-react-lite'
|
import { observer } from 'mobx-react-lite'
|
||||||
import { ChangeEventHandler, useCallback, useRef } from 'react'
|
import { ChangeEventHandler, useCallback, useRef } from 'react'
|
||||||
import AttachedFilesButton from '@/Components/AttachedFilesPopover/AttachedFilesButton'
|
|
||||||
import FileOptionsPanel from '@/Components/FileContextMenu/FileOptionsPanel'
|
import FileOptionsPanel from '@/Components/FileContextMenu/FileOptionsPanel'
|
||||||
import FilePreview from '@/Components/FilePreview/FilePreview'
|
import FilePreview from '@/Components/FilePreview/FilePreview'
|
||||||
import { FileViewProps } from './FileViewProps'
|
import { FileViewProps } from './FileViewProps'
|
||||||
@@ -53,17 +52,6 @@ const FileViewWithoutProtection = ({ application, viewControllerManager, file }:
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<div className="mr-3">
|
|
||||||
<AttachedFilesButton
|
|
||||||
application={application}
|
|
||||||
featuresController={viewControllerManager.featuresController}
|
|
||||||
filePreviewModalController={viewControllerManager.filePreviewModalController}
|
|
||||||
filesController={viewControllerManager.filesController}
|
|
||||||
navigationController={viewControllerManager.navigationController}
|
|
||||||
notesController={viewControllerManager.notesController}
|
|
||||||
selectionController={viewControllerManager.selectionController}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<FileOptionsPanel
|
<FileOptionsPanel
|
||||||
filesController={viewControllerManager.filesController}
|
filesController={viewControllerManager.filesController}
|
||||||
selectionController={viewControllerManager.selectionController}
|
selectionController={viewControllerManager.selectionController}
|
||||||
|
|||||||
@@ -5,32 +5,13 @@ import { useCallback } from 'react'
|
|||||||
import FileOptionsPanel from '../FileContextMenu/FileOptionsPanel'
|
import FileOptionsPanel from '../FileContextMenu/FileOptionsPanel'
|
||||||
import { FilesController } from '@/Controllers/FilesController'
|
import { FilesController } from '@/Controllers/FilesController'
|
||||||
import { SelectedItemsController } from '@/Controllers/SelectedItemsController'
|
import { SelectedItemsController } from '@/Controllers/SelectedItemsController'
|
||||||
import { WebApplication } from '@/Application/Application'
|
|
||||||
import { FeaturesController } from '@/Controllers/FeaturesController'
|
|
||||||
import { FilePreviewModalController } from '@/Controllers/FilePreviewModalController'
|
|
||||||
import { NavigationController } from '@/Controllers/Navigation/NavigationController'
|
|
||||||
import { NotesController } from '@/Controllers/NotesController'
|
|
||||||
import AttachedFilesButton from '../AttachedFilesPopover/AttachedFilesButton'
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
application: WebApplication
|
|
||||||
featuresController: FeaturesController
|
|
||||||
filePreviewModalController: FilePreviewModalController
|
|
||||||
filesController: FilesController
|
filesController: FilesController
|
||||||
navigationController: NavigationController
|
|
||||||
notesController: NotesController
|
|
||||||
selectionController: SelectedItemsController
|
selectionController: SelectedItemsController
|
||||||
}
|
}
|
||||||
|
|
||||||
const MultipleSelectedFiles = ({
|
const MultipleSelectedFiles = ({ filesController, selectionController }: Props) => {
|
||||||
application,
|
|
||||||
filesController,
|
|
||||||
featuresController,
|
|
||||||
filePreviewModalController,
|
|
||||||
navigationController,
|
|
||||||
notesController,
|
|
||||||
selectionController,
|
|
||||||
}: Props) => {
|
|
||||||
const count = selectionController.selectedFilesCount
|
const count = selectionController.selectedFilesCount
|
||||||
|
|
||||||
const cancelMultipleSelection = useCallback(() => {
|
const cancelMultipleSelection = useCallback(() => {
|
||||||
@@ -41,18 +22,7 @@ const MultipleSelectedFiles = ({
|
|||||||
<div className="flex h-full flex-col items-center">
|
<div className="flex h-full flex-col items-center">
|
||||||
<div className="flex w-full items-center justify-between p-4">
|
<div className="flex w-full items-center justify-between p-4">
|
||||||
<h1 className="m-0 text-lg font-bold">{count} selected files</h1>
|
<h1 className="m-0 text-lg font-bold">{count} selected files</h1>
|
||||||
<div className="flex">
|
<div>
|
||||||
<div className="mr-3">
|
|
||||||
<AttachedFilesButton
|
|
||||||
application={application}
|
|
||||||
featuresController={featuresController}
|
|
||||||
filePreviewModalController={filePreviewModalController}
|
|
||||||
filesController={filesController}
|
|
||||||
navigationController={navigationController}
|
|
||||||
notesController={notesController}
|
|
||||||
selectionController={selectionController}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<FileOptionsPanel filesController={filesController} selectionController={selectionController} />
|
<FileOptionsPanel filesController={filesController} selectionController={selectionController} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import NoteView from '@/Components/NoteView/NoteView'
|
|||||||
import MultipleSelectedFiles from '../MultipleSelectedFiles/MultipleSelectedFiles'
|
import MultipleSelectedFiles from '../MultipleSelectedFiles/MultipleSelectedFiles'
|
||||||
import { ElementIds } from '@/Constants/ElementIDs'
|
import { ElementIds } from '@/Constants/ElementIDs'
|
||||||
import FileView from '@/Components/FileView/FileView'
|
import FileView from '@/Components/FileView/FileView'
|
||||||
|
import { FileDnDContext } from '@/Components/FileDragNDropProvider/FileDragNDropProvider'
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
showMultipleSelectedNotes: boolean
|
showMultipleSelectedNotes: boolean
|
||||||
@@ -19,6 +20,9 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class NoteGroupView extends PureComponent<Props, State> {
|
class NoteGroupView extends PureComponent<Props, State> {
|
||||||
|
static override contextType = FileDnDContext
|
||||||
|
declare context: React.ContextType<typeof FileDnDContext>
|
||||||
|
|
||||||
private removeChangeObserver!: () => void
|
private removeChangeObserver!: () => void
|
||||||
|
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
@@ -77,6 +81,8 @@ class NoteGroupView extends PureComponent<Props, State> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override render() {
|
override render() {
|
||||||
|
const fileDragNDropContext = this.context
|
||||||
|
|
||||||
const shouldNotShowMultipleSelectedItems =
|
const shouldNotShowMultipleSelectedItems =
|
||||||
!this.state.showMultipleSelectedNotes && !this.state.showMultipleSelectedFiles
|
!this.state.showMultipleSelectedNotes && !this.state.showMultipleSelectedFiles
|
||||||
|
|
||||||
@@ -98,16 +104,17 @@ class NoteGroupView extends PureComponent<Props, State> {
|
|||||||
|
|
||||||
{this.state.showMultipleSelectedFiles && (
|
{this.state.showMultipleSelectedFiles && (
|
||||||
<MultipleSelectedFiles
|
<MultipleSelectedFiles
|
||||||
application={this.application}
|
|
||||||
filesController={this.viewControllerManager.filesController}
|
filesController={this.viewControllerManager.filesController}
|
||||||
selectionController={this.viewControllerManager.selectionController}
|
selectionController={this.viewControllerManager.selectionController}
|
||||||
featuresController={this.viewControllerManager.featuresController}
|
|
||||||
filePreviewModalController={this.viewControllerManager.filePreviewModalController}
|
|
||||||
navigationController={this.viewControllerManager.navigationController}
|
|
||||||
notesController={this.viewControllerManager.notesController}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{this.viewControllerManager.navigationController.isInFilesView && fileDragNDropContext?.isDraggingFiles && (
|
||||||
|
<div className="absolute bottom-8 left-1/2 z-dropdown-menu -translate-x-1/2 rounded bg-info px-5 py-3 text-info-contrast shadow-main">
|
||||||
|
Drop your files to upload them to Standard Notes
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{shouldNotShowMultipleSelectedItems && this.state.controllers.length > 0 && (
|
{shouldNotShowMultipleSelectedItems && this.state.controllers.length > 0 && (
|
||||||
<>
|
<>
|
||||||
{this.state.controllers.map((controller) => {
|
{this.state.controllers.map((controller) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user