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

285
gaia/apps/calendar/js/bridge.js Executable file
View file

@ -0,0 +1,285 @@
define(function(require, exports) {
'use strict';
var EventEmitter2 = require('ext/eventemitter2');
var co = require('ext/co');
var core = require('core');
var dayObserver = require('day_observer');
var nextTick = require('common/next_tick');
var object = require('common/object');
/**
* Fetch all the data needed to display the busytime information on the event
* views based on the busytimeId
*/
exports.fetchRecord = function(busytimeId) {
return co(function *() {
var record = yield dayObserver.findAssociated(busytimeId);
var eventStore = core.storeFactory.get('Event');
var owners = yield eventStore.ownersOf(record.event);
var provider = core.providerFactory.get(owners.account.providerType);
var capabilities = yield provider.eventCapabilities(record.event);
record.calendar = owners.calendar;
record.account = owners.account;
record.capabilities = capabilities;
return record;
});
};
/**
* Fetch all the calendars from database and emits a new event every time the
* values changes.
*
* @returns {ClientStream}
*/
exports.observeCalendars = function() {
// TODO: replace with real threads.client.stream when we get db into worker
var stream = new FakeClientStream();
var calendarStore = core.storeFactory.get('Calendar');
var getAllAndWrite = co.wrap(function *() {
// calendarStore.all() returns an object! we convert into an array since
// that is easier to render/manipulate
var calendars = yield calendarStore.all();
var data = yield object.map(
calendars,
co.wrap(function *(id, calendar) {
var caps;
try {
var provider = yield calendarStore.providerFor(calendar);
caps = provider.calendarCapabilities(calendar);
} catch (error) {
console.error(error);
return false;
}
return { calendar: calendar, capabilities: caps };
})
);
stream.write(data.filter(element => !!element));
});
calendarStore.on('add', getAllAndWrite);
calendarStore.on('remove', getAllAndWrite);
calendarStore.on('update', getAllAndWrite);
stream.cancel = function() {
calendarStore.off('add', getAllAndWrite);
calendarStore.off('remove', getAllAndWrite);
calendarStore.off('update', getAllAndWrite);
stream._cancel();
};
nextTick(getAllAndWrite);
return stream;
};
exports.updateCalendar = function(calendar) {
var calendarStore = core.storeFactory.get('Calendar');
return calendarStore.persist(calendar);
};
exports.createEvent = function(event) {
return persistEvent(event, 'create', 'canCreate');
};
exports.updateEvent = function(event) {
return persistEvent(event, 'update', 'canUpdate');
};
exports.deleteEvent = function(event) {
return persistEvent(event, 'delete', 'canDelete');
};
var persistEvent = co.wrap(function *(event, action, capability) {
event = event.data || event;
try {
var eventStore = core.storeFactory.get('Event');
var provider = yield eventStore.providerFor(event);
var caps = yield provider.eventCapabilities(event);
if (!caps[capability]) {
return Promise.reject(new Error(`Can't ${action} event`));
}
return provider[action + 'Event'](event);
} catch(err) {
console.error(
`${action} Error for event "${event._id}" ` +
`on calendar "${event.calendarId}"`
);
console.error(err);
return Promise.reject(err);
}
});
exports.getSetting = function(id) {
var settingStore = core.storeFactory.get('Setting');
return settingStore.getValue(id);
};
exports.setSetting = function(id, value) {
var settingStore = core.storeFactory.get('Setting');
return settingStore.set(id, value);
};
exports.observeSetting = function(id) {
var stream = new FakeClientStream();
var settingStore = core.storeFactory.get('Setting');
var writeOnChange = function(value) {
stream.write(value);
};
settingStore.on(`${id}Change`, writeOnChange);
stream.cancel = function() {
settingStore.off(`${id}Change`, writeOnChange);
stream._cancel();
};
exports.getSetting(id).then(writeOnChange);
return stream;
};
exports.getAccount = function(id) {
var accountStore = core.storeFactory.get('Account');
return accountStore.get(id);
};
exports.deleteAccount = function(id) {
var accountStore = core.storeFactory.get('Account');
return accountStore.remove(id);
};
/**
* Sends a request to create an account.
*
* @param {Calendar.Models.Account} model account details.
*/
exports.createAccount = co.wrap(function *(model) {
var storeFactory = core.storeFactory;
var accountStore = storeFactory.get('Account');
var calendarStore = storeFactory.get('Calendar');
// begin by persisting the account
var [, result] = yield accountStore.verifyAndPersist(model);
// finally sync the account so when
// we exit the request the user actually
// has some calendars. This should not take
// too long (compared to event sync).
yield accountStore.sync(result);
// begin sync of calendars
var calendars = yield calendarStore.remotesByAccount(result._id);
// note we don't wait for any of this to complete
// we just begin the sync and let the event handlers
// on the sync controller do the work.
for (var key in calendars) {
core.syncController.calendar(
result,
calendars[key]
);
}
return result;
});
exports.observeAccounts = function() {
var stream = new FakeClientStream();
var accountStore = core.storeFactory.get('Account');
var getAllAndWrite = co.wrap(function *() {
try {
var accounts = yield accountStore.all();
var data = object.map(accounts, (id, account) => {
return {
account: account,
provider: core.providerFactory.get(account.providerType)
};
});
stream.write(data);
} catch(err) {
console.error(`Error fetching accounts: ${err.message}`);
}
});
accountStore.on('add', getAllAndWrite);
accountStore.on('remove', getAllAndWrite);
accountStore.on('update', getAllAndWrite);
stream.cancel = function() {
accountStore.off('add', getAllAndWrite);
accountStore.off('remove', getAllAndWrite);
accountStore.off('update', getAllAndWrite);
stream._cancel();
};
nextTick(getAllAndWrite);
return stream;
};
exports.observeDay = function(date) {
var stream = new FakeClientStream();
var emit = stream.write.bind(stream);
stream.cancel = function() {
dayObserver.off(date, emit);
stream._cancel();
};
// FIXME: nextTick only really needed because dayObserver dispatches the
// first callback synchronously, easier to solve it here than to change
// dayObserver; we can remove this nextTick call after moving to threads.js
// (since it will always be async)
nextTick(() => dayObserver.on(date, emit));
return stream;
};
/**
* Returns a list of available presets filtered by
* the currently used presets in the database.
* (can't create multiple local calendars)
*/
exports.availablePresets = function(presetList) {
var accountStore = core.storeFactory.get('Account');
return accountStore.availablePresets(presetList);
};
/**
* FakeClientStream is used as a temporary solution while we move all the db
* calls into the worker. In the end all the methods inside this file will be
* transfered into the "backend/calendar_service.js" and we will simply call
* the `threads.client('calendar')` API
*/
function FakeClientStream() {
this._emitter = new EventEmitter2();
this._enabled = true;
}
FakeClientStream.prototype.write = function(data) {
this._enabled && this._emitter.emit('data', data);
};
FakeClientStream.prototype.listen = function(callback) {
this._enabled && this._emitter.on('data', callback);
};
FakeClientStream.prototype.unlisten = function(callback) {
this._enabled && this._emitter.off('data', callback);
};
FakeClientStream.prototype._cancel = function() {
this._emitter.removeAllListeners();
this._enabled = false;
};
});