feat: add files button to multiple selection view (#1067)

This commit is contained in:
Aman Harwara
2022-06-06 23:50:11 +05:30
committed by GitHub
parent 59dcca18d6
commit 218e7a3d06
14 changed files with 222 additions and 96 deletions

View File

@@ -1,16 +1,20 @@
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { calculateSubmenuStyle, SubmenuStyle } from '@/Utils/CalculateSubmenuStyle'
import { Disclosure, DisclosureButton, DisclosurePanel } from '@reach/disclosure'
import { observer } from 'mobx-react-lite'
import { FunctionComponent, useCallback, useEffect, useRef, useState } from 'react'
import Icon from '@/Components/Icon/Icon'
import { useCloseOnBlur } from '@/Hooks/useCloseOnBlur'
import { NavigationController } from '@/Controllers/Navigation/NavigationController'
import { NotesController } from '@/Controllers/NotesController'
import { NoteTagsController } from '@/Controllers/NoteTagsController'
type Props = {
viewControllerManager: ViewControllerManager
navigationController: NavigationController
notesController: NotesController
noteTagsController: NoteTagsController
}
const AddTagOption: FunctionComponent<Props> = ({ viewControllerManager }) => {
const AddTagOption: FunctionComponent<Props> = ({ navigationController, notesController, noteTagsController }) => {
const menuContainerRef = useRef<HTMLDivElement>(null)
const menuRef = useRef<HTMLDivElement>(null)
const menuButtonRef = useRef<HTMLButtonElement>(null)
@@ -84,22 +88,22 @@ const AddTagOption: FunctionComponent<Props> = ({ viewControllerManager }) => {
}}
className="sn-dropdown min-w-80 flex flex-col py-2 max-h-120 max-w-xs fixed overflow-y-auto"
>
{viewControllerManager.navigationController.tags.map((tag) => (
{navigationController.tags.map((tag) => (
<button
key={tag.uuid}
className="sn-dropdown-item sn-dropdown-item--no-icon max-w-80"
onBlur={closeOnBlur}
onClick={() => {
viewControllerManager.notesController.isTagInSelectedNotes(tag)
? viewControllerManager.notesController.removeTagFromSelectedNotes(tag).catch(console.error)
: viewControllerManager.notesController.addTagToSelectedNotes(tag).catch(console.error)
notesController.isTagInSelectedNotes(tag)
? notesController.removeTagFromSelectedNotes(tag).catch(console.error)
: notesController.addTagToSelectedNotes(tag).catch(console.error)
}}
>
<span
className={`whitespace-nowrap overflow-hidden overflow-ellipsis
${viewControllerManager.notesController.isTagInSelectedNotes(tag) ? 'font-bold' : ''}`}
${notesController.isTagInSelectedNotes(tag) ? 'font-bold' : ''}`}
>
{viewControllerManager.noteTagsController.getLongTitle(tag)}
{noteTagsController.getLongTitle(tag)}
</span>
</button>
))}

View File

@@ -1,6 +1,5 @@
import { KeyboardKey } from '@/Services/IOService'
import { WebApplication } from '@/Application/Application'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { Disclosure, DisclosureButton, DisclosurePanel } from '@reach/disclosure'
import { SNNote } from '@standardnotes/snjs'
import { FunctionComponent, useCallback, useEffect, useRef, useState } from 'react'
@@ -10,7 +9,6 @@ import { calculateSubmenuStyle, SubmenuStyle } from '@/Utils/CalculateSubmenuSty
import { useCloseOnBlur } from '@/Hooks/useCloseOnBlur'
type ChangeEditorOptionProps = {
viewControllerManager: ViewControllerManager
application: WebApplication
note: SNNote
}

View File

@@ -1,9 +1,8 @@
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import Icon from '@/Components/Icon/Icon'
import Switch from '@/Components/Switch/Switch'
import { observer } from 'mobx-react-lite'
import { useState, useEffect, useMemo, useCallback, FunctionComponent } from 'react'
import { SNApplication, SNNote } from '@standardnotes/snjs'
import { SNApplication, SNComponent, SNNote } from '@standardnotes/snjs'
import { KeyboardModifier } from '@/Services/IOService'
import ChangeEditorOption from './ChangeEditorOption'
import { BYTES_IN_ONE_MEGABYTE } from '@/Constants/Constants'
@@ -11,6 +10,7 @@ import ListedActionsOption from './ListedActionsOption'
import AddTagOption from './AddTagOption'
import { addToast, dismissToast, ToastType } from '@standardnotes/stylekit'
import { NotesOptionsProps } from './NotesOptionsProps'
import { NotesController } from '@/Controllers/NotesController'
type DeletePermanentlyButtonProps = {
closeOnBlur: NotesOptionsProps['closeOnBlur']
@@ -121,15 +121,15 @@ const NoteAttributes: FunctionComponent<{
}
const SpellcheckOptions: FunctionComponent<{
viewControllerManager: ViewControllerManager
editorForNote: SNComponent | undefined
notesController: NotesController
note: SNNote
}> = ({ viewControllerManager, note }) => {
const editor = viewControllerManager.application.componentManager.editorForNote(note)
const spellcheckControllable = Boolean(!editor || editor.package_info.spellcheckControl)
}> = ({ editorForNote, notesController, note }) => {
const spellcheckControllable = Boolean(!editorForNote || editorForNote.package_info.spellcheckControl)
const noteSpellcheck = !spellcheckControllable
? true
: note
? viewControllerManager.notesController.getSpellcheckStateForNote(note)
? notesController.getSpellcheckStateForNote(note)
: undefined
return (
@@ -137,7 +137,7 @@ const SpellcheckOptions: FunctionComponent<{
<button
className="sn-dropdown-item justify-between px-3 py-1"
onClick={() => {
viewControllerManager.notesController.toggleGlobalSpellcheckForNote(note).catch(console.error)
notesController.toggleGlobalSpellcheckForNote(note).catch(console.error)
}}
disabled={!spellcheckControllable}
>
@@ -169,7 +169,13 @@ const NoteSizeWarning: FunctionComponent<{
) : null
}
const NotesOptions = ({ application, viewControllerManager, closeOnBlur }: NotesOptionsProps) => {
const NotesOptions = ({
application,
navigationController,
notesController,
noteTagsController,
closeOnBlur,
}: NotesOptionsProps) => {
const [altKeyDown, setAltKeyDown] = useState(false)
const toggleOn = (condition: (note: SNNote) => boolean) => {
@@ -178,7 +184,7 @@ const NotesOptions = ({ application, viewControllerManager, closeOnBlur }: Notes
return notesMatchingAttribute.length > notesNotMatchingAttribute.length
}
const notes = viewControllerManager.notesController.selectedNotes
const notes = notesController.selectedNotes
const hidePreviews = toggleOn((note) => note.hidePreview)
const locked = toggleOn((note) => note.locked)
const protect = toggleOn((note) => note.protected)
@@ -189,6 +195,11 @@ const NotesOptions = ({ application, viewControllerManager, closeOnBlur }: Notes
const pinned = notes.some((note) => note.pinned)
const unpinned = notes.some((note) => !note.pinned)
const editorForNote = useMemo(
() => application.componentManager.editorForNote(notes[0]),
[application.componentManager, notes],
)
useEffect(() => {
const removeAltKeyObserver = application.io.addKeyObserver({
modifiers: [KeyboardModifier.Alt],
@@ -248,8 +259,8 @@ const NotesOptions = ({ application, viewControllerManager, closeOnBlur }: Notes
}, [application, notes])
const openRevisionHistoryModal = useCallback(() => {
viewControllerManager.notesController.setShowRevisionHistoryModal(true)
}, [viewControllerManager])
notesController.setShowRevisionHistoryModal(true)
}, [notesController])
return (
<>
@@ -265,7 +276,7 @@ const NotesOptions = ({ application, viewControllerManager, closeOnBlur }: Notes
<button
className="sn-dropdown-item justify-between"
onClick={() => {
viewControllerManager.notesController.setLockSelectedNotes(!locked)
notesController.setLockSelectedNotes(!locked)
}}
onBlur={closeOnBlur}
>
@@ -278,7 +289,7 @@ const NotesOptions = ({ application, viewControllerManager, closeOnBlur }: Notes
<button
className="sn-dropdown-item justify-between"
onClick={() => {
viewControllerManager.notesController.setHideSelectedNotePreviews(!hidePreviews)
notesController.setHideSelectedNotePreviews(!hidePreviews)
}}
onBlur={closeOnBlur}
>
@@ -291,7 +302,7 @@ const NotesOptions = ({ application, viewControllerManager, closeOnBlur }: Notes
<button
className="sn-dropdown-item justify-between"
onClick={() => {
viewControllerManager.notesController.setProtectSelectedNotes(!protect).catch(console.error)
notesController.setProtectSelectedNotes(!protect).catch(console.error)
}}
onBlur={closeOnBlur}
>
@@ -304,19 +315,23 @@ const NotesOptions = ({ application, viewControllerManager, closeOnBlur }: Notes
{notes.length === 1 && (
<>
<div className="min-h-1px my-2 bg-border"></div>
<ChangeEditorOption viewControllerManager={viewControllerManager} application={application} note={notes[0]} />
<ChangeEditorOption application={application} note={notes[0]} />
</>
)}
<div className="min-h-1px my-2 bg-border"></div>
{viewControllerManager.navigationController.tagsCount > 0 && (
<AddTagOption viewControllerManager={viewControllerManager} />
{navigationController.tagsCount > 0 && (
<AddTagOption
navigationController={navigationController}
notesController={notesController}
noteTagsController={noteTagsController}
/>
)}
{unpinned && (
<button
onBlur={closeOnBlur}
className="sn-dropdown-item"
onClick={() => {
viewControllerManager.notesController.setPinSelectedNotes(true)
notesController.setPinSelectedNotes(true)
}}
>
<Icon type="pin" className={iconClass} />
@@ -328,7 +343,7 @@ const NotesOptions = ({ application, viewControllerManager, closeOnBlur }: Notes
onBlur={closeOnBlur}
className="sn-dropdown-item"
onClick={() => {
viewControllerManager.notesController.setPinSelectedNotes(false)
notesController.setPinSelectedNotes(false)
}}
>
<Icon type="unpin" className={iconClass} />
@@ -348,7 +363,7 @@ const NotesOptions = ({ application, viewControllerManager, closeOnBlur }: Notes
onBlur={closeOnBlur}
className="sn-dropdown-item"
onClick={() => {
viewControllerManager.notesController.setArchiveSelectedNotes(true).catch(console.error)
notesController.setArchiveSelectedNotes(true).catch(console.error)
}}
>
<Icon type="archive" className={iconClassWarning} />
@@ -360,7 +375,7 @@ const NotesOptions = ({ application, viewControllerManager, closeOnBlur }: Notes
onBlur={closeOnBlur}
className="sn-dropdown-item"
onClick={() => {
viewControllerManager.notesController.setArchiveSelectedNotes(false).catch(console.error)
notesController.setArchiveSelectedNotes(false).catch(console.error)
}}
>
<Icon type="unarchive" className={iconClassWarning} />
@@ -372,7 +387,7 @@ const NotesOptions = ({ application, viewControllerManager, closeOnBlur }: Notes
<DeletePermanentlyButton
closeOnBlur={closeOnBlur}
onClick={async () => {
await viewControllerManager.notesController.deleteNotesPermanently()
await notesController.deleteNotesPermanently()
}}
/>
) : (
@@ -380,7 +395,7 @@ const NotesOptions = ({ application, viewControllerManager, closeOnBlur }: Notes
onBlur={closeOnBlur}
className="sn-dropdown-item"
onClick={async () => {
await viewControllerManager.notesController.setTrashSelectedNotes(true)
await notesController.setTrashSelectedNotes(true)
}}
>
<Icon type="trash" className={iconClassDanger} />
@@ -393,7 +408,7 @@ const NotesOptions = ({ application, viewControllerManager, closeOnBlur }: Notes
onBlur={closeOnBlur}
className="sn-dropdown-item"
onClick={async () => {
await viewControllerManager.notesController.setTrashSelectedNotes(false)
await notesController.setTrashSelectedNotes(false)
}}
>
<Icon type="restore" className={iconClassSuccess} />
@@ -402,21 +417,21 @@ const NotesOptions = ({ application, viewControllerManager, closeOnBlur }: Notes
<DeletePermanentlyButton
closeOnBlur={closeOnBlur}
onClick={async () => {
await viewControllerManager.notesController.deleteNotesPermanently()
await notesController.deleteNotesPermanently()
}}
/>
<button
onBlur={closeOnBlur}
className="sn-dropdown-item"
onClick={async () => {
await viewControllerManager.notesController.emptyTrash()
await notesController.emptyTrash()
}}
>
<div className="flex items-start">
<Icon type="trash-sweep" className="color-danger mr-2" />
<div className="flex-row">
<div className="color-danger">Empty Trash</div>
<div className="text-xs">{viewControllerManager.notesController.trashedNotesCount} notes in Trash</div>
<div className="text-xs">{notesController.trashedNotesCount} notes in Trash</div>
</div>
</div>
</button>
@@ -427,7 +442,7 @@ const NotesOptions = ({ application, viewControllerManager, closeOnBlur }: Notes
<div className="min-h-1px my-2 bg-border"></div>
<ListedActionsOption application={application} note={notes[0]} />
<div className="min-h-1px my-2 bg-border"></div>
<SpellcheckOptions viewControllerManager={viewControllerManager} note={notes[0]} />
<SpellcheckOptions editorForNote={editorForNote} notesController={notesController} note={notes[0]} />
<div className="min-h-1px my-2 bg-border"></div>
<NoteAttributes application={application} note={notes[0]} />
<NoteSizeWarning note={notes[0]} />

View File

@@ -1,4 +1,3 @@
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import Icon from '@/Components/Icon/Icon'
import VisuallyHidden from '@reach/visually-hidden'
import { useCloseOnBlur } from '@/Hooks/useCloseOnBlur'
@@ -8,14 +7,25 @@ import { observer } from 'mobx-react-lite'
import NotesOptions from './NotesOptions'
import { WebApplication } from '@/Application/Application'
import { FOCUSABLE_BUT_NOT_TABBABLE } from '@/Constants/Constants'
import { NotesController } from '@/Controllers/NotesController'
import { NavigationController } from '@/Controllers/Navigation/NavigationController'
import { NoteTagsController } from '@/Controllers/NoteTagsController'
type Props = {
application: WebApplication
viewControllerManager: ViewControllerManager
navigationController: NavigationController
notesController: NotesController
noteTagsController: NoteTagsController
onClickPreprocessing?: () => Promise<void>
}
const NotesOptionsPanel = ({ application, viewControllerManager, onClickPreprocessing }: Props) => {
const NotesOptionsPanel = ({
application,
navigationController,
notesController,
noteTagsController,
onClickPreprocessing,
}: Props) => {
const [open, setOpen] = useState(false)
const [position, setPosition] = useState({
top: 0,
@@ -82,7 +92,9 @@ const NotesOptionsPanel = ({ application, viewControllerManager, onClickPreproce
{open && (
<NotesOptions
application={application}
viewControllerManager={viewControllerManager}
navigationController={navigationController}
notesController={notesController}
noteTagsController={noteTagsController}
closeOnBlur={closeOnBlur}
/>
)}

View File

@@ -1,8 +1,12 @@
import { WebApplication } from '@/Application/Application'
import { ViewControllerManager } from '@/Services/ViewControllerManager'
import { NavigationController } from '@/Controllers/Navigation/NavigationController'
import { NotesController } from '@/Controllers/NotesController'
import { NoteTagsController } from '@/Controllers/NoteTagsController'
export type NotesOptionsProps = {
application: WebApplication
viewControllerManager: ViewControllerManager
navigationController: NavigationController
notesController: NotesController
noteTagsController: NoteTagsController
closeOnBlur: (event: { relatedTarget: EventTarget | null }) => void
}