fix: close menu & toggle notes list when note action occurs (#1601)

This commit is contained in:
Aman Harwara
2022-09-20 19:33:14 +05:30
committed by GitHub
parent 023d1665b6
commit 91d9364e95
7 changed files with 101 additions and 66 deletions

View File

@@ -175,14 +175,14 @@ const ApplicationView: FunctionComponent<Props> = ({ application, mainApplicatio
return (
<PremiumModalProvider application={application} viewControllerManager={viewControllerManager}>
<div className={platformString + ' main-ui-view sn-component'}>
<div id="app" className={appClass + ' app app-column-container'}>
<FileDragNDropProvider
application={application}
featuresController={viewControllerManager.featuresController}
filesController={viewControllerManager.filesController}
>
<ResponsivePaneProvider>
<ResponsivePaneProvider>
<div className={platformString + ' main-ui-view sn-component'}>
<div id="app" className={appClass + ' app app-column-container'}>
<FileDragNDropProvider
application={application}
featuresController={viewControllerManager.featuresController}
filesController={viewControllerManager.filesController}
>
<Navigation application={application} />
<ContentListView
application={application}
@@ -197,52 +197,52 @@ const ApplicationView: FunctionComponent<Props> = ({ application, mainApplicatio
searchOptionsController={viewControllerManager.searchOptionsController}
/>
<NoteGroupView application={application} />
</ResponsivePaneProvider>
</FileDragNDropProvider>
</FileDragNDropProvider>
</div>
<>
<Footer application={application} applicationGroup={mainApplicationGroup} />
<SessionsModal application={application} viewControllerManager={viewControllerManager} />
<PreferencesViewWrapper viewControllerManager={viewControllerManager} application={application} />
<RevisionHistoryModal
application={application}
historyModalController={viewControllerManager.historyModalController}
notesController={viewControllerManager.notesController}
selectionController={viewControllerManager.selectionController}
subscriptionController={viewControllerManager.subscriptionController}
/>
</>
{renderChallenges()}
<>
<NotesContextMenu
application={application}
navigationController={viewControllerManager.navigationController}
notesController={viewControllerManager.notesController}
noteTagsController={viewControllerManager.noteTagsController}
historyModalController={viewControllerManager.historyModalController}
/>
<TagContextMenuWrapper
navigationController={viewControllerManager.navigationController}
featuresController={viewControllerManager.featuresController}
/>
<FileContextMenuWrapper
filesController={viewControllerManager.filesController}
selectionController={viewControllerManager.selectionController}
/>
<PurchaseFlowWrapper application={application} viewControllerManager={viewControllerManager} />
<ConfirmSignoutContainer
applicationGroup={mainApplicationGroup}
viewControllerManager={viewControllerManager}
application={application}
/>
<ToastContainer />
<FilePreviewModalWrapper application={application} viewControllerManager={viewControllerManager} />
<PermissionsModalWrapper application={application} />
</>
</div>
<>
<Footer application={application} applicationGroup={mainApplicationGroup} />
<SessionsModal application={application} viewControllerManager={viewControllerManager} />
<PreferencesViewWrapper viewControllerManager={viewControllerManager} application={application} />
<RevisionHistoryModal
application={application}
historyModalController={viewControllerManager.historyModalController}
notesController={viewControllerManager.notesController}
selectionController={viewControllerManager.selectionController}
subscriptionController={viewControllerManager.subscriptionController}
/>
</>
{renderChallenges()}
<>
<NotesContextMenu
application={application}
navigationController={viewControllerManager.navigationController}
notesController={viewControllerManager.notesController}
noteTagsController={viewControllerManager.noteTagsController}
historyModalController={viewControllerManager.historyModalController}
/>
<TagContextMenuWrapper
navigationController={viewControllerManager.navigationController}
featuresController={viewControllerManager.featuresController}
/>
<FileContextMenuWrapper
filesController={viewControllerManager.filesController}
selectionController={viewControllerManager.selectionController}
/>
<PurchaseFlowWrapper application={application} viewControllerManager={viewControllerManager} />
<ConfirmSignoutContainer
applicationGroup={mainApplicationGroup}
viewControllerManager={viewControllerManager}
application={application}
/>
<ToastContainer />
<FilePreviewModalWrapper application={application} viewControllerManager={viewControllerManager} />
<PermissionsModalWrapper application={application} />
</>
</div>
</ResponsivePaneProvider>
</PremiumModalProvider>
)
}

View File

@@ -8,6 +8,8 @@ import { FilesController } from '@/Controllers/FilesController'
import { SelectedItemsController } from '@/Controllers/SelectedItemsController'
import HorizontalSeparator from '../Shared/HorizontalSeparator'
import { formatSizeToReadableString } from '@standardnotes/filepicker'
import { useResponsiveAppPane } from '../ResponsivePane/ResponsivePaneProvider'
import { AppPaneId } from '../ResponsivePane/AppPaneMetadata'
type Props = {
closeMenu: () => void
@@ -30,6 +32,7 @@ const FileMenuOptions: FunctionComponent<Props> = ({
}) => {
const { selectedFiles } = selectionController
const { handleFileAction } = filesController
const { toggleAppPane } = useResponsiveAppPane()
const hasProtectedFiles = useMemo(() => selectedFiles.some((file) => file.protected), [selectedFiles])
const hasSelectedMultipleFiles = useMemo(() => selectedFiles.length > 1, [selectedFiles.length])
@@ -68,6 +71,11 @@ const FileMenuOptions: FunctionComponent<Props> = ({
closeMenu()
}, [closeMenu, handleFileAction, selectedFiles])
const closeMenuAndToggleFilesList = useCallback(() => {
toggleAppPane(AppPaneId.Items)
closeMenu()
}, [closeMenu, toggleAppPane])
return (
<>
<button
@@ -139,6 +147,7 @@ const FileMenuOptions: FunctionComponent<Props> = ({
<button
className="flex w-full cursor-pointer items-center border-0 bg-transparent px-3 py-1.5 text-left text-sm text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:shadow-none"
onClick={() => {
closeMenuAndToggleFilesList()
void filesController.deleteFilesPermanently(selectionController.selectedFiles)
}}
>

View File

@@ -23,10 +23,12 @@ const NotesContextMenu = ({
noteTagsController,
historyModalController,
}: Props) => {
const { contextMenuOpen, contextMenuClickLocation } = notesController
const { contextMenuOpen, contextMenuClickLocation, setContextMenuOpen } = notesController
const contextMenuRef = useRef<HTMLDivElement>(null)
const closeMenu = () => setContextMenuOpen(!contextMenuOpen)
return (
<Popover
align="start"
@@ -37,7 +39,7 @@ const NotesContextMenu = ({
className="py-2"
open={contextMenuOpen}
side="right"
togglePopover={() => notesController.setContextMenuOpen(!contextMenuOpen)}
togglePopover={closeMenu}
>
<div ref={contextMenuRef}>
<NotesOptions
@@ -46,6 +48,7 @@ const NotesContextMenu = ({
notesController={notesController}
noteTagsController={noteTagsController}
historyModalController={historyModalController}
closeMenu={closeMenu}
/>
</div>
</Popover>

View File

@@ -13,6 +13,8 @@ import { NotesOptionsProps } from './NotesOptionsProps'
import { NotesController } from '@/Controllers/NotesController'
import HorizontalSeparator from '../Shared/HorizontalSeparator'
import { formatDateForContextMenu } from '@/Utils/DateUtils'
import { useResponsiveAppPane } from '../ResponsivePane/ResponsivePaneProvider'
import { AppPaneId } from '../ResponsivePane/AppPaneMetadata'
type DeletePermanentlyButtonProps = {
onClick: () => void
@@ -175,8 +177,10 @@ const NotesOptions = ({
notesController,
noteTagsController,
historyModalController,
closeMenu,
}: NotesOptionsProps) => {
const [altKeyDown, setAltKeyDown] = useState(false)
const { toggleAppPane } = useResponsiveAppPane()
const toggleOn = (condition: (note: SNNote) => boolean) => {
const notesMatchingAttribute = notes.filter(condition)
@@ -252,11 +256,15 @@ const NotesOptions = ({
}
}, [application, getNoteFileName, notes])
const duplicateSelectedItems = useCallback(() => {
notes.forEach((note) => {
application.mutator.duplicateItem(note).catch(console.error)
})
}, [application, notes])
const closeMenuAndToggleNotesList = useCallback(() => {
toggleAppPane(AppPaneId.Items)
closeMenu()
}, [closeMenu, toggleAppPane])
const duplicateSelectedItems = useCallback(async () => {
await Promise.all(notes.map((note) => application.mutator.duplicateItem(note).catch(console.error)))
closeMenuAndToggleNotesList()
}, [application.mutator, closeMenuAndToggleNotesList, notes])
const openRevisionHistoryModal = useCallback(() => {
historyModalController.openModal(notesController.firstSelectedNote)
@@ -365,8 +373,9 @@ const NotesOptions = ({
{unarchived && (
<button
className="flex w-full cursor-pointer items-center border-0 bg-transparent px-3 py-1.5 text-left text-menu-item text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:shadow-none"
onClick={() => {
notesController.setArchiveSelectedNotes(true).catch(console.error)
onClick={async () => {
await notesController.setArchiveSelectedNotes(true).catch(console.error)
closeMenuAndToggleNotesList()
}}
>
<Icon type="archive" className={iconClassWarning} />
@@ -376,8 +385,9 @@ const NotesOptions = ({
{archived && (
<button
className="flex w-full cursor-pointer items-center border-0 bg-transparent px-3 py-1.5 text-left text-menu-item text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:shadow-none"
onClick={() => {
notesController.setArchiveSelectedNotes(false).catch(console.error)
onClick={async () => {
await notesController.setArchiveSelectedNotes(false).catch(console.error)
closeMenuAndToggleNotesList()
}}
>
<Icon type="unarchive" className={iconClassWarning} />
@@ -389,6 +399,7 @@ const NotesOptions = ({
<DeletePermanentlyButton
onClick={async () => {
await notesController.deleteNotesPermanently()
closeMenuAndToggleNotesList()
}}
/>
) : (
@@ -396,6 +407,7 @@ const NotesOptions = ({
className="flex w-full cursor-pointer items-center border-0 bg-transparent px-3 py-1.5 text-left text-menu-item text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:shadow-none"
onClick={async () => {
await notesController.setTrashSelectedNotes(true)
closeMenuAndToggleNotesList()
}}
>
<Icon type="trash" className={iconClassDanger} />
@@ -408,6 +420,7 @@ const NotesOptions = ({
className="flex w-full cursor-pointer items-center border-0 bg-transparent px-3 py-1.5 text-left text-menu-item text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:shadow-none"
onClick={async () => {
await notesController.setTrashSelectedNotes(false)
closeMenuAndToggleNotesList()
}}
>
<Icon type="restore" className={iconClassSuccess} />
@@ -416,12 +429,14 @@ const NotesOptions = ({
<DeletePermanentlyButton
onClick={async () => {
await notesController.deleteNotesPermanently()
closeMenuAndToggleNotesList()
}}
/>
<button
className="flex w-full cursor-pointer items-center border-0 bg-transparent px-3 py-1.5 text-left text-menu-item text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:shadow-none"
onClick={async () => {
await notesController.emptyTrash()
closeMenuAndToggleNotesList()
}}
>
<div className="flex items-start">

View File

@@ -55,6 +55,7 @@ const NotesOptionsPanel = ({
notesController={notesController}
noteTagsController={noteTagsController}
historyModalController={historyModalController}
closeMenu={toggleMenu}
/>
</Popover>
</>

View File

@@ -10,4 +10,5 @@ export type NotesOptionsProps = {
notesController: NotesController
noteTagsController: NoteTagsController
historyModalController: HistoryModalController
closeMenu: () => void
}

View File

@@ -1,6 +1,6 @@
import { ElementIds } from '@/Constants/ElementIDs'
import { isMobileScreen } from '@/Utils'
import { useEffect, ReactNode, useMemo, createContext, useCallback, useContext, useState } from 'react'
import { useEffect, ReactNode, useMemo, createContext, useCallback, useContext, useState, memo } from 'react'
import { AppPaneId } from './AppPaneMetadata'
type ResponsivePaneData = {
@@ -24,6 +24,8 @@ type Props = {
children: ReactNode
}
const MemoizedChildren = memo(({ children }: Props) => <div>{children}</div>)
const ResponsivePaneProvider = ({ children }: Props) => {
const [currentSelectedPane, setCurrentSelectedPane] = useState<AppPaneId>(
isMobileScreen() ? AppPaneId.Items : AppPaneId.Editor,
@@ -63,7 +65,11 @@ const ResponsivePaneProvider = ({ children }: Props) => {
[currentSelectedPane, toggleAppPane],
)
return <ResponsivePaneContext.Provider value={contextValue}>{children}</ResponsivePaneContext.Provider>
return (
<ResponsivePaneContext.Provider value={contextValue}>
<MemoizedChildren children={children} />
</ResponsivePaneContext.Provider>
)
}
export default ResponsivePaneProvider