UX: Docking back button on topic timeline

This commit is contained in:
Robin Ward 2016-12-19 13:33:55 -05:00
parent 05e99a68ce
commit 36449aa2f2
3 changed files with 56 additions and 28 deletions

View File

@ -56,12 +56,12 @@ let _dragging;
const DRAG_NAME = "mousemove.discourse-widget-drag"; const DRAG_NAME = "mousemove.discourse-widget-drag";
const DRAG_NAME_TOUCH = "touchmove.discourse-widget-drag"; const DRAG_NAME_TOUCH = "touchmove.discourse-widget-drag";
function cancelDrag() { function cancelDrag(e) {
$('body').removeClass('widget-dragging'); $('body').removeClass('widget-dragging');
$(document).off(DRAG_NAME).off(DRAG_NAME_TOUCH); $(document).off(DRAG_NAME).off(DRAG_NAME_TOUCH);
if (_dragging) { if (_dragging) {
if (_dragging.dragEnd) { _dragging.dragEnd(); } if (_dragging.dragEnd) { _dragging.dragEnd(e); }
_dragging = null; _dragging = null;
} }
} }
@ -70,7 +70,7 @@ WidgetClickHook.setupDocumentCallback = function() {
if (_watchingDocument) { return; } if (_watchingDocument) { return; }
$(document).on('mousedown.discource-widget-drag, touchstart.discourse-widget-drag', e => { $(document).on('mousedown.discource-widget-drag, touchstart.discourse-widget-drag', e => {
cancelDrag(); cancelDrag(e);
const widget = findWidget(e.target, DRAG_ATTRIBUTE_NAME); const widget = findWidget(e.target, DRAG_ATTRIBUTE_NAME);
if (widget) { if (widget) {
e.preventDefault(); e.preventDefault();
@ -87,7 +87,7 @@ WidgetClickHook.setupDocumentCallback = function() {
} }
}); });
$(document).on('mouseup.discourse-widget-drag, touchend.discourse-widget-drag', () => cancelDrag()); $(document).on('mouseup.discourse-widget-drag, touchend.discourse-widget-drag', e => cancelDrag(e));
$(document).on('click.discourse-widget', e => { $(document).on('click.discourse-widget', e => {
nodeCallback(e.target, CLICK_ATTRIBUTE_NAME, w => w.click(e)); nodeCallback(e.target, CLICK_ATTRIBUTE_NAME, w => w.click(e));

View File

@ -12,6 +12,15 @@ function clamp(p, min=0.0, max=1.0) {
return Math.max(Math.min(p, max), min); return Math.max(Math.min(p, max), min);
} }
function attachBackButton(widget) {
return widget.attach('button', {
className: 'btn btn-primary btn-small back-button',
label: 'topic.timeline.back',
title: 'topic.timeline.back_description',
action: 'goBack'
});
}
createWidget('timeline-last-read', { createWidget('timeline-last-read', {
tagName: 'div.timeline-last-read', tagName: 'div.timeline-last-read',
@ -22,20 +31,12 @@ createWidget('timeline-last-read', {
html(attrs) { html(attrs) {
const result = [ iconNode('minus', { class: 'progress' }) ]; const result = [ iconNode('minus', { class: 'progress' }) ];
if (attrs.showButton) { if (attrs.showButton) {
result.push(this.attach('button', { result.push(attachBackButton(this));
className: 'btn btn-primary btn-small',
label: 'topic.timeline.back',
title: 'topic.timeline.back_description',
action: 'goBack'
}));
} }
return result; return result;
}, },
goBack() {
this.sendWidgetAction('jumpToPost', this.attrs.lastRead);
}
}); });
function timelineDate(date) { function timelineDate(date) {
@ -61,6 +62,9 @@ createWidget('timeline-scroller', {
contents.push(h('div.timeline-ago', timelineDate(date))); contents.push(h('div.timeline-ago', timelineDate(date)));
} }
if (attrs.showDockedButton) {
contents.push(attachBackButton(this));
}
let result = [ h('div.timeline-handle'), h('div.timeline-scroller-content', contents) ]; let result = [ h('div.timeline-handle'), h('div.timeline-scroller-content', contents) ];
if (attrs.fullScreen) { if (attrs.fullScreen) {
@ -74,9 +78,11 @@ createWidget('timeline-scroller', {
this.sendWidgetAction('updatePercentage', e.pageY); this.sendWidgetAction('updatePercentage', e.pageY);
}, },
dragEnd() { dragEnd(e) {
if (!$(e.target).is('button')) {
this.sendWidgetAction('commit'); this.sendWidgetAction('commit');
} }
}
}); });
createWidget('timeline-padding', { createWidget('timeline-padding', {
@ -153,22 +159,36 @@ createWidget('timeline-scrollarea', {
const before = SCROLLAREA_REMAINING * percentage; const before = SCROLLAREA_REMAINING * percentage;
const after = (SCROLLAREA_HEIGHT - before) - SCROLLER_HEIGHT; const after = (SCROLLAREA_HEIGHT - before) - SCROLLER_HEIGHT;
let showButton = false;
const hasBackPosition =
position.lastRead > 3 &&
Math.abs(position.lastRead - position.current) > 3 &&
(position.lastRead && position.lastRead !== position.total);
if (hasBackPosition) {
const lastReadTop = Math.round(position.lastReadPercentage * SCROLLAREA_HEIGHT);
showButton = ((lastReadTop < before - (SCROLLER_HEIGHT * 0.5)) ||
(lastReadTop > (before + SCROLLER_HEIGHT))) &&
(lastReadTop < (SCROLLAREA_HEIGHT - SCROLLER_HEIGHT));
}
const result = [ const result = [
this.attach('timeline-padding', { height: before }), this.attach('timeline-padding', { height: before }),
this.attach('timeline-scroller', _.merge(position, {fullScreen: attrs.fullScreen})), this.attach('timeline-scroller', _.merge(position, {
showDockedButton: hasBackPosition && !showButton,
fullScreen: attrs.fullScreen
})),
this.attach('timeline-padding', { height: after }) this.attach('timeline-padding', { height: after })
]; ];
if (position.lastRead && position.lastRead !== position.total) { if (hasBackPosition) {
const lastReadTop = Math.round(position.lastReadPercentage * SCROLLAREA_HEIGHT); const lastReadTop = Math.round(position.lastReadPercentage * SCROLLAREA_HEIGHT);
if (lastReadTop > (before + SCROLLER_HEIGHT * 0.5)) {
result.push(this.attach('timeline-last-read', { result.push(this.attach('timeline-last-read', {
top: lastReadTop, top: lastReadTop,
lastRead: position.lastRead, lastRead: position.lastRead,
showButton: (lastReadTop > (before + SCROLLER_HEIGHT)) && (lastReadTop < (SCROLLAREA_HEIGHT - SCROLLER_HEIGHT)) showButton
})); }));
} }
}
return result; return result;
}, },
@ -196,6 +216,10 @@ createWidget('timeline-scrollarea', {
_percentFor(topic, postIndex) { _percentFor(topic, postIndex) {
const total = topic.get('postStream.filteredPostsCount'); const total = topic.get('postStream.filteredPostsCount');
return clamp(parseFloat(postIndex - 1.0) / total); return clamp(parseFloat(postIndex - 1.0) / total);
},
goBack() {
this.sendWidgetAction('jumpToPost', this.position().lastRead);
} }
}); });

View File

@ -253,6 +253,10 @@
cursor: ns-resize; cursor: ns-resize;
display: flex; display: flex;
align-items: center; align-items: center;
.back-button {
margin-top: 1em;
}
} }
.timeline-replies { .timeline-replies {
@ -263,10 +267,6 @@
position: absolute; position: absolute;
margin-left: -0.35em; margin-left: -0.35em;
.btn-small {
padding: 2px 5px;
}
i.progress { i.progress {
font-size: 0.8em; font-size: 0.8em;
color: $tertiary; color: $tertiary;
@ -274,6 +274,10 @@
} }
} }
.back-button {
padding: 2px 5px;
}
.now-date { .now-date {
@include unselectable; @include unselectable;
display: inline-block; display: inline-block;