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,111 @@
/* global LockScreenBasicComponent, LockScreenClockWidgetSetup, mozIntl */
'use strict';
/**
* The Clock widget on LockScreen.
* Clock widget states:
* ClockSetup, ClockTick, ClockStop
**/
(function(exports) {
var LockScreenClockWidget = function() {
LockScreenBasicComponent.apply(this);
this.resources.elements.time = 'lockscreen-clock-time';
this.resources.elements.date = 'lockscreen-date';
this.resources.elements.alarm = 'lockscreen-alarm';
this.resources.elements.alarmtime = 'lockscreen-alarm-time';
this.timeFormatter = null;
this.dateFormatter = null;
this.configs.logger.debug = false; // turn on this when we're debugging
};
LockScreenClockWidget.prototype =
Object.create(LockScreenBasicComponent.prototype);
LockScreenClockWidget.prototype.setup = function() {
return (new LockScreenClockWidgetSetup(this));
};
LockScreenClockWidget.prototype.updateFormatters = function() {
this.dateFormatter = Intl.DateTimeFormat(navigator.languages, {
weekday: 'long',
month: 'long',
day: 'numeric'
});
// we're using mozIntl.DateTimeFormat to remove dayperiod
this.timeFormatter = mozIntl.DateTimeFormat(navigator.languages, {
hour12: navigator.mozHour12,
dayperiod: false,
hour: 'numeric',
minute: 'numeric'
});
};
LockScreenClockWidget.prototype.updateClock =
function() {
var now = new Date();
var timeText = this.timeFormatter.format(now);
var dateText = this.dateFormatter.format(now);
this.resources.elements.time.firstChild.data = timeText;
this.resources.elements.date.firstChild.data = dateText;
this.logger.debug('Clock updated', now);
};
LockScreenClockWidget.prototype.updateAlarm =
function() {
this.fetchAlarmData()
.then((alarmData) => {
// if there is no alarm
if(!alarmData) {
this.resources.elements.alarm.classList.add('no-alarms');
this.resources.elements.alarm.classList.remove('has-alarm');
return;
}
var type = 'AM',
hour = parseInt(alarmData.hour, 10);
// Decide wheter to use AM or PM
if(hour > 12) {
type = 'PM';
hour = hour - 12;
}
var fullAlarmTime = hour + ':' + alarmData.minute + type;
this.resources.elements.alarmtime.textContent = fullAlarmTime;
this.resources.elements.alarm.classList.remove('no-alarms');
this.resources.elements.alarm.classList.add('has-alarm');
this.logger.debug('Alarm updated to :', fullAlarmTime);
}).catch(function(e){
console.error('Error occured while alarm info on lockscreen : ', e);
throw(e);
});
};
/*
* Gets the Alarm Data from the DataStore.
*/
LockScreenClockWidget.prototype.fetchAlarmData = function() {
return navigator.getDataStores('alarms')
.then((stores) => {
return [stores[0].getLength(), stores[0]];
}).then(([len, store]) => {
if(0 === len) {
return;
}
return store.get(1);
}).then((fetchedData = {}) => {
if(0 === Object.keys(fetchedData).length) {
return null;
}
return fetchedData;
}).catch(function(e){
console.error('Error occured while getting alarm data : ', e);
throw(e);
});
};
exports.LockScreenClockWidget = LockScreenClockWidget;
})(window);

View file

@ -0,0 +1,62 @@
/* global DOMEventSource */
/* global LockScreenBasicState */
/* global LockScreenClockWidgetTick */
'use strict';
/**
* Setup state would initialize all resources and properties the
* component has.
*
* This is only a initialization state, and would immediately
* transfer to the starting state.
*
* Initialization state should be the only one state which isn't
* reentrant. Other states by default should be reentrant.
**/
(function(exports) {
var LockScreenClockWidgetSetup = function(component) {
LockScreenBasicState.apply(this, arguments);
this.configs.name = 'LockScreenClockWidgetSetup';
// Just to prevent stream without stream would throw error.
this.configs.stream.sources = [ new DOMEventSource({}) ];
};
LockScreenClockWidgetSetup.prototype =
Object.create(LockScreenBasicState.prototype);
LockScreenClockWidgetSetup.prototype.start = function() {
return LockScreenBasicState.prototype.start.call(this)
.next(this.queryElements.bind(this))
.next(this.component.updateFormatters.bind(this.component))
.next(this.component.updateClock.bind(this.component))
.next(this.component.updateAlarm.bind(this.component))
.next(this.transferToTick.bind(this));
};
LockScreenClockWidgetSetup.prototype.transferToTick = function() {
return this.transferTo(LockScreenClockWidgetTick);
};
LockScreenClockWidgetSetup.prototype.queryElements = function() {
var elements = this.component.resources.elements;
for (var key in elements) {
if ('string' === typeof elements[key]) {
var query = elements[key];
var result = document.getElementById(query);
if (!result) {
throw new Error(`Can't query element ${key} with query: ${query}`);
}
// Create a text node so we can update its data later, otherwise if we
// change textContent it will remove and insert a new text node, which
// could cause flickering if the docshell still has isActive false.
if (!result.firstChild) {
result.appendChild(document.createTextNode(''));
}
elements[key] = result;
}
}
};
exports.LockScreenClockWidgetSetup = LockScreenClockWidgetSetup;
})(window);

View file

@ -0,0 +1,58 @@
/* global Stream, DOMEventSource */
/* global LockScreenClockWidgetTick, LockScreenBasicState */
'use strict';
/***/
(function(exports) {
var LockScreenClockWidgetSuspend = function(component) {
LockScreenBasicState.apply(this, arguments);
this.configs.name = 'LockScreenClockWidgetSuspend';
this.configs.stream.interrupts = [
'screenchange',
];
this.configs.stream.sources =
[new DOMEventSource({events: ['screenchange']})];
this.handleSourceEvent = this.handleSourceEvent.bind(this);
};
LockScreenClockWidgetSuspend.prototype =
Object.create(LockScreenBasicState.prototype);
LockScreenClockWidgetSuspend.prototype.start = function() {
this.stream = new Stream(this.configs.stream);
return this.stream.start(this.handleSourceEvent)
.next(this.stream.ready.bind(this.stream));
};
LockScreenClockWidgetSuspend.prototype.stop =
function() {
return LockScreenBasicState.prototype.stop.call(this);
};
LockScreenClockWidgetSuspend.prototype.handleSourceEvent =
function(evt) {
switch (evt.type) {
case 'screenchange':
if (evt.detail.screenEnabled) {
// Bug 1234731 mentioned that if we update clock in tick,
// asynchronous step means it will be queued after other incidents
// at the moment screen get light up (ex: ril events in Gecko),
// so there is a visual lag that we need to deal with.
//
// The solution is we update the clock before we transfer to the
// Tick state, so that the first painting will be earlier, and using
// another entry in tick to transfer to, so that we can avoid
// calling the function again in the Tick state.
this.component.updateClock();
return this.transferToTick();
}
}
};
LockScreenClockWidgetSuspend.prototype.transferToTick =
function() {
this.component.transferTo(LockScreenClockWidgetTick);
};
exports.LockScreenClockWidgetSuspend = LockScreenClockWidgetSuspend;
})(window);

View file

@ -0,0 +1,101 @@
/* global Stream, DOMEventSource, MinuteClockSource */
/* global LockScreenClockWidgetSuspend, LockScreenBasicState */
'use strict';
/***/
(function(exports) {
var LockScreenClockWidgetTick = function(component) {
LockScreenBasicState.apply(this, arguments);
this.configs.name = 'LockScreenClockWidgetTick';
this.configs.stream.events = [
'ftudone',
'moztimechange',
'lockscreen-notification-clock-tick'
];
this.configs.stream.interrupts = [
'screenchange'
];
this.configs.stream.sources =
[new DOMEventSource({events: [
'screenchange',
'ftudone',
'moztimechange',
'screenchange',
'lockscreen-notification-clock-tick'
]}),
new MinuteClockSource({
'type': 'lockscreen-notification-clock-tick'
})
];
this.handleSourceEvent = this.handleSourceEvent.bind(this);
};
LockScreenClockWidgetTick.prototype =
Object.create(LockScreenBasicState.prototype);
/**
* Note:
* Due to performance issue we actually forked the start method to two,
* the first one, with previous state is Setup, means it's from the widget
* initialization, and need a full warming up before we call the clock
* updating function; the second one, because of Bug 1234731, will update
* the clock in the Suspend state in prior to this state, so we shouldn't
* call it here again.
*
* In fact, a state diagram conscious solution is to split one common Tick
* state into two "TickAfterSetup" and "TickFromSuspend" states.
* However, this is too rigid and verbosed, so that although we concern about
* the growth of code may soon mix the complicated statements up, we may
* treat the argument and branch as the threshold. If we trick the start
* method more than this case, we should immediately reconsider to split the
* state.
*/
LockScreenClockWidgetTick.prototype.start = function() {
if ('LockScreenClockWidgetSetup' !==
this.component._previousState.configs.name) {
return this.restart();
}
this.stream = new Stream(this.configs.stream);
return this.stream.start(this.handleSourceEvent)
.next(this.component.updateFormatters.bind(this.component))
.next(this.component.updateClock.bind(this.component))
.next(this.stream.ready.bind(this.stream));
};
LockScreenClockWidgetTick.prototype.restart = function() {
this.stream = new Stream(this.configs.stream);
return this.stream.start(this.handleSourceEvent)
.next(this.stream.ready.bind(this.stream));
};
LockScreenClockWidgetTick.prototype.stop =
function() {
return LockScreenBasicState.prototype.stop.call(this);
};
LockScreenClockWidgetTick.prototype.handleSourceEvent =
function(evt) {
switch (evt.type) {
case 'moztimechange':
this.component.updateFormatters();
this.component.updateClock();
break;
case 'ftudone':
case 'lockscreen-notification-clock-tick':
this.component.updateClock();
break;
case 'screenchange':
if (!evt.detail.screenEnabled) {
return this.transferToSuspend();
}
break;
}
};
LockScreenClockWidgetTick.prototype.transferToSuspend = function() {
this.component.transferTo(LockScreenClockWidgetSuspend);
};
exports.LockScreenClockWidgetTick = LockScreenClockWidgetTick;
})(window);