diff options
author | crupest <crupest@outlook.com> | 2020-08-02 18:42:12 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2020-08-02 18:42:12 +0800 |
commit | ccebcc9a3704dc2056513042f717c321374c5350 (patch) | |
tree | 2ea398e3bc8189a8777c800fcf8a3845d604a652 /Timeline/ClientApp/src/app/data | |
parent | c53e51d28bbaa4fb294eb335001719f82474244f (diff) | |
download | timeline-ccebcc9a3704dc2056513042f717c321374c5350.tar.gz timeline-ccebcc9a3704dc2056513042f717c321374c5350.tar.bz2 timeline-ccebcc9a3704dc2056513042f717c321374c5350.zip |
Implement sync timeline.
Diffstat (limited to 'Timeline/ClientApp/src/app/data')
-rw-r--r-- | Timeline/ClientApp/src/app/data/timeline.ts | 75 |
1 files changed, 68 insertions, 7 deletions
diff --git a/Timeline/ClientApp/src/app/data/timeline.ts b/Timeline/ClientApp/src/app/data/timeline.ts index d84f7bc4..b30f3a7d 100644 --- a/Timeline/ClientApp/src/app/data/timeline.ts +++ b/Timeline/ClientApp/src/app/data/timeline.ts @@ -94,6 +94,11 @@ export type TimelineInfoState = | TimelineInfoLoadingState
| TimelineInfoNonLoadingState;
+interface TimelineCache {
+ timeline: TimelineInfo;
+ lastUpdated: string;
+}
+
interface PostListInfo {
idList: number[];
lastUpdated: string;
@@ -101,7 +106,7 @@ interface PostListInfo { export class TimelineService {
// timeline storage structure:
- // each timeline has a TimelineInfo saved with key created by getTimelineKey
+ // each timeline has a TimelineCache saved with key created by getTimelineKey
private getTimelineKey(timelineName: string): string {
return `timeline.${timelineName}`;
@@ -110,14 +115,70 @@ export class TimelineService { private getCachedTimeline(
timelineName: string
): Promise<TimelineInfo | null> {
- return dataStorage.getItem<TimelineInfo | null>(
- this.getTimelineKey(timelineName)
- );
+ return dataStorage
+ .getItem<TimelineCache | null>(this.getTimelineKey(timelineName))
+ .then((cache) => cache?.timeline ?? null);
}
- private syncTimeline(timelineName: string): Promise<TimelineInfo> {
- // TODO: Implement this.
- throw new Error('Not implemented.');
+ private async syncTimeline(timelineName: string): Promise<TimelineInfo> {
+ const cache = await dataStorage.getItem<TimelineCache | null>(timelineName);
+
+ const save = (cache: TimelineCache): Promise<TimelineCache> =>
+ dataStorage.setItem<TimelineCache>(
+ this.getTimelineKey(timelineName),
+ cache
+ );
+ const push = (state: TimelineInfoState): void => {
+ this._timelineSubscriptionHub.update(timelineName, () =>
+ Promise.resolve(state)
+ );
+ };
+
+ let result: TimelineInfo;
+ const now = new Date();
+ if (cache == null) {
+ try {
+ const res = await getHttpTimelineClient().getTimeline(timelineName);
+ result = res;
+ await save({ timeline: result, lastUpdated: now.toISOString() });
+ push({ state: 'synced', timeline: result });
+ } catch (e) {
+ if (e instanceof HttpTimelineNotExistError) {
+ push({ state: 'synced', timeline: null });
+ } else {
+ push({ state: 'offline', timeline: null });
+ }
+ throw e;
+ }
+ } else {
+ try {
+ const res = await getHttpTimelineClient().getTimeline(timelineName, {
+ checkUniqueId: cache.timeline.uniqueId,
+ ifModifiedSince: new Date(cache.lastUpdated),
+ });
+ if (res instanceof NotModified) {
+ result = cache.timeline;
+ await save({ timeline: result, lastUpdated: now.toISOString() });
+ push({ state: 'synced', timeline: result });
+ } else {
+ result = res;
+ await save({ timeline: result, lastUpdated: now.toISOString() });
+ if (res.uniqueId === cache.timeline.uniqueId) {
+ push({ state: 'synced', timeline: result });
+ } else {
+ push({ state: 'new', timeline: result });
+ }
+ }
+ } catch (e) {
+ if (e instanceof HttpTimelineNotExistError) {
+ push({ state: 'new', timeline: null });
+ } else {
+ push({ state: 'offline', timeline: cache.timeline });
+ }
+ throw e;
+ }
+ }
+ return result;
}
private _timelineSubscriptionHub = new SubscriptionHub<
|