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,301 @@
/**
* KeyboardContext provides installed keyboard apps and enabled keyboard layouts
* in terms of ObservableArrays. It listens to the events from KeyboardHelper
* and update the ObservableArrays.
* KeyboardHelper helps on the following things:
* - Get all installed keyboard apps and layouts.
* - Enable or disable keyboard layouts.
* - Notify keyboard layout changes via the 'keyboardsrefresh' event.
* KeyboardContext handles only data and does not involve in any UI logic.
*
* @module KeyboardContext
*/
define(function(require) {
'use strict';
var Observable = require('modules/mvvm/observable');
var ObservableArray = require('modules/mvvm/observable_array');
var KeyboardHelper = require('shared/keyboard_helper');
var ManifestHelper = require('shared/manifest_helper');
// stores layout indexed by app manifestURL and layoutId
var _layoutDict = null;
var _keyboards = ObservableArray([]);
var _enabledLayouts = ObservableArray([]);
var _isReady = false;
var _parsingApps = false;
var _callbacks = [];
var _defaultEnabledCallbacks = [];
/**
* @alias module:Keyboard
* @class Keyboard
* @param {String} name
The name of the keyboard.
* @param {String} description
The description of the keyboard.
* @param {String} launchPath
The launch path of the keyboard.
* @param {Array} layouts
All layouts included in the keyboard.
* @param {DOMApplication} app
The keyboard app object.
* @returns {Keyboard}
*/
var Keyboard = function(name, description, launchPath, layouts, app) {
var _observable = Observable({
name: name,
description: description,
launchPath: launchPath,
layouts: layouts,
app: app
});
return _observable;
};
/**
* @alias module:Layout
* @class Layout
* @param {Object} Contain the following properties
* - id
The id of the layout.
* - appName
The name of the keyboard app containing the layout.
* - appManifestURL
The manifest url of the keyboard app containing
the layout.
* - name
The name of the layout.
* - nameL10nId
The l10n id of the layout name.
* - description
The description of the layout.
* - types
The supported input types of the layout.
* - enabled
The value indicating if the layout is enabled or not.
* @returns {Layout}
*/
var Layout = function(options) {
var _observable = Observable({
id: options.id,
appName: options.appName,
name: options.name,
nameL10nId: options.nameL10nId,
description: options.description,
types: options.types,
enabled: options.enabled
});
// Layout enabled changed.
_observable.observe('enabled', function(newValue, oldValue) {
if (!_parsingApps) {
KeyboardHelper.setLayoutEnabled(
options.appManifestURL, options.id, newValue);
// only check the defaults if we disabled a checkbox
if (!newValue) {
KeyboardHelper.checkDefaults(function(layouts, missingTypes) {
refreshEnabledLayouts(layouts);
notifyDefaultEnabled(layouts, missingTypes);
});
}
}
});
return _observable;
};
var _waitForLayouts;
function refreshEnabledLayouts(reEnabledLayouts) {
reEnabledLayouts.forEach(function(layout) {
var app = _layoutDict[layout.app.manifestURL];
if (app) {
app[layout.layoutId].enabled = true;
}
});
}
function notifyDefaultEnabled(layouts, missingTypes) {
_defaultEnabledCallbacks.forEach(function withCallbacks(callback) {
callback(layouts[0], missingTypes[0]);
});
}
function updateLayouts(layouts, reason) {
function mapLayout(layout) {
var app = _layoutDict[layout.app.manifestURL];
if (!app) {
app = _layoutDict[layout.app.manifestURL] = {};
}
if (app[layout.layoutId]) {
app[layout.layoutId].enabled = layout.enabled;
return app[layout.layoutId];
}
app[layout.layoutId] = Layout({
id: layout.layoutId,
appName: layout.manifest.name,
appManifestURL: layout.app.manifestURL,
name: layout.inputManifest.name,
nameL10nId: layout.inputManifest.nameL10nId,
description: layout.inputManifest.description,
types: layout.inputManifest.types,
enabled: layout.enabled});
return app[layout.layoutId];
}
function reduceApps(carry, layout) {
// if we already found this app, add it to the layouts
if (!carry.some(function checkApp(app) {
if (app.app === layout.app) {
app.layouts.push(mapLayout(layout));
return true;
}
})) {
carry.push({
app: layout.app,
manifest: layout.manifest,
layouts: [mapLayout(layout)]
});
}
return carry;
}
function mapKeyboard(app) {
return Keyboard(app.manifest.name, app.manifest.description,
app.manifest.launch_path, app.layouts, app.app);
}
_parsingApps = true;
// if we changed apps
if (reason.apps) {
// re parse every layout
_layoutDict = {};
var apps = layouts.reduce(reduceApps, []);
var keyboards = apps.map(mapKeyboard);
_keyboards.reset(keyboards);
}
var enabled = layouts.filter(function filterEnabled(layout) {
return layout.enabled;
}).map(mapLayout);
_enabledLayouts.reset(enabled);
_parsingApps = false;
if (_waitForLayouts) {
_waitForLayouts();
_waitForLayouts = undefined;
}
}
var _init = function(callback) {
document.addEventListener('DOMRetranslated', function() {
// refresh keyboard and layout in _keyboards
_keyboards.forEach(function(keyboard) {
var keyboardAppInstance = keyboard.app;
var keyboardManifest =
new ManifestHelper(keyboardAppInstance.manifest);
keyboard.name = keyboardManifest.name;
keyboard.description = keyboardManifest.description;
keyboard.layouts.forEach(function(layout) {
layout.appName = keyboardManifest.name;
});
});
});
_waitForLayouts = callback;
KeyboardHelper.stopWatching();
KeyboardHelper.watchLayouts(updateLayouts);
};
var _ready = function(callback) {
if (!callback) {
return;
}
if (_isReady) {
callback();
} else {
_callbacks.push(callback);
}
};
return {
/**
* Reset the keyboard context. It clears all cached data of installed
* keyboards and current enabled layouts.
*
* @alias module:KeyboardContext#reset
*/
reset: function kc_reset() {
_layoutDict = null;
_keyboards = ObservableArray([]);
_enabledLayouts = ObservableArray([]);
_isReady = false;
_parsingApps = false;
_callbacks = [];
_defaultEnabledCallbacks = [];
},
/**
* Initialize the keyboard context. After the context initialized, we are
* able to get the installed keyboards and enabled layouts.
*
* @alias module:KeyboardContext#init
* @param {Function} callback
* The callback when the context is initialized.
*/
init: function kc_init(callback) {
_defaultEnabledCallbacks = [];
_isReady = false;
_init(function() {
_isReady = true;
_callbacks.forEach(function(callback) {
callback();
});
});
_ready(callback);
},
/**
* Get the installed keyboards in terms of an observable array.
*
* @alias module:KeyboardContext#keyboards
* @param {Function} callback
* The result is passed to the callback when ready.
*/
keyboards: function kc_keyboards(callback) {
_ready(function() {
callback(_keyboards);
});
},
/**
* Get the enabled layouts in terms of an observable array.
*
* @alias module:KeyboardContext#enabledLayouts
* @param {Function} callback
* The result is passed to the callback when ready.
*/
enabledLayouts: function kc_enabledLayouts(callback) {
_ready(function() {
callback(_enabledLayouts);
});
},
/**
* Add a callback to be triggered when the default keyboard is enabled.
*
* @alias module:KeyboardContext#defaultKeyboardEnabled
* @param {Function} callback
* The callback to be triggered.
*/
defaultKeyboardEnabled: function kc_defaultKeyboardEnabled(callback) {
_defaultEnabledCallbacks.push(callback);
}
};
});