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;
}