Update to the latest APIs
This commit is contained in:
parent
8ae6e67eea
commit
f333a90fab
165 changed files with 2963 additions and 4747 deletions
|
@ -1,11 +1,8 @@
|
|||
import {autorun} from 'mobx'
|
||||
import AtpApi from '../third-party/api'
|
||||
import {sessionClient as AtpApi} from '../third-party/api'
|
||||
import {RootStoreModel} from './models/root-store'
|
||||
import * as libapi from './lib/api'
|
||||
import * as storage from './lib/storage'
|
||||
// import * as auth from './auth' TODO
|
||||
|
||||
import {ShellModel} from './models/shell'
|
||||
|
||||
const ROOT_STATE_STORAGE_KEY = 'root'
|
||||
const DEFAULT_SERVICE = 'http://localhost:2583'
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
*/
|
||||
|
||||
// import {ReactNativeStore} from './auth'
|
||||
import AtpApi from '../../third-party/api'
|
||||
import * as Profile from '../../third-party/api/src/types/app/bsky/profile'
|
||||
import * as Post from '../../third-party/api/src/types/app/bsky/post'
|
||||
import {sessionClient as AtpApi} from '../../third-party/api'
|
||||
import * as Profile from '../../third-party/api/src/client/types/app/bsky/actor/profile'
|
||||
import * as Post from '../../third-party/api/src/client/types/app/bsky/feed/post'
|
||||
import {AtUri} from '../../third-party/uri'
|
||||
import {RootStoreModel} from '../models/root-store'
|
||||
import {extractEntities} from '../../view/lib/strings'
|
||||
|
@ -23,7 +23,7 @@ export async function post(
|
|||
let reply
|
||||
if (replyTo) {
|
||||
const replyToUrip = new AtUri(replyTo.uri)
|
||||
const parentPost = await store.api.app.bsky.post.get({
|
||||
const parentPost = await store.api.app.bsky.feed.post.get({
|
||||
user: replyToUrip.host,
|
||||
rkey: replyToUrip.rkey,
|
||||
})
|
||||
|
@ -39,7 +39,7 @@ export async function post(
|
|||
}
|
||||
}
|
||||
const entities = extractEntities(text)
|
||||
return await store.api.app.bsky.post.create(
|
||||
return await store.api.app.bsky.feed.post.create(
|
||||
{did: store.me.did || ''},
|
||||
{
|
||||
text,
|
||||
|
@ -51,7 +51,7 @@ export async function post(
|
|||
}
|
||||
|
||||
export async function like(store: RootStoreModel, uri: string, cid: string) {
|
||||
return await store.api.app.bsky.like.create(
|
||||
return await store.api.app.bsky.feed.like.create(
|
||||
{did: store.me.did || ''},
|
||||
{
|
||||
subject: {uri, cid},
|
||||
|
@ -62,14 +62,14 @@ export async function like(store: RootStoreModel, uri: string, cid: string) {
|
|||
|
||||
export async function unlike(store: RootStoreModel, likeUri: string) {
|
||||
const likeUrip = new AtUri(likeUri)
|
||||
return await store.api.app.bsky.like.delete({
|
||||
return await store.api.app.bsky.feed.like.delete({
|
||||
did: likeUrip.hostname,
|
||||
rkey: likeUrip.rkey,
|
||||
})
|
||||
}
|
||||
|
||||
export async function repost(store: RootStoreModel, uri: string, cid: string) {
|
||||
return await store.api.app.bsky.repost.create(
|
||||
return await store.api.app.bsky.feed.repost.create(
|
||||
{did: store.me.did || ''},
|
||||
{
|
||||
subject: {uri, cid},
|
||||
|
@ -80,14 +80,15 @@ export async function repost(store: RootStoreModel, uri: string, cid: string) {
|
|||
|
||||
export async function unrepost(store: RootStoreModel, repostUri: string) {
|
||||
const repostUrip = new AtUri(repostUri)
|
||||
return await store.api.app.bsky.repost.delete({
|
||||
return await store.api.app.bsky.feed.repost.delete({
|
||||
did: repostUrip.hostname,
|
||||
rkey: repostUrip.rkey,
|
||||
})
|
||||
}
|
||||
|
||||
export async function follow(store: RootStoreModel, subject: string) {
|
||||
return await store.api.app.bsky.follow.create(
|
||||
// TODO NOW needs update
|
||||
return await store.api.app.bsky.graph.follow.create(
|
||||
{did: store.me.did || ''},
|
||||
{
|
||||
subject,
|
||||
|
@ -98,7 +99,7 @@ export async function follow(store: RootStoreModel, subject: string) {
|
|||
|
||||
export async function unfollow(store: RootStoreModel, followUri: string) {
|
||||
const followUrip = new AtUri(followUri)
|
||||
return await store.api.app.bsky.follow.delete({
|
||||
return await store.api.app.bsky.graph.follow.delete({
|
||||
did: followUrip.hostname,
|
||||
rkey: followUrip.rkey,
|
||||
})
|
||||
|
@ -108,13 +109,13 @@ export async function updateProfile(
|
|||
store: RootStoreModel,
|
||||
modifyFn: (existing?: Profile.Record) => Profile.Record,
|
||||
) {
|
||||
// TODO: replaceme
|
||||
const res = await store.api.app.bsky.profile.list({
|
||||
// TODO NOW replaceme
|
||||
const res = await store.api.app.bsky.actor.profile.list({
|
||||
user: store.me.did || '',
|
||||
})
|
||||
const existing = res.records[0]
|
||||
if (existing) {
|
||||
await store.api.app.bsky.profile.put(
|
||||
await store.api.app.bsky.actor.profile.put(
|
||||
{
|
||||
did: store.me.did || '',
|
||||
rkey: new AtUri(existing.uri).rkey,
|
||||
|
@ -122,7 +123,7 @@ export async function updateProfile(
|
|||
modifyFn(existing.value),
|
||||
)
|
||||
} else {
|
||||
await store.api.app.bsky.profile.create(
|
||||
await store.api.app.bsky.actor.profile.create(
|
||||
{
|
||||
did: store.me.did || '',
|
||||
},
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
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() {}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
import {makeAutoObservable, runInAction} from 'mobx'
|
||||
import * as GetHomeFeed from '../../third-party/api/src/types/app/bsky/getHomeFeed'
|
||||
import * as GetAuthorFeed from '../../third-party/api/src/types/app/bsky/getAuthorFeed'
|
||||
import * as GetTimeline from '../../third-party/api/src/client/types/app/bsky/feed/getTimeline'
|
||||
import * as GetAuthorFeed from '../../third-party/api/src/client/types/app/bsky/feed/getAuthorFeed'
|
||||
import {RootStoreModel} from './root-store'
|
||||
import * as apilib from '../lib/api'
|
||||
|
||||
|
@ -13,20 +13,20 @@ export class FeedItemMyStateModel {
|
|||
}
|
||||
}
|
||||
|
||||
export class FeedItemModel implements GetHomeFeed.FeedItem {
|
||||
export class FeedItemModel implements GetTimeline.FeedItem {
|
||||
// ui state
|
||||
_reactKey: string = ''
|
||||
|
||||
// data
|
||||
uri: string = ''
|
||||
cid: string = ''
|
||||
author: GetHomeFeed.User = {did: '', name: '', displayName: ''}
|
||||
repostedBy?: GetHomeFeed.User
|
||||
author: GetTimeline.User = {did: '', handle: '', displayName: ''}
|
||||
repostedBy?: GetTimeline.User
|
||||
record: Record<string, unknown> = {}
|
||||
embed?:
|
||||
| GetHomeFeed.RecordEmbed
|
||||
| GetHomeFeed.ExternalEmbed
|
||||
| GetHomeFeed.UnknownEmbed
|
||||
| GetTimeline.RecordEmbed
|
||||
| GetTimeline.ExternalEmbed
|
||||
| GetTimeline.UnknownEmbed
|
||||
replyCount: number = 0
|
||||
repostCount: number = 0
|
||||
likeCount: number = 0
|
||||
|
@ -36,14 +36,14 @@ export class FeedItemModel implements GetHomeFeed.FeedItem {
|
|||
constructor(
|
||||
public rootStore: RootStoreModel,
|
||||
reactKey: string,
|
||||
v: GetHomeFeed.FeedItem | GetAuthorFeed.FeedItem,
|
||||
v: GetTimeline.FeedItem | GetAuthorFeed.FeedItem,
|
||||
) {
|
||||
makeAutoObservable(this, {rootStore: false})
|
||||
this._reactKey = reactKey
|
||||
this.copy(v)
|
||||
}
|
||||
|
||||
copy(v: GetHomeFeed.FeedItem | GetAuthorFeed.FeedItem) {
|
||||
copy(v: GetTimeline.FeedItem | GetAuthorFeed.FeedItem) {
|
||||
this.uri = v.uri
|
||||
this.cid = v.cid
|
||||
this.author = v.author
|
||||
|
@ -100,7 +100,7 @@ export class FeedModel {
|
|||
hasLoaded = false
|
||||
hasReachedEnd = false
|
||||
error = ''
|
||||
params: GetHomeFeed.QueryParams | GetAuthorFeed.QueryParams
|
||||
params: GetTimeline.QueryParams | GetAuthorFeed.QueryParams
|
||||
loadMoreCursor: string | undefined
|
||||
_loadPromise: Promise<void> | undefined
|
||||
_loadMorePromise: Promise<void> | undefined
|
||||
|
@ -113,7 +113,7 @@ export class FeedModel {
|
|||
constructor(
|
||||
public rootStore: RootStoreModel,
|
||||
public feedType: 'home' | 'author',
|
||||
params: GetHomeFeed.QueryParams | GetAuthorFeed.QueryParams,
|
||||
params: GetTimeline.QueryParams | GetAuthorFeed.QueryParams,
|
||||
) {
|
||||
makeAutoObservable(
|
||||
this,
|
||||
|
@ -286,7 +286,7 @@ export class FeedModel {
|
|||
let cursor = undefined
|
||||
try {
|
||||
do {
|
||||
const res: GetHomeFeed.Response = await this._getFeed({
|
||||
const res: GetTimeline.Response = await this._getFeed({
|
||||
before: cursor,
|
||||
limit: Math.min(numToFetch, 100),
|
||||
})
|
||||
|
@ -304,13 +304,13 @@ export class FeedModel {
|
|||
}
|
||||
}
|
||||
|
||||
private _replaceAll(res: GetHomeFeed.Response | GetAuthorFeed.Response) {
|
||||
private _replaceAll(res: GetTimeline.Response | GetAuthorFeed.Response) {
|
||||
this.feed.length = 0
|
||||
this.hasReachedEnd = false
|
||||
this._appendAll(res)
|
||||
}
|
||||
|
||||
private _appendAll(res: GetHomeFeed.Response | GetAuthorFeed.Response) {
|
||||
private _appendAll(res: GetTimeline.Response | GetAuthorFeed.Response) {
|
||||
this.loadMoreCursor = res.data.cursor
|
||||
let counter = this.feed.length
|
||||
for (const item of res.data.feed) {
|
||||
|
@ -320,13 +320,13 @@ export class FeedModel {
|
|||
|
||||
private _append(
|
||||
keyId: number,
|
||||
item: GetHomeFeed.FeedItem | GetAuthorFeed.FeedItem,
|
||||
item: GetTimeline.FeedItem | GetAuthorFeed.FeedItem,
|
||||
) {
|
||||
// TODO: validate .record
|
||||
this.feed.push(new FeedItemModel(this.rootStore, `item-${keyId}`, item))
|
||||
}
|
||||
|
||||
private _prependAll(res: GetHomeFeed.Response | GetAuthorFeed.Response) {
|
||||
private _prependAll(res: GetTimeline.Response | GetAuthorFeed.Response) {
|
||||
let counter = this.feed.length
|
||||
for (const item of res.data.feed) {
|
||||
if (this.feed.find(item2 => item2.uri === item.uri)) {
|
||||
|
@ -338,13 +338,13 @@ export class FeedModel {
|
|||
|
||||
private _prepend(
|
||||
keyId: number,
|
||||
item: GetHomeFeed.FeedItem | GetAuthorFeed.FeedItem,
|
||||
item: GetTimeline.FeedItem | GetAuthorFeed.FeedItem,
|
||||
) {
|
||||
// TODO: validate .record
|
||||
this.feed.unshift(new FeedItemModel(this.rootStore, `item-${keyId}`, item))
|
||||
}
|
||||
|
||||
private _updateAll(res: GetHomeFeed.Response | GetAuthorFeed.Response) {
|
||||
private _updateAll(res: GetTimeline.Response | GetAuthorFeed.Response) {
|
||||
for (const item of res.data.feed) {
|
||||
const existingItem = this.feed.find(
|
||||
// this find function has a key subtley- the indexedAt comparison
|
||||
|
@ -359,15 +359,15 @@ export class FeedModel {
|
|||
}
|
||||
|
||||
protected _getFeed(
|
||||
params: GetHomeFeed.QueryParams | GetAuthorFeed.QueryParams = {},
|
||||
): Promise<GetHomeFeed.Response | GetAuthorFeed.Response> {
|
||||
params: GetTimeline.QueryParams | GetAuthorFeed.QueryParams = {},
|
||||
): Promise<GetTimeline.Response | GetAuthorFeed.Response> {
|
||||
params = Object.assign({}, this.params, params)
|
||||
if (this.feedType === 'home') {
|
||||
return this.rootStore.api.app.bsky.getHomeFeed(
|
||||
params as GetHomeFeed.QueryParams,
|
||||
return this.rootStore.api.app.bsky.feed.getTimeline(
|
||||
params as GetTimeline.QueryParams,
|
||||
)
|
||||
} else {
|
||||
return this.rootStore.api.app.bsky.getAuthorFeed(
|
||||
return this.rootStore.api.app.bsky.feed.getAuthorFeed(
|
||||
params as GetAuthorFeed.QueryParams,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {makeAutoObservable, runInAction} from 'mobx'
|
||||
import {AtUri} from '../../third-party/uri'
|
||||
import * as GetLikedBy from '../../third-party/api/src/types/app/bsky/getLikedBy'
|
||||
import * as GetLikedBy from '../../third-party/api/src/client/types/app/bsky/feed/getLikedBy'
|
||||
import {RootStoreModel} from './root-store'
|
||||
|
||||
type LikedByItem = GetLikedBy.OutputSchema['likedBy'][number]
|
||||
|
@ -11,7 +11,7 @@ export class LikedByViewItemModel implements LikedByItem {
|
|||
|
||||
// data
|
||||
did: string = ''
|
||||
name: string = ''
|
||||
handle: string = ''
|
||||
displayName: string = ''
|
||||
createdAt?: string
|
||||
indexedAt: string = ''
|
||||
|
@ -113,7 +113,7 @@ export class LikedByViewModel {
|
|||
private async _fetch(isRefreshing = false) {
|
||||
this._xLoading(isRefreshing)
|
||||
try {
|
||||
const res = await this.rootStore.api.app.bsky.getLikedBy(
|
||||
const res = await this.rootStore.api.app.bsky.feed.getLikedBy(
|
||||
Object.assign({}, this.params, {uri: this.resolvedUri}),
|
||||
)
|
||||
this._replaceAll(res)
|
||||
|
|
|
@ -3,7 +3,7 @@ import {RootStoreModel} from './root-store'
|
|||
|
||||
export class MeModel {
|
||||
did?: string
|
||||
name?: string
|
||||
handle?: string
|
||||
displayName?: string
|
||||
description?: string
|
||||
notificationCount: number = 0
|
||||
|
@ -14,7 +14,7 @@ export class MeModel {
|
|||
|
||||
clear() {
|
||||
this.did = undefined
|
||||
this.name = undefined
|
||||
this.handle = undefined
|
||||
this.displayName = undefined
|
||||
this.description = undefined
|
||||
this.notificationCount = 0
|
||||
|
@ -23,9 +23,9 @@ export class MeModel {
|
|||
async load() {
|
||||
const sess = this.rootStore.session
|
||||
if (sess.isAuthed && sess.data) {
|
||||
this.did = sess.data.userdid || ''
|
||||
this.name = sess.data.username
|
||||
const profile = await this.rootStore.api.app.bsky.getProfile({
|
||||
this.did = sess.data.did || ''
|
||||
this.handle = sess.data.handle
|
||||
const profile = await this.rootStore.api.app.bsky.actor.getProfile({
|
||||
user: this.did,
|
||||
})
|
||||
runInAction(() => {
|
||||
|
@ -43,7 +43,7 @@ export class MeModel {
|
|||
}
|
||||
|
||||
async fetchStateUpdate() {
|
||||
const res = await this.rootStore.api.app.bsky.getNotificationCount({})
|
||||
const res = await this.rootStore.api.app.bsky.notification.getCount()
|
||||
runInAction(() => {
|
||||
this.notificationCount = res.data.count
|
||||
})
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import {makeAutoObservable} from 'mobx'
|
||||
import * as GetNotifications from '../../third-party/api/src/types/app/bsky/getNotifications'
|
||||
import * as ListNotifications from '../../third-party/api/src/client/types/app/bsky/notification/list'
|
||||
import {RootStoreModel} from './root-store'
|
||||
import {hasProp} from '../lib/type-guards'
|
||||
|
||||
export interface GroupedNotification extends GetNotifications.Notification {
|
||||
additional?: GetNotifications.Notification[]
|
||||
export interface GroupedNotification extends ListNotifications.Notification {
|
||||
additional?: ListNotifications.Notification[]
|
||||
}
|
||||
|
||||
export class NotificationsViewItemModel implements GroupedNotification {
|
||||
|
@ -16,9 +16,9 @@ export class NotificationsViewItemModel implements GroupedNotification {
|
|||
cid: string = ''
|
||||
author: {
|
||||
did: string
|
||||
name: string
|
||||
handle: string
|
||||
displayName?: string
|
||||
} = {did: '', name: ''}
|
||||
} = {did: '', handle: ''}
|
||||
reason: string = ''
|
||||
reasonSubject?: string
|
||||
record: any = {}
|
||||
|
@ -93,7 +93,7 @@ export class NotificationsViewModel {
|
|||
isRefreshing = false
|
||||
hasLoaded = false
|
||||
error = ''
|
||||
params: GetNotifications.QueryParams
|
||||
params: ListNotifications.QueryParams
|
||||
loadMoreCursor?: string
|
||||
_loadPromise: Promise<void> | undefined
|
||||
_loadMorePromise: Promise<void> | undefined
|
||||
|
@ -104,7 +104,7 @@ export class NotificationsViewModel {
|
|||
|
||||
constructor(
|
||||
public rootStore: RootStoreModel,
|
||||
params: GetNotifications.QueryParams,
|
||||
params: ListNotifications.QueryParams,
|
||||
) {
|
||||
makeAutoObservable(
|
||||
this,
|
||||
|
@ -216,7 +216,7 @@ export class NotificationsViewModel {
|
|||
private async _initialLoad(isRefreshing = false) {
|
||||
this._xLoading(isRefreshing)
|
||||
try {
|
||||
const res = await this.rootStore.api.app.bsky.getNotifications(
|
||||
const res = await this.rootStore.api.app.bsky.notification.list(
|
||||
this.params,
|
||||
)
|
||||
this._replaceAll(res)
|
||||
|
@ -232,7 +232,7 @@ export class NotificationsViewModel {
|
|||
const params = Object.assign({}, this.params, {
|
||||
before: this.loadMoreCursor,
|
||||
})
|
||||
const res = await this.rootStore.api.app.bsky.getNotifications(params)
|
||||
const res = await this.rootStore.api.app.bsky.notification.list(params)
|
||||
this._appendAll(res)
|
||||
this._xIdle()
|
||||
} catch (e: any) {
|
||||
|
@ -246,8 +246,8 @@ export class NotificationsViewModel {
|
|||
let cursor = undefined
|
||||
try {
|
||||
do {
|
||||
const res: GetNotifications.Response =
|
||||
await this.rootStore.api.app.bsky.getNotifications({
|
||||
const res: ListNotifications.Response =
|
||||
await this.rootStore.api.app.bsky.notification.list({
|
||||
before: cursor,
|
||||
limit: Math.min(numToFetch, 100),
|
||||
})
|
||||
|
@ -265,12 +265,12 @@ export class NotificationsViewModel {
|
|||
}
|
||||
}
|
||||
|
||||
private _replaceAll(res: GetNotifications.Response) {
|
||||
private _replaceAll(res: ListNotifications.Response) {
|
||||
this.notifications.length = 0
|
||||
this._appendAll(res)
|
||||
}
|
||||
|
||||
private _appendAll(res: GetNotifications.Response) {
|
||||
private _appendAll(res: ListNotifications.Response) {
|
||||
this.loadMoreCursor = res.data.cursor
|
||||
let counter = this.notifications.length
|
||||
for (const item of groupNotifications(res.data.notifications)) {
|
||||
|
@ -285,7 +285,7 @@ export class NotificationsViewModel {
|
|||
)
|
||||
}
|
||||
|
||||
private _updateAll(res: GetNotifications.Response) {
|
||||
private _updateAll(res: ListNotifications.Response) {
|
||||
for (const item of res.data.notifications) {
|
||||
const existingItem = this.notifications.find(
|
||||
// this find function has a key subtlety- the indexedAt comparison
|
||||
|
@ -301,10 +301,9 @@ export class NotificationsViewModel {
|
|||
|
||||
private async _updateReadState() {
|
||||
try {
|
||||
await this.rootStore.api.app.bsky.postNotificationsSeen(
|
||||
{},
|
||||
{seenAt: new Date().toISOString()},
|
||||
)
|
||||
await this.rootStore.api.app.bsky.notification.updateSeen({
|
||||
seenAt: new Date().toISOString(),
|
||||
})
|
||||
} catch (e) {
|
||||
console.log('Failed to update notifications read state', e)
|
||||
}
|
||||
|
@ -312,7 +311,7 @@ export class NotificationsViewModel {
|
|||
}
|
||||
|
||||
function groupNotifications(
|
||||
items: GetNotifications.Notification[],
|
||||
items: ListNotifications.Notification[],
|
||||
): GroupedNotification[] {
|
||||
const items2: GroupedNotification[] = []
|
||||
for (const item of items) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {makeAutoObservable, runInAction} from 'mobx'
|
||||
import * as GetPostThread from '../../third-party/api/src/types/app/bsky/getPostThread'
|
||||
import * as GetPostThread from '../../third-party/api/src/client/types/app/bsky/feed/getPostThread'
|
||||
import {AtUri} from '../../third-party/uri'
|
||||
import _omit from 'lodash.omit'
|
||||
import {RootStoreModel} from './root-store'
|
||||
|
@ -30,7 +30,7 @@ export class PostThreadViewPostModel implements GetPostThread.Post {
|
|||
// data
|
||||
uri: string = ''
|
||||
cid: string = ''
|
||||
author: GetPostThread.User = {did: '', name: '', displayName: ''}
|
||||
author: GetPostThread.User = {did: '', handle: '', displayName: ''}
|
||||
record: Record<string, unknown> = {}
|
||||
embed?:
|
||||
| GetPostThread.RecordEmbed
|
||||
|
@ -82,8 +82,8 @@ export class PostThreadViewPostModel implements GetPostThread.Post {
|
|||
}
|
||||
this.parent = parentModel
|
||||
}
|
||||
if (v.parent?.author.name) {
|
||||
this.replyingToAuthor = v.parent.author.name
|
||||
if (v.parent?.author.handle) {
|
||||
this.replyingToAuthor = v.parent.author.handle
|
||||
}
|
||||
// replies
|
||||
if (includeChildren && v.replies) {
|
||||
|
@ -239,7 +239,7 @@ export class PostThreadViewModel {
|
|||
private async _load(isRefreshing = false) {
|
||||
this._xLoading(isRefreshing)
|
||||
try {
|
||||
const res = await this.rootStore.api.app.bsky.getPostThread(
|
||||
const res = await this.rootStore.api.app.bsky.feed.getPostThread(
|
||||
Object.assign({}, this.params, {uri: this.resolvedUri}),
|
||||
)
|
||||
this._replaceAll(res)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {makeAutoObservable} from 'mobx'
|
||||
import * as Post from '../../third-party/api/src/types/app/bsky/post'
|
||||
import * as Post from '../../third-party/api/src/client/types/app/bsky/feed/post'
|
||||
import {AtUri} from '../../third-party/uri'
|
||||
import {RootStoreModel} from './root-store'
|
||||
|
||||
|
@ -77,7 +77,7 @@ export class PostModel implements RemoveIndex<Post.Record> {
|
|||
this._xLoading()
|
||||
try {
|
||||
const urip = new AtUri(this.uri)
|
||||
const res = await this.rootStore.api.app.bsky.post.get({
|
||||
const res = await this.rootStore.api.app.bsky.feed.post.get({
|
||||
user: urip.host,
|
||||
rkey: urip.rkey,
|
||||
})
|
||||
|
|
|
@ -2,7 +2,6 @@ import {makeAutoObservable} from 'mobx'
|
|||
import {RootStoreModel} from './root-store'
|
||||
import {ProfileViewModel} from './profile-view'
|
||||
import {FeedModel} from './feed-view'
|
||||
import {BadgesViewModel} from './badges-view'
|
||||
|
||||
export const SECTION_IDS = {
|
||||
POSTS: 0,
|
||||
|
@ -20,7 +19,6 @@ export class ProfileUiModel {
|
|||
// data
|
||||
profile: ProfileViewModel
|
||||
feed: FeedModel
|
||||
badges: BadgesViewModel
|
||||
|
||||
// ui state
|
||||
selectedViewIndex = 0
|
||||
|
@ -42,16 +40,12 @@ export class ProfileUiModel {
|
|||
author: params.user,
|
||||
limit: 10,
|
||||
})
|
||||
this.badges = new BadgesViewModel(rootStore)
|
||||
}
|
||||
|
||||
get currentView(): FeedModel | BadgesViewModel {
|
||||
get currentView(): FeedModel {
|
||||
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}`)
|
||||
}
|
||||
|
||||
|
@ -79,9 +73,6 @@ export class ProfileUiModel {
|
|||
this.feed
|
||||
.setup()
|
||||
.catch(err => console.error('Failed to fetch feed', err)),
|
||||
this.badges
|
||||
.setup()
|
||||
.catch(err => console.error('Failed to fetch badges', err)),
|
||||
])
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {makeAutoObservable, runInAction} from 'mobx'
|
||||
import * as GetProfile from '../../third-party/api/src/types/app/bsky/getProfile'
|
||||
import * as Profile from '../../third-party/api/src/types/app/bsky/profile'
|
||||
import * as GetProfile from '../../third-party/api/src/client/types/app/bsky/actor/getProfile'
|
||||
import * as Profile from '../../third-party/api/src/client/types/app/bsky/actor/profile'
|
||||
import {RootStoreModel} from './root-store'
|
||||
import * as apilib from '../lib/api'
|
||||
|
||||
|
@ -22,13 +22,12 @@ export class ProfileViewModel {
|
|||
|
||||
// data
|
||||
did: string = ''
|
||||
name: string = ''
|
||||
handle: string = ''
|
||||
displayName?: string
|
||||
description?: string
|
||||
followersCount: number = 0
|
||||
followsCount: number = 0
|
||||
postsCount: number = 0
|
||||
pinnedBadges: GetProfile.Badge[] = []
|
||||
myState = new ProfileViewMyStateModel()
|
||||
|
||||
constructor(
|
||||
|
@ -118,7 +117,9 @@ export class ProfileViewModel {
|
|||
private async _load(isRefreshing = false) {
|
||||
this._xLoading(isRefreshing)
|
||||
try {
|
||||
const res = await this.rootStore.api.app.bsky.getProfile(this.params)
|
||||
const res = await this.rootStore.api.app.bsky.actor.getProfile(
|
||||
this.params,
|
||||
)
|
||||
this._replaceAll(res)
|
||||
this._xIdle()
|
||||
} catch (e: any) {
|
||||
|
@ -128,13 +129,12 @@ export class ProfileViewModel {
|
|||
|
||||
private _replaceAll(res: GetProfile.Response) {
|
||||
this.did = res.data.did
|
||||
this.name = res.data.name
|
||||
this.handle = res.data.handle
|
||||
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.pinnedBadges = res.data.pinnedBadges
|
||||
if (res.data.myState) {
|
||||
Object.assign(this.myState, res.data.myState)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {makeAutoObservable, runInAction} from 'mobx'
|
||||
import {AtUri} from '../../third-party/uri'
|
||||
import * as GetRepostedBy from '../../third-party/api/src/types/app/bsky/getRepostedBy'
|
||||
import * as GetRepostedBy from '../../third-party/api/src/client/types/app/bsky/feed/getRepostedBy'
|
||||
import {RootStoreModel} from './root-store'
|
||||
|
||||
type RepostedByItem = GetRepostedBy.OutputSchema['repostedBy'][number]
|
||||
|
@ -11,7 +11,7 @@ export class RepostedByViewItemModel implements RepostedByItem {
|
|||
|
||||
// data
|
||||
did: string = ''
|
||||
name: string = ''
|
||||
handle: string = ''
|
||||
displayName: string = ''
|
||||
createdAt?: string
|
||||
indexedAt: string = ''
|
||||
|
@ -113,7 +113,7 @@ export class RepostedByViewModel {
|
|||
private async _fetch(isRefreshing = false) {
|
||||
this._xLoading(isRefreshing)
|
||||
try {
|
||||
const res = await this.rootStore.api.app.bsky.getRepostedBy(
|
||||
const res = await this.rootStore.api.app.bsky.feed.getRepostedBy(
|
||||
Object.assign({}, this.params, {uri: this.resolvedUri}),
|
||||
)
|
||||
this._replaceAll(res)
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
*/
|
||||
|
||||
import {makeAutoObservable} from 'mobx'
|
||||
import AtpApi from '../../third-party/api'
|
||||
import type {ServiceClient} from '../../third-party/api/src/index'
|
||||
import {sessionClient as AtpApi} from '../../third-party/api'
|
||||
import type {SessionServiceClient} from '../../third-party/api/src/index'
|
||||
import {createContext, useContext} from 'react'
|
||||
import {isObj, hasProp} from '../lib/type-guards'
|
||||
import {SessionModel} from './session'
|
||||
|
@ -18,7 +18,7 @@ export class RootStoreModel {
|
|||
shell = new ShellModel()
|
||||
me = new MeModel(this)
|
||||
|
||||
constructor(public api: ServiceClient) {
|
||||
constructor(public api: SessionServiceClient) {
|
||||
makeAutoObservable(this, {
|
||||
api: false,
|
||||
resolveName: false,
|
||||
|
@ -27,14 +27,14 @@ export class RootStoreModel {
|
|||
})
|
||||
}
|
||||
|
||||
async resolveName(didOrName: string) {
|
||||
if (!didOrName) {
|
||||
throw new Error('Invalid name: ""')
|
||||
async resolveName(didOrHandle: string) {
|
||||
if (!didOrHandle) {
|
||||
throw new Error('Invalid handle: ""')
|
||||
}
|
||||
if (didOrName.startsWith('did:')) {
|
||||
return didOrName
|
||||
if (didOrHandle.startsWith('did:')) {
|
||||
return didOrHandle
|
||||
}
|
||||
const res = await this.api.com.atproto.resolveName({name: didOrName})
|
||||
const res = await this.api.com.atproto.handle.resolve({handle: didOrHandle})
|
||||
return res.data.did
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import {makeAutoObservable} from 'mobx'
|
||||
import AtpApi from '../../third-party/api'
|
||||
import type * as GetAccountsConfig from '../../third-party/api/src/types/com/atproto/getAccountsConfig'
|
||||
import {sessionClient as AtpApi} from '../../third-party/api/index'
|
||||
import type {SessionServiceClient} from '../../third-party/api/src/index'
|
||||
import type * as GetAccountsConfig from '../../third-party/api/src/client/types/com/atproto/server/getAccountsConfig'
|
||||
import {isObj, hasProp} from '../lib/type-guards'
|
||||
import {RootStoreModel} from './root-store'
|
||||
|
||||
|
@ -8,9 +9,10 @@ export type ServiceDescription = GetAccountsConfig.OutputSchema
|
|||
|
||||
interface SessionData {
|
||||
service: string
|
||||
token: string
|
||||
username: string
|
||||
userdid: string
|
||||
refreshJwt: string
|
||||
accessJwt: string
|
||||
handle: string
|
||||
did: string
|
||||
}
|
||||
|
||||
export enum OnboardingStage {
|
||||
|
@ -49,26 +51,39 @@ export class SessionModel {
|
|||
if (hasProp(v, 'data') && isObj(v.data)) {
|
||||
const data: SessionData = {
|
||||
service: '',
|
||||
token: '',
|
||||
username: '',
|
||||
userdid: '',
|
||||
refreshJwt: '',
|
||||
accessJwt: '',
|
||||
handle: '',
|
||||
did: '',
|
||||
}
|
||||
if (hasProp(v.data, 'service') && typeof v.data.service === 'string') {
|
||||
data.service = v.data.service
|
||||
}
|
||||
if (hasProp(v.data, 'token') && typeof v.data.token === 'string') {
|
||||
data.token = v.data.token
|
||||
if (
|
||||
hasProp(v.data, 'refreshJwt') &&
|
||||
typeof v.data.refreshJwt === 'string'
|
||||
) {
|
||||
data.refreshJwt = v.data.refreshJwt
|
||||
}
|
||||
if (
|
||||
hasProp(v.data, 'username') &&
|
||||
typeof v.data.username === 'string'
|
||||
hasProp(v.data, 'accessJwt') &&
|
||||
typeof v.data.accessJwt === 'string'
|
||||
) {
|
||||
data.username = v.data.username
|
||||
data.accessJwt = v.data.accessJwt
|
||||
}
|
||||
if (hasProp(v.data, 'userdid') && typeof v.data.userdid === 'string') {
|
||||
data.userdid = v.data.userdid
|
||||
if (hasProp(v.data, 'handle') && typeof v.data.handle === 'string') {
|
||||
data.handle = v.data.handle
|
||||
}
|
||||
if (data.service && data.token && data.username && data.userdid) {
|
||||
if (hasProp(v.data, 'did') && typeof v.data.did === 'string') {
|
||||
data.did = v.data.did
|
||||
}
|
||||
if (
|
||||
data.service &&
|
||||
data.refreshJwt &&
|
||||
data.accessJwt &&
|
||||
data.handle &&
|
||||
data.did
|
||||
) {
|
||||
this.data = data
|
||||
}
|
||||
}
|
||||
|
@ -112,7 +127,10 @@ export class SessionModel {
|
|||
return false
|
||||
}
|
||||
|
||||
this.rootStore.api.setHeader('Authorization', `Bearer ${this.data.token}`)
|
||||
this.rootStore.api.sessionManager.set({
|
||||
refreshJwt: this.data.refreshJwt,
|
||||
accessJwt: this.data.accessJwt,
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
|
@ -122,8 +140,8 @@ export class SessionModel {
|
|||
}
|
||||
|
||||
try {
|
||||
const sess = await this.rootStore.api.com.atproto.getSession({})
|
||||
if (sess.success && this.data && this.data.userdid === sess.data.did) {
|
||||
const sess = await this.rootStore.api.com.atproto.session.get()
|
||||
if (sess.success && this.data && this.data.did === sess.data.did) {
|
||||
this.rootStore.me.load().catch(e => {
|
||||
console.error('Failed to fetch local user information', e)
|
||||
})
|
||||
|
@ -135,28 +153,29 @@ export class SessionModel {
|
|||
}
|
||||
|
||||
async describeService(service: string): Promise<ServiceDescription> {
|
||||
const api = AtpApi.service(service)
|
||||
const res = await api.com.atproto.getAccountsConfig({})
|
||||
const api = AtpApi.service(service) as SessionServiceClient
|
||||
const res = await api.com.atproto.server.getAccountsConfig({})
|
||||
return res.data
|
||||
}
|
||||
|
||||
async login({
|
||||
service,
|
||||
username,
|
||||
handle,
|
||||
password,
|
||||
}: {
|
||||
service: string
|
||||
username: string
|
||||
handle: string
|
||||
password: string
|
||||
}) {
|
||||
const api = AtpApi.service(service)
|
||||
const res = await api.com.atproto.createSession({}, {username, password})
|
||||
if (res.data.jwt) {
|
||||
const api = AtpApi.service(service) as SessionServiceClient
|
||||
const res = await api.com.atproto.session.create({handle, password})
|
||||
if (res.data.accessJwt && res.data.refreshJwt) {
|
||||
this.setState({
|
||||
service: service,
|
||||
token: res.data.jwt,
|
||||
username: res.data.name,
|
||||
userdid: res.data.did,
|
||||
accessJwt: res.data.accessJwt,
|
||||
refreshJwt: res.data.refreshJwt,
|
||||
handle: res.data.handle,
|
||||
did: res.data.did,
|
||||
})
|
||||
this.configureApi()
|
||||
this.rootStore.me.load().catch(e => {
|
||||
|
@ -169,26 +188,29 @@ export class SessionModel {
|
|||
service,
|
||||
email,
|
||||
password,
|
||||
username,
|
||||
handle,
|
||||
inviteCode,
|
||||
}: {
|
||||
service: string
|
||||
email: string
|
||||
password: string
|
||||
username: string
|
||||
handle: string
|
||||
inviteCode?: string
|
||||
}) {
|
||||
const api = AtpApi.service(service)
|
||||
const res = await api.com.atproto.createAccount(
|
||||
{},
|
||||
{username, password, email, inviteCode},
|
||||
)
|
||||
if (res.data.jwt) {
|
||||
const api = AtpApi.service(service) as SessionServiceClient
|
||||
const res = await api.com.atproto.account.create({
|
||||
handle,
|
||||
password,
|
||||
email,
|
||||
inviteCode,
|
||||
})
|
||||
if (res.data.accessJwt && res.data.refreshJwt) {
|
||||
this.setState({
|
||||
service: service,
|
||||
token: res.data.jwt,
|
||||
username: res.data.name,
|
||||
userdid: res.data.did,
|
||||
accessJwt: res.data.accessJwt,
|
||||
refreshJwt: res.data.refreshJwt,
|
||||
handle: res.data.handle,
|
||||
did: res.data.did,
|
||||
})
|
||||
this.setOnboardingStage(OnboardingStage.Init)
|
||||
this.configureApi()
|
||||
|
@ -200,7 +222,7 @@ export class SessionModel {
|
|||
|
||||
async logout() {
|
||||
if (this.isAuthed) {
|
||||
this.rootStore.api.com.atproto.deleteSession({}).catch((e: any) => {
|
||||
this.rootStore.api.com.atproto.session.delete().catch((e: any) => {
|
||||
console.error('(Minor issue) Failed to delete session on the server', e)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {makeAutoObservable} from 'mobx'
|
||||
import {ProfileViewModel} from './profile-view'
|
||||
import * as Post from '../../third-party/api/src/types/app/bsky/post'
|
||||
import * as Post from '../../third-party/api/src/client/types/app/bsky/feed/post'
|
||||
|
||||
export interface LinkActionsModelOpts {
|
||||
newTab?: boolean
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import {makeAutoObservable} from 'mobx'
|
||||
import * as GetUserFollowers from '../../third-party/api/src/types/app/bsky/getUserFollowers'
|
||||
import * as GetFollowers from '../../third-party/api/src/client/types/app/bsky/graph/getFollowers'
|
||||
import {RootStoreModel} from './root-store'
|
||||
|
||||
type Subject = GetUserFollowers.OutputSchema['subject']
|
||||
export type FollowerItem =
|
||||
GetUserFollowers.OutputSchema['followers'][number] & {_reactKey: string}
|
||||
type Subject = GetFollowers.OutputSchema['subject']
|
||||
export type FollowerItem = GetFollowers.OutputSchema['followers'][number] & {
|
||||
_reactKey: string
|
||||
}
|
||||
|
||||
export class UserFollowersViewModel {
|
||||
// state
|
||||
|
@ -12,15 +13,15 @@ export class UserFollowersViewModel {
|
|||
isRefreshing = false
|
||||
hasLoaded = false
|
||||
error = ''
|
||||
params: GetUserFollowers.QueryParams
|
||||
params: GetFollowers.QueryParams
|
||||
|
||||
// data
|
||||
subject: Subject = {did: '', name: '', displayName: ''}
|
||||
subject: Subject = {did: '', handle: '', displayName: ''}
|
||||
followers: FollowerItem[] = []
|
||||
|
||||
constructor(
|
||||
public rootStore: RootStoreModel,
|
||||
params: GetUserFollowers.QueryParams,
|
||||
params: GetFollowers.QueryParams,
|
||||
) {
|
||||
makeAutoObservable(
|
||||
this,
|
||||
|
@ -82,7 +83,7 @@ export class UserFollowersViewModel {
|
|||
private async _fetch(isRefreshing = false) {
|
||||
this._xLoading(isRefreshing)
|
||||
try {
|
||||
const res = await this.rootStore.api.app.bsky.getUserFollowers(
|
||||
const res = await this.rootStore.api.app.bsky.graph.getFollowers(
|
||||
this.params,
|
||||
)
|
||||
this._replaceAll(res)
|
||||
|
@ -92,9 +93,9 @@ export class UserFollowersViewModel {
|
|||
}
|
||||
}
|
||||
|
||||
private _replaceAll(res: GetUserFollowers.Response) {
|
||||
private _replaceAll(res: GetFollowers.Response) {
|
||||
this.subject.did = res.data.subject.did
|
||||
this.subject.name = res.data.subject.name
|
||||
this.subject.handle = res.data.subject.handle
|
||||
this.subject.displayName = res.data.subject.displayName
|
||||
this.followers.length = 0
|
||||
let counter = 0
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import {makeAutoObservable} from 'mobx'
|
||||
import * as GetUserFollows from '../../third-party/api/src/types/app/bsky/getUserFollows'
|
||||
import * as GetFollows from '../../third-party/api/src/client/types/app/bsky/graph/getFollows'
|
||||
import {RootStoreModel} from './root-store'
|
||||
|
||||
type Subject = GetUserFollows.OutputSchema['subject']
|
||||
export type FollowItem = GetUserFollows.OutputSchema['follows'][number] & {
|
||||
type Subject = GetFollows.OutputSchema['subject']
|
||||
export type FollowItem = GetFollows.OutputSchema['follows'][number] & {
|
||||
_reactKey: string
|
||||
}
|
||||
|
||||
|
@ -13,15 +13,15 @@ export class UserFollowsViewModel {
|
|||
isRefreshing = false
|
||||
hasLoaded = false
|
||||
error = ''
|
||||
params: GetUserFollows.QueryParams
|
||||
params: GetFollows.QueryParams
|
||||
|
||||
// data
|
||||
subject: Subject = {did: '', name: '', displayName: ''}
|
||||
subject: Subject = {did: '', handle: '', displayName: ''}
|
||||
follows: FollowItem[] = []
|
||||
|
||||
constructor(
|
||||
public rootStore: RootStoreModel,
|
||||
params: GetUserFollows.QueryParams,
|
||||
params: GetFollows.QueryParams,
|
||||
) {
|
||||
makeAutoObservable(
|
||||
this,
|
||||
|
@ -83,7 +83,9 @@ export class UserFollowsViewModel {
|
|||
private async _fetch(isRefreshing = false) {
|
||||
this._xLoading(isRefreshing)
|
||||
try {
|
||||
const res = await this.rootStore.api.app.bsky.getUserFollows(this.params)
|
||||
const res = await this.rootStore.api.app.bsky.graph.getFollows(
|
||||
this.params,
|
||||
)
|
||||
this._replaceAll(res)
|
||||
this._xIdle()
|
||||
} catch (e: any) {
|
||||
|
@ -91,9 +93,9 @@ export class UserFollowsViewModel {
|
|||
}
|
||||
}
|
||||
|
||||
private _replaceAll(res: GetUserFollows.Response) {
|
||||
private _replaceAll(res: GetFollows.Response) {
|
||||
this.subject.did = res.data.subject.did
|
||||
this.subject.name = res.data.subject.name
|
||||
this.subject.handle = res.data.subject.handle
|
||||
this.subject.displayName = res.data.subject.displayName
|
||||
this.follows.length = 0
|
||||
let counter = 0
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue