mirror of
https://github.com/moparisthebest/mail
synced 2024-11-22 08:52:15 -05:00
[WO-475] give backbutton on android sane behavior
This commit is contained in:
parent
64daec7536
commit
3a713180f1
@ -21,6 +21,7 @@
|
|||||||
"console",
|
"console",
|
||||||
"importScripts",
|
"importScripts",
|
||||||
"process",
|
"process",
|
||||||
|
"Event",
|
||||||
"QUnit",
|
"QUnit",
|
||||||
"test",
|
"test",
|
||||||
"asyncTest",
|
"asyncTest",
|
||||||
|
@ -24,6 +24,7 @@ define(function(require) {
|
|||||||
InvitationDAO = require('js/dao/invitation-dao'),
|
InvitationDAO = require('js/dao/invitation-dao'),
|
||||||
DeviceStorageDAO = require('js/dao/devicestorage-dao'),
|
DeviceStorageDAO = require('js/dao/devicestorage-dao'),
|
||||||
UpdateHandler = require('js/util/update/update-handler'),
|
UpdateHandler = require('js/util/update/update-handler'),
|
||||||
|
backBtnHandler = require('js/util/backbutton-handler'),
|
||||||
config = appConfig.config,
|
config = appConfig.config,
|
||||||
str = appConfig.string;
|
str = appConfig.string;
|
||||||
|
|
||||||
@ -54,6 +55,7 @@ define(function(require) {
|
|||||||
function onDeviceReady() {
|
function onDeviceReady() {
|
||||||
axe.debug('Starting app.');
|
axe.debug('Starting app.');
|
||||||
|
|
||||||
|
backBtnHandler.start();
|
||||||
self.buildModules();
|
self.buildModules();
|
||||||
|
|
||||||
// Handle offline and online gracefully
|
// Handle offline and online gracefully
|
||||||
|
@ -23,6 +23,7 @@ requirejs([
|
|||||||
'js/controller/navigation',
|
'js/controller/navigation',
|
||||||
'js/crypto/util',
|
'js/crypto/util',
|
||||||
'js/util/error',
|
'js/util/error',
|
||||||
|
'js/util/backbutton-handler',
|
||||||
'fastclick',
|
'fastclick',
|
||||||
'angularRoute',
|
'angularRoute',
|
||||||
'angularAnimate',
|
'angularAnimate',
|
||||||
@ -49,6 +50,7 @@ requirejs([
|
|||||||
NavigationCtrl,
|
NavigationCtrl,
|
||||||
util,
|
util,
|
||||||
errorUtil,
|
errorUtil,
|
||||||
|
backButtonUtil,
|
||||||
FastClick
|
FastClick
|
||||||
) {
|
) {
|
||||||
'use strict';
|
'use strict';
|
||||||
@ -113,8 +115,13 @@ requirejs([
|
|||||||
app.run(function($rootScope) {
|
app.run(function($rootScope) {
|
||||||
// global state... inherited to all child scopes
|
// global state... inherited to all child scopes
|
||||||
$rootScope.state = {};
|
$rootScope.state = {};
|
||||||
|
|
||||||
// attach global error handler
|
// attach global error handler
|
||||||
errorUtil.attachHandler($rootScope);
|
errorUtil.attachHandler($rootScope);
|
||||||
|
|
||||||
|
// attach the back button handler to the root scope
|
||||||
|
backButtonUtil.attachHandler($rootScope);
|
||||||
|
|
||||||
// attach fastclick
|
// attach fastclick
|
||||||
FastClick.attach(document.body);
|
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(['../../src/require-config'], function() {
|
||||||
require.config({
|
require.config({
|
||||||
baseUrl: '../../src/lib',
|
baseUrl: '../../src/lib',
|
||||||
@ -59,6 +77,7 @@ function startTests() {
|
|||||||
'test/unit/app-controller-test',
|
'test/unit/app-controller-test',
|
||||||
'test/unit/pgp-test',
|
'test/unit/pgp-test',
|
||||||
'test/unit/crypto-test',
|
'test/unit/crypto-test',
|
||||||
|
'test/unit/backbutton-handler-test',
|
||||||
'test/unit/rest-dao-test',
|
'test/unit/rest-dao-test',
|
||||||
'test/unit/publickey-dao-test',
|
'test/unit/publickey-dao-test',
|
||||||
'test/unit/privatekey-dao-test',
|
'test/unit/privatekey-dao-test',
|
||||||
|
Loading…
Reference in New Issue
Block a user