diff --git a/app/assets/javascripts/components/NotesOptions.tsx b/app/assets/javascripts/components/NotesOptions.tsx index 5fa9de686..5a74079f2 100644 --- a/app/assets/javascripts/components/NotesOptions.tsx +++ b/app/assets/javascripts/components/NotesOptions.tsx @@ -128,10 +128,14 @@ export const NotesOptions = observer( className={`${buttonClass} py-2`} onBlur={closeOnBlur} onClick={() => { - appState.tags.addTagToSelectedNotes(tag); + appState.tags.isTagInSelectedNotes(tag) + ? appState.tags.removeTagFromSelectedNotes(tag) + : appState.tags.addTagToSelectedNotes(tag); }} > - {tag.title} + + {tag.title} + ))} diff --git a/app/assets/javascripts/ui_models/app_state/notes_state.ts b/app/assets/javascripts/ui_models/app_state/notes_state.ts index f09bd189b..98f3452b4 100644 --- a/app/assets/javascripts/ui_models/app_state/notes_state.ts +++ b/app/assets/javascripts/ui_models/app_state/notes_state.ts @@ -6,6 +6,7 @@ import { SNNote, NoteMutator, ContentType, + SNTag, } from '@standardnotes/snjs'; import { makeObservable, @@ -76,27 +77,30 @@ export class NotesState { const lastSelectedNoteIndex = notes.findIndex( (note) => note.uuid == this.lastSelectedNote?.uuid ); - const selectedNoteIndex = notes.findIndex((note) => note.uuid == selectedNote.uuid); + const selectedNoteIndex = notes.findIndex( + (note) => note.uuid == selectedNote.uuid + ); let protectedNotesAccessRequest: Promise; let notesToSelect = []; if (selectedNoteIndex > lastSelectedNoteIndex) { - notesToSelect = notes - .slice(lastSelectedNoteIndex, selectedNoteIndex + 1); + notesToSelect = notes.slice(lastSelectedNoteIndex, selectedNoteIndex + 1); } else { - notesToSelect = notes - .slice(selectedNoteIndex, lastSelectedNoteIndex + 1); + notesToSelect = notes.slice(selectedNoteIndex, lastSelectedNoteIndex + 1); } await Promise.all( - notesToSelect.map(async note => { - const requestAccess = note.protected && this.application.hasProtectionSources(); + notesToSelect.map(async (note) => { + const requestAccess = + note.protected && this.application.hasProtectionSources(); if (requestAccess) { if (!protectedNotesAccessRequest) { - protectedNotesAccessRequest = this.application.authorizeNoteAccess(note); + protectedNotesAccessRequest = this.application.authorizeNoteAccess( + note + ); } } - if (!requestAccess || await protectedNotesAccessRequest) { + if (!requestAccess || (await protectedNotesAccessRequest)) { this.selectedNotes[note.uuid] = note; } }) diff --git a/app/assets/javascripts/ui_models/app_state/tags_state.ts b/app/assets/javascripts/ui_models/app_state/tags_state.ts index 1fa1cbcfd..be87e96f2 100644 --- a/app/assets/javascripts/ui_models/app_state/tags_state.ts +++ b/app/assets/javascripts/ui_models/app_state/tags_state.ts @@ -17,6 +17,8 @@ export class TagsState { tagsCount: computed, addTagToSelectedNotes: action, + removeTagFromSelectedNotes: action, + isTagInSelectedNotes: action, }); appEventListeners.push( @@ -47,6 +49,33 @@ export class TagsState { this.application.sync(); } + async removeTagFromSelectedNotes(tag: SNTag): Promise { + const selectedNotes = Object.values( + this.application.getAppState().notes.selectedNotes + ); + await Promise.all( + selectedNotes.map( + async (note) => + await this.application.changeItem(tag.uuid, (mutator) => { + mutator.removeItemAsRelationship(note); + }) + ) + ); + this.application.sync(); + } + + isTagInSelectedNotes(tag: SNTag): boolean { + const selectedNotes = Object.values( + this.application.getAppState().notes.selectedNotes + ); + return selectedNotes.every((note) => + this.application + .getAppState() + .getNoteTags(note) + .find((noteTag) => noteTag.uuid === tag.uuid) + ); + } + get tagsCount(): number { return this.tags.length; }