Your music, beautifully tracked. All yours. (coming soon) teal.fm
teal-fm atproto

add more info + did changer in settings

Natalie B ab00c4c8 18a0d2f9

+163
+163
apps/amethyst/app/(tabs)/settings/index.tsx
··· 1 + import React, { useState } from "react"; 2 + import { Text } from "@/components/ui/text"; 3 + import { ScrollView, Switch, View } from "react-native"; 4 + import { Link, Stack } from "expo-router"; 5 + import { useColorScheme } from "@/lib/useColorScheme"; 6 + import { cn } from "@/lib/utils"; 7 + import { Button } from "@/components/ui/button"; 8 + 9 + import pkg from "@/package.json"; 10 + import { useStore } from "@/stores/mainStore"; 11 + import { Input } from "@/components/ui/input"; 12 + 13 + export default function Settings() { 14 + const { colorScheme, setColorScheme } = useColorScheme(); 15 + const appviewDid = useStore((state) => state.tealDid); 16 + const setAppviewDid = useStore((state) => state.setTealDid); 17 + 18 + const colorSchemeOptions = [ 19 + { label: "Light", value: "light" }, 20 + { label: "Dark", value: "dark" }, 21 + { label: "System", value: "system" }, 22 + ]; 23 + 24 + return ( 25 + <ScrollView className="flex-1 justify-start items-center gap-5 bg-background w-full"> 26 + <Stack.Screen 27 + options={{ 28 + title: "Settings", 29 + headerBackButtonDisplayMode: "minimal", 30 + headerShown: true, 31 + }} 32 + /> 33 + <View className="max-w-2xl flex-1 w-screen flex flex-col p-4 divide-y divide-muted-foreground/50 gap-4 rounded-xl my-2 mx-5"> 34 + <ButtonSelector 35 + text="Theme" 36 + values={colorSchemeOptions} 37 + selectedValue={colorScheme} 38 + setSelectedValue={setColorScheme} 39 + /> 40 + <TextInputRow 41 + labelText="Appview DID" 42 + initialValue={appviewDid || ""} // Ensure currentValue is a string 43 + onSubmit={(e) => setAppviewDid(e)} 44 + placeholder="Enter your Appview DID (e.g., did:plc:...)" 45 + /> 46 + <Link href="/auth/logoutModal" asChild> 47 + <Button variant="destructive" size="sm" className="w-max pb-1"> 48 + <Text>Sign out</Text> 49 + </Button> 50 + </Link> 51 + <View> 52 + <Text className="text-muted-foreground"> 53 + teal.fm amethyst ver. {pkg.version} 54 + </Text> 55 + <Text className="text-muted-foreground"> 56 + react native{" "} 57 + {pkg.dependencies["react-native"] 58 + .replace("~", "") 59 + .split(".") 60 + .slice(0, 2) 61 + .join(".")} 62 + , expo {pkg.dependencies.expo.split(".")[0].replace("~", "")}. 63 + </Text> 64 + </View> 65 + </View> 66 + </ScrollView> 67 + ); 68 + } 69 + 70 + function ToggleSwitch({ 71 + text, 72 + isEnabled, 73 + setIsEnabled, 74 + }: { 75 + text: string; 76 + isEnabled: boolean; 77 + setIsEnabled: React.Dispatch<React.SetStateAction<boolean>>; 78 + }) { 79 + const toggleSwitch = () => 80 + setIsEnabled((previousState: boolean) => !previousState); 81 + 82 + return ( 83 + <View className="flex-row items-center justify-between"> 84 + <Text className="text-lg">{text}</Text> 85 + <Switch className="ml-4" value={isEnabled} onValueChange={toggleSwitch} /> 86 + </View> 87 + ); 88 + } 89 + 90 + /// A selector component for smaller selections (usu. <3 values) 91 + function ButtonSelector({ 92 + text, 93 + values, 94 + selectedValue, 95 + setSelectedValue, 96 + }: { 97 + text: string; 98 + values: { label: string; value: string }[]; 99 + selectedValue: string; 100 + setSelectedValue: (value: any) => void; 101 + }) { 102 + return ( 103 + <View className="items-start gap-2 pt-2"> 104 + <Text className="text-base font-semibold">{text}</Text> 105 + <View className="flex-row items-center justify-around gap-1 w-full bg-muted h-10 px-1 rounded-xl"> 106 + {values.map(({ label, value }) => ( 107 + <Button 108 + key={value} 109 + onPress={() => setSelectedValue(value)} 110 + className={`flex-1 w-full h-8`} 111 + variant={selectedValue === value ? "secondary" : "ghost"} 112 + > 113 + <Text 114 + className={cn( 115 + selectedValue === value 116 + ? "text-foreground" 117 + : "text-muted-foreground", 118 + )} 119 + > 120 + {label} 121 + </Text> 122 + </Button> 123 + ))} 124 + </View> 125 + </View> 126 + ); 127 + } 128 + 129 + function TextInputRow({ 130 + labelText, 131 + initialValue = "", // Added initialValue prop, defaults to empty string 132 + onSubmit, 133 + placeholder, 134 + }: { 135 + labelText: string; 136 + initialValue?: string; // Made initialValue optional 137 + onSubmit: (value: string) => void; // onSubmit now takes the string value 138 + placeholder?: string; 139 + }) { 140 + const [inputValue, setInputValue] = useState(initialValue); // Internal state for the input 141 + 142 + const handleSubmit = () => { 143 + onSubmit(inputValue); 144 + }; 145 + 146 + return ( 147 + <View className="items-start gap-2 pt-2"> 148 + <Text className="text-base font-semibold">{labelText}</Text> 149 + <View className="flex-row gap-2 w-full items-center"> 150 + <Input 151 + className="border border-muted-foreground/50 bg-transparent text-foreground h-10 w-full rounded-md px-3 py-2 text-base" 152 + value={inputValue} 153 + onChangeText={setInputValue} // Update internal state on change 154 + placeholder={placeholder} 155 + placeholderTextColor="hsl(var(--muted-foreground))" 156 + /> 157 + <Button onPress={handleSubmit} size="sm"> 158 + <Text>Submit</Text> 159 + </Button> 160 + </View> 161 + </View> 162 + ); 163 + }