Skip to content

Commit

Permalink
Refactor initial load and add light and dark theme
Browse files Browse the repository at this point in the history
  • Loading branch information
chadmuro committed Nov 4, 2023
1 parent 6fff365 commit 5f3cada
Show file tree
Hide file tree
Showing 10 changed files with 409 additions and 71 deletions.
40 changes: 2 additions & 38 deletions app/(index)/_layout.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,7 @@
import { useEffect } from "react";
import { Q } from "@nozbe/watermelondb";
import { useDatabase } from "@nozbe/watermelondb/react";
import { SplashScreen, Stack, useRouter } from "expo-router";

import { useStudy } from "../../contexts/studyContext";
import Settings from "../../model/Settings";
import { Stack } from "expo-router";

export default function Layout() {
const { loading } = useStudy();
const router = useRouter();
const database = useDatabase();

useEffect(() => {
async function initialLoad() {
if (!loading) {
const settings = await database
.get<Settings>("settings")
.query(Q.where("user_id", 1))
.fetch();

if (!settings.length) {
SplashScreen.hideAsync();
// if first load show info screen
router.push("/info");
await database.write(async () => {
await database.get<Settings>("settings").create((setting) => {
setting.userId = 1;
setting.theme = "system";
setting.notificationTime = null;
});
});
} else {
SplashScreen.hideAsync();
}
}
}

initialLoad();
}, [loading]);
// TODO - on initial load show info

return (
<Stack
Expand Down
70 changes: 62 additions & 8 deletions app/_layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import React, { Suspense } from "react";
import React, { Suspense, useEffect } from "react";
import { useColorScheme } from "react-native";
import { DatabaseProvider, useDatabase } from "@nozbe/watermelondb/react";
import {
DatabaseProvider,
useDatabase,
withObservables
} from "@nozbe/watermelondb/react";
import {
DarkTheme,
DefaultTheme,
Expand All @@ -12,7 +16,9 @@ import { SplashScreen, Tabs } from "expo-router";
import { StatusBar } from "expo-status-bar";
import { TamaguiProvider, Text, Theme } from "tamagui";

import { StudyProvider } from "../contexts/studyContext";
import { SettingsProvider, useSettings } from "../contexts/settingsContext";
import { StudyProvider, useStudy } from "../contexts/studyContext";
import SettingsModel from "../model/Settings";
import config from "../tamagui.config";
import databaseProvider from "../utils/database";

Expand All @@ -31,21 +37,67 @@ export default function Layout() {
<Suspense fallback={<Text>Loading...</Text>}>
<DatabaseProvider database={databaseProvider}>
<StudyProvider>
<ThemeLayout />
<SettingsProvider>
<ThemeLayoutWrapper />
</SettingsProvider>
</StudyProvider>
</DatabaseProvider>
</Suspense>
</TamaguiProvider>
);
}

function ThemeLayout() {
function ThemeLayoutWrapper() {
const { settings, getSettings } = useSettings();
const { getTodaysReview, getTodaysStudy } = useStudy();

const database = useDatabase();

useEffect(() => {
async function initialLoad() {
await getSettings();
await getTodaysReview();
await getTodaysStudy();

if (!settings) {
await database.write(async () => {
await database.get<SettingsModel>("settings").create((setting) => {
setting.userId = 1;
setting.theme = "system";
setting.notificationTime = null;
});
});
}
SplashScreen.hideAsync();
}

initialLoad();
}, []);

if (!settings) return null;

return <EnhancedThemeLayoutComponent settings={settings} />;
}

const enhance = withObservables(["settings"], ({ settings }) => ({
settings
}));

function ThemeLayout({ settings }: { settings: SettingsModel }) {
const colorScheme = useColorScheme();

let theme = "light";
if (settings?.theme === "dark") {
theme = "dark";
} else if (settings?.theme === "light") {
theme = "light";
} else if (settings?.theme === "system") {
theme = colorScheme;
}

return (
<Theme name="dark">
<ThemeProvider value={DarkTheme}>
<Theme name={theme === "dark" ? "dark" : "light"}>
<ThemeProvider value={theme === "dark" ? DarkTheme : DefaultTheme}>
<Tabs
screenOptions={{
headerShown: false,
Expand Down Expand Up @@ -81,8 +133,10 @@ function ThemeLayout() {
}}
/>
</Tabs>
<StatusBar style="light" />
<StatusBar style={theme === "dark" ? "light" : "dark"} />
</ThemeProvider>
</Theme>
);
}

const EnhancedThemeLayoutComponent = enhance(ThemeLayout);
89 changes: 89 additions & 0 deletions app/settings/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import {
AlarmClock,
ChevronRight,
ClipboardCopy,
Mail,
Palette,
Pencil,
X
} from "@tamagui/lucide-icons";
import { H2, ListItem, Separator, YGroup } from "tamagui";

import SettingsDialog from "../../components/Dialog";
import { MyStack } from "../../components/MyStack";
import { SafeAreaView } from "../../components/SafeAreaView";
import ThemeContent from "../../components/settings/ThemeContent";
import ThemeItem from "../../components/settings/ThemeItem";
import { useSettings } from "../../contexts/settingsContext";

export default function Settings() {
const { settings } = useSettings();

return (
<SafeAreaView>
<MyStack justifyContent="flex-start">
<H2>Settings</H2>
<YGroup
alignSelf="center"
bordered
size="$5"
separator={<Separator />}
>
<YGroup.Item>
<SettingsDialog
trigger={<ThemeItem settings={settings} />}
content={<ThemeContent settings={settings} />}
title="Theme"
description="System, dark, or light mode"
/>
</YGroup.Item>

{/* <YGroup.Item>
<ListItem
hoverTheme
pressTheme
title="Reminder"
subTitle="Not set"
icon={AlarmClock}
iconAfter={ChevronRight}
/>
</YGroup.Item> */}
</YGroup>
<YGroup
alignSelf="center"
bordered
size="$5"
separator={<Separator />}
>
<YGroup.Item>
<ListItem
hoverTheme
pressTheme
title="Open default mail app"
icon={Mail}
iconAfter={ChevronRight}
/>
</YGroup.Item>
<YGroup.Item>
<ListItem
hoverTheme
pressTheme
title="Copy email to clipboard"
icon={ClipboardCopy}
iconAfter={ChevronRight}
/>
</YGroup.Item>
{/* <YGroup.Item>
<ListItem
hoverTheme
pressTheme
title="Write a review"
icon={Pencil}
iconAfter={ChevronRight}
/>
</YGroup.Item> */}
</YGroup>
</MyStack>
</SafeAreaView>
);
}
88 changes: 88 additions & 0 deletions components/Dialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import React from "react";
import { Adapt, Button, Dialog, Sheet, YStack } from "tamagui";

interface Props {
trigger: React.JSX.Element;
content: React.JSX.Element;
title: string;
description: string;
}

export default function SettingsDialog({
trigger,
content,
title,
description
}: Props) {
return (
<Dialog modal>
<Dialog.Trigger asChild>{trigger}</Dialog.Trigger>

<Adapt
when="sm"
platform="touch"
>
<Sheet
zIndex={200000}
modal
dismissOnSnapToBottom
>
<Sheet.Frame
padding="$4"
space
>
<Adapt.Contents />
</Sheet.Frame>
<Sheet.Overlay />
</Sheet>
</Adapt>

<Dialog.Portal>
<Dialog.Overlay
key="overlay"
animation="quick"
o={0.5}
enterStyle={{ o: 0 }}
exitStyle={{ o: 0 }}
/>

<Dialog.Content
bordered
elevate
key="content"
animation={[
"quick",
{
opacity: {
overshootClamping: true
}
}
]}
enterStyle={{ x: 0, y: -20, opacity: 0, scale: 0.9 }}
exitStyle={{ x: 0, y: 10, opacity: 0, scale: 0.95 }}
space
>
<Dialog.Title>{title}</Dialog.Title>
<Dialog.Description>{description}</Dialog.Description>
{content}
{/* <Fieldset>
<Label htmlFor="name">Name</Label>
<Input
id="name"
defaultValue="Nate Wienert"
/>
</Fieldset> */}

<YStack marginTop="$2">
<Dialog.Close
displayWhenAdapted
asChild
>
<Button aria-label="Close">Close</Button>
</Dialog.Close>
</YStack>
</Dialog.Content>
</Dialog.Portal>
</Dialog>
);
}
Loading

0 comments on commit 5f3cada

Please sign in to comment.