Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
212 lines
6.1 KiB
JavaScript
Executable file
212 lines
6.1 KiB
JavaScript
Executable file
'use strict';
|
|
|
|
/* global UserDictionaryListPanel, GeneralPanel, UserDictionaryEditDialog */
|
|
|
|
(function(exports) {
|
|
|
|
/*
|
|
* Controls transitioning of different panels and dialogs. The concept is
|
|
* largely the same with Settings app, but we're working under these bases here:
|
|
*
|
|
* 1) we only have two panels (general and user-dictionary-word-list), and one
|
|
* dialog (user-dictionary-edit).
|
|
* 2) we either navigate to general from word list, or
|
|
* navigate from general to word list, or
|
|
* show the dict edit dialog when we're at word list.
|
|
*
|
|
* The transition between general and word list panels are written
|
|
* ad-hoc thereby.
|
|
*
|
|
*
|
|
* == Dialogs ==
|
|
*
|
|
* A dialog is of more limited use:
|
|
*
|
|
* Similr to Settings app, a dialog is always modal and may only be stacked on
|
|
* top of another panel or another dialog, and cannot freely transition to
|
|
* another panel.
|
|
*
|
|
* We should always open a dialog with DialogController -- we try to limit a
|
|
* dialog object's ability to reach other components, and we only provide it
|
|
* with DialogController, at construction, such that it is able to open other
|
|
* dialogs only.
|
|
*
|
|
* A dialog has a onsubmit call back where it passes its result, which is
|
|
* processed by openDialog, for subsequent clean-up and transition-out, and for
|
|
* propogation the results through openDialog's originally returned Promise to
|
|
* its caller.
|
|
*/
|
|
|
|
// in case transitionend event is interrupted due to whatever reason,
|
|
// we use a timeout to make sure that the sequence is not uncontrollably
|
|
// interruptted.
|
|
const TRANSITION_TIMEOUT = 600;
|
|
|
|
var PanelController = function(app, rootPanelClass) {
|
|
this.RootPanelClass = rootPanelClass || this.ROOT_PANEL_CLASS;
|
|
|
|
this._currentPanel = null;
|
|
this.app = app;
|
|
|
|
this.rootPanel = null;
|
|
this.userDictionaryListPanel = null;
|
|
};
|
|
|
|
PanelController.prototype.ROOT_PANEL_CLASS = GeneralPanel;
|
|
|
|
PanelController.prototype.start = function() {
|
|
this.rootPanel = new this.RootPanelClass(this.app);
|
|
this.rootPanel.start();
|
|
|
|
// We support user dictionary!
|
|
if (typeof UserDictionaryListPanel === 'function') {
|
|
this.userDictionaryListPanel = new UserDictionaryListPanel(this.app);
|
|
this.userDictionaryListPanel.start();
|
|
}
|
|
|
|
Promise.resolve(this.rootPanel.beforeShow())
|
|
.then(this.rootPanel.show.bind(this.rootPanel))
|
|
.catch(e => e && console.error(e));
|
|
};
|
|
|
|
PanelController.prototype.stop = function() {
|
|
this._currentPanel = null;
|
|
|
|
this.rootPanel.stop();
|
|
this.rootPanel = null;
|
|
|
|
if (this.userDictionaryListPanel) {
|
|
this.userDictionaryListPanel.stop();
|
|
this.userDictionaryListPanel = null;
|
|
}
|
|
};
|
|
|
|
PanelController.prototype._createTransitionPromise = function(target) {
|
|
return new Promise(function(resolve){
|
|
var transitionEnd = function(){
|
|
clearTimeout(timeout);
|
|
target.removeEventListener('transitionend', transitionEnd);
|
|
|
|
resolve();
|
|
};
|
|
|
|
var timeout = setTimeout(transitionEnd, TRANSITION_TIMEOUT);
|
|
target.addEventListener('transitionend', transitionEnd);
|
|
});
|
|
};
|
|
|
|
PanelController.prototype.navigateToRoot = function() {
|
|
// we assume we're always navigating from one-level-deep panel (=> word list)
|
|
|
|
Promise.resolve(this._currentPanel.beforeHide())
|
|
.then(() => this.rootPanel.beforeShow())
|
|
.then(() => {
|
|
var transitionPromise =
|
|
this._createTransitionPromise(this._currentPanel.container);
|
|
|
|
this._currentPanel.container.classList.remove('current');
|
|
this.rootPanel.container.classList.remove('prev');
|
|
this.rootPanel.container.classList.add('current');
|
|
|
|
return transitionPromise;
|
|
})
|
|
.then(this._currentPanel.hide.bind(this._currentPanel))
|
|
.then(this.rootPanel.show.bind(this.rootPanel))
|
|
.then(() => {
|
|
this._currentPanel = null;
|
|
})
|
|
.catch(e => e && console.error(e));
|
|
};
|
|
|
|
PanelController.prototype.navigateToPanel = function(panel, options) {
|
|
// we assume we're always navigating from general
|
|
|
|
this._currentPanel = panel;
|
|
|
|
Promise.resolve(this.rootPanel.beforeHide())
|
|
.then(() => panel.beforeShow(options))
|
|
.then(() => {
|
|
var transitionPromise = this._createTransitionPromise(panel.container);
|
|
|
|
panel.container.classList.add('current');
|
|
this.rootPanel.container.classList.remove('current');
|
|
this.rootPanel.container.classList.add('prev');
|
|
|
|
return transitionPromise;
|
|
})
|
|
.then(this.rootPanel.hide.bind(this.rootPanel))
|
|
.then(panel.show.bind(panel))
|
|
.catch(e => e && console.error(e));
|
|
};
|
|
|
|
|
|
var DialogController = function() {
|
|
this.userDictionaryEditDialog = null;
|
|
};
|
|
|
|
DialogController.prototype.start = function() {
|
|
// We support user dictionary!
|
|
if (typeof UserDictionaryEditDialog === 'function') {
|
|
this.userDictionaryEditDialog = new UserDictionaryEditDialog(this);
|
|
this.userDictionaryEditDialog.start();
|
|
}
|
|
};
|
|
|
|
DialogController.prototype.stop = function() {
|
|
if (this.userDictionaryEditDialog) {
|
|
this.userDictionaryEditDialog.stop();
|
|
this.userDictionaryEditDialog = null;
|
|
}
|
|
};
|
|
|
|
DialogController.prototype._createTransitionPromise =
|
|
PanelController.prototype._createTransitionPromise;
|
|
|
|
DialogController.prototype.openDialog = function(dialog, options) {
|
|
if (!('onsubmit' in dialog)) {
|
|
return Promise.reject('Dialog does not have a onsubmit callback');
|
|
}
|
|
|
|
var resultPromiseResolve, resultPromiseReject;
|
|
|
|
var resultPromise = new Promise(function(resolve, reject){
|
|
resultPromiseResolve = resolve;
|
|
resultPromiseReject = reject;
|
|
});
|
|
|
|
dialog.onsubmit = results => {
|
|
resultPromiseResolve(results);
|
|
|
|
Promise.resolve(dialog.beforeHide())
|
|
.then(() => {
|
|
var transitionPromise = this._createTransitionPromise(dialog.container);
|
|
|
|
dialog.container.classList.remove('displayed');
|
|
|
|
return transitionPromise;
|
|
})
|
|
.then(() => {
|
|
dialog.onsubmit = undefined;
|
|
return dialog.hide();
|
|
})
|
|
.catch(e => e && console.log(e));
|
|
};
|
|
|
|
Promise.resolve(dialog.beforeShow(options))
|
|
.then(() => {
|
|
var transitionPromise = this._createTransitionPromise(dialog.container);
|
|
|
|
dialog.container.classList.add('displayed');
|
|
|
|
return transitionPromise;
|
|
})
|
|
.then(dialog.show.bind(dialog))
|
|
.catch(e => resultPromiseReject(e));
|
|
|
|
return resultPromise;
|
|
};
|
|
|
|
exports.PanelController = PanelController;
|
|
exports.DialogController = DialogController;
|
|
|
|
})(window);
|