Explorar o código

Make possible for apps to disallow the navigation bar slide gesture

On narrow screens a slide gesture can be used to open or close the
navigation bar. However that gesture could conflict at times with the
gestures used by certain apps (for example, if the right sidebar is open
the user may expect to close it by dragging it to the right, but that
could open the navigation bar instead depending on how the events are
handled). This commit makes possible for apps to disallow and allow
again that slide gesture.

In any case, note that applications can only disallow the gesture,
but they can not enable it. That is, they can prevent the gesture from
being used on narrow screens, but they can not make the gesture work on
wide screens; they are always limited by the base rules set by the core.

Signed-off-by: Daniel Calviño Sánchez <danxuliu@gmail.com>
Daniel Calviño Sánchez %!s(int64=6) %!d(string=hai) anos
pai
achega
a5db0d2825
Modificáronse 2 ficheiros con 353 adicións e 1 borrados
  1. 35 1
      core/js/js.js
  2. 318 0
      core/js/tests/specs/coreSpec.js

+ 35 - 1
core/js/js.js

@@ -1612,12 +1612,46 @@ function initCore() {
 			snapper.close();
 		});
 
+		var navigationBarSlideGestureEnabled = false;
+		var navigationBarSlideGestureAllowed = true;
+		var navigationBarSlideGestureEnablePending = false;
+
+		OC.allowNavigationBarSlideGesture = function() {
+			navigationBarSlideGestureAllowed = true;
+
+			if (navigationBarSlideGestureEnablePending) {
+				snapper.enable();
+
+				navigationBarSlideGestureEnabled = true;
+				navigationBarSlideGestureEnablePending = false;
+			}
+		};
+
+		OC.disallowNavigationBarSlideGesture = function() {
+			navigationBarSlideGestureAllowed = false;
+
+			if (navigationBarSlideGestureEnabled) {
+				snapper.disable();
+
+				navigationBarSlideGestureEnabled = false;
+				navigationBarSlideGestureEnablePending = true;
+			}
+		};
+
 		var toggleSnapperOnSize = function() {
 			if($(window).width() > 768) {
 				snapper.close();
 				snapper.disable();
-			} else {
+
+				navigationBarSlideGestureEnabled = false;
+				navigationBarSlideGestureEnablePending = false;
+			} else if (navigationBarSlideGestureAllowed) {
 				snapper.enable();
+
+				navigationBarSlideGestureEnabled = true;
+				navigationBarSlideGestureEnablePending = false;
+			} else {
+				navigationBarSlideGestureEnablePending = true;
 			}
 		};
 

+ 318 - 0
core/js/tests/specs/coreSpec.js

@@ -1162,6 +1162,90 @@ describe('Core base tests', function() {
 			expect(snapperStub.enable.calledOnce).toBe(true);
 			expect(snapperStub.disable.called).toBe(false);
 		});
+		it('is disabled when disallowing the gesture on a narrow screen', function() {
+			viewport.set(480);
+
+			window.initCore();
+
+			expect(snapperStub.enable.calledOnce).toBe(true);
+			expect(snapperStub.disable.called).toBe(false);
+			expect(snapperStub.close.called).toBe(false);
+
+			OC.disallowNavigationBarSlideGesture();
+
+			expect(snapperStub.enable.calledOnce).toBe(true);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+			expect(snapperStub.close.called).toBe(false);
+		});
+		it('is not disabled again when disallowing the gesture twice on a narrow screen', function() {
+			viewport.set(480);
+
+			window.initCore();
+
+			expect(snapperStub.enable.calledOnce).toBe(true);
+			expect(snapperStub.disable.called).toBe(false);
+			expect(snapperStub.close.called).toBe(false);
+
+			OC.disallowNavigationBarSlideGesture();
+
+			expect(snapperStub.enable.calledOnce).toBe(true);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+			expect(snapperStub.close.called).toBe(false);
+
+			OC.disallowNavigationBarSlideGesture();
+
+			expect(snapperStub.enable.calledOnce).toBe(true);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+			expect(snapperStub.close.called).toBe(false);
+		});
+		it('is enabled when allowing the gesture after disallowing it on a narrow screen', function() {
+			viewport.set(480);
+
+			window.initCore();
+
+			expect(snapperStub.enable.calledOnce).toBe(true);
+			expect(snapperStub.disable.called).toBe(false);
+			expect(snapperStub.close.called).toBe(false);
+
+			OC.disallowNavigationBarSlideGesture();
+
+			expect(snapperStub.enable.calledOnce).toBe(true);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+			expect(snapperStub.close.called).toBe(false);
+
+			OC.allowNavigationBarSlideGesture();
+
+			expect(snapperStub.enable.calledTwice).toBe(true);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+			expect(snapperStub.close.called).toBe(false);
+		});
+		it('is not enabled again when allowing the gesture twice after disallowing it on a narrow screen', function() {
+			viewport.set(480);
+
+			window.initCore();
+
+			expect(snapperStub.enable.calledOnce).toBe(true);
+			expect(snapperStub.disable.called).toBe(false);
+			expect(snapperStub.close.called).toBe(false);
+
+			OC.disallowNavigationBarSlideGesture();
+
+			expect(snapperStub.enable.calledOnce).toBe(true);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+			expect(snapperStub.close.called).toBe(false);
+
+			OC.allowNavigationBarSlideGesture();
+
+			expect(snapperStub.enable.calledTwice).toBe(true);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+			expect(snapperStub.close.called).toBe(false);
+
+			OC.allowNavigationBarSlideGesture();
+
+			expect(snapperStub.enable.calledTwice).toBe(true);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+			expect(snapperStub.close.called).toBe(false);
+		});
 		it('is disabled on a wide screen', function() {
 			viewport.set(1280);
 
@@ -1171,6 +1255,42 @@ describe('Core base tests', function() {
 			expect(snapperStub.enable.called).toBe(false);
 			expect(snapperStub.disable.calledOnce).toBe(true);
 		});
+		it('is not disabled again when disallowing the gesture on a wide screen', function() {
+			viewport.set(1280);
+
+			window.initCore();
+
+			expect(snapperStub.enable.called).toBe(false);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+			expect(snapperStub.close.calledOnce).toBe(true);
+
+			OC.disallowNavigationBarSlideGesture();
+
+			expect(snapperStub.enable.called).toBe(false);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+			expect(snapperStub.close.calledOnce).toBe(true);
+		});
+		it('is not enabled when allowing the gesture after disallowing it on a wide screen', function() {
+			viewport.set(1280);
+
+			window.initCore();
+
+			expect(snapperStub.enable.called).toBe(false);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+			expect(snapperStub.close.calledOnce).toBe(true);
+
+			OC.disallowNavigationBarSlideGesture();
+
+			expect(snapperStub.enable.called).toBe(false);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+			expect(snapperStub.close.calledOnce).toBe(true);
+
+			OC.allowNavigationBarSlideGesture();
+
+			expect(snapperStub.enable.called).toBe(false);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+			expect(snapperStub.close.calledOnce).toBe(true);
+		});
 		it('is enabled when resizing to a narrow screen', function() {
 			viewport.set(1280);
 
@@ -1192,6 +1312,130 @@ describe('Core base tests', function() {
 			expect(snapperStub.enable.calledOnce).toBe(true);
 			expect(snapperStub.disable.calledOnce).toBe(true);
 		});
+		it('is not enabled when resizing to a narrow screen after disallowing the gesture', function() {
+			viewport.set(1280);
+
+			window.initCore();
+
+			expect(snapperStub.enable.called).toBe(false);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+
+			OC.disallowNavigationBarSlideGesture();
+
+			expect(snapperStub.enable.called).toBe(false);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+
+			viewport.set(480);
+
+			// Setting the viewport width does not automatically trigger a
+			// resize.
+			$(window).resize();
+
+			// The resize handler is debounced to be executed a few milliseconds
+			// after the resize event.
+			clock.tick(1000);
+
+			expect(snapperStub.enable.called).toBe(false);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+		});
+		it('is enabled when resizing to a narrow screen after disallowing the gesture and allowing it', function() {
+			viewport.set(1280);
+
+			window.initCore();
+
+			expect(snapperStub.enable.called).toBe(false);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+
+			OC.disallowNavigationBarSlideGesture();
+
+			expect(snapperStub.enable.called).toBe(false);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+
+			OC.allowNavigationBarSlideGesture();
+
+			expect(snapperStub.enable.called).toBe(false);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+
+			viewport.set(480);
+
+			// Setting the viewport width does not automatically trigger a
+			// resize.
+			$(window).resize();
+
+			// The resize handler is debounced to be executed a few milliseconds
+			// after the resize event.
+			clock.tick(1000);
+
+			expect(snapperStub.enable.calledOnce).toBe(true);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+		});
+		it('is enabled when allowing the gesture after disallowing it and resizing to a narrow screen', function() {
+			viewport.set(1280);
+
+			window.initCore();
+
+			expect(snapperStub.enable.called).toBe(false);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+
+			OC.disallowNavigationBarSlideGesture();
+
+			expect(snapperStub.enable.called).toBe(false);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+
+			viewport.set(480);
+
+			// Setting the viewport width does not automatically trigger a
+			// resize.
+			$(window).resize();
+
+			// The resize handler is debounced to be executed a few milliseconds
+			// after the resize event.
+			clock.tick(1000);
+
+			expect(snapperStub.enable.called).toBe(false);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+
+			OC.allowNavigationBarSlideGesture();
+
+			expect(snapperStub.enable.calledOnce).toBe(true);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+		});
+		it('is disabled when disallowing the gesture after disallowing it, resizing to a narrow screen and allowing it', function() {
+			viewport.set(1280);
+
+			window.initCore();
+
+			expect(snapperStub.enable.called).toBe(false);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+
+			OC.disallowNavigationBarSlideGesture();
+
+			expect(snapperStub.enable.called).toBe(false);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+
+			viewport.set(480);
+
+			// Setting the viewport width does not automatically trigger a
+			// resize.
+			$(window).resize();
+
+			// The resize handler is debounced to be executed a few milliseconds
+			// after the resize event.
+			clock.tick(1000);
+
+			expect(snapperStub.enable.called).toBe(false);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+
+			OC.allowNavigationBarSlideGesture();
+
+			expect(snapperStub.enable.calledOnce).toBe(true);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+
+			OC.disallowNavigationBarSlideGesture();
+
+			expect(snapperStub.enable.calledOnce).toBe(true);
+			expect(snapperStub.disable.calledTwice).toBe(true);
+		});
 		it('is disabled when resizing to a wide screen', function() {
 			viewport.set(480);
 
@@ -1215,5 +1459,79 @@ describe('Core base tests', function() {
 			expect(snapperStub.disable.calledOnce).toBe(true);
 			expect(snapperStub.close.calledOnce).toBe(true);
 		});
+		it('is not disabled again when disallowing the gesture after resizing to a wide screen', function() {
+			viewport.set(480);
+
+			window.initCore();
+
+			expect(snapperStub.enable.calledOnce).toBe(true);
+			expect(snapperStub.disable.called).toBe(false);
+			expect(snapperStub.close.called).toBe(false);
+
+			viewport.set(1280);
+
+			// Setting the viewport width does not automatically trigger a
+			// resize.
+			$(window).resize();
+
+			// The resize handler is debounced to be executed a few milliseconds
+			// after the resize event.
+			clock.tick(1000);
+
+			expect(snapperStub.enable.calledOnce).toBe(true);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+			expect(snapperStub.close.calledOnce).toBe(true);
+
+			OC.disallowNavigationBarSlideGesture();
+
+			expect(snapperStub.enable.calledOnce).toBe(true);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+			expect(snapperStub.close.calledOnce).toBe(true);
+		});
+		it('is not enabled when allowing the gesture after disallowing it, resizing to a narrow screen and resizing to a wide screen', function() {
+			viewport.set(1280);
+
+			window.initCore();
+
+			expect(snapperStub.enable.called).toBe(false);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+			expect(snapperStub.close.calledOnce).toBe(true);
+
+			OC.disallowNavigationBarSlideGesture();
+
+			expect(snapperStub.enable.called).toBe(false);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+			expect(snapperStub.close.calledOnce).toBe(true);
+
+			viewport.set(480);
+
+			// Setting the viewport width does not automatically trigger a
+			// resize.
+			$(window).resize();
+
+			// The resize handler is debounced to be executed a few milliseconds
+			// after the resize event.
+			clock.tick(1000);
+
+			expect(snapperStub.enable.called).toBe(false);
+			expect(snapperStub.disable.calledOnce).toBe(true);
+			expect(snapperStub.close.calledOnce).toBe(true);
+
+			viewport.set(1280);
+
+			$(window).resize();
+
+			clock.tick(1000);
+
+			expect(snapperStub.enable.called).toBe(false);
+			expect(snapperStub.disable.calledTwice).toBe(true);
+			expect(snapperStub.close.calledTwice).toBe(true);
+
+			OC.allowNavigationBarSlideGesture();
+
+			expect(snapperStub.enable.called).toBe(false);
+			expect(snapperStub.disable.calledTwice).toBe(true);
+			expect(snapperStub.close.calledTwice).toBe(true);
+		});
 	});
 });