about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEric Bailey <git@esb.lol>2024-09-11 19:56:00 -0500
committerGitHub <noreply@github.com>2024-09-11 19:56:00 -0500
commitae71f5ce84165b683b880c4a585b5a617f2c36bb (patch)
treef717fdddb8c001dfdabfce3165c3755069b700db
parentcff7cbb4aa0a945399f4d44bb56a12ae0ed27278 (diff)
downloadvoidsky-ae71f5ce84165b683b880c4a585b5a617f2c36bb.tar.zst
NUX API (#5278)
* Set up nux API

* Bump SDK

* Naming

* Imports
-rw-r--r--package.json2
-rw-r--r--src/state/queries/nuxs/definitions.ts29
-rw-r--r--src/state/queries/nuxs/index.ts83
-rw-r--r--src/state/queries/nuxs/types.ts9
-rw-r--r--src/state/queries/nuxs/util.ts52
-rw-r--r--src/state/queries/preferences/const.ts1
-rw-r--r--yarn.lock29
7 files changed, 190 insertions, 15 deletions
diff --git a/package.json b/package.json
index eff665a64..92b6cfe15 100644
--- a/package.json
+++ b/package.json
@@ -52,7 +52,7 @@
     "open-analyzer": "EXPO_PUBLIC_OPEN_ANALYZER=1 yarn build-web"
   },
   "dependencies": {
-    "@atproto/api": "0.13.5",
+    "@atproto/api": "^0.13.7",
     "@bam.tech/react-native-image-resizer": "^3.0.4",
     "@braintree/sanitize-url": "^6.0.2",
     "@discord/bottom-sheet": "bluesky-social/react-native-bottom-sheet",
diff --git a/src/state/queries/nuxs/definitions.ts b/src/state/queries/nuxs/definitions.ts
new file mode 100644
index 000000000..c5cb1e9d9
--- /dev/null
+++ b/src/state/queries/nuxs/definitions.ts
@@ -0,0 +1,29 @@
+import zod from 'zod'
+
+import {BaseNux} from '#/state/queries/nuxs/types'
+
+export enum Nux {
+  One = 'one',
+  Two = 'two',
+}
+
+export const nuxNames = new Set(Object.values(Nux))
+
+export type AppNux =
+  | BaseNux<{
+      id: Nux.One
+      data: {
+        likes: number
+      }
+    }>
+  | BaseNux<{
+      id: Nux.Two
+      data: undefined
+    }>
+
+export const NuxSchemas = {
+  [Nux.One]: zod.object({
+    likes: zod.number(),
+  }),
+  [Nux.Two]: undefined,
+}
diff --git a/src/state/queries/nuxs/index.ts b/src/state/queries/nuxs/index.ts
new file mode 100644
index 000000000..2945e67eb
--- /dev/null
+++ b/src/state/queries/nuxs/index.ts
@@ -0,0 +1,83 @@
+import {useMutation, useQueryClient} from '@tanstack/react-query'
+
+import {AppNux, Nux} from '#/state/queries/nuxs/definitions'
+import {parseAppNux, serializeAppNux} from '#/state/queries/nuxs/util'
+import {
+  preferencesQueryKey,
+  usePreferencesQuery,
+} from '#/state/queries/preferences'
+import {useAgent} from '#/state/session'
+
+export {Nux} from '#/state/queries/nuxs/definitions'
+
+export function useNuxs() {
+  const {data, ...rest} = usePreferencesQuery()
+
+  if (data && rest.isSuccess) {
+    const nuxs = data.bskyAppState.nuxs
+      ?.map(parseAppNux)
+      ?.filter(Boolean) as AppNux[]
+
+    if (nuxs) {
+      return {
+        nuxs,
+        ...rest,
+      }
+    }
+  }
+
+  return {
+    nuxs: undefined,
+    ...rest,
+  }
+}
+
+export function useNux<T extends Nux>(id: T) {
+  const {nuxs, ...rest} = useNuxs()
+
+  if (nuxs && rest.isSuccess) {
+    const nux = nuxs.find(nux => nux.id === id)
+
+    if (nux) {
+      return {
+        nux: nux as Extract<AppNux, {id: T}>,
+        ...rest,
+      }
+    }
+  }
+
+  return {
+    nux: undefined,
+    ...rest,
+  }
+}
+
+export function useUpsertNuxMutation() {
+  const queryClient = useQueryClient()
+  const agent = useAgent()
+
+  return useMutation({
+    mutationFn: async (nux: AppNux) => {
+      await agent.bskyAppUpsertNux(serializeAppNux(nux))
+      // triggers a refetch
+      await queryClient.invalidateQueries({
+        queryKey: preferencesQueryKey,
+      })
+    },
+  })
+}
+
+export function useRemoveNuxsMutation() {
+  const queryClient = useQueryClient()
+  const agent = useAgent()
+
+  return useMutation({
+    mutationFn: async (ids: string[]) => {
+      await agent.bskyAppRemoveNuxs(ids)
+      // triggers a refetch
+      await queryClient.invalidateQueries({
+        queryKey: preferencesQueryKey,
+      })
+    },
+  })
+}
diff --git a/src/state/queries/nuxs/types.ts b/src/state/queries/nuxs/types.ts
new file mode 100644
index 000000000..5b7918470
--- /dev/null
+++ b/src/state/queries/nuxs/types.ts
@@ -0,0 +1,9 @@
+import {AppBskyActorDefs} from '@atproto/api'
+
+export type Data = Record<string, unknown> | undefined
+
+export type BaseNux<
+  T extends Pick<AppBskyActorDefs.Nux, 'id' | 'expiresAt'> & {data: Data},
+> = T & {
+  completed: boolean
+}
diff --git a/src/state/queries/nuxs/util.ts b/src/state/queries/nuxs/util.ts
new file mode 100644
index 000000000..d65b86a34
--- /dev/null
+++ b/src/state/queries/nuxs/util.ts
@@ -0,0 +1,52 @@
+import {AppBskyActorDefs, nuxSchema} from '@atproto/api'
+
+import {
+  AppNux,
+  Nux,
+  nuxNames,
+  NuxSchemas,
+} from '#/state/queries/nuxs/definitions'
+
+export function parseAppNux(nux: AppBskyActorDefs.Nux): AppNux | undefined {
+  if (!nuxNames.has(nux.id as Nux)) return
+  if (!nuxSchema.safeParse(nux).success) return
+
+  const {data, ...rest} = nux
+
+  const schema = NuxSchemas[nux.id as Nux]
+
+  if (schema && data) {
+    const parsedData = JSON.parse(data)
+
+    if (!schema.safeParse(parsedData).success) return
+
+    return {
+      ...rest,
+      data: parsedData,
+    } as AppNux
+  }
+
+  return {
+    ...rest,
+    data: undefined,
+  } as AppNux
+}
+
+export function serializeAppNux(nux: AppNux): AppBskyActorDefs.Nux {
+  const {data, ...rest} = nux
+  const schema = NuxSchemas[nux.id as Nux]
+
+  const result: AppBskyActorDefs.Nux = {
+    ...rest,
+    data: undefined,
+  }
+
+  if (schema) {
+    schema.parse(data)
+    result.data = JSON.stringify(data)
+  }
+
+  nuxSchema.parse(result)
+
+  return result
+}
diff --git a/src/state/queries/preferences/const.ts b/src/state/queries/preferences/const.ts
index 1ae7d2068..e07f40ec5 100644
--- a/src/state/queries/preferences/const.ts
+++ b/src/state/queries/preferences/const.ts
@@ -37,5 +37,6 @@ export const DEFAULT_LOGGED_OUT_PREFERENCES: UsePreferencesQueryResponse = {
   bskyAppState: {
     queuedNudges: [],
     activeProgressGuide: undefined,
+    nuxs: [],
   },
 }
diff --git a/yarn.lock b/yarn.lock
index cc440109a..b2e389aa1 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -72,31 +72,32 @@
   resolved "https://registry.yarnpkg.com/@atproto-labs/simple-store/-/simple-store-0.1.1.tgz#e743a2722b5d8732166f0a72aca8bd10e9bff106"
   integrity sha512-WKILW2b3QbAYKh+w5U2x6p5FqqLl0nAeLwGeDY+KjX01K4Dq3vQTR9b/qNp0jZm48CabPQVrqCv0PPU9LgRRRg==
 
-"@atproto/api@0.13.5":
-  version "0.13.5"
-  resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.13.5.tgz#04305cdb0a467ba366305c5e95cebb7ce0d39735"
-  integrity sha512-yT/YimcKYkrI0d282Zxo7O30OSYR+KDW89f81C6oYZfDRBcShC1aniVV8kluP5LrEAg8O27yrOSnBgx2v7XPew==
+"@atproto/api@^0.13.0":
+  version "0.13.0"
+  resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.13.0.tgz#d1c65a407f1c3c6aba5be9425f4f739a01419bd8"
+  integrity sha512-04kzIDkoEVSP7zMVOT5ezCVQcOrbXWjGYO2YBc3/tBvQ90V1pl9I+mLyz1uUHE+wRE1IRWKACcWhAz8SrYz3pA==
   dependencies:
     "@atproto/common-web" "^0.3.0"
     "@atproto/lexicon" "^0.4.1"
     "@atproto/syntax" "^0.3.0"
-    "@atproto/xrpc" "^0.6.1"
+    "@atproto/xrpc" "^0.6.0"
     await-lock "^2.2.2"
     multiformats "^9.9.0"
     tlds "^1.234.0"
 
-"@atproto/api@^0.13.0":
-  version "0.13.0"
-  resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.13.0.tgz#d1c65a407f1c3c6aba5be9425f4f739a01419bd8"
-  integrity sha512-04kzIDkoEVSP7zMVOT5ezCVQcOrbXWjGYO2YBc3/tBvQ90V1pl9I+mLyz1uUHE+wRE1IRWKACcWhAz8SrYz3pA==
+"@atproto/api@^0.13.7":
+  version "0.13.7"
+  resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.13.7.tgz#072eba2025d5251505f17b0b5d2de33749ea5ee4"
+  integrity sha512-41kSLmFWDbuPOenb52WRq1lnBkSZrL+X29tWcvEt6SZXK4xBoKAalw1MjF+oabhzff12iMtNaNvmmt2fu1L+cw==
   dependencies:
     "@atproto/common-web" "^0.3.0"
     "@atproto/lexicon" "^0.4.1"
     "@atproto/syntax" "^0.3.0"
-    "@atproto/xrpc" "^0.6.0"
+    "@atproto/xrpc" "^0.6.2"
     await-lock "^2.2.2"
     multiformats "^9.9.0"
     tlds "^1.234.0"
+    zod "^3.23.8"
 
 "@atproto/aws@^0.2.2":
   version "0.2.2"
@@ -443,10 +444,10 @@
     "@atproto/lexicon" "^0.4.1"
     zod "^3.23.8"
 
-"@atproto/xrpc@^0.6.1":
-  version "0.6.1"
-  resolved "https://registry.yarnpkg.com/@atproto/xrpc/-/xrpc-0.6.1.tgz#dcd1315c8c60eef5af2db7fa4e35a38ebc6d79d5"
-  integrity sha512-Zy5ydXEdk6sY7FDUZcEVfCL1jvbL4tXu5CcdPqbEaW6LQtk9GLds/DK1bCX9kswTGaBC88EMuqQMfkxOhp2t4A==
+"@atproto/xrpc@^0.6.2":
+  version "0.6.2"
+  resolved "https://registry.yarnpkg.com/@atproto/xrpc/-/xrpc-0.6.2.tgz#634228a7e533de01bda2214837d11574fdadad55"
+  integrity sha512-as/gb08xJb02HAGNrSQSumCe10WnOAcnM6bR6KMatQyQJuEu7OY6ZDSTM/4HfjjoxsNqdvPmbYuoUab1bKTNlA==
   dependencies:
     "@atproto/lexicon" "^0.4.1"
     zod "^3.23.8"