Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
351 lines
9.2 KiB
JavaScript
Executable file
351 lines
9.2 KiB
JavaScript
Executable file
'use strict';
|
|
|
|
var AdvancedSettings = require('./views/advanced_settings'),
|
|
CreateAccount = require('./views/create_account'),
|
|
Day = require('./views/day'),
|
|
EditEvent = require('./views/edit_event'),
|
|
Marionette = require('marionette-client'),
|
|
ModifyAccount = require('./views/modify_account'),
|
|
Month = require('./views/month'),
|
|
MonthDay = require('./views/month_day'),
|
|
ReadEvent = require('./views/read_event'),
|
|
Settings = require('./views/settings'),
|
|
Week = require('./views/week');
|
|
|
|
function Calendar(client) {
|
|
this.client = client.scope({ searchTimeout: 5000 });
|
|
this.actions = new Marionette.Actions(this.client);
|
|
|
|
// Initialize our view remotes.
|
|
this.advancedSettings = new AdvancedSettings(client);
|
|
this.createAccount = new CreateAccount(client);
|
|
this.day = new Day(client);
|
|
this.editEvent = new EditEvent(client);
|
|
this.modifyAccount = new ModifyAccount(client);
|
|
this.month = new Month(client);
|
|
this.monthDay = new MonthDay(client);
|
|
this.readEvent = new ReadEvent(client);
|
|
this.settings = new Settings(client);
|
|
this.week = new Week(client);
|
|
}
|
|
module.exports = Calendar;
|
|
|
|
Calendar.ORIGIN = 'app://calendar.gaiamobile.org';
|
|
|
|
Calendar.prototype = {
|
|
launch: function() {
|
|
var client = this.client;
|
|
|
|
client.apps.launch(Calendar.ORIGIN);
|
|
client.apps.switchToApp(Calendar.ORIGIN);
|
|
|
|
// Wait for the document body to know we're really 'launched'.
|
|
this.client.helper.waitForElement('body');
|
|
},
|
|
|
|
get addEventButton() {
|
|
return this.client.findElement('#time-header a[href="/event/add/"]');
|
|
},
|
|
|
|
get headerContent() {
|
|
return this.client.findElement('#current-month-year');
|
|
},
|
|
|
|
get timeHeader() {
|
|
return this.client.findElement('#time-header');
|
|
},
|
|
|
|
get themeColor() {
|
|
return this.client.findElement('meta[name="theme-color"]')
|
|
.getAttribute('content');
|
|
},
|
|
|
|
openModifyEventView: function() {
|
|
this.addEventButton.click();
|
|
this.editEvent.waitForDisplay();
|
|
return this;
|
|
},
|
|
|
|
openSettingsView: function() {
|
|
this._toggleSettingsView(true);
|
|
return this;
|
|
},
|
|
|
|
closeSettingsView: function() {
|
|
this._toggleSettingsView(false);
|
|
return this;
|
|
},
|
|
|
|
_toggleSettingsView: function(isOpen) {
|
|
var client = this.client;
|
|
client.helper
|
|
.waitForElement(this.timeHeader)
|
|
.tap(25, 25);
|
|
|
|
// Wait for the animation to be complete before trying to click on
|
|
// items in the drawer.
|
|
var drawer = this.client.findElement('#settings .settings-drawer');
|
|
|
|
this.client.waitFor(function() {
|
|
return drawer.getAttribute('data-animstate') === 'done';
|
|
});
|
|
|
|
if (!isOpen) {
|
|
var body = this.client.findElement('body');
|
|
// Also wait for the UI to be in a non-settings state after
|
|
// waiting for the animation to finish and the app UI to go
|
|
// back to non-settings state.
|
|
this.client.waitFor(function() {
|
|
return body.getAttribute('data-path') !== '/settings/';
|
|
});
|
|
}
|
|
return this;
|
|
},
|
|
|
|
openAdvancedSettingsView: function() {
|
|
this.openSettingsView();
|
|
this.settings.setupAdvancedSettings();
|
|
this.advancedSettings.waitForDisplay();
|
|
return this;
|
|
},
|
|
|
|
closeAdvancedSettingsView: function() {
|
|
var advancedSettings = this.advancedSettings;
|
|
advancedSettings.close();
|
|
advancedSettings.waitForHide();
|
|
},
|
|
|
|
openDayView: function() {
|
|
this.client
|
|
.findElement('#view-selector a[href="/day/"]')
|
|
.click();
|
|
this.day.waitForDisplay();
|
|
return this;
|
|
},
|
|
|
|
openMonthView: function() {
|
|
this.client
|
|
.findElement('#view-selector a[href="/month/"]')
|
|
.click();
|
|
this.month.waitForDisplay();
|
|
return this;
|
|
},
|
|
|
|
openWeekView: function() {
|
|
this.client
|
|
.findElement('#view-selector a[href="/week/"]')
|
|
.click();
|
|
this.week.waitForDisplay();
|
|
return this;
|
|
},
|
|
|
|
clickToday: function() {
|
|
this.client
|
|
.findElement('#view-selector a[href="#today"]')
|
|
.click();
|
|
return this;
|
|
},
|
|
|
|
setupAccount: function(options) {
|
|
this.openAdvancedSettingsView();
|
|
this.advancedSettings.createAccount();
|
|
this.createAccount.waitForDisplay();
|
|
this.createAccount.chooseAccountType(options.accountType);
|
|
|
|
var modifyAccount = this.modifyAccount;
|
|
modifyAccount.waitForDisplay();
|
|
[
|
|
'user',
|
|
'password',
|
|
'fullUrl'
|
|
].forEach(function(key) {
|
|
if (key in options) {
|
|
modifyAccount[key] = options[key];
|
|
}
|
|
});
|
|
|
|
modifyAccount.save();
|
|
modifyAccount.waitForHide();
|
|
this.closeSettingsView();
|
|
return this;
|
|
},
|
|
|
|
teardownAccount: function(calendarName, user) {
|
|
this.openAdvancedSettingsView();
|
|
this.advancedSettings.clickAccount(calendarName, user);
|
|
var modifyAccount = this.modifyAccount;
|
|
modifyAccount.waitForDisplay();
|
|
modifyAccount.delete();
|
|
modifyAccount.waitForHide();
|
|
this.closeAdvancedSettingsView();
|
|
this.closeSettingsView();
|
|
return this;
|
|
},
|
|
|
|
sync: function() {
|
|
this.openSettingsView();
|
|
this.settings.sync();
|
|
this.closeSettingsView();
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Create an event.
|
|
*
|
|
* Options:
|
|
* (String) calendar - calendar name [defaults to "Offline calendar"].
|
|
* (String) title - event title.
|
|
* (String) location - event location.
|
|
* (Date) startDate - event start date.
|
|
* (Date) endDate - event end date.
|
|
* (Number) startHour - shortcut for creating an event that starts today.
|
|
* (Number) duration - length of event in hours.
|
|
* (Boolean) allDay - whether this is an all day event.
|
|
* (Array) reminders - array of strings like '5 minutes before'.
|
|
*/
|
|
createEvent: function(opts) {
|
|
var startDate;
|
|
if (opts.startDate) {
|
|
startDate = opts.startDate;
|
|
} else {
|
|
startDate = new Date();
|
|
// startHour can be zero!
|
|
if (opts.startHour != null) {
|
|
startDate.setHours(opts.startHour, 0, 0, 0);
|
|
}
|
|
}
|
|
|
|
var endDate;
|
|
if (opts.endDate) {
|
|
endDate = opts.endDate;
|
|
} else {
|
|
// 1h by default
|
|
var duration = opts.duration || 1;
|
|
endDate = new Date(startDate.getTime() + duration * 60 * 60 * 1000);
|
|
}
|
|
|
|
this.openModifyEventView();
|
|
var editEvent = this.editEvent;
|
|
editEvent.title = opts.title;
|
|
editEvent.location = opts.location || '';
|
|
editEvent.description = opts.description || '';
|
|
editEvent.calendar = opts.calendar || 'Offline calendar';
|
|
editEvent.startDate = startDate;
|
|
editEvent.endDate = endDate;
|
|
if (opts.allDay) {
|
|
editEvent.allDay = opts.allDay;
|
|
} else {
|
|
editEvent.startTime = startDate;
|
|
editEvent.endTime = endDate;
|
|
}
|
|
// no reminders by default to avoid triggering notifications by mistake.
|
|
// see: https://bugzil.la/1012507
|
|
editEvent.reminders = opts.reminders == null ? [] : opts.reminders;
|
|
editEvent.save();
|
|
|
|
editEvent.waitForHide();
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Tests if content is bigger than container. If something is wrong it
|
|
* throws errors.
|
|
*/
|
|
checkOverflow: function(element, msg) {
|
|
msg = msg ? msg + ': ' : '';
|
|
|
|
var wid = element.scriptWith(function(el) {
|
|
return {
|
|
content: el.scrollWidth,
|
|
container: el.clientWidth
|
|
};
|
|
});
|
|
if (!wid.content) {
|
|
throw new Error(msg + 'invalid content width');
|
|
}
|
|
if (!wid.container) {
|
|
throw new Error(msg + 'invalid container width');
|
|
}
|
|
// we use a buffer of 1px to account for potential rounding issues
|
|
// see: Bug 959901
|
|
if (Math.abs(wid.content - wid.container) > 1) {
|
|
msg += 'content (' + wid.content + 'px) is wider than container (' +
|
|
wid.container + 'px)';
|
|
throw new Error(msg);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
formatDate: function(date) {
|
|
var month = date.getMonth() + 1,
|
|
day = date.getDate(),
|
|
year = date.getFullYear();
|
|
if (month.toString().length === 1) {
|
|
month = '0' + month;
|
|
}
|
|
if (day.toString().length === 1) {
|
|
day = '0' + day;
|
|
}
|
|
|
|
return [month, day, year].join('/');
|
|
},
|
|
|
|
swipeLeft: function() {
|
|
return this._swipe({ direction: 'left' });
|
|
},
|
|
|
|
swipeRight: function() {
|
|
return this._swipe({ direction: 'right' });
|
|
},
|
|
|
|
/**
|
|
* Options:
|
|
* (String) direction is one of 'left', 'right'.
|
|
*/
|
|
_swipe: function(options) {
|
|
var bodySize = this.client.executeScript(function() {
|
|
return {
|
|
height: document.body.clientHeight,
|
|
width: document.body.clientWidth
|
|
};
|
|
});
|
|
|
|
// (x1, y1) is swipe start.
|
|
// (x2, y2) is swipe end.
|
|
var x1, x2, y1, y2;
|
|
y1 = y2 = bodySize.height * 0.5;
|
|
if (options.direction === 'left') {
|
|
x1 = bodySize.width * 0.8;
|
|
x2 = 0;
|
|
} else if (options.direction === 'right') {
|
|
x1 = bodySize.width * 0.2;
|
|
x2 = bodySize.width;
|
|
} else {
|
|
throw new Error('swipe needs a direction');
|
|
}
|
|
|
|
var body = this.client.findElement('body');
|
|
this.actions
|
|
.flick(body, x1, y1, x2, y2)
|
|
.perform();
|
|
return this;
|
|
},
|
|
|
|
switch12HourTimeFormat: function() {
|
|
this._switchTimeFormat(true);
|
|
},
|
|
|
|
switch24HourTimeFormat: function() {
|
|
this._switchTimeFormat(false);
|
|
},
|
|
|
|
_switchTimeFormat: function(is12Hour) {
|
|
var client = this.client;
|
|
// Switch to System frame to get the permission
|
|
// of writing settings values.
|
|
client.switchToFrame();
|
|
client.settings.set('locale.hour12', is12Hour);
|
|
client.apps.switchToApp(Calendar.ORIGIN);
|
|
}
|
|
};
|