Commit 77ee59359c16729d71ef9d6eaeb5bb3413716d52
ux: bug fix: newly published message should show immediately
Andre Staltz committed on 3/15/2021, 5:42:39 PMParent: dd91ccc3ae3b96429d85421a6fce4d2b93b79b81
Files changed
src/frontend/components/Feed.ts | changed |
src/frontend/components/FullThread.ts | changed |
src/frontend/screens/thread/navigation.ts | changed |
src/frontend/components/Feed.ts | ||
---|---|---|
@@ -164,17 +164,20 @@ | ||
164 | 164 | initialLoading: boolean; |
165 | 165 | }; |
166 | 166 | |
167 | 167 | export default class Feed extends PureComponent<Props, State> { |
168 | - private addedThreadsStream: any | null; | |
169 | 168 | private yOffset: number; |
169 | + private addedThreadsStream?: {push: (x: any) => {}; end: () => {}}; | |
170 | 170 | private subscription?: Subscription; |
171 | + private drainSink?: {abort: () => {}}; | |
172 | + private latestPublicationTimestamp: number; | |
171 | 173 | |
172 | 174 | constructor(props: Props) { |
173 | 175 | super(props); |
176 | + this.yOffset = 0; | |
177 | + this.latestPublicationTimestamp = 0; | |
178 | + this.addedThreadsStream = Pushable(); | |
174 | 179 | this.state = {showPlaceholder: false, initialLoading: true}; |
175 | - this.addedThreadsStream = Pushable(); | |
176 | - this.yOffset = 0; | |
177 | 180 | } |
178 | 181 | |
179 | 182 | private _onScroll = (ev: {nativeEvent: NativeScrollEvent}) => { |
180 | 183 | if (ev?.nativeEvent?.contentOffset) { |
@@ -188,13 +191,23 @@ | ||
188 | 191 | }; |
189 | 192 | |
190 | 193 | public componentDidMount() { |
191 | 194 | this.addedThreadsStream ??= Pushable(); |
192 | - const {publication$} = this.props; | |
195 | + const {publication$, getPublicationsReadable} = this.props; | |
193 | 196 | if (publication$) { |
194 | 197 | const listener = {next: this.onPublication.bind(this)}; |
195 | 198 | this.subscription = publication$.subscribe(listener as Listener<any>); |
196 | 199 | } |
200 | + if (getPublicationsReadable) { | |
201 | + pull( | |
202 | + getPublicationsReadable({live: true, old: false}), | |
203 | + (this.drainSink = pull.drain((thread: ThreadSummaryWithExtras) => { | |
204 | + this.setState({showPlaceholder: false}); | |
205 | + this.addedThreadsStream?.push(thread); | |
206 | + this.latestPublicationTimestamp = Date.now(); | |
207 | + })), | |
208 | + ); | |
209 | + } | |
197 | 210 | } |
198 | 211 | |
199 | 212 | public componentWillUnmount() { |
200 | 213 | if (this.subscription) { |
@@ -202,29 +215,21 @@ | ||
202 | 215 | this.subscription = void 0; |
203 | 216 | } |
204 | 217 | if (this.addedThreadsStream) { |
205 | 218 | this.addedThreadsStream.end(); |
206 | - this.addedThreadsStream = null; | |
219 | + this.addedThreadsStream = void 0; | |
207 | 220 | } |
221 | + if (this.drainSink) { | |
222 | + this.drainSink.abort(); | |
223 | + this.drainSink = void 0; | |
224 | + } | |
208 | 225 | } |
209 | 226 | |
210 | 227 | private onPublication() { |
211 | - const {getPublicationsReadable} = this.props; | |
212 | - if (!getPublicationsReadable) return; | |
213 | - const readable = getPublicationsReadable({live: true, old: false}); | |
214 | - if (!readable) return; | |
215 | - const addedThreadsStream = this.addedThreadsStream; | |
216 | - const that = this; | |
217 | - | |
218 | - that.setState({showPlaceholder: true}); | |
219 | - pull( | |
220 | - readable, | |
221 | - pull.take(1), | |
222 | - pull.drain((thread: ThreadSummaryWithExtras) => { | |
223 | - that.setState({showPlaceholder: false}); | |
224 | - addedThreadsStream.push(thread); | |
225 | - }), | |
226 | - ); | |
228 | + // Prevent possible race condition in case ssb-db2 publication is very fast | |
229 | + if (Date.now() > this.latestPublicationTimestamp + 200) { | |
230 | + this.setState({showPlaceholder: true}); | |
231 | + } | |
227 | 232 | } |
228 | 233 | |
229 | 234 | public renderHeader() { |
230 | 235 | const {showPlaceholder} = this.state; |
src/frontend/components/FullThread.ts | ||
---|---|---|
@@ -1,5 +1,5 @@ | ||
1 | -/* Copyright (C) 2018-2020 The Manyverse Authors. | |
1 | +/* Copyright (C) 2018-2021 The Manyverse Authors. | |
2 | 2 | * |
3 | 3 | * This Source Code Form is subject to the terms of the Mozilla Public |
4 | 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
@@ -76,8 +76,9 @@ | ||
76 | 76 | } |
77 | 77 | |
78 | 78 | private subscription?: Subscription; |
79 | 79 | private repliesSeen: Set<MsgId> = new Set(); |
80 | + private latestPublicationTimestamp: number = 0; | |
80 | 81 | |
81 | 82 | public componentDidMount() { |
82 | 83 | const {publication$} = this.props; |
83 | 84 | if (publication$) { |
@@ -111,8 +112,9 @@ | ||
111 | 112 | const prevMessages = prevProps.thread.messages; |
112 | 113 | const nextMessages = this.props.thread.messages; |
113 | 114 | if (nextMessages.length > prevMessages.length) { |
114 | 115 | this.setState({showPlaceholder: false}); |
116 | + this.latestPublicationTimestamp = Date.now(); | |
115 | 117 | } |
116 | 118 | } |
117 | 119 | |
118 | 120 | public componentWillUnmount() { |
@@ -122,9 +124,12 @@ | ||
122 | 124 | } |
123 | 125 | } |
124 | 126 | |
125 | 127 | private onPublication() { |
126 | - this.setState({showPlaceholder: true}); | |
128 | + // Prevent possible race condition in case ssb-db2 publication is very fast | |
129 | + if (Date.now() > this.latestPublicationTimestamp + 200) { | |
130 | + this.setState({showPlaceholder: true}); | |
131 | + } | |
127 | 132 | } |
128 | 133 | |
129 | 134 | private renderMessage = ({item, index}: any) => { |
130 | 135 | const { |
src/frontend/screens/thread/navigation.ts | ||
---|---|---|
@@ -1,5 +1,5 @@ | ||
1 | -/* Copyright (C) 2018-2020 The Manyverse Authors. | |
1 | +/* Copyright (C) 2018-2021 The Manyverse Authors. | |
2 | 2 | * |
3 | 3 | * This Source Code Form is subject to the terms of the Mozilla Public |
4 | 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
@@ -85,18 +85,16 @@ | ||
85 | 85 | .compose(sample(state$)) |
86 | 86 | .map((state) => { |
87 | 87 | const messages = state.thread.messages; |
88 | 88 | const lastMsgInThread = messages[messages.length - 1]; |
89 | - const authors = (() => { | |
90 | - const set = new Set<FeedId>(); | |
91 | - for (const msg of state.thread.messages) { | |
92 | - const author = msg.value.author; | |
93 | - if (author !== state.selfFeedId && !set.has(author)) { | |
94 | - set.add(author); | |
95 | - } | |
89 | + const set = new Set<FeedId>(); | |
90 | + for (const msg of state.thread.messages) { | |
91 | + const author = msg.value.author; | |
92 | + if (author !== state.selfFeedId && !set.has(author)) { | |
93 | + set.add(author); | |
96 | 94 | } |
97 | - return [...set.values()]; | |
98 | - })(); | |
95 | + } | |
96 | + const authors = [...set.values()]; | |
99 | 97 | |
100 | 98 | return { |
101 | 99 | type: 'push', |
102 | 100 | layout: { |
Built with git-ssb-web