Notes TypeScript
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
import { AppStateEvent } from '@/services/state';
|
||||||
import { WebApplication } from './../../application';
|
import { WebApplication } from './../../application';
|
||||||
import { ApplicationEvent } from 'snjs';
|
import { ApplicationEvent } from 'snjs';
|
||||||
|
|
||||||
@@ -82,10 +83,11 @@ export class PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addAppStateObserver() {
|
addAppStateObserver() {
|
||||||
this.unsubState = this.application!.getAppState()
|
this.unsubState = this.application!.getAppState().addObserver(
|
||||||
.addObserver((eventName: any, data: any) => {
|
async (eventName, data) => {
|
||||||
this.onAppStateEvent(eventName, data);
|
this.onAppStateEvent(eventName, data);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
onAppStateEvent(eventName: any, data: any) {
|
onAppStateEvent(eventName: any, data: any) {
|
||||||
|
|||||||
@@ -1,51 +1,55 @@
|
|||||||
export const SORT_KEY_CREATED_AT = 'created_at';
|
import { SNNote, SNTag } from 'snjs';
|
||||||
export const SORT_KEY_UPDATED_AT = 'updated_at';
|
|
||||||
export const SORT_KEY_CLIENT_UPDATED_AT = 'client_updated_at';
|
|
||||||
export const SORT_KEY_TITLE = 'title';
|
|
||||||
|
|
||||||
export function filterAndSortNotes({
|
export enum NoteSortKey {
|
||||||
notes,
|
CreatedAt = 'created_at',
|
||||||
selectedTag,
|
UpdatedAt = 'updated_at',
|
||||||
showArchived,
|
ClientUpdatedAt = 'client_updated_at',
|
||||||
hidePinned,
|
Title = 'title',
|
||||||
filterText,
|
}
|
||||||
sortBy,
|
|
||||||
reverse
|
export function filterAndSortNotes(
|
||||||
}) {
|
notes: SNNote[],
|
||||||
const filtered = filterNotes({
|
selectedTag: SNTag,
|
||||||
|
showArchived: boolean,
|
||||||
|
hidePinned: boolean,
|
||||||
|
filterText: string,
|
||||||
|
sortBy: string,
|
||||||
|
reverse: boolean,
|
||||||
|
) {
|
||||||
|
const filtered = filterNotes(
|
||||||
notes,
|
notes,
|
||||||
selectedTag,
|
selectedTag,
|
||||||
showArchived,
|
showArchived,
|
||||||
hidePinned,
|
hidePinned,
|
||||||
filterText,
|
filterText,
|
||||||
});
|
);
|
||||||
const sorted = sortNotes({
|
const sorted = sortNotes(
|
||||||
notes: filtered,
|
filtered,
|
||||||
sortBy,
|
sortBy,
|
||||||
reverse
|
reverse
|
||||||
});
|
);
|
||||||
return sorted;
|
return sorted;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function filterNotes({
|
export function filterNotes(
|
||||||
notes,
|
notes: SNNote[],
|
||||||
selectedTag,
|
selectedTag: SNTag,
|
||||||
showArchived,
|
showArchived: boolean,
|
||||||
hidePinned,
|
hidePinned: boolean,
|
||||||
filterText
|
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.content.isTrashTag;
|
const isTrash = selectedTag.isTrashTag;
|
||||||
if (!isTrash && note.content.trashed) {
|
if (!isTrash && note.trashed) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const isSmartTag = selectedTag.isSmartTag();
|
const isSmartTag = selectedTag.isSmartTag();
|
||||||
if (isSmartTag) {
|
if (isSmartTag) {
|
||||||
canShowArchived = (
|
canShowArchived = (
|
||||||
canShowArchived ||
|
canShowArchived ||
|
||||||
selectedTag.content.isArchiveTag ||
|
selectedTag.isArchiveTag ||
|
||||||
isTrash
|
isTrash
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -55,17 +59,14 @@ export function filterNotes({
|
|||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return noteMatchesQuery({
|
return noteMatchesQuery(note, filterText);
|
||||||
note,
|
|
||||||
query: filterText
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function noteMatchesQuery({
|
function noteMatchesQuery(
|
||||||
note,
|
note: SNNote,
|
||||||
query
|
query: string
|
||||||
}) {
|
) {
|
||||||
if(query.length === 0) {
|
if(query.length === 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -93,12 +94,12 @@ function noteMatchesQuery({
|
|||||||
return matchesTitle || matchesBody;
|
return matchesTitle || matchesBody;
|
||||||
}
|
}
|
||||||
|
|
||||||
function stringBetweenQuotes(text) {
|
function stringBetweenQuotes(text: string) {
|
||||||
const matches = text.match(/"(.*?)"/);
|
const matches = text.match(/"(.*?)"/);
|
||||||
return matches ? matches[1] : null;
|
return matches ? matches[1] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function stringIsUuid(text) {
|
function stringIsUuid(text: string) {
|
||||||
const matches = text.match(
|
const matches = text.match(
|
||||||
/\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b/
|
/\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b/
|
||||||
);
|
);
|
||||||
@@ -106,12 +107,12 @@ function stringIsUuid(text) {
|
|||||||
return matches ? true : false;
|
return matches ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function sortNotes({
|
export function sortNotes(
|
||||||
notes = [],
|
notes: SNNote[] = [],
|
||||||
sortBy,
|
sortBy: string,
|
||||||
reverse
|
reverse: boolean
|
||||||
}) {
|
) {
|
||||||
const sortValueFn = (a, b, pinCheck = false) => {
|
const sortValueFn = (a: SNNote, b: SNNote, pinCheck = false): number => {
|
||||||
if (a.dummy) { return -1; }
|
if (a.dummy) { return -1; }
|
||||||
if (b.dummy) { return 1; }
|
if (b.dummy) { return 1; }
|
||||||
if (!pinCheck) {
|
if (!pinCheck) {
|
||||||
@@ -121,14 +122,13 @@ export function sortNotes({
|
|||||||
if (a.pinned) { return -1; }
|
if (a.pinned) { return -1; }
|
||||||
if (b.pinned) { return 1; }
|
if (b.pinned) { return 1; }
|
||||||
}
|
}
|
||||||
|
let aValue = (a as any)[sortBy] || '';
|
||||||
let aValue = a[sortBy] || '';
|
let bValue = (a as any)[sortBy] || '';
|
||||||
let bValue = b[sortBy] || '';
|
|
||||||
let vector = 1;
|
let vector = 1;
|
||||||
if (reverse) {
|
if (reverse) {
|
||||||
vector *= -1;
|
vector *= -1;
|
||||||
}
|
}
|
||||||
if (sortBy === SORT_KEY_TITLE) {
|
if (sortBy === NoteSortKey.Title) {
|
||||||
aValue = aValue.toLowerCase();
|
aValue = aValue.toLowerCase();
|
||||||
bValue = bValue.toLowerCase();
|
bValue = bValue.toLowerCase();
|
||||||
if (aValue.length === 0 && bValue.length === 0) {
|
if (aValue.length === 0 && bValue.length === 0) {
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
|
import { PanelPuppet, WebDirective } from './../../types';
|
||||||
import angular from 'angular';
|
import angular from 'angular';
|
||||||
import template from '%/notes.pug';
|
import template from '%/notes.pug';
|
||||||
import { ApplicationEvent, ContentTypes, removeFromArray } from 'snjs';
|
import { ApplicationEvent, ContentType, removeFromArray, SNNote, SNTag } from 'snjs';
|
||||||
import { PureCtrl } from '@Controllers';
|
import { PureCtrl } from '@Controllers/abstract/pure_ctrl';
|
||||||
import { AppStateEvent } from '@/services/state';
|
import { AppStateEvent } from '@/services/state';
|
||||||
import { KeyboardModifier, KeyboardKey } from '@/services/keyboardManager';
|
import { KeyboardModifier, KeyboardKey } from '@/services/keyboardManager';
|
||||||
import {
|
import {
|
||||||
@@ -11,12 +12,31 @@ import {
|
|||||||
PANEL_NAME_NOTES
|
PANEL_NAME_NOTES
|
||||||
} from '@/controllers/constants';
|
} from '@/controllers/constants';
|
||||||
import {
|
import {
|
||||||
SORT_KEY_CREATED_AT,
|
NoteSortKey,
|
||||||
SORT_KEY_UPDATED_AT,
|
|
||||||
SORT_KEY_CLIENT_UPDATED_AT,
|
|
||||||
SORT_KEY_TITLE,
|
|
||||||
filterAndSortNotes
|
filterAndSortNotes
|
||||||
} from './note_utils';
|
} from './note_utils';
|
||||||
|
import { UuidString } from '@/../../../../snjs/dist/@types/types';
|
||||||
|
|
||||||
|
type NotesState = {
|
||||||
|
tag?: SNTag
|
||||||
|
notes?: SNNote[]
|
||||||
|
renderedNotes?: SNNote[]
|
||||||
|
selectedNote?: SNNote
|
||||||
|
sortBy?: string
|
||||||
|
sortReverse?: boolean
|
||||||
|
showArchived?: boolean
|
||||||
|
hidePinned?: boolean
|
||||||
|
hideNotePreview?: boolean
|
||||||
|
hideDate?: boolean
|
||||||
|
hideTags?: boolean
|
||||||
|
noteFilter: { text: string }
|
||||||
|
mutable: { showMenu: boolean }
|
||||||
|
}
|
||||||
|
|
||||||
|
type NoteFlag = {
|
||||||
|
text: string
|
||||||
|
class: 'info' | 'neutral' | 'warning' | 'success' | 'danger'
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the height of a note cell with nothing but the title,
|
* This is the height of a note cell with nothing but the title,
|
||||||
@@ -29,10 +49,19 @@ const ELEMENT_ID_SCROLL_CONTAINER = 'notes-scrollable';
|
|||||||
|
|
||||||
class NotesCtrl extends PureCtrl {
|
class NotesCtrl extends PureCtrl {
|
||||||
|
|
||||||
|
private panelPuppet?: PanelPuppet
|
||||||
|
private reloadNotesPromise?: any
|
||||||
|
private notesToDisplay = 0
|
||||||
|
private pageSize = 0
|
||||||
|
private searchSubmitted = false
|
||||||
|
private newNoteKeyObserver: any
|
||||||
|
private nextNoteKeyObserver: any
|
||||||
|
private previousNoteKeyObserver: any
|
||||||
|
private searchKeyObserver: any
|
||||||
|
private noteFlags: Partial<Record<UuidString, NoteFlag[]>> = {}
|
||||||
|
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor(
|
constructor($timeout: ng.ITimeoutService, ) {
|
||||||
$timeout,
|
|
||||||
) {
|
|
||||||
super($timeout);
|
super($timeout);
|
||||||
this.resetPagination();
|
this.resetPagination();
|
||||||
}
|
}
|
||||||
@@ -46,53 +75,62 @@ class NotesCtrl extends PureCtrl {
|
|||||||
onReady: () => this.reloadPreferences()
|
onReady: () => this.reloadPreferences()
|
||||||
};
|
};
|
||||||
this.onWindowResize = this.onWindowResize.bind(this);
|
this.onWindowResize = this.onWindowResize.bind(this);
|
||||||
|
this.onPanelResize = this.onPanelResize.bind(this);
|
||||||
window.addEventListener('resize', this.onWindowResize, true);
|
window.addEventListener('resize', this.onWindowResize, true);
|
||||||
this.registerKeyboardShortcuts();
|
this.registerKeyboardShortcuts();
|
||||||
}
|
}
|
||||||
|
|
||||||
onWindowResize() {
|
onWindowResize() {
|
||||||
this.resetPagination({
|
this.resetPagination(true);
|
||||||
keepCurrentIfLarger: true
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit() {
|
deinit() {
|
||||||
this.panelPuppet.onReady = null;
|
this.panelPuppet!.onReady = undefined;
|
||||||
this.panelPuppet = null;
|
this.panelPuppet = undefined;
|
||||||
window.removeEventListener('resize', this.onWindowResize, true);
|
window.removeEventListener('resize', this.onWindowResize, true);
|
||||||
this.onWindowResize = null;
|
(this.onWindowResize as any) = undefined;
|
||||||
this.onPanelResize = null;
|
(this.onPanelResize as any) = undefined;
|
||||||
|
this.newNoteKeyObserver();
|
||||||
|
this.nextNoteKeyObserver();
|
||||||
|
this.previousNoteKeyObserver();
|
||||||
|
this.searchKeyObserver();
|
||||||
|
this.newNoteKeyObserver = undefined;
|
||||||
|
this.nextNoteKeyObserver = undefined;
|
||||||
|
this.previousNoteKeyObserver = undefined;
|
||||||
|
this.searchKeyObserver = undefined;
|
||||||
super.deinit();
|
super.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getState() {
|
||||||
|
return this.state as NotesState;
|
||||||
|
}
|
||||||
|
|
||||||
getInitialState() {
|
getInitialState() {
|
||||||
return {
|
return {
|
||||||
notes: [],
|
notes: [],
|
||||||
renderedNotes: [],
|
renderedNotes: [],
|
||||||
selectedNote: null,
|
|
||||||
tag: null,
|
|
||||||
sortBy: null,
|
|
||||||
showArchived: null,
|
|
||||||
hidePinned: null,
|
|
||||||
sortReverse: null,
|
|
||||||
panelTitle: null,
|
|
||||||
mutable: { showMenu: false },
|
mutable: { showMenu: false },
|
||||||
noteFilter: { text: '' },
|
noteFilter: { text: '' },
|
||||||
};
|
} as NotesState;
|
||||||
}
|
}
|
||||||
|
|
||||||
onAppLaunch() {
|
async onAppLaunch() {
|
||||||
super.onAppLaunch();
|
super.onAppLaunch();
|
||||||
this.streamNotesAndTags();
|
this.streamNotesAndTags();
|
||||||
this.reloadPreferences();
|
this.reloadPreferences();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
onAppStateEvent(eventName, data) {
|
onAppStateEvent(eventName: AppStateEvent, data?: any) {
|
||||||
if (eventName === AppStateEvent.TagChanged) {
|
if (eventName === AppStateEvent.TagChanged) {
|
||||||
this.handleTagChange(this.application.getAppState().getSelectedTag(), data.previousTag);
|
this.handleTagChange(
|
||||||
|
this.application!.getAppState().getSelectedTag()!,
|
||||||
|
data.previousTag
|
||||||
|
);
|
||||||
} else if (eventName === AppStateEvent.NoteChanged) {
|
} else if (eventName === AppStateEvent.NoteChanged) {
|
||||||
this.handleNoteSelection(this.application.getAppState().getSelectedNote());
|
this.handleNoteSelection(
|
||||||
|
this.application!.getAppState().getSelectedNote()!
|
||||||
|
);
|
||||||
} else if (eventName === AppStateEvent.PreferencesChanged) {
|
} else if (eventName === AppStateEvent.PreferencesChanged) {
|
||||||
this.reloadPreferences();
|
this.reloadPreferences();
|
||||||
this.reloadNotes();
|
this.reloadNotes();
|
||||||
@@ -102,12 +140,12 @@ class NotesCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
async onAppEvent(eventName) {
|
async onAppEvent(eventName: ApplicationEvent) {
|
||||||
if (eventName === ApplicationEvent.SignedIn) {
|
if (eventName === ApplicationEvent.SignedIn) {
|
||||||
/** Delete dummy note if applicable */
|
/** Delete dummy note if applicable */
|
||||||
if (this.state.selectedNote && this.state.selectedNote.dummy) {
|
if (this.getState().selectedNote && this.getState().selectedNote!.dummy) {
|
||||||
this.application.deleteItemLocally({ item: this.state.selectedNote });
|
this.application!.deleteItemLocally(this.getState().selectedNote!);
|
||||||
await this.selectNote(null);
|
await this.selectNote(undefined);
|
||||||
await this.reloadNotes();
|
await this.reloadNotes();
|
||||||
}
|
}
|
||||||
} else if (eventName === ApplicationEvent.CompletedSync) {
|
} else if (eventName === ApplicationEvent.CompletedSync) {
|
||||||
@@ -125,7 +163,7 @@ class NotesCtrl extends PureCtrl {
|
|||||||
* that may be in progress. This is the sync alternative to `async getMostValidNotes`
|
* that may be in progress. This is the sync alternative to `async getMostValidNotes`
|
||||||
*/
|
*/
|
||||||
getPossiblyStaleNotes() {
|
getPossiblyStaleNotes() {
|
||||||
return this.state.notes;
|
return this.getState().notes!;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -146,21 +184,21 @@ class NotesCtrl extends PureCtrl {
|
|||||||
* @access private
|
* @access private
|
||||||
*/
|
*/
|
||||||
async createPlaceholderNote() {
|
async createPlaceholderNote() {
|
||||||
const selectedTag = this.application.getAppState().getSelectedTag();
|
const selectedTag = this.application!.getAppState().getSelectedTag()!;
|
||||||
if (selectedTag.isSmartTag() && !selectedTag.content.isAllTag) {
|
if (selectedTag.isSmartTag() && !selectedTag.isAllTag) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return this.createNewNote();
|
return this.createNewNote();
|
||||||
}
|
}
|
||||||
|
|
||||||
streamNotesAndTags() {
|
streamNotesAndTags() {
|
||||||
this.application.streamItems({
|
this.application!.streamItems(
|
||||||
contentType: [ContentType.Note, ContentType.Tag],
|
[ContentType.Note, ContentType.Tag],
|
||||||
stream: async ({ items }) => {
|
async (items) => {
|
||||||
await this.reloadNotes();
|
await this.reloadNotes();
|
||||||
const selectedNote = this.state.selectedNote;
|
const selectedNote = this.getState().selectedNote;
|
||||||
if (selectedNote) {
|
if (selectedNote) {
|
||||||
const discarded = selectedNote.deleted || selectedNote.content.trashed;
|
const discarded = selectedNote.deleted || selectedNote.trashed;
|
||||||
if (discarded) {
|
if (discarded) {
|
||||||
this.selectNextOrCreateNew();
|
this.selectNextOrCreateNew();
|
||||||
}
|
}
|
||||||
@@ -169,87 +207,83 @@ class NotesCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Note has changed values, reset its flags */
|
/** Note has changed values, reset its flags */
|
||||||
const notes = items.filter((item) => item.content_type === ContentType.Note);
|
const notes = items.filter((item) => item.content_type === ContentType.Note) as SNNote[];
|
||||||
for (const note of notes) {
|
for (const note of notes) {
|
||||||
if(note.deleted) {
|
if (note.deleted) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
this.loadFlagsForNote(note);
|
this.loadFlagsForNote(note);
|
||||||
note.cachedCreatedAtString = note.createdAtString();
|
|
||||||
note.cachedUpdatedAtString = note.updatedAtString();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async selectNote(note) {
|
async selectNote(note?: SNNote) {
|
||||||
return this.application.getAppState().setSelectedNote(note);
|
return this.application!.getAppState().setSelectedNote(note);
|
||||||
}
|
}
|
||||||
|
|
||||||
async createNewNote() {
|
async createNewNote() {
|
||||||
const selectedTag = this.application.getAppState().getSelectedTag();
|
const selectedTag = this.application!.getAppState().getSelectedTag();
|
||||||
if (!selectedTag) {
|
if (!selectedTag) {
|
||||||
throw 'Attempting to create note with no selected tag';
|
throw 'Attempting to create note with no selected tag';
|
||||||
}
|
}
|
||||||
let title;
|
let title;
|
||||||
let isDummyNote = true;
|
let isDummyNote = true;
|
||||||
if (this.isFiltering()) {
|
if (this.isFiltering()) {
|
||||||
title = this.state.noteFilter.text;
|
title = this.getState().noteFilter.text;
|
||||||
isDummyNote = false;
|
isDummyNote = false;
|
||||||
} else if (this.state.selectedNote && this.state.selectedNote.dummy) {
|
} else if (this.getState().selectedNote && this.getState().selectedNote!.dummy) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
title = `Note ${this.state.notes.length + 1}`;
|
title = `Note ${this.getState().notes!.length + 1}`;
|
||||||
}
|
}
|
||||||
const newNote = await this.application.createManagedItem({
|
const newNote = await this.application!.createManagedItem(
|
||||||
contentType: ContentType.Note,
|
ContentType.Note,
|
||||||
content: {
|
{
|
||||||
text: '',
|
text: '',
|
||||||
title: title
|
title: title,
|
||||||
|
references: []
|
||||||
},
|
},
|
||||||
override: {
|
true,
|
||||||
dummy: isDummyNote,
|
{
|
||||||
client_updated_at: new Date()
|
dummy: isDummyNote
|
||||||
}
|
}
|
||||||
});
|
) as SNNote;
|
||||||
this.application.setItemNeedsSync({ item: newNote });
|
|
||||||
if (!selectedTag.isSmartTag()) {
|
if (!selectedTag.isSmartTag()) {
|
||||||
selectedTag.addItemAsRelationship(newNote);
|
this.application!.changeItem(selectedTag.uuid, (mutator) => {
|
||||||
this.application.setItemNeedsSync({ item: selectedTag });
|
mutator.addItemAsRelationship(newNote);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
this.selectNote(newNote);
|
this.selectNote(newNote);
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleTagChange(tag, previousTag) {
|
async handleTagChange(tag: SNTag, previousTag?: SNTag) {
|
||||||
if (this.state.selectedNote && this.state.selectedNote.dummy) {
|
if (this.getState().selectedNote && this.getState().selectedNote!.dummy) {
|
||||||
await this.application.deleteItemLocally({ item: this.state.selectedNote });
|
await this.application!.deleteItemLocally(this.getState().selectedNote!);
|
||||||
if (previousTag) {
|
await this.selectNote(undefined);
|
||||||
removeFromArray(previousTag.notes, this.state.selectedNote);
|
|
||||||
}
|
|
||||||
await this.selectNote(null);
|
|
||||||
}
|
}
|
||||||
await this.setState({ tag: tag });
|
await this.setState({ tag: tag });
|
||||||
|
|
||||||
this.resetScrollPosition();
|
this.resetScrollPosition();
|
||||||
this.setShowMenuFalse();
|
this.setShowMenuFalse();
|
||||||
await this.setNoteFilterText('');
|
await this.setNoteFilterText('');
|
||||||
this.application.getDesktopService().searchText();
|
this.application!.getDesktopService().searchText();
|
||||||
this.resetPagination();
|
this.resetPagination();
|
||||||
|
|
||||||
/* Capture db load state before beginning reloadNotes, since this status may change during reload */
|
/* Capture db load state before beginning reloadNotes, since this status may change during reload */
|
||||||
const dbLoaded = this.application.isDatabaseLoaded();
|
const dbLoaded = this.application!.isDatabaseLoaded();
|
||||||
await this.reloadNotes();
|
await this.reloadNotes();
|
||||||
|
|
||||||
if (this.state.notes.length > 0) {
|
if (this.getState().notes!.length > 0) {
|
||||||
this.selectFirstNote();
|
this.selectFirstNote();
|
||||||
} else if (dbLoaded) {
|
} else if (dbLoaded) {
|
||||||
if (!tag.isSmartTag() || tag.content.isAllTag) {
|
if (!tag.isSmartTag() || tag.isAllTag) {
|
||||||
this.createPlaceholderNote();
|
this.createPlaceholderNote();
|
||||||
} else if (
|
} else if (
|
||||||
this.state.selectedNote &&
|
this.getState().selectedNote &&
|
||||||
!this.state.notes.includes(this.state.selectedNote)
|
!this.getState().notes!.includes(this.getState().selectedNote!)
|
||||||
) {
|
) {
|
||||||
this.selectNote(null);
|
this.selectNote(undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -262,8 +296,8 @@ class NotesCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async removeNoteFromList(note) {
|
async removeNoteFromList(note: SNNote) {
|
||||||
const notes = this.state.notes;
|
const notes = this.getState().notes!;
|
||||||
removeFromArray(notes, note);
|
removeFromArray(notes, note);
|
||||||
await this.setState({
|
await this.setState({
|
||||||
notes: notes,
|
notes: notes,
|
||||||
@@ -277,23 +311,24 @@ class NotesCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async performPeloadNotes() {
|
async performPeloadNotes() {
|
||||||
if (!this.state.tag) {
|
const tag = this.getState().tag!;
|
||||||
|
if (!tag) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const notes = filterAndSortNotes({
|
const tagNotes = this.appState.getTagNotes(tag);
|
||||||
notes: this.state.tag.notes,
|
const notes = filterAndSortNotes(
|
||||||
selectedTag: this.state.tag,
|
tagNotes,
|
||||||
showArchived: this.state.showArchived,
|
tag,
|
||||||
hidePinned: this.state.hidePinned,
|
this.getState().showArchived!,
|
||||||
filterText: this.state.noteFilter.text.toLowerCase(),
|
this.getState().hidePinned!,
|
||||||
sortBy: this.state.sortBy,
|
this.getState().noteFilter.text.toLowerCase(),
|
||||||
reverse: this.state.sortReverse
|
this.getState().sortBy!,
|
||||||
});
|
this.getState().sortReverse!
|
||||||
|
);
|
||||||
for (const note of notes) {
|
for (const note of notes) {
|
||||||
if (note.errorDecrypting) {
|
if (note.errorDecrypting) {
|
||||||
this.loadFlagsForNote(note);
|
this.loadFlagsForNote(note);
|
||||||
}
|
}
|
||||||
note.shouldShowTags = this.shouldShowTagsForNote(note);
|
|
||||||
}
|
}
|
||||||
await this.setState({
|
await this.setState({
|
||||||
notes: notes,
|
notes: notes,
|
||||||
@@ -305,19 +340,19 @@ class NotesCtrl extends PureCtrl {
|
|||||||
setShowMenuFalse() {
|
setShowMenuFalse() {
|
||||||
this.setState({
|
this.setState({
|
||||||
mutable: {
|
mutable: {
|
||||||
...this.state.mutable,
|
...this.getState().mutable,
|
||||||
showMenu: false
|
showMenu: false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleNoteSelection(note) {
|
async handleNoteSelection(note: SNNote) {
|
||||||
const previousNote = this.state.selectedNote;
|
const previousNote = this.getState().selectedNote;
|
||||||
if (previousNote === note) {
|
if (previousNote === note) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (previousNote && previousNote.dummy) {
|
if (previousNote && previousNote.dummy) {
|
||||||
await this.application.deleteItemLocally({ item: previousNote });
|
await this.application!.deleteItemLocally(previousNote);
|
||||||
this.removeNoteFromList(previousNote);
|
this.removeNoteFromList(previousNote);
|
||||||
}
|
}
|
||||||
await this.setState({
|
await this.setState({
|
||||||
@@ -326,49 +361,49 @@ class NotesCtrl extends PureCtrl {
|
|||||||
if (!note) {
|
if (!note) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.selectedIndex = Math.max(0, this.displayableNotes().indexOf(note));
|
if (note.conflictOf) {
|
||||||
if (note.content.conflict_of) {
|
this.application!.changeAndSaveItem(note.uuid, (mutator) => {
|
||||||
note.content.conflict_of = null;
|
mutator.conflictOf = undefined;
|
||||||
this.application.saveItem({ item: note });
|
})
|
||||||
}
|
}
|
||||||
if (this.isFiltering()) {
|
if (this.isFiltering()) {
|
||||||
this.application.getDesktopService().searchText(this.state.noteFilter.text);
|
this.application!.getDesktopService().searchText(this.getState().noteFilter.text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reloadPreferences() {
|
reloadPreferences() {
|
||||||
const viewOptions = {};
|
const viewOptions = {} as NotesState;
|
||||||
const prevSortValue = this.state.sortBy;
|
const prevSortValue = this.getState().sortBy;
|
||||||
let sortBy = this.application.getPrefsService().getValue(
|
let sortBy = this.application!.getPrefsService().getValue(
|
||||||
PrefKeys.SortNotesBy,
|
PrefKeys.SortNotesBy,
|
||||||
SORT_KEY_CREATED_AT
|
NoteSortKey.CreatedAt
|
||||||
);
|
);
|
||||||
if (sortBy === SORT_KEY_UPDATED_AT) {
|
if (sortBy === NoteSortKey.UpdatedAt) {
|
||||||
/** Use client_updated_at instead */
|
/** Use client_updated_at instead */
|
||||||
sortBy = SORT_KEY_CLIENT_UPDATED_AT;
|
sortBy = NoteSortKey.ClientUpdatedAt;
|
||||||
}
|
}
|
||||||
viewOptions.sortBy = sortBy;
|
viewOptions.sortBy = sortBy;
|
||||||
viewOptions.sortReverse = this.application.getPrefsService().getValue(
|
viewOptions.sortReverse = this.application!.getPrefsService().getValue(
|
||||||
PrefKeys.SortNotesReverse,
|
PrefKeys.SortNotesReverse,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
viewOptions.showArchived = this.application.getPrefsService().getValue(
|
viewOptions.showArchived = this.application!.getPrefsService().getValue(
|
||||||
PrefKeys.NotesShowArchived,
|
PrefKeys.NotesShowArchived,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
viewOptions.hidePinned = this.application.getPrefsService().getValue(
|
viewOptions.hidePinned = this.application!.getPrefsService().getValue(
|
||||||
PrefKeys.NotesHidePinned,
|
PrefKeys.NotesHidePinned,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
viewOptions.hideNotePreview = this.application.getPrefsService().getValue(
|
viewOptions.hideNotePreview = this.application!.getPrefsService().getValue(
|
||||||
PrefKeys.NotesHideNotePreview,
|
PrefKeys.NotesHideNotePreview,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
viewOptions.hideDate = this.application.getPrefsService().getValue(
|
viewOptions.hideDate = this.application!.getPrefsService().getValue(
|
||||||
PrefKeys.NotesHideDate,
|
PrefKeys.NotesHideDate,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
viewOptions.hideTags = this.application.getPrefsService().getValue(
|
viewOptions.hideTags = this.application!.getPrefsService().getValue(
|
||||||
PrefKeys.NotesHideTags,
|
PrefKeys.NotesHideTags,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
@@ -378,27 +413,32 @@ class NotesCtrl extends PureCtrl {
|
|||||||
if (prevSortValue && prevSortValue !== sortBy) {
|
if (prevSortValue && prevSortValue !== sortBy) {
|
||||||
this.selectFirstNote();
|
this.selectFirstNote();
|
||||||
}
|
}
|
||||||
const width = this.application.getPrefsService().getValue(
|
const width = this.application!.getPrefsService().getValue(
|
||||||
PrefKeys.NotesPanelWidth
|
PrefKeys.NotesPanelWidth
|
||||||
);
|
);
|
||||||
if (width && this.panelPuppet.ready) {
|
if (width && this.panelPuppet!.ready) {
|
||||||
this.panelPuppet.setWidth(width);
|
this.panelPuppet!.setWidth!(width);
|
||||||
if (this.panelPuppet.isCollapsed()) {
|
if (this.panelPuppet!.isCollapsed!()) {
|
||||||
this.application.getAppState().panelDidResize(
|
this.application!.getAppState().panelDidResize(
|
||||||
PANEL_NAME_NOTES,
|
PANEL_NAME_NOTES,
|
||||||
this.panelPuppet.isCollapsed()
|
this.panelPuppet!.isCollapsed!()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onPanelResize = (newWidth, lastLeft, isAtMaxWidth, isCollapsed) => {
|
onPanelResize(
|
||||||
this.application.getPrefsService().setUserPrefValue(
|
newWidth: number,
|
||||||
|
lastLeft: number,
|
||||||
|
isAtMaxWidth: boolean,
|
||||||
|
isCollapsed: boolean
|
||||||
|
) {
|
||||||
|
this.application!.getPrefsService().setUserPrefValue(
|
||||||
PrefKeys.NotesPanelWidth,
|
PrefKeys.NotesPanelWidth,
|
||||||
newWidth
|
newWidth
|
||||||
);
|
);
|
||||||
this.application.getPrefsService().syncUserPreferences();
|
this.application!.getPrefsService().syncUserPreferences();
|
||||||
this.application.getAppState().panelDidResize(
|
this.application!.getAppState().panelDidResize(
|
||||||
PANEL_NAME_NOTES,
|
PANEL_NAME_NOTES,
|
||||||
isCollapsed
|
isCollapsed
|
||||||
);
|
);
|
||||||
@@ -408,11 +448,11 @@ class NotesCtrl extends PureCtrl {
|
|||||||
this.notesToDisplay += this.pageSize;
|
this.notesToDisplay += this.pageSize;
|
||||||
this.reloadNotes();
|
this.reloadNotes();
|
||||||
if (this.searchSubmitted) {
|
if (this.searchSubmitted) {
|
||||||
this.application.getDesktopService().searchText(this.state.noteFilter.text);
|
this.application!.getDesktopService().searchText(this.getState().noteFilter.text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resetPagination({ keepCurrentIfLarger } = {}) {
|
resetPagination(keepCurrentIfLarger = false) {
|
||||||
const clientHeight = document.documentElement.clientHeight;
|
const clientHeight = document.documentElement.clientHeight;
|
||||||
this.pageSize = Math.ceil(clientHeight / MIN_NOTE_CELL_HEIGHT);
|
this.pageSize = Math.ceil(clientHeight / MIN_NOTE_CELL_HEIGHT);
|
||||||
if (this.pageSize === 0) {
|
if (this.pageSize === 0) {
|
||||||
@@ -427,10 +467,10 @@ class NotesCtrl extends PureCtrl {
|
|||||||
reloadPanelTitle() {
|
reloadPanelTitle() {
|
||||||
let title;
|
let title;
|
||||||
if (this.isFiltering()) {
|
if (this.isFiltering()) {
|
||||||
const resultCount = this.state.notes.length;
|
const resultCount = this.getState().notes!.length;
|
||||||
title = `${resultCount} search results`;
|
title = `${resultCount} search results`;
|
||||||
} else if (this.state.tag) {
|
} else if (this.getState().tag) {
|
||||||
title = `${this.state.tag.title}`;
|
title = `${this.getState().tag!.title}`;
|
||||||
}
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
panelTitle: title
|
panelTitle: title
|
||||||
@@ -439,27 +479,27 @@ class NotesCtrl extends PureCtrl {
|
|||||||
|
|
||||||
optionsSubtitle() {
|
optionsSubtitle() {
|
||||||
let base = "";
|
let base = "";
|
||||||
if (this.state.sortBy === 'created_at') {
|
if (this.getState().sortBy === 'created_at') {
|
||||||
base += " Date Added";
|
base += " Date Added";
|
||||||
} else if (this.state.sortBy === 'client_updated_at') {
|
} else if (this.getState().sortBy === 'client_updated_at') {
|
||||||
base += " Date Modified";
|
base += " Date Modified";
|
||||||
} else if (this.state.sortBy === 'title') {
|
} else if (this.getState().sortBy === 'title') {
|
||||||
base += " Title";
|
base += " Title";
|
||||||
}
|
}
|
||||||
if (this.state.showArchived) {
|
if (this.getState().showArchived) {
|
||||||
base += " | + Archived";
|
base += " | + Archived";
|
||||||
}
|
}
|
||||||
if (this.state.hidePinned) {
|
if (this.getState().hidePinned) {
|
||||||
base += " | – Pinned";
|
base += " | – Pinned";
|
||||||
}
|
}
|
||||||
if (this.state.sortReverse) {
|
if (this.getState().sortReverse) {
|
||||||
base += " | Reversed";
|
base += " | Reversed";
|
||||||
}
|
}
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
loadFlagsForNote(note) {
|
loadFlagsForNote(note: SNNote) {
|
||||||
const flags = [];
|
const flags = [] as NoteFlag[];
|
||||||
if (note.pinned) {
|
if (note.pinned) {
|
||||||
flags.push({
|
flags.push({
|
||||||
text: "Pinned",
|
text: "Pinned",
|
||||||
@@ -472,7 +512,7 @@ class NotesCtrl extends PureCtrl {
|
|||||||
class: 'warning'
|
class: 'warning'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (note.content.protected) {
|
if (note.protected) {
|
||||||
flags.push({
|
flags.push({
|
||||||
text: "Protected",
|
text: "Protected",
|
||||||
class: 'success'
|
class: 'success'
|
||||||
@@ -484,13 +524,13 @@ class NotesCtrl extends PureCtrl {
|
|||||||
class: 'neutral'
|
class: 'neutral'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (note.content.trashed) {
|
if (note.trashed) {
|
||||||
flags.push({
|
flags.push({
|
||||||
text: "Deleted",
|
text: "Deleted",
|
||||||
class: 'danger'
|
class: 'danger'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (note.content.conflict_of) {
|
if (note.conflictOf) {
|
||||||
flags.push({
|
flags.push({
|
||||||
text: "Conflicted Copy",
|
text: "Conflicted Copy",
|
||||||
class: 'danger'
|
class: 'danger'
|
||||||
@@ -515,19 +555,19 @@ class NotesCtrl extends PureCtrl {
|
|||||||
class: 'danger'
|
class: 'danger'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
note.flags = flags;
|
this.noteFlags[note.uuid] = flags;
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
displayableNotes() {
|
displayableNotes() {
|
||||||
return this.state.notes;
|
return this.getState().notes!;
|
||||||
}
|
}
|
||||||
|
|
||||||
getFirstNonProtectedNote() {
|
getFirstNonProtectedNote() {
|
||||||
const displayableNotes = this.displayableNotes();
|
const displayableNotes = this.displayableNotes();
|
||||||
let index = 0;
|
let index = 0;
|
||||||
let note = displayableNotes[index];
|
let note = displayableNotes[index];
|
||||||
while (note && note.content.protected) {
|
while (note && note.protected) {
|
||||||
index++;
|
index++;
|
||||||
if (index >= displayableNotes.length) {
|
if (index >= displayableNotes.length) {
|
||||||
break;
|
break;
|
||||||
@@ -546,7 +586,9 @@ class NotesCtrl extends PureCtrl {
|
|||||||
|
|
||||||
selectNextNote() {
|
selectNextNote() {
|
||||||
const displayableNotes = this.displayableNotes();
|
const displayableNotes = this.displayableNotes();
|
||||||
const currentIndex = displayableNotes.indexOf(this.state.selectedNote);
|
const currentIndex = displayableNotes.findIndex((candidate) => {
|
||||||
|
return candidate.uuid === this.getState().selectedNote!.uuid
|
||||||
|
});
|
||||||
if (currentIndex + 1 < displayableNotes.length) {
|
if (currentIndex + 1 < displayableNotes.length) {
|
||||||
this.selectNote(displayableNotes[currentIndex + 1]);
|
this.selectNote(displayableNotes[currentIndex + 1]);
|
||||||
}
|
}
|
||||||
@@ -556,16 +598,16 @@ class NotesCtrl extends PureCtrl {
|
|||||||
const note = this.getFirstNonProtectedNote();
|
const note = this.getFirstNonProtectedNote();
|
||||||
if (note) {
|
if (note) {
|
||||||
this.selectNote(note);
|
this.selectNote(note);
|
||||||
} else if (!this.state.tag || !this.state.tag.isSmartTag()) {
|
} else if (!this.getState().tag || !this.getState().tag!.isSmartTag()) {
|
||||||
this.createPlaceholderNote();
|
this.createPlaceholderNote();
|
||||||
} else {
|
} else {
|
||||||
this.selectNote(null);
|
this.selectNote(undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
selectPreviousNote() {
|
selectPreviousNote() {
|
||||||
const displayableNotes = this.displayableNotes();
|
const displayableNotes = this.displayableNotes();
|
||||||
const currentIndex = displayableNotes.indexOf(this.state.selectedNote);
|
const currentIndex = displayableNotes.indexOf(this.getState().selectedNote!);
|
||||||
if (currentIndex - 1 >= 0) {
|
if (currentIndex - 1 >= 0) {
|
||||||
this.selectNote(displayableNotes[currentIndex - 1]);
|
this.selectNote(displayableNotes[currentIndex - 1]);
|
||||||
return true;
|
return true;
|
||||||
@@ -575,14 +617,14 @@ class NotesCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isFiltering() {
|
isFiltering() {
|
||||||
return this.state.noteFilter.text &&
|
return this.getState().noteFilter.text &&
|
||||||
this.state.noteFilter.text.length > 0;
|
this.getState().noteFilter.text.length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
async setNoteFilterText(text) {
|
async setNoteFilterText(text: string) {
|
||||||
await this.setState({
|
await this.setState({
|
||||||
noteFilter: {
|
noteFilter: {
|
||||||
...this.state.noteFilter,
|
...this.getState().noteFilter,
|
||||||
text: text
|
text: text
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -609,66 +651,49 @@ class NotesCtrl extends PureCtrl {
|
|||||||
* enter before highlighting desktop search results.
|
* enter before highlighting desktop search results.
|
||||||
*/
|
*/
|
||||||
this.searchSubmitted = true;
|
this.searchSubmitted = true;
|
||||||
this.application.getDesktopService().searchText(this.state.noteFilter.text);
|
this.application!.getDesktopService().searchText(this.getState().noteFilter.text);
|
||||||
}
|
}
|
||||||
|
|
||||||
selectedMenuItem() {
|
selectedMenuItem() {
|
||||||
this.setShowMenuFalse();
|
this.setShowMenuFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
togglePrefKey(key) {
|
togglePrefKey(key: string) {
|
||||||
this.application.getPrefsService().setUserPrefValue(key, !this.state[key]);
|
this.application!.getPrefsService().setUserPrefValue(key, !this.state[key]);
|
||||||
this.application.getPrefsService().syncUserPreferences();
|
this.application!.getPrefsService().syncUserPreferences();
|
||||||
}
|
}
|
||||||
|
|
||||||
selectedSortByCreated() {
|
selectedSortByCreated() {
|
||||||
this.setSortBy(SORT_KEY_CREATED_AT);
|
this.setSortBy(NoteSortKey.CreatedAt);
|
||||||
}
|
}
|
||||||
|
|
||||||
selectedSortByUpdated() {
|
selectedSortByUpdated() {
|
||||||
this.setSortBy(SORT_KEY_CLIENT_UPDATED_AT);
|
this.setSortBy(NoteSortKey.ClientUpdatedAt);
|
||||||
}
|
}
|
||||||
|
|
||||||
selectedSortByTitle() {
|
selectedSortByTitle() {
|
||||||
this.setSortBy(SORT_KEY_TITLE);
|
this.setSortBy(NoteSortKey.Title);
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleReverseSort() {
|
toggleReverseSort() {
|
||||||
this.selectedMenuItem();
|
this.selectedMenuItem();
|
||||||
this.application.getPrefsService().setUserPrefValue(
|
this.application!.getPrefsService().setUserPrefValue(
|
||||||
PrefKeys.SortNotesReverse,
|
PrefKeys.SortNotesReverse,
|
||||||
!this.state.sortReverse
|
!this.getState().sortReverse
|
||||||
);
|
);
|
||||||
this.application.getPrefsService().syncUserPreferences();
|
this.application!.getPrefsService().syncUserPreferences();
|
||||||
}
|
}
|
||||||
|
|
||||||
setSortBy(type) {
|
setSortBy(type: NoteSortKey) {
|
||||||
this.application.getPrefsService().setUserPrefValue(
|
this.application!.getPrefsService().setUserPrefValue(
|
||||||
PrefKeys.SortNotesBy,
|
PrefKeys.SortNotesBy,
|
||||||
type
|
type
|
||||||
);
|
);
|
||||||
this.application.getPrefsService().syncUserPreferences();
|
this.application!.getPrefsService().syncUserPreferences();
|
||||||
}
|
|
||||||
|
|
||||||
shouldShowTagsForNote(note) {
|
|
||||||
if (this.state.hideTags || note.content.protected) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (this.state.tag.content.isAllTag) {
|
|
||||||
return note.tags && note.tags.length > 0;
|
|
||||||
}
|
|
||||||
if (this.state.tag.isSmartTag()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Inside a tag, only show tags string if
|
|
||||||
* note contains tags other than this.state.tag
|
|
||||||
*/
|
|
||||||
return note.tags && note.tags.length > 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getSearchBar() {
|
getSearchBar() {
|
||||||
return document.getElementById(ELEMENT_ID_SEARCH_BAR);
|
return document.getElementById(ELEMENT_ID_SEARCH_BAR)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
registerKeyboardShortcuts() {
|
registerKeyboardShortcuts() {
|
||||||
@@ -677,7 +702,7 @@ class NotesCtrl extends PureCtrl {
|
|||||||
* use Control modifier as well. These rules don't apply to desktop, but
|
* use Control modifier as well. These rules don't apply to desktop, but
|
||||||
* probably better to be consistent.
|
* probably better to be consistent.
|
||||||
*/
|
*/
|
||||||
this.newNoteKeyObserver = this.application.getKeyboardService().addKeyObserver({
|
this.newNoteKeyObserver = this.application!.getKeyboardService().addKeyObserver({
|
||||||
key: 'n',
|
key: 'n',
|
||||||
modifiers: [
|
modifiers: [
|
||||||
KeyboardModifier.Meta,
|
KeyboardModifier.Meta,
|
||||||
@@ -689,7 +714,7 @@ class NotesCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.nextNoteKeyObserver = this.application.getKeyboardService().addKeyObserver({
|
this.nextNoteKeyObserver = this.application!.getKeyboardService().addKeyObserver({
|
||||||
key: KeyboardKey.Down,
|
key: KeyboardKey.Down,
|
||||||
elements: [
|
elements: [
|
||||||
document.body,
|
document.body,
|
||||||
@@ -704,7 +729,7 @@ class NotesCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.nextNoteKeyObserver = this.application.getKeyboardService().addKeyObserver({
|
this.previousNoteKeyObserver = this.application!.getKeyboardService().addKeyObserver({
|
||||||
key: KeyboardKey.Up,
|
key: KeyboardKey.Up,
|
||||||
element: document.body,
|
element: document.body,
|
||||||
onKeyDown: (event) => {
|
onKeyDown: (event) => {
|
||||||
@@ -712,7 +737,7 @@ class NotesCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.searchKeyObserver = this.application.getKeyboardService().addKeyObserver({
|
this.searchKeyObserver = this.application!.getKeyboardService().addKeyObserver({
|
||||||
key: "f",
|
key: "f",
|
||||||
modifiers: [
|
modifiers: [
|
||||||
KeyboardModifier.Meta,
|
KeyboardModifier.Meta,
|
||||||
@@ -726,8 +751,9 @@ class NotesCtrl extends PureCtrl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NotesPanel {
|
export class NotesPanel extends WebDirective {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
super();
|
||||||
this.template = template;
|
this.template = template;
|
||||||
this.replace = true;
|
this.replace = true;
|
||||||
this.controller = NotesCtrl;
|
this.controller = NotesCtrl;
|
||||||
@@ -20,7 +20,7 @@ enum KeyboardKeyEvent {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type KeyboardObserver = {
|
type KeyboardObserver = {
|
||||||
key?: KeyboardKey
|
key?: KeyboardKey | string
|
||||||
modifiers?: KeyboardModifier[]
|
modifiers?: KeyboardModifier[]
|
||||||
onKeyDown?: (event: KeyboardEvent) => void
|
onKeyDown?: (event: KeyboardEvent) => void
|
||||||
onKeyUp?: (event: KeyboardEvent) => void
|
onKeyUp?: (event: KeyboardEvent) => void
|
||||||
@@ -87,7 +87,7 @@ export class KeyboardManager {
|
|||||||
|
|
||||||
eventMatchesKeyAndModifiers(
|
eventMatchesKeyAndModifiers(
|
||||||
event: KeyboardEvent,
|
event: KeyboardEvent,
|
||||||
key: KeyboardKey,
|
key: KeyboardKey | string,
|
||||||
modifiers: KeyboardModifier[] = []
|
modifiers: KeyboardModifier[] = []
|
||||||
) {
|
) {
|
||||||
const eventModifiers = this.modifiersForEvent(event);
|
const eventModifiers = this.modifiersForEvent(event);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { WebApplication } from './../application';
|
import { WebApplication } from './../application';
|
||||||
import { isDesktopApplication } from '@/utils';
|
import { isDesktopApplication } from '@/utils';
|
||||||
import pull from 'lodash/pull';
|
import pull from 'lodash/pull';
|
||||||
import { ProtectedAction, ApplicationEvent, SNTag, SNNote, SNUserPrefs } from 'snjs';
|
import { ProtectedAction, ApplicationEvent, SNTag, SNNote, SNUserPrefs, ContentType } from 'snjs';
|
||||||
|
|
||||||
export enum AppStateEvent {
|
export enum AppStateEvent {
|
||||||
TagChanged = 1,
|
TagChanged = 1,
|
||||||
@@ -48,6 +48,7 @@ export class AppState {
|
|||||||
this.application = application;
|
this.application = application;
|
||||||
this.registerVisibilityObservers();
|
this.registerVisibilityObservers();
|
||||||
this.addAppEventObserver();
|
this.addAppEventObserver();
|
||||||
|
this.streamNotesAndTags();
|
||||||
|
|
||||||
const onVisibilityChange = () => {
|
const onVisibilityChange = () => {
|
||||||
const visible = document.visibilityState === "visible";
|
const visible = document.visibilityState === "visible";
|
||||||
@@ -73,6 +74,27 @@ export class AppState {
|
|||||||
this.onVisibilityChange = undefined;
|
this.onVisibilityChange = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
streamNotesAndTags() {
|
||||||
|
this.application!.streamItems(
|
||||||
|
[ContentType.Note, ContentType.Tag],
|
||||||
|
async (items) => {
|
||||||
|
if(this.selectedNote) {
|
||||||
|
const matchingNote = items.find((candidate) => candidate.uuid === this.selectedNote!.uuid);
|
||||||
|
if(matchingNote) {
|
||||||
|
this.selectedNote = matchingNote as SNNote;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.selectedTag) {
|
||||||
|
const matchingTag = items.find((candidate) => candidate.uuid === this.selectedTag!.uuid);
|
||||||
|
if (matchingTag) {
|
||||||
|
this.selectedTag = matchingTag as SNTag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
addAppEventObserver() {
|
addAppEventObserver() {
|
||||||
this.unsubApp = this.application.addEventObserver(async (eventName) => {
|
this.unsubApp = this.application.addEventObserver(async (eventName) => {
|
||||||
if (eventName === ApplicationEvent.Started) {
|
if (eventName === ApplicationEvent.Started) {
|
||||||
@@ -166,12 +188,20 @@ export class AppState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns the tags that are referncing this note */
|
||||||
getNoteTags(note: SNNote) {
|
getNoteTags(note: SNNote) {
|
||||||
return this.application.referencesForItem(note).filter((ref) => {
|
return this.application.referencingForItem(note).filter((ref) => {
|
||||||
return ref.content_type === note.content_type;
|
return ref.content_type === note.content_type;
|
||||||
}) as SNTag[]
|
}) as SNTag[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns the notes this tag references */
|
||||||
|
getTagNotes(tag: SNTag) {
|
||||||
|
return this.application.referencesForItem(tag).filter((ref) => {
|
||||||
|
return ref.content_type === tag.content_type;
|
||||||
|
}) as SNNote[]
|
||||||
|
}
|
||||||
|
|
||||||
getSelectedTag() {
|
getSelectedTag() {
|
||||||
return this.selectedTag;
|
return this.selectedTag;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export interface PasswordWizardScope extends Partial<ng.IScope> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type PanelPuppet = {
|
export type PanelPuppet = {
|
||||||
onReady: () => void
|
onReady?: () => void
|
||||||
ready?: boolean
|
ready?: boolean
|
||||||
setWidth?: (width: number) => void
|
setWidth?: (width: number) => void
|
||||||
setLeft?: (left: number) => void
|
setLeft?: (left: number) => void
|
||||||
|
|||||||
@@ -112,8 +112,8 @@
|
|||||||
ng-class="{'selected' : self.state.selectedNote == note}"
|
ng-class="{'selected' : self.state.selectedNote == note}"
|
||||||
ng-click='self.selectNote(note, true)'
|
ng-click='self.selectNote(note, true)'
|
||||||
)
|
)
|
||||||
.note-flags(ng-show='note.flags.length > 0')
|
.note-flags(ng-show='self.noteFlags[note.uuid].length > 0')
|
||||||
.flag(ng-class='flag.class', ng-repeat='flag in note.flags')
|
.flag(ng-class='flag.class', ng-repeat='flag in self.noteFlags[note.uuid]')
|
||||||
.label {{flag.text}}
|
.label {{flag.text}}
|
||||||
.name(ng-show='note.title')
|
.name(ng-show='note.title')
|
||||||
| {{note.title}}
|
| {{note.title}}
|
||||||
@@ -135,11 +135,9 @@
|
|||||||
) {{note.text}}
|
) {{note.text}}
|
||||||
.date.faded(ng-show='!self.state.hideDate')
|
.date.faded(ng-show='!self.state.hideDate')
|
||||||
span(ng-show="self.state.sortBy == 'client_updated_at'")
|
span(ng-show="self.state.sortBy == 'client_updated_at'")
|
||||||
| Modified {{note.cachedUpdatedAtString || 'Now'}}
|
| Modified {{note.updatedAtString || 'Now'}}
|
||||||
span(ng-show="self.state.sortBy != 'client_updated_at'")
|
span(ng-show="self.state.sortBy != 'client_updated_at'")
|
||||||
| {{note.cachedCreatedAtString || 'Now'}}
|
| {{note.createdAtString || 'Now'}}
|
||||||
.tags-string(ng-show='note.shouldShowTags')
|
|
||||||
.faded {{note.savedTagsString || note.tagsString()}}
|
|
||||||
panel-resizer(
|
panel-resizer(
|
||||||
collapsable="true"
|
collapsable="true"
|
||||||
control="self.panelPuppet"
|
control="self.panelPuppet"
|
||||||
|
|||||||
Reference in New Issue
Block a user