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/me.ts61
-rw-r--r--src/state/models/ui/shell.ts5
2 files changed, 64 insertions, 2 deletions
diff --git a/src/state/models/me.ts b/src/state/models/me.ts
index b99363790..ba2dc6f32 100644
--- a/src/state/models/me.ts
+++ b/src/state/models/me.ts
@@ -1,5 +1,8 @@
 import {makeAutoObservable, runInAction} from 'mobx'
-import {ComAtprotoServerDefs} from '@atproto/api'
+import {
+  ComAtprotoServerDefs,
+  ComAtprotoServerListAppPasswords,
+} from '@atproto/api'
 import {RootStoreModel} from './root-store'
 import {PostsFeedModel} from './feeds/posts'
 import {NotificationsFeedModel} from './feeds/notifications'
@@ -21,6 +24,7 @@ export class MeModel {
   notifications: NotificationsFeedModel
   follows: MyFollowsCache
   invites: ComAtprotoServerDefs.InviteCode[] = []
+  appPasswords: ComAtprotoServerListAppPasswords.AppPassword[] = []
   lastProfileStateUpdate = Date.now()
   lastNotifsUpdate = Date.now()
 
@@ -37,7 +41,7 @@ export class MeModel {
     this.mainFeed = new PostsFeedModel(this.rootStore, 'home', {
       algorithm: 'reverse-chronological',
     })
-    this.notifications = new NotificationsFeedModel(this.rootStore, {})
+    this.notifications = new NotificationsFeedModel(this.rootStore)
     this.follows = new MyFollowsCache(this.rootStore)
   }
 
@@ -51,6 +55,7 @@ export class MeModel {
     this.description = ''
     this.avatar = ''
     this.invites = []
+    this.appPasswords = []
   }
 
   serialize(): unknown {
@@ -107,6 +112,7 @@ export class MeModel {
       })
       this.rootStore.emitSessionLoaded()
       await this.fetchInviteCodes()
+      await this.fetchAppPasswords()
     } else {
       this.clear()
     }
@@ -118,6 +124,7 @@ export class MeModel {
       this.lastProfileStateUpdate = Date.now()
       await this.fetchProfile()
       await this.fetchInviteCodes()
+      await this.fetchAppPasswords()
     }
     if (Date.now() - this.lastNotifsUpdate > NOTIFS_UPDATE_INTERVAL) {
       this.lastNotifsUpdate = Date.now()
@@ -171,6 +178,56 @@ export class MeModel {
       await this.rootStore.invitedUsers.fetch(this.invites)
     }
   }
+
+  async fetchAppPasswords() {
+    if (this.rootStore.session) {
+      try {
+        const res =
+          await this.rootStore.agent.com.atproto.server.listAppPasswords({})
+        runInAction(() => {
+          this.appPasswords = res.data.passwords
+        })
+      } catch (e) {
+        this.rootStore.log.error('Failed to fetch user app passwords', e)
+      }
+    }
+  }
+
+  async createAppPassword(name: string) {
+    if (this.rootStore.session) {
+      try {
+        if (this.appPasswords.find(p => p.name === name)) {
+          // TODO: this should be handled by the backend but it's not
+          throw new Error('App password with this name already exists')
+        }
+        const res =
+          await this.rootStore.agent.com.atproto.server.createAppPassword({
+            name,
+          })
+        runInAction(() => {
+          this.appPasswords.push(res.data)
+        })
+        return res.data
+      } catch (e) {
+        this.rootStore.log.error('Failed to create app password', e)
+      }
+    }
+  }
+
+  async deleteAppPassword(name: string) {
+    if (this.rootStore.session) {
+      try {
+        await this.rootStore.agent.com.atproto.server.revokeAppPassword({
+          name: name,
+        })
+        runInAction(() => {
+          this.appPasswords = this.appPasswords.filter(p => p.name !== name)
+        })
+      } catch (e) {
+        this.rootStore.log.error('Failed to delete app password', e)
+      }
+    }
+  }
 }
 
 function isInviteAvailable(invite: ComAtprotoServerDefs.InviteCode): boolean {
diff --git a/src/state/models/ui/shell.ts b/src/state/models/ui/shell.ts
index b717fe05c..6c58262d8 100644
--- a/src/state/models/ui/shell.ts
+++ b/src/state/models/ui/shell.ts
@@ -70,6 +70,10 @@ export interface InviteCodesModal {
   name: 'invite-codes'
 }
 
+export interface AddAppPasswordModal {
+  name: 'add-app-password'
+}
+
 export interface ContentFilteringSettingsModal {
   name: 'content-filtering-settings'
 }
@@ -79,6 +83,7 @@ export type Modal =
   | ChangeHandleModal
   | DeleteAccountModal
   | EditProfileModal
+  | AddAppPasswordModal
 
   // Curation
   | ContentFilteringSettingsModal