frontend client for gemstone. decentralised workplace app
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor: move chat component

serenity d10792b1 5227d5f7

+165 -15
+3 -5
src/app/(protected)/index.tsx
··· 1 - import ChatComponentProfiled from "@/components/ChatComponentProfiled"; 1 + import { Chat } from "@/components/Chat"; 2 2 import { Loading } from "@/components/primitives/Loading"; 3 3 import { useChannelRecords } from "@/providers/authed/ChannelsProvider"; 4 4 import { useSessions } from "@/providers/authed/SessionsProvider"; ··· 14 14 style={{ 15 15 flex: 1, 16 16 justifyContent: "center", 17 - alignItems: "center", 17 + alignItems: "stretch", 18 18 }} 19 19 > 20 20 {isAppReady ? ( 21 - <ChatComponentProfiled 22 - channelAtUri={channels[0].channelAtUri} 23 - /> 21 + <Chat channelAtUri={channels[0].channelAtUri} /> 24 22 ) : ( 25 23 <Loading /> 26 24 )}
+156
src/components/Chat/index.tsx
··· 1 + import { Message } from "@/components/Message"; 2 + import { Loading } from "@/components/primitives/Loading"; 3 + import { Text } from "@/components/primitives/Text"; 4 + import { useChannel } from "@/lib/hooks/useChannel"; 5 + import type { AtUri } from "@/lib/types/atproto"; 6 + import { useProfile } from "@/providers/authed/ProfileProvider"; 7 + import { useState } from "react"; 8 + import { 9 + View, 10 + TextInput, 11 + TouchableOpacity, 12 + StyleSheet, 13 + ScrollView, 14 + Image, 15 + } from "react-native"; 16 + 17 + export const Chat = ({ channelAtUri }: { channelAtUri: AtUri }) => { 18 + const [inputText, setInputText] = useState(""); 19 + const { messages, sendMessageToChannel, isConnected } = 20 + useChannel(channelAtUri); 21 + 22 + const handleSend = () => { 23 + if (inputText.trim()) { 24 + sendMessageToChannel(inputText); 25 + setInputText(""); 26 + } 27 + }; 28 + 29 + const { profile, isLoading } = useProfile(); 30 + 31 + return isLoading ? ( 32 + <Loading /> 33 + ) : ( 34 + <View style={{ flex: 1, flexDirection: "column" }}> 35 + {profile && ( 36 + <View> 37 + <View style={styles.profile}> 38 + <Text> 39 + Hi, {profile.displayName ?? profile.handle}! 40 + </Text> 41 + {profile.avatar && ( 42 + <Image 43 + style={styles.avatar} 44 + source={{ uri: profile.avatar }} 45 + /> 46 + )} 47 + </View> 48 + </View> 49 + )} 50 + <View style={styles.header}> 51 + <Text style={styles.status}> 52 + {isConnected ? "🟢 Connected" : "🔴 Disconnected"} 53 + </Text> 54 + </View> 55 + 56 + <ScrollView style={styles.messagesContainer}> 57 + {messages.map((msg, index) => ( 58 + <Message message={msg} key={index} /> 59 + ))} 60 + </ScrollView> 61 + 62 + <View style={styles.inputContainer}> 63 + <TextInput 64 + style={styles.input} 65 + value={inputText} 66 + onChangeText={setInputText} 67 + placeholder="boop" 68 + onSubmitEditing={handleSend} 69 + /> 70 + <TouchableOpacity 71 + style={styles.button} 72 + onPress={handleSend} 73 + disabled={!isConnected} 74 + > 75 + <Text style={styles.buttonText}>Send</Text> 76 + </TouchableOpacity> 77 + </View> 78 + </View> 79 + ); 80 + }; 81 + 82 + const styles = StyleSheet.create({ 83 + container: { 84 + flex: 1, 85 + backgroundColor: "#fff", 86 + }, 87 + profile: { 88 + display: "flex", 89 + flexDirection: "row", 90 + justifyContent: "space-between", 91 + padding: 16, 92 + borderBottomWidth: 1, 93 + borderBottomColor: "#e0e0e0", 94 + alignItems: "center", 95 + }, 96 + avatar: { 97 + width: 32, 98 + height: 32, 99 + borderRadius: 2000000000, 100 + }, 101 + header: { 102 + padding: 16, 103 + borderBottomWidth: 1, 104 + borderBottomColor: "#e0e0e0", 105 + }, 106 + status: { 107 + fontSize: 14, 108 + fontWeight: "600", 109 + }, 110 + messagesContainer: { 111 + flex: 1, 112 + padding: 16, 113 + }, 114 + messageItem: { 115 + marginBottom: 12, 116 + padding: 12, 117 + backgroundColor: "#f5f5f5", 118 + borderRadius: 8, 119 + }, 120 + messageText: { 121 + fontSize: 16, 122 + marginBottom: 4, 123 + }, 124 + timestamp: { 125 + fontSize: 12, 126 + color: "#666", 127 + }, 128 + inputContainer: { 129 + flexDirection: "row", 130 + padding: 16, 131 + borderTopWidth: 1, 132 + borderTopColor: "#e0e0e0", 133 + }, 134 + input: { 135 + flex: 1, 136 + borderWidth: 1, 137 + borderColor: "#ccc", 138 + borderRadius: 8, 139 + paddingHorizontal: 12, 140 + paddingVertical: 8, 141 + marginRight: 8, 142 + fontSize: 16, 143 + }, 144 + button: { 145 + backgroundColor: "#007AFF", 146 + paddingHorizontal: 20, 147 + paddingVertical: 10, 148 + borderRadius: 8, 149 + justifyContent: "center", 150 + }, 151 + buttonText: { 152 + color: "#fff", 153 + fontSize: 16, 154 + fontWeight: "600", 155 + }, 156 + });
+6 -10
src/components/ChatComponentProfiled.tsx src/components/Chat/index.web.tsx
··· 1 - import { Loading } from "@/components/Loading"; 2 1 import { Message } from "@/components/Message"; 2 + import { Loading } from "@/components/primitives/Loading"; 3 + import { Text } from "@/components/primitives/Text"; 3 4 import { useChannel } from "@/lib/hooks/useChannel"; 4 5 import type { AtUri } from "@/lib/types/atproto"; 5 6 import { useProfile } from "@/providers/authed/ProfileProvider"; 6 7 import { useState } from "react"; 7 8 import { 8 9 View, 9 - Text, 10 10 TextInput, 11 11 TouchableOpacity, 12 12 StyleSheet, ··· 14 14 Image, 15 15 } from "react-native"; 16 16 17 - export default function ChatComponentProfiled({ 18 - channelAtUri, 19 - }: { 20 - channelAtUri: AtUri; 21 - }) { 17 + export const Chat = ({ channelAtUri }: { channelAtUri: AtUri }) => { 22 18 const [inputText, setInputText] = useState(""); 23 19 const { messages, sendMessageToChannel, isConnected } = 24 20 useChannel(channelAtUri); ··· 35 31 return isLoading ? ( 36 32 <Loading /> 37 33 ) : ( 38 - <View style={styles.container}> 34 + <View style={{ flex: 1, flexDirection: "column" }}> 39 35 {profile && ( 40 36 <View> 41 37 <View style={styles.profile}> ··· 68 64 style={styles.input} 69 65 value={inputText} 70 66 onChangeText={setInputText} 71 - placeholder="Type a message..." 67 + placeholder="boop" 72 68 onSubmitEditing={handleSend} 73 69 /> 74 70 <TouchableOpacity ··· 81 77 </View> 82 78 </View> 83 79 ); 84 - } 80 + }; 85 81 86 82 const styles = StyleSheet.create({ 87 83 container: {