From a69514dbef806bf1ee531cac3a7a9fee18162f2b Mon Sep 17 00:00:00 2001 From: crupest Date: Sun, 9 Aug 2020 22:35:27 +0800 Subject: Refactor timeline observable. --- Timeline/ClientApp/src/app/data/timeline.ts | 38 +++++++++------------- .../src/app/timeline/TimelinePageTemplateUI.tsx | 11 +++++-- 2 files changed, 24 insertions(+), 25 deletions(-) (limited to 'Timeline/ClientApp/src') diff --git a/Timeline/ClientApp/src/app/data/timeline.ts b/Timeline/ClientApp/src/app/data/timeline.ts index 81cf20e9..9867b128 100644 --- a/Timeline/ClientApp/src/app/data/timeline.ts +++ b/Timeline/ClientApp/src/app/data/timeline.ts @@ -7,7 +7,7 @@ import { uniqBy } from 'lodash'; import { convertError } from '../utilities/rxjs'; import { dataStorage, throwIfNotNetworkError } from './common'; -import { DataHub } from './DataHub'; +import { DataHub, WithSyncStatus } from './DataHub'; import { UserAuthInfo, checkLogin, userService, userInfoService } from './user'; @@ -70,7 +70,7 @@ export const timelineVisibilityTooltipTranslationMap: Record< export class TimelineNotExistError extends Error {} export class TimelineNameConflictError extends Error {} -export type TimelineWithSyncStatus = +export type TimelineWithSyncStatus = WithSyncStatus< | { type: 'cache'; timeline: TimelineInfo; @@ -79,12 +79,9 @@ export type TimelineWithSyncStatus = type: 'offline' | 'synced'; timeline: TimelineInfo | null; } - | { - type: 'notexist'; - timeline?: undefined; - }; +>; -export interface TimelinePostsWithSyncState { +export type TimelinePostsWithSyncState = WithSyncStatus<{ type: | 'cache' | 'offline' // Sync failed and use cache. @@ -92,7 +89,7 @@ export interface TimelinePostsWithSyncState { | 'forbid' // The list is forbidden to see. | 'notexist'; // The timeline does not exist. posts: TimelinePostInfo[]; -} +}>; type TimelineData = Omit & { owner: string; @@ -182,31 +179,28 @@ export class TimelineService { }); getTimeline$(timelineName: string): Observable { - return this._timelineHub.getObservable(timelineName).pipe( + return this._timelineHub.getDataWithSyncStatusObservable(timelineName).pipe( switchMap((state) => { - if (state.timeline != null) { + const { timeline } = state; + if (timeline != null) { return combineLatest( - [state.timeline.owner, ...state.timeline.members].map((u) => + [timeline.owner, ...timeline.members].map((u) => userInfoService.getUser$(u) ) ).pipe( map((users) => { return { - type: state.type, + ...state, timeline: { - ...state.timeline, + ...timeline, owner: users[0], members: users.slice(1), }, - } as TimelineWithSyncStatus; + }; }) ); } else { - return [ - { - ...state, - } as TimelineWithSyncStatus, - ]; + return of(state as TimelineWithSyncStatus); } }) ); @@ -356,11 +350,11 @@ export class TimelineService { }); getPosts$(timelineName: string): Observable { - return this._postsHub.getObservable(timelineName).pipe( + return this._postsHub.getDataWithSyncStatusObservable(timelineName).pipe( switchMap((state) => { if (state.posts.length === 0) { return of({ - type: state.type, + ...state, posts: [], }); } @@ -381,7 +375,7 @@ export class TimelineService { ]).pipe( map(([authors, datas]) => { return { - type: state.type, + ...state, posts: state.posts.map((post, i) => { const { content } = post; diff --git a/Timeline/ClientApp/src/app/timeline/TimelinePageTemplateUI.tsx b/Timeline/ClientApp/src/app/timeline/TimelinePageTemplateUI.tsx index 70507988..18b3323d 100644 --- a/Timeline/ClientApp/src/app/timeline/TimelinePageTemplateUI.tsx +++ b/Timeline/ClientApp/src/app/timeline/TimelinePageTemplateUI.tsx @@ -24,7 +24,7 @@ import Timeline, { import AppBar from '../common/AppBar'; import TimelinePostEdit, { TimelinePostSendCallback } from './TimelinePostEdit'; -type TimelinePostSyncState = 'cache' | 'syncing' | 'synced' | 'offline'; +type TimelinePostSyncState = 'syncing' | 'synced' | 'offline'; const TimelinePostSyncStateBadge: React.FC<{ state: TimelinePostSyncState; @@ -37,7 +37,6 @@ const TimelinePostSyncStateBadge: React.FC<{
{(() => { switch (state) { - case 'cache': case 'syncing': { return ( <> @@ -226,11 +225,17 @@ export default function TimelinePageTemplateUI( ? 'calc(68px + 1.5em)' : `${cardHeight + 60}px`; + const syncState: TimelinePostSyncState = postListState.syncing + ? 'syncing' + : postListState.type === 'synced' + ? 'synced' + : 'offline'; + timelineBody = (