Skip to content

Commit

Permalink
feat: complete recent viewed feature
Browse files Browse the repository at this point in the history
  • Loading branch information
obeim committed Feb 2, 2024
1 parent b9eabe7 commit 1fcc0ed
Show file tree
Hide file tree
Showing 21 changed files with 172 additions and 38 deletions.
7 changes: 3 additions & 4 deletions app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import { openDatabase } from "@/db/utils";
import { QueryClient, QueryClientProvider } from "react-query";

SplashScreen.preventAutoHideAsync();

export default function RootLayout(): ReactNode {
const queryClient = new QueryClient();

const [fontsLoaded, fontError] = useFonts({
"HelveticaNeueLTArabic-Bold": require("../assets/fonts/HelveticaNeueLTArabic-Bold.ttf"),
"HelveticaNeueLTArabic-Roman": require("../assets/fonts/HelveticaNeueLTArabic-Roman.ttf"),
Expand All @@ -31,8 +32,6 @@ export default function RootLayout(): ReactNode {
return null;
}

const queryClient = new QueryClient();

return (
<QueryClientProvider client={queryClient}>
<SafeAreaView
Expand All @@ -45,7 +44,7 @@ export default function RootLayout(): ReactNode {
screenOptions={{
headerShown: false,
contentStyle: { padding: 0, margin: 0, backgroundColor: "white" },
animation: "slide_from_right",
animation: "slide_from_bottom",
}}
/>
</SafeAreaView>
Expand Down
9 changes: 9 additions & 0 deletions contexts/RecentContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Recent } from "@/types";
import { createContext } from "react";

export default createContext<RecentContextType>({ setRecent: () => {} });

export interface RecentContextType {
recent?: Recent;
setRecent: (recent: Recent) => void;
}
2 changes: 1 addition & 1 deletion db/repos/AyatRepo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const getAyatAsJozz = async (id: number) => {
});
ayat = ayat.map((aya, index) => {
if (index > 0 && aya.sora === ayat[index - 1].sora)
return { ...aya, sora_name_ar: "no" };
return { ...aya, sora_name_ar: `${aya.sora_name_ar},no` };
else return aya;
});
return ayat;
Expand Down
2 changes: 1 addition & 1 deletion models/Ayah.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Ayah, Surah } from "@/types/Suar";
import { Ayah, Surah } from "@/types";
import { ColumnMapping, columnTypes } from "expo-sqlite-orm";

const AyahModal: ColumnMapping<Ayah> = {
Expand Down
2 changes: 1 addition & 1 deletion models/Surah.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Surah } from "@/types/Suar";
import { Surah } from "@/types";
import { ColumnMapping, columnTypes } from "expo-sqlite-orm";

const SurahModal: ColumnMapping<Surah> = {
Expand Down
16 changes: 16 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"react-dom": "18.2.0",
"react-native": "0.72.6",
"react-native-gesture-handler": "~2.12.0",
"react-native-mmkv": "^2.11.0",
"react-native-safe-area-context": "4.6.3",
"react-native-screens": "~3.22.0",
"react-native-svg": "^14.1.0",
Expand Down
2 changes: 1 addition & 1 deletion screens/home/components/JozzCard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Surah } from "@/types/Suar";
import { Surah } from "@/types";
import { memo } from "react";
import { Text, Pressable } from "react-native";

Expand Down
60 changes: 42 additions & 18 deletions screens/home/components/MainCard.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,52 @@
import { Pressable, Text, View } from "react-native";
import Doc from "@/assets/icons/doc.svg";
import ArrowRight from "@/assets/icons/arrow_right.svg";
import { router } from "expo-router";
import { router, useFocusEffect } from "expo-router";
import { storage } from "@/utils";
import { useCallback, useEffect, useState } from "react";
import { Recent } from "@/types";

export function MainCard() {
const [recent, setRecent] = useState<Recent>();
useFocusEffect(
useCallback(() => {
let recentJSON = storage.getString("recent");
if (recentJSON) setRecent(JSON.parse(recentJSON));
}, [])
);

return (
<View className="mt-5 bg-lotion w-full rounded-[17px] px-6 relative py-6">
<View className="h-8 flex flex-col justify-center">
<Text className="font-HelveticaRoman text-xl pt-2 text-primary">
الفاتحة
</Text>
<Text className="text-secondary/30 font-HelveticaLight">الأية : 1</Text>
</View>
<Pressable
className="flex-[0.2] h-8 flex-row items-center absolute right-3 top-6"
onPress={() => {
router.push("/surah/1");
}}
>
<Text className=" font-HelveticaBold text-primary">
متابعة القراءة
{recent ? (
<>
<View className="h-10 flex flex-col justify-center">
<Text className="font-HelveticaRoman text-xl text-primary">
{recent.type === "surah" ? recent?.name : `الجزء ${recent.id}`}
</Text>
<Text className="text-secondary/30 font-HelveticaLight">
{recent.type === "surah"
? `الأية : ${recent?.aya}`
: `${recent.name} الأية : ${recent?.aya}`}
</Text>
</View>
<Pressable
className="flex-[0.2] h-8 flex-row items-center absolute right-3 top-6"
onPress={() => {
router.push(
`/${recent.type === "surah" ? "surah" : "jozz"}/${recent.id}`
);
}}
>
<Text className=" font-HelveticaBold text-primary">
متابعة القراءة
</Text>
<ArrowRight width={22} height={12} className="mt-2" />
</Pressable>
</>
) : (
<Text className="text-center font-HelveticaRoman text-primary/20">
لم يتم قراءة شئ موخرا
</Text>
<ArrowRight width={22} height={12} className="mt-2" />
</Pressable>
)}
</View>
);
}
2 changes: 1 addition & 1 deletion screens/home/components/SurahCard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Surah } from "@/types/Suar";
import { Surah } from "@/types";
import { memo } from "react";
import { Text, View, Pressable } from "react-native";

Expand Down
2 changes: 1 addition & 1 deletion screens/home/components/SurahTab.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { FlatList, Text } from "react-native";
import SurahCard from "./SurahCard";
import { router } from "expo-router";
import { Surah } from "@/types/Suar";
import { Surah } from "@/types";
import { useMemo } from "react";

const SurahTab = ({ data, search }: { data: Surah[]; search: string }) => {
Expand Down
2 changes: 1 addition & 1 deletion screens/home/components/TypeTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useState } from "react";
import Tabs from "@/components/Tabs";
import SurahTab from "./SurahTab";
import JozzTab from "./JozzTab";
import { Surah } from "@/types/Suar";
import { Surah } from "@/types";

export const TypeTabs = (props: { data: Surah[]; search: string }) => {
const [tab, setTab] = useState<string>("surah");
Expand Down
1 change: 0 additions & 1 deletion screens/home/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { TypeTabs } from "./components/TypeTabs";
import { useEffect, useState } from "react";
import { useQuery } from "react-query";
import SurahsRepo from "@/db/repos/SurahsRepo";
import { Surah } from "@/types/Suar";

const Home = () => {
const [search, setSearch] = useState<string>("");
Expand Down
12 changes: 9 additions & 3 deletions screens/jozz/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useLocalSearchParams } from "expo-router";
import { Header } from "./Header";
import { AyaCard } from "../surah/components/AyaCard";
import { getAyatAsJozz } from "@/db/repos/AyatRepo";
import { useState } from "react";
import useOnAyaScrolling from "@/utils/useOnAyaScrolling";

const Jozz = () => {
const local = useLocalSearchParams();
Expand All @@ -15,7 +15,10 @@ const Jozz = () => {
},
{ cacheTime: Infinity }
);
const [currentSora, setCurrentSora] = useState();

const { viewabilityConfigCallbackPairs } = useOnAyaScrolling({
type: "jozz",
});

return (
!isLoading &&
Expand All @@ -24,9 +27,12 @@ const Jozz = () => {
<Header title={`الجزء ${local.id}`} />
<FlatList
data={data}
viewabilityConfigCallbackPairs={
viewabilityConfigCallbackPairs.current as any
}
renderItem={({ item, index }) => (
<View key={index}>
{item.sora_name_ar !== "no" && (
{!item.sora_name_ar.includes("no") && (
<Text className="my-2 bg-primary mx-auto text-white font-UthmanicHafs text-lg w-1/2 text-center">
{item.sora_name_ar}
</Text>
Expand Down
2 changes: 0 additions & 2 deletions screens/surah/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { Pressable, View } from "react-native";
import BigArrow from "@/assets/icons/big_arrow.svg";
import Menu from "@/assets/icons/Menu.svg";
import { Text } from "react-native";
import { Surah as SurahType } from "@/types/Suar";
import { router } from "expo-router";

export function Header({
Expand Down
2 changes: 1 addition & 1 deletion screens/surah/components/AyaCard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Ayah } from "@/types/Suar";
import { Ayah } from "@/types";
import { Text, View } from "react-native";
import Bookmark from "@/assets/icons/bookmark.svg";
import { useState } from "react";
Expand Down
10 changes: 8 additions & 2 deletions screens/surah/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@ import { FlatList, Text } from "react-native";
import { AyaCard } from "./components/AyaCard";
import { useQuery } from "react-query";
import { getSuraWithAyat } from "@/db/repos/SurahsRepo";
import useOnAyaScrolling from "@/utils/useOnAyaScrolling";

const Surah = () => {
const local = useLocalSearchParams();

const { isLoading, data, isFetched } = useQuery(
"sura",
() => {
return getSuraWithAyat(parseInt(local.id as string));
},
{ cacheTime: Infinity }
);
const { viewabilityConfigCallbackPairs } = useOnAyaScrolling({});

return (
!isLoading &&
Expand All @@ -29,8 +32,11 @@ const Surah = () => {
<View className=" bg-white">
<FlatList
data={data?.ayat}
viewabilityConfigCallbackPairs={
viewabilityConfigCallbackPairs.current as any
}
renderItem={({ item, index }) => (
<>
<View className="bg-lotion" key={index}>
{local.id !== "1" && local.id !== "9" && index === 0 && (
<Text className="mt-5 text-primary font-UthmanicHafs text-lg text-center ">
بِسْمِ ٱللَّهِ ٱلرَّحْمَٰنِ ٱلرَّحِيمِ
Expand All @@ -41,7 +47,7 @@ const Surah = () => {
isFirst={index === 0}
isLast={index + 1 !== data?.ayat.length}
/>
</>
</View>
)}
className="w-full bg-lotion h-[93%] px-5 overflow-hidden"
/>
Expand Down
8 changes: 8 additions & 0 deletions types/Suar.ts → types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,11 @@ export interface Ayah {
maany_aya: string;
aya_text_tashkil: string;
}

export interface Recent {
type: "surah" | "jozz";
name: string;
aya: number;
index: number;
id: number;
}
32 changes: 32 additions & 0 deletions utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { MMKV } from "react-native-mmkv";

export function onChangeDelayed({
event,
onChange,
Expand All @@ -16,3 +18,33 @@ export function onChangeDelayed({
}, 1000)
);
}

export const storage = new MMKV({
id: `mystorage`,
encryptionKey: "abyss",
});

export const onAyaChanged = ({
viewableItems,
onChange,
type = "surah",
}: any) => {
if (viewableItems)
onChange(() => {
storage.set(
"recent",
JSON.stringify({
type: type,
name: viewableItems[viewableItems.length - 1].item.sora_name_ar.split(
","
)[0],
aya: viewableItems[viewableItems.length - 1].item.aya_no,
index: viewableItems[viewableItems.length - 1].index,
id:
type === "jozz"
? viewableItems[0].item.jozz
: viewableItems[viewableItems.length - 1].item.sora,
})
);
});
};
19 changes: 19 additions & 0 deletions utils/useOnAyaScrolling.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { useRef } from "react";
import useOnChange from "./useOnChange";
import { onAyaChanged } from ".";

const useOnAyaScrolling = ({ type }: { type?: "surah" | "jozz" }) => {
const { onChange } = useOnChange({ delay: 1000 });

const onViewableItemsChanged = ({ viewableItems }: any) => {
onAyaChanged({ viewableItems, onChange, type });
};

const viewabilityConfigCallbackPairs = useRef([{ onViewableItemsChanged }]);

return {
viewabilityConfigCallbackPairs,
};
};

export default useOnAyaScrolling;
17 changes: 17 additions & 0 deletions utils/useOnChange.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useState } from "react";

const useOnChange = ({ delay }: { delay?: number }) => {
const [timeout, setTimeOutValue] = useState<NodeJS.Timeout>();

const onChange = (callback: () => void) => {
if (timeout) clearTimeout(timeout);
setTimeOutValue(
setTimeout(function () {
callback();
}, delay || 1000)
);
};
return { onChange };
};

export default useOnChange;

0 comments on commit 1fcc0ed

Please sign in to comment.