Refactors most controllers and directives into classes for more organized and maintainable code
This commit is contained in:
379
app/assets/javascripts/controllers/footer.js
Normal file
379
app/assets/javascripts/controllers/footer.js
Normal file
@@ -0,0 +1,379 @@
|
||||
import { PrivilegesManager } from '@/services/privilegesManager';
|
||||
import template from '%/footer.pug';
|
||||
import {
|
||||
APP_STATE_EVENT_EDITOR_FOCUSED,
|
||||
APP_STATE_EVENT_BEGAN_BACKUP_DOWNLOAD,
|
||||
APP_STATE_EVENT_ENDED_BACKUP_DOWNLOAD
|
||||
} from '@/state';
|
||||
import {
|
||||
STRING_GENERIC_SYNC_ERROR,
|
||||
STRING_NEW_UPDATE_READY
|
||||
} from '@/strings';
|
||||
|
||||
class FooterCtrl {
|
||||
|
||||
/* @ngInject */
|
||||
constructor(
|
||||
$rootScope,
|
||||
$timeout,
|
||||
alertManager,
|
||||
appState,
|
||||
authManager,
|
||||
componentManager,
|
||||
modelManager,
|
||||
nativeExtManager,
|
||||
passcodeManager,
|
||||
privilegesManager,
|
||||
statusManager,
|
||||
syncManager,
|
||||
) {
|
||||
this.$rootScope = $rootScope;
|
||||
this.$timeout = $timeout;
|
||||
this.alertManager = alertManager;
|
||||
this.appState = appState;
|
||||
this.authManager = authManager;
|
||||
this.componentManager = componentManager;
|
||||
this.modelManager = modelManager;
|
||||
this.nativeExtManager = nativeExtManager;
|
||||
this.passcodeManager = passcodeManager;
|
||||
this.privilegesManager = privilegesManager;
|
||||
this.statusManager = statusManager;
|
||||
this.syncManager = syncManager;
|
||||
|
||||
this.rooms = [];
|
||||
this.themesWithIcons = [];
|
||||
this.showSyncResolution = false;
|
||||
|
||||
this.addAppStateObserver();
|
||||
this.updateOfflineStatus();
|
||||
this.addSyncEventHandler();
|
||||
this.findErrors();
|
||||
this.registerMappingObservers();
|
||||
this.registerComponentHandler();
|
||||
this.addRootScopeListeners();
|
||||
|
||||
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();
|
||||
} else if(eventName === APP_STATE_EVENT_BEGAN_BACKUP_DOWNLOAD) {
|
||||
this.backupStatus = this.statusManager.addStatusFromString(
|
||||
"Saving local backup..."
|
||||
);
|
||||
} else if(eventName === APP_STATE_EVENT_ENDED_BACKUP_DOWNLOAD) {
|
||||
if(data.success) {
|
||||
this.backupStatus = this.statusManager.replaceStatusWithString(
|
||||
this.backupStatus,
|
||||
"Successfully saved backup."
|
||||
);
|
||||
} else {
|
||||
this.backupStatus = this.statusManager.replaceStatusWithString(
|
||||
this.backupStatus,
|
||||
"Unable to save local backup."
|
||||
);
|
||||
}
|
||||
|
||||
this.$timeout(() => {
|
||||
this.backupStatus = this.statusManager.removeStatus(this.backupStatus);
|
||||
}, 2000)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
addSyncEventHandler() {
|
||||
this.syncManager.addEventHandler((syncEvent, data) => {
|
||||
this.$timeout(() => {
|
||||
if(syncEvent === "local-data-loaded") {
|
||||
if(this.offline && this.modelManager.noteCount() === 0) {
|
||||
this.showAccountMenu = true;
|
||||
}
|
||||
} else if(syncEvent === "enter-out-of-sync") {
|
||||
this.outOfSync = true;
|
||||
} else if(syncEvent === "exit-out-of-sync") {
|
||||
this.outOfSync = false;
|
||||
} else if(syncEvent === 'sync:completed') {
|
||||
this.syncUpdated();
|
||||
this.findErrors();
|
||||
this.updateOfflineStatus();
|
||||
} else if(syncEvent === 'sync:error') {
|
||||
this.findErrors();
|
||||
this.updateOfflineStatus();
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
registerMappingObservers() {
|
||||
this.modelManager.addItemSyncObserver(
|
||||
'room-bar',
|
||||
'SN|Component',
|
||||
(allItems, validItems, deletedItems, source) => {
|
||||
this.rooms = this.modelManager.components.filter((candidate) => {
|
||||
return candidate.area === 'rooms' && !candidate.deleted
|
||||
});
|
||||
if(this.queueExtReload) {
|
||||
this.queueExtReload = false;
|
||||
this.reloadExtendedData();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
this.modelManager.addItemSyncObserver(
|
||||
'footer-bar-themes',
|
||||
'SN|Theme',
|
||||
(allItems, validItems, deletedItems, source) => {
|
||||
const themes = this.modelManager.validItemsForContentType('SN|Theme')
|
||||
.filter((candidate) => {
|
||||
return (
|
||||
!candidate.deleted &&
|
||||
candidate.content.package_info &&
|
||||
candidate.content.package_info.dock_icon
|
||||
);
|
||||
}).sort((a, b) => {
|
||||
return a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1;
|
||||
});
|
||||
const differ = themes.length !== this.themesWithIcons.length;
|
||||
this.themesWithIcons = themes;
|
||||
if(differ) {
|
||||
this.reloadDockShortcuts();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
registerComponentHandler() {
|
||||
this.componentManager.registerHandler({
|
||||
identifier: "roomBar",
|
||||
areas: ["rooms", "modal"],
|
||||
activationHandler: (component) => {},
|
||||
actionHandler: (component, action, data) => {
|
||||
if(action === "set-size") {
|
||||
component.setLastSize(data);
|
||||
}
|
||||
},
|
||||
focusHandler: (component, focused) => {
|
||||
if(component.isEditor() && focused) {
|
||||
this.closeAllRooms();
|
||||
this.closeAccountMenu();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
reloadExtendedData() {
|
||||
if(this.reloadInProgress) {
|
||||
return;
|
||||
}
|
||||
this.reloadInProgress = true;
|
||||
|
||||
/**
|
||||
* A reload consists of opening the extensions manager,
|
||||
* then closing it after a short delay.
|
||||
*/
|
||||
const extWindow = this.rooms.find((room) => {
|
||||
return room.package_info.identifier === this.nativeExtManager.extManagerId;
|
||||
});
|
||||
if(!extWindow) {
|
||||
this.queueExtReload = true;
|
||||
this.reloadInProgress = false;
|
||||
return;
|
||||
}
|
||||
this.selectRoom(extWindow);
|
||||
this.$timeout(() => {
|
||||
this.selectRoom(extWindow);
|
||||
this.reloadInProgress = false;
|
||||
this.$rootScope.$broadcast('ext-reload-complete');
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
getUser() {
|
||||
return this.authManager.user;
|
||||
}
|
||||
|
||||
updateOfflineStatus() {
|
||||
this.offline = this.authManager.offline();
|
||||
}
|
||||
|
||||
openSecurityUpdate() {
|
||||
this.authManager.presentPasswordWizard('upgrade-security');
|
||||
}
|
||||
|
||||
findErrors() {
|
||||
this.error = this.syncManager.syncStatus.error;
|
||||
}
|
||||
|
||||
accountMenuPressed() {
|
||||
this.showAccountMenu = !this.showAccountMenu;
|
||||
this.closeAllRooms();
|
||||
}
|
||||
|
||||
toggleSyncResolutionMenu = () => {
|
||||
this.showSyncResolution = !this.showSyncResolution;
|
||||
}
|
||||
|
||||
closeAccountMenu = () => {
|
||||
this.showAccountMenu = false;
|
||||
}
|
||||
|
||||
hasPasscode() {
|
||||
return this.passcodeManager.hasPasscode();
|
||||
}
|
||||
|
||||
lockApp() {
|
||||
this.$rootScope.lockApplication();
|
||||
}
|
||||
|
||||
refreshData() {
|
||||
this.isRefreshing = true;
|
||||
this.syncManager.sync({
|
||||
force: true,
|
||||
performIntegrityCheck: true
|
||||
}).then((response) => {
|
||||
this.$timeout(() => {
|
||||
this.isRefreshing = false;
|
||||
}, 200)
|
||||
if(response && response.error) {
|
||||
this.alertManager.alert({
|
||||
text: STRING_GENERIC_SYNC_ERROR
|
||||
});
|
||||
} else {
|
||||
this.syncUpdated();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
syncUpdated() {
|
||||
this.lastSyncDate = new Date();
|
||||
}
|
||||
|
||||
onNewUpdateAvailable() {
|
||||
this.newUpdateAvailable = true;
|
||||
}
|
||||
|
||||
clickedNewUpdateAnnouncement() {
|
||||
this.newUpdateAvailable = false;
|
||||
this.alertManager.alert({
|
||||
text: STRING_NEW_UPDATE_READY
|
||||
})
|
||||
}
|
||||
|
||||
reloadDockShortcuts() {
|
||||
const shortcuts = [];
|
||||
for(const theme of this.themesWithIcons) {
|
||||
const name = theme.content.package_info.name;
|
||||
const icon = theme.content.package_info.dock_icon;
|
||||
if(!icon) {
|
||||
continue;
|
||||
}
|
||||
shortcuts.push({
|
||||
name: name,
|
||||
component: theme,
|
||||
icon: icon
|
||||
})
|
||||
}
|
||||
|
||||
this.dockShortcuts = shortcuts.sort((a, b) => {
|
||||
/** Circles first, then images */
|
||||
const aType = a.icon.type;
|
||||
const bType = b.icon.type;
|
||||
if(aType === bType) {
|
||||
return 0;
|
||||
} else if(aType === 'circle' && bType === 'svg') {
|
||||
return -1;
|
||||
} else if(bType === 'circle' && aType === 'svg') {
|
||||
return 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
initSvgForShortcut(shortcut) {
|
||||
const id = 'dock-svg-' + shortcut.component.uuid;
|
||||
const element = document.getElementById(id);
|
||||
const parser = new DOMParser();
|
||||
const svg = shortcut.component.content.package_info.dock_icon.source;
|
||||
const doc = parser.parseFromString(svg, 'image/svg+xml');
|
||||
element.appendChild(doc.documentElement);
|
||||
}
|
||||
|
||||
selectShortcut(shortcut) {
|
||||
this.componentManager.toggleComponent(shortcut.component);
|
||||
}
|
||||
|
||||
onRoomDismiss(room) {
|
||||
room.showRoom = false;
|
||||
}
|
||||
|
||||
closeAllRooms() {
|
||||
for(const room of this.rooms) {
|
||||
room.showRoom = false;
|
||||
}
|
||||
}
|
||||
|
||||
async selectRoom(room) {
|
||||
const run = () => {
|
||||
this.$timeout(() => {
|
||||
room.showRoom = !room.showRoom;
|
||||
})
|
||||
}
|
||||
|
||||
if(!room.showRoom) {
|
||||
const requiresPrivilege = await this.privilegesManager.actionRequiresPrivilege(
|
||||
PrivilegesManager.ActionManageExtensions
|
||||
);
|
||||
if(requiresPrivilege) {
|
||||
this.privilegesManager.presentPrivilegesModal(
|
||||
PrivilegesManager.ActionManageExtensions,
|
||||
run
|
||||
);
|
||||
} else {
|
||||
run();
|
||||
}
|
||||
} else {
|
||||
run();
|
||||
}
|
||||
}
|
||||
|
||||
clickOutsideAccountMenu() {
|
||||
if(this.privilegesManager.authenticationInProgress()) {
|
||||
return;
|
||||
}
|
||||
this.showAccountMenu = false;
|
||||
}
|
||||
}
|
||||
|
||||
export class Footer {
|
||||
constructor() {
|
||||
this.restrict = 'E';
|
||||
this.scope = {};
|
||||
this.template = template;
|
||||
this.controller = FooterCtrl;
|
||||
this.replace = true;
|
||||
this.controllerAs = 'ctrl';
|
||||
this.bindToController = true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user