Skip to content

Commit

Permalink
feat: add protect option to menu
Browse files Browse the repository at this point in the history
  • Loading branch information
Antonella Sgarlatta committed May 11, 2021
1 parent b3380cf commit 8302733
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 35 deletions.
3 changes: 3 additions & 0 deletions app/assets/icons/ic-textbox-password.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions app/assets/javascripts/components/Icon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import HashtagIcon from '../../icons/ic-hashtag.svg';
import ChevronRightIcon from '../../icons/ic-chevron-right.svg';
import RestoreIcon from '../../icons/ic-restore.svg';
import CloseIcon from '../../icons/ic-close.svg';
import PasswordIcon from '../../icons/ic-textbox-password.svg';
import { toDirective } from './utils';

const ICONS = {
Expand All @@ -23,6 +24,7 @@ const ICONS = {
'chevron-right': ChevronRightIcon,
'restore': RestoreIcon,
'close': CloseIcon,
'password': PasswordIcon,
};

type Props = {
Expand Down
14 changes: 14 additions & 0 deletions app/assets/javascripts/components/NotesOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export const NotesOptions = observer(
const notes = Object.values(appState.notes.selectedNotes);
const hidePreviews = toggleOn(note => note.hidePreview);
const locked = toggleOn(note => note.locked);
const protect = toggleOn(note => note.protected);
const archived = notes.some((note) => note.archived);
const unarchived = notes.some((note) => !note.archived);
const trashed = notes.some((note) => note.trashed);
Expand Down Expand Up @@ -84,6 +85,19 @@ export const NotesOptions = observer(
Show preview
</span>
</Switch>
<Switch
onBlur={closeOnBlur}
className="px-3 py-1.5"
checked={protect}
onChange={() => {
appState.notes.setProtectSelectedNotes(!protect);
}}
>
<span className="flex items-center">
<Icon type="password" className={iconClass} />
Protect
</span>
</Switch>
<div className="h-1px my-2 bg-border"></div>
{appState.tags.tagsCount > 0 && (
<Disclosure
Expand Down
73 changes: 51 additions & 22 deletions app/assets/javascripts/ui_models/app_state/notes_state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export class NotesState {
top: 0,
left: 0,
};
showProtectedWarning = false;

constructor(
private application: WebApplication,
Expand All @@ -36,6 +37,7 @@ export class NotesState {
selectedNotes: observable,
contextMenuOpen: observable,
contextMenuPosition: observable,
showProtectedWarning: observable,

selectedNotesCount: computed,

Expand All @@ -52,6 +54,7 @@ export class NotesState {
addTagToSelectedNotes: action,
removeTagFromSelectedNotes: action,
isTagInSelectedNotes: action,
setShowProtectedWarning: action,
});

appEventListeners.push(
Expand All @@ -75,6 +78,23 @@ export class NotesState {
return Object.keys(this.selectedNotes).length;
}

async runProtectedAction(action: (note: SNNote) => void, notes: SNNote[]): Promise<void> {
let protectedNotesAccessRequest: Promise<boolean>;
await Promise.all(
notes.map(async (note) => {
if (note.protected) {
if (!protectedNotesAccessRequest) {
protectedNotesAccessRequest =
this.application.authorizeNoteAccess(note);
}
}
if (!note.protected || await protectedNotesAccessRequest) {
action(note);
}
})
);
}

async selectNotesRange(selectedNote: SNNote): Promise<void> {
const notes = this.application.getDisplayableItems(
ContentType.Note
Expand All @@ -85,32 +105,18 @@ export class NotesState {
const selectedNoteIndex = notes.findIndex(
(note) => note.uuid == selectedNote.uuid
);
let protectedNotesAccessRequest: Promise<boolean>;
let notesToSelect = [];

let notesToSelect = [];
if (selectedNoteIndex > lastSelectedNoteIndex) {
notesToSelect = notes.slice(lastSelectedNoteIndex, selectedNoteIndex + 1);
} else {
notesToSelect = notes.slice(selectedNoteIndex, lastSelectedNoteIndex + 1);
}

await Promise.all(
notesToSelect.map(async (note) => {
const requestAccess =
note.protected && this.application.hasProtectionSources();
if (requestAccess) {
if (!protectedNotesAccessRequest) {
protectedNotesAccessRequest =
this.application.authorizeNoteAccess(note);
}
}
if (!requestAccess || (await protectedNotesAccessRequest)) {
this.selectedNotes[note.uuid] = note;
}
})
);

this.lastSelectedNote = selectedNote;
this.runProtectedAction((note) => {
this.selectedNotes[note.uuid] = note;
this.lastSelectedNote = selectedNote;
}, notesToSelect);
}

async selectNote(note: SNNote): Promise<void> {
Expand Down Expand Up @@ -211,7 +217,7 @@ export class NotesState {
});
}
} else {
this.changeSelectedNotes((mutator) => {
await this.changeSelectedNotes((mutator) => {
mutator.trashed = trashed;
});
this.unselectNotes();
Expand Down Expand Up @@ -258,7 +264,7 @@ export class NotesState {
await this.application.deleteItem(note);
}
} else {
this.changeSelectedNotes((mutator) => {
await this.changeSelectedNotes((mutator) => {
mutator.trashed = true;
});
}
Expand All @@ -282,7 +288,7 @@ export class NotesState {
return;
}

this.changeSelectedNotes((mutator) => {
await this.changeSelectedNotes((mutator) => {
mutator.archived = archived;
});

Expand All @@ -292,6 +298,25 @@ export class NotesState {
});
}

async setProtectSelectedNotes(protect: boolean): Promise<void> {
if (protect) {
await this.changeSelectedNotes((mutator) => {
mutator.protected = protect;
});
if (!this.application.hasProtectionSources()) {
this.setShowProtectedWarning(true);
}
} else {
const selectedNotes = Object.values(this.selectedNotes);
this.runProtectedAction(async (note) => {
await this.application.changeItem(note.uuid, (mutator) => {
mutator.protected = protect;
});
}, selectedNotes);
this.setShowProtectedWarning(false);
}
}

unselectNotes(): void {
this.selectedNotes = {};
}
Expand Down Expand Up @@ -326,6 +351,10 @@ export class NotesState {
);
}

setShowProtectedWarning(show: boolean): void {
this.showProtectedWarning = show;
}

private get io() {
return this.application.io;
}
Expand Down
4 changes: 2 additions & 2 deletions app/assets/javascripts/views/editor/editor-view.pug
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#editor-column.section.editor.sn-component(aria-label='Note')
protected-note-panel.h-full.flex.justify-center.items-center(
ng-if='self.state.showProtectedWarning'
ng-if='self.appState.notes.showProtectedWarning'
app-state='self.appState'
on-view-note='self.dismissProtectedWarning()'
)
.flex-grow.flex.flex-col(
ng-if='!self.state.showProtectedWarning'
ng-if='!self.appState.notes.showProtectedWarning'
)
.sn-component
.sk-app-bar.no-edges(
Expand Down
19 changes: 8 additions & 11 deletions app/assets/javascripts/views/editor/editor_view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ type EditorState = {
textareaUnloading: boolean;
/** Fields that can be directly mutated by the template */
mutable: any;
showProtectedWarning: boolean;
};

type EditorValues = {
Expand Down Expand Up @@ -241,7 +240,6 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
mutable: {
tagsString: '',
},
showProtectedWarning: false,
} as EditorState;
}

Expand Down Expand Up @@ -291,16 +289,15 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
async handleEditorNoteChange() {
this.cancelPendingSetStatus();
const note = this.editor.note;
const showProtectedWarning =
note.protected && !this.application.hasProtectionSources();
const showProtectedWarning = note.protected && !this.application.hasProtectionSources();
this.setShowProtectedWarning(showProtectedWarning);
await this.setState({
showActionsMenu: false,
showOptionsMenu: false,
showEditorMenu: false,
showHistoryMenu: false,
altKeyDown: false,
noteStatus: undefined,
showProtectedWarning,
});
this.editorValues.title = note.title;
this.editorValues.text = note.text;
Expand All @@ -318,9 +315,7 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
}

async dismissProtectedWarning() {
await this.setState({
showProtectedWarning: false,
});
this.setShowProtectedWarning(false);
this.focusTitle();
}

Expand Down Expand Up @@ -658,6 +653,10 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
}
}

setShowProtectedWarning(show: boolean) {
this.application.getAppState().notes.setShowProtectedWarning(show);
}

async deleteNote(permanently: boolean) {
if (this.editor.isTemplateNote) {
this.application.alertService!.alert(STRING_DELETE_PLACEHOLDER_ATTEMPT);
Expand Down Expand Up @@ -767,9 +766,7 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
} else {
const note = await this.application.protectNote(this.note);
if (note?.protected && !this.application.hasProtectionSources()) {
this.setState({
showProtectedWarning: true,
});
this.setShowProtectedWarning(true);
}
}
}
Expand Down

0 comments on commit 8302733

Please sign in to comment.