diff --git a/xtablo-expo/app/(home)/(tabs)/index.tsx b/xtablo-expo/app/(home)/(tabs)/index.tsx
index 23d99b9..a4d7589 100644
--- a/xtablo-expo/app/(home)/(tabs)/index.tsx
+++ b/xtablo-expo/app/(home)/(tabs)/index.tsx
@@ -1,17 +1,17 @@
import { router } from "expo-router";
import { ChannelList } from "stream-chat-expo";
-import { ChannelSort } from "stream-chat";
+import { ChannelSort, Channel } from "stream-chat";
import { useUser } from "@/providers/UserProvider";
-import {
- View,
- Text,
- StyleSheet,
- TouchableOpacity,
- StatusBar,
-} from "react-native";
+import { View, Text, StyleSheet, StatusBar } from "react-native";
import { LinearGradient } from "expo-linear-gradient";
import { Search } from "lucide-react-native";
-import React from "react";
+import React, { useMemo } from "react";
+import {
+ useSharedValue,
+ useAnimatedStyle,
+ interpolate,
+ Extrapolate,
+} from "react-native-reanimated";
import { useTablosList } from "@/hooks/tablos";
import { ColorMap } from "@/constants/colors";
import { UserTablo } from "@/types/tablos.types";
@@ -21,7 +21,7 @@ const CustomChannelAvatar = ({
channel,
tablos,
}: {
- channel: any;
+ channel: Channel;
tablos: UserTablo[];
}) => {
const tabloId = channel?.id || "";
@@ -108,25 +108,170 @@ const CustomChannelAvatar = ({
);
};
+// Custom Title Component for bigger channel names
+const CustomChannelTitle = ({ channel }: { channel: Channel }) => {
+ const channelName = channel?.data?.name || channel?.id || "Channel";
+
+ return (
+
+ {channelName}
+
+ );
+};
+
export default function HomeScreen() {
const user = useUser();
const { data: tablos } = useTablosList();
- const filters = {
- members: { $in: [user.id] },
- type: "messaging",
- };
+ // Search animation state
+ // const [isSearchVisible, setIsSearchVisible] = useState(false);
+ // const [searchQuery, setSearchQuery] = useState("");
+ // const [debouncedSearchQuery, setDebouncedSearchQuery] = useState("");
+ const searchAnimation = useSharedValue(0);
+ // const searchInputRef = useRef(null);
+
+ // // Debounce search query for better performance
+ // useEffect(() => {
+ // const timer = setTimeout(() => {
+ // setDebouncedSearchQuery(searchQuery);
+ // }, 300);
+
+ // return () => clearTimeout(timer);
+ // }, [searchQuery]);
+
+ // Create filters based on search query
+ const filters = useMemo(() => {
+ const baseFilters = {
+ members: { $in: [user.id] },
+ type: "messaging",
+ };
+
+ // Add name filter when searching
+ // if (debouncedSearchQuery.trim()) {
+ // return {
+ // ...baseFilters,
+ // name: { $autocomplete: debouncedSearchQuery.trim() },
+ // };
+ // }
+
+ return baseFilters;
+ }, [user.id]);
+
const sort: ChannelSort = { last_updated: -1 };
const options = {
state: true,
watch: true,
+ limit: 20,
};
// Create a wrapper component for the avatar that has access to tablos data
- const AvatarWithTablos = ({ channel }: { channel: any }) => (
+ const AvatarWithTablos = ({ channel }: { channel: Channel }) => (
);
+ // Toggle search animation
+ // const toggleSearch = () => {
+ // const toValue = isSearchVisible ? 0 : 1;
+
+ // searchAnimation.value = withTiming(toValue, {
+ // duration: 300,
+ // });
+
+ // if (toValue === 1) {
+ // // Focus input when animation starts
+ // setTimeout(() => searchInputRef.current?.focus(), 150);
+ // } else {
+ // // Clear search when hiding
+ // setSearchQuery("");
+ // setDebouncedSearchQuery("");
+ // }
+
+ // setIsSearchVisible(!isSearchVisible);
+ // };
+
+ // Close search when keyboard is dismissed
+ // useEffect(() => {
+ // const keyboardDidHideListener = Keyboard.addListener(
+ // "keyboardDidHide",
+ // () => {
+ // if (isSearchVisible && searchQuery === "") {
+ // toggleSearch();
+ // }
+ // }
+ // );
+
+ // return () => {
+ // keyboardDidHideListener?.remove();
+ // };
+ // }, [isSearchVisible, searchQuery]);
+
+ // Animated styles using react-native-reanimated
+ const animatedSearchStyle = useAnimatedStyle(() => {
+ const height = interpolate(
+ searchAnimation.value,
+ [0, 1],
+ [0, 80],
+ Extrapolate.CLAMP
+ );
+
+ const opacity = interpolate(
+ searchAnimation.value,
+ [0, 0.5, 1],
+ [0, 0, 1],
+ Extrapolate.CLAMP
+ );
+
+ return {
+ height,
+ opacity,
+ };
+ });
+
+ // Simple search header component - no memoization
+ // const SearchHeader = () => (
+ //
+ //
+ //
+ // {
+ // console.log("Searching for:", searchQuery);
+ // Keyboard.dismiss();
+ // }}
+ // />
+ // {searchQuery.length > 0 && (
+ // {
+ // setSearchQuery("");
+ // setDebouncedSearchQuery("");
+ // searchInputRef.current?.focus();
+ // }}
+ // style={styles.clearButton}
+ // >
+ //
+ //
+ // )}
+ //
+
+ // {/* Search Results Info */}
+ // {debouncedSearchQuery.trim() && (
+ //
+ //
+ // Recherche: "{debouncedSearchQuery}"
+ //
+ //
+ // )}
+ //
+ // );
+
return (
@@ -143,31 +288,77 @@ export default function HomeScreen() {
Discussions
+ {/* {debouncedSearchQuery.trim()
+ ? `Recherche: "${debouncedSearchQuery}"`
+ : "Gérez les conversations de vos tablos"} */}
Gérez les conversations de vos tablos
-
-
-
+ {/*
+ {isSearchVisible ? (
+
+ ) : (
+
+ )}
+ */}
- {/* Decorative Elements
+ {/* Decorative Elements */}
- */}
+
- {/* Channel List */}
+ {/* Channel List with animated search */}
+ {/* */}
{
+ // Close search when selecting a channel
+ // if (isSearchVisible) {
+ // toggleSearch();
+ // }
router.push(`/channel/${channel.cid}`);
}}
sort={sort}
options={options}
PreviewAvatar={AvatarWithTablos}
+ PreviewTitle={CustomChannelTitle}
+ // ListHeaderComponent={SearchHeader}
+ // Show loading state during search
+ LoadingIndicator={() => (
+
+
+ {/* {debouncedSearchQuery
+ ? "Recherche en cours..."
+ : "Chargement..."} */}
+ Chargement...
+
+
+ )}
+ // Show empty state when no results
+ EmptyStateIndicator={() => (
+
+
+
+ {/* {debouncedSearchQuery
+ ? "Aucun résultat"
+ : "Aucune conversation"} */}
+ Aucune conversation
+
+
+ {/* {debouncedSearchQuery
+ ? `Aucune conversation trouvée pour "${debouncedSearchQuery}"`
+ : "Vous n'avez pas encore de conversations"} */}
+ Vous n'avez pas encore de conversations
+
+
+ )}
/>
@@ -393,4 +584,75 @@ const styles = StyleSheet.create({
fontSize: 11,
fontWeight: "bold",
},
+ // Custom Channel Title Styles
+ customChannelTitle: {
+ fontSize: 18,
+ fontWeight: "bold",
+ color: "#1f2937",
+ },
+
+ // Search Header Styles
+ searchHeaderContainer: {
+ backgroundColor: "#f8fafc",
+ borderBottomWidth: 1,
+ borderBottomColor: "#e5e7eb",
+ overflow: "hidden",
+ paddingHorizontal: 20,
+ },
+ searchInputContainer: {
+ flexDirection: "row",
+ alignItems: "center",
+ backgroundColor: "white",
+ borderRadius: 8,
+ paddingHorizontal: 12,
+ paddingVertical: 8,
+ borderWidth: 1,
+ borderColor: "#e5e7eb",
+ marginTop: 15,
+ },
+ searchIcon: {
+ marginRight: 10,
+ },
+ searchInput: {
+ flex: 1,
+ fontSize: 16,
+ color: "#374151",
+ paddingVertical: 0,
+ fontWeight: "500",
+ },
+ clearButton: {
+ padding: 5,
+ },
+ searchInfoContainer: {
+ paddingTop: 10,
+ paddingBottom: 15,
+ },
+ searchInfoText: {
+ fontSize: 14,
+ color: "#6b7280",
+ },
+ searchLoadingContainer: {
+ paddingVertical: 20,
+ alignItems: "center",
+ },
+ searchLoadingText: {
+ fontSize: 16,
+ color: "#6b7280",
+ },
+ emptySearchContainer: {
+ paddingVertical: 40,
+ alignItems: "center",
+ },
+ emptySearchTitle: {
+ fontSize: 20,
+ color: "#4b5563",
+ marginTop: 10,
+ },
+ emptySearchMessage: {
+ fontSize: 16,
+ color: "#6b7280",
+ marginTop: 5,
+ textAlign: "center",
+ paddingHorizontal: 20,
+ },
});