diff options
Diffstat (limited to 'src/state/models')
-rw-r--r-- | src/state/models/cache/handle-resolutions.ts | 5 | ||||
-rw-r--r-- | src/state/models/cache/posts.ts | 31 | ||||
-rw-r--r-- | src/state/models/content/post-thread.ts | 45 | ||||
-rw-r--r-- | src/state/models/content/profile.ts | 6 | ||||
-rw-r--r-- | src/state/models/feeds/notifications.ts | 5 | ||||
-rw-r--r-- | src/state/models/feeds/posts.ts | 4 | ||||
-rw-r--r-- | src/state/models/root-store.ts | 4 |
7 files changed, 96 insertions, 4 deletions
diff --git a/src/state/models/cache/handle-resolutions.ts b/src/state/models/cache/handle-resolutions.ts new file mode 100644 index 000000000..2e2b69661 --- /dev/null +++ b/src/state/models/cache/handle-resolutions.ts @@ -0,0 +1,5 @@ +import {LRUMap} from 'lru_map' + +export class HandleResolutionsCache { + cache: LRUMap<string, string> = new LRUMap(500) +} diff --git a/src/state/models/cache/posts.ts b/src/state/models/cache/posts.ts new file mode 100644 index 000000000..48621226a --- /dev/null +++ b/src/state/models/cache/posts.ts @@ -0,0 +1,31 @@ +import {LRUMap} from 'lru_map' +import {RootStoreModel} from '../root-store' +import {AppBskyFeedDefs} from '@atproto/api' + +type PostView = AppBskyFeedDefs.PostView + +export class PostsCache { + cache: LRUMap<string, PostView> = new LRUMap(500) + + constructor(public rootStore: RootStoreModel) {} + + set(uri: string, postView: PostView) { + this.cache.set(uri, postView) + if (postView.author.handle) { + this.rootStore.handleResolutions.cache.set( + postView.author.handle, + postView.author.did, + ) + } + } + + fromFeedItem(feedItem: AppBskyFeedDefs.FeedViewPost) { + this.set(feedItem.post.uri, feedItem.post) + if ( + feedItem.reply?.parent && + AppBskyFeedDefs.isPostView(feedItem.reply?.parent) + ) { + this.set(feedItem.reply.parent.uri, feedItem.reply.parent) + } + } +} diff --git a/src/state/models/content/post-thread.ts b/src/state/models/content/post-thread.ts index 0a67c783e..c500174a5 100644 --- a/src/state/models/content/post-thread.ts +++ b/src/state/models/content/post-thread.ts @@ -12,6 +12,8 @@ import {PostThreadItemModel} from './post-thread-item' export class PostThreadModel { // state isLoading = false + isLoadingFromCache = false + isFromCache = false isRefreshing = false hasLoaded = false error = '' @@ -20,7 +22,7 @@ export class PostThreadModel { params: GetPostThread.QueryParams // data - thread?: PostThreadItemModel + thread?: PostThreadItemModel | null = null isBlocked = false constructor( @@ -52,7 +54,7 @@ export class PostThreadModel { } get hasContent() { - return typeof this.thread !== 'undefined' + return !!this.thread } get hasError() { @@ -82,10 +84,16 @@ export class PostThreadModel { if (!this.resolvedUri) { await this._resolveUri() } + if (this.hasContent) { await this.update() } else { - await this._load() + const precache = this.rootStore.posts.cache.get(this.resolvedUri) + if (precache) { + await this._loadPrecached(precache) + } else { + await this._load() + } } } @@ -169,6 +177,37 @@ export class PostThreadModel { }) } + async _loadPrecached(precache: AppBskyFeedDefs.PostView) { + // start with the cached version + this.isLoadingFromCache = true + this.isFromCache = true + this._replaceAll({ + success: true, + headers: {}, + data: { + thread: { + post: precache, + }, + }, + }) + this._xIdle() + + // then update in the background + try { + const res = await this.rootStore.agent.getPostThread( + Object.assign({}, this.params, {uri: this.resolvedUri}), + ) + this._replaceAll(res) + } catch (e: any) { + console.log(e) + this._xIdle(e) + } finally { + runInAction(() => { + this.isLoadingFromCache = false + }) + } + } + async _load(isRefreshing = false) { if (this.hasLoaded && !isRefreshing) { return diff --git a/src/state/models/content/profile.ts b/src/state/models/content/profile.ts index 34b2ea28e..c4cbe6d44 100644 --- a/src/state/models/content/profile.ts +++ b/src/state/models/content/profile.ts @@ -253,6 +253,12 @@ export class ProfileModel { try { const res = await this.rootStore.agent.getProfile(this.params) this.rootStore.profiles.overwrite(this.params.actor, res) // cache invalidation + if (res.data.handle) { + this.rootStore.handleResolutions.cache.set( + res.data.handle, + res.data.did, + ) + } this._replaceAll(res) await this._createRichText() this._xIdle() diff --git a/src/state/models/feeds/notifications.ts b/src/state/models/feeds/notifications.ts index 05e2ef0db..b7ac3a53b 100644 --- a/src/state/models/feeds/notifications.ts +++ b/src/state/models/feeds/notifications.ts @@ -503,7 +503,9 @@ export class NotificationsFeedModel { const postsRes = await this.rootStore.agent.app.bsky.feed.getPosts({ uris: [addedUri], }) - notif.setAdditionalData(postsRes.data.posts[0]) + const post = postsRes.data.posts[0] + notif.setAdditionalData(post) + this.rootStore.posts.set(post.uri, post) } const filtered = this._filterNotifications([notif]) return filtered[0] @@ -611,6 +613,7 @@ export class NotificationsFeedModel { ), ) for (const post of postsChunks.flat()) { + this.rootStore.posts.set(post.uri, post) const models = addedPostMap.get(post.uri) if (models?.length) { for (const model of models) { diff --git a/src/state/models/feeds/posts.ts b/src/state/models/feeds/posts.ts index 4e6633d38..94d7228ed 100644 --- a/src/state/models/feeds/posts.ts +++ b/src/state/models/feeds/posts.ts @@ -374,6 +374,9 @@ export class PostsFeedModel { this.rootStore.me.follows.hydrateProfiles( res.data.feed.map(item => item.post.author), ) + for (const item of res.data.feed) { + this.rootStore.posts.fromFeedItem(item) + } const slices = this.tuner.tune(res.data.feed, this.feedTuners) @@ -405,6 +408,7 @@ export class PostsFeedModel { res: GetTimeline.Response | GetAuthorFeed.Response | GetCustomFeed.Response, ) { for (const item of res.data.feed) { + this.rootStore.posts.fromFeedItem(item) const existingSlice = this.slices.find(slice => slice.containsUri(item.post.uri), ) diff --git a/src/state/models/root-store.ts b/src/state/models/root-store.ts index d76ea07c9..6ced8090a 100644 --- a/src/state/models/root-store.ts +++ b/src/state/models/root-store.ts @@ -12,7 +12,9 @@ import {isObj, hasProp} from 'lib/type-guards' import {LogModel} from './log' import {SessionModel} from './session' import {ShellUiModel} from './ui/shell' +import {HandleResolutionsCache} from './cache/handle-resolutions' import {ProfilesCache} from './cache/profiles-view' +import {PostsCache} from './cache/posts' import {LinkMetasCache} from './cache/link-metas' import {NotificationsFeedItemModel} from './feeds/notifications' import {MeModel} from './me' @@ -45,7 +47,9 @@ export class RootStoreModel { preferences = new PreferencesModel(this) me = new MeModel(this) invitedUsers = new InvitedUsers(this) + handleResolutions = new HandleResolutionsCache() profiles = new ProfilesCache(this) + posts = new PostsCache(this) linkMetas = new LinkMetasCache(this) imageSizes = new ImageSizesCache() mutedThreads = new MutedThreads() |