feat: toggle move to trash to delete permanently on alt key down

This commit is contained in:
Antonella Sgarlatta
2021-07-28 16:18:05 -03:00
parent eb6d8c9cba
commit 44bf907aa4
7 changed files with 74 additions and 43 deletions

View File

@@ -213,7 +213,7 @@ DEPENDENCIES
dotenv-rails dotenv-rails
haml haml
lograge (~> 0.11.2) lograge (~> 0.11.2)
newrelic_rpm newrelic_rpm (~> 7.0)
non-stupid-digest-assets non-stupid-digest-assets
puma puma
rack-cors rack-cors

View File

@@ -3,12 +3,14 @@ import { toDirective, useCloseOnBlur, useCloseOnClickOutside } from './utils';
import { observer } from 'mobx-react-lite'; import { observer } from 'mobx-react-lite';
import { NotesOptions } from './NotesOptions'; import { NotesOptions } from './NotesOptions';
import { useCallback, useEffect, useRef } from 'preact/hooks'; import { useCallback, useEffect, useRef } from 'preact/hooks';
import { WebApplication } from '@/ui_models/application';
type Props = { type Props = {
application: WebApplication;
appState: AppState; appState: AppState;
}; };
const NotesContextMenu = observer(({ appState }: Props) => { const NotesContextMenu = observer(({ application, appState }: Props) => {
const { const {
contextMenuOpen, contextMenuOpen,
contextMenuPosition, contextMenuPosition,
@@ -46,7 +48,11 @@ const NotesContextMenu = observer(({ appState }: Props) => {
maxHeight: contextMenuMaxHeight, maxHeight: contextMenuMaxHeight,
}} }}
> >
<NotesOptions appState={appState} closeOnBlur={closeOnBlur} /> <NotesOptions
application={application}
appState={appState}
closeOnBlur={closeOnBlur}
/>
</div> </div>
) : null; ) : null;
}); });

View File

@@ -9,15 +9,33 @@ import {
DisclosurePanel, DisclosurePanel,
} from '@reach/disclosure'; } from '@reach/disclosure';
import { SNNote } from '@standardnotes/snjs/dist/@types'; import { SNNote } from '@standardnotes/snjs/dist/@types';
import { WebApplication } from '@/ui_models/application';
import { KeyboardModifier } from '@/services/ioService';
type Props = { type Props = {
application: WebApplication;
appState: AppState; appState: AppState;
closeOnBlur: (event: { relatedTarget: EventTarget | null }) => void; closeOnBlur: (event: { relatedTarget: EventTarget | null }) => void;
onSubmenuChange?: (submenuOpen: boolean) => void; onSubmenuChange?: (submenuOpen: boolean) => void;
}; };
type DeletePermanentlyButtonProps = {
closeOnBlur: Props["closeOnBlur"];
onClick: () => void;
}
const DeletePermanentlyButton = ({
closeOnBlur,
onClick,
}: DeletePermanentlyButtonProps) => (
<button onBlur={closeOnBlur} className="sn-dropdown-item" onClick={onClick}>
<Icon type="close" className="color-danger mr-2" />
<span className="color-danger">Delete permanently</span>
</button>
);
export const NotesOptions = observer( export const NotesOptions = observer(
({ appState, closeOnBlur, onSubmenuChange }: Props) => { ({ application, appState, closeOnBlur, onSubmenuChange }: Props) => {
const [tagsMenuOpen, setTagsMenuOpen] = useState(false); const [tagsMenuOpen, setTagsMenuOpen] = useState(false);
const [tagsMenuPosition, setTagsMenuPosition] = useState<{ const [tagsMenuPosition, setTagsMenuPosition] = useState<{
top: number; top: number;
@@ -29,6 +47,7 @@ export const NotesOptions = observer(
}); });
const [tagsMenuMaxHeight, setTagsMenuMaxHeight] = const [tagsMenuMaxHeight, setTagsMenuMaxHeight] =
useState<number | 'auto'>('auto'); useState<number | 'auto'>('auto');
const [altKeyDown, setAltKeyDown] = useState(false);
const toggleOn = (condition: (note: SNNote) => boolean) => { const toggleOn = (condition: (note: SNNote) => boolean) => {
const notesMatchingAttribute = notes.filter(condition); const notesMatchingAttribute = notes.filter(condition);
@@ -59,6 +78,22 @@ export const NotesOptions = observer(
} }
}, [tagsMenuOpen, onSubmenuChange]); }, [tagsMenuOpen, onSubmenuChange]);
useEffect(() => {
const removeAltKeyObserver = application.io.addKeyObserver({
modifiers: [KeyboardModifier.Alt],
onKeyDown: () => {
setAltKeyDown(true);
},
onKeyUp: () => {
setAltKeyDown(false);
}
});
return () => {
removeAltKeyObserver();
};
}, [application]);
const openTagsMenu = () => { const openTagsMenu = () => {
const defaultFontSize = window.getComputedStyle( const defaultFontSize = window.getComputedStyle(
document.documentElement document.documentElement
@@ -235,18 +270,26 @@ export const NotesOptions = observer(
Unarchive Unarchive
</button> </button>
)} )}
{notTrashed && ( {notTrashed &&
<button (altKeyDown ? (
onBlur={closeOnBlur} <DeletePermanentlyButton
className="sn-dropdown-item" closeOnBlur={closeOnBlur}
onClick={async () => { onClick={async () => {
await appState.notes.setTrashSelectedNotes(true); await appState.notes.deleteNotesPermanently();
}} }}
> />
<Icon type="trash" className={iconClass} /> ) : (
Move to Trash <button
</button> onBlur={closeOnBlur}
)} className="sn-dropdown-item"
onClick={async () => {
await appState.notes.setTrashSelectedNotes(true);
}}
>
<Icon type="trash" className={iconClass} />
Move to Trash
</button>
))}
{trashed && ( {trashed && (
<> <>
<button <button
@@ -259,16 +302,12 @@ export const NotesOptions = observer(
<Icon type="restore" className={iconClass} /> <Icon type="restore" className={iconClass} />
Restore Restore
</button> </button>
<button <DeletePermanentlyButton
onBlur={closeOnBlur} closeOnBlur={closeOnBlur}
className="sn-dropdown-item"
onClick={async () => { onClick={async () => {
await appState.notes.deleteNotesPermanently(); await appState.notes.deleteNotesPermanently();
}} }}
> />
<Icon type="close" className="color-danger mr-2" />
<span className="color-danger">Delete permanently</span>
</button>
<button <button
onBlur={closeOnBlur} onBlur={closeOnBlur}
className="sn-dropdown-item" className="sn-dropdown-item"

View File

@@ -10,12 +10,14 @@ import {
import { useRef, useState } from 'preact/hooks'; import { useRef, useState } from 'preact/hooks';
import { observer } from 'mobx-react-lite'; import { observer } from 'mobx-react-lite';
import { NotesOptions } from './NotesOptions'; import { NotesOptions } from './NotesOptions';
import { WebApplication } from '@/ui_models/application';
type Props = { type Props = {
application: WebApplication;
appState: AppState; appState: AppState;
}; };
export const NotesOptionsPanel = observer(({ appState }: Props) => { export const NotesOptionsPanel = observer(({ application, appState }: Props) => {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const [position, setPosition] = useState({ const [position, setPosition] = useState({
top: 0, top: 0,
@@ -76,6 +78,7 @@ export const NotesOptionsPanel = observer(({ appState }: Props) => {
> >
{open && ( {open && (
<NotesOptions <NotesOptions
application={application}
appState={appState} appState={appState}
closeOnBlur={closeOnBlur} closeOnBlur={closeOnBlur}
onSubmenuChange={onSubmenuChange} onSubmenuChange={onSubmenuChange}

View File

@@ -37,6 +37,7 @@
on-dismiss="self.removeChallenge(challenge)" on-dismiss="self.removeChallenge(challenge)"
) )
notes-context-menu( notes-context-menu(
application='self.application'
app-state='self.appState' app-state='self.appState'
) )

View File

@@ -49,6 +49,7 @@
) {{self.state.noteStatus.message}} ) {{self.state.noteStatus.message}}
.desc(ng-show='self.state.noteStatus.desc') {{self.state.noteStatus.desc}} .desc(ng-show='self.state.noteStatus.desc') {{self.state.noteStatus.desc}}
notes-options-panel( notes-options-panel(
application='self.application',
app-state='self.appState', app-state='self.appState',
ng-if='self.appState.notes.selectedNotesCount > 0' ng-if='self.appState.notes.selectedNotesCount > 0'
) )

View File

@@ -64,7 +64,6 @@ type EditorState = {
showOptionsMenu: boolean; showOptionsMenu: boolean;
showEditorMenu: boolean; showEditorMenu: boolean;
showHistoryMenu: boolean; showHistoryMenu: boolean;
altKeyDown: boolean;
spellcheck: boolean; spellcheck: boolean;
/** /**
* Setting to false then true will allow the current editor component-view to be destroyed * Setting to false then true will allow the current editor component-view to be destroyed
@@ -217,7 +216,6 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
showOptionsMenu: false, showOptionsMenu: false,
showEditorMenu: false, showEditorMenu: false,
showHistoryMenu: false, showHistoryMenu: false,
altKeyDown: false,
noteStatus: undefined, noteStatus: undefined,
editorUnloading: false, editorUnloading: false,
textareaUnloading: false, textareaUnloading: false,
@@ -277,7 +275,6 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
showOptionsMenu: false, showOptionsMenu: false,
showEditorMenu: false, showEditorMenu: false,
showHistoryMenu: false, showHistoryMenu: false,
altKeyDown: false,
noteStatus: undefined, noteStatus: undefined,
}); });
this.editorValues.title = note.title; this.editorValues.title = note.title;
@@ -843,22 +840,6 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
} }
registerKeyboardShortcuts() { registerKeyboardShortcuts() {
this.removeAltKeyObserver = this.application
.io
.addKeyObserver({
modifiers: [KeyboardModifier.Alt],
onKeyDown: () => {
this.setState({
altKeyDown: true,
});
},
onKeyUp: () => {
this.setState({
altKeyDown: false,
});
},
});
this.removeTrashKeyObserver = this.application this.removeTrashKeyObserver = this.application
.io .io
.addKeyObserver({ .addKeyObserver({