feat: select multiple notes in list
This commit is contained in:
@@ -19,6 +19,7 @@ import { ActionsMenuState } from './actions_menu_state';
|
||||
import { NoAccountWarningState } from './no_account_warning_state';
|
||||
import { SyncState } from './sync_state';
|
||||
import { SearchOptionsState } from './search_options_state';
|
||||
import { NotesState } from './notes_state';
|
||||
|
||||
export enum AppStateEvent {
|
||||
TagChanged,
|
||||
@@ -62,7 +63,8 @@ export class AppState {
|
||||
readonly actionsMenu = new ActionsMenuState();
|
||||
readonly noAccountWarning: NoAccountWarningState;
|
||||
readonly sync = new SyncState();
|
||||
readonly searchOptions;
|
||||
readonly searchOptions: SearchOptionsState;
|
||||
readonly notes: NotesState;
|
||||
isSessionsModalVisible = false;
|
||||
|
||||
private appEventObserverRemovers: (() => void)[] = [];
|
||||
@@ -77,6 +79,12 @@ export class AppState {
|
||||
this.$timeout = $timeout;
|
||||
this.$rootScope = $rootScope;
|
||||
this.application = application;
|
||||
this.notes = new NotesState(
|
||||
this.application,
|
||||
async () => {
|
||||
await this.notifyEvent(AppStateEvent.ActiveEditorChanged);
|
||||
}
|
||||
);
|
||||
this.noAccountWarning = new NoAccountWarningState(
|
||||
application,
|
||||
this.appEventObserverRemovers
|
||||
@@ -175,28 +183,6 @@ export class AppState {
|
||||
}
|
||||
}
|
||||
|
||||
async openEditor(noteUuid: string): Promise<void> {
|
||||
if (this.getActiveEditor()?.note?.uuid === noteUuid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const note = this.application.findItem(noteUuid) as SNNote;
|
||||
if (!note) {
|
||||
console.warn('Tried accessing a non-existant note of UUID ' + noteUuid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (await this.application.authorizeNoteAccess(note)) {
|
||||
const activeEditor = this.getActiveEditor();
|
||||
if (!activeEditor) {
|
||||
this.application.editorGroup.createEditor(noteUuid);
|
||||
} else {
|
||||
activeEditor.setNote(note);
|
||||
}
|
||||
await this.notifyEvent(AppStateEvent.ActiveEditorChanged);
|
||||
}
|
||||
}
|
||||
|
||||
getActiveEditor() {
|
||||
return this.application.editorGroup.editors[0];
|
||||
}
|
||||
|
||||
66
app/assets/javascripts/ui_models/app_state/notes_state.ts
Normal file
66
app/assets/javascripts/ui_models/app_state/notes_state.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import { KeyboardModifier } from "@/services/ioService";
|
||||
import { UuidString, SNNote } from "@standardnotes/snjs";
|
||||
import { makeObservable, observable, action } from "mobx";
|
||||
import { WebApplication } from "../application";
|
||||
import { Editor } from "../editor";
|
||||
|
||||
export class NotesState {
|
||||
selectedNotes: Record<UuidString, SNNote> = {};
|
||||
|
||||
constructor(
|
||||
private application: WebApplication,
|
||||
private onActiveEditorChanged: () => Promise<void>
|
||||
) {
|
||||
makeObservable(this, {
|
||||
selectedNotes: observable,
|
||||
selectNote: action,
|
||||
});
|
||||
}
|
||||
|
||||
get activeEditor(): Editor | undefined {
|
||||
return this.application.editorGroup.editors[0];
|
||||
}
|
||||
|
||||
async selectNote(note: SNNote): Promise<void> {
|
||||
if (
|
||||
this.io.activeModifiers.has(KeyboardModifier.Meta) ||
|
||||
this.io.activeModifiers.has(KeyboardModifier.Ctrl)
|
||||
) {
|
||||
this.selectedNotes[note.uuid] = note;
|
||||
} else {
|
||||
this.selectedNotes = {
|
||||
[note.uuid]: note,
|
||||
};
|
||||
}
|
||||
await this.openEditor(note.uuid);
|
||||
}
|
||||
|
||||
async openEditor(noteUuid: string): Promise<void> {
|
||||
if (this.activeEditor?.note?.uuid === noteUuid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const note = this.application.findItem(noteUuid) as SNNote | undefined;
|
||||
if (!note) {
|
||||
console.warn('Tried accessing a non-existant note of UUID ' + noteUuid);
|
||||
return;
|
||||
}
|
||||
|
||||
if (await this.application.authorizeNoteAccess(note)) {
|
||||
if (!this.activeEditor) {
|
||||
this.application.editorGroup.createEditor(noteUuid);
|
||||
} else {
|
||||
this.activeEditor.setNote(note);
|
||||
}
|
||||
await this.onActiveEditorChanged();
|
||||
|
||||
if (note.waitingForKey) {
|
||||
this.application.presentKeyRecoveryWizard();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private get io() {
|
||||
return this.application.io;
|
||||
}
|
||||
}
|
||||
@@ -9,23 +9,21 @@ import {
|
||||
SNComponent,
|
||||
PermissionDialog,
|
||||
DeinitSource,
|
||||
Platform,
|
||||
} from '@standardnotes/snjs';
|
||||
import angular from 'angular';
|
||||
import { getPlatform } from '@/utils';
|
||||
import { AlertService } from '@/services/alertService';
|
||||
import { WebDeviceInterface } from '@/web_device_interface';
|
||||
import {
|
||||
DesktopManager,
|
||||
AutolockService,
|
||||
ArchiveManager,
|
||||
NativeExtManager,
|
||||
StatusManager,
|
||||
ThemeManager,
|
||||
KeyboardManager
|
||||
} from '@/services';
|
||||
import { AppState } from '@/ui_models/app_state';
|
||||
import { Bridge } from '@/services/bridge';
|
||||
import { WebCrypto } from '@/crypto';
|
||||
import { AlertService } from '@/services/alertService';
|
||||
import { AutolockService } from '@/services/autolock_service';
|
||||
import { ArchiveManager } from '@/services/archiveManager';
|
||||
import { DesktopManager } from '@/services/desktopManager';
|
||||
import { IOService } from '@/services/ioService';
|
||||
import { NativeExtManager } from '@/services/nativeExtManager';
|
||||
import { StatusManager } from '@/services/statusManager';
|
||||
import { ThemeManager } from '@/services/themeManager';
|
||||
|
||||
type WebServices = {
|
||||
appState: AppState;
|
||||
@@ -35,7 +33,7 @@ type WebServices = {
|
||||
nativeExtService: NativeExtManager;
|
||||
statusManager: StatusManager;
|
||||
themeService: ThemeManager;
|
||||
keyboardService: KeyboardManager;
|
||||
io: IOService;
|
||||
}
|
||||
|
||||
export class WebApplication extends SNApplication {
|
||||
@@ -49,6 +47,7 @@ export class WebApplication extends SNApplication {
|
||||
/* @ngInject */
|
||||
constructor(
|
||||
deviceInterface: WebDeviceInterface,
|
||||
platform: Platform,
|
||||
identifier: string,
|
||||
private $compile: angular.ICompileService,
|
||||
scope: angular.IScope,
|
||||
@@ -57,7 +56,7 @@ export class WebApplication extends SNApplication {
|
||||
) {
|
||||
super(
|
||||
bridge.environment,
|
||||
getPlatform(),
|
||||
platform,
|
||||
deviceInterface,
|
||||
WebCrypto,
|
||||
new AlertService(),
|
||||
@@ -139,8 +138,8 @@ export class WebApplication extends SNApplication {
|
||||
return this.webServices.themeService;
|
||||
}
|
||||
|
||||
public getKeyboardService() {
|
||||
return this.webServices.keyboardService;
|
||||
public get io() {
|
||||
return this.webServices.io;
|
||||
}
|
||||
|
||||
async checkForSecurityUpdate() {
|
||||
|
||||
@@ -1,24 +1,26 @@
|
||||
import { WebDeviceInterface } from '@/web_device_interface';
|
||||
import { WebApplication } from './application';
|
||||
import { ApplicationDescriptor, SNApplicationGroup, DeviceInterface } from '@standardnotes/snjs';
|
||||
import {
|
||||
ArchiveManager,
|
||||
DesktopManager,
|
||||
KeyboardManager,
|
||||
AutolockService,
|
||||
NativeExtManager,
|
||||
StatusManager,
|
||||
ThemeManager
|
||||
} from '@/services';
|
||||
ApplicationDescriptor,
|
||||
SNApplicationGroup,
|
||||
DeviceInterface,
|
||||
Platform,
|
||||
} from '@standardnotes/snjs';
|
||||
import { AppState } from '@/ui_models/app_state';
|
||||
import { Bridge } from '@/services/bridge';
|
||||
import { isDesktopApplication } from '@/utils';
|
||||
import { getPlatform, isDesktopApplication } from '@/utils';
|
||||
import { ArchiveManager } from '@/services/archiveManager';
|
||||
import { DesktopManager } from '@/services/desktopManager';
|
||||
import { IOService } from '@/services/ioService';
|
||||
import { AutolockService } from '@/services/autolock_service';
|
||||
import { StatusManager } from '@/services/statusManager';
|
||||
import { NativeExtManager } from '@/services/nativeExtManager';
|
||||
import { ThemeManager } from '@/services/themeManager';
|
||||
|
||||
export class ApplicationGroup extends SNApplicationGroup {
|
||||
|
||||
$compile: ng.ICompileService
|
||||
$rootScope: ng.IRootScopeService
|
||||
$timeout: ng.ITimeoutService
|
||||
$compile: ng.ICompileService;
|
||||
$rootScope: ng.IRootScopeService;
|
||||
$timeout: ng.ITimeoutService;
|
||||
|
||||
/* @ngInject */
|
||||
constructor(
|
||||
@@ -26,75 +28,72 @@ export class ApplicationGroup extends SNApplicationGroup {
|
||||
$rootScope: ng.IRootScopeService,
|
||||
$timeout: ng.ITimeoutService,
|
||||
private defaultSyncServerHost: string,
|
||||
private bridge: Bridge,
|
||||
private bridge: Bridge
|
||||
) {
|
||||
super(new WebDeviceInterface(
|
||||
$timeout,
|
||||
bridge
|
||||
));
|
||||
super(new WebDeviceInterface($timeout, bridge));
|
||||
this.$compile = $compile;
|
||||
this.$timeout = $timeout;
|
||||
this.$rootScope = $rootScope;
|
||||
}
|
||||
|
||||
async initialize(callback?: any) {
|
||||
async initialize(callback?: any): Promise<void> {
|
||||
await super.initialize({
|
||||
applicationCreator: this.createApplication
|
||||
applicationCreator: this.createApplication,
|
||||
});
|
||||
|
||||
if (isDesktopApplication()) {
|
||||
Object.defineProperty(window, 'desktopManager', {
|
||||
get: () => (this.primaryApplication as WebApplication).getDesktopService()
|
||||
get: () =>
|
||||
(this.primaryApplication as WebApplication).getDesktopService(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private createApplication = (descriptor: ApplicationDescriptor, deviceInterface: DeviceInterface) => {
|
||||
private createApplication = (
|
||||
descriptor: ApplicationDescriptor,
|
||||
deviceInterface: DeviceInterface
|
||||
) => {
|
||||
const scope = this.$rootScope.$new(true);
|
||||
const platform = getPlatform();
|
||||
const application = new WebApplication(
|
||||
deviceInterface as WebDeviceInterface,
|
||||
platform,
|
||||
descriptor.identifier,
|
||||
this.$compile,
|
||||
scope,
|
||||
this.defaultSyncServerHost,
|
||||
this.bridge,
|
||||
this.bridge
|
||||
);
|
||||
const appState = new AppState(
|
||||
this.$rootScope,
|
||||
this.$timeout,
|
||||
application,
|
||||
this.bridge,
|
||||
);
|
||||
const archiveService = new ArchiveManager(
|
||||
application
|
||||
this.bridge
|
||||
);
|
||||
const archiveService = new ArchiveManager(application);
|
||||
const desktopService = new DesktopManager(
|
||||
this.$rootScope,
|
||||
this.$timeout,
|
||||
application,
|
||||
this.bridge,
|
||||
this.bridge
|
||||
);
|
||||
const keyboardService = new KeyboardManager();
|
||||
const autolockService = new AutolockService(
|
||||
application
|
||||
);
|
||||
const nativeExtService = new NativeExtManager(
|
||||
application
|
||||
);
|
||||
const statusService = new StatusManager();
|
||||
const themeService = new ThemeManager(
|
||||
application,
|
||||
const io = new IOService(
|
||||
platform === Platform.MacWeb || platform === Platform.MacDesktop
|
||||
);
|
||||
const autolockService = new AutolockService(application);
|
||||
const nativeExtService = new NativeExtManager(application);
|
||||
const statusManager = new StatusManager();
|
||||
const themeService = new ThemeManager(application);
|
||||
application.setWebServices({
|
||||
appState,
|
||||
archiveService,
|
||||
desktopService,
|
||||
keyboardService,
|
||||
io,
|
||||
autolockService,
|
||||
nativeExtService,
|
||||
statusManager: statusService,
|
||||
themeService
|
||||
statusManager,
|
||||
themeService,
|
||||
});
|
||||
return application;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user