diff options
| author | MohamedBassem <me@mbassem.com> | 2024-03-15 21:06:13 +0000 |
|---|---|---|
| committer | MohamedBassem <me@mbassem.com> | 2024-03-15 21:06:13 +0000 |
| commit | 267f72f84c6a5979eae696dae8fddee25188c1bb (patch) | |
| tree | 704907d296f82c524c0a359c3c8e5ccab4415b3d | |
| parent | c4d7223115865474f09661cdbfee60a559f4b2c2 (diff) | |
| download | karakeep-267f72f84c6a5979eae696dae8fddee25188c1bb.tar.zst | |
ui(mobile): New header style in the app
| -rw-r--r-- | apps/mobile/app/dashboard/(tabs)/_layout.tsx | 2 | ||||
| -rw-r--r-- | apps/mobile/app/dashboard/(tabs)/index.tsx | 90 | ||||
| -rw-r--r-- | apps/mobile/app/dashboard/(tabs)/lists.tsx | 45 | ||||
| -rw-r--r-- | apps/mobile/app/dashboard/(tabs)/search.tsx | 36 | ||||
| -rw-r--r-- | apps/mobile/app/dashboard/(tabs)/settings.tsx | 24 | ||||
| -rw-r--r-- | apps/mobile/app/dashboard/_layout.tsx | 8 | ||||
| -rw-r--r-- | apps/mobile/app/dashboard/archive.tsx | 9 | ||||
| -rw-r--r-- | apps/mobile/app/dashboard/favourites.tsx | 13 | ||||
| -rw-r--r-- | apps/mobile/app/dashboard/lists/[slug].tsx | 17 | ||||
| -rw-r--r-- | apps/mobile/app/dashboard/tags/[slug].tsx | 19 | ||||
| -rw-r--r-- | apps/mobile/components/bookmarks/BookmarkList.tsx | 9 | ||||
| -rw-r--r-- | apps/mobile/components/ui/PageTitle.tsx | 5 |
12 files changed, 163 insertions, 114 deletions
diff --git a/apps/mobile/app/dashboard/(tabs)/_layout.tsx b/apps/mobile/app/dashboard/(tabs)/_layout.tsx index ce73a5c9..db6656b2 100644 --- a/apps/mobile/app/dashboard/(tabs)/_layout.tsx +++ b/apps/mobile/app/dashboard/(tabs)/_layout.tsx @@ -4,7 +4,7 @@ import { ClipboardList, Home, Search, Settings } from "lucide-react-native"; export default function TabLayout() { return ( - <Tabs screenOptions={{ tabBarActiveTintColor: "blue" }}> + <Tabs screenOptions={{ tabBarActiveTintColor: "blue", headerShown: false }}> <Tabs.Screen name="index" options={{ diff --git a/apps/mobile/app/dashboard/(tabs)/index.tsx b/apps/mobile/app/dashboard/(tabs)/index.tsx index 1736def9..1a17d472 100644 --- a/apps/mobile/app/dashboard/(tabs)/index.tsx +++ b/apps/mobile/app/dashboard/(tabs)/index.tsx @@ -1,60 +1,62 @@ -import { Platform, View } from "react-native"; +import { Platform, SafeAreaView, View } from "react-native"; import * as Haptics from "expo-haptics"; -import { Stack, useRouter } from "expo-router"; +import { useRouter } from "expo-router"; import BookmarkList from "@/components/bookmarks/BookmarkList"; import { MenuView } from "@react-native-menu/menu"; import { SquarePen } from "lucide-react-native"; +import PageTitle from "@/components/ui/PageTitle"; function HeaderRight() { const router = useRouter(); return ( - <MenuView - onPressAction={({ nativeEvent }) => { - Haptics.selectionAsync(); - if (nativeEvent.event === "note") { - router.navigate("dashboard/add-note"); - } else if (nativeEvent.event === "link") { - router.navigate("dashboard/add-link"); - } - }} - actions={[ - { - id: "link", - title: "New Link", - image: Platform.select({ - ios: "link", - android: "ic_menu_link", - }), - }, - { - id: "note", - title: "New Note", - image: Platform.select({ - ios: "note", - android: "ic_menu_note", - }), - }, - ]} - shouldOpenOnLongPress={false} - > - <View className="mt-2 px-2"> - <SquarePen - onPress={() => Haptics.selectionAsync()} - /> - </View> - </MenuView> + <MenuView + onPressAction={({ nativeEvent }) => { + Haptics.selectionAsync(); + if (nativeEvent.event === "note") { + router.navigate("dashboard/add-note"); + } else if (nativeEvent.event === "link") { + router.navigate("dashboard/add-link"); + } + }} + actions={[ + { + id: "link", + title: "New Link", + image: Platform.select({ + ios: "link", + android: "ic_menu_link", + }), + }, + { + id: "note", + title: "New Note", + image: Platform.select({ + ios: "note", + android: "ic_menu_note", + }), + }, + ]} + shouldOpenOnLongPress={false} + > + <View className="my-auto px-4"> + <SquarePen onPress={() => Haptics.selectionAsync()} /> + </View> + </MenuView> ); } export default function Home() { return ( - <> - <Stack.Screen - options={{ - headerRight: () => <HeaderRight />, - }} + <SafeAreaView> + <BookmarkList + archived={false} + header={ + <View className="flex flex-row justify-between"> + <PageTitle title="Home" /> + <HeaderRight /> + </View> + } /> - <BookmarkList archived={false} /> - </> + </SafeAreaView> ); } diff --git a/apps/mobile/app/dashboard/(tabs)/lists.tsx b/apps/mobile/app/dashboard/(tabs)/lists.tsx index 2aece541..e0ed8489 100644 --- a/apps/mobile/app/dashboard/(tabs)/lists.tsx +++ b/apps/mobile/app/dashboard/(tabs)/lists.tsx @@ -1,8 +1,9 @@ import { useEffect, useState } from "react"; -import { FlatList, View, Text, Pressable } from "react-native"; +import { FlatList, Pressable, SafeAreaView, Text, View } from "react-native"; import { Link } from "expo-router"; import { api } from "@/lib/trpc"; import { ChevronRight } from "lucide-react-native"; +import PageTitle from "@/components/ui/PageTitle"; export default function Lists() { const [refreshing, setRefreshing] = useState(false); @@ -47,24 +48,28 @@ export default function Lists() { ); return ( - <FlatList - contentContainerStyle={{ - gap: 5, - marginTop: 5, - }} - renderItem={(l) => ( - <Link asChild key={l.item.id} href={l.item.href}> - <Pressable className="mx-2 flex flex-row justify-between rounded-xl border border-gray-100 bg-white px-4 py-2"> - <Text className="text-lg"> - {l.item.logo} {l.item.name} - </Text> - <ChevronRight /> - </Pressable> - </Link> - )} - data={links} - refreshing={refreshing} - onRefresh={onRefresh} - /> + <SafeAreaView> + <FlatList + ListHeaderComponent={ + <PageTitle title="Lists" /> + } + contentContainerStyle={{ + gap: 5, + }} + renderItem={(l) => ( + <Link asChild key={l.item.id} href={l.item.href}> + <Pressable className="mx-2 flex flex-row justify-between rounded-xl border border-gray-100 bg-white px-4 py-2"> + <Text className="text-lg"> + {l.item.logo} {l.item.name} + </Text> + <ChevronRight /> + </Pressable> + </Link> + )} + data={links} + refreshing={refreshing} + onRefresh={onRefresh} + /> + </SafeAreaView> ); } diff --git a/apps/mobile/app/dashboard/(tabs)/search.tsx b/apps/mobile/app/dashboard/(tabs)/search.tsx index 043dffab..76e9aef9 100644 --- a/apps/mobile/app/dashboard/(tabs)/search.tsx +++ b/apps/mobile/app/dashboard/(tabs)/search.tsx @@ -1,11 +1,11 @@ import { useState } from "react"; -import { View } from "react-native"; +import { SafeAreaView, View } from "react-native"; import BookmarkList from "@/components/bookmarks/BookmarkList"; -import { Divider } from "@/components/ui/Divider"; import { Input } from "@/components/ui/Input"; import { api } from "@/lib/trpc"; import { keepPreviousData } from "@tanstack/react-query"; import { useDebounce } from "use-debounce"; +import PageTitle from "@/components/ui/PageTitle"; export default function Search() { const [search, setSearch] = useState(""); @@ -18,17 +18,25 @@ export default function Search() { ); return ( - <View> - <Input - placeholder="Search" - className="mx-4 mt-4 bg-white" - value={search} - onChangeText={setSearch} - autoFocus - autoCapitalize="none" - /> - <Divider orientation="horizontal" className="mt-4 w-full" /> - {data && <BookmarkList ids={data.bookmarks.map((b) => b.id)} />} - </View> + <SafeAreaView> + {data && ( + <BookmarkList + ids={data.bookmarks.map((b) => b.id)} + header={ + <View> + <PageTitle title="Search" /> + <Input + placeholder="Search" + className="mx-4 bg-white" + value={search} + onChangeText={setSearch} + autoFocus + autoCapitalize="none" + /> + </View> + } + /> + )} + </SafeAreaView> ); } diff --git a/apps/mobile/app/dashboard/(tabs)/settings.tsx b/apps/mobile/app/dashboard/(tabs)/settings.tsx index 81b21fc8..fe138f52 100644 --- a/apps/mobile/app/dashboard/(tabs)/settings.tsx +++ b/apps/mobile/app/dashboard/(tabs)/settings.tsx @@ -1,10 +1,10 @@ import { useEffect } from "react"; -import { Text, View } from "react-native"; +import { SafeAreaView, Text, View } from "react-native"; import { useRouter } from "expo-router"; -import Logo from "@/components/Logo"; import { Button } from "@/components/ui/Button"; import { useSession } from "@/lib/session"; import { api } from "@/lib/trpc"; +import PageTitle from "@/components/ui/PageTitle"; export default function Dashboard() { const router = useRouter(); @@ -26,15 +26,17 @@ export default function Dashboard() { }, [error]); return ( - <View className="flex h-full w-full items-center gap-4 p-4"> - <Logo /> - <View className="w-full rounded-lg bg-white px-4 py-2"> - <Text className="text-lg"> - {isLoading ? "Loading ..." : data?.email} - </Text> - </View> + <SafeAreaView> + <PageTitle title="Settings" /> + <View className="flex h-full w-full items-center gap-4 px-4 py-2"> + <View className="w-full rounded-lg bg-white px-4 py-2"> + <Text className="text-lg"> + {isLoading ? "Loading ..." : data?.email} + </Text> + </View> - <Button className="w-full" label="Log Out" onPress={logout} /> - </View> + <Button className="w-full" label="Log Out" onPress={logout} /> + </View> + </SafeAreaView> ); } diff --git a/apps/mobile/app/dashboard/_layout.tsx b/apps/mobile/app/dashboard/_layout.tsx index ff2384d2..bb14a203 100644 --- a/apps/mobile/app/dashboard/_layout.tsx +++ b/apps/mobile/app/dashboard/_layout.tsx @@ -10,13 +10,17 @@ export default function Dashboard() { <Stack.Screen name="favourites" options={{ - title: "⭐️ Favourites", + headerTitle: "", + headerBackTitle: "Back", + headerTransparent: true, }} /> <Stack.Screen name="archive" options={{ - title: "🗄️ Archive", + headerTitle: "", + headerBackTitle: "Back", + headerTransparent: true, }} /> <Stack.Screen diff --git a/apps/mobile/app/dashboard/archive.tsx b/apps/mobile/app/dashboard/archive.tsx index 2c559684..5c86c6fc 100644 --- a/apps/mobile/app/dashboard/archive.tsx +++ b/apps/mobile/app/dashboard/archive.tsx @@ -1,10 +1,11 @@ -import { View } from "react-native"; +import { SafeAreaView } from "react-native"; import BookmarkList from "@/components/bookmarks/BookmarkList"; +import PageTitle from "@/components/ui/PageTitle"; export default function Archive() { return ( - <View> - <BookmarkList archived /> - </View> + <SafeAreaView> + <BookmarkList archived header={<PageTitle title="🗄️ Archive" />} /> + </SafeAreaView> ); } diff --git a/apps/mobile/app/dashboard/favourites.tsx b/apps/mobile/app/dashboard/favourites.tsx index 42a139f9..6025d514 100644 --- a/apps/mobile/app/dashboard/favourites.tsx +++ b/apps/mobile/app/dashboard/favourites.tsx @@ -1,10 +1,15 @@ -import { View } from "react-native"; +import { SafeAreaView } from "react-native"; import BookmarkList from "@/components/bookmarks/BookmarkList"; +import PageTitle from "@/components/ui/PageTitle"; export default function Favourites() { return ( - <View> - <BookmarkList archived={false} favourited /> - </View> + <SafeAreaView> + <BookmarkList + archived={false} + favourited + header={<PageTitle title="⭐️ Favourites" />} + /> + </SafeAreaView> ); } diff --git a/apps/mobile/app/dashboard/lists/[slug].tsx b/apps/mobile/app/dashboard/lists/[slug].tsx index f85aeeaf..0d1c01dc 100644 --- a/apps/mobile/app/dashboard/lists/[slug].tsx +++ b/apps/mobile/app/dashboard/lists/[slug].tsx @@ -1,7 +1,8 @@ -import { View } from "react-native"; +import { SafeAreaView, View } from "react-native"; import { Stack, useLocalSearchParams } from "expo-router"; import BookmarkList from "@/components/bookmarks/BookmarkList"; import FullPageSpinner from "@/components/ui/FullPageSpinner"; +import PageTitle from "@/components/ui/PageTitle"; import { api } from "@/lib/trpc"; export default function ListView() { @@ -12,19 +13,25 @@ export default function ListView() { const { data: list } = api.lists.get.useQuery({ listId: slug }); return ( - <> + <SafeAreaView> <Stack.Screen options={{ - headerTitle: list ? `${list.icon} ${list.name}` : "Loading ...", + headerTitle: "", + headerBackTitle: "Back", + headerTransparent: true, }} /> {list ? ( <View> - <BookmarkList archived={false} ids={list.bookmarks} /> + <BookmarkList + archived={false} + ids={list.bookmarks} + header={<PageTitle title={`${list.icon} ${list.name}`} />} + /> </View> ) : ( <FullPageSpinner /> )} - </> + </SafeAreaView> ); } diff --git a/apps/mobile/app/dashboard/tags/[slug].tsx b/apps/mobile/app/dashboard/tags/[slug].tsx index 39d1a87d..2d37b172 100644 --- a/apps/mobile/app/dashboard/tags/[slug].tsx +++ b/apps/mobile/app/dashboard/tags/[slug].tsx @@ -1,10 +1,11 @@ -import { View } from "react-native"; +import { SafeAreaView, View } from "react-native"; import { Stack, useLocalSearchParams } from "expo-router"; import BookmarkList from "@/components/bookmarks/BookmarkList"; import FullPageSpinner from "@/components/ui/FullPageSpinner"; +import PageTitle from "@/components/ui/PageTitle"; import { api } from "@/lib/trpc"; -export default function ListView() { +export default function TagView() { const { slug } = useLocalSearchParams(); if (typeof slug !== "string") { throw new Error("Unexpected param type"); @@ -13,19 +14,25 @@ export default function ListView() { const { data: tag } = api.tags.get.useQuery({ tagId: slug }); return ( - <> + <SafeAreaView> <Stack.Screen options={{ - headerTitle: tag ? `${tag.name}` : "Loading ...", + headerTitle: "", + headerBackTitle: "Back", + headerTransparent: true, }} /> {tag ? ( <View> - <BookmarkList archived={false} ids={tag.bookmarks} /> + <BookmarkList + archived={false} + ids={tag.bookmarks} + header={<PageTitle title={tag.name} />} + /> </View> ) : ( <FullPageSpinner /> )} - </> + </SafeAreaView> ); } diff --git a/apps/mobile/components/bookmarks/BookmarkList.tsx b/apps/mobile/components/bookmarks/BookmarkList.tsx index 48272fb3..04a3d922 100644 --- a/apps/mobile/components/bookmarks/BookmarkList.tsx +++ b/apps/mobile/components/bookmarks/BookmarkList.tsx @@ -1,20 +1,22 @@ import { useEffect, useRef, useState } from "react"; -import { Text, View, Keyboard } from "react-native"; +import { Keyboard, Text, View } from "react-native"; import Animated, { LinearTransition } from "react-native-reanimated"; import { api } from "@/lib/trpc"; +import { useScrollToTop } from "@react-navigation/native"; import FullPageSpinner from "../ui/FullPageSpinner"; import BookmarkCard from "./BookmarkCard"; -import { useScrollToTop } from '@react-navigation/native'; export default function BookmarkList({ favourited, archived, ids, + header }: { favourited?: boolean; archived?: boolean; ids?: string[]; + header?: React.ReactElement; }) { const apiUtils = api.useUtils(); const [refreshing, setRefreshing] = useState(false); @@ -44,13 +46,14 @@ export default function BookmarkList({ <Animated.FlatList ref={flatListRef} itemLayoutAnimation={LinearTransition} + ListHeaderComponent={header} contentContainerStyle={{ gap: 15, marginBottom: 15, }} renderItem={(b) => <BookmarkCard bookmark={b.item} />} ListEmptyComponent={ - <View className="h-full pt-4 items-center justify-center"> + <View className="items-center justify-center pt-4"> <Text className="text-xl">No Bookmarks</Text> </View> } diff --git a/apps/mobile/components/ui/PageTitle.tsx b/apps/mobile/components/ui/PageTitle.tsx new file mode 100644 index 00000000..1d1a8400 --- /dev/null +++ b/apps/mobile/components/ui/PageTitle.tsx @@ -0,0 +1,5 @@ +import {Text} from "react-native"; + +export default function PageTitle({ title }: { title: string }) { + return <Text className="p-4 text-4xl font-bold">{title}</Text>; +} |
