git ssb

1+

Daan Patchwork / manyverse



Commit 08654a085d8863748507c772005f4da8298f6338

ux: bug fix: unread dot on Private tab should behave correctly

Andre Staltz committed on 8/31/2020, 11:55:51 AM
Parent: 44939bf1cc94a4c7e3436a09469466ef2b4667a2

Files changed

src/frontend/screens/central/private-tab/model.tschanged
src/frontend/screens/conversation/props.tschanged
src/frontend/screens/central/private-tab/model.tsView
@@ -3,15 +3,19 @@
33 * This Source Code Form is subject to the terms of the Mozilla Public
44 * License, v. 2.0. If a copy of the MPL was not distributed with this
55 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
66
7-import xs, {Stream} from 'xstream';
7+import xs from 'xstream';
88 import {FeedId, MsgId} from 'ssb-typescript';
99 import {GetReadable, SSBSource} from '../../../drivers/ssb';
1010 import {PrivateThreadAndExtras} from '../../../ssb/types';
1111 import {NavSource} from 'cycle-native-navigation';
1212 import {Screens} from '../../enums';
13-import {Props as ConversationProps} from '../../conversation/props';
13+import {
14+ Props as ConversationProps,
15+ isExistingConversationProps,
16+ isNewConversationProps,
17+} from '../../conversation/props';
1418
1519 export type State = {
1620 selfFeedId: FeedId;
1721 selfAvatarUrl?: string;
@@ -32,12 +36,8 @@
3236
3337 const incUpdatesReducer$ = ssbSource.privateLiveUpdates$.map(
3438 rootId =>
3539 function incUpdatesReducer(prev: State): State {
36- // FIXME: this if guard also means that every other new root will be
37- // ignored, not just the one that *we* are creating.
38- if (prev.conversationsOpen.has('new')) return prev;
39-
4040 // The updated conversation is already open, don't mark it read
4141 if (prev.conversationsOpen.has(rootId)) return prev;
4242
4343 return {
@@ -47,46 +47,66 @@
4747 };
4848 },
4949 );
5050
51- const conversationOpenedReducer$ = navSource
51+ const newConversationOpenedReducer$ = navSource
5252 .globalDidAppear(Screens.Conversation)
53+ .filter(ev => isNewConversationProps(ev.passProps as any))
54+ .map(appear => {
55+ const conversationDisappears$ = navSource
56+ .globalDidDisappear(Screens.Conversation)
57+ .filter(disappear => disappear.componentId === appear.componentId);
58+ return ssbSource.selfPrivateRoots$
59+ .map(msg => [msg.key, appear.componentId])
60+ .endWhen(conversationDisappears$)
61+ .take(1);
62+ })
63+ .flatten()
5364 .map(
54- ev =>
55- function conversationOpenedReducer(prev: State): State {
56- const conversationProps = ev.passProps as ConversationProps;
57- const {selfFeedId, recps, rootMsgId} = conversationProps;
58- const {conversationsOpen} = prev;
59- if (!selfFeedId) return prev;
60- if (rootMsgId) {
61- prev.updates.delete(rootMsgId);
62- if (conversationsOpen.has(rootMsgId)) {
63- return {
64- ...prev,
65- updatesFlag: !prev.updatesFlag,
66- };
67- }
68- // store in both directions
69- conversationsOpen.set(rootMsgId, ev.componentId);
70- conversationsOpen.set(ev.componentId, rootMsgId);
65+ ([rootMsgId, componentId]) =>
66+ function newRootReducer(prev: State): State {
67+ prev.updates.delete(rootMsgId); // mark the new conversation read
68+ if (prev.conversationsOpen.has(rootMsgId)) {
7169 return {
7270 ...prev,
73- conversationsOpen,
7471 updatesFlag: !prev.updatesFlag,
7572 };
76- } else if (Array.isArray(recps)) {
77- if (conversationsOpen.has('new')) return prev;
78- // store in both directions
79- conversationsOpen.set('new', ev.componentId);
80- conversationsOpen.set(ev.componentId, 'new');
73+ }
74+ // store in both directions
75+ prev.conversationsOpen.set(rootMsgId, componentId);
76+ prev.conversationsOpen.set(componentId, rootMsgId);
77+ return {
78+ ...prev,
79+ conversationsOpen: prev.conversationsOpen,
80+ updatesFlag: !prev.updatesFlag,
81+ };
82+ },
83+ );
84+
85+ const oldConversationOpenedReducer$ = navSource
86+ .globalDidAppear(Screens.Conversation)
87+ .map(
88+ ev =>
89+ function conversationOpenedReducer(prev: State): State {
90+ const props = ev.passProps as ConversationProps;
91+ if (!isExistingConversationProps(props)) return prev;
92+ const {rootMsgId} = props;
93+ const {conversationsOpen} = prev;
94+ prev.updates.delete(rootMsgId); // mark the conversation read
95+ if (conversationsOpen.has(rootMsgId)) {
8196 return {
8297 ...prev,
83- conversationsOpen,
8498 updatesFlag: !prev.updatesFlag,
8599 };
86- } else {
87- return prev;
88100 }
101+ // store in both directions
102+ conversationsOpen.set(rootMsgId, ev.componentId);
103+ conversationsOpen.set(ev.componentId, rootMsgId);
104+ return {
105+ ...prev,
106+ conversationsOpen,
107+ updatesFlag: !prev.updatesFlag,
108+ };
89109 },
90110 );
91111
92112 const conversationClosedReducer$ = navSource
@@ -109,8 +129,9 @@
109129
110130 return xs.merge(
111131 setPrivateFeedReducer$,
112132 incUpdatesReducer$,
113- conversationOpenedReducer$,
133+ newConversationOpenedReducer$,
134+ oldConversationOpenedReducer$,
114135 conversationClosedReducer$,
115136 );
116137 }
src/frontend/screens/conversation/props.tsView
@@ -13,4 +13,24 @@
1313 rootMsgId?: MsgId;
1414 recps?: PrivateThreadAndExtras['recps'];
1515 goBackActionType?: string;
1616 };
17+
18+function selfFeedIdExists(props: Partial<Record<keyof Props, any>>): boolean {
19+ return props.selfFeedId && typeof props.selfFeedId === 'string';
20+}
21+
22+export function isExistingConversationProps(
23+ props: Partial<Record<keyof Props, any>>,
24+): props is Props & Required<Pick<Props, 'rootMsgId'>> {
25+ const rootMsgIdExists =
26+ props.rootMsgId && typeof props.rootMsgId === 'string';
27+ return selfFeedIdExists(props) && rootMsgIdExists;
28+}
29+
30+export function isNewConversationProps(
31+ props: Partial<Record<keyof Props, any>>,
32+): props is Props & Required<Pick<Props, 'recps'>> {
33+ const recpsExists =
34+ props.recps && Array.isArray(props.recps) && props.recps.length > 0;
35+ return selfFeedIdExists(props) && recpsExists;
36+}

Built with git-ssb-web