···
1
+
import { Loading } from "@/components/primitives/Loading";
import { Text } from "@/components/primitives/Text";
2
-
import { View } from "react-native";
3
+
import { useFacet } from "@/lib/facet";
4
+
import type { AtUri, DidPlc, DidWeb } from "@/lib/types/atproto";
5
+
import { systemsGmstnDevelopmentChannelInviteRecordSchema } from "@/lib/types/lexicon/systems.gmstn.development.channel.invite";
6
+
import { partition } from "@/lib/utils/arrays";
8
+
getCommitFromFullAtUri,
9
+
getRecordFromFullAtUri,
11
+
} from "@/lib/utils/atproto";
12
+
import { addMembership } from "@/lib/utils/gmstn";
13
+
import { useMemberships } from "@/providers/authed/MembershipsProvider";
15
+
useOAuthAgentGuaranteed,
16
+
useOAuthSessionGuaranteed,
17
+
} from "@/providers/OAuthProvider";
18
+
import { useCurrentPalette } from "@/providers/ThemeProvider";
19
+
import { useConstellationInvitesQuery } from "@/queries/hooks/useConstellationInvitesQuery";
20
+
import { useMutation, useQueryClient } from "@tanstack/react-query";
21
+
import { Check, Mail, MailOpen, X } from "lucide-react-native";
22
+
import { FlatList, Pressable, View } from "react-native";
23
+
import z from "zod";
export const Invites = () => {
26
+
const { semantic } = useCurrentPalette();
27
+
const { atoms, typography } = useFacet();
28
+
const { memberships } = useMemberships();
29
+
const session = useOAuthSessionGuaranteed();
30
+
const { useQuery } =
31
+
useConstellationInvitesQuery(session);
33
+
const { data: invites, isLoading } = useQuery();
35
+
console.log(invites);
37
+
const membershipAtUris: Array<Required<AtUri>> = memberships
38
+
.map((membershipRecord) => {
39
+
const res = stringToAtUri(membershipRecord.membership.invite.uri);
40
+
if (!res.ok) return;
41
+
return res.data as Required<AtUri>;
43
+
.filter((membership) => membership !== undefined);
45
+
const [existingInvites, pendingInvites] = partition(
46
+
invites?.invites ?? [],
48
+
membershipAtUris.some(
49
+
(membership) => invite.rkey === membership.rKey,
53
+
console.log({existingInvites, pendingInvites})
···
72
+
borderColor: semantic.borderVariant,
73
+
borderRadius: atoms.radii.lg,
75
+
paddingVertical: 16,
82
+
flexDirection: "row",
83
+
alignItems: "center",
91
+
color={semantic.text}
95
+
typography.weights.byName.medium,
96
+
typography.sizes.xl,
103
+
contentContainerStyle={{ gap: 4 }}
104
+
data={pendingInvites}
105
+
renderItem={({ item: invite }) => (
108
+
authority: invite.did as
111
+
collection: invite.collection,
121
+
borderColor: semantic.borderVariant,
122
+
borderRadius: atoms.radii.lg,
124
+
paddingVertical: 16,
131
+
flexDirection: "row",
132
+
alignItems: "center",
140
+
color={semantic.text}
144
+
typography.weights.byName.medium,
145
+
typography.sizes.xl,
152
+
data={existingInvites}
153
+
renderItem={({ item: invite }) => (
155
+
<Text>{invite.rkey}</Text>
166
+
const PendingInvite = ({ inviteAtUri }: { inviteAtUri: Required<AtUri> }) => {
167
+
const { semantic } = useCurrentPalette();
168
+
const { atoms } = useFacet();
169
+
const session = useOAuthSessionGuaranteed();
170
+
const agent = useOAuthAgentGuaranteed();
171
+
const { queryKey: constellationInvitesQueryKey } =
172
+
useConstellationInvitesQuery(session);
173
+
const queryClient = useQueryClient();
175
+
const queryKeysToInvalidate = constellationInvitesQueryKey.concat(["membership", session.did])
177
+
const { mutate: mutateInvites, error: inviteMutationError } = useMutation({
178
+
mutationFn: async (state: "accepted" | "rejected") => {
179
+
const inviteCommitRes = await getCommitFromFullAtUri(inviteAtUri);
180
+
if (!inviteCommitRes.ok)
182
+
"Could not resolve invite record from user's PDS.",
184
+
const { data: inviteCommit } = inviteCommitRes;
187
+
success: parseSuccess,
189
+
data: inviteRecordParsed,
190
+
} = systemsGmstnDevelopmentChannelInviteRecordSchema.safeParse(
191
+
inviteCommit.value,
195
+
`Could not validate invite record schema. ${z.prettifyError(parseError)}`,
198
+
const { uri, cid } = inviteCommit;
201
+
"Invite commit record did not have a cid somehow. Ensure that the data on PDS is not malformed.",
204
+
const creationResult = await addMembership({
207
+
channel: inviteRecordParsed.channel,
216
+
if(!creationResult.ok) throw new Error(`Error when submitting data. Check the inputs. ${creationResult.error}`)
218
+
onSuccess: async () => {
219
+
await queryClient.invalidateQueries({
220
+
queryKey: queryKeysToInvalidate,
224
+
// TODO: handle error
229
+
<View style={{ flexDirection: "row", alignItems: "center", gap: 2 }}>
230
+
<Text>{inviteAtUri.rKey}</Text>
231
+
<Pressable style={{ marginLeft: 2 }} onPress={() => {
232
+
mutateInvites("accepted")
234
+
{({ hovered }) => (
238
+
color={semantic.positive}
240
+
backgroundColor: hovered
241
+
? semantic.surfaceVariant
242
+
: semantic.surface,
244
+
borderRadius: atoms.radii.sm,
249
+
<Pressable style={{ marginLeft: 2 }} onPress={() => {
250
+
mutateInvites("rejected")
252
+
{({ hovered }) => (
256
+
color={semantic.negative}
258
+
backgroundColor: hovered
259
+
? semantic.surfaceVariant
260
+
: semantic.surface,
262
+
borderRadius: atoms.radii.sm,