UX: Docking back button on topic timeline
This commit is contained in:
parent
05e99a68ce
commit
36449aa2f2
|
@ -56,12 +56,12 @@ let _dragging;
|
|||
const DRAG_NAME = "mousemove.discourse-widget-drag";
|
||||
const DRAG_NAME_TOUCH = "touchmove.discourse-widget-drag";
|
||||
|
||||
function cancelDrag() {
|
||||
function cancelDrag(e) {
|
||||
$('body').removeClass('widget-dragging');
|
||||
$(document).off(DRAG_NAME).off(DRAG_NAME_TOUCH);
|
||||
|
||||
if (_dragging) {
|
||||
if (_dragging.dragEnd) { _dragging.dragEnd(); }
|
||||
if (_dragging.dragEnd) { _dragging.dragEnd(e); }
|
||||
_dragging = null;
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ WidgetClickHook.setupDocumentCallback = function() {
|
|||
if (_watchingDocument) { return; }
|
||||
|
||||
$(document).on('mousedown.discource-widget-drag, touchstart.discourse-widget-drag', e => {
|
||||
cancelDrag();
|
||||
cancelDrag(e);
|
||||
const widget = findWidget(e.target, DRAG_ATTRIBUTE_NAME);
|
||||
if (widget) {
|
||||
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 => {
|
||||
nodeCallback(e.target, CLICK_ATTRIBUTE_NAME, w => w.click(e));
|
||||
|
|
|
@ -12,6 +12,15 @@ function clamp(p, min=0.0, max=1.0) {
|
|||
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', {
|
||||
tagName: 'div.timeline-last-read',
|
||||
|
||||
|
@ -22,20 +31,12 @@ createWidget('timeline-last-read', {
|
|||
html(attrs) {
|
||||
const result = [ iconNode('minus', { class: 'progress' }) ];
|
||||
if (attrs.showButton) {
|
||||
result.push(this.attach('button', {
|
||||
className: 'btn btn-primary btn-small',
|
||||
label: 'topic.timeline.back',
|
||||
title: 'topic.timeline.back_description',
|
||||
action: 'goBack'
|
||||
}));
|
||||
result.push(attachBackButton(this));
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
goBack() {
|
||||
this.sendWidgetAction('jumpToPost', this.attrs.lastRead);
|
||||
}
|
||||
});
|
||||
|
||||
function timelineDate(date) {
|
||||
|
@ -61,6 +62,9 @@ createWidget('timeline-scroller', {
|
|||
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) ];
|
||||
|
||||
if (attrs.fullScreen) {
|
||||
|
@ -74,9 +78,11 @@ createWidget('timeline-scroller', {
|
|||
this.sendWidgetAction('updatePercentage', e.pageY);
|
||||
},
|
||||
|
||||
dragEnd() {
|
||||
dragEnd(e) {
|
||||
if (!$(e.target).is('button')) {
|
||||
this.sendWidgetAction('commit');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
createWidget('timeline-padding', {
|
||||
|
@ -153,22 +159,36 @@ createWidget('timeline-scrollarea', {
|
|||
const before = SCROLLAREA_REMAINING * percentage;
|
||||
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 = [
|
||||
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 })
|
||||
];
|
||||
|
||||
if (position.lastRead && position.lastRead !== position.total) {
|
||||
if (hasBackPosition) {
|
||||
const lastReadTop = Math.round(position.lastReadPercentage * SCROLLAREA_HEIGHT);
|
||||
if (lastReadTop > (before + SCROLLER_HEIGHT * 0.5)) {
|
||||
result.push(this.attach('timeline-last-read', {
|
||||
top: lastReadTop,
|
||||
lastRead: position.lastRead,
|
||||
showButton: (lastReadTop > (before + SCROLLER_HEIGHT)) && (lastReadTop < (SCROLLAREA_HEIGHT - SCROLLER_HEIGHT))
|
||||
showButton
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
@ -196,6 +216,10 @@ createWidget('timeline-scrollarea', {
|
|||
_percentFor(topic, postIndex) {
|
||||
const total = topic.get('postStream.filteredPostsCount');
|
||||
return clamp(parseFloat(postIndex - 1.0) / total);
|
||||
},
|
||||
|
||||
goBack() {
|
||||
this.sendWidgetAction('jumpToPost', this.position().lastRead);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -253,6 +253,10 @@
|
|||
cursor: ns-resize;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.back-button {
|
||||
margin-top: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.timeline-replies {
|
||||
|
@ -263,10 +267,6 @@
|
|||
position: absolute;
|
||||
margin-left: -0.35em;
|
||||
|
||||
.btn-small {
|
||||
padding: 2px 5px;
|
||||
}
|
||||
|
||||
i.progress {
|
||||
font-size: 0.8em;
|
||||
color: $tertiary;
|
||||
|
@ -274,6 +274,10 @@
|
|||
}
|
||||
}
|
||||
|
||||
.back-button {
|
||||
padding: 2px 5px;
|
||||
}
|
||||
|
||||
.now-date {
|
||||
@include unselectable;
|
||||
display: inline-block;
|
||||
|
|
Loading…
Reference in New Issue