diff options
| author | crupest <crupest@outlook.com> | 2020-07-30 23:35:27 +0800 | 
|---|---|---|
| committer | crupest <crupest@outlook.com> | 2020-07-30 23:35:27 +0800 | 
| commit | dd44dc2bd3dada15d9b0b676cc5a5b1ef0686559 (patch) | |
| tree | 068a6671392c541e9c79c6cf13a5202d4f605d70 /Timeline/ClientApp/src/app/data/timeline.ts | |
| parent | 2afc8d5d6b1e7cb466e62d0e59e2c05143d664c6 (diff) | |
| download | timeline-dd44dc2bd3dada15d9b0b676cc5a5b1ef0686559.tar.gz timeline-dd44dc2bd3dada15d9b0b676cc5a5b1ef0686559.tar.bz2 timeline-dd44dc2bd3dada15d9b0b676cc5a5b1ef0686559.zip  | |
Save post data locally.
Diffstat (limited to 'Timeline/ClientApp/src/app/data/timeline.ts')
| -rw-r--r-- | Timeline/ClientApp/src/app/data/timeline.ts | 100 | 
1 files changed, 88 insertions, 12 deletions
diff --git a/Timeline/ClientApp/src/app/data/timeline.ts b/Timeline/ClientApp/src/app/data/timeline.ts index 04b63de2..50d45aa5 100644 --- a/Timeline/ClientApp/src/app/data/timeline.ts +++ b/Timeline/ClientApp/src/app/data/timeline.ts @@ -32,6 +32,7 @@ import {    HttpTimelineNameConflictError,
    HttpTimelineGenericPostInfo,
  } from '../http/timeline';
 +import { BlobWithEtag, NotModified } from '../http/common';
  export type TimelineInfo = HttpTimelineInfo;
  export type TimelineChangePropertyRequest = HttpTimelinePatchRequest;
 @@ -158,6 +159,7 @@ export class TimelineService {    // post list storage structure:
    // each timeline has a PostListInfo saved with key created by getPostListInfoKey
    // each post of a timeline has a HttpTimelinePostInfo with key created by getPostKey
 +  // each post with data has BlobWithEtag with key created by getPostDataKey
    private getPostListInfoKey(timelineUniqueId: string): string {
      return `timeline.${timelineUniqueId}.postListInfo`;
 @@ -167,6 +169,10 @@ export class TimelineService {      return `timeline.${timelineUniqueId}.post.${id}`;
    }
 +  private getPostDataKey(timelineUniqueId: string, id: number): string {
 +    return `timeline.${timelineUniqueId}.post.${id}.data`;
 +  }
 +
    private async getCachedPostList(
      timelineName: string
    ): Promise<TimelinePostInfo[]> {
 @@ -260,6 +266,9 @@ export class TimelineService {            await dataStorage.removeItem(
              this.getPostKey(timeline.uniqueId, post.id)
            );
 +          await dataStorage.removeItem(
 +            this.getPostDataKey(timeline.uniqueId, post.id)
 +          );
          } else {
            await dataStorage.setItem<HttpTimelinePostInfo>(
              this.getPostKey(timeline.uniqueId, post.id),
 @@ -323,6 +332,75 @@ export class TimelineService {      return this._postListSubscriptionHub;
    }
 +  private async getCachePostData(
 +    timelineName: string,
 +    postId: number
 +  ): Promise<Blob | null> {
 +    const timeline = await this.getTimeline(timelineName).toPromise();
 +    const cache = await dataStorage.getItem<BlobWithEtag | null>(
 +      this.getPostDataKey(timeline.uniqueId, postId)
 +    );
 +    if (cache == null) {
 +      return null;
 +    } else {
 +      return cache.data;
 +    }
 +  }
 +
 +  private async syncCachePostData(
 +    timelineName: string,
 +    postId: number
 +  ): Promise<Blob | null> {
 +    const timeline = await this.getTimeline(timelineName).toPromise();
 +    const dataKey = this.getPostDataKey(timeline.uniqueId, postId);
 +    const cache = await dataStorage.getItem<BlobWithEtag | null>(dataKey);
 +
 +    if (cache == null) {
 +      const dataWithEtag = await getHttpTimelineClient().getPostData(
 +        timelineName,
 +        postId,
 +        userService.currentUser?.token
 +      );
 +      await dataStorage.setItem<BlobWithEtag>(dataKey, dataWithEtag);
 +      this._postDataSubscriptionHub.update(
 +        {
 +          postId,
 +          timelineName,
 +        },
 +        () =>
 +          Promise.resolve({
 +            blob: dataWithEtag.data,
 +            url: URL.createObjectURL(dataWithEtag.data),
 +          })
 +      );
 +      return dataWithEtag.data;
 +    } else {
 +      const res = await getHttpTimelineClient().getPostData(
 +        timelineName,
 +        postId,
 +        userService.currentUser?.token,
 +        cache.etag
 +      );
 +      if (res instanceof NotModified) {
 +        return cache.data;
 +      } else {
 +        await dataStorage.setItem<BlobWithEtag>(dataKey, res);
 +        this._postDataSubscriptionHub.update(
 +          {
 +            postId,
 +            timelineName,
 +          },
 +          () =>
 +            Promise.resolve({
 +              blob: res.data,
 +              url: URL.createObjectURL(res.data),
 +            })
 +        );
 +        return res.data;
 +      }
 +    }
 +  }
 +
    private _postDataSubscriptionHub = new SubscriptionHub<
      PostKey,
      BlobWithUrl | null
 @@ -330,18 +408,16 @@ export class TimelineService {      (key) => `${key.timelineName}/${key.postId}`,
      () => null,
      async (key) => {
 -      const blob = (
 -        await getHttpTimelineClient().getPostData(
 -          key.timelineName,
 -          key.postId,
 -          userService.currentUser?.token
 -        )
 -      ).data;
 -      const url = URL.createObjectURL(blob);
 -      return {
 -        blob,
 -        url,
 -      };
 +      const blob = await this.getCachePostData(key.timelineName, key.postId);
 +      const result =
 +        blob == null
 +          ? null
 +          : {
 +              blob,
 +              url: URL.createObjectURL(blob),
 +            };
 +      void this.syncCachePostData(key.timelineName, key.postId);
 +      return result;
      },
      (_key, data) => {
        if (data != null) URL.revokeObjectURL(data.url);
  | 
