mirror of
https://github.com/moparisthebest/mail
synced 2024-11-22 00:42:20 -05:00
[WO-475] give backbutton on android sane behavior
This commit is contained in:
parent
64daec7536
commit
3a713180f1
@ -21,6 +21,7 @@
|
||||
"console",
|
||||
"importScripts",
|
||||
"process",
|
||||
"Event",
|
||||
"QUnit",
|
||||
"test",
|
||||
"asyncTest",
|
||||
|
@ -24,6 +24,7 @@ define(function(require) {
|
||||
InvitationDAO = require('js/dao/invitation-dao'),
|
||||
DeviceStorageDAO = require('js/dao/devicestorage-dao'),
|
||||
UpdateHandler = require('js/util/update/update-handler'),
|
||||
backBtnHandler = require('js/util/backbutton-handler'),
|
||||
config = appConfig.config,
|
||||
str = appConfig.string;
|
||||
|
||||
@ -54,6 +55,7 @@ define(function(require) {
|
||||
function onDeviceReady() {
|
||||
axe.debug('Starting app.');
|
||||
|
||||
backBtnHandler.start();
|
||||
self.buildModules();
|
||||
|
||||
// Handle offline and online gracefully
|
||||
|
@ -23,6 +23,7 @@ requirejs([
|
||||
'js/controller/navigation',
|
||||
'js/crypto/util',
|
||||
'js/util/error',
|
||||
'js/util/backbutton-handler',
|
||||
'fastclick',
|
||||
'angularRoute',
|
||||
'angularAnimate',
|
||||
@ -49,6 +50,7 @@ requirejs([
|
||||
NavigationCtrl,
|
||||
util,
|
||||
errorUtil,
|
||||
backButtonUtil,
|
||||
FastClick
|
||||
) {
|
||||
'use strict';
|
||||
@ -113,8 +115,13 @@ requirejs([
|
||||
app.run(function($rootScope) {
|
||||
// global state... inherited to all child scopes
|
||||
$rootScope.state = {};
|
||||
|
||||
// attach global error handler
|
||||
errorUtil.attachHandler($rootScope);
|
||||
|
||||
// attach the back button handler to the root scope
|
||||
backButtonUtil.attachHandler($rootScope);
|
||||
|
||||
// attach fastclick
|
||||
FastClick.attach(document.body);
|
||||
});
|
||||
|
58
src/js/util/backbutton-handler.js
Normal file
58
src/js/util/backbutton-handler.js
Normal file
@ -0,0 +1,58 @@
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var axe = require('axe'),
|
||||
DEBUG_TAG = 'backbutton handler';
|
||||
|
||||
/**
|
||||
* The back button handler introduces meaningful behavior fo rthe back button:
|
||||
* if there's an open lightbox, close it;
|
||||
* if the reader is open in mobile mode, close it;
|
||||
* if the navigation is open, close it;
|
||||
* if there's nothing else open, shut down the app;
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
var backBtnHandler = {
|
||||
attachHandler: function(scope) {
|
||||
this.scope = scope;
|
||||
},
|
||||
start: function() {
|
||||
document.addEventListener("backbutton", handleBackButton, false);
|
||||
},
|
||||
stop: function() {
|
||||
document.removeEventListener("backbutton", handleBackButton, false);
|
||||
}
|
||||
};
|
||||
|
||||
function handleBackButton(event) {
|
||||
axe.debug(DEBUG_TAG, 'back button pressed');
|
||||
|
||||
// this disarms the default behavior which we NEVER want
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
if (backBtnHandler.scope.state.lightbox) {
|
||||
// closes the lightbox (error msgs, writer, ...)
|
||||
backBtnHandler.scope.state.lightbox = undefined;
|
||||
axe.debug(DEBUG_TAG, 'lightbox closed');
|
||||
backBtnHandler.scope.$apply();
|
||||
} else if (backBtnHandler.scope.state.read && backBtnHandler.scope.state.read.open) {
|
||||
// closes the reader
|
||||
backBtnHandler.scope.state.read.toggle(false);
|
||||
axe.debug(DEBUG_TAG, 'reader closed');
|
||||
backBtnHandler.scope.$apply();
|
||||
} else if (backBtnHandler.scope.state.nav && backBtnHandler.scope.state.nav.open) {
|
||||
// closes the navigation
|
||||
backBtnHandler.scope.state.nav.toggle(false);
|
||||
axe.debug(DEBUG_TAG, 'navigation closed');
|
||||
backBtnHandler.scope.$apply();
|
||||
} else {
|
||||
// exits the app
|
||||
navigator.app.exitApp();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return backBtnHandler;
|
||||
});
|
67
test/unit/backbutton-handler-test.js
Normal file
67
test/unit/backbutton-handler-test.js
Normal file
@ -0,0 +1,67 @@
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
|
||||
var btnHandler = require('js/util/backbutton-handler'),
|
||||
expect = chai.expect;
|
||||
|
||||
describe('Backbutton Handler', function() {
|
||||
chai.Assertion.includeStack = true;
|
||||
|
||||
var scope, event;
|
||||
|
||||
beforeEach(function() {
|
||||
scope = {
|
||||
state: {},
|
||||
$apply: function() {}
|
||||
};
|
||||
|
||||
event = new CustomEvent('backbutton');
|
||||
|
||||
// this is a precondition for the test. throw an exception
|
||||
// if this would produce side effects
|
||||
expect(navigator.app).to.not.exist;
|
||||
navigator.app = {};
|
||||
|
||||
btnHandler.attachHandler(scope);
|
||||
btnHandler.start();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
btnHandler.stop();
|
||||
delete navigator.app;
|
||||
});
|
||||
|
||||
it('should close lightbox', function() {
|
||||
scope.state.lightbox = 'asd';
|
||||
document.dispatchEvent(event);
|
||||
expect(scope.state.lightbox).to.be.undefined;
|
||||
});
|
||||
|
||||
it('should close reader', function() {
|
||||
scope.state.read = {
|
||||
open: true,
|
||||
toggle: function(state) {
|
||||
scope.state.read.open = state;
|
||||
}
|
||||
};
|
||||
document.dispatchEvent(event);
|
||||
expect(scope.state.read.open).to.be.false;
|
||||
});
|
||||
|
||||
it('should close navigation', function() {
|
||||
scope.state.nav = {
|
||||
open: true,
|
||||
toggle: function(state) {
|
||||
scope.state.nav.open = state;
|
||||
}
|
||||
};
|
||||
document.dispatchEvent(event);
|
||||
expect(scope.state.nav.open).to.be.false;
|
||||
});
|
||||
|
||||
it('should close app', function(done) {
|
||||
navigator.app.exitApp = done;
|
||||
document.dispatchEvent(event);
|
||||
});
|
||||
});
|
||||
});
|
@ -22,6 +22,24 @@ if (!Function.prototype.bind) {
|
||||
};
|
||||
}
|
||||
|
||||
// a warm round of applause for phantomjs for missing events
|
||||
(function() {
|
||||
function CustomEvent(event, params) {
|
||||
params = params || {
|
||||
bubbles: false,
|
||||
cancelable: false,
|
||||
detail: undefined
|
||||
};
|
||||
var evt = document.createEvent('CustomEvent');
|
||||
evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);
|
||||
return evt;
|
||||
}
|
||||
|
||||
CustomEvent.prototype = window.Event.prototype;
|
||||
|
||||
window.CustomEvent = CustomEvent;
|
||||
})();
|
||||
|
||||
require(['../../src/require-config'], function() {
|
||||
require.config({
|
||||
baseUrl: '../../src/lib',
|
||||
@ -59,6 +77,7 @@ function startTests() {
|
||||
'test/unit/app-controller-test',
|
||||
'test/unit/pgp-test',
|
||||
'test/unit/crypto-test',
|
||||
'test/unit/backbutton-handler-test',
|
||||
'test/unit/rest-dao-test',
|
||||
'test/unit/publickey-dao-test',
|
||||
'test/unit/privatekey-dao-test',
|
||||
|
Loading…
Reference in New Issue
Block a user