Replace mock-api with real api
This commit is contained in:
parent
5193a5b48e
commit
aabde2b401
110 changed files with 16045 additions and 3742 deletions
|
@ -1,30 +1,30 @@
|
|||
import {makeAutoObservable, runInAction} from 'mobx'
|
||||
import {bsky} from '@adxp/mock-api'
|
||||
import * as GetFeedView from '../../third-party/api/src/types/todo/social/getFeed'
|
||||
import {RootStoreModel} from './root-store'
|
||||
import * as apilib from '../lib/api'
|
||||
|
||||
export class FeedViewItemMyStateModel {
|
||||
hasLiked: boolean = false
|
||||
hasReposted: boolean = false
|
||||
repost?: string
|
||||
like?: string
|
||||
|
||||
constructor() {
|
||||
makeAutoObservable(this)
|
||||
}
|
||||
}
|
||||
|
||||
export class FeedViewItemModel implements bsky.FeedView.FeedItem {
|
||||
export class FeedViewItemModel implements GetFeedView.FeedItem {
|
||||
// ui state
|
||||
_reactKey: string = ''
|
||||
|
||||
// data
|
||||
uri: string = ''
|
||||
author: bsky.FeedView.User = {did: '', name: '', displayName: ''}
|
||||
repostedBy?: bsky.FeedView.User
|
||||
author: GetFeedView.User = {did: '', name: '', displayName: ''}
|
||||
repostedBy?: GetFeedView.User
|
||||
record: Record<string, unknown> = {}
|
||||
embed?:
|
||||
| bsky.FeedView.RecordEmbed
|
||||
| bsky.FeedView.ExternalEmbed
|
||||
| bsky.FeedView.UnknownEmbed
|
||||
| GetFeedView.RecordEmbed
|
||||
| GetFeedView.ExternalEmbed
|
||||
| GetFeedView.UnknownEmbed
|
||||
replyCount: number = 0
|
||||
repostCount: number = 0
|
||||
likeCount: number = 0
|
||||
|
@ -34,14 +34,14 @@ export class FeedViewItemModel implements bsky.FeedView.FeedItem {
|
|||
constructor(
|
||||
public rootStore: RootStoreModel,
|
||||
reactKey: string,
|
||||
v: bsky.FeedView.FeedItem,
|
||||
v: GetFeedView.FeedItem,
|
||||
) {
|
||||
makeAutoObservable(this, {rootStore: false})
|
||||
this._reactKey = reactKey
|
||||
this.copy(v)
|
||||
}
|
||||
|
||||
copy(v: bsky.FeedView.FeedItem) {
|
||||
copy(v: GetFeedView.FeedItem) {
|
||||
this.uri = v.uri
|
||||
this.author = v.author
|
||||
this.repostedBy = v.repostedBy
|
||||
|
@ -52,52 +52,56 @@ export class FeedViewItemModel implements bsky.FeedView.FeedItem {
|
|||
this.likeCount = v.likeCount
|
||||
this.indexedAt = v.indexedAt
|
||||
if (v.myState) {
|
||||
this.myState.hasLiked = v.myState.hasLiked
|
||||
this.myState.hasReposted = v.myState.hasReposted
|
||||
this.myState.like = v.myState.like
|
||||
this.myState.repost = v.myState.repost
|
||||
}
|
||||
}
|
||||
|
||||
async toggleLike() {
|
||||
if (this.myState.hasLiked) {
|
||||
await apilib.unlike(this.rootStore.api, 'alice.com', this.uri)
|
||||
if (this.myState.like) {
|
||||
await apilib.unlike(this.rootStore.api, 'alice.test', this.uri)
|
||||
runInAction(() => {
|
||||
this.likeCount--
|
||||
this.myState.hasLiked = false
|
||||
this.myState.like = undefined
|
||||
})
|
||||
} else {
|
||||
await apilib.like(this.rootStore.api, 'alice.com', this.uri)
|
||||
const res = await apilib.like(this.rootStore.api, 'alice.test', this.uri)
|
||||
runInAction(() => {
|
||||
this.likeCount++
|
||||
this.myState.hasLiked = true
|
||||
this.myState.like = res.uri
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async toggleRepost() {
|
||||
if (this.myState.hasReposted) {
|
||||
await apilib.unrepost(this.rootStore.api, 'alice.com', this.uri)
|
||||
if (this.myState.repost) {
|
||||
await apilib.unrepost(this.rootStore.api, 'alice.test', this.uri)
|
||||
runInAction(() => {
|
||||
this.repostCount--
|
||||
this.myState.hasReposted = false
|
||||
this.myState.repost = undefined
|
||||
})
|
||||
} else {
|
||||
await apilib.repost(this.rootStore.api, 'alice.com', this.uri)
|
||||
const res = await apilib.repost(
|
||||
this.rootStore.api,
|
||||
'alice.test',
|
||||
this.uri,
|
||||
)
|
||||
runInAction(() => {
|
||||
this.repostCount++
|
||||
this.myState.hasReposted = true
|
||||
this.myState.repost = res.uri
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class FeedViewModel implements bsky.FeedView.Response {
|
||||
export class FeedViewModel {
|
||||
// state
|
||||
isLoading = false
|
||||
isRefreshing = false
|
||||
hasLoaded = false
|
||||
hasReachedEnd = false
|
||||
error = ''
|
||||
params: bsky.FeedView.Params
|
||||
params: GetFeedView.QueryParams
|
||||
_loadPromise: Promise<void> | undefined
|
||||
_loadMorePromise: Promise<void> | undefined
|
||||
_updatePromise: Promise<void> | undefined
|
||||
|
@ -105,7 +109,10 @@ export class FeedViewModel implements bsky.FeedView.Response {
|
|||
// data
|
||||
feed: FeedViewItemModel[] = []
|
||||
|
||||
constructor(public rootStore: RootStoreModel, params: bsky.FeedView.Params) {
|
||||
constructor(
|
||||
public rootStore: RootStoreModel,
|
||||
params: GetFeedView.QueryParams,
|
||||
) {
|
||||
makeAutoObservable(
|
||||
this,
|
||||
{
|
||||
|
@ -223,10 +230,7 @@ export class FeedViewModel implements bsky.FeedView.Response {
|
|||
this._xLoading(isRefreshing)
|
||||
await new Promise(r => setTimeout(r, 250)) // DEBUG
|
||||
try {
|
||||
const res = (await this.rootStore.api.mainPds.view(
|
||||
'blueskyweb.xyz:FeedView',
|
||||
this.params,
|
||||
)) as bsky.FeedView.Response
|
||||
const res = await this.rootStore.api.todo.social.getFeed(this.params)
|
||||
this._replaceAll(res)
|
||||
this._xIdle()
|
||||
} catch (e: any) {
|
||||
|
@ -241,11 +245,8 @@ export class FeedViewModel implements bsky.FeedView.Response {
|
|||
const params = Object.assign({}, this.params, {
|
||||
before: this.loadMoreCursor,
|
||||
})
|
||||
const res = (await this.rootStore.api.mainPds.view(
|
||||
'blueskyweb.xyz:FeedView',
|
||||
params,
|
||||
)) as bsky.FeedView.Response
|
||||
if (res.feed.length === 0) {
|
||||
const res = await this.rootStore.api.todo.social.getFeed(params)
|
||||
if (res.data.feed.length === 0) {
|
||||
runInAction(() => {
|
||||
this.hasReachedEnd = true
|
||||
})
|
||||
|
@ -265,20 +266,18 @@ export class FeedViewModel implements bsky.FeedView.Response {
|
|||
let cursor = undefined
|
||||
try {
|
||||
do {
|
||||
const res = (await this.rootStore.api.mainPds.view(
|
||||
'blueskyweb.xyz:FeedView',
|
||||
{
|
||||
const res: GetFeedView.Response =
|
||||
await this.rootStore.api.todo.social.getFeed({
|
||||
before: cursor,
|
||||
limit: Math.min(numToFetch, 100),
|
||||
},
|
||||
)) as bsky.FeedView.Response
|
||||
if (res.feed.length === 0) {
|
||||
})
|
||||
if (res.data.feed.length === 0) {
|
||||
break // sanity check
|
||||
}
|
||||
this._updateAll(res)
|
||||
numToFetch -= res.feed.length
|
||||
cursor = this.feed[res.feed.length - 1].indexedAt
|
||||
console.log(numToFetch, cursor, res.feed.length)
|
||||
numToFetch -= res.data.feed.length
|
||||
cursor = this.feed[res.data.feed.length - 1].indexedAt
|
||||
console.log(numToFetch, cursor, res.data.feed.length)
|
||||
} while (numToFetch > 0)
|
||||
this._xIdle()
|
||||
} catch (e: any) {
|
||||
|
@ -286,26 +285,26 @@ export class FeedViewModel implements bsky.FeedView.Response {
|
|||
}
|
||||
}
|
||||
|
||||
private _replaceAll(res: bsky.FeedView.Response) {
|
||||
private _replaceAll(res: GetFeedView.Response) {
|
||||
this.feed.length = 0
|
||||
this.hasReachedEnd = false
|
||||
this._appendAll(res)
|
||||
}
|
||||
|
||||
private _appendAll(res: bsky.FeedView.Response) {
|
||||
private _appendAll(res: GetFeedView.Response) {
|
||||
let counter = this.feed.length
|
||||
for (const item of res.feed) {
|
||||
for (const item of res.data.feed) {
|
||||
this._append(counter++, item)
|
||||
}
|
||||
}
|
||||
|
||||
private _append(keyId: number, item: bsky.FeedView.FeedItem) {
|
||||
private _append(keyId: number, item: GetFeedView.FeedItem) {
|
||||
// TODO: validate .record
|
||||
this.feed.push(new FeedViewItemModel(this.rootStore, `item-${keyId}`, item))
|
||||
}
|
||||
|
||||
private _updateAll(res: bsky.FeedView.Response) {
|
||||
for (const item of res.feed) {
|
||||
private _updateAll(res: GetFeedView.Response) {
|
||||
for (const item of res.data.feed) {
|
||||
const existingItem = this.feed.find(
|
||||
// this find function has a key subtley- the indexedAt comparison
|
||||
// the reason for this is reposts: they set the URI of the original post, not of the repost record
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import {makeAutoObservable, runInAction} from 'mobx'
|
||||
import {bsky, AdxUri} from '@adxp/mock-api'
|
||||
import {AdxUri} from '../../third-party/uri'
|
||||
import * as GetLikedBy from '../../third-party/api/src/types/todo/social/getLikedBy'
|
||||
import {RootStoreModel} from './root-store'
|
||||
|
||||
type LikedByItem = bsky.LikedByView.Response['likedBy'][number]
|
||||
type LikedByItem = GetLikedBy.OutputSchema['likedBy'][number]
|
||||
|
||||
export class LikedByViewItemModel implements LikedByItem {
|
||||
// ui state
|
||||
|
@ -22,14 +23,14 @@ export class LikedByViewItemModel implements LikedByItem {
|
|||
}
|
||||
}
|
||||
|
||||
export class LikedByViewModel implements bsky.LikedByView.Response {
|
||||
export class LikedByViewModel {
|
||||
// state
|
||||
isLoading = false
|
||||
isRefreshing = false
|
||||
hasLoaded = false
|
||||
error = ''
|
||||
resolvedUri = ''
|
||||
params: bsky.LikedByView.Params
|
||||
params: GetLikedBy.QueryParams
|
||||
|
||||
// data
|
||||
uri: string = ''
|
||||
|
@ -37,7 +38,7 @@ export class LikedByViewModel implements bsky.LikedByView.Response {
|
|||
|
||||
constructor(
|
||||
public rootStore: RootStoreModel,
|
||||
params: bsky.LikedByView.Params,
|
||||
params: GetLikedBy.QueryParams,
|
||||
) {
|
||||
makeAutoObservable(
|
||||
this,
|
||||
|
@ -113,10 +114,9 @@ export class LikedByViewModel implements bsky.LikedByView.Response {
|
|||
this._xLoading(isRefreshing)
|
||||
await new Promise(r => setTimeout(r, 250)) // DEBUG
|
||||
try {
|
||||
const res = (await this.rootStore.api.mainPds.view(
|
||||
'blueskyweb.xyz:LikedByView',
|
||||
const res = await this.rootStore.api.todo.social.getLikedBy(
|
||||
Object.assign({}, this.params, {uri: this.resolvedUri}),
|
||||
)) as bsky.LikedByView.Response
|
||||
)
|
||||
this._replaceAll(res)
|
||||
this._xIdle()
|
||||
} catch (e: any) {
|
||||
|
@ -124,10 +124,10 @@ export class LikedByViewModel implements bsky.LikedByView.Response {
|
|||
}
|
||||
}
|
||||
|
||||
private _replaceAll(res: bsky.LikedByView.Response) {
|
||||
private _replaceAll(res: GetLikedBy.Response) {
|
||||
this.likedBy.length = 0
|
||||
let counter = 0
|
||||
for (const item of res.likedBy) {
|
||||
for (const item of res.data.likedBy) {
|
||||
this._append(counter++, item)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,18 +14,16 @@ export class MeModel {
|
|||
async load() {
|
||||
const sess = this.rootStore.session
|
||||
if (sess.isAuthed) {
|
||||
const userDb = this.rootStore.api.mockDb.mainUser
|
||||
this.did = userDb.did
|
||||
this.name = userDb.name
|
||||
const profile = await this.rootStore.api
|
||||
.repo(this.did, true)
|
||||
.collection('blueskyweb.xyz:Profiles')
|
||||
.get('Profile', 'profile')
|
||||
.catch(_ => undefined)
|
||||
// TODO
|
||||
this.did = 'did:test:alice'
|
||||
this.name = 'alice.todo'
|
||||
const profile = await this.rootStore.api.todo.social.getProfile({
|
||||
user: this.did,
|
||||
})
|
||||
runInAction(() => {
|
||||
if (profile?.valid) {
|
||||
this.displayName = profile.value.displayName
|
||||
this.description = profile.value.description
|
||||
if (profile?.data) {
|
||||
this.displayName = profile.data.displayName
|
||||
this.description = profile.data.description
|
||||
} else {
|
||||
this.displayName = ''
|
||||
this.description = ''
|
||||
|
|
|
@ -231,8 +231,9 @@ export class NavigationModel {
|
|||
}
|
||||
|
||||
hydrate(v: unknown) {
|
||||
this.tabs.length = 0
|
||||
this.tabIndex = 0
|
||||
// this.tabs.length = 0
|
||||
// this.tabIndex = 0
|
||||
return // DEBUG
|
||||
if (isObj(v)) {
|
||||
if (hasProp(v, 'tabs') && Array.isArray(v.tabs)) {
|
||||
for (const tab of v.tabs) {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import {makeAutoObservable, runInAction} from 'mobx'
|
||||
import {bsky} from '@adxp/mock-api'
|
||||
import {makeAutoObservable} from 'mobx'
|
||||
import * as GetNotifications from '../../third-party/api/src/types/todo/social/getNotifications'
|
||||
import {RootStoreModel} from './root-store'
|
||||
import {hasProp} from '../lib/type-guards'
|
||||
|
||||
export class NotificationsViewItemModel
|
||||
implements bsky.NotificationsView.Notification
|
||||
implements GetNotifications.Notification
|
||||
{
|
||||
// ui state
|
||||
_reactKey: string = ''
|
||||
|
@ -23,14 +23,14 @@ export class NotificationsViewItemModel
|
|||
constructor(
|
||||
public rootStore: RootStoreModel,
|
||||
reactKey: string,
|
||||
v: bsky.NotificationsView.Notification,
|
||||
v: GetNotifications.Notification,
|
||||
) {
|
||||
makeAutoObservable(this, {rootStore: false})
|
||||
this._reactKey = reactKey
|
||||
this.copy(v)
|
||||
}
|
||||
|
||||
copy(v: bsky.NotificationsView.Notification) {
|
||||
copy(v: GetNotifications.Notification) {
|
||||
this.uri = v.uri
|
||||
this.author = v.author
|
||||
this.record = v.record
|
||||
|
@ -77,13 +77,13 @@ export class NotificationsViewItemModel
|
|||
}
|
||||
}
|
||||
|
||||
export class NotificationsViewModel implements bsky.NotificationsView.Response {
|
||||
export class NotificationsViewModel {
|
||||
// state
|
||||
isLoading = false
|
||||
isRefreshing = false
|
||||
hasLoaded = false
|
||||
error = ''
|
||||
params: bsky.NotificationsView.Params
|
||||
params: GetNotifications.QueryParams
|
||||
_loadPromise: Promise<void> | undefined
|
||||
_loadMorePromise: Promise<void> | undefined
|
||||
_updatePromise: Promise<void> | undefined
|
||||
|
@ -93,7 +93,7 @@ export class NotificationsViewModel implements bsky.NotificationsView.Response {
|
|||
|
||||
constructor(
|
||||
public rootStore: RootStoreModel,
|
||||
params: bsky.NotificationsView.Params,
|
||||
params: GetNotifications.QueryParams,
|
||||
) {
|
||||
makeAutoObservable(
|
||||
this,
|
||||
|
@ -212,10 +212,9 @@ export class NotificationsViewModel implements bsky.NotificationsView.Response {
|
|||
this._xLoading(isRefreshing)
|
||||
await new Promise(r => setTimeout(r, 250)) // DEBUG
|
||||
try {
|
||||
const res = (await this.rootStore.api.mainPds.view(
|
||||
'blueskyweb.xyz:NotificationsView',
|
||||
const res = await this.rootStore.api.todo.social.getNotifications(
|
||||
this.params,
|
||||
)) as bsky.NotificationsView.Response
|
||||
)
|
||||
this._replaceAll(res)
|
||||
this._xIdle()
|
||||
} catch (e: any) {
|
||||
|
@ -230,10 +229,7 @@ export class NotificationsViewModel implements bsky.NotificationsView.Response {
|
|||
const params = Object.assign({}, this.params, {
|
||||
before: this.loadMoreCursor,
|
||||
})
|
||||
const res = (await this.rootStore.api.mainPds.view(
|
||||
'blueskyweb.xyz:NotificationsView',
|
||||
params,
|
||||
)) as bsky.NotificationsView.Response
|
||||
const res = await this.rootStore.api.todo.social.getNotifications(params)
|
||||
this._appendAll(res)
|
||||
this._xIdle()
|
||||
} catch (e: any) {
|
||||
|
@ -248,20 +244,18 @@ export class NotificationsViewModel implements bsky.NotificationsView.Response {
|
|||
let cursor = undefined
|
||||
try {
|
||||
do {
|
||||
const res = (await this.rootStore.api.mainPds.view(
|
||||
'blueskyweb.xyz:NotificationsView',
|
||||
{
|
||||
const res: GetNotifications.Response =
|
||||
await this.rootStore.api.todo.social.getNotifications({
|
||||
before: cursor,
|
||||
limit: Math.min(numToFetch, 100),
|
||||
},
|
||||
)) as bsky.NotificationsView.Response
|
||||
if (res.notifications.length === 0) {
|
||||
})
|
||||
if (res.data.notifications.length === 0) {
|
||||
break // sanity check
|
||||
}
|
||||
this._updateAll(res)
|
||||
numToFetch -= res.notifications.length
|
||||
cursor = this.notifications[res.notifications.length - 1].indexedAt
|
||||
console.log(numToFetch, cursor, res.notifications.length)
|
||||
numToFetch -= res.data.notifications.length
|
||||
cursor = this.notifications[res.data.notifications.length - 1].indexedAt
|
||||
console.log(numToFetch, cursor, res.data.notifications.length)
|
||||
} while (numToFetch > 0)
|
||||
this._xIdle()
|
||||
} catch (e: any) {
|
||||
|
@ -269,27 +263,27 @@ export class NotificationsViewModel implements bsky.NotificationsView.Response {
|
|||
}
|
||||
}
|
||||
|
||||
private _replaceAll(res: bsky.NotificationsView.Response) {
|
||||
private _replaceAll(res: GetNotifications.Response) {
|
||||
this.notifications.length = 0
|
||||
this._appendAll(res)
|
||||
}
|
||||
|
||||
private _appendAll(res: bsky.NotificationsView.Response) {
|
||||
private _appendAll(res: GetNotifications.Response) {
|
||||
let counter = this.notifications.length
|
||||
for (const item of res.notifications) {
|
||||
for (const item of res.data.notifications) {
|
||||
this._append(counter++, item)
|
||||
}
|
||||
}
|
||||
|
||||
private _append(keyId: number, item: bsky.NotificationsView.Notification) {
|
||||
private _append(keyId: number, item: GetNotifications.Notification) {
|
||||
// TODO: validate .record
|
||||
this.notifications.push(
|
||||
new NotificationsViewItemModel(this.rootStore, `item-${keyId}`, item),
|
||||
)
|
||||
}
|
||||
|
||||
private _updateAll(res: bsky.NotificationsView.Response) {
|
||||
for (const item of res.notifications) {
|
||||
private _updateAll(res: GetNotifications.Response) {
|
||||
for (const item of res.data.notifications) {
|
||||
const existingItem = this.notifications.find(
|
||||
// this find function has a key subtley- the indexedAt comparison
|
||||
// the reason for this is reposts: they set the URI of the original post, not of the repost record
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import {makeAutoObservable, runInAction} from 'mobx'
|
||||
import {bsky, AdxUri} from '@adxp/mock-api'
|
||||
import * as GetPostThread from '../../third-party/api/src/types/todo/social/getPostThread'
|
||||
import {AdxUri} from '../../third-party/uri'
|
||||
import _omit from 'lodash.omit'
|
||||
import {RootStoreModel} from './root-store'
|
||||
import * as apilib from '../lib/api'
|
||||
|
@ -12,15 +13,15 @@ function* reactKeyGenerator(): Generator<string> {
|
|||
}
|
||||
|
||||
export class PostThreadViewPostMyStateModel {
|
||||
hasLiked: boolean = false
|
||||
hasReposted: boolean = false
|
||||
like?: string
|
||||
repost?: string
|
||||
|
||||
constructor() {
|
||||
makeAutoObservable(this)
|
||||
}
|
||||
}
|
||||
|
||||
export class PostThreadViewPostModel implements bsky.PostThreadView.Post {
|
||||
export class PostThreadViewPostModel implements GetPostThread.Post {
|
||||
// ui state
|
||||
_reactKey: string = ''
|
||||
_depth = 0
|
||||
|
@ -28,12 +29,12 @@ export class PostThreadViewPostModel implements bsky.PostThreadView.Post {
|
|||
|
||||
// data
|
||||
uri: string = ''
|
||||
author: bsky.PostThreadView.User = {did: '', name: '', displayName: ''}
|
||||
author: GetPostThread.User = {did: '', name: '', displayName: ''}
|
||||
record: Record<string, unknown> = {}
|
||||
embed?:
|
||||
| bsky.PostThreadView.RecordEmbed
|
||||
| bsky.PostThreadView.ExternalEmbed
|
||||
| bsky.PostThreadView.UnknownEmbed
|
||||
| GetPostThread.RecordEmbed
|
||||
| GetPostThread.ExternalEmbed
|
||||
| GetPostThread.UnknownEmbed
|
||||
parent?: PostThreadViewPostModel
|
||||
replyCount: number = 0
|
||||
replies?: PostThreadViewPostModel[]
|
||||
|
@ -45,7 +46,7 @@ export class PostThreadViewPostModel implements bsky.PostThreadView.Post {
|
|||
constructor(
|
||||
public rootStore: RootStoreModel,
|
||||
reactKey: string,
|
||||
v?: bsky.PostThreadView.Post,
|
||||
v?: GetPostThread.Post,
|
||||
) {
|
||||
makeAutoObservable(this, {rootStore: false})
|
||||
this._reactKey = reactKey
|
||||
|
@ -57,7 +58,7 @@ export class PostThreadViewPostModel implements bsky.PostThreadView.Post {
|
|||
}
|
||||
}
|
||||
|
||||
assignTreeModels(keyGen: Generator<string>, v: bsky.PostThreadView.Post) {
|
||||
assignTreeModels(keyGen: Generator<string>, v: GetPostThread.Post) {
|
||||
// parents
|
||||
if (v.parent) {
|
||||
// TODO: validate .record
|
||||
|
@ -93,33 +94,37 @@ export class PostThreadViewPostModel implements bsky.PostThreadView.Post {
|
|||
}
|
||||
|
||||
async toggleLike() {
|
||||
if (this.myState.hasLiked) {
|
||||
await apilib.unlike(this.rootStore.api, 'alice.com', this.uri)
|
||||
if (this.myState.like) {
|
||||
await apilib.unlike(this.rootStore.api, 'alice.test', this.uri)
|
||||
runInAction(() => {
|
||||
this.likeCount--
|
||||
this.myState.hasLiked = false
|
||||
this.myState.like = undefined
|
||||
})
|
||||
} else {
|
||||
await apilib.like(this.rootStore.api, 'alice.com', this.uri)
|
||||
const res = await apilib.like(this.rootStore.api, 'alice.test', this.uri)
|
||||
runInAction(() => {
|
||||
this.likeCount++
|
||||
this.myState.hasLiked = true
|
||||
this.myState.like = res.uri
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async toggleRepost() {
|
||||
if (this.myState.hasReposted) {
|
||||
await apilib.unrepost(this.rootStore.api, 'alice.com', this.uri)
|
||||
if (this.myState.repost) {
|
||||
await apilib.unrepost(this.rootStore.api, 'alice.test', this.uri)
|
||||
runInAction(() => {
|
||||
this.repostCount--
|
||||
this.myState.hasReposted = false
|
||||
this.myState.repost = undefined
|
||||
})
|
||||
} else {
|
||||
await apilib.repost(this.rootStore.api, 'alice.com', this.uri)
|
||||
const res = await apilib.repost(
|
||||
this.rootStore.api,
|
||||
'alice.test',
|
||||
this.uri,
|
||||
)
|
||||
runInAction(() => {
|
||||
this.repostCount++
|
||||
this.myState.hasReposted = true
|
||||
this.myState.repost = res.uri
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -132,14 +137,14 @@ export class PostThreadViewModel {
|
|||
hasLoaded = false
|
||||
error = ''
|
||||
resolvedUri = ''
|
||||
params: bsky.PostThreadView.Params
|
||||
params: GetPostThread.QueryParams
|
||||
|
||||
// data
|
||||
thread?: PostThreadViewPostModel
|
||||
|
||||
constructor(
|
||||
public rootStore: RootStoreModel,
|
||||
params: bsky.PostThreadView.Params,
|
||||
params: GetPostThread.QueryParams,
|
||||
) {
|
||||
makeAutoObservable(
|
||||
this,
|
||||
|
@ -226,10 +231,9 @@ export class PostThreadViewModel {
|
|||
private async _load(isRefreshing = false) {
|
||||
this._xLoading(isRefreshing)
|
||||
try {
|
||||
const res = (await this.rootStore.api.mainPds.view(
|
||||
'blueskyweb.xyz:PostThreadView',
|
||||
const res = await this.rootStore.api.todo.social.getPostThread(
|
||||
Object.assign({}, this.params, {uri: this.resolvedUri}),
|
||||
)) as bsky.PostThreadView.Response
|
||||
)
|
||||
this._replaceAll(res)
|
||||
this._xIdle()
|
||||
} catch (e: any) {
|
||||
|
@ -237,16 +241,16 @@ export class PostThreadViewModel {
|
|||
}
|
||||
}
|
||||
|
||||
private _replaceAll(res: bsky.PostThreadView.Response) {
|
||||
private _replaceAll(res: GetPostThread.Response) {
|
||||
// TODO: validate .record
|
||||
const keyGen = reactKeyGenerator()
|
||||
const thread = new PostThreadViewPostModel(
|
||||
this.rootStore,
|
||||
keyGen.next().value,
|
||||
res.thread,
|
||||
res.data.thread,
|
||||
)
|
||||
thread._isHighlightedPost = true
|
||||
thread.assignTreeModels(keyGen, res.thread)
|
||||
thread.assignTreeModels(keyGen, res.data.thread)
|
||||
this.thread = thread
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
import {makeAutoObservable} from 'mobx'
|
||||
import {bsky, AdxUri} from '@adxp/mock-api'
|
||||
import * as Post from '../../third-party/api/src/types/todo/social/post'
|
||||
import {AdxUri} from '../../third-party/uri'
|
||||
import {RootStoreModel} from './root-store'
|
||||
|
||||
export type PostEntities = bsky.Post.Record['entities']
|
||||
export type PostReply = bsky.Post.Record['reply']
|
||||
export class PostModel implements bsky.Post.Record {
|
||||
export type PostEntities = Post.Record['entities']
|
||||
export type PostReply = Post.Record['reply']
|
||||
type RemoveIndex<T> = {
|
||||
[P in keyof T as string extends P
|
||||
? never
|
||||
: number extends P
|
||||
? never
|
||||
: P]: T[P]
|
||||
}
|
||||
export class PostModel implements RemoveIndex<Post.Record> {
|
||||
// state
|
||||
isLoading = false
|
||||
hasLoaded = false
|
||||
|
@ -70,13 +78,14 @@ export class PostModel implements bsky.Post.Record {
|
|||
await new Promise(r => setTimeout(r, 250)) // DEBUG
|
||||
try {
|
||||
const urip = new AdxUri(this.uri)
|
||||
const res = await this.rootStore.api.mainPds
|
||||
.repo(urip.host, false)
|
||||
.collection(urip.collection)
|
||||
.get('Post', urip.recordKey)
|
||||
if (!res.valid) {
|
||||
throw new Error(res.error)
|
||||
}
|
||||
const res = await this.rootStore.api.todo.social.post.get({
|
||||
nameOrDid: urip.host,
|
||||
tid: urip.recordKey,
|
||||
})
|
||||
// TODO
|
||||
// if (!res.valid) {
|
||||
// throw new Error(res.error)
|
||||
// }
|
||||
this._replaceAll(res.value)
|
||||
this._xIdle()
|
||||
} catch (e: any) {
|
||||
|
@ -84,7 +93,7 @@ export class PostModel implements bsky.Post.Record {
|
|||
}
|
||||
}
|
||||
|
||||
private _replaceAll(res: bsky.Post.Record) {
|
||||
private _replaceAll(res: Post.Record) {
|
||||
this.text = res.text
|
||||
this.entities = res.entities
|
||||
this.reply = res.reply
|
||||
|
|
|
@ -1,38 +1,39 @@
|
|||
import {makeAutoObservable, runInAction} from 'mobx'
|
||||
import {bsky} from '@adxp/mock-api'
|
||||
import * as GetProfile from '../../third-party/api/src/types/todo/social/getProfile'
|
||||
import * as Profile from '../../third-party/api/src/types/todo/social/profile'
|
||||
import {RootStoreModel} from './root-store'
|
||||
import * as apilib from '../lib/api'
|
||||
|
||||
export class ProfileViewMyStateModel {
|
||||
hasFollowed: boolean = false
|
||||
follow?: string
|
||||
|
||||
constructor() {
|
||||
makeAutoObservable(this)
|
||||
}
|
||||
}
|
||||
|
||||
export class ProfileViewModel implements bsky.ProfileView.Response {
|
||||
export class ProfileViewModel {
|
||||
// state
|
||||
isLoading = false
|
||||
isRefreshing = false
|
||||
hasLoaded = false
|
||||
error = ''
|
||||
params: bsky.ProfileView.Params
|
||||
params: GetProfile.QueryParams
|
||||
|
||||
// data
|
||||
did: string = ''
|
||||
name: string = ''
|
||||
displayName: string = ''
|
||||
description: string = ''
|
||||
displayName?: string
|
||||
description?: string
|
||||
followersCount: number = 0
|
||||
followsCount: number = 0
|
||||
postsCount: number = 0
|
||||
badges: bsky.ProfileView.Badge[] = []
|
||||
badges: GetProfile.Badge[] = []
|
||||
myState = new ProfileViewMyStateModel()
|
||||
|
||||
constructor(
|
||||
public rootStore: RootStoreModel,
|
||||
params: bsky.ProfileView.Params,
|
||||
params: GetProfile.QueryParams,
|
||||
) {
|
||||
makeAutoObservable(
|
||||
this,
|
||||
|
@ -69,27 +70,31 @@ export class ProfileViewModel implements bsky.ProfileView.Response {
|
|||
}
|
||||
|
||||
async toggleFollowing() {
|
||||
if (this.myState.hasFollowed) {
|
||||
await apilib.unfollow(this.rootStore.api, 'alice.com', {
|
||||
if (!this.rootStore.me.did) {
|
||||
throw new Error('Not logged in')
|
||||
}
|
||||
if (this.myState.follow) {
|
||||
await apilib.unfollow(this.rootStore.api, this.rootStore.me.did, {
|
||||
did: this.did,
|
||||
})
|
||||
runInAction(() => {
|
||||
this.followersCount--
|
||||
this.myState.hasFollowed = false
|
||||
this.myState.follow = undefined
|
||||
})
|
||||
} else {
|
||||
await apilib.follow(this.rootStore.api, 'alice.com', {
|
||||
did: this.did,
|
||||
name: this.name,
|
||||
})
|
||||
const res = await apilib.follow(
|
||||
this.rootStore.api,
|
||||
this.rootStore.me.did,
|
||||
this.did,
|
||||
)
|
||||
runInAction(() => {
|
||||
this.followersCount++
|
||||
this.myState.hasFollowed = true
|
||||
this.myState.follow = res.uri
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async updateProfile(profile: bsky.Profile.Record) {
|
||||
async updateProfile(profile: Profile.Record) {
|
||||
if (this.did !== this.rootStore.me.did) {
|
||||
throw new Error('Not your profile!')
|
||||
}
|
||||
|
@ -120,10 +125,7 @@ export class ProfileViewModel implements bsky.ProfileView.Response {
|
|||
this._xLoading(isRefreshing)
|
||||
await new Promise(r => setTimeout(r, 250)) // DEBUG
|
||||
try {
|
||||
const res = (await this.rootStore.api.mainPds.view(
|
||||
'blueskyweb.xyz:ProfileView',
|
||||
this.params,
|
||||
)) as bsky.ProfileView.Response
|
||||
const res = await this.rootStore.api.todo.social.getProfile(this.params)
|
||||
this._replaceAll(res)
|
||||
this._xIdle()
|
||||
} catch (e: any) {
|
||||
|
@ -131,17 +133,17 @@ export class ProfileViewModel implements bsky.ProfileView.Response {
|
|||
}
|
||||
}
|
||||
|
||||
private _replaceAll(res: bsky.ProfileView.Response) {
|
||||
this.did = res.did
|
||||
this.name = res.name
|
||||
this.displayName = res.displayName
|
||||
this.description = res.description
|
||||
this.followersCount = res.followersCount
|
||||
this.followsCount = res.followsCount
|
||||
this.postsCount = res.postsCount
|
||||
this.badges = res.badges
|
||||
if (res.myState) {
|
||||
Object.assign(this.myState, res.myState)
|
||||
private _replaceAll(res: GetProfile.Response) {
|
||||
this.did = res.data.did
|
||||
this.name = res.data.name
|
||||
this.displayName = res.data.displayName
|
||||
this.description = res.data.description
|
||||
this.followersCount = res.data.followersCount
|
||||
this.followsCount = res.data.followsCount
|
||||
this.postsCount = res.data.postsCount
|
||||
this.badges = res.data.badges
|
||||
if (res.data.myState) {
|
||||
Object.assign(this.myState, res.data.myState)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import {makeAutoObservable, runInAction} from 'mobx'
|
||||
import {bsky, AdxUri} from '@adxp/mock-api'
|
||||
import {AdxUri} from '../../third-party/uri'
|
||||
import * as GetRepostedBy from '../../third-party/api/src/types/todo/social/getRepostedBy'
|
||||
import {RootStoreModel} from './root-store'
|
||||
|
||||
type RepostedByItem = bsky.RepostedByView.Response['repostedBy'][number]
|
||||
type RepostedByItem = GetRepostedBy.OutputSchema['repostedBy'][number]
|
||||
|
||||
export class RepostedByViewItemModel implements RepostedByItem {
|
||||
// ui state
|
||||
|
@ -22,14 +23,14 @@ export class RepostedByViewItemModel implements RepostedByItem {
|
|||
}
|
||||
}
|
||||
|
||||
export class RepostedByViewModel implements bsky.RepostedByView.Response {
|
||||
export class RepostedByViewModel {
|
||||
// state
|
||||
isLoading = false
|
||||
isRefreshing = false
|
||||
hasLoaded = false
|
||||
error = ''
|
||||
resolvedUri = ''
|
||||
params: bsky.RepostedByView.Params
|
||||
params: GetRepostedBy.QueryParams
|
||||
|
||||
// data
|
||||
uri: string = ''
|
||||
|
@ -37,7 +38,7 @@ export class RepostedByViewModel implements bsky.RepostedByView.Response {
|
|||
|
||||
constructor(
|
||||
public rootStore: RootStoreModel,
|
||||
params: bsky.RepostedByView.Params,
|
||||
params: GetRepostedBy.QueryParams,
|
||||
) {
|
||||
makeAutoObservable(
|
||||
this,
|
||||
|
@ -113,10 +114,9 @@ export class RepostedByViewModel implements bsky.RepostedByView.Response {
|
|||
this._xLoading(isRefreshing)
|
||||
await new Promise(r => setTimeout(r, 250)) // DEBUG
|
||||
try {
|
||||
const res = (await this.rootStore.api.mainPds.view(
|
||||
'blueskyweb.xyz:RepostedByView',
|
||||
const res = await this.rootStore.api.todo.social.getRepostedBy(
|
||||
Object.assign({}, this.params, {uri: this.resolvedUri}),
|
||||
)) as bsky.RepostedByView.Response
|
||||
)
|
||||
this._replaceAll(res)
|
||||
this._xIdle()
|
||||
} catch (e: any) {
|
||||
|
@ -131,10 +131,10 @@ export class RepostedByViewModel implements bsky.RepostedByView.Response {
|
|||
this._xIdle()
|
||||
}
|
||||
|
||||
private _replaceAll(res: bsky.RepostedByView.Response) {
|
||||
private _replaceAll(res: GetRepostedBy.Response) {
|
||||
this.repostedBy.length = 0
|
||||
let counter = 0
|
||||
for (const item of res.repostedBy) {
|
||||
for (const item of res.data.repostedBy) {
|
||||
this._append(counter++, item)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*/
|
||||
|
||||
import {makeAutoObservable} from 'mobx'
|
||||
import {adx, AdxClient} from '@adxp/mock-api'
|
||||
import AdxApi, {ServiceClient} from '../../third-party/api'
|
||||
import {createContext, useContext} from 'react'
|
||||
import {isObj, hasProp} from '../lib/type-guards'
|
||||
import {SessionModel} from './session'
|
||||
|
@ -17,7 +17,7 @@ export class RootStoreModel {
|
|||
shell = new ShellModel()
|
||||
me = new MeModel(this)
|
||||
|
||||
constructor(public api: AdxClient) {
|
||||
constructor(public api: ServiceClient) {
|
||||
makeAutoObservable(this, {
|
||||
api: false,
|
||||
resolveName: false,
|
||||
|
@ -27,9 +27,11 @@ export class RootStoreModel {
|
|||
}
|
||||
|
||||
async resolveName(didOrName: string) {
|
||||
const userDb = this.api.mockDb.getUser(didOrName)
|
||||
if (!userDb) throw new Error(`User not found: ${didOrName}`)
|
||||
return userDb.did
|
||||
throw new Error('TODO')
|
||||
return ''
|
||||
// const userDb = this.api.mockDb.getUser(didOrName)
|
||||
// if (!userDb) throw new Error(`User not found: ${didOrName}`)
|
||||
// return userDb.did
|
||||
}
|
||||
|
||||
serialize(): unknown {
|
||||
|
@ -51,7 +53,7 @@ export class RootStoreModel {
|
|||
}
|
||||
}
|
||||
|
||||
const throwawayInst = new RootStoreModel(adx) // this will be replaced by the loader
|
||||
const throwawayInst = new RootStoreModel(AdxApi.service('http://localhost')) // this will be replaced by the loader
|
||||
const RootStoreContext = createContext<RootStoreModel>(throwawayInst)
|
||||
export const RootStoreProvider = RootStoreContext.Provider
|
||||
export const useStores = () => useContext(RootStoreContext)
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import {makeAutoObservable} from 'mobx'
|
||||
import {bsky} from '@adxp/mock-api'
|
||||
import * as GetUserFollowers from '../../third-party/api/src/types/todo/social/getUserFollowers'
|
||||
import {RootStoreModel} from './root-store'
|
||||
|
||||
type Subject = bsky.UserFollowersView.Response['subject']
|
||||
type Subject = GetUserFollowers.OutputSchema['subject']
|
||||
export type FollowerItem =
|
||||
bsky.UserFollowersView.Response['followers'][number] & {_reactKey: string}
|
||||
GetUserFollowers.OutputSchema['followers'][number] & {_reactKey: string}
|
||||
|
||||
export class UserFollowersViewModel implements bsky.UserFollowersView.Response {
|
||||
export class UserFollowersViewModel {
|
||||
// state
|
||||
isLoading = false
|
||||
isRefreshing = false
|
||||
hasLoaded = false
|
||||
error = ''
|
||||
params: bsky.UserFollowersView.Params
|
||||
params: GetUserFollowers.QueryParams
|
||||
|
||||
// data
|
||||
subject: Subject = {did: '', name: '', displayName: ''}
|
||||
|
@ -20,7 +20,7 @@ export class UserFollowersViewModel implements bsky.UserFollowersView.Response {
|
|||
|
||||
constructor(
|
||||
public rootStore: RootStoreModel,
|
||||
params: bsky.UserFollowersView.Params,
|
||||
params: GetUserFollowers.QueryParams,
|
||||
) {
|
||||
makeAutoObservable(
|
||||
this,
|
||||
|
@ -83,10 +83,9 @@ export class UserFollowersViewModel implements bsky.UserFollowersView.Response {
|
|||
this._xLoading(isRefreshing)
|
||||
await new Promise(r => setTimeout(r, 250)) // DEBUG
|
||||
try {
|
||||
const res = (await this.rootStore.api.mainPds.view(
|
||||
'blueskyweb.xyz:UserFollowersView',
|
||||
const res = await this.rootStore.api.todo.social.getUserFollowers(
|
||||
this.params,
|
||||
)) as bsky.UserFollowersView.Response
|
||||
)
|
||||
this._replaceAll(res)
|
||||
this._xIdle()
|
||||
} catch (e: any) {
|
||||
|
@ -94,13 +93,13 @@ export class UserFollowersViewModel implements bsky.UserFollowersView.Response {
|
|||
}
|
||||
}
|
||||
|
||||
private _replaceAll(res: bsky.UserFollowersView.Response) {
|
||||
this.subject.did = res.subject.did
|
||||
this.subject.name = res.subject.name
|
||||
this.subject.displayName = res.subject.displayName
|
||||
private _replaceAll(res: GetUserFollowers.Response) {
|
||||
this.subject.did = res.data.subject.did
|
||||
this.subject.name = res.data.subject.name
|
||||
this.subject.displayName = res.data.subject.displayName
|
||||
this.followers.length = 0
|
||||
let counter = 0
|
||||
for (const item of res.followers) {
|
||||
for (const item of res.data.followers) {
|
||||
this._append({_reactKey: `item-${counter++}`, ...item})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
import {makeAutoObservable} from 'mobx'
|
||||
import {bsky} from '@adxp/mock-api'
|
||||
import * as GetUserFollows from '../../third-party/api/src/types/todo/social/getUserFollows'
|
||||
import {RootStoreModel} from './root-store'
|
||||
|
||||
type Subject = bsky.UserFollowsView.Response['subject']
|
||||
export type FollowItem = bsky.UserFollowsView.Response['follows'][number] & {
|
||||
type Subject = GetUserFollows.OutputSchema['subject']
|
||||
export type FollowItem = GetUserFollows.OutputSchema['follows'][number] & {
|
||||
_reactKey: string
|
||||
}
|
||||
|
||||
export class UserFollowsViewModel implements bsky.UserFollowsView.Response {
|
||||
export class UserFollowsViewModel {
|
||||
// state
|
||||
isLoading = false
|
||||
isRefreshing = false
|
||||
hasLoaded = false
|
||||
error = ''
|
||||
params: bsky.UserFollowsView.Params
|
||||
params: GetUserFollows.QueryParams
|
||||
|
||||
// data
|
||||
subject: Subject = {did: '', name: '', displayName: ''}
|
||||
|
@ -21,7 +21,7 @@ export class UserFollowsViewModel implements bsky.UserFollowsView.Response {
|
|||
|
||||
constructor(
|
||||
public rootStore: RootStoreModel,
|
||||
params: bsky.UserFollowsView.Params,
|
||||
params: GetUserFollows.QueryParams,
|
||||
) {
|
||||
makeAutoObservable(
|
||||
this,
|
||||
|
@ -84,10 +84,9 @@ export class UserFollowsViewModel implements bsky.UserFollowsView.Response {
|
|||
this._xLoading(isRefreshing)
|
||||
await new Promise(r => setTimeout(r, 250)) // DEBUG
|
||||
try {
|
||||
const res = (await this.rootStore.api.mainPds.view(
|
||||
'blueskyweb.xyz:UserFollowsView',
|
||||
const res = await this.rootStore.api.todo.social.getUserFollows(
|
||||
this.params,
|
||||
)) as bsky.UserFollowsView.Response
|
||||
)
|
||||
this._replaceAll(res)
|
||||
this._xIdle()
|
||||
} catch (e: any) {
|
||||
|
@ -95,13 +94,13 @@ export class UserFollowsViewModel implements bsky.UserFollowsView.Response {
|
|||
}
|
||||
}
|
||||
|
||||
private _replaceAll(res: bsky.UserFollowsView.Response) {
|
||||
this.subject.did = res.subject.did
|
||||
this.subject.name = res.subject.name
|
||||
this.subject.displayName = res.subject.displayName
|
||||
private _replaceAll(res: GetUserFollows.Response) {
|
||||
this.subject.did = res.data.subject.did
|
||||
this.subject.name = res.data.subject.name
|
||||
this.subject.displayName = res.data.subject.displayName
|
||||
this.follows.length = 0
|
||||
let counter = 0
|
||||
for (const item of res.follows) {
|
||||
for (const item of res.data.follows) {
|
||||
this._append({_reactKey: `item-${counter++}`, ...item})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue