Skip to content

Commit

Permalink
feat: toggle move to trash to delete permanently on alt key down
Browse files Browse the repository at this point in the history
  • Loading branch information
Antonella Sgarlatta committed Jul 28, 2021
1 parent eb6d8c9 commit 44bf907
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 43 deletions.
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ DEPENDENCIES
dotenv-rails
haml
lograge (~> 0.11.2)
newrelic_rpm
newrelic_rpm (~> 7.0)
non-stupid-digest-assets
puma
rack-cors
Expand Down
10 changes: 8 additions & 2 deletions app/assets/javascripts/components/NotesContextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import { toDirective, useCloseOnBlur, useCloseOnClickOutside } from './utils';
import { observer } from 'mobx-react-lite';
import { NotesOptions } from './NotesOptions';
import { useCallback, useEffect, useRef } from 'preact/hooks';
import { WebApplication } from '@/ui_models/application';

type Props = {
application: WebApplication;
appState: AppState;
};

const NotesContextMenu = observer(({ appState }: Props) => {
const NotesContextMenu = observer(({ application, appState }: Props) => {
const {
contextMenuOpen,
contextMenuPosition,
Expand Down Expand Up @@ -46,7 +48,11 @@ const NotesContextMenu = observer(({ appState }: Props) => {
maxHeight: contextMenuMaxHeight,
}}
>
<NotesOptions appState={appState} closeOnBlur={closeOnBlur} />
<NotesOptions
application={application}
appState={appState}
closeOnBlur={closeOnBlur}
/>
</div>
) : null;
});
Expand Down
79 changes: 59 additions & 20 deletions app/assets/javascripts/components/NotesOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,33 @@ import {
DisclosurePanel,
} from '@reach/disclosure';
import { SNNote } from '@standardnotes/snjs/dist/@types';
import { WebApplication } from '@/ui_models/application';
import { KeyboardModifier } from '@/services/ioService';

type Props = {
application: WebApplication;
appState: AppState;
closeOnBlur: (event: { relatedTarget: EventTarget | null }) => 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(
({ appState, closeOnBlur, onSubmenuChange }: Props) => {
({ application, appState, closeOnBlur, onSubmenuChange }: Props) => {
const [tagsMenuOpen, setTagsMenuOpen] = useState(false);
const [tagsMenuPosition, setTagsMenuPosition] = useState<{
top: number;
Expand All @@ -29,6 +47,7 @@ export const NotesOptions = observer(
});
const [tagsMenuMaxHeight, setTagsMenuMaxHeight] =
useState<number | 'auto'>('auto');
const [altKeyDown, setAltKeyDown] = useState(false);

const toggleOn = (condition: (note: SNNote) => boolean) => {
const notesMatchingAttribute = notes.filter(condition);
Expand Down Expand Up @@ -59,6 +78,22 @@ export const NotesOptions = observer(
}
}, [tagsMenuOpen, onSubmenuChange]);

useEffect(() => {
const removeAltKeyObserver = application.io.addKeyObserver({
modifiers: [KeyboardModifier.Alt],
onKeyDown: () => {
setAltKeyDown(true);
},
onKeyUp: () => {
setAltKeyDown(false);
}
});

return () => {
removeAltKeyObserver();
};
}, [application]);

const openTagsMenu = () => {
const defaultFontSize = window.getComputedStyle(
document.documentElement
Expand Down Expand Up @@ -235,18 +270,26 @@ export const NotesOptions = observer(
Unarchive
</button>
)}
{notTrashed && (
<button
onBlur={closeOnBlur}
className="sn-dropdown-item"
onClick={async () => {
await appState.notes.setTrashSelectedNotes(true);
}}
>
<Icon type="trash" className={iconClass} />
Move to Trash
</button>
)}
{notTrashed &&
(altKeyDown ? (
<DeletePermanentlyButton
closeOnBlur={closeOnBlur}
onClick={async () => {
await appState.notes.deleteNotesPermanently();
}}
/>
) : (
<button
onBlur={closeOnBlur}
className="sn-dropdown-item"
onClick={async () => {
await appState.notes.setTrashSelectedNotes(true);
}}
>
<Icon type="trash" className={iconClass} />
Move to Trash
</button>
))}
{trashed && (
<>
<button
Expand All @@ -259,16 +302,12 @@ export const NotesOptions = observer(
<Icon type="restore" className={iconClass} />
Restore
</button>
<button
onBlur={closeOnBlur}
className="sn-dropdown-item"
<DeletePermanentlyButton
closeOnBlur={closeOnBlur}
onClick={async () => {
await appState.notes.deleteNotesPermanently();
}}
>
<Icon type="close" className="color-danger mr-2" />
<span className="color-danger">Delete permanently</span>
</button>
/>
<button
onBlur={closeOnBlur}
className="sn-dropdown-item"
Expand Down
5 changes: 4 additions & 1 deletion app/assets/javascripts/components/NotesOptionsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ import {
import { useRef, useState } from 'preact/hooks';
import { observer } from 'mobx-react-lite';
import { NotesOptions } from './NotesOptions';
import { WebApplication } from '@/ui_models/application';

type Props = {
application: WebApplication;
appState: AppState;
};

export const NotesOptionsPanel = observer(({ appState }: Props) => {
export const NotesOptionsPanel = observer(({ application, appState }: Props) => {
const [open, setOpen] = useState(false);
const [position, setPosition] = useState({
top: 0,
Expand Down Expand Up @@ -76,6 +78,7 @@ export const NotesOptionsPanel = observer(({ appState }: Props) => {
>
{open && (
<NotesOptions
application={application}
appState={appState}
closeOnBlur={closeOnBlur}
onSubmenuChange={onSubmenuChange}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
on-dismiss="self.removeChallenge(challenge)"
)
notes-context-menu(
application='self.application'
app-state='self.appState'
)

1 change: 1 addition & 0 deletions app/assets/javascripts/views/editor/editor-view.pug
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
) {{self.state.noteStatus.message}}
.desc(ng-show='self.state.noteStatus.desc') {{self.state.noteStatus.desc}}
notes-options-panel(
application='self.application',
app-state='self.appState',
ng-if='self.appState.notes.selectedNotesCount > 0'
)
Expand Down
19 changes: 0 additions & 19 deletions app/assets/javascripts/views/editor/editor_view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ type EditorState = {
showOptionsMenu: boolean;
showEditorMenu: boolean;
showHistoryMenu: boolean;
altKeyDown: boolean;
spellcheck: boolean;
/**
* Setting to false then true will allow the current editor component-view to be destroyed
Expand Down Expand Up @@ -217,7 +216,6 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
showOptionsMenu: false,
showEditorMenu: false,
showHistoryMenu: false,
altKeyDown: false,
noteStatus: undefined,
editorUnloading: false,
textareaUnloading: false,
Expand Down Expand Up @@ -277,7 +275,6 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
showOptionsMenu: false,
showEditorMenu: false,
showHistoryMenu: false,
altKeyDown: false,
noteStatus: undefined,
});
this.editorValues.title = note.title;
Expand Down Expand Up @@ -843,22 +840,6 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
}

registerKeyboardShortcuts() {
this.removeAltKeyObserver = this.application
.io
.addKeyObserver({
modifiers: [KeyboardModifier.Alt],
onKeyDown: () => {
this.setState({
altKeyDown: true,
});
},
onKeyUp: () => {
this.setState({
altKeyDown: false,
});
},
});

this.removeTrashKeyObserver = this.application
.io
.addKeyObserver({
Expand Down

0 comments on commit 44bf907

Please sign in to comment.