VulpesOS/gaia/apps/communications/contacts/js/navigation.js
OverSu b38dea0597 Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
2026-09-30 23:13:03 +02:00

290 lines
8.5 KiB
JavaScript
Executable file

'use strict';
/* global LazyLoader */
/* exported navigationStack */
function navigationStack(currentView) {
/* jshint validthis:true */
// Each transition entry includes a 'forwards' property including the
// classes which will be added to the 'current' and 'next' view when the
// transition goes forwards, as well as a 'backwards' property including the
// classes which will be added to the 'current' and 'next' view when the
// transition goes backwards.
this.transitions = {
'none': {
forwards: {},
backwards: {}
},
'right-left': {
forwards: {
next: 'app-go-in'
},
backwards: {
current: 'app-go-back-out'
}
},
'popup': {
forwards: {
next: 'app-go-up-in'
},
backwards: {
current: 'app-go-up-back-out'
}
},
'activity-popup': {
forwards: {
next: 'app-go-up-in'
},
backwards: {}
},
'fade-in': {
forwards: {
next: 'fade-in'
},
backwards: {
current: 'fade-out'
}
},
'go-deeper': {
forwards: {
current: 'app-go-deeper-out',
next: 'app-go-deeper-in'
},
backwards: {
current: 'app-go-deeper-back-out',
next: 'app-go-deeper-back-in'
}
},
'go-deeper-search': {
forwards: {
current: 'move-out-from-forward',
next: 'move-in-from-forward'
},
backwards: {
current: 'move-out-from-backward',
next: 'move-in-from-backward'
}
}
};
var COMMS_APP_ORIGIN = location.origin;
var screenshotViewId = 'view-screenshot';
var _currentView = currentView;
document.getElementById(currentView).classList.add('current');
this.stack = [];
navigationStack._zIndex = navigationStack._zIndex || 0;
this.stack.push({view: _currentView, transition: 'popup',
zIndex: ++navigationStack._zIndex});
var waitForAnimation = function ng_waitForAnimation(view, callback) {
if (!callback) {
return;
}
view.addEventListener('animationend', function ng_onAnimationEnd() {
view.removeEventListener('animationend', ng_onAnimationEnd);
setTimeout(callback, 0);
});
};
this.go = function go(nextView, transition, callback) {
if (_currentView === nextView) {
if (callback) {
callback();
}
return;
}
var parent = window.parent;
if (nextView == 'view-contact-form') {
parent.postMessage({type: 'hide-navbar'}, COMMS_APP_ORIGIN);
}
// Remove items that match nextView from the stack to prevent duplicates.
this.stack = this.stack.filter(function(item) {
return item.view != nextView;
});
var current;
var currentClassList;
// Performance is very bad when there are too many contacts so we use
// -moz-element and animate this 'screenshot" element.
if (transition.indexOf('go-deeper') === 0) {
current = document.getElementById(screenshotViewId);
// Load the screenshot dom content
LazyLoader.load([current]);
current.style.zIndex = this.stack[this.stack.length - 1].zIndex;
currentClassList = current.classList;
if (transition.indexOf('search') !== -1) {
currentClassList.add('search');
} else {
currentClassList.add('contact-list');
}
currentClassList.remove('hide');
} else {
current = document.getElementById(_currentView);
currentClassList = current.classList;
}
var forwardsClasses = this.transitions[transition].forwards;
// Add forwards class to current view.
currentClassList.add('block-item');
if (forwardsClasses.current) {
currentClassList.add(forwardsClasses.current);
}
var next = document.getElementById(nextView);
// Add forwards class to next view.
if (forwardsClasses.next) {
next.classList.add(forwardsClasses.next);
next.addEventListener('animationend', function ng_onNextBackwards(ev) {
next.removeEventListener('animationend', ng_onNextBackwards);
next.classList.remove('block-item');
});
}
next.classList.add('current');
var realCurrentView = document.getElementById(_currentView);
var _callbackInner = function _callback() {
next.classList.add('current');
realCurrentView.classList.remove('current');
if (callback) {
callback();
}
};
if (transition === 'none') {
setTimeout(_callbackInner, 0);
} else {
waitForAnimation(next, _callbackInner);
}
var zIndex = ++navigationStack._zIndex;
this.stack.push({ view: nextView, transition: transition,
zIndex: zIndex});
next.style.zIndex = zIndex;
_currentView = nextView;
};
this.back = function back(callback) {
if (this.stack.length < 2) {
if (typeof callback === 'function') {
setTimeout(callback, 0);
}
return;
}
var currentView = this.stack.pop();
var current = document.getElementById(currentView.view);
var currentClassList = current.classList;
var nextView = this.stack[this.stack.length - 1];
var transition = currentView.transition;
var next = document.getElementById(nextView.view);
var nextClassList;
// Performance is very bad when there are too many contacts so we use
// -moz-element and animate this 'screenshot" element.
if (transition.indexOf('go-deeper') === 0) {
next = document.getElementById(screenshotViewId);
} else {
next = document.getElementById(nextView.view);
}
nextClassList = next.classList;
var forwardsClasses = this.transitions[transition].forwards;
var backwardsClasses = this.transitions[transition].backwards;
if (currentView.view == 'view-contact-form') {
parent.postMessage({type: 'show-navbar'}, COMMS_APP_ORIGIN);
}
// Add backwards class to current view.
if (backwardsClasses.current) {
currentClassList.add('block-item');
currentClassList.add(backwardsClasses.current);
current.addEventListener('animationend',
function ng_onCurrentBackwards() {
current.removeEventListener('animationend', ng_onCurrentBackwards);
// Once the backwards animation completes, delete the added classes
// to restore the elements to their initial state.
currentClassList.remove(forwardsClasses.next);
currentClassList.remove(backwardsClasses.current);
current.style.zIndex = null;
currentClassList.remove('block-item');
if (!backwardsClasses.next) {
nextClassList.remove('block-item');
}
}
);
} else {
current.style.zIndex = null;
currentClassList.remove('block-item');
if (!backwardsClasses.next) {
nextClassList.remove('block-item');
}
}
next.style.zIndex = nextView.zIndex;
// Add backwards class to next view.
if (backwardsClasses.next) {
nextClassList.add(backwardsClasses.next);
next.addEventListener('animationend', function ng_onNextBackwards() {
next.removeEventListener('animationend', ng_onNextBackwards);
// Once the backwards animation completes, delete the added classes
// to restore the elements to their initial state.
nextClassList.remove(forwardsClasses.current);
nextClassList.remove(backwardsClasses.next);
if (transition.indexOf('go-deeper') === 0) {
// Hide the -moz-element element once the animation completes.
nextClassList.add('hide');
nextClassList.remove('search');
nextClassList.remove('contact-list');
}
nextClassList.remove('block-item');
});
}
document.getElementById(nextView.view).classList.add('current');
var _callbackInner = function _callbackInner() {
document.getElementById(nextView.view).classList.add('current');
currentClassList.remove('current');
if (callback) {
callback();
}
};
if ((!backwardsClasses.current && !backwardsClasses.next) ||
transition === 'none') {
setTimeout(_callbackInner, 0);
} else {
waitForAnimation(current, _callbackInner);
}
_currentView = nextView.view;
navigationStack._zIndex = nextView.zIndex;
};
this.home = function home(callback) {
if (this.stack.length < 2) {
if (typeof callback === 'function') {
setTimeout(callback, 0);
}
return;
}
while (this.stack.length > 1) {
this.back(callback);
}
};
this.currentView = function currentView() {
return _currentView != null ? _currentView : '';
};
}