Update to the latest APIs

This commit is contained in:
Paul Frazee 2022-11-04 17:39:54 -05:00
parent 8ae6e67eea
commit f333a90fab
165 changed files with 2963 additions and 4747 deletions

View file

@ -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'

View file

@ -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 || '',
},

View file

@ -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() {}
}

View file

@ -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,
)
}

View file

@ -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)

View file

@ -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
})

View file

@ -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) {

View file

@ -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)

View file

@ -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,
})

View file

@ -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)),
])
}

View file

@ -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)
}

View file

@ -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)

View file

@ -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
}

View file

@ -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)
})
}

View file

@ -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

View file

@ -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

View file

@ -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