Rework profile page to include working view selector
This commit is contained in:
parent
2ec09ba545
commit
bb06ef4f6e
19 changed files with 569 additions and 94 deletions
49
src/state/models/badges-view.ts
Normal file
49
src/state/models/badges-view.ts
Normal file
|
@ -0,0 +1,49 @@
|
|||
import {makeAutoObservable} from 'mobx'
|
||||
import {RootStoreModel} from './root-store'
|
||||
|
||||
// TODO / DEBUG
|
||||
// this is a temporary fake for the model until the view actually gets implemented in the bsky api
|
||||
// -prf
|
||||
|
||||
export class BadgesViewModel {
|
||||
// state
|
||||
isLoading = false
|
||||
isRefreshing = false
|
||||
hasLoaded = false
|
||||
error = ''
|
||||
|
||||
constructor(public rootStore: RootStoreModel) {
|
||||
makeAutoObservable(
|
||||
this,
|
||||
{
|
||||
rootStore: false,
|
||||
},
|
||||
{autoBind: true},
|
||||
)
|
||||
}
|
||||
|
||||
get hasContent() {
|
||||
return false
|
||||
}
|
||||
|
||||
get hasError() {
|
||||
return this.error !== ''
|
||||
}
|
||||
|
||||
get isEmpty() {
|
||||
return this.hasLoaded && !this.hasContent
|
||||
}
|
||||
|
||||
// public api
|
||||
// =
|
||||
|
||||
async setup() {
|
||||
this.hasLoaded = true
|
||||
}
|
||||
|
||||
async refresh() {}
|
||||
|
||||
async loadMore() {}
|
||||
|
||||
async update() {}
|
||||
}
|
|
@ -95,6 +95,7 @@ export class FeedViewModel implements bsky.FeedView.Response {
|
|||
isLoading = false
|
||||
isRefreshing = false
|
||||
hasLoaded = false
|
||||
hasReachedEnd = false
|
||||
error = ''
|
||||
params: bsky.FeedView.Params
|
||||
_loadPromise: Promise<void> | undefined
|
||||
|
@ -244,7 +245,13 @@ export class FeedViewModel implements bsky.FeedView.Response {
|
|||
'blueskyweb.xyz:FeedView',
|
||||
params,
|
||||
)) as bsky.FeedView.Response
|
||||
this._appendAll(res)
|
||||
if (res.feed.length === 0) {
|
||||
runInAction(() => {
|
||||
this.hasReachedEnd = true
|
||||
})
|
||||
} else {
|
||||
this._appendAll(res)
|
||||
}
|
||||
this._xIdle()
|
||||
} catch (e: any) {
|
||||
this._xIdle(`Failed to load feed: ${e.toString()}`)
|
||||
|
@ -281,6 +288,7 @@ export class FeedViewModel implements bsky.FeedView.Response {
|
|||
|
||||
private _replaceAll(res: bsky.FeedView.Response) {
|
||||
this.feed.length = 0
|
||||
this.hasReachedEnd = false
|
||||
this._appendAll(res)
|
||||
}
|
||||
|
||||
|
|
98
src/state/models/profile-ui.ts
Normal file
98
src/state/models/profile-ui.ts
Normal file
|
@ -0,0 +1,98 @@
|
|||
import {makeAutoObservable} from 'mobx'
|
||||
import {RootStoreModel} from './root-store'
|
||||
import {ProfileViewModel} from './profile-view'
|
||||
import {FeedViewModel} from './feed-view'
|
||||
import {BadgesViewModel} from './badges-view'
|
||||
|
||||
export const SECTION_IDS = {
|
||||
POSTS: 0,
|
||||
BADGES: 1,
|
||||
}
|
||||
|
||||
export interface ProfileUiParams {
|
||||
user: string
|
||||
}
|
||||
|
||||
export class ProfileUiModel {
|
||||
// constants
|
||||
static SELECTOR_ITEMS = ['Posts', 'Badges']
|
||||
|
||||
// data
|
||||
profile: ProfileViewModel
|
||||
feed: FeedViewModel
|
||||
badges: BadgesViewModel
|
||||
|
||||
// ui state
|
||||
selectedViewIndex = 0
|
||||
|
||||
constructor(
|
||||
public rootStore: RootStoreModel,
|
||||
public params: ProfileUiParams,
|
||||
) {
|
||||
makeAutoObservable(
|
||||
this,
|
||||
{
|
||||
rootStore: false,
|
||||
params: false,
|
||||
},
|
||||
{autoBind: true},
|
||||
)
|
||||
this.profile = new ProfileViewModel(rootStore, {user: params.user})
|
||||
this.feed = new FeedViewModel(rootStore, {author: params.user, limit: 10})
|
||||
this.badges = new BadgesViewModel(rootStore)
|
||||
}
|
||||
|
||||
get currentView(): FeedViewModel | BadgesViewModel {
|
||||
if (this.selectedViewIndex === SECTION_IDS.POSTS) {
|
||||
return this.feed
|
||||
}
|
||||
if (this.selectedViewIndex === SECTION_IDS.BADGES) {
|
||||
return this.badges
|
||||
}
|
||||
throw new Error(`Invalid selector value: ${this.selectedViewIndex}`)
|
||||
}
|
||||
|
||||
get isInitialLoading() {
|
||||
const view = this.currentView
|
||||
return view.isLoading && !view.isRefreshing && !view.hasContent
|
||||
}
|
||||
|
||||
get isRefreshing() {
|
||||
return this.profile.isRefreshing || this.currentView.isRefreshing
|
||||
}
|
||||
|
||||
// public api
|
||||
// =
|
||||
|
||||
setSelectedViewIndex(index: number) {
|
||||
this.selectedViewIndex = index
|
||||
}
|
||||
|
||||
async setup() {
|
||||
await Promise.all([
|
||||
this.profile
|
||||
.setup()
|
||||
.catch(err => console.error('Failed to fetch profile', err)),
|
||||
this.feed
|
||||
.setup()
|
||||
.catch(err => console.error('Failed to fetch feed', err)),
|
||||
this.badges
|
||||
.setup()
|
||||
.catch(err => console.error('Failed to fetch badges', err)),
|
||||
])
|
||||
}
|
||||
|
||||
async update() {
|
||||
await this.currentView.update()
|
||||
}
|
||||
|
||||
async refresh() {
|
||||
await Promise.all([this.profile.refresh(), this.currentView.refresh()])
|
||||
}
|
||||
|
||||
async loadMore() {
|
||||
if (!this.currentView.isLoading && !this.currentView.hasError) {
|
||||
await this.currentView.loadMore()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -65,7 +65,7 @@ export class ProfileViewModel implements bsky.ProfileView.Response {
|
|||
}
|
||||
|
||||
async refresh() {
|
||||
await this._load()
|
||||
await this._load(true)
|
||||
}
|
||||
|
||||
async toggleFollowing() {
|
||||
|
@ -108,8 +108,8 @@ export class ProfileViewModel implements bsky.ProfileView.Response {
|
|||
// loader functions
|
||||
// =
|
||||
|
||||
private async _load() {
|
||||
this._xLoading()
|
||||
private async _load(isRefreshing = false) {
|
||||
this._xLoading(isRefreshing)
|
||||
await new Promise(r => setTimeout(r, 250)) // DEBUG
|
||||
try {
|
||||
const res = (await this.rootStore.api.mainPds.view(
|
||||
|
@ -119,7 +119,7 @@ export class ProfileViewModel implements bsky.ProfileView.Response {
|
|||
this._replaceAll(res)
|
||||
this._xIdle()
|
||||
} catch (e: any) {
|
||||
this._xIdle(`Failed to load feed: ${e.toString()}`)
|
||||
this._xIdle(e.toString())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue