Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: sync darkmode with system #14

Merged
merged 10 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,8 @@
LastUpgradeCheck = 1130;
TargetAttributes = {
13B07F861A680F5B00A75B9A = {
DevelopmentTeam = G5DZE7G2V4;
LastSwiftMigration = 1250;
DevelopmentTeam = "G5DZE7G2V4";
ProvisioningStyle = Automatic;
};
};
Expand Down Expand Up @@ -374,7 +374,10 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = designplayground/designplayground.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = G5DZE7G2V4;
ENABLE_BITCODE = NO;
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
Expand All @@ -397,9 +400,6 @@
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
DEVELOPMENT_TEAM = "G5DZE7G2V4";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
};
name = Debug;
};
Expand All @@ -410,7 +410,10 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = designplayground/designplayground.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = G5DZE7G2V4;
INFOPLIST_FILE = designplayground/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
Expand All @@ -427,9 +430,6 @@
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
DEVELOPMENT_TEAM = "G5DZE7G2V4";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
};
name = Release;
};
Expand Down
2 changes: 1 addition & 1 deletion examples/designdemo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"@formatjs/intl-numberformat": "^8.10.3",
"@formatjs/intl-pluralrules": "^5.2.14",
"@formatjs/intl-relativetimeformat": "^11.2.14",
"@gorhom/bottom-sheet": "^5.0.0-alpha.11",
"@gorhom/bottom-sheet": "^5",
"@gorhom/portal": "^1.0.14",
"@react-native-community/slider": "4.5.2",
"@react-navigation/drawer": "^6.6.15",
Expand Down
9 changes: 8 additions & 1 deletion examples/designdemo/src/app/(tabs)/_layout.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import MaterialIcons from "@expo/vector-icons/MaterialIcons";
import { DrawerActions } from "@react-navigation/native";
import { useThemePreferences } from "@siteed/design-system";
import { Tabs, useNavigation } from "expo-router";
import React from "react";

export default function TabLayout() {
const navigation = useNavigation();
const { darkMode, theme } = useThemePreferences();

return (
<Tabs
Expand All @@ -15,12 +17,17 @@ export default function TabLayout() {
name="menu"
size={24}
style={{ paddingLeft: 10 }}
color="black"
color={darkMode ? "white" : "black"}
onPress={() => {
navigation.dispatch(DrawerActions.toggleDrawer());
}}
/>
),
tabBarStyle: {
backgroundColor: theme.colors.background,
},
tabBarActiveTintColor: theme.colors.primary,
tabBarInactiveTintColor: theme.colors.onSurface,
}}
>
<Tabs.Screen name="index" options={{ title: "Theme", href: "/" }} />
Expand Down
1 change: 1 addition & 0 deletions examples/designdemo/src/app/(tabs)/bug.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ const InnerComponent = ({ onChange, footerHeight }: InnerComponentProps) => {
<Text>{JSON.stringify(options)}</Text>
<Picker
label="Picker"
showCreateOptionButton
options={options}
onFinish={(values) => {
console.log("Picker value changed to:", values);
Expand Down
6 changes: 2 additions & 4 deletions examples/designdemo/src/app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,15 @@
import { ThemeProvider } from "@react-navigation/native";
import { useThemePreferences } from "@siteed/design-system";
import { Drawer } from "expo-router/drawer";
import { StatusBar } from "expo-status-bar";

export const unstable_settings = {
initialRouteName: "/",
};

export default function HomeLayout() {
const { theme, darkMode } = useThemePreferences();
const { theme } = useThemePreferences();

return (
<ThemeProvider value={{ ...theme }}>
<StatusBar style={darkMode ? "light" : "dark"} />
<Drawer screenOptions={{ headerShown: true }}>
<Drawer.Screen name="(tabs)" />
</Drawer>
Expand Down
4 changes: 1 addition & 3 deletions examples/designdemo/src/app/modal.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import BottomSheet, { BottomSheetView } from "@gorhom/bottom-sheet";
import { StatusBar } from "expo-status-bar";
import React, { useCallback, useMemo, useRef } from "react";
import { Platform, StyleSheet, View } from "react-native";
import { StyleSheet, View } from "react-native";
import { Button, Text } from "react-native-paper";

export default function ModalScreen() {
Expand Down Expand Up @@ -30,7 +29,6 @@ export default function ModalScreen() {
<View style={styles.container}>
<Text style={styles.title}>Modal</Text>

<StatusBar style={Platform.OS === "ios" ? "light" : "auto"} />
<Button onPress={() => handleSnapPress(2)}>Snap To 90%</Button>
<Button onPress={() => handleSnapPress(1)}>Snap To 50%</Button>
<Button onPress={() => handleSnapPress(0)}>Snap To 25%</Button>
Expand Down
23 changes: 22 additions & 1 deletion examples/designdemo/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,33 @@
import "intl-pluralrules";
// Keep polyfills at the top

import { UIProvider } from "@siteed/design-system";
import { UIProvider, useThemePreferences } from "@siteed/design-system";
import { setLoggerConfig } from "@siteed/react-native-logger";
import { registerRootComponent } from "expo";
import { App as ExpoRouterApp } from "expo-router/build/qualified-entry";
import { StatusBar as ExpoStatusBar } from "expo-status-bar";
import { useEffect, useState } from "react";
import { ActivityIndicator } from "react-native-paper";

setLoggerConfig({ namespaces: "*" });

const DebugStatusBar = () => {
const { darkMode, isReady: themeReady } = useThemePreferences();

const [ready, setReady] = useState(false);

useEffect(() => {
const timeout = setTimeout(() => setReady(true), 10);
return () => clearTimeout(timeout);
}, []);

if (!ready || !themeReady) {
return <ActivityIndicator />;
}

return <ExpoStatusBar style={darkMode ? "light" : "dark"} />;
};

const AppEntry = () => {
return (
<UIProvider
Expand All @@ -18,6 +38,7 @@ const AppEntry = () => {
}}
>
<ExpoRouterApp />
<DebugStatusBar />
</UIProvider>
);
};
Expand Down
4 changes: 2 additions & 2 deletions packages/design-system/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@siteed/design-system",
"version": "0.28.16",
"version": "0.29.2",
"author": "Arthur Breton <[email protected]> (https://github.com/deeeed)",
"license": "MIT",
"repository": {
Expand Down Expand Up @@ -67,7 +67,7 @@
"@commitlint/config-conventional": "^19.1.0",
"@evilmartians/lefthook": "^1.6.7",
"@expo/vector-icons": "^14.0.2",
"@gorhom/bottom-sheet": "5.0.0-alpha.11",
"@gorhom/bottom-sheet": "^5",
"@gorhom/portal": "^1.0.14",
"@react-native-async-storage/async-storage": "1.23.1",
"@react-native-community/datetimepicker": "8.0.1",
Expand Down
19 changes: 8 additions & 11 deletions packages/design-system/src/components/picker/PickerContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export const PickerContent: React.FC<PickerContentProps> = ({
noResultsText,
onChange,
onItemPress,
showDebugCreate = true,
showDebugCreate = false,
}) => {
const theme = useTheme();
const styles = useMemo(() => getStyles(theme), [theme]);
Expand Down Expand Up @@ -132,7 +132,6 @@ export const PickerContent: React.FC<PickerContentProps> = ({
renderFooter: ({ resolve, data }) => {
return (
<View>
<Text>data: {JSON.stringify(data)}</Text>
<ConfirmCancelFooter
onCancel={() => resolve(undefined)}
onFinish={() => resolve(data)}
Expand Down Expand Up @@ -207,15 +206,13 @@ export const PickerContent: React.FC<PickerContentProps> = ({
) : (
renderOptions()
)}
<View style={{ height: 100 }}>
{showDebugCreate && (
<IconButton
icon="plus"
onPress={handleCreate}
style={styles.debugCreateButton}
/>
)}
</View>
{showDebugCreate && (
<IconButton
icon="plus"
onPress={handleCreate}
style={styles.debugCreateButton}
/>
)}
</View>
);
};
3 changes: 3 additions & 0 deletions packages/design-system/src/components/picker/picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export interface PickerProps {
emptyOptionsMessage?: string;
noResultsText?: string;
emptyActionLabel?: string;
showCreateOptionButton?: boolean;
}

export const Picker = ({
Expand All @@ -70,6 +71,7 @@ export const Picker = ({
emptyOptionsMessage = 'No options available',
noResultsText = 'No options available',
emptyActionLabel = 'Create New',
showCreateOptionButton = false,
onFinish,
emptyAction,
}: PickerProps) => {
Expand Down Expand Up @@ -100,6 +102,7 @@ export const Picker = ({
options={data || []}
multi={multi}
showSearch={showSearch}
showDebugCreate={showCreateOptionButton}
emptyLabel={emptyLabel}
emptyOptionsTitle={emptyOptionsTitle}
emptyOptionsMessage={emptyOptionsMessage}
Expand Down
32 changes: 27 additions & 5 deletions packages/design-system/src/hooks/_useAppPreferencesSetup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ interface useThemePreferencesProps {
export interface ThemeActions {
toggleShouldUseDeviceColors?: () => void;
toggleDarkMode: () => void;
setDarkMode: (value: boolean) => void;
toggleThemeVersion: () => void;
toggleCollapsed: () => void;
toggleCustomFont: () => void;
Expand All @@ -29,6 +30,7 @@ export interface ThemePreferences {
theme: AppTheme;
darkMode: boolean;
shouldUseDeviceColors?: boolean;
isReady: boolean;
}

const logger = baseLogger.extend('useAppPreferencesSetup');
Expand All @@ -37,19 +39,27 @@ export const useAppPreferencesSetup = ({
theme,
i18nInstance,
savePreferences,
setDarkMode,
setDarkMode: setThemeDarkMode,
}: useThemePreferencesProps) => {
const [collapsed, setCollapsed] = useState(false);
const [darkMode, setLocalDarkmode] = useState(theme.dark);
const [customFontLoaded, setCustomFont] = useState(false);
const [rippleEffectEnabled, setRippleEffectEnabled] = useState(true);
const [dynamicTheme, setDynamicTheme] = useState<AppTheme>(theme);
const [listener, setListener] = useState(false);
const [isReady, setIsReady] = useState(false);

useEffect(() => {
setDynamicTheme(theme);
}, [theme]);

// FIXNE: find a reliable way to determins when all providers are ready and set it from the parent UIProvider.
// Currently, it causes issue with the status bar that is set too soon and somehow doesn't sync the theme.
// useEffect(() => {
// const timeout = setTimeout(() => setIsReady(true), 1000);
// return () => clearTimeout(timeout);
// }, []);

useEffect(() => {
const onLanguage = (lng: string) => {
savePreferences?.({
Expand All @@ -61,7 +71,9 @@ export const useAppPreferencesSetup = ({

if (!listener && i18nInstance.isInitialized) {
i18nInstance.on('languageChanged', onLanguage);
console.log('language changed set isReady to true');
setListener(true);
setIsReady(true);
}

return () => {};
Expand All @@ -77,16 +89,24 @@ export const useAppPreferencesSetup = ({
const preferences: ThemeActions & ThemePreferences = useMemo(
() => ({
toggleDarkMode: () => {
const oldValue = dynamicTheme.dark ?? false;
const newValue = !oldValue;
const newValue = !dynamicTheme.dark;
setLocalDarkmode(newValue);
setDarkMode(newValue);
setThemeDarkMode(newValue);
savePreferences?.({
darkMode: newValue,
rippleEffectEnabled,
locale: i18nInstance.language,
});
},
setDarkMode: (value: boolean) => {
setLocalDarkmode(value);
setThemeDarkMode(value);
savePreferences?.({
darkMode: value,
rippleEffectEnabled,
locale: i18nInstance.language,
});
},
toggleCollapsed: () => setCollapsed(!collapsed),
toggleCustomFont: () => setCustomFont(!customFontLoaded),
toggleRippleEffect: () => {
Expand Down Expand Up @@ -125,15 +145,17 @@ export const useAppPreferencesSetup = ({
collapsed,
darkMode,
theme: dynamicTheme,
isReady,
}),
[
dynamicTheme,
isReady,
collapsed,
i18nInstance,
savePreferences,
customFontLoaded,
rippleEffectEnabled,
setDarkMode,
setThemeDarkMode,
]
);

Expand Down
Loading
Loading