frontend client for gemstone. decentralised workplace app
1
fork

Configure Feed

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

feat: profile differentiation

serenity 16cdcb45 effbf7dd

+148
+21
app/[slug].tsx
··· 1 + import ChatComponentProfiled from "@/app/components/ChatComponentProfiled"; 2 + import { capitalise } from "@/app/lib/utils/strings"; 3 + import { useLocalSearchParams } from "expo-router"; 4 + import { Text, View } from "react-native"; 5 + 6 + export default function Index() { 7 + const { slug } = useLocalSearchParams(); 8 + const name = typeof slug === "string" ? slug : slug[0]; 9 + return ( 10 + <View 11 + style={{ 12 + flex: 1, 13 + justifyContent: "center", 14 + alignItems: "center", 15 + }} 16 + > 17 + <Text>Hi, {capitalise(name)}!</Text> 18 + <ChatComponentProfiled /> 19 + </View> 20 + ); 21 + }
+124
app/components/ChatComponentProfiled.tsx
··· 1 + import { useWebSocket } from "@/app/hooks/useWebSocket"; 2 + import { useState } from "react"; 3 + import { 4 + View, 5 + Text, 6 + TextInput, 7 + TouchableOpacity, 8 + StyleSheet, 9 + ScrollView, 10 + } from "react-native"; 11 + 12 + export default function ChatComponentProfiled() { 13 + const [inputText, setInputText] = useState(""); 14 + const { messages, isConnected, sendMessage } = useWebSocket( 15 + "ws://localhost:8080", 16 + ); 17 + 18 + const handleSend = () => { 19 + if (inputText.trim()) { 20 + sendMessage(inputText); 21 + setInputText(""); 22 + } 23 + }; 24 + 25 + return ( 26 + <View style={styles.container}> 27 + <View style={styles.header}> 28 + <Text style={styles.status}> 29 + {isConnected ? "🟢 Connected" : "🔴 Disconnected"} 30 + </Text> 31 + </View> 32 + 33 + <ScrollView style={styles.messagesContainer}> 34 + {messages.map((msg, index) => ( 35 + <View key={index} style={styles.messageItem}> 36 + <Text style={styles.messageText}>{msg.text}</Text> 37 + <Text style={styles.timestamp}> 38 + {new Date(msg.timestamp).toLocaleTimeString()} 39 + </Text> 40 + </View> 41 + ))} 42 + </ScrollView> 43 + 44 + <View style={styles.inputContainer}> 45 + <TextInput 46 + style={styles.input} 47 + value={inputText} 48 + onChangeText={setInputText} 49 + placeholder="Type a message..." 50 + onSubmitEditing={handleSend} 51 + /> 52 + <TouchableOpacity 53 + style={styles.button} 54 + onPress={handleSend} 55 + disabled={!isConnected} 56 + > 57 + <Text style={styles.buttonText}>Send</Text> 58 + </TouchableOpacity> 59 + </View> 60 + </View> 61 + ); 62 + } 63 + 64 + const styles = StyleSheet.create({ 65 + container: { 66 + flex: 1, 67 + backgroundColor: "#fff", 68 + }, 69 + header: { 70 + padding: 16, 71 + borderBottomWidth: 1, 72 + borderBottomColor: "#e0e0e0", 73 + }, 74 + status: { 75 + fontSize: 14, 76 + fontWeight: "600", 77 + }, 78 + messagesContainer: { 79 + flex: 1, 80 + padding: 16, 81 + }, 82 + messageItem: { 83 + marginBottom: 12, 84 + padding: 12, 85 + backgroundColor: "#f5f5f5", 86 + borderRadius: 8, 87 + }, 88 + messageText: { 89 + fontSize: 16, 90 + marginBottom: 4, 91 + }, 92 + timestamp: { 93 + fontSize: 12, 94 + color: "#666", 95 + }, 96 + inputContainer: { 97 + flexDirection: "row", 98 + padding: 16, 99 + borderTopWidth: 1, 100 + borderTopColor: "#e0e0e0", 101 + }, 102 + input: { 103 + flex: 1, 104 + borderWidth: 1, 105 + borderColor: "#ccc", 106 + borderRadius: 8, 107 + paddingHorizontal: 12, 108 + paddingVertical: 8, 109 + marginRight: 8, 110 + fontSize: 16, 111 + }, 112 + button: { 113 + backgroundColor: "#007AFF", 114 + paddingHorizontal: 20, 115 + paddingVertical: 10, 116 + borderRadius: 8, 117 + justifyContent: "center", 118 + }, 119 + buttonText: { 120 + color: "#fff", 121 + fontSize: 16, 122 + fontWeight: "600", 123 + }, 124 + });
+3
app/lib/utils/strings.ts
··· 1 + export const capitalise = (str: string) => { 2 + return str.charAt(0).toUpperCase() + str.slice(1); 3 + };