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.
This commit is contained in:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

View file

@ -0,0 +1,255 @@
/* global AccessibilityHelper, LazyLoader */
/* exported ViewManager */
/* -*- Mode: js; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
'use strict';
var ViewManager = (function() {
// The ViewManager is in charge of simply manage the different views of the
// applications. ViewManager.changeViewTo() valid values are listed above
// these lines.
function ViewManager(tabs) {
tabs = tabs || [];
this._tabs = {};
tabs.forEach(function _registerTab(tabItem) {
if (typeof tabItem !== 'object') {
tabItem = { id: tabItem };
}
this._tabs[tabItem.id] = tabItem.tab || 'left';
}, this);
this._currentView = null;
this._currentTab = null;
}
// Return true if the passed view is a tab
ViewManager.prototype._isTab = function _isTab(view) {
return this._tabs.hasOwnProperty(view);
};
// Make target enter screen's main area and call callback after, passing as
// arguments if the new view is a tab, the new view id and a third parameter
// depending on if the view was a tab or not:
// If it is a tab: it returns the current overlay view id or null
// If it is not a tab: it returns the previous ovrlay view or null
ViewManager.prototype.changeViewTo = function _changeViewTo(viewHash,
obstructed,
callback) {
var hashParts = viewHash.split('?');
var viewId = hashParts[0];
if (this.isCurrentView(viewId)) {
return;
}
// Note here how we set the same value with different semantincs.
// This is used at the end of the function and the names are the correct
// because, depending on if the view is a tab or not, semantics may change.
var previousViewId, currentViewId;
previousViewId = currentViewId = this._currentView ?
this._currentView.id : null;
var view = document.getElementById(viewId);
var params = parseQueryParams(hashParts[1]);
var self = this;
// lazy load HTML of the panel
this.loadPanel(view, function() {
// Tabs are treated in a different way than overlay views
var isTab = self._isTab(viewId);
if (isTab) {
// Disposing the current view
var disposingTab = null;
if (self._currentTab) {
disposingTab = document.getElementById(self._currentTab);
}
if (disposingTab) {
disposingTab.dataset.viewport = self._tabs[disposingTab.id];
document.getElementById(disposingTab.id + '-filter').classList.remove(
'.selected');
}
// Showing the new one
view.dataset.viewport = '';
document.getElementById(view.id + '-filter').classList.add('.selected');
AccessibilityHelper.setAriaSelected(
document.getElementById(view.id + '-control'),
document.querySelectorAll('[role="tab"]'));
self._currentTab = viewId;
// Overlay view
} else {
self.closeCurrentView();
previousViewId = self._currentView ? self._currentView.id : '';
self._currentView = {
id: viewId,
defaultViewport: view.dataset.viewport,
obstructed: obstructed
};
// With a combination of CSS, we actually animate and display the view
delete view.dataset.viewport;
if (obstructed) {
document.querySelector(obstructed).classList.add('behind');
}
}
if (typeof callback === 'function') {
callback(isTab, viewId, isTab ? currentViewId : previousViewId);
}
notifyViewChange(isTab, viewId, params);
});
};
function notifyViewChange(isTab, current, params) {
var type = isTab ? 'tabchanged' : 'viewchanged';
var event = new CustomEvent(type, {
detail: {
id: current,
params: params
}
});
window.dispatchEvent(event);
}
ViewManager.prototype.loadPanel = function _loadPanel(panel, callback) {
if (!panel || panel.hidden === false) {
if (typeof callback === 'function') {
callback();
}
return;
}
LazyLoader.load(panel, function() {
var resourceRemaining = 0;
function loadResource(node) {
node.onload = onResourceLoaded;
document.head.appendChild(node);
resourceRemaining++;
}
// activate all styles
Array.from(panel.querySelectorAll('link')).forEach((node) => {
if (!document.querySelector('head > link[href="' + node.href + '"]')) {
var styleLink = document.createElement('link');
styleLink.href = node.href;
styleLink.media = node.media;
styleLink.rel = node.rel;
styleLink.type = node.type;
loadResource(styleLink);
}
node.remove();
});
// activate all scripts
Array.from(panel.querySelectorAll('script')).forEach((node) => {
if (!document.querySelector('head > script[src="' + node.src + '"]')) {
var scriptLink = document.createElement('script');
scriptLink.src = node.src;
scriptLink.type = node.type;
loadResource(scriptLink);
}
node.remove();
});
// add listeners
var headers = Array.from(
panel.querySelectorAll('gaia-header[action="close"]')
);
headers.forEach((headerWithClose) => {
headerWithClose.addEventListener('action', function() {
window.parent.location.hash = '#';
});
});
panel.hidden = false;
checkCallback();
function checkCallback() {
if (resourceRemaining === 0 && typeof callback === 'function') {
callback();
}
}
function onResourceLoaded() {
resourceRemaining--;
checkCallback();
}
});
};
// Close the current view returning to the previous one
ViewManager.prototype.closeCurrentView = function _closeCurrentView() {
if (!this._currentView) {
return;
}
var view = document.getElementById(this._currentView.id);
// With a combination of CSS, Restoring the last viewport we actually
// animate and hide the current view
view.dataset.viewport = this._currentView.defaultViewport;
if (this._currentView.obstructed) {
var obstructed = document.querySelector(this._currentView.obstructed);
obstructed.classList.remove('behind');
}
this._currentView = null;
};
// Test if the current view is the one passed as parameter
ViewManager.prototype.isCurrentView = function _isCurrentView(view) {
return this._currentView && this._currentView.id === view;
};
// Return the current view id or null if not current view
ViewManager.prototype.getCurrentView = function _getCurrentView() {
return this._currentView ? this._currentView.id : null;
};
// Return true if the tab id passed is the current tab
ViewManager.prototype.isCurrentTab = function _isCurrentTab(tab) {
return this._currentTab && this._currentTab === tab;
};
// Return the current tab
ViewManager.prototype.getCurrentTab = function _getCurrentTab() {
return this._currentTab;
};
function parseQueryParams(queryParams) {
var params = {};
queryParams = (queryParams || '').split('&');
queryParams.forEach(function(param) {
if (!param) { return; }
var pair = param.split('=');
var key = pair[0];
var value = pair[1];
if (params[key]) {
if (!Array.isArray(params[key])) {
params[key] = [params[key]];
}
params[key].push(value);
return;
}
params[key] = value;
});
return params;
}
return ViewManager;
}());