Skip to content
This repository has been archived by the owner on Nov 3, 2021. It is now read-only.

Commit

Permalink
Merge pull request #15842 from lodr/bug-963682-providing-ux-for-non-r…
Browse files Browse the repository at this point in the history
…eady-sim

Bug 963682 - Providing a fake modal dialog to prevent the user to interact with the application unless the SIM is ready. r=mai
(cherry picked from commit 397f3aa)
  • Loading branch information
delapuente authored and jhford committed Feb 3, 2014
1 parent 4cc9855 commit bb36b41
Show file tree
Hide file tree
Showing 7 changed files with 325 additions and 102 deletions.
41 changes: 29 additions & 12 deletions apps/costcontrol/index.html
Expand Up @@ -9,6 +9,10 @@

<!-- Building blocks Temporal -->
<link rel="stylesheet" type="text/css" href="style/bb/input-areas/style.css">
<link rel="stylesheet" type="text/css" href="style/bb/menus-dialogues/valueselector/date/style.css">
<link rel="stylesheet" type="text/css" href="style/bb/menus-dialogues/valueselector/style.css">
<link rel="stylesheet" type="text/css" href="style/bb/menus-dialogues/core.css">
<link rel="stylesheet" type="text/css" href="style/bb/menus-dialogues/prompt/style.css">

<!-- Building blocks -->
<link rel="stylesheet" type="text/css" href="shared/style/headers.css">
Expand Down Expand Up @@ -46,6 +50,7 @@
<script type="text/javascript" defer src="js/common.js"></script>
<script type="text/javascript" defer src="js/costcontrol.js"></script>
<script type="text/javascript" defer src="js/costcontrol_init.js"></script>
<script type="text/javascript" defer src="js/views/NonReadyScreen.js"></script>
<script type="text/javascript" defer src="js/view_manager.js"></script>
<script type="text/javascript" defer src="js/app.js"></script>

Expand Down Expand Up @@ -90,26 +95,38 @@ <h1 data-l10n-id="usage">Usage</h1>
</li>
</ul>

<!-- BALANCE TAB -->
<section is="balance-tab" role="region" id="balance-tab" class="view" data-viewport="left" hidden></section>
<!-- BALANCE TAB -->
<section is="balance-tab" role="region" id="balance-tab" class="view" data-viewport="left" hidden></section>

<!-- TELEPHONY TAB -->
<section is="telephony-tab" role="region" id="telephony-tab" class="view" data-viewport="left" hidden></section>
<!-- TELEPHONY TAB -->
<section is="telephony-tab" role="region" id="telephony-tab" class="view" data-viewport="left" hidden></section>

<!-- The top up input -->
<section is="topup-dialog" role="region" id="topup-dialog" class="view" data-viewport="bottom" hidden></section>
<!-- The top up input -->
<section is="topup-dialog" role="region" id="topup-dialog" class="view" data-viewport="bottom" hidden></section>

<!-- DATA USAGE TAB -->
<section is="datausage-tab" id="datausage-tab" role="region" class="view" data-viewport="right" hidden></section
<!-- DATA USAGE TAB -->
<section is="datausage-tab" id="datausage-tab" role="region" class="view" data-viewport="right" hidden></section>

<!-- Settings view -->
<section id="settings-view" class="view" data-viewport="bottom">
<iframe id="settings-view-placeholder"></iframe>
</section>
<!-- Settings view -->
<section id="settings-view" class="view" data-viewport="bottom">
<iframe id="settings-view-placeholder"></iframe>
</section>

</section>
<iframe id="message-handler" src="">
</iframe>
<iframe id="fte_view" class="window non-ready"></iframe>

<!-- SIM non ready screen -->
<section role="dialog" class="view" data-viewport="ethereal" id="non-ready-screen">
<div class="center">
<h3>Card is not ready</h3>
<p>The button will close the application.</p>
<progress></progress>
</div>
<menu>
<button class="full" data-l10n-id="confirm">Ok</button>
</menu>
</section>
</body>
</html>
128 changes: 69 additions & 59 deletions apps/costcontrol/js/app.js
Expand Up @@ -40,78 +40,85 @@ var CostControlApp = (function() {
'use strict';

var costcontrol, initialized = false;
function checkSIMStatus(callback) {

var iccid = Common.dataSimIccId;
var dataSimIccInfo = Common.dataSimIcc;
var cardState = checkCardState();

// SIM not ready
if (cardState !== 'ready') {
debug('SIM not ready:', cardState);
dataSimIccInfo.oncardstatechange = checkSIMStatus;

// SIM is ready, but ICC info is not ready yet
} else if (!Common.isValidICCID(iccid)) {
debug('ICC info not ready yet');
dataSimIccInfo.oniccinfochange = checkSIMStatus;

// All ready
} else {
debug('SIM ready. ICCID:', iccid);
dataSimIccInfo.oncardstatechange = undefined;
dataSimIccInfo.oniccinfochange = undefined;
document.getElementById('message-handler').src = 'message_handler.html';
Common.waitForDOMAndMessageHandler(window, startApp.bind(null, callback));
}
}

// Check the card status. Return 'ready' if all OK or take actions for
// special situations such as 'pin/puk locked' or 'absent'.
function checkCardState() {
var state, cardState;
state = cardState = Common.dataSimIcc.cardState;
var vmanager;

// Set the application in waiting for SIM mode. During this mode, the
// application shows a dialog informing about the current situation of the
// SIM. Once ready, callback is executed.
function waitForSIMReady(callback) {
Common.loadDataSIMIccId(function _onIccId(iccid) {
var iccid = Common.dataSimIccId;
var dataSimIccInfo = Common.dataSimIcc;
var cardState = dataSimIccInfo && dataSimIccInfo.cardState;

// SIM not ready
if (cardState !== 'ready') {
showNonReadyScreen(cardState);
debug('SIM not ready:', cardState);
dataSimIccInfo.oncardstatechange = function() {
waitForSIMReady(callback);
};

// SIM is absent
if (!cardState || cardState === 'absent') {
debug('There is no SIM');
showSimErrorDialog('no-sim2');
// SIM is ready, but ICC info is not ready yet
} else if (!Common.isValidICCID(iccid)) {
showNonReadyScreen(cardState);
debug('ICC info not ready yet');
dataSimIccInfo.oniccinfochange = function() {
waitForSIMReady(callback);
};

// SIM is locked
} else if (
cardState === 'pinRequired' ||
cardState === 'pukRequired'
) {
showSimErrorDialog('sim-locked');
state = 'locked';
}
// All ready
} else {
hideNotReadyScreen();
debug('SIM ready. ICCID:', iccid);
dataSimIccInfo.oncardstatechange = undefined;
dataSimIccInfo.oniccinfochange = undefined;
callback && callback();
}

return state;
// In case we can not get a valid ICCID.
}, function _errorNoSim() {
console.warn('Error when trying to get the ICC ID');
showNonReadyScreen(null);
});
}

function showSimErrorDialog(status) {
function realShowSimError(status) {
var header = _('widget-' + status + '-heading');
var msg = _('widget-' + status + '-meta');
Common.modalAlert(header + '\n' + msg);
Common.closeApplication();
}
// Displays a faked modal dialog that can be automatically close when the SIM
// is ready. A second call if it is already shown will only update the
// message.
var nonReadyScreen;
function showNonReadyScreen(cardState) {

if (isApplicationLocalized) {
realShowSimError(status);
realshowNonReadyScreen(cardState);
} else {
window.addEventListener('localized', function _onlocalized() {
window.removeEventListener('localized', _onlocalized);
realShowSimError(status);
realshowNonReadyScreen(cardState);
});
}

function realshowNonReadyScreen(messageId) {
debug('Showing non-ready screen.');
if (!nonReadyScreen) {
nonReadyScreen =
new NonReadyScreen(document.getElementById('non-ready-screen'));
}
nonReadyScreen.updateForState(cardState);
vmanager.changeViewTo(nonReadyScreen.id);
}
}

function hideNotReadyScreen(status) {
debug('Hiding non-ready screen.');
vmanager.closeCurrentView();
return;
}

// XXX: See the module documentation for details about URL schema
var vmanager, tabmanager, settingsVManager;
var tabmanager, settingsVManager;
function setupCardHandler() {
// View managers for dialogs and settings
vmanager = new ViewManager();
tabmanager = new ViewManager(
['balance-tab', 'telephony-tab', { id: 'datausage-tab', tab: 'right' }]
);
Expand Down Expand Up @@ -271,7 +278,7 @@ var CostControlApp = (function() {
document.addEventListener('visibilitychange',
function _onVisibilityChange(evt) {
if (!document.hidden && initialized) {
checkCardState(Common.dataSimIcc);
waitForSIMReady();
}
}
);
Expand Down Expand Up @@ -383,9 +390,11 @@ var CostControlApp = (function() {

return {
init: function() {
Common.loadDataSIMIccId(checkSIMStatus, function _errorNoSim() {
console.warn('Error when trying to get the ICC ID');
showSimErrorDialog('no-sim2');
vmanager = new ViewManager();
waitForSIMReady(function _onSIMReady() {
document
.getElementById('message-handler').src = 'message_handler.html';
Common.waitForDOMAndMessageHandler(window, startApp);
});
// XXX: See bug 944342 -[Cost control] move all the process related to the
// network and data interfaces loading to the start-up process of CC
Expand All @@ -400,6 +409,7 @@ var CostControlApp = (function() {
currentMode = null;
isApplicationLocalized = false;
window.location.hash = '';
nonReadyScreen = null;
},
showBalanceTab: function _showBalanceTab() {
window.location.hash = '#balance-tab';
Expand Down
74 changes: 74 additions & 0 deletions apps/costcontrol/js/views/NonReadyScreen.js
@@ -0,0 +1,74 @@
'use strict';

/* global Common */
/* global _ */

function NonReadyScreen(container) {
this.id = container.id;
this.container = container;
this.activity = container.querySelector('progress');
this.header = container.querySelector('h3');
this.message = container.querySelector('p');
this.button = container.querySelector('button');

this.button.onclick = Common.closeApplication;
}

// Configure the non ready screen depending on the card status. For
// absent, pinRequired and pukRequired, shows a message and give the
// user the opportunity to close the app. For other states, it shows
// a progress spinner.
NonReadyScreen.prototype.updateForState = function(cardState) {
switch (cardState) {
case null:
case 'absent':
case 'pinRequired':
case 'pukRequired':
this.setMessageMode(cardState);
break;

default:
this.setWaitingMode();
break;
}
};

NonReadyScreen.prototype.setMessageMode = function(cardState) {
this.activity.setAttribute('aria-hidden', true);
[this.header, this.message, this.button.parentNode].forEach(function (el) {
el.setAttribute('aria-hidden', false);
});

var messageId = this.getMessageIdFor(cardState);
if (messageId) {
var header = _('widget-' + messageId + '-heading');
var msg = _('widget-' + messageId + '-meta');
this.header.textContent = header;
this.message.textContent = msg;
}
};

NonReadyScreen.prototype.setWaitingMode = function() {
this.activity.setAttribute('aria-hidden', false);
[this.header, this.message, this.button.parentNode].forEach(function (el) {
el.setAttribute('aria-hidden', true);
});
};

NonReadyScreen.prototype.getMessageIdFor = function(cardState) {
var message;

// SIM is absent
if (!cardState || cardState === 'absent') {
message = 'no-sim2';

// SIM is locked
} else if (
cardState === 'pinRequired' ||
cardState === 'pukRequired'
) {
message = 'sim-locked';
}

return message;
};
2 changes: 1 addition & 1 deletion apps/costcontrol/test/unit/mock_common.js
Expand Up @@ -73,7 +73,7 @@ var MockCommon = function(config) {
setTimeout(function() {
self.dataSimIccId = fakeAllInterfaces[1].id;
if (typeof onsuccess === 'function') {
onsuccess();
onsuccess(self.dataSimIccId);
}
}, 0);
}
Expand Down
11 changes: 11 additions & 0 deletions apps/costcontrol/test/unit/mock_non_ready_screen.js
@@ -0,0 +1,11 @@
'use strict';

function MockNonReadyScreen(container) {
this.id = container.id;
}

MockNonReadyScreen.prototype.updateForState = function(cardState) {
var event = new CustomEvent('nonReadyScreenUpdated', { detail: cardState });
window.dispatchEvent(event);
console.log('NonReadyScreen in state: ' + cardState);
};

0 comments on commit bb36b41

Please sign in to comment.