Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #7540 from dscravag/nightly2

Nightly 2013-01-11
  • Loading branch information...
commit 50034cf938ff160bfb9525b0653ba9f61013831e 2 parents 9d4983b + de643c2
@dscravag dscravag authored
Showing with 2,340 additions and 943 deletions.
  1. +1 −0  .gitignore
  2. +1 −1  apps/calendar/index.html
  3. +37 −28 apps/calendar/js/app.js
  4. +43 −3 apps/calendar/js/calc.js
  5. +1 −1  apps/calendar/js/templates/week.js
  6. +20 −2 apps/calendar/js/views/month_child.js
  7. +3 −4 apps/calendar/js/views/months_day.js
  8. +6 −6 apps/calendar/js/views/time_header.js
  9. +9 −0 apps/calendar/locales/calendar.en-US.properties
  10. +1 −1  apps/calendar/locales/calendar.fr.properties
  11. +20 −5 apps/calendar/test/unit/app_test.js
  12. +103 −0 apps/calendar/test/unit/calc_test.js
  13. +1 −1  apps/calendar/test/unit/views/months_day_test.js
  14. +17 −26 apps/camera/js/camera.js
  15. +1 −1  apps/communications/contacts/config.json
  16. +24 −6 apps/communications/contacts/js/contacts_details.js
  17. +4 −0 apps/communications/contacts/js/contacts_form.js
  18. +14 −0 apps/communications/contacts/js/search.js
  19. +2 −2 apps/communications/dialer/js/dialer.js
  20. +2 −0  apps/communications/dialer/js/handled_call.js
  21. +71 −47 apps/communications/dialer/js/keypad.js
  22. +1 −2  apps/communications/dialer/js/oncall.js
  23. +1 −1  apps/communications/dialer/js/utils.js
  24. +21 −8 apps/communications/dialer/style/commslog.css
  25. +1 −1  apps/communications/dialer/test/unit/mock_keypad.js
  26. +10 −10 apps/communications/ftu/index.html
  27. +3 −3 apps/communications/ftu/locales/ftu.en-US.properties
  28. +38 −4 apps/costcontrol/fte.html
  29. +2 −8 apps/costcontrol/js/app.js
  30. +52 −7 apps/costcontrol/js/fte.js
  31. +29 −11 apps/costcontrol/js/message_handler.js
  32. +9 −9 apps/costcontrol/js/utils/debug.js
  33. +1 −0  apps/costcontrol/js/views/telephony.js
  34. +41 −3 apps/costcontrol/js/widget.js
  35. +14 −0 apps/costcontrol/locales/costcontrol.en-US.properties
  36. BIN  apps/costcontrol/style/images/widget/sim/authed-sim.png
  37. BIN  apps/costcontrol/style/images/widget/sim/no-sim.png
  38. BIN  apps/costcontrol/style/images/widget/sim/nonauthed-sim.png
  39. +22 −5 apps/costcontrol/style/views/firsttime.css
  40. +32 −0 apps/costcontrol/style/widget.css
  41. +8 −0 apps/costcontrol/widget.html
  42. +4 −4 apps/email/index.html
  43. +7 −1 apps/email/js/compose-cards.js
  44. +34 −20 apps/email/js/mail-app.js
  45. +6 −0 apps/email/manifest.webapp
  46. +2 −0  apps/email/style/message-cards.css
  47. +1 −1  apps/gallery/manifest.webapp
  48. +32 −49 apps/homescreen/everything.me/config/config.js
  49. +49 −0 apps/homescreen/everything.me/config/shortcuts.js
  50. +11 −8 apps/homescreen/everything.me/css/common.css
  51. +189 −109 apps/homescreen/everything.me/js/Brain.js
  52. +2 −2 apps/homescreen/everything.me/js/Core.js
  53. +81 −28 apps/homescreen/everything.me/js/api/DoATAPI.js
  54. +18 −14 apps/homescreen/everything.me/js/api/apiv2.js
  55. +6 −6 apps/homescreen/everything.me/js/etmmanager.js
  56. +1 −0  apps/homescreen/everything.me/js/everything.me.js
  57. +19 −2 apps/homescreen/everything.me/js/helpers/Utils.js
  58. +10 −2 apps/homescreen/everything.me/js/plugins/Analytics.js
  59. +23 −3 apps/homescreen/everything.me/modules/Apps/Apps.css
  60. +4 −0 apps/homescreen/everything.me/modules/Apps/Apps.js
  61. +2 −5 apps/homescreen/everything.me/modules/ConnectionMessage/ConnectionMessage.css
  62. +11 −3 apps/homescreen/everything.me/modules/ConnectionMessage/ConnectionMessage.js
  63. +25 −22 apps/homescreen/everything.me/modules/Searchbar/Searchbar.css
  64. +9 −0 apps/homescreen/everything.me/modules/Searchbar/Searchbar.js
  65. +0 −5 apps/homescreen/everything.me/modules/Shortcuts/Shortcuts.css
  66. +22 −16 apps/homescreen/everything.me/modules/Shortcuts/Shortcuts.js
  67. +10 −10 apps/homescreen/everything.me/modules/ShortcutsCustomize/ShortcutsCustomize.css
  68. +22 −14 apps/homescreen/everything.me/modules/ShortcutsCustomize/ShortcutsCustomize.js
  69. +33 −6 apps/homescreen/everything.me/modules/SmartFolder/SmartFolder.css
  70. +34 −9 apps/homescreen/everything.me/modules/SmartFolder/SmartFolder.js
  71. +1 −0  apps/homescreen/index.html
  72. +37 −0 apps/homescreen/locales/homescreen.en-US.properties
  73. +8 −0 apps/homescreen/style/app_tapped_filter.svg
  74. +4 −0 apps/homescreen/style/grid.css
  75. +80 −51 apps/settings/index.html
  76. +4 −1 apps/settings/js/about.js
  77. +7 −1 apps/settings/js/onpair.js
  78. +72 −36 apps/settings/js/settings.js
  79. +1 −0  apps/settings/locales/settings.en-US.properties
  80. +1 −1  apps/settings/style/icons.css
  81. +49 −11 apps/settings/style/lists.css
  82. +47 −23 apps/settings/style/settings.css
  83. +14 −2 apps/settings/test/unit/settings_test.js
  84. +12 −3 apps/sms/js/sms.js
  85. +6 −3 apps/sms/js/utils.js
  86. +62 −2 apps/sms/style/sms.css
  87. +8 −0 apps/system/index.html
  88. +1 −0  apps/system/js/app_install_manager.js
  89. +8 −4 apps/system/js/attention_screen.js
  90. +12 −0 apps/system/js/lockscreen.js
  91. +12 −0 apps/system/js/sim_lock.js
  92. +33 −9 apps/system/js/simcard_dialog.js
  93. +2 −1  apps/system/js/sound_manager.js
  94. +2 −1  apps/system/js/trusted_ui.js
  95. +34 −16 apps/system/js/updatable.js
  96. +24 −24 apps/system/js/update_manager.js
  97. +5 −0 apps/system/locales/system.en-US.properties
  98. +2 −11 apps/system/style/lockscreen/lockscreen.css
  99. +1 −0  apps/system/style/notifications/notifications.css
  100. +10 −0 apps/system/style/zindex.css
  101. +31 −12 apps/system/test/unit/app_install_manager_test.js
  102. +3 −0  apps/system/test/unit/mock_app.js
  103. +7 −0 apps/system/test/unit/mock_updatable.js
  104. +6 −0 apps/system/test/unit/mock_update_manager.js
  105. +116 −57 apps/system/test/unit/updatable_test.js
  106. +44 −21 apps/system/test/unit/update_manager_test.js
  107. +1 −5 apps/video/index.html
  108. +20 −27 apps/video/js/video.js
  109. +1 −0  build/applications-data.js
  110. +54 −1 build/ua-override-prefs.js
  111. +2 −1  external-apps/maps/metadata.json
  112. +46 −0 locales/languages_all.json
  113. +5 −0 locales/languages_basecamp.json
  114. +8 −0 locales/languages_dev.json
  115. +2 −0  shared/locales/date/date.en-US.properties
  116. +3 −0  shared/locales/date/date.fr.properties
  117. +1 −1  shared/style/edit_mode/index.html
  118. +12 −3 shared/style/status.css
  119. +1 −1  test_apps/uitest/index.html
  120. +84 −68 test_apps/uitest/js/identity.js
  121. +1 −1  test_apps/uitest/tests/identity.html
View
1  .gitignore
@@ -19,6 +19,7 @@ manifest.appcache
/apps/*/test/unit/_sandbox.html
/apps/*/test/unit/_proxy.html
/apps/*/shared
+/apps/settings/resources/support.json
/test_apps/*/test/unit/_sandbox.html
/test_apps/*/test/unit/_proxy.html
/showcase_apps/*/test/unit/_sandbox.html
View
2  apps/calendar/index.html
@@ -390,7 +390,7 @@ <h1 data-l10n-id="account-header">Account</h1>
<form role="dialog" data-type="confirm" id="remove-account-dialog">
<section>
- <h1 data-l10n-id="remove-account-dialog">>Remove Account</h1>
+ <h1 data-l10n-id="remove-account-dialog">Remove Account</h1>
<p data-l10n-id="remove-account-dialog-details">
Removing this account will also remove your local copy of associated calendars and events.
</p>
View
65 apps/calendar/js/app.js
@@ -77,6 +77,40 @@ Calendar.App = (function(window) {
}
};
+ var DateL10n = {
+ /**
+ * Localizes all elements with data-l10n-date-format.
+ */
+ localizeElements: function(parent) {
+ var elements = document.querySelectorAll(
+ '[data-l10n-date-format]'
+ );
+
+ var len = elements.length;
+ var i = 0;
+
+ for (; i < len; i++) {
+ DateL10n.localizeElement(elements[i]);
+ }
+ },
+
+ /**
+ * Localize a single element expected to have data-l10n-date-format.
+ */
+ localizeElement: function(element) {
+ var date = element.dataset.date;
+ var formatKey = element.dataset.l10nDateFormat;
+ var format = navigator.mozL10n.get(formatKey);
+
+ if (date) {
+ element.textContent = Calendar.App.dateFormat.localeFormat(
+ new Date(date),
+ format
+ );
+ }
+ }
+ };
+
/**
* Focal point for state management
* within calendar application.
@@ -87,6 +121,8 @@ Calendar.App = (function(window) {
var App = {
PendingManager: PendingManager,
+ DateL10n: DateL10n,
+
//XXX: always assumes that app is never lazy loaded
startingURL: window.location.href,
@@ -220,34 +256,7 @@ Calendar.App = (function(window) {
*
*/
observeDateLocalization: function() {
- function localize() {
- var elements = document.querySelectorAll(
- '[data-l10n-date-format]'
- );
-
- var len = elements.length;
- var i = 0;
-
- var date;
- var format;
- var el;
-
- for (; i < len; i++) {
- el = elements[i];
-
- date = el.dataset.date;
- format = el.dataset.l10nDateFormat;
-
- if (date) {
- el.textContent = Calendar.App.dateFormat.localeFormat(
- new Date(date),
- format
- );
- }
- }
- }
-
- window.addEventListener('localized', localize);
+ window.addEventListener('localized', DateL10n.localizeElements);
},
/**
View
46 apps/calendar/js/calc.js
@@ -8,6 +8,8 @@ Calendar.Calc = (function() {
_hourDate: new Date(),
+ startsOnMonday: false,
+
FLOATING: 'floating',
ALLDAY: 'allday',
@@ -78,6 +80,24 @@ Calendar.Calc = (function() {
},
/**
+ * Calculates day of week when starting day is Monday.
+ */
+ dayOfWeekFromMonday: function(numeric) {
+ var day = numeric - 1;
+ if (day < 0)
+ return 6;
+
+ return day;
+ },
+
+ /**
+ * Calculates day of week when starting day is Sunday.
+ */
+ dayOfWeekFromSunday: function(numeric) {
+ return numeric;
+ },
+
+ /**
* Checks is given date is today.
*
* @param {Date} date compare.
@@ -403,10 +423,20 @@ Calendar.Calc = (function() {
/**
* Returns localized day of week.
+ *
+ * @param {Date|Number} date numeric or date object.
*/
dayOfWeek: function(date) {
- // XXX: we need to localize this further.
- return date.getDay();
+ var number = date;
+
+ if (typeof(date) !== 'number') {
+ number = date.getDay();
+ }
+
+ if (Calc.startsOnMonday) {
+ return this.dayOfWeekFromMonday(number);
+ }
+ return this.dayOfWeekFromSunday(number);
},
/**
@@ -417,7 +447,7 @@ Calendar.Calc = (function() {
*/
getWeekStartDate: function(date) {
var currentDay = Calc.dayOfWeek(date);
- var startDay = date.getDate() - currentDay;
+ var startDay = (date.getDate() - currentDay);
return Calc.createDay(date, startDay);
},
@@ -578,6 +608,16 @@ Calendar.Calc = (function() {
};
+ window.addEventListener('localized', function changeStartDay() {
+ var startDay = navigator.mozL10n.get('weekStartsOnMonday');
+
+ if (startDay && parseInt(startDay, 10)) {
+ Calc.startsOnMonday = true;
+ } else {
+ Calc.startsOnMonday = false;
+ }
+ });
+
return Calc;
}());
View
2  apps/calendar/js/templates/week.js
@@ -29,7 +29,7 @@
event: function() {
return '<li class="event" data-id="' + this.h('busytimeId') + '">' +
- '<div class="container calend +ar-id-' + this.h('calendarId') + ' ' +
+ '<div class="container calendar-id-' + this.h('calendarId') + ' ' +
'calendar-display calendar-color">' +
this.h('title') +
'</div>' +
View
22 apps/calendar/js/views/month_child.js
@@ -2,6 +2,11 @@
var template = Calendar.Templates.Month;
var Calc = Calendar.Calc;
+ // horrible hack to clear cache when we re-localize
+ window.addEventListener('localized', function clearHeaderCache() {
+ Child._dayHeaders = null;
+ });
+
function Child() {
Calendar.View.apply(this, arguments);
@@ -192,9 +197,22 @@
var html = '';
for (; i < days; i++) {
- name = navigator.mozL10n.get('weekday-' + i + '-short');
+ var day = i;
+ // localization updates this value
+ if (Calendar.Calc.startsOnMonday) {
+ // 0 is monday which is 1 in l10n (based on js engine's getDay)
+ day += 1;
+
+ // 6th day of the week which Sunday (and 0 in js engine).
+ if (day === 7) {
+ day = 0;
+ }
+ }
+ var l10n = 'weekday-' + day + '-short';
+
+ name = navigator.mozL10n.get(l10n);
html += template.weekDaysHeaderDay.render({
- day: String(i),
+ day: String(day),
dayName: name
});
}
View
7 apps/calendar/js/views/months_day.js
@@ -41,9 +41,8 @@ Calendar.ns('Views').MonthsDay = (function() {
_updateHeader: function() {
var header = this.header;
- var template = navigator.mozL10n.get(
- 'agenda-date-format'
- );
+ var formatName = 'agenda-date-format';
+ var template = navigator.mozL10n.get(formatName);
// maybe we should localize this output ?
var format = this.app.dateFormat.localeFormat(
@@ -53,7 +52,7 @@ Calendar.ns('Views').MonthsDay = (function() {
header.textContent = format;
header.dataset.date = this.date.toString();
- header.dataset.l10nDateFormat = template;
+ header.dataset.l10nDateFormat = formatName;
},
handleEvent: function(e) {
View
12 apps/calendar/js/views/time_header.js
@@ -28,12 +28,12 @@ Calendar.ns('Views').TimeHeader = (function() {
},
scales: {
- month: '%B %Y',
- day: '%A %B %e',
+ month: 'month-view-header-format',
+ day: 'day-view-header-format',
// when week starts in one month and ends
// in another, we need both of them
// in the header
- singleMonth: '%B '
+ singleMonth: 'single-month-view-header-format'
},
handleEvent: function(e) {
@@ -112,19 +112,19 @@ Calendar.ns('Views').TimeHeader = (function() {
if (firstWeekday.getMonth() !== lastWeekday.getMonth()) {
scale = this.app.dateFormat.localeFormat(
firstWeekday,
- this.scales.singleMonth
+ navigator.mozL10n.get(this.scales.singleMonth)
);
}
return scale + this.app.dateFormat.localeFormat(
lastWeekday,
- this.scales.month
+ navigator.mozL10n.get(this.scales.month)
);
}
return this.app.dateFormat.localeFormat(
this.controller.position,
- this.scales[type] || this.scales.month
+ navigator.mozL10n.get(this.scales[type] || this.scales.month)
);
},
View
9 apps/calendar/locales/calendar.en-US.properties
@@ -86,6 +86,15 @@ agenda-date-format=%A %e %B %Y
hour-format=%I %p
hour-allday=All Day
+# Default header used in month view / week view
+month-view-header-format=%B %Y
+
+# In week view when displaying multiple months (weeks that span months).
+single-month-view-header-format=%B
+
+# Header format used for in the day view.
+day-view-header-format=%A %B %e
+
#errors
error-start-after-end=End date must come after start date
error-unauthenticated=Wrong login and/or password
View
2  apps/calendar/locales/calendar.fr.properties
@@ -76,7 +76,7 @@ sync-frequency-hourly.textContent=Chaque heure
alarm-starting={{title}} a débuté à {{distance}}
alarm-started={{title}} débutera dans {{distance}}
-# 24 vs 12 see http://www.cplusplus.com/reference/clibrary/ctime/strftime/
+# Date formatting details (http://pubs.opengroup.org/onlinepubs/007908799/xsh/strftime.html)
hour-format=%Hh
#errors
View
25 apps/calendar/test/unit/app_test.js
@@ -49,6 +49,19 @@ suite('app', function() {
var expected;
var fmt;
var id = 0;
+ var realL10n;
+ var l10nMap;
+
+ suiteSetup(function() {
+ realL10n = navigator.mozL10n.get;
+ navigator.mozL10n.get = function(name) {
+ return l10nMap[name] || '';
+ };
+ });
+
+ suiteTeardown(function() {
+ navigator.mozL10n.get = realL10n;
+ });
function dateElement(date, format) {
var el = document.createElement('span');
@@ -61,24 +74,26 @@ suite('app', function() {
return el;
}
- function addExpect(date, format) {
+ function addExpect(date, formatName, formatValue) {
var elId = 'dateId-' + (++id);
- dateElement(date, format).id = elId;
+ l10nMap[formatName] = formatValue;
+ dateElement(date, formatName).id = elId;
expected.push(
- [elId, fmt.localeFormat(date, format)]
+ [elId, fmt.localeFormat(date, formatValue)]
);
}
setup(function() {
+ l10nMap = {};
fmt = Calendar.App.dateFormat = navigator.mozL10n.DateTimeFormat();
expected = [];
var formatXDate = new Date(2012, 1, 1);
var formatCDate = new Date(2012, 1, 1, 7, 2, 9);
- addExpect(formatCDate, '%x');
- addExpect(formatCDate, '%c');
+ addExpect(formatCDate, 'myl10nKey', '%x');
+ addExpect(formatCDate, 'otherl10nKey', '%c');
subject.observeDateLocalization();
window.dispatchEvent(new Event('localized'));
View
103 apps/calendar/test/unit/calc_test.js
@@ -62,7 +62,110 @@ suite('calendar/calc', function() {
var result = subject.formatHour(23);
assert.equal(result, '11 PM');
});
+ });
+
+ test('#dayOfWeekFromSunday', function() {
+ var expected = [
+ ['sun', 0, 0],
+ ['mon', 1, 1],
+ ['tue', 2, 2],
+ ['wed', 3, 3],
+ ['thu', 4, 4],
+ ['fri', 5, 5],
+ ['sat', 6, 6]
+ ];
+
+ expected.forEach(function(line) {
+ var [name, date, numeric] = line;
+ assert.equal(
+ subject.dayOfWeekFromSunday(date),
+ numeric,
+ name
+ );
+ });
+ });
+
+ test('#dayOfWeekFromMonday', function() {
+ var expected = [
+ ['mon', 1, 0],
+ ['tue', 2, 1],
+ ['wed', 3, 2],
+ ['thu', 4, 3],
+ ['fri', 5, 4],
+ ['sat', 6, 5],
+ ['sun', 0, 6]
+ ];
+
+ expected.forEach(function(line) {
+ var [name, date, numeric] = line;
+ assert.equal(
+ subject.dayOfWeekFromMonday(date),
+ numeric,
+ name
+ );
+ });
+ });
+
+ suite('#dayOfWeek', function() {
+ var realStartDay;
+ var date = new Date(2012, 0, 1);
+
+ suiteSetup(function() {
+ realStartDay = subject.startsOnMonday;
+ });
+
+ suiteTeardown(function() {
+ subject.startsOnMonday = realStartDay;
+ });
+
+ test('weekStartOnMonday = 0', function() {
+ subject.startsOnMonday = 0;
+ assert.equal(
+ subject.dayOfWeek(date),
+ 0
+ );
+ });
+
+ test('weekStartsOnMonday = 1', function() {
+ subject.startsOnMonday = 1;
+ assert.equal(
+ subject.dayOfWeek(date),
+ 6
+ );
+ });
+ });
+ suite('handle localization events', function() {
+ var reaL10n;
+ var weekStartsOnMonday = 0;
+
+ suiteSetup(function() {
+ reaL10n = navigator.mozL10n;
+ navigator.mozL10n = {
+ get: function(name) {
+ if (name === 'weekStartsOnMonday') {
+ return weekStartsOnMonday;
+ }
+ return reaL10n.get.apply(this, arguments);
+ }
+ };
+ });
+
+ suiteTeardown(function() {
+ navigator.mozL10n = reaL10n;
+ });
+
+ test('weekStartsOnMonday = 1', function() {
+ weekStartsOnMonday = 1;
+ window.dispatchEvent(new Event('localized'));
+ assert.ok(subject.startsOnMonday, 'week starts on monday');
+ });
+
+ test('weekStartsOnMonday = 0', function() {
+ weekStartsOnMonday = 0;
+ window.dispatchEvent(new Event('localized'));
+ assert.ok(!subject.startsOnMonday, 'week starts on sunday');
+ });
});
suite('#spanOfMonth', function() {
View
2  apps/calendar/test/unit/views/months_day_test.js
@@ -106,7 +106,7 @@ suite('views/months_day', function() {
assert.equal(
el.dataset.l10nDateFormat,
- format,
+ 'agenda-date-format',
'sets element\'s l10nDateFormat'
);
View
43 apps/camera/js/camera.js
@@ -85,12 +85,9 @@ var Camera = {
image: {prefix: 'IMG_'}
},
- // Because we dont want to wait for the geolocation query
- // before we can take a photo, we keep a track of the users
- // position, when the camera jumps into foreground or every
- // 10 minutes
- POSITION_TIMEOUT: 1000 * 60 * 10,
- _positionTimer: null,
+ PROMPT_DELAY: 2000,
+
+ _watchId: null,
_position: null,
_pendingPick: null,
@@ -166,7 +163,6 @@ var Camera = {
this._shutterSound.mozAudioChannelType = 'publicnotification';
this._storageState = this.STORAGE_INIT;
this.setCaptureMode(this.CAMERA);
- this.initPositionUpdate();
// We lock the screen orientation and deal with rotating
// the icons manually
@@ -541,6 +537,7 @@ var Camera = {
viewfinder.mozSrcObject = stream;
viewfinder.play();
this.checkStorageSpace();
+ setTimeout(this.initPositionUpdate.bind(this), this.PROMPT_DELAY);
}
function gotCamera(camera) {
@@ -603,7 +600,6 @@ var Camera = {
this.viewfinder.play();
this.setSource(this._camera);
this._previewActive = true;
- this.initPositionUpdate();
},
stopPreview: function camera_stopPreview() {
@@ -614,8 +610,6 @@ var Camera = {
this.viewfinder.pause();
this._previewActive = false;
this.viewfinder.mozSrcObject = null;
- this.cancelPositionUpdate();
-
this.release();
},
@@ -850,29 +844,25 @@ var Camera = {
},
initPositionUpdate: function camera_initPositionUpdate() {
- if (this._positionTimer) {
+ if (this._watchId || document.mozHidden) {
return;
}
- this._positionTimer = setInterval(this.updatePosition.bind(this),
- this.POSITION_TIMEOUT);
- this.updatePosition();
+ this._watchId = navigator.geolocation
+ .watchPosition(this.updatePosition.bind(this));
},
- updatePosition: function camera_updatePosition() {
- var self = this;
- navigator.geolocation.getCurrentPosition(function(position) {
- self._position = {
- latitude: position.coords.latitude,
- longitude: position.coords.longitude
- };
- }, function() {
- console.warn('Camera: Could not fetch location');
- });
+ updatePosition: function camera_updatePosition(position) {
+ this._position = {
+ timestamp: position.timestamp,
+ altitude: position.coords.altitude,
+ latitude: position.coords.latitude,
+ longitude: position.coords.longitude
+ };
},
cancelPositionUpdate: function camera_cancelPositionUpdate() {
- window.clearInterval(this._positionTimer);
- this._positionTimer = null;
+ navigator.geolocation.clearWatch(this._watchId);
+ this._watchId = null;
},
release: function camera_release(callback) {
@@ -899,6 +889,7 @@ document.addEventListener('mozvisibilitychange', function() {
if (document.mozHidden) {
Camera.stopPreview();
Camera.cancelPick();
+ Camera.cancelPositionUpdate();
if (this._secureMode) // If the lockscreen is locked
Filmstrip.clear(); // then forget everything when closing camera
} else {
View
2  apps/communications/contacts/config.json
@@ -1,6 +1,6 @@
{
"facebookEnabled": true,
- "operationsTimeout": 10000,
+ "operationsTimeout": 25000,
"logLevel": "DEBUG",
"facebookSyncPeriod": 24,
"testToken": ""
View
30 apps/communications/contacts/js/contacts_details.js
@@ -21,6 +21,7 @@ contacts.Details = (function() {
isFbLinked,
editContactButton,
cover,
+ wrapper,
favoriteMessage,
detailsInner,
TAG_OPTIONS,
@@ -53,6 +54,7 @@ contacts.Details = (function() {
favoriteMessage = dom.querySelector('#toggle-favorite');
notesTemplate = dom.querySelector('#note-details-template-\\#i\\#');
+ wrapper = dom.querySelector('#contact-detail-wrapper');
initPullEffect(cover);
};
@@ -65,8 +67,17 @@ contacts.Details = (function() {
};
var initPullEffect = function cd_initPullEffect(cover) {
- cover.addEventListener('mousedown', function(event) {
- if (event.target != cover || contactDetails.classList.contains('no-photo'))
+ wrapper.addEventListener('touchstart', function(event) {
+
+ // Avoiding repaint (at least when no scroll is needed)
+ if (cover.style.overflow == 'hidden') {
+ var headerHeight = 5;
+ contactDetails.style.top = headerHeight + 'rem';
+ contactDetails.style.position = 'fixed';
+ }
+
+ var event = event.changedTouches[0];
+ if (contactDetails.classList.contains('no-photo'))
return;
var startPosition = event.clientY;
@@ -74,6 +85,7 @@ contacts.Details = (function() {
cover.classList.add('up');
var onMouseMove = function onMouseMove(event) {
+ var event = event.changedTouches[0];
var newMargin = event.clientY - startPosition;
if (newMargin > 0 && newMargin < 150) {
contactDetails.classList.remove('up');
@@ -87,16 +99,22 @@ contacts.Details = (function() {
};
var onMouseUp = function onMouseUp(event) {
+ var event = event.changedTouches[0];
contactDetails.classList.add('up');
cover.classList.add('up');
contactDetails.style.transform = null;
cover.style.transform = null;
- removeEventListener('mousemove', onMouseMove);
- removeEventListener('mouseup', onMouseUp);
+ removeEventListener('touchmove', onMouseMove);
+ removeEventListener('touchend', onMouseUp);
+ contactDetails.addEventListener('transitionend', function transEnd() {
+ contactDetails.style.position = 'relative';
+ contactDetails.style.top = '0';
+ this.removeEventListener('transitionend', transEnd);
+ });
};
- addEventListener('mousemove', onMouseMove);
- addEventListener('mouseup', onMouseUp);
+ addEventListener('touchmove', onMouseMove);
+ addEventListener('touchend', onMouseUp);
});
};
View
4 apps/communications/contacts/js/contacts_form.js
@@ -316,6 +316,10 @@ contacts.Form = (function() {
var deleteContact = function deleteContact(contact) {
var deleteSuccess = function deleteSuccess() {
contacts.List.remove(contact.id);
+ if (contacts.Search.isInSearchMode()) {
+ contacts.Search.invalidateCache();
+ contacts.Search.removeContact(contact.id);
+ }
Contacts.setCurrent({});
Contacts.navigation.home();
};
View
14 apps/communications/contacts/js/search.js
@@ -363,6 +363,18 @@ contacts.Search = (function() {
return inSearchMode;
}
+ var invalidateCache = function s_invalidate() {
+ canReuseSearchables = false;
+ searchableNodes = null;
+ contactNodes = null;
+ currentSet = {};
+ }
+
+ var removeContact = function s_removeContact(id) {
+ var contact = searchList.querySelector('li[data-uuid=\"' + id + '\"]');
+ searchList.removeChild(contact);
+ }
+
function showProgress() {
searchNoResult.classList.add('hide');
searchProgress.classList.remove('hidden');
@@ -380,6 +392,8 @@ contacts.Search = (function() {
return {
'init': init,
+ 'invalidateCache': invalidateCache,
+ 'removeContact': removeContact,
'search': search,
'enterSearchMode': enterSearchMode,
'exitSearchMode': exitSearchMode,
View
4 apps/communications/dialer/js/dialer.js
@@ -28,7 +28,7 @@ var CallHandler = (function callHandler() {
var number = activity.source.data.number;
var fillNumber = function actHandleDisplay() {
if (number) {
- KeypadManager.updatePhoneNumber(number);
+ KeypadManager.updatePhoneNumber(number, 'begin', false);
if (window.location.hash != '#keyboard-view') {
window.location.hash = '#keyboard-view';
}
@@ -194,7 +194,7 @@ var CallHandler = (function callHandler() {
}.bind(this);
var connected, disconnected = function clearPhoneView() {
- KeypadManager.updatePhoneNumber('');
+ KeypadManager.updatePhoneNumber('', 'begin', true);
};
TelephonyHelper.call(number, oncall, connected, disconnected);
View
2  apps/communications/dialer/js/handled_call.js
@@ -116,6 +116,7 @@ HandledCall.prototype.updateCallNumber = function hc_updateCallNumber() {
Contacts.findByNumber(number, function lookupContact(contact, matchingTel) {
if (contact && contact.name) {
node.textContent = contact.name;
+ KeypadManager.formatPhoneNumber('end', true);
var additionalInfo = Utils.getPhoneNumberAdditionalInfo(matchingTel,
contact);
KeypadManager.updateAdditionalContactInfo(additionalInfo);
@@ -127,6 +128,7 @@ HandledCall.prototype.updateCallNumber = function hc_updateCallNumber() {
}
node.textContent = number;
+ KeypadManager.formatPhoneNumber('end', true);
});
};
View
118 apps/communications/dialer/js/keypad.js
@@ -141,6 +141,10 @@ var TonePlayer = {
};
var KeypadManager = {
+
+ _MAX_FONT_SIZE_DIAL_PAD: 18,
+ _MAX_FONT_SIZE_ON_CALL: 16,
+
_phoneNumber: '',
_onCall: false,
@@ -223,7 +227,11 @@ var KeypadManager = {
var defaultFontSize = window.getComputedStyle(document.body, null)
.getPropertyValue('font-size');
this.minFontSize = parseInt(parseInt(defaultFontSize) * 10 * 0.226);
- this.maxFontSize = parseInt(parseInt(defaultFontSize) * 18 * 0.226);
+ this.maxFontSize = this._onCall ?
+ parseInt(parseInt(defaultFontSize) * this._MAX_FONT_SIZE_ON_CALL
+ * 0.226) :
+ parseInt(parseInt(defaultFontSize) * this._MAX_FONT_SIZE_DIAL_PAD
+ * 0.226);
this.phoneNumberView.value = '';
this._phoneNumber = '';
@@ -355,7 +363,7 @@ var KeypadManager = {
OnCallHandler.end();
},
- formatPhoneNumber: function kh_formatPhoneNumber(ellipsisSide) {
+ formatPhoneNumber: function kh_formatPhoneNumber(ellipsisSide, maxFontSize) {
if (this._onCall) {
var fakeView = CallScreen.activeCall.querySelector('.fake-number');
var view = CallScreen.activeCall.querySelector('.number');
@@ -371,47 +379,60 @@ var KeypadManager = {
}
}
- var newFontSize = this.getNextFontSize(view, fakeView);
+ var newFontSize;
+ if (maxFontSize) {
+ newFontSize = this.maxFontSize;
+ } else {
+ newFontSize = this.getNextFontSize(view, fakeView);
+ }
view.style.fontSize = newFontSize + 'px';
this.addEllipsis(view, fakeView, ellipsisSide);
},
addEllipsis: function kh_addEllipsis(view, fakeView, ellipsisSide) {
- var side = ellipsisSide || 'left';
- var computedStyle = window.getComputedStyle(view, null);
- var currentFontSize = parseInt(computedStyle.getPropertyValue('font-size'));
- var viewWidth = view.getBoundingClientRect().width;
- fakeView.style.fontSize = currentFontSize + 'px';
- fakeView.innerHTML = view.value ? view.value : view.innerHTML;
-
- var value = fakeView.innerHTML;
-
- // Guess the possible position of the ellipsis in order to minimize
- // the following while loop iterations:
- var counter = value.length -
- (viewWidth *
- (fakeView.textContent.length / fakeView.getBoundingClientRect().width));
-
- var newPhoneNumber;
- while (fakeView.getBoundingClientRect().width > viewWidth) {
-
- if (side == 'left') {
- newPhoneNumber = '\u2026' + value.substr(-value.length + counter);
- } else if (side == 'right') {
- newPhoneNumber = value.substr(0, value.length - counter) + '\u2026';
+ var side = ellipsisSide || 'begin';
+ LazyL10n.get(function localized(_) {
+ var localizedSide;
+ if (navigator.mozL10n.language.direction === 'rtl') {
+ localizedSide = (side === 'begin' ? 'right' : 'left');
+ } else {
+ localizedSide = (side === 'begin' ? 'left' : 'right');
}
+ var computedStyle = window.getComputedStyle(view, null);
+ var currentFontSize = parseInt(computedStyle.getPropertyValue('font-size'));
+ var viewWidth = view.getBoundingClientRect().width;
+ fakeView.style.fontSize = currentFontSize + 'px';
+ fakeView.innerHTML = view.value ? view.value : view.innerHTML;
+
+ var value = fakeView.innerHTML;
+
+ // Guess the possible position of the ellipsis in order to minimize
+ // the following while loop iterations:
+ var counter = value.length -
+ (viewWidth *
+ (fakeView.textContent.length / fakeView.getBoundingClientRect().width));
+
+ var newPhoneNumber;
+ while (fakeView.getBoundingClientRect().width > viewWidth) {
+
+ if (localizedSide == 'left') {
+ newPhoneNumber = '\u2026' + value.substr(-value.length + counter);
+ } else if (localizedSide == 'right') {
+ newPhoneNumber = value.substr(0, value.length - counter) + '\u2026';
+ }
- fakeView.innerHTML = newPhoneNumber;
- counter++;
- }
+ fakeView.innerHTML = newPhoneNumber;
+ counter++;
+ }
- if (newPhoneNumber) {
- if (view.value) {
- view.value = newPhoneNumber;
- } else {
- view.innerHTML = newPhoneNumber;
+ if (newPhoneNumber) {
+ if (view.value) {
+ view.value = newPhoneNumber;
+ } else {
+ view.innerHTML = newPhoneNumber;
+ }
}
- }
+ });
},
getNextFontSize: function kh_getNextFontSize(view, fakeView) {
@@ -486,7 +507,7 @@ var KeypadManager = {
self._longPress = true;
self.updateAddContactStatus();
- self._updatePhoneNumberView();
+ self._updatePhoneNumberView('begin', false);
}, 400, this);
}
@@ -515,7 +536,7 @@ var KeypadManager = {
this._phoneNumber += key;
this.updateAddContactStatus();
}
- this._updatePhoneNumberView();
+ this._updatePhoneNumberView('begin', false);
} else if (event.type == 'mouseup' || event.type == 'mouseleave') {
// Stop playing the DTMF/tone after a small delay
// or right away if this is a long press
@@ -540,8 +561,6 @@ var KeypadManager = {
if (this._holdTimer)
clearTimeout(this._holdTimer);
-
- this._updatePhoneNumberView();
}
},
@@ -552,12 +571,14 @@ var KeypadManager = {
this.callBarAddContact.classList.remove('disabled');
},
- updatePhoneNumber: function kh_updatePhoneNumber(number) {
+ updatePhoneNumber: function kh_updatePhoneNumber(number, ellipsisSide,
+ maxFontSize) {
this._phoneNumber = number;
- this._updatePhoneNumberView();
+ this._updatePhoneNumberView(ellipsisSide, maxFontSize);
},
- _updatePhoneNumberView: function kh_updatePhoneNumberview() {
+ _updatePhoneNumberView: function kh_updatePhoneNumberview(ellipsisSide,
+ maxFontSize) {
var phoneNumber = this._phoneNumber;
// If there are digits in the phone number, show the delete button.
@@ -573,16 +594,18 @@ var KeypadManager = {
this.phoneNumberView.value = phoneNumber;
this.moveCaretToEnd(this.phoneNumberView);
}
-
- this.formatPhoneNumber();
+
+ this.formatPhoneNumber(ellipsisSide, maxFontSize);
},
- restorePhoneNumber: function kh_restorePhoneNumber() {
- this.updatePhoneNumber(this._originalPhoneNumber);
+ restorePhoneNumber: function kh_restorePhoneNumber(ellipsisSide,
+ maxFontSize) {
+ this.updatePhoneNumber(this._originalPhoneNumber, ellipsisSide,
+ maxFontSize);
},
updateAdditionalContactInfo:
- function kh_updatePhoneNumber(additionalContactInfo) {
+ function kh_updateAdditionalContactInfo(additionalContactInfo) {
this._additionalContactInfo = additionalContactInfo;
this._updateAdditionalContactInfoView();
},
@@ -592,7 +615,8 @@ var KeypadManager = {
var phoneNumberView = CallScreen.activeCall.querySelector('.number');
var additionalview = CallScreen.activeCall.querySelector(
'.additionalContactInfo');
- if (!this._additionalContactInfo || this._additionalContactInfo === '') {
+ if (!this._additionalContactInfo ||
+ this._additionalContactInfo.trim() === '') {
additionalview.textContent = '';
additionalview.classList.add('noAdditionalContactInfo');
phoneNumberView.classList.add('noAdditionalContactInfo');
View
3  apps/communications/dialer/js/oncall.js
@@ -95,9 +95,8 @@ var CallScreen = {
},
hideKeypad: function cs_hideKeypad() {
- KeypadManager.restorePhoneNumber();
+ KeypadManager.restorePhoneNumber('end', true);
KeypadManager.restoreAdditionalContactInfo();
- KeypadManager.formatPhoneNumber();
this.body.classList.remove('showKeypad');
},
View
2  apps/communications/dialer/js/utils.js
@@ -47,7 +47,7 @@ var Utils = {
if (matchingTel.carrier) {
phoneCarrier = matchingTel.carrier;
} else {
- additionalInfo = additionalInfo + ', ' + matchingTel.value;
+ additionalInfo = additionalInfo + ', ' + contactPhoneNumber;
}
if (phoneType && phoneCarrier) {
View
29 apps/communications/dialer/style/commslog.css
@@ -16,7 +16,7 @@ form[role="dialog"][data-type="edit"] header .icon {
/* Override Building Block [Edit mode] styles */
form[role="dialog"][data-type="edit"] header,
form[role="dialog"][data-type="edit"] > menu {
- transition: all 0.4s ease;
+ transition: all 0.3s ease;
}
form[role="dialog"][data-type="edit"] header {
@@ -134,15 +134,26 @@ ul[role="tablist"][data-type="filter"] > [role="tab"].selected > a {
pointer-events: none;
}
+.log-item .pack-end {
+ position: absolute;
+ right: 0;
+}
+
+.log-item:not(.hasPhoto) .pack-end {
+ width: 0;
+}
+
.log-item .primary-info {
text-overflow: clip;
}
-.log-item.hasPhoto .primary-info {
+.log-item.hasPhoto .primary-info,
+.log-item.hasPhoto .secondary-info {
width: 19rem;
}
-.log-item:not(.hasPhoto) .primary-info {
+.log-item:not(.hasPhoto) .primary-info,
+.log-item:not(.hasPhoto) .secondary-info {
width: 25rem;
}
@@ -177,21 +188,23 @@ ul[role="tablist"][data-type="filter"] > [role="tab"].selected > a {
.recents-edit label:not([for]).call-log-selection {
transform: translateX(4rem);
- transition: transform 0.4s ease;
+ transition: transform 0.3s ease;
}
.recents-edit .log-item a {
transform: translateX(3rem);
- transition: all 0.4s ease;
+ transition: all 0.3s ease;
}
.recents-edit .log-item.hasPhoto .primary-info,
- .recents-edit .log-item:not(.hasPhoto) .primary-info {
- width: 22rem;
+.recents-edit .log-item.hasPhoto .secondary-info,
+.recents-edit .log-item:not(.hasPhoto) .primary-info,
+.recents-edit .log-item:not(.hasPhoto) .secondary-info {
+ width: 22rem;
}
.recents-edit .pack-end {
- transition: all 0.4s ease;
+ transition: all 0.3s ease;
transform: translateX(6rem);
}
View
2  apps/communications/dialer/test/unit/mock_keypad.js
@@ -5,7 +5,7 @@ var MockKeypadManager = {
},
mFormatPhoneNumberCalled: false,
updateAdditionalContactInfo:
- function khm_updateAdditionalContactInfo(ellipsisSide) {
+ function khm_updateAdditionalContactInfo(ellipsisSide, maxFontSize) {
this.mUpdateAdditionalContactInfo = true;
},
mUpdateAdditionalContactInfo: false,
View
20 apps/communications/ftu/index.html
@@ -389,16 +389,16 @@ <h2 data-l10n-id="about-other"> Other </h2>
</section>
</article>
<menu role="navigation" id="nav-bar" class="forward-only">
- <button id="back" class="button-left back" data-l10n-id="back">
- back
+ <button id="back" class="button-left back" data-l10n-id="navbar-back">
+ Back
<span></span>
</button>
- <button class="recommend forward" id="forward" data-l10n-id="next">
- next
+ <button class="recommend forward" id="forward" data-l10n-id="navbar-next">
+ Next
<span></span>
</button>
- <button class="recommend" id="wifi-join-button" data-l10n-id="join">
- join
+ <button class="recommend" id="wifi-join-button" data-l10n-id="navbar-join">
+ Join
</button>
</menu>
</section>
@@ -487,12 +487,12 @@ <h2 data-l10n-id="joinTutorial">
</section>
</article>
<nav role="navigation" id="tutorialNavBar" class="forward-only">
- <button id="backTutorial" class="button-left back" data-l10n-id="back">
- back
+ <button id="backTutorial" class="button-left back" data-l10n-id="navbar-back">
+ Back
<span></span>
</button>
- <button class="recommend forward" id="forwardTutorial" data-l10n-id="next">
- next
+ <button class="recommend forward" id="forwardTutorial" data-l10n-id="navbar-next">
+ Next
<span></span>
</button>
</nav>
View
6 apps/communications/ftu/locales/ftu.en-US.properties
@@ -160,9 +160,9 @@ privacy-e-me.title={{privacy-e-me}}
# Navigation bar
#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#
-back=back
-next=next
-join=join
+navbar-back=Back
+navbar-next=Next
+navbar-join=Join
skip=Skip
#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#=#
View
42 apps/costcontrol/fte.html
@@ -56,9 +56,34 @@
<li>Set data report and alert</li>
</ol>
- <!-- Step 1 -->
+ <!-- Global Step 1 -->
<section role="region" class="view step" data-viewport="" id="step-1">
<header>
+ <h1 data-l10n-id="fte-welcome-title">Welcome</h1>
+ </header>
+ <section class="content">
+ <div class="authed-sim" aria-hidden="true">
+ <h2 data-l10n-id="fte-authed-sim">Save money by keeping track of your phone and internet usage.</h2>
+ </div>
+ <div class="nonauthed-sim" aria-hidden="true">
+ <h2 data-l10n-id="fte-nonauthed-sim">Save money by keeping track of your internet usage.</h2>
+ </div>
+ <div class="no-sim" aria-hidden="true">
+ <h2 data-l10n-id="fte-no-sim">Get clear information about how much internet you're using.</h2>
+ </div>
+ <p data-l10n-id="fte-sim-info" class="info">Information shown on usage comes directly from this device. Check with your mobile service provider for detailed account information.</p>
+ </section>
+ <menu>
+ <button class="recommend" data-navigation="next">
+ <span></span>
+ <span data-l10n-id="next">Next</span>
+ </button>
+ </menu>
+ </section>
+
+ <!-- Step 2 -->
+ <section role="region" class="view step" data-viewport="right" id="step-2">
+ <header>
<h1 data-l10n-id="select-plan-type">Select your plan type</h1>
</header>
<ul class="content choices">
@@ -75,7 +100,11 @@ <h1 data-l10n-id="select-plan-type">Select your plan type</h1>
</label>
</li>
</ul>
- <menu>
+ <menu data-items="2">
+ <button data-navigation="back">
+ <span></span>
+ <span data-l10n-id="back">Back</span>
+ </button>
<button id="to-step-2" class="recommend" data-navigation="next">
<span></span>
<span data-l10n-id="next">Next</span>
@@ -97,7 +126,8 @@ <h1 data-l10n-id="set-balance-reminders">Set balance reminders</h1>
<p data-l10n-id="low-balance-alert">Low Balance alert</p>
</li>
<li>
- <label id="currency" class="end" for="ft-balance-alert-value">
+ <label class="end" for="ft-balance-alert-value">
+ <span id="currency"></span>
<input class="settings-option" data-option="lowLimitThreshold" data-disable-on="lowLimit=false" type="number" id="ft-balance-alert-value">
</label>
<p data-l10n-id="low-balance-explanation">Alert me when I’m under</p>
@@ -281,7 +311,11 @@ <h1 data-l10n-id="set-internet-data-report">Set internet data report</h1>
<p data-l10n-id="starting-on">Starting on</p>
</li>
</ul>
- <menu data-items="1">
+ <menu data-items="2">
+ <button data-navigation="back">
+ <span></span>
+ <span data-l10n-id="back">Back</span>
+ </button>
<button class="recommend" data-navigation="next">
<span></span>
<span data-l10n-id="next">Next</span>
View
10 apps/costcontrol/js/app.js
@@ -11,19 +11,13 @@ var CostControlApp = (function() {
'use strict';
+
var costcontrol, initialized = false;
window.addEventListener('DOMContentLoaded', function _onDOMReady() {
var mobileConnection = window.navigator.mozMobileConnection;
- // No SIM
- if (!mobileConnection || mobileConnection.cardState === 'absent') {
- //TODO: Add a message saying there is no functionality when no SIM
- // then close
- window.close();
- return;
-
// SIM is not ready
- } else if (mobileConnection.cardState !== 'ready') {
+ if (mobileConnection.cardState !== 'ready') {
debug('SIM not ready:', mobileConnection.cardState);
mobileConnection.oniccinfochange = _onDOMReady;
View
59 apps/costcontrol/js/fte.js
@@ -7,11 +7,37 @@
'use strict';
var costcontrol;
+ var hasSim = true;
window.addEventListener('DOMContentLoaded', function _onDOMReady() {
+ var mobileConnection = window.navigator.mozMobileConnection;
+ var stepsLeft = 2;
+
+ // No SIM
+ if (!mobileConnection || mobileConnection.cardState === 'absent') {
+ hasSim = false;
+ trySetup();
+
+ // SIM is not ready
+ } else if (mobileConnection.cardState !== 'ready') {
+ debug('SIM not ready:', mobileConnection.cardState);
+ mobileConnection.oniccinfochange = _onDOMReady;
+
+ // SIM is ready
+ } else {
+ mobileConnection.oniccinfochange = undefined;
+ trySetup();
+ }
+
CostControl.getInstance(function _onCostControl(instance) {
costcontrol = instance;
- setupFTE();
+ trySetup();
});
+
+ function trySetup() {
+ if (!(--stepsLeft)) {
+ setupFTE();
+ }
+ }
});
var wizard, vmanager;
@@ -23,18 +49,37 @@
AutoSettings.addType('data-limit', dataLimitConfigurer);
// Currency is set by config as well
- if (configuration && configuration.credit && configuration.credit.currency) {
- document.getElementById('currency').textContent = configuration.credit.currency;
+ if (configuration && configuration.credit
+ && configuration.credit.currency) {
+
+ document.getElementById('currency').textContent =
+ configuration.credit.currency;
}
var mode = costcontrol.getApplicationMode(settings);
+
+ // Handle welcome screen
+ var selectors = {
+ PREPAID: '.authed-sim',
+ POSTPAID: '.authed-sim',
+ DATA_USAGE_ONLY: '.nonauthed-sim'
+ };
+
+ var selector = hasSim ? selectors[mode] : '.no-sim';
+ wizard.querySelector(selector).setAttribute('aria-hidden', false);
+ if (!hasSim) {
+ wizard.querySelector('p.info').setAttribute('aria-hidden', true);
+ }
+
if (mode === 'DATA_USAGE_ONLY') {
debug('FTE for non supported SIM');
- reset(['non-vivo-step-1', 'non-vivo-step-2']);
+ wizard.dataset.steps = '3';
+ reset(['step-1', 'non-vivo-step-1', 'non-vivo-step-2']);
AutoSettings.initialize(ConfigManager, vmanager, '#non-vivo-step-1');
AutoSettings.initialize(ConfigManager, vmanager, '#non-vivo-step-2');
} else {
+ wizard.dataset.steps = '4';
AutoSettings.initialize(ConfigManager, vmanager, '#step-1');
// Plantype selection
@@ -67,15 +112,15 @@
// TRACK SETUP
- var currentTrack = ['step-1'];
+ var currentTrack = ['step-1', 'step-2'];
function selectTrack(evt) {
if (evt.target.value === 'prepaid') {
- currentTrack = ['step-1', 'prepaid-step-2', 'prepaid-step-3'];
+ currentTrack = ['step-1', 'step-2', 'prepaid-step-2', 'prepaid-step-3'];
AutoSettings.initialize(ConfigManager, vmanager, '#prepaid-step-2');
AutoSettings.initialize(ConfigManager, vmanager, '#prepaid-step-3');
ConfigManager.setOption({ dataLimitValue: 40, dataLimitUnit: 'MB' });
} else if (evt.target.value === 'postpaid') {
- currentTrack = ['step-1', 'postpaid-step-2', 'postpaid-step-3'];
+ currentTrack = ['step-1', 'step-2', 'postpaid-step-2', 'postpaid-step-3'];
AutoSettings.initialize(ConfigManager, vmanager, '#postpaid-step-2');
AutoSettings.initialize(ConfigManager, vmanager, '#postpaid-step-3');
ConfigManager.setOption({ dataLimitValue: 2, dataLimitUnit: 'GB' });
View
40 apps/costcontrol/js/message_handler.js
@@ -6,16 +6,31 @@
function inStandAloneMode() {
return window.parent.location.pathname === '/message_handler.html';
}
+ // XXX: This case implies that message handler triggered by system
+ // (inStandAlone check) has replaced CC application (history's length check).
+ //
+ // This only occurs when the system (window manager) has detected there is
+ // already an iframe for CC application, it is in background and it is
+ // not the message handler. So, as the CC index.html uses the this file
+ // inside an iframe (no standalone mode), all the messages should be attended
+ // so we can conclude **there is nothing to do**.
+ if (inStandAloneMode() && window.history.length > 1) {
+ debug('Nothing to do, closing...')
+ window.history.back();
+ }
function inApplicationMode() {
return window.parent.location.pathname === '/index.html';
}
// Close if in standalone mode
- function closeIfProceed() {
+ function closeIfProceeds() {
+ debug('Trying to close...');
if (inStandAloneMode()) {
- setTimeout(window.close, 1000);
- debug('Closing message handler');
+ setTimeout(function _close() {
+ window.close();
+ debug('Closing message handler');
+ }, 500);
}
}
@@ -65,7 +80,7 @@
// Non expected SMS
if (configuration.balance.senders.indexOf(sms.sender) === -1 &&
configuration.topup.senders.indexOf(sms.sender) === -1) {
- closeIfProceed();
+ closeIfProceeds();
return;
}
@@ -122,7 +137,7 @@
debug('Balance up to date and stored');
debug('Trying to synchronize!');
localStorage['sync'] = 'lastBalance#' + Math.random();
- closeIfProceed();
+ closeIfProceeds();
}
);
} else if (isConfirmation) {
@@ -135,7 +150,7 @@
debug('TopUp confirmed!');
debug('Trying to synchronize!');
localStorage['sync'] = 'waitingForTopUp#' + Math.random();
- closeIfProceed();
+ closeIfProceeds();
}
);
} else if (isError) {
@@ -149,7 +164,7 @@
debug('Balance up to date and stored');
debug('Trying to synchronize!');
localStorage['sync'] = 'errors#' + Math.random();
- closeIfProceed();
+ closeIfProceeds();
}
);
}
@@ -168,7 +183,7 @@
debug('Timeout for balance');
debug('Trying to synchronize!');
localStorage['sync'] = 'errors#' + Math.random();
- closeIfProceed();
+ closeIfProceeds();
}
);
});
@@ -183,7 +198,7 @@
debug('Timeout for topup');
debug('Trying to synchronize!');
localStorage['sync'] = 'errors#' + Math.random();
- closeIfProceed();
+ closeIfProceeds();
}
);
});
@@ -193,6 +208,7 @@
ConfigManager.requestSettings(function _onSettings(settings) {
resetAll();
updateNextReset(settings.trackingPeriod, settings.resetTime);
+ closeIfProceeds();
});
break;
}
@@ -208,9 +224,10 @@
settings.lastTelephonyActivity.timestamp = new Date();
settings.lastTelephonyActivity.smscount += realCount;
ConfigManager.setOption({
- lastDataUsage: settings.lastTelephonyActivity
+ lastTelephonyActivity: settings.lastTelephonyActivity
}, function _sync() {
localStorage['sync'] = 'lastTelephonyActivity#' + Math.random();
+ closeIfProceeds();
});
});
});
@@ -226,9 +243,10 @@
settings.lastTelephonyActivity.timestamp = new Date();
settings.lastTelephonyActivity.calltime += tcall.duration;
ConfigManager.setOption({
- lastDataUsage: settings.lastTelephonyActivity
+ lastTelephonyActivity: settings.lastTelephonyActivity
}, function _sync() {
localStorage['sync'] = 'lastTelephonyActivity#' + Math.random();
+ closeIfProceeds();
});
});
}
View
18 apps/costcontrol/js/utils/debug.js
@@ -1,25 +1,25 @@
var debug = (function() {
- var DEBUG_ID = 0;
+ var SEQ_ID = 0;
+ var PROCESS_ID = Date.now();
var DEBUGGING = false;
var DEBUG_PREFIX = 'CC';
- var currentWindow = window;
-
- return function() {
+ return function _debug() {
if (!DEBUGGING)
return;
- var parents = [currentWindow.location.pathname];
- while (currentWindow.location.pathname !==
- currentWindow.parent.location.pathname) {
+ var currentWindow = window;
+ var parents = [];
+ while (currentWindow !== currentWindow.parent) {
parents.push(currentWindow.location.pathname);
currentWindow = currentWindow.parent;
}
+ parents.push(currentWindow.location.pathname);
parents = parents.reverse().join('>') + ':';
- var uId = DEBUG_ID++;
- var message = ['(' + uId + ')', DEBUG_PREFIX, parents];
+ var uId = PROCESS_ID;
+ var message = ['(' + uId + '-' + (SEQ_ID++) + ')', DEBUG_PREFIX, parents];
for (var i = 0, len = arguments.length, obj; i < len; i++) {
obj = arguments[i];
message.push(typeof obj === 'object' ? JSON.stringify(obj) : obj);
View
1  apps/costcontrol/js/views/telephony.js
@@ -72,6 +72,7 @@ var TelephonyTab = (function() {
ConfigManager.requestSettings(function _onSettings(settings) {
costcontrol.request(requestObj, function _afterRequest(result) {
var telephonyActivity = result.data;
+ debug('Last telephony activity:', telephonyActivity);
updateTimePeriod(settings.lastTelephonyReset, null, null, settings);
updateCounters(telephonyActivity);
updateNextReset(settings.nextReset, null, null, settings);
View
44 apps/costcontrol/js/widget.js
@@ -13,13 +13,14 @@
'use strict';
var costcontrol;
+ var hasSim = true;
window.addEventListener('DOMContentLoaded', function _onDOMReady() {
var mobileConnection = window.navigator.mozMobileConnection;
// No SIM
if (!mobileConnection || mobileConnection.cardState === 'absent') {
- //TODO: Put the NO SIM message
- return;
+ hasSim = false;
+ _startWidget();
// SIM is not ready
} else if (mobileConnection.cardState !== 'ready') {
@@ -47,12 +48,13 @@
updateUI();
});
- var initialized, widget, leftPanel, rightPanel, views = {};
+ var initialized, widget, leftPanel, rightPanel, fte, views = {};
function setupWidget() {
// HTML entities
widget = document.getElementById('cost-control');
leftPanel = document.getElementById('left-panel');
rightPanel = document.getElementById('right-panel');
+ fte = document.getElementById('fte-view');
views.dataUsage = document.getElementById('datausage-view');
views.limitedDataUsage = document.getElementById('datausage-limit-view');
views.telephony = document.getElementById('telephony-view');
@@ -122,12 +124,48 @@
// USER INTERFACE
+ function setupFte(provider, mode) {
+
+ fte.setAttribute('aria-hidden', false);
+
+ fte.addEventListener('click', function launchFte() {
+ fte.removeEventListener('click', launchFte);
+ var activity = new MozActivity({ name: 'costcontrol/balance' });
+ });
+
+ leftPanel.setAttribute('aria-hidden', true);
+ rightPanel.setAttribute('aria-hidden', true);
+
+ var keyLookup = {
+ PREPAID: 'widget-authed-sim',
+ POSTPAID: 'widget-authed-sim',
+ DATA_USAGE_ONLY: 'widget-nonauthed-sim'
+ };
+
+ var simKey = hasSim ? keyLookup[mode] : 'widget-no-sim';
+
+ document.getElementById('fte-icon').className = 'icon ' + simKey;
+
+ fte.querySelector('p:first-child').innerHTML = navigator.mozL10n.get(simKey + '-heading', { provider: provider });
+ fte.querySelector('p:last-child').innerHTML = navigator.mozL10n.get(simKey + '-meta');
+ }
+
var currentMode;
function updateUI() {
+
ConfigManager.requestAll(function _onInfo(configuration, settings) {
var mode = costcontrol.getApplicationMode(settings);
debug('Widget UI mode:', mode);
+ // Show 'fte' widget
+ if (ConfigManager.option('fte')) {
+ setupFte(configuration.provider, mode);
+ return;
+ }
+ fte.setAttribute('aria-hidden', true);
+ leftPanel.setAttribute('aria-hidden', false);
+ rightPanel.setAttribute('aria-hidden', false);
+
var isPrepaid = (mode === 'PREPAID');
var isDataUsageOnly = (mode === 'DATA_USAGE_ONLY');
View
14 apps/costcontrol/locales/costcontrol.en-US.properties
@@ -14,6 +14,20 @@ never = Never
magnitude = {{value}} {{unit}}
currency = {{currency}}{{value}}
+# FTE Widget
+widget-authed-sim-heading = New {{provider}} SIM inserted
+widget-authed-sim-meta = Tap to track your phone and internet usage.
+widget-nonauthed-sim-heading = New SIM inserted
+widget-nonauthed-sim-meta = Tap to track your internet usage.
+widget-no-sim-heading = No SIM inserted
+widget-no-sim-meta = Tap to track your WiFi usage.
+
+# FTE Welcome
+fte-authed-sim = Save money by keeping track of your phone and internet usage.
+fte-nonauthed-sim = Save money by keeping track of your internet usage.
+fte-no-sim = Get clear information about how much internet you're using.
+fte-sim-info = Information shown on usage comes directly from this device. Check with your mobile service provider for detailed account information.
+
# In the HTML
phone-activity = Phone Activity
View
BIN  apps/costcontrol/style/images/widget/sim/authed-sim.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  apps/costcontrol/style/images/widget/sim/no-sim.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  apps/costcontrol/style/images/widget/sim/nonauthed-sim.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
27 apps/costcontrol/style/views/firsttime.css
@@ -34,6 +34,10 @@ body[role="application"] [role="dialog"] {
transition: all 0.35s cubic-bezier(0.000, 1.000, 0.535, 1.110);
}
+#firsttime-view[data-steps="4"] .step-state:before {
+ width: calc(100% / 4);
+}
+
/* STATES */
#firsttime-view.step-1 .step-state:before {
transform: translateX(0);
@@ -47,12 +51,25 @@ body[role="application"] [role="dialog"] {
transform: translateX(200%);
}
+#firsttime-view.step-4 .step-state:before {
+ transform: translateX(300%);
+}
+
/* Content */
- #firsttime-view .content {
- padding: 2.5rem 1.5rem 0;
- list-style: none;
- margin: 0;
- }
+#firsttime-view .content {
+ padding: 3.5rem 1.5rem 0;
+ list-style: none;
+ margin: 0;
+}
+
+#firsttime-view .content h2 {
+ font-size: 1.9rem;
+ margin-bottom: 1.6rem;
+}
+
+#firsttime-view .content p {
+ font-size: 1.6rem;
+}
/* General menu */
#firsttime-view .step menu {
View
32 apps/costcontrol/style/widget.css
@@ -59,6 +59,38 @@ p.meta {
float: none;
}
+/* FTE */
+.widget-authed-sim {
+ background: url(images/widget/sim/authed-sim.png);
+}
+
+.widget-nonauthed-sim {
+ background: url(images/widget/sim/nonauthed-sim.png);
+}
+
+.widget-no-sim {
+ background: url(images/widget/sim/no-sim.png);
+}
+
+#fte-view .icon {
+ float:left;
+ margin-left: 0.5rem;
+ width: 3.75rem;
+ height: 4.5rem;
+ vertical-align: middle;
+ background-position: center;
+ background-repeat: no-repeat;
+}
+
+#fte-view p.meta {
+ font-size:1.4em;
+}
+
+#fte-view p:not(.meta) {
+ font-weight: bold;
+ font-size: 1.5em;
+}
+
/* Credit & Data structure */
.credit,
.data {
View
8 apps/costcontrol/widget.html
@@ -23,6 +23,14 @@
<body>
<section id="cost-control">
+ <section id="fte-view" aria-hidden="true">
+ <span id="fte-icon" class="icon"></span>
+ <div class="info">
+ <p></p>
+ <p class="meta"></p>
+ </div>
+ </section>
+
<section class="credit" id="left-panel">
<section class="view" id="balance-view">
View
8 apps/email/index.html
@@ -302,7 +302,7 @@ <h3 class="msg-envelope-subject"></h3>
</section>
<div class="scrollregion-below-header">
<div class="cmp-envelope-bar">
- <div class="cmp-envelope-line">
+ <div class="cmp-envelope-line cmp-combo">
<span class="cmp-to-label cmp-addr-label"
data-l10n-id="compose-to">tO:</span>
<div class="cmp-to-container cmp-addr-container">
@@ -315,7 +315,7 @@ <h3 class="msg-envelope-subject"></h3>
<!-- XXX: spec calls for showing cc/bcc merged until selected,
but there is also the case where replying itself might need
to expand, so we are deferring that feature -->
- <div class="cmp-envelope-line">
+ <div class="cmp-envelope-line cmp-combo">
<span class="cmp-cc-label cmp-addr-label"
data-l10n-id="compose-cc">cC:</span>
<div class="cmp-cc-container cmp-addr-container">
@@ -325,7 +325,7 @@ <h3 class="msg-envelope-subject"></h3>
<div class="cmp-cc-add cmp-contact-add"></div>
</div>
</div>
- <div class="cmp-envelope-line">
+ <div class="cmp-envelope-line cmp-combo">
<span class="cmp-bcc-label cmp-addr-label"
data-l10n-id="compose-bcc">BcC:</span>
<div class="cmp-bcc-container cmp-addr-container">
@@ -335,7 +335,7 @@ <h3 class="msg-envelope-subject"></h3>
<div class="cmp-bcc-add cmp-contact-add"></div>
</div>
</div>
- <div class="cmp-envelope-line">
+ <div class="cmp-envelope-line cmp-subject">
<span class="cmp-subject-label"
data-l10n-id="compose-subject">SubjecT:</span>
<input class="cmp-subject-text" type="text" />
View
8 apps/email/js/compose-cards.js
@@ -46,12 +46,18 @@ function ComposeCard(domNode, mode, args) {
addBtns[i].addEventListener('click', this.onContactAdd.bind(this));
}
// Add input focus:
- var containerList = domNode.getElementsByClassName('cmp-bubble-container');
+ var containerList = domNode.getElementsByClassName('cmp-combo');
for (var i = 0; i < containerList.length; i++) {
containerList[i].addEventListener('click',
this.onContainerClick.bind(this));
}
+ // Add subject focus for larger hitbox
+ var subjectContainer = domNode.querySelector('.cmp-subject');
+ subjectContainer.addEventListener('click', function subjectFocus() {
+ subjectContainer.querySelector('input').focus();
+ });
+
// Add attachments
var attachmentsContainer =
domNode.getElementsByClassName('cmp-attachments-container')[0];
View
54 apps/email/js/mail-app.js
@@ -6,6 +6,8 @@
var MailAPI = null;
var App = {
+ initialized: false,
+
/**
* Bind any global notifications, relay localizations to the back-end.
*/
@@ -53,6 +55,7 @@ var App = {
archives: mozL10n.get('folder-archives')
}
});
+ this.initialized = true;