diff options
Diffstat (limited to 'src/state/models/feeds/algo')
-rw-r--r-- | src/state/models/feeds/algo/actor.ts | 121 | ||||
-rw-r--r-- | src/state/models/feeds/algo/algo-item.ts | 142 | ||||
-rw-r--r-- | src/state/models/feeds/algo/saved.ts | 249 |
3 files changed, 0 insertions, 512 deletions
diff --git a/src/state/models/feeds/algo/actor.ts b/src/state/models/feeds/algo/actor.ts deleted file mode 100644 index e42df8495..000000000 --- a/src/state/models/feeds/algo/actor.ts +++ /dev/null @@ -1,121 +0,0 @@ -import {makeAutoObservable} from 'mobx' -import {AppBskyFeedGetActorFeeds as GetActorFeeds} from '@atproto/api' -import {RootStoreModel} from '../../root-store' -import {bundleAsync} from 'lib/async/bundle' -import {cleanError} from 'lib/strings/errors' -import {AlgoItemModel} from './algo-item' - -const PAGE_SIZE = 30 - -export class ActorFeedsModel { - // state - isLoading = false - isRefreshing = false - hasLoaded = false - error = '' - hasMore = true - loadMoreCursor?: string - - // data - feeds: AlgoItemModel[] = [] - - constructor( - public rootStore: RootStoreModel, - public params: GetActorFeeds.QueryParams, - ) { - makeAutoObservable( - this, - { - rootStore: false, - }, - {autoBind: true}, - ) - } - - get hasContent() { - return this.feeds.length > 0 - } - - get hasError() { - return this.error !== '' - } - - get isEmpty() { - return this.hasLoaded && !this.hasContent - } - - // public api - // = - - async refresh() { - return this.loadMore(true) - } - - clear() { - this.isLoading = false - this.isRefreshing = false - this.hasLoaded = false - this.error = '' - this.hasMore = true - this.loadMoreCursor = undefined - this.feeds = [] - } - - loadMore = bundleAsync(async (replace: boolean = false) => { - if (!replace && !this.hasMore) { - return - } - this._xLoading(replace) - try { - const res = await this.rootStore.agent.app.bsky.feed.getActorFeeds({ - actor: this.params.actor, - limit: PAGE_SIZE, - cursor: replace ? undefined : this.loadMoreCursor, - }) - console.log('res', res.data.feeds) - if (replace) { - this._replaceAll(res) - } else { - this._appendAll(res) - } - this._xIdle() - } catch (e: any) { - this._xIdle(e) - } - }) - - // state transitions - // = - - _xLoading(isRefreshing = false) { - this.isLoading = true - this.isRefreshing = isRefreshing - this.error = '' - } - - _xIdle(err?: any) { - this.isLoading = false - this.isRefreshing = false - this.hasLoaded = true - this.error = cleanError(err) - if (err) { - this.rootStore.log.error('Failed to fetch user followers', err) - } - } - - // helper functions - // = - - _replaceAll(res: GetActorFeeds.Response) { - this.feeds = [] - this._appendAll(res) - } - - _appendAll(res: GetActorFeeds.Response) { - this.loadMoreCursor = res.data.cursor - this.hasMore = !!this.loadMoreCursor - for (const f of res.data.feeds) { - this.feeds.push(new AlgoItemModel(this.rootStore, f)) - } - } -} diff --git a/src/state/models/feeds/algo/algo-item.ts b/src/state/models/feeds/algo/algo-item.ts deleted file mode 100644 index bd4ea4fd6..000000000 --- a/src/state/models/feeds/algo/algo-item.ts +++ /dev/null @@ -1,142 +0,0 @@ -import {AppBskyFeedDefs, AtUri} from '@atproto/api' -import {makeAutoObservable} from 'mobx' -import {RootStoreModel} from 'state/models/root-store' - -export class AlgoItemModel { - // data - data: AppBskyFeedDefs.GeneratorView - - constructor( - public rootStore: RootStoreModel, - view: AppBskyFeedDefs.GeneratorView, - ) { - this.data = view - makeAutoObservable( - this, - { - rootStore: false, - }, - {autoBind: true}, - ) - } - - // local actions - // = - set toggleSaved(value: boolean) { - console.log('toggleSaved', this.data.viewer) - if (this.data.viewer) { - this.data.viewer.saved = value - } - } - - get getUri() { - return this.data.uri - } - - get isSaved() { - return this.data.viewer?.saved - } - - get isLiked() { - return this.data.viewer?.like - } - - private toggleLiked(s?: string) { - if (this.data.viewer) { - if (this.data.viewer.like) { - this.data.viewer.like = undefined - } else { - this.data.viewer.like = s - } - } - } - - private incrementLike() { - if (this.data.likeCount) { - this.data.likeCount += 1 - } else { - this.data.likeCount = 1 - } - } - - private decrementLike() { - if (this.data.likeCount) { - this.data.likeCount -= 1 - } else { - this.data.likeCount = 0 - } - } - - private rewriteData(data: AppBskyFeedDefs.GeneratorView) { - this.data = data - } - - // public apis - // = - async like() { - try { - const res = await this.rootStore.agent.app.bsky.feed.like.create( - { - repo: this.rootStore.me.did, - }, - { - subject: { - uri: this.data.uri, - cid: this.data.cid, - }, - createdAt: new Date().toISOString(), - }, - ) - this.toggleLiked(res.uri) - this.incrementLike() - } catch (e: any) { - this.rootStore.log.error('Failed to like feed', e) - } - } - - async unlike() { - try { - await this.rootStore.agent.app.bsky.feed.like.delete({ - repo: this.rootStore.me.did, - rkey: new AtUri(this.data.viewer?.like!).rkey, - }) - this.toggleLiked() - this.decrementLike() - } catch (e: any) { - this.rootStore.log.error('Failed to unlike feed', e) - } - } - - static async getView(store: RootStoreModel, uri: string) { - const res = await store.agent.app.bsky.feed.getFeedGenerator({ - feed: uri, - }) - const view = res.data.view - return view - } - - async checkIsValid() { - const res = await this.rootStore.agent.app.bsky.feed.getFeedGenerator({ - feed: this.data.uri, - }) - return res.data.isValid - } - - async checkIsOnline() { - const res = await this.rootStore.agent.app.bsky.feed.getFeedGenerator({ - feed: this.data.uri, - }) - return res.data.isOnline - } - - async reload() { - const res = await this.rootStore.agent.app.bsky.feed.getFeedGenerator({ - feed: this.data.uri, - }) - this.rewriteData(res.data.view) - } - - serialize() { - return JSON.stringify(this.data) - } -} diff --git a/src/state/models/feeds/algo/saved.ts b/src/state/models/feeds/algo/saved.ts deleted file mode 100644 index cb2015ccb..000000000 --- a/src/state/models/feeds/algo/saved.ts +++ /dev/null @@ -1,249 +0,0 @@ -import {makeAutoObservable, runInAction} from 'mobx' -import {AppBskyFeedGetSavedFeeds as GetSavedFeeds} from '@atproto/api' -import {RootStoreModel} from '../../root-store' -import {bundleAsync} from 'lib/async/bundle' -import {cleanError} from 'lib/strings/errors' -import {AlgoItemModel} from './algo-item' -import {hasProp, isObj} from 'lib/type-guards' - -const PAGE_SIZE = 30 - -export class SavedFeedsModel { - // state - isLoading = false - isRefreshing = false - hasLoaded = false - error = '' - hasMore = true - loadMoreCursor?: string - - // data - feeds: AlgoItemModel[] = [] - pinned: AlgoItemModel[] = [] - - constructor(public rootStore: RootStoreModel) { - makeAutoObservable( - this, - { - rootStore: false, - }, - {autoBind: true}, - ) - } - - serialize() { - return { - pinned: this.pinned.map(f => f.serialize()), - } - } - - hydrate(v: unknown) { - if (isObj(v)) { - if (hasProp(v, 'pinned')) { - const pinnedSerialized = (v as any).pinned as string[] - const pinnedDeserialized = pinnedSerialized.map( - (s: string) => new AlgoItemModel(this.rootStore, JSON.parse(s)), - ) - this.pinned = pinnedDeserialized - } - } - } - - get hasContent() { - return this.feeds.length > 0 - } - - get hasError() { - return this.error !== '' - } - - get isEmpty() { - return this.hasLoaded && !this.hasContent - } - - get numOfFeeds() { - return this.feeds.length - } - - get listOfFeedNames() { - return this.feeds.map( - f => f.data.displayName ?? f.data.creator.displayName + "'s feed", - ) - } - - get listOfPinnedFeedNames() { - return this.pinned.map( - f => f.data.displayName ?? f.data.creator.displayName + "'s feed", - ) - } - - get savedFeedsWithoutPinned() { - return this.feeds.filter( - f => !this.pinned.find(p => p.data.uri === f.data.uri), - ) - } - - togglePinnedFeed(feed: AlgoItemModel) { - if (!this.isPinned(feed)) { - this.pinned.push(feed) - } else { - this.removePinnedFeed(feed.data.uri) - } - } - - removePinnedFeed(uri: string) { - this.pinned = this.pinned.filter(f => f.data.uri !== uri) - } - - reorderPinnedFeeds(temp: AlgoItemModel[]) { - this.pinned = temp - } - - isPinned(feed: AlgoItemModel) { - return this.pinned.find(f => f.data.uri === feed.data.uri) ? true : false - } - - movePinnedItem(item: AlgoItemModel, direction: 'up' | 'down') { - if (this.pinned.length < 2) { - throw new Error('Array must have at least 2 items') - } - const index = this.pinned.indexOf(item) - if (index === -1) { - throw new Error('Item not found in array') - } - - const len = this.pinned.length - - runInAction(() => { - if (direction === 'up') { - if (index === 0) { - // Remove the item from the first place and put it at the end - this.pinned.push(this.pinned.shift()!) - } else { - // Swap the item with the one before it - const temp = this.pinned[index] - this.pinned[index] = this.pinned[index - 1] - this.pinned[index - 1] = temp - } - } else if (direction === 'down') { - if (index === len - 1) { - // Remove the item from the last place and put it at the start - this.pinned.unshift(this.pinned.pop()!) - } else { - // Swap the item with the one after it - const temp = this.pinned[index] - this.pinned[index] = this.pinned[index + 1] - this.pinned[index + 1] = temp - } - } - // this.pinned = [...this.pinned] - }) - } - - // public api - // = - - async refresh() { - return this.loadMore(true) - } - - clear() { - this.isLoading = false - this.isRefreshing = false - this.hasLoaded = false - this.error = '' - this.hasMore = true - this.loadMoreCursor = undefined - this.feeds = [] - } - - loadMore = bundleAsync(async (replace: boolean = false) => { - if (!replace && !this.hasMore) { - return - } - this._xLoading(replace) - try { - const res = await this.rootStore.agent.app.bsky.feed.getSavedFeeds({ - limit: PAGE_SIZE, - cursor: replace ? undefined : this.loadMoreCursor, - }) - if (replace) { - this._replaceAll(res) - } else { - this._appendAll(res) - } - this._xIdle() - } catch (e: any) { - this._xIdle(e) - } - }) - - removeFeed(uri: string) { - this.feeds = this.feeds.filter(f => f.data.uri !== uri) - } - - addFeed(algoItem: AlgoItemModel) { - this.feeds.push(new AlgoItemModel(this.rootStore, algoItem.data)) - } - - async save(algoItem: AlgoItemModel) { - try { - await this.rootStore.agent.app.bsky.feed.saveFeed({ - feed: algoItem.getUri, - }) - algoItem.toggleSaved = true - this.addFeed(algoItem) - } catch (e: any) { - this.rootStore.log.error('Failed to save feed', e) - } - } - - async unsave(algoItem: AlgoItemModel) { - const uri = algoItem.getUri - try { - await this.rootStore.agent.app.bsky.feed.unsaveFeed({ - feed: uri, - }) - algoItem.toggleSaved = false - this.removeFeed(uri) - this.removePinnedFeed(uri) - } catch (e: any) { - this.rootStore.log.error('Failed to unsanve feed', e) - } - } - - // state transitions - // = - - _xLoading(isRefreshing = false) { - this.isLoading = true - this.isRefreshing = isRefreshing - this.error = '' - } - - _xIdle(err?: any) { - this.isLoading = false - this.isRefreshing = false - this.hasLoaded = true - this.error = cleanError(err) - if (err) { - this.rootStore.log.error('Failed to fetch user followers', err) - } - } - - // helper functions - // = - - _replaceAll(res: GetSavedFeeds.Response) { - this.feeds = [] - this._appendAll(res) - } - - _appendAll(res: GetSavedFeeds.Response) { - this.loadMoreCursor = res.data.cursor - this.hasMore = !!this.loadMoreCursor - for (const f of res.data.feeds) { - this.feeds.push(new AlgoItemModel(this.rootStore, f)) - } - } -} |