aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMohamedBassem <me@mbassem.com>2024-03-15 21:06:13 +0000
committerMohamedBassem <me@mbassem.com>2024-03-15 21:06:13 +0000
commit267f72f84c6a5979eae696dae8fddee25188c1bb (patch)
tree704907d296f82c524c0a359c3c8e5ccab4415b3d
parentc4d7223115865474f09661cdbfee60a559f4b2c2 (diff)
downloadkarakeep-267f72f84c6a5979eae696dae8fddee25188c1bb.tar.zst
ui(mobile): New header style in the app
-rw-r--r--apps/mobile/app/dashboard/(tabs)/_layout.tsx2
-rw-r--r--apps/mobile/app/dashboard/(tabs)/index.tsx90
-rw-r--r--apps/mobile/app/dashboard/(tabs)/lists.tsx45
-rw-r--r--apps/mobile/app/dashboard/(tabs)/search.tsx36
-rw-r--r--apps/mobile/app/dashboard/(tabs)/settings.tsx24
-rw-r--r--apps/mobile/app/dashboard/_layout.tsx8
-rw-r--r--apps/mobile/app/dashboard/archive.tsx9
-rw-r--r--apps/mobile/app/dashboard/favourites.tsx13
-rw-r--r--apps/mobile/app/dashboard/lists/[slug].tsx17
-rw-r--r--apps/mobile/app/dashboard/tags/[slug].tsx19
-rw-r--r--apps/mobile/components/bookmarks/BookmarkList.tsx9
-rw-r--r--apps/mobile/components/ui/PageTitle.tsx5
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>;
+}