fix: don't close popover when previewing file (#1017)
This commit is contained in:
@@ -22,7 +22,7 @@ import { PremiumModalProvider } from '@/Hooks/usePremiumModal'
|
|||||||
import { ConfirmSignoutContainer } from '@/Components/ConfirmSignoutModal'
|
import { ConfirmSignoutContainer } from '@/Components/ConfirmSignoutModal'
|
||||||
import { TagsContextMenu } from '@/Components/Tags/TagContextMenu'
|
import { TagsContextMenu } from '@/Components/Tags/TagContextMenu'
|
||||||
import { ToastContainer } from '@standardnotes/stylekit'
|
import { ToastContainer } from '@standardnotes/stylekit'
|
||||||
import { FilePreviewModalProvider } from '@/Components/Files/FilePreviewModalProvider'
|
import { FilePreviewModal } from '../Files/FilePreviewModal'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
application: WebApplication
|
application: WebApplication
|
||||||
@@ -169,54 +169,53 @@ export class ApplicationView extends PureComponent<Props, State> {
|
|||||||
const renderAppContents = !this.state.needsUnlock && this.state.launched
|
const renderAppContents = !this.state.needsUnlock && this.state.launched
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FilePreviewModalProvider application={this.application}>
|
<PremiumModalProvider application={this.application} appState={this.appState}>
|
||||||
<PremiumModalProvider application={this.application} appState={this.appState}>
|
<div className={this.platformString + ' main-ui-view sn-component'}>
|
||||||
<div className={this.platformString + ' main-ui-view sn-component'}>
|
{renderAppContents && (
|
||||||
{renderAppContents && (
|
<div id="app" className={this.state.appClass + ' app app-column-container'}>
|
||||||
<div id="app" className={this.state.appClass + ' app app-column-container'}>
|
<Navigation application={this.application} />
|
||||||
<Navigation application={this.application} />
|
<NotesView application={this.application} appState={this.appState} />
|
||||||
<NotesView application={this.application} appState={this.appState} />
|
<NoteGroupView application={this.application} />
|
||||||
<NoteGroupView application={this.application} />
|
</div>
|
||||||
</div>
|
)}
|
||||||
)}
|
{renderAppContents && (
|
||||||
{renderAppContents && (
|
<>
|
||||||
<>
|
<Footer application={this.application} applicationGroup={this.props.mainApplicationGroup} />
|
||||||
<Footer application={this.application} applicationGroup={this.props.mainApplicationGroup} />
|
<SessionsModal application={this.application} appState={this.appState} />
|
||||||
<SessionsModal application={this.application} appState={this.appState} />
|
<PreferencesViewWrapper appState={this.appState} application={this.application} />
|
||||||
<PreferencesViewWrapper appState={this.appState} application={this.application} />
|
<RevisionHistoryModalWrapper application={this.application} appState={this.appState} />
|
||||||
<RevisionHistoryModalWrapper application={this.application} appState={this.appState} />
|
</>
|
||||||
</>
|
)}
|
||||||
)}
|
{this.state.challenges.map((challenge) => {
|
||||||
{this.state.challenges.map((challenge) => {
|
return (
|
||||||
return (
|
<div className="sk-modal">
|
||||||
<div className="sk-modal">
|
<ChallengeModal
|
||||||
<ChallengeModal
|
key={challenge.id}
|
||||||
key={challenge.id}
|
|
||||||
application={this.application}
|
|
||||||
appState={this.appState}
|
|
||||||
mainApplicationGroup={this.props.mainApplicationGroup}
|
|
||||||
challenge={challenge}
|
|
||||||
onDismiss={this.removeChallenge}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
{renderAppContents && (
|
|
||||||
<>
|
|
||||||
<NotesContextMenu application={this.application} appState={this.appState} />
|
|
||||||
<TagsContextMenu appState={this.appState} />
|
|
||||||
<PurchaseFlowWrapper application={this.application} appState={this.appState} />
|
|
||||||
<ConfirmSignoutContainer
|
|
||||||
applicationGroup={this.props.mainApplicationGroup}
|
|
||||||
appState={this.appState}
|
|
||||||
application={this.application}
|
application={this.application}
|
||||||
|
appState={this.appState}
|
||||||
|
mainApplicationGroup={this.props.mainApplicationGroup}
|
||||||
|
challenge={challenge}
|
||||||
|
onDismiss={this.removeChallenge}
|
||||||
/>
|
/>
|
||||||
<ToastContainer />
|
</div>
|
||||||
</>
|
)
|
||||||
)}
|
})}
|
||||||
</div>
|
{renderAppContents && (
|
||||||
</PremiumModalProvider>
|
<>
|
||||||
</FilePreviewModalProvider>
|
<NotesContextMenu application={this.application} appState={this.appState} />
|
||||||
|
<TagsContextMenu appState={this.appState} />
|
||||||
|
<PurchaseFlowWrapper application={this.application} appState={this.appState} />
|
||||||
|
<ConfirmSignoutContainer
|
||||||
|
applicationGroup={this.props.mainApplicationGroup}
|
||||||
|
appState={this.appState}
|
||||||
|
application={this.application}
|
||||||
|
/>
|
||||||
|
<ToastContainer />
|
||||||
|
<FilePreviewModal application={this.application} appState={this.appState} />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</PremiumModalProvider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import { StreamingFileReader } from '@standardnotes/filepicker'
|
|||||||
import { PopoverFileItemAction, PopoverFileItemActionType } from './PopoverFileItemAction'
|
import { PopoverFileItemAction, PopoverFileItemActionType } from './PopoverFileItemAction'
|
||||||
import { AttachedFilesPopover } from './AttachedFilesPopover'
|
import { AttachedFilesPopover } from './AttachedFilesPopover'
|
||||||
import { usePremiumModal } from '@/Hooks/usePremiumModal'
|
import { usePremiumModal } from '@/Hooks/usePremiumModal'
|
||||||
import { useFilePreviewModal } from '../Files/FilePreviewModalProvider'
|
|
||||||
import { PopoverTabs } from './PopoverTabs'
|
import { PopoverTabs } from './PopoverTabs'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -30,7 +29,6 @@ const isHandlingFileDrag = (event: DragEvent) =>
|
|||||||
export const AttachedFilesButton: FunctionComponent<Props> = observer(
|
export const AttachedFilesButton: FunctionComponent<Props> = observer(
|
||||||
({ application, appState, onClickPreprocessing }) => {
|
({ application, appState, onClickPreprocessing }) => {
|
||||||
const premiumModal = usePremiumModal()
|
const premiumModal = usePremiumModal()
|
||||||
const filePreviewModal = useFilePreviewModal()
|
|
||||||
|
|
||||||
const note: SNNote | undefined = Object.values(appState.notes.selectedNotes)[0]
|
const note: SNNote | undefined = Object.values(appState.notes.selectedNotes)[0]
|
||||||
|
|
||||||
@@ -45,6 +43,14 @@ export const AttachedFilesButton: FunctionComponent<Props> = observer(
|
|||||||
const containerRef = useRef<HTMLDivElement>(null)
|
const containerRef = useRef<HTMLDivElement>(null)
|
||||||
const [closeOnBlur, keepMenuOpen] = useCloseOnBlur(containerRef, setOpen)
|
const [closeOnBlur, keepMenuOpen] = useCloseOnBlur(containerRef, setOpen)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (appState.filePreviewModal.isOpen) {
|
||||||
|
keepMenuOpen(true)
|
||||||
|
} else {
|
||||||
|
keepMenuOpen(false)
|
||||||
|
}
|
||||||
|
}, [appState.filePreviewModal.isOpen, keepMenuOpen])
|
||||||
|
|
||||||
const [currentTab, setCurrentTab] = useState(PopoverTabs.AttachedFiles)
|
const [currentTab, setCurrentTab] = useState(PopoverTabs.AttachedFiles)
|
||||||
const [allFiles, setAllFiles] = useState<SNFile[]>([])
|
const [allFiles, setAllFiles] = useState<SNFile[]>([])
|
||||||
const [attachedFiles, setAttachedFiles] = useState<SNFile[]>([])
|
const [attachedFiles, setAttachedFiles] = useState<SNFile[]>([])
|
||||||
@@ -205,7 +211,8 @@ export const AttachedFilesButton: FunctionComponent<Props> = observer(
|
|||||||
await renameFile(file, action.payload.name)
|
await renameFile(file, action.payload.name)
|
||||||
break
|
break
|
||||||
case PopoverFileItemActionType.PreviewFile:
|
case PopoverFileItemActionType.PreviewFile:
|
||||||
filePreviewModal.activate(file, currentTab === PopoverTabs.AllFiles ? allFiles : attachedFiles)
|
keepMenuOpen(true)
|
||||||
|
appState.filePreviewModal.activate(file, currentTab === PopoverTabs.AllFiles ? allFiles : attachedFiles)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { WebApplication } from '@/UIModels/Application'
|
import { WebApplication } from '@/UIModels/Application'
|
||||||
import { concatenateUint8Arrays } from '@/Utils/ConcatenateUint8Arrays'
|
import { concatenateUint8Arrays } from '@/Utils/ConcatenateUint8Arrays'
|
||||||
import { DialogContent, DialogOverlay } from '@reach/dialog'
|
import { DialogContent, DialogOverlay } from '@reach/dialog'
|
||||||
import { SNFile } from '@standardnotes/snjs'
|
|
||||||
import { addToast, NoPreviewIllustration, ToastType } from '@standardnotes/stylekit'
|
import { addToast, NoPreviewIllustration, ToastType } from '@standardnotes/stylekit'
|
||||||
import { FunctionComponent } from 'preact'
|
import { FunctionComponent } from 'preact'
|
||||||
import { useCallback, useEffect, useRef, useState } from 'preact/hooks'
|
import { useCallback, useEffect, useRef, useState } from 'preact/hooks'
|
||||||
@@ -12,18 +11,21 @@ import { FilePreviewInfoPanel } from './FilePreviewInfoPanel'
|
|||||||
import { isFileTypePreviewable } from './isFilePreviewable'
|
import { isFileTypePreviewable } from './isFilePreviewable'
|
||||||
import { PreviewComponent } from './PreviewComponent'
|
import { PreviewComponent } from './PreviewComponent'
|
||||||
import { FOCUSABLE_BUT_NOT_TABBABLE } from '@/Constants'
|
import { FOCUSABLE_BUT_NOT_TABBABLE } from '@/Constants'
|
||||||
import { useFilePreviewModal } from './FilePreviewModalProvider'
|
|
||||||
import { KeyboardKey } from '@/Services/IOService'
|
import { KeyboardKey } from '@/Services/IOService'
|
||||||
|
import { AppState } from '@/UIModels/AppState'
|
||||||
|
import { observer } from 'mobx-react-lite'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
application: WebApplication
|
application: WebApplication
|
||||||
files: SNFile[]
|
appState: AppState
|
||||||
file: SNFile
|
|
||||||
onDismiss: () => void
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FilePreviewModal: FunctionComponent<Props> = ({ application, files, file, onDismiss }) => {
|
export const FilePreviewModal: FunctionComponent<Props> = observer(({ application, appState }) => {
|
||||||
const context = useFilePreviewModal()
|
const { currentFile, setCurrentFile, otherFiles, dismiss, isOpen } = appState.filePreviewModal
|
||||||
|
|
||||||
|
if (!currentFile || !isOpen) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
const [objectUrl, setObjectUrl] = useState<string>()
|
const [objectUrl, setObjectUrl] = useState<string>()
|
||||||
const [isFilePreviewable, setIsFilePreviewable] = useState(false)
|
const [isFilePreviewable, setIsFilePreviewable] = useState(false)
|
||||||
@@ -37,7 +39,7 @@ export const FilePreviewModal: FunctionComponent<Props> = ({ application, files,
|
|||||||
try {
|
try {
|
||||||
const chunks: Uint8Array[] = []
|
const chunks: Uint8Array[] = []
|
||||||
setFileDownloadProgress(0)
|
setFileDownloadProgress(0)
|
||||||
await application.files.downloadFile(file, async (decryptedChunk, progress) => {
|
await application.files.downloadFile(currentFile, async (decryptedChunk, progress) => {
|
||||||
chunks.push(decryptedChunk)
|
chunks.push(decryptedChunk)
|
||||||
if (progress) {
|
if (progress) {
|
||||||
setFileDownloadProgress(Math.round(progress.percentComplete))
|
setFileDownloadProgress(Math.round(progress.percentComplete))
|
||||||
@@ -47,7 +49,7 @@ export const FilePreviewModal: FunctionComponent<Props> = ({ application, files,
|
|||||||
setObjectUrl(
|
setObjectUrl(
|
||||||
URL.createObjectURL(
|
URL.createObjectURL(
|
||||||
new Blob([finalDecryptedBytes], {
|
new Blob([finalDecryptedBytes], {
|
||||||
type: file.mimeType,
|
type: currentFile.mimeType,
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -56,32 +58,32 @@ export const FilePreviewModal: FunctionComponent<Props> = ({ application, files,
|
|||||||
} finally {
|
} finally {
|
||||||
setIsLoadingFile(false)
|
setIsLoadingFile(false)
|
||||||
}
|
}
|
||||||
}, [application.files, file])
|
}, [application.files, currentFile])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setIsLoadingFile(true)
|
setIsLoadingFile(true)
|
||||||
}, [file.uuid])
|
}, [currentFile.uuid])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const isPreviewable = isFileTypePreviewable(file.mimeType)
|
const isPreviewable = isFileTypePreviewable(currentFile.mimeType)
|
||||||
setIsFilePreviewable(isPreviewable)
|
setIsFilePreviewable(isPreviewable)
|
||||||
|
|
||||||
if (!isPreviewable) {
|
if (!isPreviewable) {
|
||||||
setIsLoadingFile(false)
|
setIsLoadingFile(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentFileIdRef.current !== file.uuid && isPreviewable) {
|
if (currentFileIdRef.current !== currentFile.uuid && isPreviewable) {
|
||||||
getObjectUrl().catch(console.error)
|
getObjectUrl().catch(console.error)
|
||||||
}
|
}
|
||||||
|
|
||||||
currentFileIdRef.current = file.uuid
|
currentFileIdRef.current = currentFile.uuid
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
if (objectUrl) {
|
if (objectUrl) {
|
||||||
URL.revokeObjectURL(objectUrl)
|
URL.revokeObjectURL(objectUrl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [file, getObjectUrl, objectUrl])
|
}, [currentFile, getObjectUrl, objectUrl])
|
||||||
|
|
||||||
const keyDownHandler = (event: KeyboardEvent) => {
|
const keyDownHandler = (event: KeyboardEvent) => {
|
||||||
if (event.key !== KeyboardKey.Left && event.key !== KeyboardKey.Right) {
|
if (event.key !== KeyboardKey.Left && event.key !== KeyboardKey.Right) {
|
||||||
@@ -90,22 +92,22 @@ export const FilePreviewModal: FunctionComponent<Props> = ({ application, files,
|
|||||||
|
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|
||||||
const currentFileIndex = files.findIndex((fileFromArray) => fileFromArray.uuid === file.uuid)
|
const currentFileIndex = otherFiles.findIndex((fileFromArray) => fileFromArray.uuid === currentFile.uuid)
|
||||||
|
|
||||||
switch (event.key) {
|
switch (event.key) {
|
||||||
case KeyboardKey.Left: {
|
case KeyboardKey.Left: {
|
||||||
const previousFileIndex = currentFileIndex - 1 >= 0 ? currentFileIndex - 1 : files.length - 1
|
const previousFileIndex = currentFileIndex - 1 >= 0 ? currentFileIndex - 1 : otherFiles.length - 1
|
||||||
const previousFile = files[previousFileIndex]
|
const previousFile = otherFiles[previousFileIndex]
|
||||||
if (previousFile) {
|
if (previousFile) {
|
||||||
context.setCurrentFile(previousFile)
|
setCurrentFile(previousFile)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case KeyboardKey.Right: {
|
case KeyboardKey.Right: {
|
||||||
const nextFileIndex = currentFileIndex + 1 < files.length ? currentFileIndex + 1 : 0
|
const nextFileIndex = currentFileIndex + 1 < otherFiles.length ? currentFileIndex + 1 : 0
|
||||||
const nextFile = files[nextFileIndex]
|
const nextFile = otherFiles[nextFileIndex]
|
||||||
if (nextFile) {
|
if (nextFile) {
|
||||||
context.setCurrentFile(nextFile)
|
setCurrentFile(nextFile)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -116,7 +118,7 @@ export const FilePreviewModal: FunctionComponent<Props> = ({ application, files,
|
|||||||
<DialogOverlay
|
<DialogOverlay
|
||||||
className="sn-component"
|
className="sn-component"
|
||||||
aria-label="File preview modal"
|
aria-label="File preview modal"
|
||||||
onDismiss={onDismiss}
|
onDismiss={dismiss}
|
||||||
initialFocusRef={closeButtonRef}
|
initialFocusRef={closeButtonRef}
|
||||||
dangerouslyBypassScrollLock
|
dangerouslyBypassScrollLock
|
||||||
>
|
>
|
||||||
@@ -137,11 +139,11 @@ export const FilePreviewModal: FunctionComponent<Props> = ({ application, files,
|
|||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<div className="w-6 h-6">
|
<div className="w-6 h-6">
|
||||||
{getFileIconComponent(
|
{getFileIconComponent(
|
||||||
application.iconsController.getIconForFileType(file.mimeType),
|
application.iconsController.getIconForFileType(currentFile.mimeType),
|
||||||
'w-6 h-6 flex-shrink-0',
|
'w-6 h-6 flex-shrink-0',
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<span className="ml-3 font-medium">{file.name}</span>
|
<span className="ml-3 font-medium">{currentFile.name}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<button
|
<button
|
||||||
@@ -155,7 +157,7 @@ export const FilePreviewModal: FunctionComponent<Props> = ({ application, files,
|
|||||||
variant="primary"
|
variant="primary"
|
||||||
className="mr-4"
|
className="mr-4"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
application.getArchiveService().downloadData(objectUrl, file.name)
|
application.getArchiveService().downloadData(objectUrl, currentFile.name)
|
||||||
addToast({
|
addToast({
|
||||||
type: ToastType.Success,
|
type: ToastType.Success,
|
||||||
message: 'Successfully downloaded file',
|
message: 'Successfully downloaded file',
|
||||||
@@ -167,7 +169,7 @@ export const FilePreviewModal: FunctionComponent<Props> = ({ application, files,
|
|||||||
)}
|
)}
|
||||||
<button
|
<button
|
||||||
ref={closeButtonRef}
|
ref={closeButtonRef}
|
||||||
onClick={onDismiss}
|
onClick={dismiss}
|
||||||
aria-label="Close modal"
|
aria-label="Close modal"
|
||||||
className="flex p-1 bg-transparent hover:bg-contrast border-0 cursor-pointer rounded"
|
className="flex p-1 bg-transparent hover:bg-contrast border-0 cursor-pointer rounded"
|
||||||
>
|
>
|
||||||
@@ -186,7 +188,7 @@ export const FilePreviewModal: FunctionComponent<Props> = ({ application, files,
|
|||||||
<span className="mt-3">Loading file...</span>
|
<span className="mt-3">Loading file...</span>
|
||||||
</div>
|
</div>
|
||||||
) : objectUrl ? (
|
) : objectUrl ? (
|
||||||
<PreviewComponent file={file} objectUrl={objectUrl} />
|
<PreviewComponent file={currentFile} objectUrl={objectUrl} />
|
||||||
) : (
|
) : (
|
||||||
<div className="flex flex-col items-center">
|
<div className="flex flex-col items-center">
|
||||||
<NoPreviewIllustration className="w-30 h-30 mb-4" />
|
<NoPreviewIllustration className="w-30 h-30 mb-4" />
|
||||||
@@ -210,7 +212,7 @@ export const FilePreviewModal: FunctionComponent<Props> = ({ application, files,
|
|||||||
<Button
|
<Button
|
||||||
variant="normal"
|
variant="normal"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
application.getAppState().files.downloadFile(file).catch(console.error)
|
application.getAppState().files.downloadFile(currentFile).catch(console.error)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Download
|
Download
|
||||||
@@ -225,7 +227,7 @@ export const FilePreviewModal: FunctionComponent<Props> = ({ application, files,
|
|||||||
<Button
|
<Button
|
||||||
variant="primary"
|
variant="primary"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
application.getAppState().files.downloadFile(file).catch(console.error)
|
application.getAppState().files.downloadFile(currentFile).catch(console.error)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Download
|
Download
|
||||||
@@ -235,9 +237,9 @@ export const FilePreviewModal: FunctionComponent<Props> = ({ application, files,
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{showFileInfoPanel && <FilePreviewInfoPanel file={file} />}
|
{showFileInfoPanel && <FilePreviewInfoPanel file={currentFile} />}
|
||||||
</div>
|
</div>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</DialogOverlay>
|
</DialogOverlay>
|
||||||
)
|
)
|
||||||
}
|
})
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
import { WebApplication } from '@/UIModels/Application'
|
|
||||||
import { SNFile } from '@standardnotes/snjs'
|
|
||||||
import { createContext, FunctionComponent } from 'preact'
|
|
||||||
import { useContext, useState } from 'preact/hooks'
|
|
||||||
import { FilePreviewModal } from './FilePreviewModal'
|
|
||||||
|
|
||||||
type FilePreviewActivateFunction = (file: SNFile, files: SNFile[]) => void
|
|
||||||
|
|
||||||
type FilePreviewModalContextData = {
|
|
||||||
activate: FilePreviewActivateFunction
|
|
||||||
setCurrentFile: (file: SNFile) => void
|
|
||||||
}
|
|
||||||
|
|
||||||
const FilePreviewModalContext = createContext<FilePreviewModalContextData | null>(null)
|
|
||||||
|
|
||||||
export const useFilePreviewModal = (): FilePreviewModalContextData => {
|
|
||||||
const value = useContext(FilePreviewModalContext)
|
|
||||||
|
|
||||||
if (!value) {
|
|
||||||
throw new Error('FilePreviewModalProvider not found.')
|
|
||||||
}
|
|
||||||
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
export const FilePreviewModalProvider: FunctionComponent<{
|
|
||||||
application: WebApplication
|
|
||||||
}> = ({ application, children }) => {
|
|
||||||
const [isOpen, setIsOpen] = useState(false)
|
|
||||||
const [currentFile, setCurrentFile] = useState<SNFile>()
|
|
||||||
const [files, setFiles] = useState<SNFile[]>([])
|
|
||||||
|
|
||||||
const activate: FilePreviewActivateFunction = (file, files) => {
|
|
||||||
setCurrentFile(file)
|
|
||||||
setFiles(files)
|
|
||||||
setIsOpen(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
const close = () => {
|
|
||||||
setIsOpen(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<FilePreviewModalContext.Provider value={{ activate, setCurrentFile }}>
|
|
||||||
{isOpen && currentFile && (
|
|
||||||
<FilePreviewModal application={application} files={files} file={currentFile} onDismiss={close} />
|
|
||||||
)}
|
|
||||||
{children}
|
|
||||||
</FilePreviewModalContext.Provider>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -32,6 +32,7 @@ import { SubscriptionState } from './SubscriptionState'
|
|||||||
import { SyncState } from './SyncState'
|
import { SyncState } from './SyncState'
|
||||||
import { TagsState } from './TagsState'
|
import { TagsState } from './TagsState'
|
||||||
import { WebOrDesktopDevice } from '@/Device/WebOrDesktopDevice'
|
import { WebOrDesktopDevice } from '@/Device/WebOrDesktopDevice'
|
||||||
|
import { FilePreviewModalState } from './FilePreviewModalState'
|
||||||
|
|
||||||
export enum AppStateEvent {
|
export enum AppStateEvent {
|
||||||
TagChanged,
|
TagChanged,
|
||||||
@@ -84,6 +85,7 @@ export class AppState {
|
|||||||
readonly notesView: NotesViewState
|
readonly notesView: NotesViewState
|
||||||
readonly subscription: SubscriptionState
|
readonly subscription: SubscriptionState
|
||||||
readonly files: FilesState
|
readonly files: FilesState
|
||||||
|
readonly filePreviewModal = new FilePreviewModalState()
|
||||||
|
|
||||||
isSessionsModalVisible = false
|
isSessionsModalVisible = false
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { SNFile } from '@standardnotes/snjs/dist/@types'
|
||||||
|
import { action, makeObservable, observable } from 'mobx'
|
||||||
|
|
||||||
|
export class FilePreviewModalState {
|
||||||
|
isOpen = false
|
||||||
|
currentFile: SNFile | undefined = undefined
|
||||||
|
otherFiles: SNFile[] = []
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
makeObservable(this, {
|
||||||
|
isOpen: observable,
|
||||||
|
currentFile: observable,
|
||||||
|
otherFiles: observable,
|
||||||
|
|
||||||
|
activate: action,
|
||||||
|
dismiss: action,
|
||||||
|
setCurrentFile: action,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
setCurrentFile = (currentFile: SNFile) => {
|
||||||
|
this.currentFile = currentFile
|
||||||
|
}
|
||||||
|
|
||||||
|
activate = (currentFile: SNFile, otherFiles: SNFile[]) => {
|
||||||
|
this.currentFile = currentFile
|
||||||
|
this.otherFiles = otherFiles
|
||||||
|
this.isOpen = true
|
||||||
|
}
|
||||||
|
|
||||||
|
dismiss = () => {
|
||||||
|
this.isOpen = false
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user