Merge branch 'release/3.6.2' into main
This commit is contained in:
@@ -40,14 +40,14 @@ function useSessions(
|
|||||||
(async () => {
|
(async () => {
|
||||||
setRefreshing(true);
|
setRefreshing(true);
|
||||||
const response = await application.getSessions();
|
const response = await application.getSessions();
|
||||||
if ('error' in response) {
|
if ('error' in response || !response.data) {
|
||||||
if (response.error?.message) {
|
if (response.error?.message) {
|
||||||
setErrorMessage(response.error.message);
|
setErrorMessage(response.error.message);
|
||||||
} else {
|
} else {
|
||||||
setErrorMessage('An unknown error occured while loading sessions.');
|
setErrorMessage('An unknown error occured while loading sessions.');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const sessions = response as Session[];
|
const sessions = response.data;
|
||||||
setSessions(sessions);
|
setSessions(sessions);
|
||||||
setErrorMessage('');
|
setErrorMessage('');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,21 +7,25 @@ import {
|
|||||||
PayloadContent,
|
PayloadContent,
|
||||||
} from '@standardnotes/snjs';
|
} from '@standardnotes/snjs';
|
||||||
|
|
||||||
function zippableTxtName(name: string, suffix = ""): string {
|
function sanitizeFileName(name: string) {
|
||||||
const sanitizedName = name
|
return name
|
||||||
.replace(/\//g, '')
|
.replace(/\//g, '')
|
||||||
.replace(/\\+/g, '')
|
.replace(/\\+/g, '')
|
||||||
.replace(/:/g, ' ')
|
.replace(/:/g, ' ')
|
||||||
.replace(/\./g, ' ');
|
.replace(/\|/g, ' ')
|
||||||
const nameEnd = suffix + ".txt";
|
.replace(/\./g, ' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
function zippableTxtName(name: string, suffix = ''): string {
|
||||||
|
const sanitizedName = sanitizeFileName(name);
|
||||||
|
const nameEnd = suffix + '.txt';
|
||||||
const maxFileNameLength = 255;
|
const maxFileNameLength = 255;
|
||||||
return sanitizedName.slice(0, maxFileNameLength - nameEnd.length) + nameEnd;
|
return sanitizedName.slice(0, maxFileNameLength - nameEnd.length) + nameEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ArchiveManager {
|
export class ArchiveManager {
|
||||||
|
private readonly application: WebApplication;
|
||||||
private readonly application: WebApplication
|
private textFile?: string;
|
||||||
private textFile?: string
|
|
||||||
|
|
||||||
constructor(application: WebApplication) {
|
constructor(application: WebApplication) {
|
||||||
this.application = application;
|
this.application = application;
|
||||||
@@ -36,10 +40,9 @@ export class ArchiveManager {
|
|||||||
if (!data) {
|
if (!data) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const blobData = new Blob(
|
const blobData = new Blob([JSON.stringify(data, null, 2)], {
|
||||||
[JSON.stringify(data, null, 2)],
|
type: 'text/json',
|
||||||
{ type: 'text/json' }
|
});
|
||||||
);
|
|
||||||
if (encrypted) {
|
if (encrypted) {
|
||||||
this.downloadData(
|
this.downloadData(
|
||||||
blobData,
|
blobData,
|
||||||
@@ -85,21 +88,18 @@ export class ArchiveManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async downloadZippedDecryptedItems(
|
private async downloadZippedDecryptedItems(data: BackupFile) {
|
||||||
data: BackupFile
|
|
||||||
) {
|
|
||||||
await this.loadZip();
|
await this.loadZip();
|
||||||
const items = data.items;
|
const items = data.items;
|
||||||
this.zip.createWriter(
|
this.zip.createWriter(
|
||||||
new this.zip.BlobWriter('application/zip'),
|
new this.zip.BlobWriter('application/zip'),
|
||||||
async (zipWriter: any) => {
|
async (zipWriter: any) => {
|
||||||
await new Promise((resolve) => {
|
await new Promise((resolve) => {
|
||||||
const blob = new Blob(
|
const blob = new Blob([JSON.stringify(data, null, 2)], {
|
||||||
[JSON.stringify(data, null, 2)],
|
type: 'text/plain',
|
||||||
{ type: 'text/plain' }
|
});
|
||||||
);
|
|
||||||
const fileName = zippableTxtName(
|
const fileName = zippableTxtName(
|
||||||
'Standard Notes Backup and Import File.txt'
|
'Standard Notes Backup and Import File'
|
||||||
);
|
);
|
||||||
zipWriter.add(fileName, new this.zip.BlobReader(blob), resolve);
|
zipWriter.add(fileName, new this.zip.BlobReader(blob), resolve);
|
||||||
});
|
});
|
||||||
@@ -120,7 +120,8 @@ export class ArchiveManager {
|
|||||||
name = '';
|
name = '';
|
||||||
}
|
}
|
||||||
const blob = new Blob([contents], { type: 'text/plain' });
|
const blob = new Blob([contents], { type: 'text/plain' });
|
||||||
const fileName = `Items/${item.content_type}/` +
|
const fileName =
|
||||||
|
`Items/${sanitizeFileName(item.content_type)}/` +
|
||||||
zippableTxtName(name, `-${item.uuid.split('-')[0]}`);
|
zippableTxtName(name, `-${item.uuid.split('-')[0]}`);
|
||||||
zipWriter.add(fileName, new this.zip.BlobReader(blob), () => {
|
zipWriter.add(fileName, new this.zip.BlobReader(blob), () => {
|
||||||
index++;
|
index++;
|
||||||
@@ -138,7 +139,9 @@ export class ArchiveManager {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
nextFile();
|
nextFile();
|
||||||
}, onerror);
|
},
|
||||||
|
onerror
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private hrefForData(data: Blob) {
|
private hrefForData(data: Blob) {
|
||||||
|
|||||||
@@ -168,6 +168,7 @@ export class AppState {
|
|||||||
readonly noAccountWarning: NoAccountWarningState;
|
readonly noAccountWarning: NoAccountWarningState;
|
||||||
readonly sync = new SyncState();
|
readonly sync = new SyncState();
|
||||||
isSessionsModalVisible = false;
|
isSessionsModalVisible = false;
|
||||||
|
mouseUp = Promise.resolve();
|
||||||
|
|
||||||
private appEventObserverRemovers: (() => void)[] = [];
|
private appEventObserverRemovers: (() => void)[] = [];
|
||||||
|
|
||||||
@@ -195,6 +196,7 @@ export class AppState {
|
|||||||
this.notifyEvent(event);
|
this.notifyEvent(event);
|
||||||
};
|
};
|
||||||
this.registerVisibilityObservers();
|
this.registerVisibilityObservers();
|
||||||
|
document.addEventListener('mousedown', this.onMouseDown);
|
||||||
|
|
||||||
if (this.bridge.appVersion.includes('-beta')) {
|
if (this.bridge.appVersion.includes('-beta')) {
|
||||||
this.showBetaWarning = storage.get(StorageKey.ShowBetaWarning) ?? true;
|
this.showBetaWarning = storage.get(StorageKey.ShowBetaWarning) ?? true;
|
||||||
@@ -231,9 +233,16 @@ export class AppState {
|
|||||||
this.rootScopeCleanup2 = undefined;
|
this.rootScopeCleanup2 = undefined;
|
||||||
}
|
}
|
||||||
document.removeEventListener('visibilitychange', this.onVisibilityChange);
|
document.removeEventListener('visibilitychange', this.onVisibilityChange);
|
||||||
|
document.removeEventListener('mousedown', this.onMouseDown);
|
||||||
this.onVisibilityChange = undefined;
|
this.onVisibilityChange = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMouseDown = (): void => {
|
||||||
|
this.mouseUp = new Promise((resolve) => {
|
||||||
|
document.addEventListener('mouseup', () => resolve(), { once: true });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
openSessionsModal() {
|
openSessionsModal() {
|
||||||
this.isSessionsModalVisible = true;
|
this.isSessionsModalVisible = true;
|
||||||
}
|
}
|
||||||
@@ -259,7 +268,7 @@ export class AppState {
|
|||||||
async createEditor(title?: string) {
|
async createEditor(title?: string) {
|
||||||
const activeEditor = this.getActiveEditor();
|
const activeEditor = this.getActiveEditor();
|
||||||
const activeTagUuid = this.selectedTag
|
const activeTagUuid = this.selectedTag
|
||||||
? this.selectedTag.isSmartTag()
|
? this.selectedTag.isSmartTag
|
||||||
? undefined
|
? undefined
|
||||||
: this.selectedTag.uuid
|
: this.selectedTag.uuid
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|||||||
@@ -63,8 +63,7 @@ export class WebApplication extends SNApplication {
|
|||||||
WebCrypto,
|
WebCrypto,
|
||||||
new AlertService(),
|
new AlertService(),
|
||||||
identifier,
|
identifier,
|
||||||
undefined,
|
[],
|
||||||
undefined,
|
|
||||||
defaultSyncServerHost
|
defaultSyncServerHost
|
||||||
);
|
);
|
||||||
this.$compile = $compile;
|
this.$compile = $compile;
|
||||||
|
|||||||
@@ -460,7 +460,7 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
|
|||||||
await this.editor.insertTemplatedNote();
|
await this.editor.insertTemplatedNote();
|
||||||
}
|
}
|
||||||
const selectedTag = this.appState.selectedTag;
|
const selectedTag = this.appState.selectedTag;
|
||||||
if (!selectedTag?.isSmartTag() && !selectedTag?.hasRelationshipWithItem(note)) {
|
if (!selectedTag?.isSmartTag && !selectedTag?.hasRelationshipWithItem(note)) {
|
||||||
await this.application.changeItem(
|
await this.application.changeItem(
|
||||||
selectedTag!.uuid,
|
selectedTag!.uuid,
|
||||||
(mutator) => {
|
(mutator) => {
|
||||||
@@ -1052,7 +1052,7 @@ class EditorViewCtrl extends PureViewCtrl<unknown, EditorState> {
|
|||||||
if (savedUuid === this.note.uuid) {
|
if (savedUuid === this.note.uuid) {
|
||||||
const selectedTag = this.appState.selectedTag;
|
const selectedTag = this.appState.selectedTag;
|
||||||
if (
|
if (
|
||||||
!selectedTag?.isSmartTag() &&
|
!selectedTag?.isSmartTag &&
|
||||||
!selectedTag?.hasRelationshipWithItem(this.note)
|
!selectedTag?.hasRelationshipWithItem(this.note)
|
||||||
) {
|
) {
|
||||||
this.application.changeAndSaveItem(
|
this.application.changeAndSaveItem(
|
||||||
|
|||||||
@@ -1,69 +0,0 @@
|
|||||||
import { SNNote } from '@standardnotes/snjs';
|
|
||||||
|
|
||||||
export function notePassesFilter(
|
|
||||||
note: SNNote,
|
|
||||||
showArchived: boolean,
|
|
||||||
hidePinned: boolean,
|
|
||||||
filterText: string
|
|
||||||
): boolean {
|
|
||||||
const canShowArchived = showArchived;
|
|
||||||
const canShowPinned = !hidePinned;
|
|
||||||
if ((note.archived && !canShowArchived) || (note.pinned && !canShowPinned)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (note.protected) {
|
|
||||||
const match = noteMatchesQuery(note, filterText);
|
|
||||||
/** Only match title to prevent leaking protected note text */
|
|
||||||
return match === Match.Title || match === Match.TitleAndText;
|
|
||||||
} else {
|
|
||||||
return noteMatchesQuery(note, filterText) !== Match.None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Match {
|
|
||||||
None = 0,
|
|
||||||
Title = 1,
|
|
||||||
Text = 2,
|
|
||||||
TitleAndText = Title + Text,
|
|
||||||
Uuid = 5,
|
|
||||||
}
|
|
||||||
|
|
||||||
function noteMatchesQuery(note: SNNote, query: string): Match {
|
|
||||||
if (query.length === 0) {
|
|
||||||
return Match.TitleAndText;
|
|
||||||
}
|
|
||||||
const title = note.safeTitle().toLowerCase();
|
|
||||||
const text = note.safeText().toLowerCase();
|
|
||||||
const lowercaseText = query.toLowerCase();
|
|
||||||
const words = lowercaseText.split(' ');
|
|
||||||
const quotedText = stringBetweenQuotes(lowercaseText);
|
|
||||||
if (quotedText) {
|
|
||||||
return (
|
|
||||||
(title.includes(quotedText) ? Match.Title : Match.None) +
|
|
||||||
(text.includes(quotedText) ? Match.Text : Match.None)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (stringIsUuid(lowercaseText)) {
|
|
||||||
return note.uuid === lowercaseText ? Match.Uuid : Match.None;
|
|
||||||
}
|
|
||||||
const matchesTitle = words.every((word) => {
|
|
||||||
return title.indexOf(word) >= 0;
|
|
||||||
});
|
|
||||||
const matchesBody = words.every((word) => {
|
|
||||||
return text.indexOf(word) >= 0;
|
|
||||||
});
|
|
||||||
return (matchesTitle ? Match.Title : 0) + (matchesBody ? Match.Text : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
function stringBetweenQuotes(text: string) {
|
|
||||||
const matches = text.match(/"(.*?)"/);
|
|
||||||
return matches ? matches[1] : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function stringIsUuid(text: string) {
|
|
||||||
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/
|
|
||||||
);
|
|
||||||
// eslint-disable-next-line no-unneeded-ternary
|
|
||||||
return matches ? true : false;
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#notes-column.sn-component.section.notes(aria-label='Notes')
|
#notes-column.sn-component.section.notes(aria-label='Notes')
|
||||||
.content
|
.content
|
||||||
#notes-title-bar.section-title-bar
|
#notes-title-bar.section-title-bar
|
||||||
.padded
|
.p-4.pt-0
|
||||||
.section-title-bar-header
|
.section-title-bar-header
|
||||||
.sk-h2.font-semibold.title {{self.state.panelTitle}}
|
.sk-h2.font-semibold.title {{self.state.panelTitle}}
|
||||||
.sk-button.contrast.wide(
|
.sk-button.contrast.wide(
|
||||||
@@ -12,18 +12,34 @@
|
|||||||
i.icon.ion-plus.add-button
|
i.icon.ion-plus.add-button
|
||||||
.filter-section(role='search')
|
.filter-section(role='search')
|
||||||
input#search-bar.filter-bar(
|
input#search-bar.filter-bar(
|
||||||
ng-blur='self.onFilterEnter()',
|
ng-ref='self.searchBarInput'
|
||||||
|
ng-focus='self.onSearchInputFocus()'
|
||||||
|
ng-blur='self.onSearchInputBlur()',
|
||||||
ng-change='self.filterTextChanged()',
|
ng-change='self.filterTextChanged()',
|
||||||
ng-keyup='$event.keyCode == 13 && self.onFilterEnter();',
|
ng-keyup='$event.keyCode == 13 && self.onFilterEnter();',
|
||||||
ng-model='self.state.noteFilter.text',
|
ng-model='self.state.noteFilter.text',
|
||||||
placeholder='Search',
|
placeholder='Search',
|
||||||
select-on-focus='true',
|
select-on-focus='true',
|
||||||
title='Searches notes in the currently selected tag'
|
title='Searches notes in the currently selected tag'
|
||||||
)
|
)
|
||||||
#search-clear-button(
|
#search-clear-button(
|
||||||
ng-click='self.clearFilterText();',
|
ng-click='self.clearFilterText();',
|
||||||
ng-show='self.state.noteFilter.text'
|
ng-show='self.state.noteFilter.text'
|
||||||
) ✕
|
) ✕
|
||||||
|
label.sk-panel-row.justify-left.mt-2.animate-slide-in-top(
|
||||||
|
ng-if='self.state.searchIsFocused || self.state.searchOptionsAreFocused || self.state.authorizingSearchOptions'
|
||||||
|
style="padding-bottom: 0"
|
||||||
|
)
|
||||||
|
.sk-horizontal-group.tight
|
||||||
|
input(
|
||||||
|
ng-ref='self.searchOptionsInput'
|
||||||
|
ng-focus="self.onSearchOptionsFocus()"
|
||||||
|
ng-blur="self.onSearchOptionsBlur()"
|
||||||
|
type="checkbox"
|
||||||
|
ng-checked="self.state.noteFilter.includeProtectedNoteText"
|
||||||
|
ng-on-click="self.onIncludeProtectedNoteTextChange($event)"
|
||||||
|
)
|
||||||
|
p.sk-p.capitalize Include protected contents
|
||||||
no-account-warning(
|
no-account-warning(
|
||||||
application='self.application'
|
application='self.application'
|
||||||
app-state='self.appState'
|
app-state='self.appState'
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import {
|
|||||||
PrefKey,
|
PrefKey,
|
||||||
findInArray,
|
findInArray,
|
||||||
CollectionSort,
|
CollectionSort,
|
||||||
|
UuidString,
|
||||||
|
NotesDisplayCriteria
|
||||||
} from '@standardnotes/snjs';
|
} from '@standardnotes/snjs';
|
||||||
import { PureViewCtrl } from '@Views/abstract/pure_view_ctrl';
|
import { PureViewCtrl } from '@Views/abstract/pure_view_ctrl';
|
||||||
import { AppStateEvent } from '@/ui_models/app_state';
|
import { AppStateEvent } from '@/ui_models/app_state';
|
||||||
@@ -16,10 +18,6 @@ import { KeyboardModifier, KeyboardKey } from '@/services/keyboardManager';
|
|||||||
import {
|
import {
|
||||||
PANEL_NAME_NOTES
|
PANEL_NAME_NOTES
|
||||||
} from '@/views/constants';
|
} from '@/views/constants';
|
||||||
import {
|
|
||||||
notePassesFilter
|
|
||||||
} from './note_utils';
|
|
||||||
import { UuidString } from '@standardnotes/snjs';
|
|
||||||
|
|
||||||
type NotesState = {
|
type NotesState = {
|
||||||
panelTitle: string
|
panelTitle: string
|
||||||
@@ -33,7 +31,13 @@ type NotesState = {
|
|||||||
hideNotePreview?: boolean
|
hideNotePreview?: boolean
|
||||||
hideDate?: boolean
|
hideDate?: boolean
|
||||||
hideTags: boolean
|
hideTags: boolean
|
||||||
noteFilter: { text: string }
|
noteFilter: {
|
||||||
|
text: string;
|
||||||
|
includeProtectedNoteText: boolean;
|
||||||
|
}
|
||||||
|
searchIsFocused: boolean;
|
||||||
|
searchOptionsAreFocused: boolean;
|
||||||
|
authorizingSearchOptions: boolean;
|
||||||
mutable: { showMenu: boolean }
|
mutable: { showMenu: boolean }
|
||||||
completedFullSync: boolean
|
completedFullSync: boolean
|
||||||
[PrefKey.TagsPanelWidth]?: number
|
[PrefKey.TagsPanelWidth]?: number
|
||||||
@@ -72,6 +76,8 @@ class NotesViewCtrl extends PureViewCtrl<unknown, NotesState> {
|
|||||||
private searchKeyObserver: any
|
private searchKeyObserver: any
|
||||||
private noteFlags: Partial<Record<UuidString, NoteFlag[]>> = {}
|
private noteFlags: Partial<Record<UuidString, NoteFlag[]>> = {}
|
||||||
private removeObservers: Array<() => void> = [];
|
private removeObservers: Array<() => void> = [];
|
||||||
|
private searchBarInput?: JQLite;
|
||||||
|
private searchOptionsInput?: JQLite;
|
||||||
|
|
||||||
/* @ngInject */
|
/* @ngInject */
|
||||||
constructor($timeout: ng.ITimeoutService,) {
|
constructor($timeout: ng.ITimeoutService,) {
|
||||||
@@ -127,10 +133,16 @@ class NotesViewCtrl extends PureViewCtrl<unknown, NotesState> {
|
|||||||
renderedNotes: [],
|
renderedNotes: [],
|
||||||
renderedNotesTags: [],
|
renderedNotesTags: [],
|
||||||
mutable: { showMenu: false },
|
mutable: { showMenu: false },
|
||||||
noteFilter: { text: '' },
|
noteFilter: {
|
||||||
|
text: '',
|
||||||
|
includeProtectedNoteText: false
|
||||||
|
},
|
||||||
panelTitle: '',
|
panelTitle: '',
|
||||||
completedFullSync: false,
|
completedFullSync: false,
|
||||||
hideTags: true,
|
hideTags: true,
|
||||||
|
searchIsFocused: false,
|
||||||
|
searchOptionsAreFocused: false,
|
||||||
|
authorizingSearchOptions: false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,7 +223,7 @@ class NotesViewCtrl extends PureViewCtrl<unknown, NotesState> {
|
|||||||
*/
|
*/
|
||||||
private async createPlaceholderNote() {
|
private async createPlaceholderNote() {
|
||||||
const selectedTag = this.selectedTag!;
|
const selectedTag = this.selectedTag!;
|
||||||
if (selectedTag.isSmartTag() && !selectedTag.isAllTag) {
|
if (selectedTag.isSmartTag && !selectedTag.isAllTag) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return this.createNewNote();
|
return this.createNewNote();
|
||||||
@@ -330,20 +342,20 @@ class NotesViewCtrl extends PureViewCtrl<unknown, NotesState> {
|
|||||||
* an index is roughly O(n^2).
|
* an index is roughly O(n^2).
|
||||||
*/
|
*/
|
||||||
private reloadNotesDisplayOptions() {
|
private reloadNotesDisplayOptions() {
|
||||||
const tag = this.appState.selectedTag!;
|
const tag = this.appState.selectedTag;
|
||||||
this.application!.setNotesDisplayOptions(
|
const searchText = this.getState().noteFilter.text.toLowerCase();
|
||||||
tag,
|
const criteria = NotesDisplayCriteria.Create({
|
||||||
this.state.sortBy! as CollectionSort,
|
sortProperty: this.state.sortBy! as CollectionSort,
|
||||||
this.state.sortReverse! ? 'asc' : 'dsc',
|
sortDirection: this.state.sortReverse! ? 'asc' : 'dsc',
|
||||||
(note: SNNote) => {
|
tags: tag ? [tag] : [],
|
||||||
return notePassesFilter(
|
includeArchived: this.getState().showArchived!,
|
||||||
note,
|
includePinned: !this.getState().hidePinned!,
|
||||||
this.getState().showArchived! || tag?.isArchiveTag || tag?.isTrashTag,
|
searchQuery: {
|
||||||
this.getState().hidePinned!,
|
query: searchText ?? '',
|
||||||
this.getState().noteFilter.text.toLowerCase()
|
includeProtectedNoteText: this.state.noteFilter.includeProtectedNoteText
|
||||||
);
|
|
||||||
}
|
}
|
||||||
);
|
});
|
||||||
|
this.application!.setNotesDisplayCriteria(criteria);
|
||||||
}
|
}
|
||||||
|
|
||||||
private get selectedTag() {
|
private get selectedTag() {
|
||||||
@@ -376,7 +388,7 @@ class NotesViewCtrl extends PureViewCtrl<unknown, NotesState> {
|
|||||||
const selectedTag = this.appState.selectedTag;
|
const selectedTag = this.appState.selectedTag;
|
||||||
if (!selectedTag) {
|
if (!selectedTag) {
|
||||||
return [];
|
return [];
|
||||||
} else if (selectedTag?.isSmartTag()) {
|
} else if (selectedTag?.isSmartTag) {
|
||||||
return notes.map((note) =>
|
return notes.map((note) =>
|
||||||
this.appState
|
this.appState
|
||||||
.getNoteTags(note)
|
.getNoteTags(note)
|
||||||
@@ -691,6 +703,64 @@ class NotesViewCtrl extends PureViewCtrl<unknown, NotesState> {
|
|||||||
await this.reloadNotes();
|
await this.reloadNotes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async onIncludeProtectedNoteTextChange(event: Event) {
|
||||||
|
this.searchBarInput?.[0].focus();
|
||||||
|
if (this.state.noteFilter.includeProtectedNoteText) {
|
||||||
|
this.state.noteFilter.includeProtectedNoteText = false;
|
||||||
|
this.reloadNotesDisplayOptions();
|
||||||
|
await this.reloadNotes();
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
authorizingSearchOptions: true,
|
||||||
|
});
|
||||||
|
event.preventDefault();
|
||||||
|
if (await this.application.authorizeSearchingProtectedNotesText()) {
|
||||||
|
this.state.noteFilter.includeProtectedNoteText = true;
|
||||||
|
this.reloadNotesDisplayOptions();
|
||||||
|
await this.reloadNotes();
|
||||||
|
}
|
||||||
|
await this.$timeout(50);
|
||||||
|
await this.setState({
|
||||||
|
authorizingSearchOptions: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onSearchInputFocus() {
|
||||||
|
this.setState({
|
||||||
|
searchIsFocused: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async onSearchInputBlur() {
|
||||||
|
await this.appState.mouseUp;
|
||||||
|
/**
|
||||||
|
* Wait a non-zero amount of time so the newly-focused element can have
|
||||||
|
* enough time to set its state
|
||||||
|
*/
|
||||||
|
await this.$timeout(50);
|
||||||
|
await this.setState({
|
||||||
|
searchIsFocused:
|
||||||
|
this.searchBarInput?.[0] === document.activeElement,
|
||||||
|
});
|
||||||
|
this.onFilterEnter();
|
||||||
|
}
|
||||||
|
|
||||||
|
onSearchOptionsFocus() {
|
||||||
|
this.setState({
|
||||||
|
searchOptionsAreFocused: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async onSearchOptionsBlur() {
|
||||||
|
await this.appState.mouseUp;
|
||||||
|
await this.$timeout(50);
|
||||||
|
this.setState({
|
||||||
|
searchOptionsAreFocused:
|
||||||
|
this.searchOptionsInput?.[0] === document.activeElement,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
onFilterEnter() {
|
onFilterEnter() {
|
||||||
/**
|
/**
|
||||||
* For Desktop, performing a search right away causes
|
* For Desktop, performing a search right away causes
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ class TagsViewCtrl extends PureViewCtrl<unknown, TagState> {
|
|||||||
if (tag === this.state.templateTag) {
|
if (tag === this.state.templateTag) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (tag.isSmartTag()) {
|
if (tag.isSmartTag) {
|
||||||
/** Other smart tags do not contain counts */
|
/** Other smart tags do not contain counts */
|
||||||
if (tag.isAllTag) {
|
if (tag.isAllTag) {
|
||||||
const notes = this.application.notesMatchingSmartTag(tag as SNSmartTag)
|
const notes = this.application.notesMatchingSmartTag(tag as SNSmartTag)
|
||||||
@@ -246,12 +246,8 @@ class TagsViewCtrl extends PureViewCtrl<unknown, TagState> {
|
|||||||
this.selectTag(tag as SNTag);
|
this.selectTag(tag as SNTag);
|
||||||
}
|
}
|
||||||
} else if (data.item!.content_type === ContentType.SmartTag) {
|
} else if (data.item!.content_type === ContentType.SmartTag) {
|
||||||
this.application.createTemplateItem(
|
const matchingTag = this.getState().smartTags.find(t => t.uuid === data.item!.uuid);
|
||||||
ContentType.SmartTag,
|
this.selectTag(matchingTag as SNSmartTag);
|
||||||
data.item!.content as PayloadContent
|
|
||||||
).then(smartTag => {
|
|
||||||
this.selectTag(smartTag as SNSmartTag);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} else if (action === ComponentAction.ClearSelection) {
|
} else if (action === ComponentAction.ClearSelection) {
|
||||||
this.selectTag(this.getState().smartTags[0]);
|
this.selectTag(this.getState().smartTags[0]);
|
||||||
|
|||||||
@@ -206,10 +206,6 @@ $footer-height: 32px;
|
|||||||
|
|
||||||
.section-title-bar {
|
.section-title-bar {
|
||||||
|
|
||||||
.padded {
|
|
||||||
padding: 0 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.add-button {
|
.add-button {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,6 @@
|
|||||||
|
|
||||||
#notes-menu-bar {
|
#notes-menu-bar {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-top: 14px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#notes-options-menu {
|
#notes-options-menu {
|
||||||
|
|||||||
@@ -97,13 +97,37 @@ $screen-md-max: ($screen-lg-min - 1) !default;
|
|||||||
justify-self: flex-start;
|
justify-self: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.animate-slide-in-top {
|
||||||
|
animation: slide-in-top .1s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slide-in-top {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-40%);
|
||||||
|
}
|
||||||
|
75% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateY(0%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.m-0 {
|
.m-0 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mb-0 {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.mt-1 {
|
.mt-1 {
|
||||||
margin-top: .25rem;
|
margin-top: .25rem;
|
||||||
}
|
}
|
||||||
|
.mt-2 {
|
||||||
|
margin-top: .5rem;
|
||||||
|
}
|
||||||
.mt-3 {
|
.mt-3 {
|
||||||
margin-top: .75rem;
|
margin-top: .75rem;
|
||||||
}
|
}
|
||||||
@@ -114,10 +138,17 @@ $screen-md-max: ($screen-lg-min - 1) !default;
|
|||||||
.p-0 {
|
.p-0 {
|
||||||
padding: 0rem;
|
padding: 0rem;
|
||||||
}
|
}
|
||||||
|
.p-4 {
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
.p-5 {
|
.p-5 {
|
||||||
padding: 1.25rem;
|
padding: 1.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pt-0 {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.px-3 {
|
.px-3 {
|
||||||
padding-left: .75rem;
|
padding-left: .75rem;
|
||||||
padding-right: .75rem;
|
padding-right: .75rem;
|
||||||
|
|||||||
@@ -149,7 +149,7 @@
|
|||||||
.sk-panel-row
|
.sk-panel-row
|
||||||
.sk-panel-column
|
.sk-panel-column
|
||||||
.sk-h1.sk-bold.wrap {{self.state.user.email}}
|
.sk-h1.sk-bold.wrap {{self.state.user.email}}
|
||||||
.sk-subtitle.subtle.normal {{self.state.server}}
|
.sk-subtitle.neutral {{self.state.server}}
|
||||||
.sk-panel-row
|
.sk-panel-row
|
||||||
a.sk-a.info.sk-panel-row.condensed(
|
a.sk-a.info.sk-panel-row.condensed(
|
||||||
ng-click="self.openPasswordWizard()"
|
ng-click="self.openPasswordWizard()"
|
||||||
@@ -303,11 +303,11 @@
|
|||||||
.sk-panel-footer
|
.sk-panel-footer
|
||||||
.sk-panel-row
|
.sk-panel-row
|
||||||
.sk-p.left.neutral
|
.sk-p.left.neutral
|
||||||
span.faded {{self.state.appVersion}}
|
span {{self.state.appVersion}}
|
||||||
span(ng-if="self.state.showBetaWarning")
|
span(ng-if="self.state.showBetaWarning")
|
||||||
span.faded (
|
span (
|
||||||
a.sk-a(ng-click="self.appState.disableBetaWarning()") Hide beta warning
|
a.sk-a(ng-click="self.appState.disableBetaWarning()") Hide beta warning
|
||||||
span.faded )
|
span )
|
||||||
a.sk-a.right(
|
a.sk-a.right(
|
||||||
ng-click='self.hidePasswordForm()',
|
ng-click='self.hidePasswordForm()',
|
||||||
ng-if='self.state.formData.showLogin || self.state.formData.showRegister'
|
ng-if='self.state.formData.showLogin || self.state.formData.showRegister'
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "standard-notes-web",
|
"name": "standard-notes-web",
|
||||||
"version": "3.6.1",
|
"version": "3.6.2",
|
||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
"pug-loader": "^2.4.0",
|
"pug-loader": "^2.4.0",
|
||||||
"sass-loader": "^8.0.2",
|
"sass-loader": "^8.0.2",
|
||||||
"serve-static": "^1.14.1",
|
"serve-static": "^1.14.1",
|
||||||
"sn-stylekit": "^2.2.0",
|
"sn-stylekit": "^2.2.1",
|
||||||
"ts-loader": "^8.0.17",
|
"ts-loader": "^8.0.17",
|
||||||
"typescript": "^4.1.5",
|
"typescript": "^4.1.5",
|
||||||
"typescript-eslint": "0.0.1-alpha.0",
|
"typescript-eslint": "0.0.1-alpha.0",
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
"@reach/alert-dialog": "^0.13.0",
|
"@reach/alert-dialog": "^0.13.0",
|
||||||
"@reach/dialog": "^0.13.0",
|
"@reach/dialog": "^0.13.0",
|
||||||
"@standardnotes/sncrypto-web": "^1.2.10",
|
"@standardnotes/sncrypto-web": "^1.2.10",
|
||||||
"@standardnotes/snjs": "^2.0.61",
|
"@standardnotes/snjs": "^2.0.67",
|
||||||
"mobx": "^6.1.6",
|
"mobx": "^6.1.6",
|
||||||
"preact": "^10.5.12"
|
"preact": "^10.5.12"
|
||||||
}
|
}
|
||||||
|
|||||||
22
yarn.lock
22
yarn.lock
@@ -1832,6 +1832,11 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
tslib "^2.0.0"
|
tslib "^2.0.0"
|
||||||
|
|
||||||
|
"@standardnotes/auth@^2.0.0":
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@standardnotes/auth/-/auth-2.0.0.tgz#93f633fd40855f87843f911109e92b29dcbc5a04"
|
||||||
|
integrity sha512-B2NznCm3pzwBvBU/YQfuDrtlEbLO3hNH3QrqSwK2dFwUGAnl5UQPC9FKFWYgly05rWevwMY3IUmiZRzUEVlKsQ==
|
||||||
|
|
||||||
"@standardnotes/sncrypto-common@^1.2.7", "@standardnotes/sncrypto-common@^1.2.9":
|
"@standardnotes/sncrypto-common@^1.2.7", "@standardnotes/sncrypto-common@^1.2.9":
|
||||||
version "1.2.9"
|
version "1.2.9"
|
||||||
resolved "https://registry.yarnpkg.com/@standardnotes/sncrypto-common/-/sncrypto-common-1.2.9.tgz#5212a959e4ec563584e42480bfd39ef129c3cbdf"
|
resolved "https://registry.yarnpkg.com/@standardnotes/sncrypto-common/-/sncrypto-common-1.2.9.tgz#5212a959e4ec563584e42480bfd39ef129c3cbdf"
|
||||||
@@ -1845,11 +1850,12 @@
|
|||||||
"@standardnotes/sncrypto-common" "^1.2.7"
|
"@standardnotes/sncrypto-common" "^1.2.7"
|
||||||
libsodium-wrappers "^0.7.8"
|
libsodium-wrappers "^0.7.8"
|
||||||
|
|
||||||
"@standardnotes/snjs@^2.0.61":
|
"@standardnotes/snjs@^2.0.67":
|
||||||
version "2.0.61"
|
version "2.0.67"
|
||||||
resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.61.tgz#82608ef48830a80afbc9468ed2d308e59e4e9a08"
|
resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.0.67.tgz#87e29f40bb5efaa36f30ddc5905164f7dce194d9"
|
||||||
integrity sha512-MVnzT7cX7oIak9g/xlOJKfWCfBygw8kXtuVHSofdxPhYIPIr1MwK4xkkqho/ZShVfPQEESyj3RaEsOIzKuuL4w==
|
integrity sha512-XCDxlFQCh0zmV3Hc9mjU7ritZ/2Ma5JPoCbDy4CIAlkKdmVL4tu/4jCfRFILM0zpKF/kLsCTbLGdG7TgU/ReKg==
|
||||||
dependencies:
|
dependencies:
|
||||||
|
"@standardnotes/auth" "^2.0.0"
|
||||||
"@standardnotes/sncrypto-common" "^1.2.9"
|
"@standardnotes/sncrypto-common" "^1.2.9"
|
||||||
|
|
||||||
"@svgr/babel-plugin-add-jsx-attribute@^5.4.0":
|
"@svgr/babel-plugin-add-jsx-attribute@^5.4.0":
|
||||||
@@ -7802,10 +7808,10 @@ slice-ansi@^4.0.0:
|
|||||||
astral-regex "^2.0.0"
|
astral-regex "^2.0.0"
|
||||||
is-fullwidth-code-point "^3.0.0"
|
is-fullwidth-code-point "^3.0.0"
|
||||||
|
|
||||||
sn-stylekit@^2.2.0:
|
sn-stylekit@^2.2.1:
|
||||||
version "2.2.0"
|
version "2.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/sn-stylekit/-/sn-stylekit-2.2.0.tgz#0c143cb25addf4a1edf02d41ea1d6821017f8652"
|
resolved "https://registry.yarnpkg.com/sn-stylekit/-/sn-stylekit-2.2.1.tgz#4a81a05b2b2d67a11af9d06f3964ac1ece3aa84a"
|
||||||
integrity sha512-xUx+EujROZBaoMrvM0y7CjHPD6WJfwu1tY3oeFG/sV3M9YvCcGkX76Jz9iPt0daeYM4h0oAWphniH7pLi3aFwA==
|
integrity sha512-mrvUbf2HbWOfxbNglo7RXa5JBe9UV9rurupeGoX/Kh4/lVlB2n/56ZT103xk/4tp0/mVCpxjD7Dt1stKFxsvFA==
|
||||||
|
|
||||||
snapdragon-node@^2.0.1:
|
snapdragon-node@^2.0.1:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
|
|||||||
Reference in New Issue
Block a user