Fixes smart tags, toggling archive, and toggling trashed
This commit is contained in:
@@ -7,7 +7,8 @@ import {
|
|||||||
SNNote,
|
SNNote,
|
||||||
SNUserPrefs,
|
SNUserPrefs,
|
||||||
ContentType,
|
ContentType,
|
||||||
SNSmartTag
|
SNSmartTag,
|
||||||
|
PayloadSource
|
||||||
} from 'snjs';
|
} from 'snjs';
|
||||||
import { WebApplication } from '@/ui_models/application';
|
import { WebApplication } from '@/ui_models/application';
|
||||||
import { Editor } from '@/ui_models/editor';
|
import { Editor } from '@/ui_models/editor';
|
||||||
@@ -155,13 +156,22 @@ export class AppState {
|
|||||||
streamNotesAndTags() {
|
streamNotesAndTags() {
|
||||||
this.application!.streamItems(
|
this.application!.streamItems(
|
||||||
[ContentType.Note, ContentType.Tag],
|
[ContentType.Note, ContentType.Tag],
|
||||||
async (items) => {
|
async (items, source) => {
|
||||||
/** Close any editors for deleted notes */
|
/** Close any editors for deleted/trashed/archived notes */
|
||||||
const notes = items.filter((candidate) => candidate.content_type === ContentType.Note) as SNNote[];
|
if (source === PayloadSource.PreSyncSave) {
|
||||||
for (const note of notes) {
|
const notes = items.filter((candidate) =>
|
||||||
if (note.deleted) {
|
candidate.content_type === ContentType.Note
|
||||||
|
) as SNNote[];
|
||||||
|
for (const note of notes) {
|
||||||
const editor = this.editorForNote(note);
|
const editor = this.editorForNote(note);
|
||||||
if (editor) {
|
if (!editor) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (note.deleted) {
|
||||||
|
this.closeEditor(editor);
|
||||||
|
} else if (note.trashed && !this.selectedTag?.isTrashTag) {
|
||||||
|
this.closeEditor(editor);
|
||||||
|
} else if (note.archived && !this.selectedTag?.isArchiveTag) {
|
||||||
this.closeEditor(editor);
|
this.closeEditor(editor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -461,11 +461,25 @@ class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bypassDebouncer Calling save will debounce by default. You can pass true to save
|
||||||
|
* immediately.
|
||||||
|
* @param isUserModified This field determines if the item will be saved as a user
|
||||||
|
* modification, thus updating the user modified date displayed in the UI
|
||||||
|
* @param dontUpdatePreviews Whether this change should update the note's plain and HTML
|
||||||
|
* preview.
|
||||||
|
* @param customMutate A custom mutator function.
|
||||||
|
* @param closeAfterSync Whether this editor should be closed after the sync starts.
|
||||||
|
* This allows us to make a destructive change, wait for sync to be triggered, then
|
||||||
|
* close the editor (if we closed the editor before sync began, we'd get an exception,
|
||||||
|
* since the debouncer will be triggered on a non-existent editor)
|
||||||
|
*/
|
||||||
async saveNote(
|
async saveNote(
|
||||||
bypassDebouncer = false,
|
bypassDebouncer = false,
|
||||||
isUserModified = false,
|
isUserModified = false,
|
||||||
dontUpdatePreviews = false,
|
dontUpdatePreviews = false,
|
||||||
customMutate?: (mutator: NoteMutator) => void
|
customMutate?: (mutator: NoteMutator) => void,
|
||||||
|
closeAfterSync = false
|
||||||
) {
|
) {
|
||||||
this.performFirefoxPinnedTabFix();
|
this.performFirefoxPinnedTabFix();
|
||||||
const note = this.note;
|
const note = this.note;
|
||||||
@@ -493,7 +507,7 @@ class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.showSavingStatus();
|
this.showSavingStatus();
|
||||||
this.application.changeItem(note.uuid, (mutator) => {
|
await this.application.changeItem(note.uuid, (mutator) => {
|
||||||
const noteMutator = mutator as NoteMutator;
|
const noteMutator = mutator as NoteMutator;
|
||||||
if (customMutate) {
|
if (customMutate) {
|
||||||
customMutate(noteMutator);
|
customMutate(noteMutator);
|
||||||
@@ -518,6 +532,9 @@ class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
|||||||
: SAVE_TIMEOUT_DEBOUNCE;
|
: SAVE_TIMEOUT_DEBOUNCE;
|
||||||
this.saveTimeout = this.$timeout(() => {
|
this.saveTimeout = this.$timeout(() => {
|
||||||
this.application.sync();
|
this.application.sync();
|
||||||
|
if(closeAfterSync) {
|
||||||
|
this.appState.closeEditor(this.editor);
|
||||||
|
}
|
||||||
}, syncDebouceMs);
|
}, syncDebouceMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -670,7 +687,6 @@ class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.appState.closeEditor(this.editor);
|
|
||||||
},
|
},
|
||||||
undefined,
|
undefined,
|
||||||
true,
|
true,
|
||||||
@@ -702,9 +718,9 @@ class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
|||||||
true,
|
true,
|
||||||
(mutator) => {
|
(mutator) => {
|
||||||
mutator.trashed = false;
|
mutator.trashed = false;
|
||||||
}
|
},
|
||||||
|
true
|
||||||
);
|
);
|
||||||
this.appState.closeEditor(this.editor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteNotePermanantely() {
|
deleteNotePermanantely() {
|
||||||
@@ -790,7 +806,9 @@ class EditorViewCtrl extends PureViewCtrl implements EditorViewScope {
|
|||||||
true,
|
true,
|
||||||
(mutator) => {
|
(mutator) => {
|
||||||
mutator.archived = !this.note.archived
|
mutator.archived = !this.note.archived
|
||||||
}
|
},
|
||||||
|
/** If we are unarchiving, and we are in the archived tag, close the editor */
|
||||||
|
this.note.archived && this.appState.selectedTag?.isArchiveTag
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export function filterAndSortNotes(
|
|||||||
showArchived: boolean,
|
showArchived: boolean,
|
||||||
hidePinned: boolean,
|
hidePinned: boolean,
|
||||||
filterText: string,
|
filterText: string,
|
||||||
sortBy: string,
|
sortBy: string,
|
||||||
reverse: boolean,
|
reverse: boolean,
|
||||||
) {
|
) {
|
||||||
const filtered = filterNotes(
|
const filtered = filterNotes(
|
||||||
@@ -37,12 +37,11 @@ export function filterNotes(
|
|||||||
showArchived: boolean,
|
showArchived: boolean,
|
||||||
hidePinned: boolean,
|
hidePinned: boolean,
|
||||||
filterText: string
|
filterText: string
|
||||||
) {
|
) {
|
||||||
return notes.filter((note) => {
|
return notes.filter((note) => {
|
||||||
let canShowArchived = showArchived;
|
let canShowArchived = showArchived;
|
||||||
const canShowPinned = !hidePinned;
|
const canShowPinned = !hidePinned;
|
||||||
const isTrash = selectedTag.isTrashTag;
|
if (!selectedTag.isTrashTag && note.trashed) {
|
||||||
if (!isTrash && note.trashed) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const isSmartTag = selectedTag.isSmartTag();
|
const isSmartTag = selectedTag.isSmartTag();
|
||||||
@@ -50,7 +49,7 @@ export function filterNotes(
|
|||||||
canShowArchived = (
|
canShowArchived = (
|
||||||
canShowArchived ||
|
canShowArchived ||
|
||||||
selectedTag.isArchiveTag ||
|
selectedTag.isArchiveTag ||
|
||||||
isTrash
|
selectedTag.isTrashTag
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
@@ -67,18 +66,18 @@ function noteMatchesQuery(
|
|||||||
note: SNNote,
|
note: SNNote,
|
||||||
query: string
|
query: string
|
||||||
) {
|
) {
|
||||||
if(query.length === 0) {
|
if (query.length === 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const title = note.safeTitle().toLowerCase();
|
const title = note.safeTitle().toLowerCase();
|
||||||
const text = note.safeText().toLowerCase();
|
const text = note.safeText().toLowerCase();
|
||||||
const lowercaseText = query.toLowerCase();
|
const lowercaseText = query.toLowerCase();
|
||||||
|
|
||||||
const quotedText = stringBetweenQuotes(lowercaseText);
|
const quotedText = stringBetweenQuotes(lowercaseText);
|
||||||
if(quotedText) {
|
if (quotedText) {
|
||||||
return title.includes(quotedText) || text.includes(quotedText);
|
return title.includes(quotedText) || text.includes(quotedText);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stringIsUuid(lowercaseText)) {
|
if (stringIsUuid(lowercaseText)) {
|
||||||
return note.uuid === lowercaseText;
|
return note.uuid === lowercaseText;
|
||||||
}
|
}
|
||||||
@@ -90,7 +89,7 @@ function noteMatchesQuery(
|
|||||||
const matchesBody = words.every((word) => {
|
const matchesBody = words.every((word) => {
|
||||||
return text.indexOf(word) >= 0;
|
return text.indexOf(word) >= 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
return matchesTitle || matchesBody;
|
return matchesTitle || matchesBody;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,10 +107,10 @@ function stringIsUuid(text: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function sortNotes(
|
export function sortNotes(
|
||||||
notes: SNNote[] = [],
|
notes: SNNote[] = [],
|
||||||
sortBy: string,
|
sortBy: string,
|
||||||
reverse: boolean
|
reverse: boolean
|
||||||
) {
|
) {
|
||||||
const sortValueFn = (a: SNNote, b: SNNote, pinCheck = false): number => {
|
const sortValueFn = (a: SNNote, b: SNNote, pinCheck = false): number => {
|
||||||
if (!pinCheck) {
|
if (!pinCheck) {
|
||||||
if (a.pinned && b.pinned) {
|
if (a.pinned && b.pinned) {
|
||||||
|
|||||||
@@ -138,7 +138,6 @@ class NotesViewCtrl extends PureViewCtrl {
|
|||||||
this.handleEditorChange();
|
this.handleEditorChange();
|
||||||
} else if (eventName === AppStateEvent.PreferencesChanged) {
|
} else if (eventName === AppStateEvent.PreferencesChanged) {
|
||||||
this.reloadPreferences();
|
this.reloadPreferences();
|
||||||
this.reloadNotes();
|
|
||||||
} else if (eventName === AppStateEvent.EditorFocused) {
|
} else if (eventName === AppStateEvent.EditorFocused) {
|
||||||
this.setShowMenuFalse();
|
this.setShowMenuFalse();
|
||||||
}
|
}
|
||||||
@@ -283,12 +282,12 @@ class NotesViewCtrl extends PureViewCtrl {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async reloadNotes() {
|
private async reloadNotes() {
|
||||||
this.reloadNotesPromise = this.performPeloadNotes();
|
this.reloadNotesPromise = this.performPeloadNotes();
|
||||||
return this.reloadNotesPromise;
|
return this.reloadNotesPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
async performPeloadNotes() {
|
private async performPeloadNotes() {
|
||||||
const tag = this.appState.selectedTag!;
|
const tag = this.appState.selectedTag!;
|
||||||
if (!tag) {
|
if (!tag) {
|
||||||
return;
|
return;
|
||||||
@@ -336,7 +335,7 @@ class NotesViewCtrl extends PureViewCtrl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reloadPreferences() {
|
async reloadPreferences() {
|
||||||
const viewOptions = {} as NotesState;
|
const viewOptions = {} as NotesState;
|
||||||
const prevSortValue = this.getState().sortBy;
|
const prevSortValue = this.getState().sortBy;
|
||||||
let sortBy = this.application!.getPrefsService().getValue(
|
let sortBy = this.application!.getPrefsService().getValue(
|
||||||
@@ -372,12 +371,9 @@ class NotesViewCtrl extends PureViewCtrl {
|
|||||||
WebPrefKey.NotesHideTags,
|
WebPrefKey.NotesHideTags,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
this.setNotesState({
|
await this.setNotesState({
|
||||||
...viewOptions
|
...viewOptions
|
||||||
});
|
});
|
||||||
if (prevSortValue && prevSortValue !== sortBy) {
|
|
||||||
this.selectFirstNote();
|
|
||||||
}
|
|
||||||
const width = this.application!.getPrefsService().getValue(
|
const width = this.application!.getPrefsService().getValue(
|
||||||
WebPrefKey.NotesPanelWidth
|
WebPrefKey.NotesPanelWidth
|
||||||
);
|
);
|
||||||
@@ -390,6 +386,10 @@ class NotesViewCtrl extends PureViewCtrl {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
await this.reloadNotes();
|
||||||
|
if (prevSortValue && prevSortValue !== sortBy) {
|
||||||
|
this.selectFirstNote();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onPanelResize(
|
onPanelResize(
|
||||||
|
|||||||
@@ -183,8 +183,14 @@ class TagsViewCtrl extends PureViewCtrl {
|
|||||||
const noteCounts: NoteCounts = {};
|
const noteCounts: NoteCounts = {};
|
||||||
for (const tag of allTags) {
|
for (const tag of allTags) {
|
||||||
if (tag.isSmartTag()) {
|
if (tag.isSmartTag()) {
|
||||||
const notes = this.application.notesMatchingSmartTag(tag as SNSmartTag);
|
/** Other smart tags do not contain counts */
|
||||||
noteCounts[tag.uuid] = notes.length;
|
if(tag.isAllTag) {
|
||||||
|
const notes = this.application.notesMatchingSmartTag(tag as SNSmartTag)
|
||||||
|
.filter((note) => {
|
||||||
|
return !note.archived && !note.trashed;
|
||||||
|
})
|
||||||
|
noteCounts[tag.uuid] = notes.length;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const notes = this.application.referencesForItem(tag, ContentType.Note)
|
const notes = this.application.referencesForItem(tag, ContentType.Note)
|
||||||
.filter((note) => {
|
.filter((note) => {
|
||||||
|
|||||||
295
dist/javascripts/app.js
vendored
295
dist/javascripts/app.js
vendored
File diff suppressed because one or more lines are too long
2
dist/javascripts/app.js.map
vendored
2
dist/javascripts/app.js.map
vendored
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user