···
1
+
import { Loading } from "@/components/primitives/Loading";
2
+
import { Text } from "@/components/primitives/Text";
3
+
import { useFacet } from "@/lib/facet";
4
+
import { lighten } from "@/lib/facet/src/lib/colors";
5
+
import type { ComAtprotoRepoStrongRef } from "@/lib/types/atproto";
7
+
useOAuthAgentGuaranteed,
8
+
useOAuthSessionGuaranteed,
9
+
} from "@/providers/OAuthProvider";
10
+
import { useCurrentPalette } from "@/providers/ThemeProvider";
11
+
import { useChannelsQuery } from "@/queries/hooks/useChannelsQuery";
12
+
import { useLatticesQuery } from "@/queries/hooks/useLatticesQuery";
13
+
import { useShardsQuery } from "@/queries/hooks/useShardsQuery";
14
+
import { Picker } from "@react-native-picker/picker";
15
+
import { useMutation, useQueryClient } from "@tanstack/react-query";
16
+
import type { Dispatch, SetStateAction } from "react";
17
+
import { useState } from "react";
18
+
import { Pressable, TextInput, View } from "react-native";
20
+
export const AddChannelModalContent = ({
23
+
setShowAddModal: Dispatch<SetStateAction<boolean>>;
25
+
const { semantic } = useCurrentPalette();
26
+
const { atoms, typography } = useFacet();
27
+
const [name, setName] = useState("");
28
+
const [topic, setTopic] = useState("");
29
+
const [mutationError, setMutationError] = useState<string | undefined>(
33
+
const agent = useOAuthAgentGuaranteed();
34
+
const session = useOAuthSessionGuaranteed();
35
+
const queryClient = useQueryClient();
36
+
const { useQuery: useLatticesQueryActual } = useLatticesQuery(session);
37
+
const { useQuery: useShardsQueryActual } = useShardsQuery(session);
38
+
const { queryKey: channelsQueryKey } = useChannelsQuery(session);
40
+
const { data: lattices, isLoading: latticesLoading } =
41
+
useLatticesQueryActual();
42
+
const { data: shards, isLoading: shardsLoading } = useShardsQueryActual();
44
+
const { mutate: newChannelMutation, isPending: mutationPending } =
46
+
mutationFn: async () => {
47
+
// const registerResult = await registerNewChannel({
48
+
// channelDomain: inputText,
51
+
// if (!registerResult.ok) {
53
+
// "Something went wrong when registering the channel.",
54
+
// registerResult.error,
57
+
// `Something went wrong when registering the channel. ${registerResult.error}`,
60
+
// setShowAddModal(false);
62
+
onSuccess: async () => {
63
+
await queryClient.invalidateQueries({
64
+
queryKey: channelsQueryKey,
66
+
setShowAddModal(false);
70
+
"Something went wrong when registering the channel.",
73
+
setMutationError(err.message);
77
+
const selectableShards = shards
78
+
? shards.map((shard) => ({
79
+
domain: shard.uri.rKey,
86
+
const selectableLattices = lattices
87
+
? lattices.map((lattice) => ({
88
+
domain: lattice.uri.rKey,
91
+
uri: lattice.uriStr,
96
+
const [selectedShard, setSelectedShard] = useState<
97
+
Omit<ComAtprotoRepoStrongRef, "$type">
98
+
>(selectableShards[0].ref);
99
+
const [selectedLattice, setSelectedLattice] = useState<
100
+
Omit<ComAtprotoRepoStrongRef, "$type">
101
+
>(selectableLattices[0].ref);
103
+
const isLoading = latticesLoading && shardsLoading;
105
+
selectedShard: JSON.stringify(selectedShard),
106
+
selectedLattice: JSON.stringify(selectedLattice),
110
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- must explicitly check because we are deriving from an array.
111
+
const readyToSubmit = !!(selectedShard && selectedLattice && name.trim());
116
+
backgroundColor: semantic.surface,
117
+
borderRadius: atoms.radii.lg,
127
+
<View style={{ gap: 4 }}>
134
+
borderColor: semantic.borderVariant,
136
+
paddingHorizontal: 10,
137
+
paddingVertical: 10,
138
+
color: semantic.text,
140
+
fontFamily: typography.families.primary,
143
+
typography.weights.byName.extralight,
144
+
typography.sizes.sm,
147
+
onChangeText={(newName) => {
148
+
const coerced = newName
150
+
.replace(" ", "-");
153
+
placeholder="general"
154
+
placeholderTextColor={semantic.textPlaceholder}
157
+
<View style={{ gap: 4 }}>
158
+
<Text>(optional) Topic:</Text>
164
+
borderColor: semantic.borderVariant,
166
+
paddingHorizontal: 10,
167
+
paddingVertical: 10,
168
+
color: semantic.text,
170
+
fontFamily: typography.families.primary,
173
+
typography.weights.byName.extralight,
174
+
typography.sizes.sm,
177
+
onChangeText={setTopic}
178
+
placeholder="General discussion channel"
179
+
placeholderTextColor={semantic.textPlaceholder}
182
+
<View style={{ gap: 4 }}>
183
+
<Text>Shard (store at):</Text>
184
+
{/* TODO: for native, we want to render this with a bottom sheet instead*/}
188
+
? shards.map((shard) => ({
189
+
domain: shard.uri.rKey,
193
+
$type: "com.atproto.repo.strongRef",
198
+
setSelectedShard={setSelectedShard}
201
+
<View style={{ gap: 4 }}>
202
+
<Text>Lattice (route through):</Text>
203
+
{/* TODO: for native, we want to render this with a bottom sheet instead*/}
207
+
? lattices.map((lattice) => ({
208
+
domain: lattice.uri.rKey,
211
+
uri: lattice.uriStr,
212
+
$type: "com.atproto.repo.strongRef",
217
+
setSelectedLattice={setSelectedLattice}
221
+
disabled={!readyToSubmit}
223
+
newChannelMutation();
227
+
mutationPending ? (
228
+
<Loading size="small" />
232
+
backgroundColor: readyToSubmit
234
+
? lighten(semantic.primary, 7)
236
+
: semantic.textPlaceholder,
237
+
borderRadius: atoms.radii.lg,
238
+
alignItems: "center",
239
+
paddingVertical: 10,
244
+
typography.weights.byName.normal,
245
+
{ color: semantic.textInverse },
260
+
const SelectShard = ({
266
+
ref: ComAtprotoRepoStrongRef;
268
+
setSelectedShard: Dispatch<SetStateAction<ComAtprotoRepoStrongRef>>;
272
+
onValueChange={(_, idx) => {
273
+
setSelectedShard(shards[idx].ref);
276
+
{shards.map((shard) => (
277
+
<Picker.Item label={shard.domain} key={shard.domain} />
283
+
const SelectLattices = ({
285
+
setSelectedLattice,
289
+
ref: ComAtprotoRepoStrongRef;
291
+
setSelectedLattice: Dispatch<SetStateAction<ComAtprotoRepoStrongRef>>;
295
+
onValueChange={(_, idx) => {
296
+
setSelectedLattice(lattices[idx].ref);
299
+
{lattices.map((lattice) => (
300
+
<Picker.Item label={lattice.domain} key={lattice.domain} />