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,229 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- /
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
'use strict';
/* global applications */
/* global AppWindow */
/* global AppInstallManager */
/* global AppInstallDialogs */
/* global BookmarkManager */
/* global SystemBanner */
(function(exports) {
const PREVIEW_OPENED_TIMES_KEY = 'preview-opened-times';
const PREVIEW_OPENED_TIMES_TO_HINT = 3;
const ADD_TO_APPS_ICON_PATH = '/style/icons/add_to_apps.png';
/**
* This window inherited AppWindow and altered some properties of the later.
*
* @constructor PreviewWindow
* @augments AppWindow
*/
var PreviewWindow = function(configs) {
if (configs && configs.rearWindow) {
// Render inside its opener.
this.container = configs.rearWindow;
}
this.isAppLike = !configs.manifestURL;
this.identity = configs.manifestURL || configs.url;
this.features = configs.features || {};
this.systemBanner = new SystemBanner();
configs.chrome = {
scrollable: false
};
AppWindow.call(this, configs);
if (this.features.name) {
this.name = this.features.name;
}
this.iframe.focus();
this.container.element.addEventListener('_closed', this);
this.element.addEventListener('_opened', this);
this.element.addEventListener('_willdestroy', this);
};
/**
* @borrows AppWindow.prototype as PreviewWindow.prototype
* @memberof PreviewWindow
*/
PreviewWindow.prototype = Object.create(AppWindow.prototype);
PreviewWindow.REGISTERED_EVENTS =
['mozbrowserclose', 'mozbrowsererror', 'mozbrowservisibilitychange',
'mozbrowserloadend', 'mozbrowseractivitydone', 'mozbrowserloadstart',
'mozbrowsertitlechange', 'mozbrowserlocationchange',
'mozbrowsericonchange'];
PreviewWindow.SUB_COMPONENTS = {
'transitionController': window.AppTransitionController,
'modalDialog': window.AppModalDialog,
'valueSelector': window.ValueSelector,
'authDialog': window.AppAuthenticationDialog,
'contextmenu': window.BrowserContextMenu,
'childWindowFactory': window.ChildWindowFactory
};
/**
* We would maintain our own events by other components.
*
* @type String
* @memberof PreviewWindow
*/
PreviewWindow.prototype.eventPrefix = 'preview';
PreviewWindow.prototype._DEBUG = false;
PreviewWindow.prototype.CLASS_NAME = 'PreviewWindow';
PreviewWindow.prototype.CLASS_LIST = 'appWindow previewWindow';
PreviewWindow.prototype.openAnimation = 'fade-in';
PreviewWindow.prototype.closeAnimation = 'fade-out';
PreviewWindow.prototype.requestOpen = function() {
this.open();
};
PreviewWindow.prototype.requestClose = function() {
this.close();
};
PreviewWindow.prototype.isFocusable = function() {
return this.isVisible();
};
PreviewWindow.prototype._handle_back = function(evt) {
if (document.activeElement !== this.iframe) {
return;
}
if (this.config.url.startsWith('app://')) {
this.kill();
} else {
var goBackReq = this.iframe.getCanGoBack();
goBackReq.onsuccess = () => {
if (goBackReq.result) {
this.iframe.goBack();
} else {
this.kill();
}
};
goBackReq.onerror = () => {
this.kill();
};
}
};
PreviewWindow.prototype._handle__opened = function(evt) {
var previewOpenedTimes =
JSON.parse(localStorage.getItem(PREVIEW_OPENED_TIMES_KEY) || '{}');
if (!previewOpenedTimes[this.identity]) {
previewOpenedTimes[this.identity] = 0;
}
previewOpenedTimes[this.identity]++;
localStorage.setItem(PREVIEW_OPENED_TIMES_KEY,
JSON.stringify(previewOpenedTimes));
var showPreviewHint = function() {
window.interactiveNotifications.showNotification(
window.InteractiveNotifications.TYPE.NORMAL, {
title: {
id: 'preview-app-hint'
},
text: {
id: 'add-to-apps'
},
icon: ADD_TO_APPS_ICON_PATH
});
};
if (this.isWebsite) {
BookmarkManager.get(this.identity).then((bookmark) => {
if (!bookmark) {
showPreviewHint();
}
});
} else if (!AppInstallManager.getAppAddedState(this.manifestURL)) {
showPreviewHint();
}
};
PreviewWindow.prototype._handle__willdestroy = function(evt) {
this.container.element.removeEventListener('_closed', this);
var previewOpenedTimes =
JSON.parse(localStorage.getItem(PREVIEW_OPENED_TIMES_KEY) || '{}');
var needPrompt =
previewOpenedTimes[this.identity] == PREVIEW_OPENED_TIMES_TO_HINT;
var options;
if (this.isAppLike) {
if (needPrompt) {
BookmarkManager.get(this.identity).then((bookmark) => {
if (!bookmark) {
options = {
manifest: {
name: this.features.name
}
};
AppInstallManager.appInstallDialogs
.show(AppInstallDialogs.TYPES.AddAppDialog, options)
.then(() => {
return BookmarkManager.add({
name: this.features.name,
url: this.identity,
iconUrl: this.features.iconUrl
});
})
.then(() => {
this.systemBanner.show({
id: 'added-to-apps',
args: {
appName: this.features.name
}
});
});
}
});
}
} else {
if (needPrompt && !AppInstallManager.getAppAddedState(this.manifestURL)) {
var app = applications.getByManifestURL(this.manifestURL);
options = {
manifest: app.manifest
};
var onFulfilled = AppInstallManager.handleAddAppToApps
.bind(AppInstallManager, app);
var onRejected = AppInstallManager.uninstallPreviewApp
.bind(AppInstallManager);
AppInstallManager.appInstallDialogs
.show(AppInstallDialogs.TYPES.AddAppDialog, options)
.then(onFulfilled, onRejected);
} else {
AppInstallManager.uninstallPreviewApp();
}
}
};
// This handler is triggered by "this.container.element".
PreviewWindow.prototype._handle__closed = function(evt) {
// kill itself when the parent app intends to close.
this.kill();
};
/**
* @exports PreviewWindow
*/
exports.PreviewWindow = PreviewWindow;
})(window);