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,124 @@
define(function(require, exports, module) {
'use strict';
function Account(options) {
var key;
if (typeof(options) === 'undefined') {
options = {};
}
for (key in options) {
if (options.hasOwnProperty(key)) {
this[key] = options[key];
}
}
}
module.exports = Account;
Account.prototype = {
/**
* Type of provider this
* account requires.
*/
providerType: null,
/**
* ID for this model always set
* by the store when hydrating
*/
id: null,
/**
* Which preset this model came from.
*/
preset: null,
/**
* Domain for account
*/
domain: '',
/**
* url/path for account
*/
entrypoint: '',
/**
* Location where calendars can be found.
* May be the same as entrypoint.
*/
calendarHome: '',
/**
* username for authentication
*/
user: '',
/**
* password for authentication
*/
password: '',
get fullUrl() {
return this.domain + this.entrypoint;
},
set fullUrl(value) {
var protocolIdx = value.indexOf('://');
this.domain = value;
this.entrypoint = '/';
if (protocolIdx !== -1) {
protocolIdx += 3;
// next chunk
var domainChunk = value.substr(protocolIdx);
var pathIdx = domainChunk.indexOf('/');
if (pathIdx !== -1) {
pathIdx = pathIdx + protocolIdx;
this.entrypoint = value.substr(pathIdx);
this.domain = value.substr(0, pathIdx);
}
}
},
/**
* Data only version of this object.
* Used for both passing data between
* threads (workers) and persisting data
* in indexeddb.
*/
toJSON: function() {
var output = {};
var fields = [
'entrypoint',
'calendarHome',
'domain',
'password',
'user',
'providerType',
'preset',
'oauth',
'error'
];
fields.forEach(function(key) {
output[key] = this[key];
}, this);
if (this._id || this._id === 0) {
output._id = this._id;
}
return output;
}
};
});

View file

@ -0,0 +1,153 @@
define(function(require, exports, module) {
'use strict';
function Cal(options) {
if (typeof(options) === 'undefined') {
options = {};
}
this.remote = {};
for (var key in options) {
if (options.hasOwnProperty(key)) {
this[key] = options[key];
}
}
}
module.exports = Cal;
Cal.prototype = {
/**
* Local copy of calendars remote state.
* Taken from a calendar providers .toJSON method.
*
* @type {Object}
*/
remote: null,
/**
* The date at which this calendar's events
* where synchronized.
*
* @type {Date}
*/
firstEventSyncDate: null,
/**
* Last sync token used in previous
* event synchronization.
*
* @type {String}
*/
lastEventSyncToken: '',
/**
* Last date of event synchronization.
* This is not going to be used
* for any kind of serious operation
* right now this is just for the UI.
*
* @type {Date}
*/
lastEventSyncDate: '',
/**
* Indicates if calendar is displayed
* locally in the ui.
*
* @type {Boolean}
*/
localDisplayed: true,
/**
* Id of account this record
* is associated with.
*/
accountId: '',
/**
* Updates remote with data from a calendar provider.
*
* @param {Calendar.Provider.Calendar.Abstract} provider remote.
*/
updateRemote: function(provider) {
var data = provider;
if ('toJSON' in provider) {
data = provider.toJSON();
}
this.remote = data;
},
/**
* Checks if local and remote state differ
* via sync tokens. Returns true when
* local sync token and remote do not match.
* Does not account for local changes only
* when the server state has changed
* and we have not yet synchronized.
*
* @return {Boolean} true when sync needed.
*/
eventSyncNeeded: function() {
var local = this.lastEventSyncToken;
var remote = this.remote.syncToken;
return local != remote;
},
set name(name) {
this.remote.name = name;
return this.remote.name;
},
set color(color) {
this.remote.color = color;
return this.remote.color;
},
set description(description) {
this.remote.description = description;
return this.remote.description;
},
get name() {
return this.remote.name;
},
get color() {
var color = this.remote.color;
if (color) {
if (color.substr(0, 1) === '#') {
return color.substr(0, 7);
}
}
return this.remote.color;
},
get description() {
return this.remote.description;
},
toJSON: function() {
var result = {
error: this.error,
remote: this.remote,
accountId: this.accountId,
localDisplayed: this.localDisplayed,
lastEventSyncDate: this.lastEventSyncDate,
lastEventSyncToken: this.lastEventSyncToken,
firstEventSyncDate: this.firstEventSyncDate
};
if (this._id || this._id === 0) {
result._id = this._id;
}
return result;
}
};
});

View file

@ -0,0 +1,268 @@
define(function(require, exports, module) {
'use strict';
var Calc = require('common/calc');
var probablyParseInt = require('common/probably_parse_int');
/**
* Creates a wrapper around a event instance from the db
*/
function Event(data) {
var isNew = false;
if (typeof(data) === 'undefined') {
isNew = true;
data = Object.create(null);
data.remote = {};
}
this.data = data;
/** shortcut */
var remote = this.remote = this.data.remote;
if ('start' in remote && !('startDate' in remote)) {
remote.startDate = Calc.dateFromTransport(
remote.start
);
}
if ('end' in remote && !('endDate' in remote)) {
remote.endDate = Calc.dateFromTransport(
remote.end
);
}
if (isNew) {
this.resetToDefaults();
}
var start = this.remote.startDate;
var end = this.remote.endDate;
// the typeof check is to see if we have already
// set the value in resetToDefaults (or prior)
if (
typeof(this._isAllDay) === 'undefined' &&
Calc.isOnlyDate(start) &&
Calc.isOnlyDate(end)
) {
// mostly to handle the case before the time
// where we actually managed isAllDay as a setter.
this.isAllDay = true;
} else {
// not on prototype intentionally because
// we need to either need to resetToDefaults
// or check startDate/endDate in the constructor.
this.isAllDay = false;
}
}
module.exports = Event;
Event.prototype = {
/**
* Sets default values of an event.
*/
resetToDefaults: function() {
var now = new Date();
this.isAllDay = false;
this.startDate = new Date(
now.getFullYear(),
now.getMonth(),
now.getDate()
);
this.endDate = new Date(
now.getFullYear(),
now.getMonth(),
now.getDate() + 1
);
},
get _id() {
return this.data._id;
},
_setDate: function(date, field) {
if (!(date instanceof Date)) {
throw new TypeError('must pass instance of Date');
}
var allDay = this.isAllDay;
if (allDay) {
// clone the existing date
date = new Date(date.valueOf());
// filter out the stuff we don't care about
date.setHours(0);
date.setMinutes(0);
date.setSeconds(0);
date.setMilliseconds(0);
}
this.remote[field] = Calc.dateToTransport(
date,
null, // TODO allow setting tzid
allDay
);
this.remote[field + 'Date'] = date;
},
/* start date */
get startDate() {
return this.remote.startDate;
},
set startDate(value) {
this._setDate(value, 'start');
},
/* end date */
get endDate() {
return this.remote.endDate;
},
set endDate(value) {
this._setDate(value, 'end');
},
set isAllDay(value) {
this._isAllDay = value;
// send values through the their setter.
if (this.endDate) {
this.endDate = this.endDate;
}
if (this.startDate) {
this.startDate = this.startDate;
}
},
get isAllDay() {
return this._isAllDay;
},
/* associated records */
get calendarId() {
return this.data.calendarId;
},
set calendarId(value) {
if (value && typeof(value) !== 'number') {
value = probablyParseInt(value);
}
this.data.calendarId = value;
},
/* simple setters */
get syncToken() {
return this.remote.syncToken;
},
set syncToken(value) {
this.remote.syncToken = value;
},
get title() {
return this.remote.title || '';
},
set title(value) {
this.remote.title = value;
},
get description() {
return this.remote.description || '';
},
set description(value) {
this.remote.description = value;
},
get location() {
return this.remote.location || '';
},
set location(value) {
this.remote.location = value;
return this.remote.location;
},
get alarms() {
return this.remote.alarms || [];
},
set alarms(value) {
this.remote.alarms = value;
return this.remote.alarms;
},
/**
* If data doesn't have any errors, the event
* takes on the attributes of data.
*
* @param {Object} data, object that contains
* at least some attributes of the event object.
*
* @return {Object} errors if validationErrors returns erros,
* true otherwise.
*/
updateAttributes: function(data) {
var errors = this.validationErrors(data);
if (errors) {
return errors;
}
for (var field in data) {
this[field] = data[field];
}
return true;
},
/**
* Validates the contents of the model.
*
* Output example:
*
* [
* {
* name: 'invalidDate',
* properties: ['startDate', 'endDate']
* }
* //...
* ]
*
* @param {Object} data, optional object that contains
* at least some attributes of the event object.
* @return {Array|False} see above.
*/
validationErrors: function(data) {
var obj = data || this;
var end = obj.endDate.valueOf();
var start = obj.startDate.valueOf();
var errors = [];
if (start >= end) {
errors.push({
name: 'start-after-end'
});
}
if (errors.length) {
return errors;
}
return false;
}
};
});