Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Reorganize state models for clarity (#378)

authored by

Paul Frazee and committed by
GitHub
2045c615 9652d994

+163 -171
+2 -2
src/lib/notifee.ts
··· 1 1 import notifee, {EventType} from '@notifee/react-native' 2 2 import {AppBskyEmbedImages} from '@atproto/api' 3 3 import {RootStoreModel} from 'state/models/root-store' 4 - import {NotificationsViewItemModel} from 'state/models/notifications-view' 4 + import {NotificationsFeedItemModel} from 'state/models/feeds/notifications' 5 5 import {enforceLen} from 'lib/strings/helpers' 6 6 import {resetToTab} from '../Navigation' 7 7 ··· 40 40 } 41 41 42 42 export function displayNotificationFromModel( 43 - notif: NotificationsViewItemModel, 43 + notif: NotificationsFeedItemModel, 44 44 ) { 45 45 let author = notif.author.displayName || notif.author.handle 46 46 let title: string
+15 -11
src/state/models/feed-view.ts src/state/models/feeds/posts.ts
··· 10 10 import AwaitLock from 'await-lock' 11 11 import {bundleAsync} from 'lib/async/bundle' 12 12 import sampleSize from 'lodash.samplesize' 13 - import {RootStoreModel} from './root-store' 13 + import {RootStoreModel} from '../root-store' 14 14 import {cleanError} from 'lib/strings/errors' 15 15 import {SUGGESTED_FOLLOWS} from 'lib/constants' 16 16 import { ··· 27 27 const PAGE_SIZE = 30 28 28 let _idCounter = 0 29 29 30 - export class FeedItemModel { 30 + export class PostsFeedItemModel { 31 31 // ui state 32 32 _reactKey: string = '' 33 33 ··· 139 139 } 140 140 } 141 141 142 - export class FeedSliceModel { 142 + export class PostsFeedSliceModel { 143 143 // ui state 144 144 _reactKey: string = '' 145 145 146 146 // data 147 - items: FeedItemModel[] = [] 147 + items: PostsFeedItemModel[] = [] 148 148 149 149 constructor( 150 150 public rootStore: RootStoreModel, ··· 154 154 this._reactKey = reactKey 155 155 for (const item of slice.items) { 156 156 this.items.push( 157 - new FeedItemModel(rootStore, `item-${_idCounter++}`, item), 157 + new PostsFeedItemModel(rootStore, `item-${_idCounter++}`, item), 158 158 ) 159 159 } 160 160 makeAutoObservable(this, {rootStore: false}) ··· 206 206 } 207 207 } 208 208 209 - export class FeedModel { 209 + export class PostsFeedModel { 210 210 // state 211 211 isLoading = false 212 212 isRefreshing = false ··· 223 223 lock = new AwaitLock() 224 224 225 225 // data 226 - slices: FeedSliceModel[] = [] 227 - nextSlices: FeedSliceModel[] = [] 226 + slices: PostsFeedSliceModel[] = [] 227 + nextSlices: PostsFeedSliceModel[] = [] 228 228 229 229 constructor( 230 230 public rootStore: RootStoreModel, ··· 445 445 if (nextSlices[0]?.uri !== this.slices[0]?.uri) { 446 446 const nextSlicesModels = nextSlices.map( 447 447 slice => 448 - new FeedSliceModel(this.rootStore, `item-${_idCounter++}`, slice), 448 + new PostsFeedSliceModel( 449 + this.rootStore, 450 + `item-${_idCounter++}`, 451 + slice, 452 + ), 449 453 ) 450 454 if (autoPrepend) { 451 455 runInAction(() => { ··· 526 530 527 531 const slices = this.tuner.tune(res.data.feed, this.feedTuners) 528 532 529 - const toAppend: FeedSliceModel[] = [] 533 + const toAppend: PostsFeedSliceModel[] = [] 530 534 for (const slice of slices) { 531 - const sliceModel = new FeedSliceModel( 535 + const sliceModel = new PostsFeedSliceModel( 532 536 this.rootStore, 533 537 `item-${_idCounter++}`, 534 538 slice,
+3 -3
src/state/models/likes-view.ts src/state/models/lists/likes.ts
··· 1 1 import {makeAutoObservable, runInAction} from 'mobx' 2 - import {AtUri} from '../../third-party/uri' 2 + import {AtUri} from '../../../third-party/uri' 3 3 import {AppBskyFeedGetLikes as GetLikes} from '@atproto/api' 4 - import {RootStoreModel} from './root-store' 4 + import {RootStoreModel} from '../root-store' 5 5 import {cleanError} from 'lib/strings/errors' 6 6 import {bundleAsync} from 'lib/async/bundle' 7 7 import * as apilib from 'lib/api/index' ··· 10 10 11 11 export type LikeItem = GetLikes.Like 12 12 13 - export class LikesViewModel { 13 + export class LikesModel { 14 14 // state 15 15 isLoading = false 16 16 isRefreshing = false
+6 -6
src/state/models/me.ts
··· 1 1 import {makeAutoObservable, runInAction} from 'mobx' 2 2 import {RootStoreModel} from './root-store' 3 - import {FeedModel} from './feed-view' 4 - import {NotificationsViewModel} from './notifications-view' 3 + import {PostsFeedModel} from './feeds/posts' 4 + import {NotificationsFeedModel} from './feeds/notifications' 5 5 import {MyFollowsCache} from './cache/my-follows' 6 6 import {isObj, hasProp} from 'lib/type-guards' 7 7 ··· 13 13 avatar: string = '' 14 14 followsCount: number | undefined 15 15 followersCount: number | undefined 16 - mainFeed: FeedModel 17 - notifications: NotificationsViewModel 16 + mainFeed: PostsFeedModel 17 + notifications: NotificationsFeedModel 18 18 follows: MyFollowsCache 19 19 20 20 constructor(public rootStore: RootStoreModel) { ··· 23 23 {rootStore: false, serialize: false, hydrate: false}, 24 24 {autoBind: true}, 25 25 ) 26 - this.mainFeed = new FeedModel(this.rootStore, 'home', { 26 + this.mainFeed = new PostsFeedModel(this.rootStore, 'home', { 27 27 algorithm: 'reverse-chronological', 28 28 }) 29 - this.notifications = new NotificationsViewModel(this.rootStore, {}) 29 + this.notifications = new NotificationsFeedModel(this.rootStore, {}) 30 30 this.follows = new MyFollowsCache(this.rootStore) 31 31 } 32 32
+16 -16
src/state/models/notifications-view.ts src/state/models/feeds/notifications.ts
··· 9 9 } from '@atproto/api' 10 10 import AwaitLock from 'await-lock' 11 11 import {bundleAsync} from 'lib/async/bundle' 12 - import {RootStoreModel} from './root-store' 13 - import {PostThreadViewModel} from './post-thread-view' 12 + import {RootStoreModel} from '../root-store' 13 + import {PostThreadModel} from '../content/post-thread' 14 14 import {cleanError} from 'lib/strings/errors' 15 15 16 16 const GROUPABLE_REASONS = ['like', 'repost', 'follow'] ··· 30 30 | AppBskyFeedLike.Record 31 31 | AppBskyGraphFollow.Record 32 32 33 - export class NotificationsViewItemModel { 33 + export class NotificationsFeedItemModel { 34 34 // ui state 35 35 _reactKey: string = '' 36 36 ··· 47 47 record?: SupportedRecord 48 48 isRead: boolean = false 49 49 indexedAt: string = '' 50 - additional?: NotificationsViewItemModel[] 50 + additional?: NotificationsFeedItemModel[] 51 51 52 52 // additional data 53 - additionalPost?: PostThreadViewModel 53 + additionalPost?: PostThreadModel 54 54 55 55 constructor( 56 56 public rootStore: RootStoreModel, ··· 75 75 this.additional = [] 76 76 for (const add of v.additional) { 77 77 this.additional.push( 78 - new NotificationsViewItemModel(this.rootStore, '', add), 78 + new NotificationsFeedItemModel(this.rootStore, '', add), 79 79 ) 80 80 } 81 81 } else if (!preserve) { ··· 171 171 postUri = this.subjectUri 172 172 } 173 173 if (postUri) { 174 - this.additionalPost = new PostThreadViewModel(this.rootStore, { 174 + this.additionalPost = new PostThreadModel(this.rootStore, { 175 175 uri: postUri, 176 176 depth: 0, 177 177 }) ··· 185 185 } 186 186 } 187 187 188 - export class NotificationsViewModel { 188 + export class NotificationsFeedModel { 189 189 // state 190 190 isLoading = false 191 191 isRefreshing = false ··· 199 199 lock = new AwaitLock() 200 200 201 201 // data 202 - notifications: NotificationsViewItemModel[] = [] 202 + notifications: NotificationsFeedItemModel[] = [] 203 203 unreadCount = 0 204 204 205 205 // this is used to help trigger push notifications ··· 416 416 } 417 417 } 418 418 419 - async getNewMostRecent(): Promise<NotificationsViewItemModel | undefined> { 419 + async getNewMostRecent(): Promise<NotificationsFeedItemModel | undefined> { 420 420 let old = this.mostRecentNotificationUri 421 421 const res = await this.rootStore.agent.listNotifications({ 422 422 limit: 1, ··· 425 425 return 426 426 } 427 427 this.mostRecentNotificationUri = res.data.notifications[0].uri 428 - const notif = new NotificationsViewItemModel( 428 + const notif = new NotificationsFeedItemModel( 429 429 this.rootStore, 430 430 'mostRecent', 431 431 res.data.notifications[0], ··· 467 467 this.loadMoreCursor = res.data.cursor 468 468 this.hasMore = !!this.loadMoreCursor 469 469 const promises = [] 470 - const itemModels: NotificationsViewItemModel[] = [] 470 + const itemModels: NotificationsFeedItemModel[] = [] 471 471 for (const item of groupNotifications(res.data.notifications)) { 472 - const itemModel = new NotificationsViewItemModel( 472 + const itemModel = new NotificationsFeedItemModel( 473 473 this.rootStore, 474 474 `item-${_idCounter++}`, 475 475 item, ··· 496 496 497 497 async _prependAll(res: ListNotifications.Response) { 498 498 const promises = [] 499 - const itemModels: NotificationsViewItemModel[] = [] 499 + const itemModels: NotificationsFeedItemModel[] = [] 500 500 const dedupedNotifs = res.data.notifications.filter( 501 501 n1 => 502 502 !this.notifications.find( ··· 504 504 ), 505 505 ) 506 506 for (const item of groupNotifications(dedupedNotifs)) { 507 - const itemModel = new NotificationsViewItemModel( 507 + const itemModel = new NotificationsFeedItemModel( 508 508 this.rootStore, 509 509 `item-${_idCounter++}`, 510 510 item, ··· 565 565 return items2 566 566 } 567 567 568 - type N = ListNotifications.Notification | NotificationsViewItemModel 568 + type N = ListNotifications.Notification | NotificationsFeedItemModel 569 569 function isEq(a: N, b: N) { 570 570 // this function has a key subtlety- the indexedAt comparison 571 571 // the reason for this is reposts: they set the URI of the original post, not of the repost record
+10 -10
src/state/models/post-thread-view.ts src/state/models/content/post-thread.ts
··· 5 5 AppBskyFeedDefs, 6 6 RichText, 7 7 } from '@atproto/api' 8 - import {AtUri} from '../../third-party/uri' 9 - import {RootStoreModel} from './root-store' 8 + import {AtUri} from '../../../third-party/uri' 9 + import {RootStoreModel} from '../root-store' 10 10 import * as apilib from 'lib/api/index' 11 11 import {cleanError} from 'lib/strings/errors' 12 12 ··· 17 17 } 18 18 } 19 19 20 - export class PostThreadViewPostModel { 20 + export class PostThreadItemModel { 21 21 // ui state 22 22 _reactKey: string = '' 23 23 _depth = 0 ··· 29 29 // data 30 30 post: AppBskyFeedDefs.PostView 31 31 postRecord?: FeedPost.Record 32 - parent?: PostThreadViewPostModel | AppBskyFeedDefs.NotFoundPost 33 - replies?: (PostThreadViewPostModel | AppBskyFeedDefs.NotFoundPost)[] 32 + parent?: PostThreadItemModel | AppBskyFeedDefs.NotFoundPost 33 + replies?: (PostThreadItemModel | AppBskyFeedDefs.NotFoundPost)[] 34 34 richText?: RichText 35 35 36 36 get uri() { ··· 79 79 // parents 80 80 if (includeParent && v.parent) { 81 81 if (AppBskyFeedDefs.isThreadViewPost(v.parent)) { 82 - const parentModel = new PostThreadViewPostModel( 82 + const parentModel = new PostThreadItemModel( 83 83 this.rootStore, 84 84 keyGen.next().value, 85 85 v.parent, ··· 106 106 const replies = [] 107 107 for (const item of v.replies) { 108 108 if (AppBskyFeedDefs.isThreadViewPost(item)) { 109 - const itemModel = new PostThreadViewPostModel( 109 + const itemModel = new PostThreadItemModel( 110 110 this.rootStore, 111 111 keyGen.next().value, 112 112 item, ··· 182 182 } 183 183 } 184 184 185 - export class PostThreadViewModel { 185 + export class PostThreadModel { 186 186 // state 187 187 isLoading = false 188 188 isRefreshing = false ··· 193 193 params: GetPostThread.QueryParams 194 194 195 195 // data 196 - thread?: PostThreadViewPostModel 196 + thread?: PostThreadItemModel 197 197 198 198 constructor( 199 199 public rootStore: RootStoreModel, ··· 321 321 _replaceAll(res: GetPostThread.Response) { 322 322 sortThread(res.data.thread) 323 323 const keyGen = reactKeyGenerator() 324 - const thread = new PostThreadViewPostModel( 324 + const thread = new PostThreadItemModel( 325 325 this.rootStore, 326 326 keyGen.next().value, 327 327 res.data.thread as AppBskyFeedDefs.ThreadViewPost,
+2 -2
src/state/models/post.ts src/state/models/content/post.ts
··· 1 1 import {makeAutoObservable} from 'mobx' 2 2 import {AppBskyFeedPost as Post} from '@atproto/api' 3 - import {AtUri} from '../../third-party/uri' 4 - import {RootStoreModel} from './root-store' 3 + import {AtUri} from '../../../third-party/uri' 4 + import {RootStoreModel} from '../root-store' 5 5 import {cleanError} from 'lib/strings/errors' 6 6 7 7 type RemoveIndex<T> = {
+4 -4
src/state/models/profile-view.ts src/state/models/content/profile.ts
··· 5 5 AppBskyActorProfile, 6 6 RichText, 7 7 } from '@atproto/api' 8 - import {RootStoreModel} from './root-store' 8 + import {RootStoreModel} from '../root-store' 9 9 import * as apilib from 'lib/api/index' 10 10 import {cleanError} from 'lib/strings/errors' 11 11 12 12 export const ACTOR_TYPE_USER = 'app.bsky.system.actorUser' 13 13 14 - export class ProfileViewViewerModel { 14 + export class ProfileViewerModel { 15 15 muted?: boolean 16 16 following?: string 17 17 followedBy?: string ··· 21 21 } 22 22 } 23 23 24 - export class ProfileViewModel { 24 + export class ProfileModel { 25 25 // state 26 26 isLoading = false 27 27 isRefreshing = false ··· 40 40 followersCount: number = 0 41 41 followsCount: number = 0 42 42 postsCount: number = 0 43 - viewer = new ProfileViewViewerModel() 43 + viewer = new ProfileViewerModel() 44 44 45 45 // added data 46 46 descriptionRichText?: RichText = new RichText({text: ''})
+2 -2
src/state/models/profiles-view.ts src/state/models/cache/profiles-view.ts
··· 1 1 import {makeAutoObservable} from 'mobx' 2 2 import {LRUMap} from 'lru_map' 3 - import {RootStoreModel} from './root-store' 3 + import {RootStoreModel} from '../root-store' 4 4 import {AppBskyActorGetProfile as GetProfile} from '@atproto/api' 5 5 6 6 type CacheValue = Promise<GetProfile.Response> | GetProfile.Response 7 - export class ProfilesViewModel { 7 + export class ProfilesCache { 8 8 cache: LRUMap<string, CacheValue> = new LRUMap(100) 9 9 10 10 constructor(public rootStore: RootStoreModel) {
+3 -3
src/state/models/reposted-by-view.ts src/state/models/lists/reposted-by.ts
··· 1 1 import {makeAutoObservable, runInAction} from 'mobx' 2 - import {AtUri} from '../../third-party/uri' 2 + import {AtUri} from '../../../third-party/uri' 3 3 import { 4 4 AppBskyFeedGetRepostedBy as GetRepostedBy, 5 5 AppBskyActorDefs, 6 6 } from '@atproto/api' 7 - import {RootStoreModel} from './root-store' 7 + import {RootStoreModel} from '../root-store' 8 8 import {bundleAsync} from 'lib/async/bundle' 9 9 import {cleanError} from 'lib/strings/errors' 10 10 import * as apilib from 'lib/api/index' ··· 13 13 14 14 export type RepostedByItem = AppBskyActorDefs.ProfileViewBasic 15 15 16 - export class RepostedByViewModel { 16 + export class RepostedByModel { 17 17 // state 18 18 isLoading = false 19 19 isRefreshing = false
+5 -5
src/state/models/root-store.ts
··· 12 12 import {LogModel} from './log' 13 13 import {SessionModel} from './session' 14 14 import {ShellUiModel} from './ui/shell' 15 - import {ProfilesViewModel} from './profiles-view' 15 + import {ProfilesCache} from './cache/profiles-view' 16 16 import {LinkMetasCache} from './cache/link-metas' 17 - import {NotificationsViewItemModel} from './notifications-view' 17 + import {NotificationsFeedItemModel} from './feeds/notifications' 18 18 import {MeModel} from './me' 19 19 import {PreferencesModel} from './ui/preferences' 20 20 import {resetToTab} from '../../Navigation' ··· 36 36 shell = new ShellUiModel(this) 37 37 preferences = new PreferencesModel() 38 38 me = new MeModel(this) 39 - profiles = new ProfilesViewModel(this) 39 + profiles = new ProfilesCache(this) 40 40 linkMetas = new LinkMetasCache(this) 41 41 imageSizes = new ImageSizesCache() 42 42 ··· 205 205 206 206 // a notification has been queued for push 207 207 onPushNotification( 208 - handler: (notif: NotificationsViewItemModel) => void, 208 + handler: (notif: NotificationsFeedItemModel) => void, 209 209 ): EmitterSubscription { 210 210 return DeviceEventEmitter.addListener('push-notification', handler) 211 211 } 212 - emitPushNotification(notif: NotificationsViewItemModel) { 212 + emitPushNotification(notif: NotificationsFeedItemModel) { 213 213 DeviceEventEmitter.emit('push-notification', notif) 214 214 } 215 215
+5 -5
src/state/models/suggested-posts-view.ts src/state/models/discovery/suggested-posts.ts
··· 1 1 import {makeAutoObservable, runInAction} from 'mobx' 2 - import {RootStoreModel} from './root-store' 3 - import {FeedItemModel} from './feed-view' 2 + import {RootStoreModel} from '../root-store' 3 + import {PostsFeedItemModel} from '../feeds/posts' 4 4 import {cleanError} from 'lib/strings/errors' 5 5 import {TEAM_HANDLES} from 'lib/constants' 6 6 import { ··· 8 8 mergePosts, 9 9 } from 'lib/api/build-suggested-posts' 10 10 11 - export class SuggestedPostsView { 11 + export class SuggestedPostsModel { 12 12 // state 13 13 isLoading = false 14 14 hasLoaded = false 15 15 error = '' 16 16 17 17 // data 18 - posts: FeedItemModel[] = [] 18 + posts: PostsFeedItemModel[] = [] 19 19 20 20 constructor(public rootStore: RootStoreModel) { 21 21 makeAutoObservable( ··· 57 57 this.posts = finalPosts.map((post, i) => { 58 58 // strip the reasons to hide that these are reposts 59 59 delete post.reason 60 - return new FeedItemModel(this.rootStore, `post-${i}`, post) 60 + return new PostsFeedItemModel(this.rootStore, `post-${i}`, post) 61 61 }) 62 62 }) 63 63 this._xIdle()
+8 -8
src/state/models/ui/profile.ts
··· 1 1 import {makeAutoObservable} from 'mobx' 2 2 import {RootStoreModel} from '../root-store' 3 - import {ProfileViewModel} from '../profile-view' 4 - import {FeedModel} from '../feed-view' 3 + import {ProfileModel} from '../content/profile' 4 + import {PostsFeedModel} from '../feeds/posts' 5 5 6 6 export enum Sections { 7 7 Posts = 'Posts', ··· 20 20 static EMPTY_ITEM = {_reactKey: '__empty__'} 21 21 22 22 // data 23 - profile: ProfileViewModel 24 - feed: FeedModel 23 + profile: ProfileModel 24 + feed: PostsFeedModel 25 25 26 26 // ui state 27 27 selectedViewIndex = 0 ··· 38 38 }, 39 39 {autoBind: true}, 40 40 ) 41 - this.profile = new ProfileViewModel(rootStore, {actor: params.user}) 42 - this.feed = new FeedModel(rootStore, 'author', { 41 + this.profile = new ProfileModel(rootStore, {actor: params.user}) 42 + this.feed = new PostsFeedModel(rootStore, 'author', { 43 43 actor: params.user, 44 44 limit: 10, 45 45 }) 46 46 } 47 47 48 - get currentView(): FeedModel { 48 + get currentView(): PostsFeedModel { 49 49 if ( 50 50 this.selectedView === Sections.Posts || 51 51 this.selectedView === Sections.PostsWithReplies ··· 137 137 138 138 async update() { 139 139 const view = this.currentView 140 - if (view instanceof FeedModel) { 140 + if (view instanceof PostsFeedModel) { 141 141 await view.update() 142 142 } 143 143 }
+3 -3
src/state/models/ui/shell.ts
··· 1 1 import {AppBskyEmbedRecord} from '@atproto/api' 2 2 import {RootStoreModel} from '../root-store' 3 3 import {makeAutoObservable} from 'mobx' 4 - import {ProfileViewModel} from '../profile-view' 4 + import {ProfileModel} from '../content/profile' 5 5 import {isObj, hasProp} from 'lib/type-guards' 6 6 import {PickedMedia} from 'lib/media/types' 7 7 ··· 14 14 15 15 export interface EditProfileModal { 16 16 name: 'edit-profile' 17 - profileView: ProfileViewModel 17 + profileView: ProfileModel 18 18 onUpdate?: () => void 19 19 } 20 20 ··· 77 77 78 78 export class ProfileImageLightbox implements LightboxModel { 79 79 name = 'profile-image' 80 - constructor(public profileView: ProfileViewModel) { 80 + constructor(public profileView: ProfileModel) { 81 81 makeAutoObservable(this) 82 82 } 83 83 }
+2 -2
src/state/models/user-autocomplete-view.ts src/state/models/discovery/user-autocomplete.ts
··· 1 1 import {makeAutoObservable, runInAction} from 'mobx' 2 2 import {AppBskyActorDefs} from '@atproto/api' 3 3 import AwaitLock from 'await-lock' 4 - import {RootStoreModel} from './root-store' 4 + import {RootStoreModel} from '../root-store' 5 5 6 - export class UserAutocompleteViewModel { 6 + export class UserAutocompleteModel { 7 7 // state 8 8 isLoading = false 9 9 isActive = false
+2 -2
src/state/models/user-followers-view.ts src/state/models/lists/user-followers.ts
··· 3 3 AppBskyGraphGetFollowers as GetFollowers, 4 4 AppBskyActorDefs as ActorDefs, 5 5 } from '@atproto/api' 6 - import {RootStoreModel} from './root-store' 6 + import {RootStoreModel} from '../root-store' 7 7 import {cleanError} from 'lib/strings/errors' 8 8 import {bundleAsync} from 'lib/async/bundle' 9 9 ··· 11 11 12 12 export type FollowerItem = ActorDefs.ProfileViewBasic 13 13 14 - export class UserFollowersViewModel { 14 + export class UserFollowersModel { 15 15 // state 16 16 isLoading = false 17 17 isRefreshing = false
+2 -2
src/state/models/user-follows-view.ts src/state/models/lists/user-follows.ts
··· 3 3 AppBskyGraphGetFollows as GetFollows, 4 4 AppBskyActorDefs as ActorDefs, 5 5 } from '@atproto/api' 6 - import {RootStoreModel} from './root-store' 6 + import {RootStoreModel} from '../root-store' 7 7 import {cleanError} from 'lib/strings/errors' 8 8 import {bundleAsync} from 'lib/async/bundle' 9 9 ··· 11 11 12 12 export type FollowItem = ActorDefs.ProfileViewBasic 13 13 14 - export class UserFollowsViewModel { 14 + export class UserFollowsModel { 15 15 // state 16 16 isLoading = false 17 17 isRefreshing = false
+3 -3
src/view/com/composer/Composer.tsx
··· 15 15 import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' 16 16 import {RichText} from '@atproto/api' 17 17 import {useAnalytics} from 'lib/analytics' 18 - import {UserAutocompleteViewModel} from 'state/models/user-autocomplete-view' 18 + import {UserAutocompleteModel} from 'state/models/discovery/user-autocomplete' 19 19 import {ExternalEmbed} from './ExternalEmbed' 20 20 import {Text} from '../util/text/Text' 21 21 import * as Toast from '../util/Toast' ··· 69 69 ) 70 70 const [selectedPhotos, setSelectedPhotos] = React.useState<string[]>([]) 71 71 72 - const autocompleteView = React.useMemo<UserAutocompleteViewModel>( 73 - () => new UserAutocompleteViewModel(store), 72 + const autocompleteView = React.useMemo<UserAutocompleteModel>( 73 + () => new UserAutocompleteModel(store), 74 74 [store], 75 75 ) 76 76
+2 -2
src/view/com/composer/text-input/TextInput.tsx
··· 11 11 } from '@mattermost/react-native-paste-input' 12 12 import {AppBskyRichtextFacet, RichText} from '@atproto/api' 13 13 import isEqual from 'lodash.isequal' 14 - import {UserAutocompleteViewModel} from 'state/models/user-autocomplete-view' 14 + import {UserAutocompleteModel} from 'state/models/discovery/user-autocomplete' 15 15 import {Autocomplete} from './mobile/Autocomplete' 16 16 import {Text} from 'view/com/util/text/Text' 17 17 import {useStores} from 'state/index' ··· 36 36 richtext: RichText 37 37 placeholder: string 38 38 suggestedLinks: Set<string> 39 - autocompleteView: UserAutocompleteViewModel 39 + autocompleteView: UserAutocompleteModel 40 40 setRichText: (v: RichText) => void 41 41 onPhotoPasted: (uri: string) => void 42 42 onSuggestedLinksChanged: (uris: Set<string>) => void
+2 -2
src/view/com/composer/text-input/TextInput.web.tsx
··· 9 9 import {Placeholder} from '@tiptap/extension-placeholder' 10 10 import {Text} from '@tiptap/extension-text' 11 11 import isEqual from 'lodash.isequal' 12 - import {UserAutocompleteViewModel} from 'state/models/user-autocomplete-view' 12 + import {UserAutocompleteModel} from 'state/models/discovery/user-autocomplete' 13 13 import {createSuggestion} from './web/Autocomplete' 14 14 15 15 export interface TextInputRef { ··· 21 21 richtext: RichText 22 22 placeholder: string 23 23 suggestedLinks: Set<string> 24 - autocompleteView: UserAutocompleteViewModel 24 + autocompleteView: UserAutocompleteModel 25 25 setRichText: (v: RichText) => void 26 26 onPhotoPasted: (uri: string) => void 27 27 onSuggestedLinksChanged: (uris: Set<string>) => void
+2 -2
src/view/com/composer/text-input/mobile/Autocomplete.tsx
··· 1 1 import React, {useEffect} from 'react' 2 2 import {Animated, TouchableOpacity, StyleSheet, View} from 'react-native' 3 3 import {observer} from 'mobx-react-lite' 4 - import {UserAutocompleteViewModel} from 'state/models/user-autocomplete-view' 4 + import {UserAutocompleteModel} from 'state/models/discovery/user-autocomplete' 5 5 import {useAnimatedValue} from 'lib/hooks/useAnimatedValue' 6 6 import {usePalette} from 'lib/hooks/usePalette' 7 7 import {Text} from 'view/com/util/text/Text' ··· 11 11 view, 12 12 onSelect, 13 13 }: { 14 - view: UserAutocompleteViewModel 14 + view: UserAutocompleteModel 15 15 onSelect: (item: string) => void 16 16 }) => { 17 17 const pal = usePalette('default')
+2 -2
src/view/com/composer/text-input/web/Autocomplete.tsx
··· 11 11 SuggestionProps, 12 12 SuggestionKeyDownProps, 13 13 } from '@tiptap/suggestion' 14 - import {UserAutocompleteViewModel} from 'state/models/user-autocomplete-view' 14 + import {UserAutocompleteModel} from 'state/models/discovery/user-autocomplete' 15 15 16 16 interface MentionListRef { 17 17 onKeyDown: (props: SuggestionKeyDownProps) => boolean ··· 20 20 export function createSuggestion({ 21 21 autocompleteView, 22 22 }: { 23 - autocompleteView: UserAutocompleteViewModel 23 + autocompleteView: UserAutocompleteModel 24 24 }): Omit<SuggestionOptions, 'editor'> { 25 25 return { 26 26 async items({query}) {
+3 -3
src/view/com/discover/SuggestedPosts.tsx
··· 2 2 import {ActivityIndicator, StyleSheet, View} from 'react-native' 3 3 import {observer} from 'mobx-react-lite' 4 4 import {useStores} from 'state/index' 5 - import {SuggestedPostsView} from 'state/models/suggested-posts-view' 5 + import {SuggestedPostsModel} from 'state/models/discovery/suggested-posts' 6 6 import {s} from 'lib/styles' 7 7 import {FeedItem as Post} from '../posts/FeedItem' 8 8 import {Text} from '../util/text/Text' ··· 11 11 export const SuggestedPosts = observer(() => { 12 12 const pal = usePalette('default') 13 13 const store = useStores() 14 - const suggestedPostsView = React.useMemo<SuggestedPostsView>( 15 - () => new SuggestedPostsView(store), 14 + const suggestedPostsView = React.useMemo<SuggestedPostsModel>( 15 + () => new SuggestedPostsModel(store), 16 16 [store], 17 17 ) 18 18
+2 -2
src/view/com/modals/EditProfile.tsx
··· 12 12 import {Text} from '../util/text/Text' 13 13 import {ErrorMessage} from '../util/error/ErrorMessage' 14 14 import {useStores} from 'state/index' 15 - import {ProfileViewModel} from 'state/models/profile-view' 15 + import {ProfileModel} from 'state/models/content/profile' 16 16 import {s, colors, gradients} from 'lib/styles' 17 17 import {enforceLen} from 'lib/strings/helpers' 18 18 import {MAX_DISPLAY_NAME, MAX_DESCRIPTION} from 'lib/constants' ··· 30 30 profileView, 31 31 onUpdate, 32 32 }: { 33 - profileView: ProfileViewModel 33 + profileView: ProfileModel 34 34 onUpdate?: () => void 35 35 }) { 36 36 const store = useStores()
+2 -2
src/view/com/notifications/Feed.tsx
··· 2 2 import {observer} from 'mobx-react-lite' 3 3 import {CenteredView, FlatList} from '../util/Views' 4 4 import {ActivityIndicator, RefreshControl, StyleSheet, View} from 'react-native' 5 - import {NotificationsViewModel} from 'state/models/notifications-view' 5 + import {NotificationsFeedModel} from 'state/models/feeds/notifications' 6 6 import {FeedItem} from './FeedItem' 7 7 import {NotificationFeedLoadingPlaceholder} from '../util/LoadingPlaceholder' 8 8 import {ErrorMessage} from '../util/error/ErrorMessage' ··· 19 19 onPressTryAgain, 20 20 onScroll, 21 21 }: { 22 - view: NotificationsViewModel 22 + view: NotificationsFeedModel 23 23 scrollElRef?: MutableRefObject<FlatList<any> | null> 24 24 onPressTryAgain?: () => void 25 25 onScroll?: OnScrollCb
+4 -4
src/view/com/notifications/FeedItem.tsx
··· 14 14 FontAwesomeIconStyle, 15 15 Props, 16 16 } from '@fortawesome/react-native-fontawesome' 17 - import {NotificationsViewItemModel} from 'state/models/notifications-view' 18 - import {PostThreadViewModel} from 'state/models/post-thread-view' 17 + import {NotificationsFeedItemModel} from 'state/models/feeds/notifications' 18 + import {PostThreadModel} from 'state/models/content/post-thread' 19 19 import {s, colors} from 'lib/styles' 20 20 import {ago} from 'lib/strings/time' 21 21 import {pluralize} from 'lib/strings/helpers' ··· 42 42 export const FeedItem = observer(function FeedItem({ 43 43 item, 44 44 }: { 45 - item: NotificationsViewItemModel 45 + item: NotificationsFeedItemModel 46 46 }) { 47 47 const pal = usePalette('default') 48 48 const [isAuthorsExpanded, setAuthorsExpanded] = React.useState<boolean>(false) ··· 338 338 function AdditionalPostText({ 339 339 additionalPost, 340 340 }: { 341 - additionalPost?: PostThreadViewModel 341 + additionalPost?: PostThreadModel 342 342 }) { 343 343 const pal = usePalette('default') 344 344 if (
+2 -5
src/view/com/post-thread/PostLikedBy.tsx
··· 2 2 import {observer} from 'mobx-react-lite' 3 3 import {ActivityIndicator, RefreshControl, StyleSheet, View} from 'react-native' 4 4 import {CenteredView, FlatList} from '../util/Views' 5 - import {LikesViewModel, LikeItem} from 'state/models/likes-view' 5 + import {LikesModel, LikeItem} from 'state/models/lists/likes' 6 6 import {ErrorMessage} from '../util/error/ErrorMessage' 7 7 import {ProfileCardWithFollowBtn} from '../profile/ProfileCard' 8 8 import {useStores} from 'state/index' ··· 11 11 export const PostLikedBy = observer(function ({uri}: {uri: string}) { 12 12 const pal = usePalette('default') 13 13 const store = useStores() 14 - const view = React.useMemo( 15 - () => new LikesViewModel(store, {uri}), 16 - [store, uri], 17 - ) 14 + const view = React.useMemo(() => new LikesModel(store, {uri}), [store, uri]) 18 15 19 16 useEffect(() => { 20 17 view.loadMore().catch(err => store.log.error('Failed to fetch likes', err))
+2 -5
src/view/com/post-thread/PostRepostedBy.tsx
··· 2 2 import {observer} from 'mobx-react-lite' 3 3 import {ActivityIndicator, RefreshControl, StyleSheet, View} from 'react-native' 4 4 import {CenteredView, FlatList} from '../util/Views' 5 - import { 6 - RepostedByViewModel, 7 - RepostedByItem, 8 - } from 'state/models/reposted-by-view' 5 + import {RepostedByModel, RepostedByItem} from 'state/models/lists/reposted-by' 9 6 import {ProfileCardWithFollowBtn} from '../profile/ProfileCard' 10 7 import {ErrorMessage} from '../util/error/ErrorMessage' 11 8 import {useStores} from 'state/index' ··· 19 16 const pal = usePalette('default') 20 17 const store = useStores() 21 18 const view = React.useMemo( 22 - () => new RepostedByViewModel(store, {uri}), 19 + () => new RepostedByModel(store, {uri}), 23 20 [store, uri], 24 21 ) 25 22
+9 -9
src/view/com/post-thread/PostThread.tsx
··· 9 9 } from 'react-native' 10 10 import {CenteredView, FlatList} from '../util/Views' 11 11 import { 12 - PostThreadViewModel, 13 - PostThreadViewPostModel, 14 - } from 'state/models/post-thread-view' 12 + PostThreadModel, 13 + PostThreadItemModel, 14 + } from 'state/models/content/post-thread' 15 15 import { 16 16 FontAwesomeIcon, 17 17 FontAwesomeIconStyle, ··· 31 31 _reactKey: '__bottom_border__', 32 32 _isHighlightedPost: false, 33 33 } 34 - type YieldedItem = PostThreadViewPostModel | typeof REPLY_PROMPT 34 + type YieldedItem = PostThreadItemModel | typeof REPLY_PROMPT 35 35 36 36 export const PostThread = observer(function PostThread({ 37 37 uri, ··· 39 39 onPressReply, 40 40 }: { 41 41 uri: string 42 - view: PostThreadViewModel 42 + view: PostThreadModel 43 43 onPressReply: () => void 44 44 }) { 45 45 const pal = usePalette('default') ··· 109 109 // I could find to get a border positioned directly under the last item 110 110 // -prf 111 111 return <View style={[styles.bottomBorder, pal.border]} /> 112 - } else if (item instanceof PostThreadViewPostModel) { 112 + } else if (item instanceof PostThreadItemModel) { 113 113 return <PostThreadItem item={item} onPostReply={onRefresh} /> 114 114 } 115 115 return <></> ··· 187 187 }) 188 188 189 189 function* flattenThread( 190 - post: PostThreadViewPostModel, 190 + post: PostThreadItemModel, 191 191 isAscending = false, 192 192 ): Generator<YieldedItem, void> { 193 193 if (post.parent) { 194 194 if ('notFound' in post.parent && post.parent.notFound) { 195 195 // TODO render not found 196 196 } else { 197 - yield* flattenThread(post.parent as PostThreadViewPostModel, true) 197 + yield* flattenThread(post.parent as PostThreadItemModel, true) 198 198 } 199 199 } 200 200 yield post ··· 206 206 if ('notFound' in reply && reply.notFound) { 207 207 // TODO render not found 208 208 } else { 209 - yield* flattenThread(reply as PostThreadViewPostModel) 209 + yield* flattenThread(reply as PostThreadItemModel) 210 210 } 211 211 } 212 212 } else if (!isAscending && !post.parent && post.post.replyCount) {
+2 -2
src/view/com/post-thread/PostThreadItem.tsx
··· 7 7 FontAwesomeIcon, 8 8 FontAwesomeIconStyle, 9 9 } from '@fortawesome/react-native-fontawesome' 10 - import {PostThreadViewPostModel} from 'state/models/post-thread-view' 10 + import {PostThreadItemModel} from 'state/models/content/post-thread' 11 11 import {Link} from '../util/Link' 12 12 import {RichText} from '../util/text/RichText' 13 13 import {Text} from '../util/text/Text' ··· 31 31 item, 32 32 onPostReply, 33 33 }: { 34 - item: PostThreadViewPostModel 34 + item: PostThreadItemModel 35 35 onPostReply: () => void 36 36 }) { 37 37 const pal = usePalette('default')
+4 -4
src/view/com/post/Post.tsx
··· 11 11 import Clipboard from '@react-native-clipboard/clipboard' 12 12 import {AtUri} from '../../../third-party/uri' 13 13 import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' 14 - import {PostThreadViewModel} from 'state/models/post-thread-view' 14 + import {PostThreadModel} from 'state/models/content/post-thread' 15 15 import {Link} from '../util/Link' 16 16 import {UserInfoText} from '../util/UserInfoText' 17 17 import {PostMeta} from '../util/PostMeta' ··· 34 34 style, 35 35 }: { 36 36 uri: string 37 - initView?: PostThreadViewModel 37 + initView?: PostThreadModel 38 38 showReplyLine?: boolean 39 39 hideError?: boolean 40 40 style?: StyleProp<ViewStyle> 41 41 }) { 42 42 const pal = usePalette('default') 43 43 const store = useStores() 44 - const [view, setView] = useState<PostThreadViewModel | undefined>(initView) 44 + const [view, setView] = useState<PostThreadModel | undefined>(initView) 45 45 const [deleted, setDeleted] = useState(false) 46 46 47 47 useEffect(() => { 48 48 if (initView || view?.params.uri === uri) { 49 49 return // no change needed? or trigger refresh? 50 50 } 51 - const newView = new PostThreadViewModel(store, {uri, depth: 0}) 51 + const newView = new PostThreadModel(store, {uri, depth: 0}) 52 52 setView(newView) 53 53 newView.setup().catch(err => store.log.error('Failed to fetch post', err)) 54 54 }, [initView, uri, view?.params.uri, store])
+1 -1
src/view/com/post/PostText.tsx
··· 4 4 import {LoadingPlaceholder} from '../util/LoadingPlaceholder' 5 5 import {ErrorMessage} from '../util/error/ErrorMessage' 6 6 import {Text} from '../util/text/Text' 7 - import {PostModel} from 'state/models/post' 7 + import {PostModel} from 'state/models/content/post' 8 8 import {useStores} from 'state/index' 9 9 10 10 export const PostText = observer(function PostText({
+2 -2
src/view/com/posts/Feed.tsx
··· 11 11 import {FlatList} from '../util/Views' 12 12 import {PostFeedLoadingPlaceholder} from '../util/LoadingPlaceholder' 13 13 import {ErrorMessage} from '../util/error/ErrorMessage' 14 - import {FeedModel} from 'state/models/feed-view' 14 + import {PostsFeedModel} from 'state/models/feeds/posts' 15 15 import {FeedSlice} from './FeedSlice' 16 16 import {OnScrollCb} from 'lib/hooks/useOnMainScroll' 17 17 import {s} from 'lib/styles' ··· 33 33 testID, 34 34 headerOffset = 0, 35 35 }: { 36 - feed: FeedModel 36 + feed: PostsFeedModel 37 37 style?: StyleProp<ViewStyle> 38 38 showPostFollowBtn?: boolean 39 39 scrollElRef?: MutableRefObject<FlatList<any> | null>
+2 -2
src/view/com/posts/FeedItem.tsx
··· 7 7 FontAwesomeIcon, 8 8 FontAwesomeIconStyle, 9 9 } from '@fortawesome/react-native-fontawesome' 10 - import {FeedItemModel} from 'state/models/feed-view' 10 + import {PostsFeedItemModel} from 'state/models/feeds/posts' 11 11 import {Link, DesktopWebTextLink} from '../util/Link' 12 12 import {Text} from '../util/text/Text' 13 13 import {UserInfoText} from '../util/UserInfoText' ··· 30 30 showFollowBtn, 31 31 ignoreMuteFor, 32 32 }: { 33 - item: FeedItemModel 33 + item: PostsFeedItemModel 34 34 isThreadChild?: boolean 35 35 isThreadParent?: boolean 36 36 showReplyLine?: boolean
+3 -3
src/view/com/posts/FeedSlice.tsx
··· 1 1 import React from 'react' 2 2 import {StyleSheet, View} from 'react-native' 3 - import {FeedSliceModel} from 'state/models/feed-view' 3 + import {PostsFeedSliceModel} from 'state/models/feeds/posts' 4 4 import {AtUri} from '../../../third-party/uri' 5 5 import {Link} from '../util/Link' 6 6 import {Text} from '../util/text/Text' ··· 13 13 showFollowBtn, 14 14 ignoreMuteFor, 15 15 }: { 16 - slice: FeedSliceModel 16 + slice: PostsFeedSliceModel 17 17 showFollowBtn?: boolean 18 18 ignoreMuteFor?: string 19 19 }) { ··· 66 66 ) 67 67 } 68 68 69 - function ViewFullThread({slice}: {slice: FeedSliceModel}) { 69 + function ViewFullThread({slice}: {slice: PostsFeedSliceModel}) { 70 70 const pal = usePalette('default') 71 71 const itemHref = React.useMemo(() => { 72 72 const urip = new AtUri(slice.rootItem.post.uri)
+3 -3
src/view/com/profile/ProfileFollowers.tsx
··· 2 2 import {observer} from 'mobx-react-lite' 3 3 import {ActivityIndicator, RefreshControl, StyleSheet, View} from 'react-native' 4 4 import { 5 - UserFollowersViewModel, 5 + UserFollowersModel, 6 6 FollowerItem, 7 - } from 'state/models/user-followers-view' 7 + } from 'state/models/lists/user-followers' 8 8 import {CenteredView, FlatList} from '../util/Views' 9 9 import {ErrorMessage} from '../util/error/ErrorMessage' 10 10 import {ProfileCardWithFollowBtn} from './ProfileCard' ··· 19 19 const pal = usePalette('default') 20 20 const store = useStores() 21 21 const view = React.useMemo( 22 - () => new UserFollowersViewModel(store, {actor: name}), 22 + () => new UserFollowersModel(store, {actor: name}), 23 23 [store, name], 24 24 ) 25 25
+2 -2
src/view/com/profile/ProfileFollows.tsx
··· 2 2 import {observer} from 'mobx-react-lite' 3 3 import {ActivityIndicator, RefreshControl, StyleSheet, View} from 'react-native' 4 4 import {CenteredView, FlatList} from '../util/Views' 5 - import {UserFollowsViewModel, FollowItem} from 'state/models/user-follows-view' 5 + import {UserFollowsModel, FollowItem} from 'state/models/lists/user-follows' 6 6 import {ErrorMessage} from '../util/error/ErrorMessage' 7 7 import {ProfileCardWithFollowBtn} from './ProfileCard' 8 8 import {useStores} from 'state/index' ··· 16 16 const pal = usePalette('default') 17 17 const store = useStores() 18 18 const view = React.useMemo( 19 - () => new UserFollowsViewModel(store, {actor: name}), 19 + () => new UserFollowsModel(store, {actor: name}), 20 20 [store, name], 21 21 ) 22 22
+3 -9
src/view/com/profile/ProfileHeader.tsx
··· 13 13 } from '@fortawesome/react-native-fontawesome' 14 14 import {useNavigation} from '@react-navigation/native' 15 15 import {BlurView} from '../util/BlurView' 16 - import {ProfileViewModel} from 'state/models/profile-view' 16 + import {ProfileModel} from 'state/models/content/profile' 17 17 import {useStores} from 'state/index' 18 18 import {ProfileImageLightbox} from 'state/models/ui/shell' 19 19 import {pluralize} from 'lib/strings/helpers' ··· 34 34 const BACK_HITSLOP = {left: 30, top: 30, right: 30, bottom: 30} 35 35 36 36 export const ProfileHeader = observer( 37 - ({ 38 - view, 39 - onRefreshAll, 40 - }: { 41 - view: ProfileViewModel 42 - onRefreshAll: () => void 43 - }) => { 37 + ({view, onRefreshAll}: {view: ProfileModel; onRefreshAll: () => void}) => { 44 38 const pal = usePalette('default') 45 39 46 40 // loading ··· 91 85 view, 92 86 onRefreshAll, 93 87 }: { 94 - view: ProfileViewModel 88 + view: ProfileModel 95 89 onRefreshAll: () => void 96 90 }) { 97 91 const pal = usePalette('default')
+3 -3
src/view/screens/Home.tsx
··· 4 4 import {observer} from 'mobx-react-lite' 5 5 import useAppState from 'react-native-appstate-hook' 6 6 import {NativeStackScreenProps, HomeTabNavigatorParams} from 'lib/routes/types' 7 - import {FeedModel} from 'state/models/feed-view' 7 + import {PostsFeedModel} from 'state/models/feeds/posts' 8 8 import {withAuthRequired} from 'view/com/auth/withAuthRequired' 9 9 import {Feed} from '../com/posts/Feed' 10 10 import {FollowingEmptyState} from 'view/com/posts/FollowingEmptyState' ··· 26 26 const [selectedPage, setSelectedPage] = React.useState(0) 27 27 28 28 const algoFeed = React.useMemo(() => { 29 - const feed = new FeedModel(store, 'goodstuff', {}) 29 + const feed = new PostsFeedModel(store, 'goodstuff', {}) 30 30 feed.setup() 31 31 return feed 32 32 }, [store]) ··· 104 104 renderEmptyState, 105 105 }: { 106 106 testID?: string 107 - feed: FeedModel 107 + feed: PostsFeedModel 108 108 isPageFocused: boolean 109 109 renderEmptyState?: () => JSX.Element 110 110 }) => {
+3 -3
src/view/screens/PostThread.tsx
··· 7 7 import {ViewHeader} from '../com/util/ViewHeader' 8 8 import {PostThread as PostThreadComponent} from '../com/post-thread/PostThread' 9 9 import {ComposePrompt} from 'view/com/composer/Prompt' 10 - import {PostThreadViewModel} from 'state/models/post-thread-view' 10 + import {PostThreadModel} from 'state/models/content/post-thread' 11 11 import {useStores} from 'state/index' 12 12 import {s} from 'lib/styles' 13 13 import {useSafeAreaInsets} from 'react-native-safe-area-context' ··· 22 22 const safeAreaInsets = useSafeAreaInsets() 23 23 const {name, rkey} = route.params 24 24 const uri = makeRecordUri(name, 'app.bsky.feed.post', rkey) 25 - const view = useMemo<PostThreadViewModel>( 26 - () => new PostThreadViewModel(store, {uri}), 25 + const view = useMemo<PostThreadModel>( 26 + () => new PostThreadModel(store, {uri}), 27 27 [store, uri], 28 28 ) 29 29
+2 -2
src/view/screens/Profile.tsx
··· 8 8 import {CenteredView} from '../com/util/Views' 9 9 import {ProfileUiModel} from 'state/models/ui/profile' 10 10 import {useStores} from 'state/index' 11 - import {FeedSliceModel} from 'state/models/feed-view' 11 + import {PostsFeedSliceModel} from 'state/models/feeds/posts' 12 12 import {ProfileHeader} from '../com/profile/ProfileHeader' 13 13 import {FeedSlice} from '../com/posts/FeedSlice' 14 14 import {PostFeedLoadingPlaceholder} from '../com/util/LoadingPlaceholder' ··· 124 124 style={styles.emptyState} 125 125 /> 126 126 ) 127 - } else if (item instanceof FeedSliceModel) { 127 + } else if (item instanceof PostsFeedSliceModel) { 128 128 return <FeedSlice slice={item} ignoreMuteFor={uiState.profile.did} /> 129 129 } 130 130 return <View />
+3 -3
src/view/screens/Search.tsx
··· 16 16 import {observer} from 'mobx-react-lite' 17 17 import {Text} from 'view/com/util/text/Text' 18 18 import {useStores} from 'state/index' 19 - import {UserAutocompleteViewModel} from 'state/models/user-autocomplete-view' 19 + import {UserAutocompleteModel} from 'state/models/discovery/user-autocomplete' 20 20 import {SearchUIModel} from 'state/models/ui/search' 21 21 import {FoafsModel} from 'state/models/discovery/foafs' 22 22 import {SuggestedActorsModel} from 'state/models/discovery/suggested-actors' ··· 37 37 const onMainScroll = useOnMainScroll(store) 38 38 const [isInputFocused, setIsInputFocused] = React.useState<boolean>(false) 39 39 const [query, setQuery] = React.useState<string>('') 40 - const autocompleteView = React.useMemo<UserAutocompleteViewModel>( 41 - () => new UserAutocompleteViewModel(store), 40 + const autocompleteView = React.useMemo<UserAutocompleteModel>( 41 + () => new UserAutocompleteModel(store), 42 42 [store], 43 43 ) 44 44 const foafs = React.useMemo<FoafsModel>(
+3 -3
src/view/shell/desktop/Search.tsx
··· 1 1 import React from 'react' 2 2 import {TextInput, View, StyleSheet, TouchableOpacity} from 'react-native' 3 3 import {useNavigation, StackActions} from '@react-navigation/native' 4 - import {UserAutocompleteViewModel} from 'state/models/user-autocomplete-view' 4 + import {UserAutocompleteModel} from 'state/models/discovery/user-autocomplete' 5 5 import {observer} from 'mobx-react-lite' 6 6 import {useStores} from 'state/index' 7 7 import {usePalette} from 'lib/hooks/usePalette' ··· 16 16 const textInput = React.useRef<TextInput>(null) 17 17 const [isInputFocused, setIsInputFocused] = React.useState<boolean>(false) 18 18 const [query, setQuery] = React.useState<string>('') 19 - const autocompleteView = React.useMemo<UserAutocompleteViewModel>( 20 - () => new UserAutocompleteViewModel(store), 19 + const autocompleteView = React.useMemo<UserAutocompleteModel>( 20 + () => new UserAutocompleteModel(store), 21 21 [store], 22 22 ) 23 23 const navigation = useNavigation<NavigationProp>()