about summary refs log tree commit diff
path: root/src/state/models
diff options
context:
space:
mode:
Diffstat (limited to 'src/state/models')
-rw-r--r--src/state/models/feed-view.ts99
-rw-r--r--src/state/models/liked-by-view.ts20
-rw-r--r--src/state/models/me.ts20
-rw-r--r--src/state/models/navigation.ts5
-rw-r--r--src/state/models/notifications-view.ts54
-rw-r--r--src/state/models/post-thread-view.ts60
-rw-r--r--src/state/models/post.ts33
-rw-r--r--src/state/models/profile-view.ts66
-rw-r--r--src/state/models/reposted-by-view.ts20
-rw-r--r--src/state/models/root-store.ts14
-rw-r--r--src/state/models/user-followers-view.ts27
-rw-r--r--src/state/models/user-follows-view.ts27
12 files changed, 226 insertions, 219 deletions
diff --git a/src/state/models/feed-view.ts b/src/state/models/feed-view.ts
index 9ba96764b..a7975b66a 100644
--- a/src/state/models/feed-view.ts
+++ b/src/state/models/feed-view.ts
@@ -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
diff --git a/src/state/models/liked-by-view.ts b/src/state/models/liked-by-view.ts
index 91c94093d..cb76d0bbd 100644
--- a/src/state/models/liked-by-view.ts
+++ b/src/state/models/liked-by-view.ts
@@ -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)
     }
   }
diff --git a/src/state/models/me.ts b/src/state/models/me.ts
index 3fd5db9ac..1ec418b78 100644
--- a/src/state/models/me.ts
+++ b/src/state/models/me.ts
@@ -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 = ''
diff --git a/src/state/models/navigation.ts b/src/state/models/navigation.ts
index d984a536f..b7e15a290 100644
--- a/src/state/models/navigation.ts
+++ b/src/state/models/navigation.ts
@@ -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) {
diff --git a/src/state/models/notifications-view.ts b/src/state/models/notifications-view.ts
index ef8f14996..dc372ab55 100644
--- a/src/state/models/notifications-view.ts
+++ b/src/state/models/notifications-view.ts
@@ -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
diff --git a/src/state/models/post-thread-view.ts b/src/state/models/post-thread-view.ts
index f3603ec49..ce72201f5 100644
--- a/src/state/models/post-thread-view.ts
+++ b/src/state/models/post-thread-view.ts
@@ -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
   }
 }
diff --git a/src/state/models/post.ts b/src/state/models/post.ts
index 463230101..e6542a375 100644
--- a/src/state/models/post.ts
+++ b/src/state/models/post.ts
@@ -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
diff --git a/src/state/models/profile-view.ts b/src/state/models/profile-view.ts
index 42c3737e9..24d49c112 100644
--- a/src/state/models/profile-view.ts
+++ b/src/state/models/profile-view.ts
@@ -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)
     }
   }
 }
diff --git a/src/state/models/reposted-by-view.ts b/src/state/models/reposted-by-view.ts
index 74698767e..90f4764b3 100644
--- a/src/state/models/reposted-by-view.ts
+++ b/src/state/models/reposted-by-view.ts
@@ -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)
     }
   }
diff --git a/src/state/models/root-store.ts b/src/state/models/root-store.ts
index 47213f9d1..adbcb2389 100644
--- a/src/state/models/root-store.ts
+++ b/src/state/models/root-store.ts
@@ -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)
diff --git a/src/state/models/user-followers-view.ts b/src/state/models/user-followers-view.ts
index af10e57d5..8d6a929bf 100644
--- a/src/state/models/user-followers-view.ts
+++ b/src/state/models/user-followers-view.ts
@@ -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})
     }
   }
diff --git a/src/state/models/user-follows-view.ts b/src/state/models/user-follows-view.ts
index fd890a662..45f8b4b05 100644
--- a/src/state/models/user-follows-view.ts
+++ b/src/state/models/user-follows-view.ts
@@ -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})
     }
   }