Skip to content

Commit

Permalink
Merge pull request mozilla-b2g#16941 from vingtetun/bug943845.relanding
Browse files Browse the repository at this point in the history
Bug 943845 - [Gallery] There is a little delay between before rendering ...
  • Loading branch information
vingtetun committed Mar 6, 2014
2 parents 83197dc + eebebd9 commit d4c4aa7
Show file tree
Hide file tree
Showing 5 changed files with 235 additions and 0 deletions.
1 change: 1 addition & 0 deletions apps/gallery/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
<script defer src="shared/js/tag_visibility_monitor.js"></script>
<script defer src="shared/js/media/media_utils.js"></script>
<script defer src="shared/js/screen_layout.js"></script>
<script defer src="shared/js/scroll_detector.js"></script>

<!-- Specific code -->
<script defer src="js/config.js"></script>
Expand Down
11 changes: 11 additions & 0 deletions apps/gallery/js/gallery.js
Original file line number Diff line number Diff line change
Expand Up @@ -1238,3 +1238,14 @@ function showOverlay(id) {
// make it opaque to touch events. Without this, it does not prevent
// the user from interacting with the UI.
$('overlay').addEventListener('click', function dummyHandler() {});


// Change the thumbnails quality while scrolling using the scrollstart/scrollend
// events from shared/js/scroll_detector.js.
window.addEventListener('scrollstart', function onScrollStart(e) {
thumbnails.classList.add('scrolling');
});

window.addEventListener('scrollend', function onScrollEnd(e) {
thumbnails.classList.remove('scrolling');
});
11 changes: 11 additions & 0 deletions apps/gallery/style/gallery.css
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,17 @@ body.pickView #thumbnails {
padding-bottom: calc((100% - 0.2rem) / 3 );
}

/* Favor scrolling performance for the thumbnails list while
* scrolling.
*/
#thumbnails.scrolling .thumbnail {
image-rendering: -moz-crisp-edges;
}

#thumbnails.scrolling .thumbnail-group-header {
text-rendering: optimizeSpeed;
}

.thumbnail:nth-child(3n) {
margin-right: 0;
}
Expand Down
161 changes: 161 additions & 0 deletions apps/gallery/test/unit/scroll_detector_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/**
* Tests for the shared scroll detector helper
* TODO: Shared code unit tests should not be in gallery
* Bug #841422 has been filed to move these tests
*/

'use strict';

require('/shared/js/scroll_detector.js');

suite('shared/js/scroll_detector.js', function() {
var scrollable;
var content;
var clock;

// Keep in sync with the value into scroll_detector.js
const IDLE_TIME=400;

function scrollBy(x, y, async) {
if (!async) {
// Scroll by steps
while (x) {
x-=10;
scrollable.scrollLeft += Math.min(x, 10);
}

while (y) {
y-=10;
scrollable.scrollLeft += Math.min(y, 10);
}

window.dispatchEvent(new CustomEvent('scroll'));
} else {
window.dispatchEvent(new CustomEvent('mozbrowserasyncscroll'));
}
}

setup(function() {
scrollable = document.createElement('div');
scrollable.style.height = scrollable.style.width = '200px';
scrollable.style.overflowX = 'scroll';
scrollable.style.overflowY = 'scroll';

content = document.createElement('div');
content.style.height = content.style.width = '300px';

scrollable.appendChild(content);

this.sinon.useFakeTimers();
clock = this.sinon.clock;
});

function checkScrollDetectorForXScroll() {
checkScrollDetector(10, 0, false);
checkScrollDetector(10, 0, true);
}

function checkScrollDetectorForYScroll() {
checkScrollDetector(0, 10, false);
checkScrollDetector(0, 10, true);
}

function checkScrollDetectorForXYScroll() {
checkScrollDetector(10, 10, false);
checkScrollDetector(10, 10, true);
}

function checkScrollDetector(x, y, async) {
test('Check scrollstart is fired for first scroll', function() {
var scrollStartHasFired = false;

window.addEventListener('scrollstart', function onScrollStart(e) {
window.removeEventListener(e.type, onScrollStart);
scrollStartHasFired = true;
});

scrollBy(0, 10, async);

assert.isTrue(scrollStartHasFired);
});

test('check scrollstart is not fired for following scroll', function() {
var scrollStartHasFired = false;

window.addEventListener('scrollstart', function onScrollStart(e) {
window.removeEventListener(e.type, onScrollStart);
scrollStartHasFired = true;
});

scrollBy(0, 10, async);

assert.isFalse(scrollStartHasFired);
});

test('check scrollend is not fired before IDLE_TIME', function() {
var scrollEndHasFired = false;

scrollBy(0, 10, async);

window.addEventListener('scrollend', function onScrollEnd(e) {
window.removeEventListener(e.type, onScrollEnd);
scrollEndHasFired = true;
});

clock.tick(IDLE_TIME - 1);

assert.isFalse(scrollEndHasFired);
});

test('check scrollend is fired after IDLE_TIME', function() {
var scrollEndHasFired = false;

scrollBy(0, 10, async);

window.addEventListener('scrollend', function onScrollEnd(e) {
window.removeEventListener(e.type, onScrollEnd);
scrollEndHasFired = true;
});

this.sinon.clock.tick(IDLE_TIME);

assert.isTrue(scrollEndHasFired);
});

test('check scrollend is delayed after a new scroll', function() {
var scrollEndHasFired = false;

// Starts a scroll
scrollBy(0, 10, async);

window.addEventListener('scrollend', function onScrollEnd(e) {
window.removeEventListener(e.type, onScrollEnd);
scrollEndHasFired = true;
});

this.sinon.clock.tick(IDLE_TIME - 1);

// Starts a new scroll right before the delay in order to reset
// the timeout
scrollBy(0, 10, async);

// Ensure the scrollend event has not fired
assert.isFalse(scrollEndHasFired);

this.sinon.clock.tick(IDLE_TIME - 1);

// Ensure the scrollend event has not fired
assert.isFalse(scrollEndHasFired);

this.sinon.clock.tick(1);

// Ensure the scrollend event fired after the expected idle time
assert.isTrue(scrollEndHasFired);
});
}

// Starting the tests from here
checkScrollDetectorForXScroll();
checkScrollDetectorForYScroll();
checkScrollDetectorForXYScroll();
});
51 changes: 51 additions & 0 deletions shared/js/scroll_detector.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* This helper is used to determine when a scroll action has started or
* when it is finished.
* It listens for scroll events happening inside the application and
* fire a scrollstart event for the first scroll and a scrollend event
* once a no scroll action is following after a given delay.
*
*/

(function ScrollDetector() {
'use strict';

var scrollTimeout = null;

// IDLE_TIME is the time allowed between 2 scroll actions before
// considering that the scroll action has finished.
// It should not be < to the mozbrowserasyncscroll delay defined in
// gfx/layers/ipc/AsyncPanZoomController.cpp
const IDLE_TIME = 400;

var isScrolling = false;
function handleScroll(e) {
if (!isScrolling) {
dispatchScrollStart();
}

if (scrollTimeout) {
window.clearTimeout(scrollTimeout);
}
scrollTimeout = window.setTimeout(dispatchScrollEnd, IDLE_TIME);
}

function dispatchScrollStart() {
isScrolling = true;
dispatchCustomScrollEvent();
}

function dispatchScrollEnd() {
isScrolling = false;
dispatchCustomScrollEvent();
}

function dispatchCustomScrollEvent() {
var eventName = isScrolling ? 'scrollstart' : 'scrollend';
window.dispatchEvent(new CustomEvent(eventName));
}

window.addEventListener('mozbrowserasyncscroll', handleScroll, true);
window.addEventListener('scroll', handleScroll, true);
})();

0 comments on commit d4c4aa7

Please sign in to comment.