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

24
gaia/tv_apps/tv-ftu/bower.json Executable file
View file

@ -0,0 +1,24 @@
{
"name": "TV FTU",
"version": "0.0.0",
"homepage": "https://github.com/mozilla-b2g/gaia/tree/master/tv_apps/tv-ftu",
"authors": [
"Fischer Liu <fliu@mozilla.com>"
],
"description": "TV FTU",
"main": "index.html",
"license": "MPL",
"private": true,
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"dependencies": {
"evt": "fxos-components/evt#~0.4.0",
"smart-button": "fxos-components/smart-button",
"smart-icons": "smart-components/smart-icons"
}
}

View file

@ -0,0 +1,28 @@
{
"name": "evt",
"main": "index.js",
"version": "0.4.0",
"homepage": "https://github.com/wilsonpage/evt",
"authors": [
"Wilson Page <wilsonpage@me.com>"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"package.json",
"test",
"tests",
"README.md"
],
"_release": "0.4.0",
"_resolution": {
"type": "version",
"tag": "v0.4.0",
"commit": "3593dd6b4dd19f683d00fd0eaf2581c11a128da6"
},
"_source": "git://github.com/gaia-components/evt.git",
"_target": "~0.4.0",
"_originalSource": "gaia-components/evt"
}

View file

@ -0,0 +1,19 @@
{
"name": "evt",
"main": "index.js",
"version": "0.4.0",
"homepage": "https://github.com/wilsonpage/evt",
"authors": [
"Wilson Page <wilsonpage@me.com>"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"package.json",
"test",
"tests",
"README.md"
]
}

View file

@ -0,0 +1,154 @@
/**
* Evt
*
* A super lightweight
* event emitter library.
*
* @version 0.3.3
* @author Wilson Page <wilson.page@me.com>
*/
;(function() {
/**
* Locals
*/
var proto = Events.prototype;
var slice = [].slice;
/**
* Creates a new event emitter
* instance, or if passed an
* object, mixes the event logic
* into it.
*
* @param {Object} obj
* @return {Object}
*/
function Events(obj) {
if (!(this instanceof Events)) return new Events(obj);
if (obj) return mixin(obj, proto);
}
/**
* Registers a callback
* with an event name.
*
* @param {String} name
* @param {Function} cb
* @return {Event}
*/
proto.on = function(name, cb) {
this._cbs = this._cbs || {};
(this._cbs[name] || (this._cbs[name] = [])).push(cb);
return this;
};
/**
* Attach a callback that once
* called, detaches itself.
*
* TODO: Implement `.off()` to work
* with `once()` callbacks.
*
* @param {String} name
* @param {Function} cb
* @public
*/
proto.once = function(name, cb) {
this.on(name, one);
function one() {
cb.apply(this, arguments);
this.off(name, one);
}
};
/**
* Removes a single callback,
* or all callbacks associated
* with the passed event name.
*
* @param {String} name
* @param {Function} cb
* @return {Event}
*/
proto.off = function(name, cb) {
this._cbs = this._cbs || {};
if (!name) { this._cbs = {}; return; }
if (!cb) { return delete this._cbs[name]; }
var cbs = this._cbs[name] || [];
var i;
while (cbs && ~(i = cbs.indexOf(cb))) { cbs.splice(i, 1); }
return this;
};
/**
* Fires an event, triggering
* all callbacks registered on this
* event name.
*
* @param {String} name
* @return {Event}
*/
proto.fire = proto.emit = function(options) {
var cbs = this._cbs = this._cbs || {};
var name = options.name || options;
var batch = (cbs[name] || []).concat(cbs['*'] || []);
var ctx = options.ctx || this;
if (batch.length) {
this._fireArgs = arguments;
var args = slice.call(arguments, 1);
while (batch.length) {
batch.shift().apply(ctx, args);
}
}
return this;
};
proto.firer = function(name) {
var self = this;
return function() {
var args = slice.call(arguments);
args.unshift(name);
self.fire.apply(self, args);
};
};
/**
* Util
*/
/**
* Mixes in the properties
* of the second object into
* the first.
*
* @param {Object} a
* @param {Object} b
* @return {Object}
*/
function mixin(a, b) {
for (var key in b) a[key] = b[key];
return a;
}
/**
* Expose 'Event' (UMD)
*/
if (typeof exports === 'object') {
module.exports = Events;
} else if (typeof define === 'function' && define.amd) {
define(function(){ return Events; });
} else {
window.evt = Events;
}
})();

View file

@ -0,0 +1,26 @@
{
"name": "smart-button",
"version": "0.0.2",
"homepage": "https://github.com/gaia-components/smart-button",
"main": "script.js",
"license": "MPL",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests",
"examples",
"LICENSE",
"README.md"
],
"_release": "0.0.2",
"_resolution": {
"type": "version",
"tag": "v0.0.2",
"commit": "04fdae935e2f2ba99d1c4f3e156d17f12eb2d142"
},
"_source": "git://github.com/gaia-components/smart-button.git",
"_target": "*",
"_originalSource": "gaia-components/smart-button"
}

View file

@ -0,0 +1,17 @@
{
"name": "smart-button",
"version": "0.0.2",
"homepage": "https://github.com/gaia-components/smart-button",
"main": "script.js",
"license": "MPL",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests",
"examples",
"LICENSE",
"README.md"
]
}

View file

@ -0,0 +1,62 @@
'use strict';
/* global KeyEvent */
window.SmartButton = (function(win) {
// Extend from the HTMLButtonElement prototype
var proto = Object.create(HTMLButtonElement.prototype);
proto.createdCallback = function() {
this.addEventListener('mousedown', this);
this.addEventListener('mouseup', this);
this.addEventListener('touchstart', this);
this.addEventListener('touchend', this);
this.addEventListener('keydown', this);
this.addEventListener('keyup', this);
this.addEventListener('focus', this);
this.addEventListener('blur', this);
this.addEventListener('transitionend', this);
this.tabIndex = 0;
};
proto.handleEvent = function(evt) {
switch(evt.type) {
case 'mousedown':
case 'touchstart':
this.classList.add('pressed');
break;
case 'keydown':
if (evt.keyCode === KeyEvent.DOM_VK_RETURN) {
this.classList.add('pressed');
}
break;
case 'mouseup':
case 'touchend':
this.classList.remove('pressed');
this.classList.add('released');
break;
case 'keyup':
if (evt.keyCode === KeyEvent.DOM_VK_RETURN) {
this.classList.remove('pressed');
this.classList.add('released');
this.click();
}
break;
case 'transitionend':
if (this.classList.contains('released')) {
this.classList.remove('released');
}
break;
case 'focus':
this.classList.add('focused');
break;
case 'blur':
this.classList.remove('pressed');
this.classList.remove('released');
this.classList.remove('focused');
break;
}
};
// Register and return the constructor
return document.registerElement('smart-button', { prototype: proto });
})(window);

View file

@ -0,0 +1,497 @@
/**
* Button state:
* 1. normal
* In this state, we don't add any class.
* 2. focused (class name: focused)
* The focused state may be triggered by keyboard or touch/mouse.
* 3. pressed (class name: pressed)
* This state is triggered by user pressed confirm button, mousedown,
* and touchdown.
* 4. released (class name: released)
* This state is only for changing duration of transition. We enter this
* state when user release the button. After transitionend, we goes back
* to focused state.
**/
smart-button {
font-family: "Fira Sans";
display: inline-block;
width: 8rem;
height: 8rem;
/* we need to set border to none to remove the button border */
border: none;
/* the radius is still make button as round even if we don't have border */
border-radius: 50%;
/* 50% is not a real circle because of rounding, we have to use a value larger
than 50% */
-moz-outline-radius: 60%;
outline: transparent 0 solid;
background-color: rgba(0, 0, 0, 0.5);
background-repeat: no-repeat;
background-size: 5.4rem auto;
background-position: center center;
font-style: italic;
transition-property: all;
transition-timing-function: cubic-bezier(0.25, 0, 0, 1.0);
transition-duration: 0.42s;
}
smart-button.focused {
outline: 0;
background-color: #ffffff;
transform: scale(1.2);
transition-duration: 0.42s;
}
smart-button.released {
transition-duration: 0.16s;
}
smart-button.toggled {
background-color: #00caf2;
}
smart-button.pressed {
background-color: #00caf2;
transform: scale(0.8);
transition-duration: 0.06s;
}
smart-button.disabled {
background-color: rgba(0, 0, 0, 0.5);
}
smart-button[data-icon]:before {
width: 5.4rem;
left: 1.3rem;
font-size: 5.4rem;
line-height: 8rem;
text-align: center;
color: #ffffff;
white-space: normal;
top: 0;
position: absolute;
}
smart-button[data-icon].focused:before {
color: #2d2d2d;
}
smart-button[data-icon].toggled:before {
color: #00caf2;
}
smart-button[data-icon].pressed:before {
color: #ffffff;
}
smart-button[data-icon].disabled:before {
color: #ffffff;
opacity: 0.3;
}
/**
* Simple Text Button
**/
smart-button[type="simple-text"] {
color: #dddddd;
background: none;
border: none;
border-radius: 0;
width: auto;
height: 8rem;
line-height: 8rem;
font-size: 2.4rem;
-moz-user-select: none;
padding-left: 2.6rem;
padding-right: 2.6rem;
}
smart-button[type="simple-text"].focused {
color: #ffffff;
background: none;
}
smart-button[type="simple-text"].toggled {
color: #00caf2;
}
smart-button[type="simple-text"].pressed {
color: #00caf2;
background: none;
}
/**
* End of Simple Text Button
**/
/**
* underlined text button
*/
smart-button[type="underlined-text"] {
position: relative;
color: white;
font-size: 2.4rem;
padding-left: 3.8rem;
padding-right: 3.8rem;
border-radius: 4rem;
width: auto;
line-height: 8rem;
margin-right: 1.4rem;
overflow: hidden;
}
smart-button[type="underlined-text"]:after {
position: absolute;
width: 100%;
height: 100%;
left: 0;
content: ' ';
border-bottom: 0.6rem #61acd7 solid;
box-sizing: border-box;
}
smart-button[type="underlined-text"].focused {
transform: scale(1.2);
color: #2d2d2d;
}
smart-button[type="underlined-text"].pressed {
transform: scale(1);
color: white;
background-color: #00caf2;
}
/**
* End of underlined text button
*/
/**
* App Icons
**/
smart-button[type="app-button"] {
/* To use 33.4rem instead of to use 33.6rem is to work around the anti-alias
pixel. So, the circle is filled by the background almost totally. */
width: 33.4rem;
height: 33.4rem;
position: relative;
overflow: hidden;
background-color: transparent;
}
smart-button[type="app-button"].focused {
transform: scale(1.4);
/* To use outline will not change the size of button and make the whole button
thrilling. */
outline: 0.8rem solid #ffffff;
}
smart-button[type="app-button"].pressed {
/* While scaling, we may have a gap between outline and icon which may be
anti-alias pixel. So, we use scale(1.22) to prevent such kind of case */
transform: scale(1.22);
/* To use outline will not change the size of button and make the whole button
thrilling. */
outline: 1.0rem solid #ffffff;
}
smart-button[type="app-button"].fullsized {
background-size: 33.6rem auto;
}
smart-button[type="app-button"].fitted {
background-size: 22rem auto;
}
/** we use :after as label */
smart-button[type="app-button"]:after {
content: attr(label);
position: absolute;
bottom: 0;
left: auto;
right: auto;
width: 33.6rem;
height: 8rem;
padding-top: 1rem;
line-height: 3rem;
text-align: center;
font-size: 2.8rem;
font-style: italic;
color: #ffffff;
}
/**
* text backgorund color
**/
smart-button[type="app-button"][app-type="deck"]:after {
background-color: transparent;
}
smart-button[type="app-button"][app-type="tv"]:after {
background-color: #d90c83;
}
smart-button[type="app-button"][app-type="app"]:after {
background-color: rgba(0, 0, 0, 0.4);
}
smart-button[type="app-button"][app-type="device"]:after {
background-color: #4a82ea;
}
smart-button[type="app-button"][app-type="folder"] {
background-color: #595959;
}
smart-button[type="app-button"]:before {
left: 0;
line-height: 30rem;
font-size: 16rem;
width: 100%;
}
smart-button[type="app-button"][app-type="folder"]:before {
color: #CCCCCC;
}
/**
* End of App Icons
**/
/**
* text and icon button
*/
smart-button[type="text-and-icon"] {
position: relative;
color: white;
font-size: 2.4rem;
padding-left: 4.6rem;
padding-right: 4.6rem;
border-radius: 4rem;
width: auto;
line-height: 8rem;
margin-right: 1.4rem;
overflow: hidden;
}
smart-button[type="text-and-icon"][data-icon] {
padding-left: 9.6rem;
}
smart-button[type="text-and-icon"][data-icon]:before {
left: 3.8rem;
}
smart-button[type="text-and-icon"].focused {
transform: scale(1.2);
color: #2d2d2d;
}
smart-button[type="text-and-icon"].pressed {
transform: scale(1);
color: white;
background-color: #00caf2;
}
/**
* End of text and icon button
*/
/**
* banner button
**/
smart-button[type="banner-button"] {
position: relative;
color: #ffffff;
font-size: 2rem;
width: 36rem;
height: 20rem;
overflow: hidden;
border-radius: 0;
border: 0 solid #ffffff;
background-color: #5f5f5f;
background-repeat: no-repeat;
background-size: 120%;
box-sizing: border-box;
transition-property: all;
transition-timing-function: cubic-bezier(0.25, 0, 0.5, 1.0);
transition-duration: 0.1s;
}
smart-button[type="banner-button"][label]:before {
content: attr(label);
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 5rem;
line-height: 5rem;
text-align: center;
background-color: rgba(0, 0, 0, 0.4);
}
smart-button[type="banner-button"]:after {
content: " ";
position: absolute;
bottom: 0;
left: 0;
right: 0;
top: 0;
transition-property: all;
transition-timing-function: cubic-bezier(0.25, 0, 0, 1.0);
transition-duration: 0.06s;
background-color: rgba(255, 255, 255, 0);
}
smart-button[type="banner-button"].focused {
transform: none;
border-width: 1.2rem;
background-size: 100%;
transition-duration: 0.24s;
}
smart-button[type="banner-button"].pressed {
transform: scale(0.945, 0.9);
}
smart-button[type="banner-button"].pressed:after {
background-color: rgba(255, 255, 255, 0.5);
}
/**
* banner button
**/
/**
* circle text button
*/
smart-button[type="circle-text"] {
width: 21rem;
height: 21rem;
color: white;
background-color: #5f6368;
line-height: 21rem;
padding: 2.5rem 2rem 1.5rem 2rem;
text-align: center;
font-size: 3.2rem;
font-weight: bolder;
overflow: hidden;
transition-property: transform, color, background-color;
}
smart-button[type="circle-text"].focused {
transform: scale(1.2);
color: #2d2d2d;
background-color: white;
transition-property: transform, color, background-color;
}
smart-button[type="circle-text"].pressed {
transform: scale(1);
color: white;
background-color: #00caf2;
transition-property: transform, color, background-color;
}
smart-button[type="circle-text"].primary {
background-color: #00caf2;
transition-property: transform, color, background-color;
}
smart-button[type="circle-text"].primary.focused {
color: #ffffff;
background-color: #00caf2;
transition-property: transform, color, background-color;
}
smart-button[type="circle-text"].primary.pressed {
background-color: #0097b5;
transition-property: transform, color, background-color;
}
smart-button[type="circle-text"].danger {
background-color: #e63d2f;
transition-property: transform, color, background-color;
}
smart-button[type="circle-text"].danger.focused {
color: #ffffff;
background-color: #e63d2f;
transition-property: transform, color, background-color;
}
smart-button[type="circle-text"].danger.pressed {
background-color: #ac2e23;
transition-property: transform, color, background-color;
}
/**
* End of circle text button
*/
/**
* rounded-corner text button
*/
smart-button[type="rounded-corner-text"] {
-moz-user-select: none;
width: auto;
height: 8rem;
border-radius: 4rem;
background-color: #5f6368;
padding: 0 3.8rem;
line-height: 8rem;
color: white;
text-align: center;
font-size: 2.4rem;
overflow: hidden;
transition-property: transform, color, background-color;
}
smart-button[type="rounded-corner-text"].focused,
smart-button[type="rounded-corner-text"]:hover {
transform: scale(1.2);
color: #2d2d2d;
background-color: white;
}
smart-button[type="rounded-corner-text"].pressed {
transform: scale(1);
/*color: white;*/
background-color: #00caf2;
}
smart-button[type="rounded-corner-text"].primary {
background-color: #00caf2;
}
smart-button[type="rounded-corner-text"].primary:hover,
smart-button[type="rounded-corner-text"].primary.focused {
color: #ffffff;
background-color: #00caf2;
}
smart-button[type="rounded-corner-text"].primary.pressed {
background-color: #0097b5;
}
/**
* End of rounded-corner text button
*/

View file

@ -0,0 +1,30 @@
{
"name": "smart-icons",
"version": "0.0.3",
"homepage": "https://github.com/smart-components/smart-icons",
"description": "Icon font for smart-screen",
"license": "MPL",
"private": true,
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"templates",
"images",
"test",
"tests",
"index.html",
"Gruntfile.js",
"README.md",
"package.json"
],
"_release": "0.0.3",
"_resolution": {
"type": "version",
"tag": "v0.0.3",
"commit": "0c335ac23f484069b4fafa7b7e5afd9f3c08d66e"
},
"_source": "git://github.com/smart-components/smart-icons.git",
"_target": "*",
"_originalSource": "smart-components/smart-icons"
}

View file

@ -0,0 +1,21 @@
{
"name": "smart-icons",
"version": "0.0.3",
"homepage": "https://github.com/smart-components/smart-icons",
"description": "Icon font for smart-screen",
"license": "MPL",
"private": true,
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"templates",
"images",
"test",
"tests",
"index.html",
"Gruntfile.js",
"README.md",
"package.json"
]
}

Binary file not shown.

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,25 @@
/* Generated by grunt-webfont */
/* Based on https://github.com/endtwist/fontcustom/blob/master/lib/fontcustom/templates/fontcustom.css */
@font-face {
font-family: "smart-icons";
src: url("fonts/smart-icons.ttf") format("truetype");
font-weight: 500;
font-style: normal;
}
[data-icon]:before,
.ligature-icons {
font-family: "smart-icons";
content: attr(data-icon);
display: inline-block;
font-weight: 500;
font-style: normal;
text-decoration: inherit;
text-transform: none;
text-rendering: optimizeLegibility;
font-size: 30px;
-webkit-font-smoothing: antialiased;
}

64
gaia/tv_apps/tv-ftu/index.html Executable file
View file

@ -0,0 +1,64 @@
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1">
<meta charset="utf-8">
<title>FTU - App Usage Metrics</title>
<!-- stylesheets of building blocks -->
<link rel="stylesheet" type="text/css" href="bower_components/smart-icons/smart-icons.css">
<link rel="stylesheet" type="text/css" href="bower_components/smart-button/style.css">
<link rel="stylesheet" type="text/css" href="style/index.css">
<!-- building block -->
<script defer src="bower_components/evt/index.js"></script>
<script defer src="bower_components/smart-button/script.js"></script>
<!-- For test purpose on phone only -->
<script defer src="shared/js/gesture_detector.js"></script>
<script defer src="shared/js/smart-screen/init_gesture.js"></script>
<!-- shared libraries -->
<script defer src="shared/js/settings_listener.js"></script>
<script defer src="shared/js/smart-screen/simple_key_navigation.js"></script>
<script defer src="shared/js/smart-screen/key_navigation_adapter.js"></script>
<!-- main javascript code -->
<script defer src="js/tv_ftu.js"></script>
<!-- Shared L10n libraries -->
<script src="shared/js/l10n.js"></script>
<!-- L10n properties -->
<meta name="defaultLanguage" content="en-US">
<meta name="availableLanguages" content="en-US">
<link rel="localization" href="locales/ftu.{locale}.properties"/>
</head>
<body>
<article id="app-usage-slide" class="slide">
<section class="slide-section top">
<img id="app-usage-slide-logo" src="style/images/firefox_logo.png">
</section>
<section id="app-usage-terms-section" class="slide-section mid" tabindex="-1">
<div id="app-usage-terms">
<p id="app-usage-terms-title" class="slide-description txt-large txt-center" data-l10n-id="about-firefox-os"></p>
<p class="slide-description txt-mid" data-l10n-id="welcome-to-fx-os"></p>
<p class="slide-description txt-mid" data-l10n-id="mozilla-cares-privacy"></p>
<p class="slide-description txt-mid" data-l10n-id="initial-activation"></p>
<p class="slide-description txt-mid" data-l10n-id="app-usage"></p>
<p class="slide-description txt-mid" data-l10n-id="tv-is-created-by-several-parties"></p>
<p class="slide-description txt-mid txt-center" data-l10n-id="send-data"></p>
</div>
</section>
<section class="slide-section bottom">
<div id="app-usage-arrow-icon" data-icon="arrow-down"></div>
<smart-button id="app-usage-no-button" type="rounded-corner-text" data-l10n-id="no"></smart-button>
<smart-button id="app-usage-yes-button" class="primary" type="rounded-corner-text" data-l10n-id="yes"></smart-button>
</section>
</article>
</body>
</html>

View file

@ -0,0 +1,98 @@
/* global evt, SettingsListener, KeyNavigationAdapter, SimpleKeyNavigation */
(function (exports) {
'use strict';
window.addEventListener('load', function() {
var tvFTU = evt({
init: function () {
this.APP_USAGE_ENABLE_KEY = 'debug.performance_data.shared';
this.APP_USAGE_ENABLE_VALUE = true;
this.APP_USAGE_DISABLE_VALUE = false;
this._noButton =
document.getElementById('app-usage-no-button');
this._yesButton =
document.getElementById('app-usage-yes-button');
this._terms =
document.getElementById('app-usage-terms');
this._termsSection =
document.getElementById('app-usage-terms-section');
this._arrowIcon =
document.getElementById('app-usage-arrow-icon');
this.keyNavAdapter = new KeyNavigationAdapter();
this.keyNavAdapter.init();
this.keyNavAdapter.on('move', this.onKeyMove.bind(this));
this.keyNavAdapter.on('enter-keyup', this.onEnterKeyUp.bind(this));
this.buttonNav = new SimpleKeyNavigation();
this.buttonNav.start(
[this._noButton, this._yesButton],
SimpleKeyNavigation.DIRECTION.HORIZONTAL
);
this.buttonNav.on('focusChanged', (elem) => {
this.fire('focus', elem);
});
this.buttonNav.pause();
this._termsSection.focus();
this._currentFocused = this._termsSection;
this.on('focus', this.onFocus.bind(this));
},
onFocus: function (elem) {
this._currentFocused = elem;
},
onKeyMove: function (key) {
switch (key) {
case 'up':
if (this._currentFocused !== this._termsSection) {
this.buttonNav.blur();
this.buttonNav.pause();
this._termsSection.focus();
this.fire('focus', this._termsSection);
this._arrowIcon.classList.remove('hidden');
}
break;
case 'down':
if (this._currentFocused === this._termsSection) {
var unscrolledHeight = this._terms.clientHeight -
this._termsSection.scrollTop -
this._termsSection.clientHeight;
if (unscrolledHeight <= 0) {
this.buttonNav.resume();
this.buttonNav.focusOn(this._yesButton);
this._arrowIcon.classList.add('hidden');
}
}
break;
}
},
onEnterKeyUp: function () {
switch (this._currentFocused) {
case this._yesButton:
case this._noButton:
var setting = {};
if (this._currentFocused === this._yesButton) {
setting[this.APP_USAGE_ENABLE_KEY] = this.APP_USAGE_ENABLE_VALUE;
} else {
setting[this.APP_USAGE_ENABLE_KEY] = this.APP_USAGE_DISABLE_VALUE;
}
SettingsListener.getSettingsLock().set(setting);
window.close();
break;
}
}
});
tvFTU.init();
exports.tvFTU = tvFTU;
});
})(window);

View file

@ -0,0 +1,9 @@
no=No
yes=Yes
welcome-to-fx-os=Welcome to Firefox OS, the free and open source operating system from Mozilla. Our mission is to promote openness, innovation and opportunity by keeping the power of the Web in your hands.
mozilla-cares-privacy=Mozilla cares about your Privacy. When Firefox OS sends information to us, our Mozilla Privacy Policy describes how we handle that information.
initial-activation=Initial Activation: Upon initial activation of your Firefox OS device, Firefox OS sends to Mozilla a one-time data ping (e.g., data relating to device specific information such as software release version, partner ID, country and screen size) which helps Mozilla determine if security updates and critical fixes are needed for our users and partners, determine requirements for app developers so they can build better apps for our users, and helps Mozilla with market analysis (e.g., determine how many devices have been activated).
app-usage=App Usage: In order to improve content discovery on Firefox Marketplace, Firefox OS sends "Application Usage Information" (e.g., active use time, counts of opens/closes/crashes, list of uninstalled apps on Firefox OS devices) to Mozilla. You can disable the sharing of App Usage Information in the Firefox OS “Settings” app on your device.
tv-is-created-by-several-parties=The TV you are using is created by several parties. This notice only covers how Mozilla handles your information for official versions of Firefox OS authorized by Mozilla.
send-data=Send data to us?
about-firefox-os=About Firefox OS

View file

@ -0,0 +1,24 @@
{
"name": "TV FTU",
"description": "TV First Time Usage",
"launch_path": "/index.html",
"type": "certified",
"developer": {
"name": "The Gaia Team",
"url": "https://github.com/mozilla-b2g/gaia"
},
"locales": {
"en-US": {
"name": "TV FTU",
"description": "TV First Time Usage"
}
},
"icons": {
"336": "/style/icons/Blank.png"
},
"default_locale": "en-US",
"permissions": {
"settings":{ "access": "readwrite" },
"moz-extremely-unstable-and-will-change-webcomponents":{}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View file

@ -0,0 +1,123 @@
html {
font-size: 10px;
/* We have Fira Sans as default font in real device. But it isn't default in
* browser. That's the main reason this line is here.*/
font-family: "Fira Sans";
font-weight: 100;
font-style: italic;
}
html, body {
width: 100%;
height: 100%;
overflow: hidden;
margin: 0;
padding: 0;
background: #000;
}
body {
background: url('images/background.png');
}
.txt-mid {
font-size: 3.8rem;
}
.txt-large {
font-size: 7rem;
}
.txt-center {
text-align: center;
}
smart-button[type=rounded-corner-text] {
width: 23.7rem;
font-size: 2.4rem;
font-weight: normal;
}
.slide {
width: 100%;
height: 100%;
color: #fff;
position: fixed;
}
.slide-section {
position: absolute;
margin-right: -50%;
left: 50%;
transform: translate(-50%, 0px);
}
.slide-section.top {
top: 7.5rem;
}
.slide-section.mid {
width: 152rem;
height: 51rem;
top: 24rem;
overflow: hidden;
}
.slide-section.bottom {
bottom: 10.5rem;
}
.slide-description {
margin: 0;
margin-bottom: 6rem;
}
.slide-description:last-child {
margin-bottom: 0;
}
#app-usage-slide {
background: rgba(0, 0, 0, 0.3);
}
#app-usage-terms-section {
overflow: scroll;
}
#app-usage-terms-section:focus {
outline: none;
}
#app-usage-terms-title {
margin-bottom: 8rem;
}
#app-usage-slide-logo {
width: 15rem;
height: 15rem;
}
#app-usage-no-button {
margin-right: 1.8rem;
}
#app-usage-arrow-icon {
width: 6rem;
height: 6rem;
position: absolute;
margin-right: -50%;
bottom: 15rem;
left: 50%;
transform: translate(-50%, 0px);
opacity: 1;
transition: opacity 0.3s ease;
}
#app-usage-arrow-icon.hidden {
opacity: 0;
}
#app-usage-arrow-icon[data-icon]::before {
font-size: 6rem;
}

View file

@ -0,0 +1,14 @@
{
"extends": "../../../../.jshintrc",
"node": true,
"predef": [
"suite",
"test",
"setup",
"teardown",
"suiteSetup",
"suiteTeardown",
"marionette",
"marionetteScriptFinished"
]
}

View file

@ -0,0 +1,18 @@
{
"extends": "../../../../.jshintrc",
"predef": [
"assert",
"suite",
"test",
"setup",
"teardown",
"suiteSetup",
"suiteTeardown",
"require",
"requireApp",
"sinon",
"mocha",
"loadBodyHTML"
]
}