Fixes #300
This commit is contained in:
@@ -7,7 +7,8 @@ import template from '%/editor.pug';
|
||||
import { PureCtrl } from '@Controllers';
|
||||
import {
|
||||
APP_STATE_EVENT_NOTE_CHANGED,
|
||||
APP_STATE_EVENT_PREFERENCES_CHANGED
|
||||
APP_STATE_EVENT_PREFERENCES_CHANGED,
|
||||
EVENT_SOURCE_SCRIPT
|
||||
} from '@/state';
|
||||
import {
|
||||
STRING_DELETED_NOTE,
|
||||
@@ -237,11 +238,11 @@ class EditorCtrl extends PureCtrl {
|
||||
if (eventName === 'sync:taking-too-long') {
|
||||
this.setState({
|
||||
syncTakingTooLong: true
|
||||
})
|
||||
});
|
||||
} else if (eventName === 'sync:completed') {
|
||||
this.setState({
|
||||
syncTakingTooLong: false
|
||||
})
|
||||
});
|
||||
if (this.state.note.dirty) {
|
||||
/** if we're still dirty, don't change status, a sync is likely upcoming. */
|
||||
} else {
|
||||
@@ -263,7 +264,7 @@ class EditorCtrl extends PureCtrl {
|
||||
this.showErrorStatus();
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
addSyncStatusObserver() {
|
||||
@@ -359,25 +360,6 @@ class EditorCtrl extends PureCtrl {
|
||||
return this.actionsManager.extensionsInContextOfItem(this.state.note).length > 0;
|
||||
}
|
||||
|
||||
focusEditor({ delay } = {}) {
|
||||
setTimeout(() => {
|
||||
const element = document.getElementById(ELEMENT_ID_NOTE_TEXT_EDITOR);
|
||||
if (element) {
|
||||
element.focus();
|
||||
}
|
||||
}, delay);
|
||||
}
|
||||
|
||||
focusTitle(delay) {
|
||||
setTimeout(function () {
|
||||
document.getElementById(ELEMENT_ID_NOTE_TITLE_EDITOR).focus();
|
||||
}, delay);
|
||||
}
|
||||
|
||||
clickedTextArea() {
|
||||
this.setMenuState('showOptionsMenu', false);
|
||||
}
|
||||
|
||||
saveNote({
|
||||
bypassDebouncer,
|
||||
updateClientModified,
|
||||
@@ -429,8 +411,8 @@ class EditorCtrl extends PureCtrl {
|
||||
text: STRING_GENERIC_SAVE_ERROR
|
||||
});
|
||||
}
|
||||
})
|
||||
}, syncDebouceMs)
|
||||
});
|
||||
}, syncDebouceMs);
|
||||
}
|
||||
|
||||
showSavingStatus() {
|
||||
@@ -444,7 +426,7 @@ class EditorCtrl extends PureCtrl {
|
||||
this.setState({
|
||||
saveError: false,
|
||||
syncTakingTooLong: false
|
||||
})
|
||||
});
|
||||
let status = "All changes saved";
|
||||
if (this.authManager.offline()) {
|
||||
status += " (offline)";
|
||||
@@ -459,12 +441,12 @@ class EditorCtrl extends PureCtrl {
|
||||
error = {
|
||||
message: "Sync Unreachable",
|
||||
desc: "Changes saved offline"
|
||||
}
|
||||
};
|
||||
}
|
||||
this.setState({
|
||||
saveError: true,
|
||||
syncTakingTooLong: false
|
||||
})
|
||||
});
|
||||
this.setStatus(error);
|
||||
}
|
||||
|
||||
@@ -485,8 +467,8 @@ class EditorCtrl extends PureCtrl {
|
||||
status.date = new Date();
|
||||
this.setState({
|
||||
noteStatus: status
|
||||
})
|
||||
}, waitForMs)
|
||||
});
|
||||
}, waitForMs);
|
||||
}
|
||||
|
||||
contentChanged() {
|
||||
@@ -508,12 +490,29 @@ class EditorCtrl extends PureCtrl {
|
||||
});
|
||||
}
|
||||
|
||||
focusEditor() {
|
||||
const element = document.getElementById(ELEMENT_ID_NOTE_TEXT_EDITOR);
|
||||
if (element) {
|
||||
this.lastEditorFocusEventSource = EVENT_SOURCE_SCRIPT;
|
||||
element.focus();
|
||||
}
|
||||
}
|
||||
|
||||
focusTitle() {
|
||||
document.getElementById(ELEMENT_ID_NOTE_TITLE_EDITOR).focus();
|
||||
}
|
||||
|
||||
clickedTextArea() {
|
||||
this.setMenuState('showOptionsMenu', false);
|
||||
}
|
||||
|
||||
onNameFocus() {
|
||||
this.editingName = true;
|
||||
}
|
||||
|
||||
onContentFocus() {
|
||||
this.appState.editorDidFocus();
|
||||
this.appState.editorDidFocus(this.lastEditorFocusEventSource);
|
||||
this.lastEditorFocusEventSource = null;
|
||||
}
|
||||
|
||||
onNameBlur() {
|
||||
@@ -585,24 +584,13 @@ class EditorCtrl extends PureCtrl {
|
||||
if (note === this.state.note) {
|
||||
this.setState({
|
||||
note: null
|
||||
})
|
||||
});
|
||||
}
|
||||
if (note.dummy) {
|
||||
this.modelManager.removeItemLocally(note);
|
||||
return;
|
||||
}
|
||||
|
||||
this.syncManager.sync().then(() => {
|
||||
if (this.authManager.offline()) {
|
||||
/**
|
||||
* When deleting items while ofline, we need
|
||||
* to explictly tell angular to refresh UI
|
||||
*/
|
||||
setTimeout(function () {
|
||||
this.$rootScope.safeApply();
|
||||
}, 50);
|
||||
}
|
||||
});
|
||||
this.syncManager.sync();
|
||||
}
|
||||
|
||||
restoreTrashedNote() {
|
||||
|
||||
@@ -4,7 +4,8 @@ import template from '%/footer.pug';
|
||||
import {
|
||||
APP_STATE_EVENT_EDITOR_FOCUSED,
|
||||
APP_STATE_EVENT_BEGAN_BACKUP_DOWNLOAD,
|
||||
APP_STATE_EVENT_ENDED_BACKUP_DOWNLOAD
|
||||
APP_STATE_EVENT_ENDED_BACKUP_DOWNLOAD,
|
||||
EVENT_SOURCE_USER_INTERACTION
|
||||
} from '@/state';
|
||||
import {
|
||||
STRING_GENERIC_SYNC_ERROR,
|
||||
@@ -55,33 +56,35 @@ class FooterCtrl {
|
||||
|
||||
this.authManager.checkForSecurityUpdate().then((available) => {
|
||||
this.securityUpdateAvailable = available;
|
||||
})
|
||||
});
|
||||
this.statusManager.addStatusObserver((string) => {
|
||||
this.$timeout(() => {
|
||||
this.arbitraryStatusMessage = string;
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
addRootScopeListeners() {
|
||||
this.$rootScope.$on("security-update-status-changed", () => {
|
||||
this.securityUpdateAvailable = this.authManager.securityUpdateAvailable;
|
||||
})
|
||||
});
|
||||
this.$rootScope.$on("reload-ext-data", () => {
|
||||
this.reloadExtendedData();
|
||||
});
|
||||
this.$rootScope.$on("new-update-available", () => {
|
||||
this.$timeout(() => {
|
||||
this.onNewUpdateAvailable();
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
addAppStateObserver() {
|
||||
this.appState.addObserver((eventName, data) => {
|
||||
if(eventName === APP_STATE_EVENT_EDITOR_FOCUSED) {
|
||||
this.closeAllRooms();
|
||||
this.closeAccountMenu();
|
||||
if (data.eventSource === EVENT_SOURCE_USER_INTERACTION) {
|
||||
this.closeAllRooms();
|
||||
this.closeAccountMenu();
|
||||
}
|
||||
} else if(eventName === APP_STATE_EVENT_BEGAN_BACKUP_DOWNLOAD) {
|
||||
this.backupStatus = this.statusManager.addStatusFromString(
|
||||
"Saving local backup..."
|
||||
@@ -98,12 +101,11 @@ class FooterCtrl {
|
||||
"Unable to save local backup."
|
||||
);
|
||||
}
|
||||
|
||||
this.$timeout(() => {
|
||||
this.backupStatus = this.statusManager.removeStatus(this.backupStatus);
|
||||
}, 2000)
|
||||
}, 2000);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
addSyncEventHandler() {
|
||||
|
||||
@@ -113,7 +113,7 @@ class NotesCtrl extends PureCtrl {
|
||||
} else if (eventName === APP_STATE_EVENT_EDITOR_FOCUSED) {
|
||||
this.setShowMenuFalse();
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
addSignInObserver() {
|
||||
|
||||
@@ -61,14 +61,10 @@ class RootCtrl {
|
||||
}
|
||||
|
||||
defineRootScopeFunctions() {
|
||||
this.$rootScope.sync = () => {
|
||||
this.syncManager.sync();
|
||||
}
|
||||
|
||||
this.$rootScope.lockApplication = () => {
|
||||
/** Reloading wipes current objects from memory */
|
||||
window.location.reload();
|
||||
}
|
||||
};
|
||||
|
||||
this.$rootScope.safeApply = (fn) => {
|
||||
const phase = this.$scope.$root.$$phase;
|
||||
@@ -93,12 +89,12 @@ class RootCtrl {
|
||||
this.$timeout(() => {
|
||||
this.$scope.needsUnlock = false;
|
||||
this.loadAfterUnlock();
|
||||
})
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
this.$scope.onUpdateAvailable = () => {
|
||||
this.$rootScope.$broadcast('new-update-available');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
initializeStorageManager() {
|
||||
@@ -173,13 +169,13 @@ class RootCtrl {
|
||||
this.uploadSyncStatus = this.statusManager.replaceStatusWithString(
|
||||
this.uploadSyncStatus,
|
||||
`Syncing ${status.current}/${status.total} items...`
|
||||
)
|
||||
);
|
||||
} else if(this.uploadSyncStatus) {
|
||||
this.uploadSyncStatus = this.statusManager.removeStatus(
|
||||
this.uploadSyncStatus
|
||||
);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
configureKeyRequestHandler() {
|
||||
@@ -197,7 +193,7 @@ class RootCtrl {
|
||||
keys: keys,
|
||||
offline: offline,
|
||||
auth_params: authParams
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@@ -258,7 +254,7 @@ class RootCtrl {
|
||||
setInterval(() => {
|
||||
this.syncManager.sync();
|
||||
}, AUTO_SYNC_INTERVAL);
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -268,31 +264,35 @@ class RootCtrl {
|
||||
this.modelManager.handleSignout();
|
||||
this.syncManager.handleSignout();
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
addDragDropHandlers() {
|
||||
/**
|
||||
* Disable dragging and dropping of files into main SN interface.
|
||||
* Disable dragging and dropping of files (but allow text) into main SN interface.
|
||||
* both 'dragover' and 'drop' are required to prevent dropping of files.
|
||||
* This will not prevent extensions from receiving drop events.
|
||||
*/
|
||||
window.addEventListener('dragover', (event) => {
|
||||
event.preventDefault();
|
||||
}, false)
|
||||
if (event.dataTransfer.files.length > 0) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}, false);
|
||||
|
||||
window.addEventListener('drop', (event) => {
|
||||
event.preventDefault();
|
||||
this.alertManager.alert({
|
||||
text: STRING_DEFAULT_FILE_ERROR
|
||||
})
|
||||
}, false)
|
||||
if(event.dataTransfer.files.length > 0) {
|
||||
event.preventDefault();
|
||||
this.alertManager.alert({
|
||||
text: STRING_DEFAULT_FILE_ERROR
|
||||
});
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
|
||||
handleAutoSignInFromParams() {
|
||||
const urlParam = (key) => {
|
||||
return this.$location.search()[key];
|
||||
}
|
||||
};
|
||||
|
||||
const autoSignInFromParams = async () => {
|
||||
const server = urlParam('server');
|
||||
|
||||
@@ -227,7 +227,8 @@ class TagsPanelCtrl extends PureCtrl {
|
||||
this.editingOriginalName = null;
|
||||
|
||||
const matchingTag = this.modelManager.findTag(tag.title);
|
||||
if (this.state.newTag === tag && matchingTag) {
|
||||
const alreadyExists = matchingTag && matchingTag !== tag;
|
||||
if (this.state.newTag === tag && alreadyExists) {
|
||||
this.alertManager.alert({
|
||||
text: "A tag with this name already exists."
|
||||
});
|
||||
@@ -264,9 +265,7 @@ class TagsPanelCtrl extends PureCtrl {
|
||||
destructive: true,
|
||||
onConfirm: () => {
|
||||
this.modelManager.setItemToBeDeleted(tag);
|
||||
this.syncManager.sync().then(() => {
|
||||
this.$rootScope.safeApply();
|
||||
});
|
||||
this.syncManager.sync();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -190,18 +190,18 @@ export class PasscodeManager {
|
||||
} else {
|
||||
// tab visibility listener, web only
|
||||
document.addEventListener('visibilitychange', (e) => {
|
||||
let visible = document.visibilityState == "visible";
|
||||
const visible = document.visibilityState === "visible";
|
||||
this.documentVisibilityChanged(visible);
|
||||
});
|
||||
|
||||
// verify document is in focus every so often as visibilitychange event is not triggered
|
||||
// on a typical window blur event but rather on tab changes
|
||||
this.pollFocusTimeout = setInterval(() => {
|
||||
let hasFocus = document.hasFocus();
|
||||
const hasFocus = document.hasFocus();
|
||||
|
||||
if(hasFocus && this.lastFocusState == "hidden") {
|
||||
if(hasFocus && this.lastFocusState === "hidden") {
|
||||
this.documentVisibilityChanged(true);
|
||||
} else if(!hasFocus && this.lastFocusState == "visible") {
|
||||
} else if(!hasFocus && this.lastFocusState === "visible") {
|
||||
this.documentVisibilityChanged(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@ export const APP_STATE_EVENT_BEGAN_BACKUP_DOWNLOAD = 6;
|
||||
export const APP_STATE_EVENT_ENDED_BACKUP_DOWNLOAD = 7;
|
||||
export const APP_STATE_EVENT_DESKTOP_EXTS_READY = 8;
|
||||
|
||||
export const EVENT_SOURCE_USER_INTERACTION = 1;
|
||||
export const EVENT_SOURCE_SCRIPT = 2;
|
||||
|
||||
export class AppState {
|
||||
|
||||
/* @ngInject */
|
||||
@@ -34,8 +37,8 @@ export class AppState {
|
||||
await callback(eventName, data);
|
||||
}
|
||||
resolve();
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
setSelectedTag(tag) {
|
||||
@@ -58,7 +61,7 @@ export class AppState {
|
||||
APP_STATE_EVENT_NOTE_CHANGED,
|
||||
{ previousNote: previousNote }
|
||||
);
|
||||
}
|
||||
};
|
||||
if (note && note.content.protected &&
|
||||
await this.privilegesManager.actionRequiresPrivilege(
|
||||
PrivilegesManager.ActionViewProtectedNotes
|
||||
@@ -94,12 +97,13 @@ export class AppState {
|
||||
panel: name,
|
||||
collapsed: collapsed
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
editorDidFocus() {
|
||||
editorDidFocus(eventSource) {
|
||||
this.notifyEvent(
|
||||
APP_STATE_EVENT_EDITOR_FOCUSED
|
||||
APP_STATE_EVENT_EDITOR_FOCUSED,
|
||||
{eventSource: eventSource}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user