FIX: Optimistically fix topic timeline state issues

This is my second try at this. The first b246a63a59 raised an issue
with the event delegation not working because the topic id changed.

This adds support for delegating events to dynamic keys by passing a
function where a static key would normally be needed. This means that
each timeline will have its own unique state key and events will only
delegate to the proper topic.
This commit is contained in:
Robin Ward 2021-09-13 15:45:31 -04:00
parent 2e0992c757
commit 7f769e9e76
3 changed files with 15 additions and 13 deletions

View File

@ -83,6 +83,7 @@ export default Component.extend({
afterPatch() {}, afterPatch() {},
eventDispatched(eventName, key, refreshArg) { eventDispatched(eventName, key, refreshArg) {
key = typeof key === "function" ? key(refreshArg) : key;
const onRefresh = camelize(eventName.replace(/:/, "-")); const onRefresh = camelize(eventName.replace(/:/, "-"));
this.dirtyKeys.keyDirty(key, { onRefresh, refreshArg }); this.dirtyKeys.keyDirty(key, { onRefresh, refreshArg });
this.queueRerender(); this.queueRerender();

View File

@ -105,7 +105,10 @@ export default MountWidget.extend(Docking, {
}); });
} }
this.dispatch("topic:current-post-scrolled", "timeline-scrollarea"); this.dispatch(
"topic:current-post-scrolled",
() => `timeline-scrollarea-${this.topic.id}`
);
this.dispatch("topic:toggle-actions", "topic-admin-menu-button"); this.dispatch("topic:toggle-actions", "topic-admin-menu-button");
if (!this.site.mobileView) { if (!this.site.mobileView) {
this.appEvents.on("composer:opened", this, this.queueRerender); this.appEvents.on("composer:opened", this, this.queueRerender);

View File

@ -2,7 +2,6 @@ import ComponentConnector from "discourse/widgets/component-connector";
import I18n from "I18n"; import I18n from "I18n";
import RawHtml from "discourse/widgets/raw-html"; import RawHtml from "discourse/widgets/raw-html";
import { createWidget } from "discourse/widgets/widget"; import { createWidget } from "discourse/widgets/widget";
import { deepMerge } from "discourse-common/lib/object";
import { h } from "virtual-dom"; import { h } from "virtual-dom";
import { iconNode } from "discourse-common/lib/icon-library"; import { iconNode } from "discourse-common/lib/icon-library";
import { later } from "@ember/runloop"; import { later } from "@ember/runloop";
@ -76,7 +75,7 @@ function timelineDate(date) {
createWidget("timeline-scroller", { createWidget("timeline-scroller", {
tagName: "div.timeline-scroller", tagName: "div.timeline-scroller",
buildKey: () => `timeline-scroller`, buildKey: (attrs) => `timeline-scroller-${attrs.topicId}`,
defaultState() { defaultState() {
return { dragging: false }; return { dragging: false };
@ -144,7 +143,7 @@ createWidget("timeline-padding", {
createWidget("timeline-scrollarea", { createWidget("timeline-scrollarea", {
tagName: "div.timeline-scrollarea", tagName: "div.timeline-scrollarea",
buildKey: () => `timeline-scrollarea`, buildKey: (attrs) => `timeline-scrollarea-${attrs.topic.id}`,
buildAttributes() { buildAttributes() {
return { style: `height: ${scrollareaHeight()}px` }; return { style: `height: ${scrollareaHeight()}px` };
@ -239,15 +238,15 @@ createWidget("timeline-scrollarea", {
before + SCROLLER_HEIGHT - 5 < lastReadTop || before > lastReadTop + 25; before + SCROLLER_HEIGHT - 5 < lastReadTop || before > lastReadTop + 25;
} }
let scrollerAttrs = position;
scrollerAttrs.showDockedButton =
!attrs.mobileView && hasBackPosition && !showButton;
scrollerAttrs.fullScreen = attrs.fullScreen;
scrollerAttrs.topicId = attrs.topic.id;
const result = [ const result = [
this.attach("timeline-padding", { height: before }), this.attach("timeline-padding", { height: before }),
this.attach( this.attach("timeline-scroller", scrollerAttrs),
"timeline-scroller",
deepMerge(position, {
showDockedButton: !attrs.mobileView && hasBackPosition && !showButton,
fullScreen: attrs.fullScreen,
})
),
this.attach("timeline-padding", { height: after }), this.attach("timeline-padding", { height: after }),
]; ];
@ -410,8 +409,7 @@ createWidget("timeline-footer-controls", {
export default createWidget("topic-timeline", { export default createWidget("topic-timeline", {
tagName: "div.topic-timeline", tagName: "div.topic-timeline",
buildKey: (attrs) => `topic-timeline-area-${attrs.topic.id}`,
buildKey: () => "topic-timeline-area",
defaultState() { defaultState() {
return { position: null, excerpt: null }; return { position: null, excerpt: null };