From f2e39d8ad24041637810327ca28ad78f9f36bf2f Mon Sep 17 00:00:00 2001 From: Ansh Nanda Date: Tue, 16 May 2023 15:50:52 -0700 Subject: allow for pinning saved feeds --- src/state/models/feeds/algo/algo-item.ts | 4 ++ src/state/models/feeds/algo/saved.ts | 42 ++++++++++++ src/state/models/me.ts | 4 ++ src/view/com/algos/AlgoItem.tsx | 67 +++++++++++-------- src/view/index.ts | 2 + src/view/screens/CustomFeed.tsx | 2 +- src/view/screens/SavedFeeds.tsx | 107 ++++++++++++++++++++++--------- 7 files changed, 170 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/src/state/models/feeds/algo/algo-item.ts b/src/state/models/feeds/algo/algo-item.ts index 0eaeebd39..39bc760ac 100644 --- a/src/state/models/feeds/algo/algo-item.ts +++ b/src/state/models/feeds/algo/algo-item.ts @@ -153,4 +153,8 @@ export class AlgoItemModel { }) this.data = 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 index 5d2f854dc..15859fe0c 100644 --- a/src/state/models/feeds/algo/saved.ts +++ b/src/state/models/feeds/algo/saved.ts @@ -4,6 +4,7 @@ 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 @@ -18,6 +19,7 @@ export class SavedFeedsModel { // data feeds: AlgoItemModel[] = [] + pinned: AlgoItemModel[] = [] constructor(public rootStore: RootStoreModel) { makeAutoObservable( @@ -29,6 +31,24 @@ export class SavedFeedsModel { ) } + 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 } @@ -51,6 +71,28 @@ export class SavedFeedsModel { ) } + 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.pinned = this.pinned.filter(f => f.data.uri !== feed.data.uri) + } + } + + reorderPinnedFeeds(temp: AlgoItemModel[]) { + this.pinned = temp + } + + isPinned(feed: AlgoItemModel) { + return this.pinned.find(f => f.data.uri === feed.data.uri) ? true : false + } + // public api // = diff --git a/src/state/models/me.ts b/src/state/models/me.ts index 314e76b9c..68c89ac9b 100644 --- a/src/state/models/me.ts +++ b/src/state/models/me.ts @@ -69,6 +69,7 @@ export class MeModel { displayName: this.displayName, description: this.description, avatar: this.avatar, + savedFeeds: this.savedFeeds.serialize(), } } @@ -90,6 +91,9 @@ export class MeModel { if (hasProp(v, 'avatar') && typeof v.avatar === 'string') { avatar = v.avatar } + if (hasProp(v, 'savedFeeds') && isObj(v.savedFeeds)) { + this.savedFeeds.hydrate(v.savedFeeds) + } if (did && handle) { this.did = did this.handle = handle diff --git a/src/view/com/algos/AlgoItem.tsx b/src/view/com/algos/AlgoItem.tsx index 4377e3583..f7d320530 100644 --- a/src/view/com/algos/AlgoItem.tsx +++ b/src/view/com/algos/AlgoItem.tsx @@ -19,7 +19,17 @@ import {useStores} from 'state/index' import {HeartIconSolid} from 'lib/icons' const AlgoItem = observer( - ({item, style}: {item: AlgoItemModel; style?: StyleProp}) => { + ({ + item, + style, + showBottom = true, + onLongPress, + }: { + item: AlgoItemModel + style?: StyleProp + showBottom?: boolean + onLongPress?: () => void + }) => { const store = useStores() const pal = usePalette('default') const navigation = useNavigation() @@ -34,10 +44,11 @@ const AlgoItem = observer( rkey: item.data.uri, }) }} + onLongPress={onLongPress} key={item.data.uri}> - + @@ -49,37 +60,39 @@ const AlgoItem = observer( - - - {/* + {showBottom ? ( + + + {/* */} - - - {item.data.likeCount && item.data.likeCount > 1 - ? `Liked by ${item.data.likeCount} others` - : 'Be the first to like this'} - - - -