add switch theme, remove unneeded search bar context

This commit is contained in:
Jorrin
2024-03-23 16:29:28 +01:00
parent 7308eb2221
commit 4ec78b13ab
10 changed files with 169 additions and 186 deletions

View File

@@ -1,4 +1,3 @@
import { useRef } from "react";
import { Platform } from "react-native"; import { Platform } from "react-native";
import * as Haptics from "expo-haptics"; import * as Haptics from "expo-haptics";
import { Tabs } from "expo-router"; import { Tabs } from "expo-router";
@@ -8,119 +7,108 @@ import { useTheme, View } from "tamagui";
import { MovieWebSvg } from "~/components/Icon"; import { MovieWebSvg } from "~/components/Icon";
import SvgTabBarIcon from "~/components/SvgTabBarIcon"; import SvgTabBarIcon from "~/components/SvgTabBarIcon";
import TabBarIcon from "~/components/TabBarIcon"; import TabBarIcon from "~/components/TabBarIcon";
import SearchTabContext from "../../components/ui/SearchTabContext";
export default function TabLayout() { export default function TabLayout() {
// eslint-disable-next-line @typescript-eslint/no-empty-function
const focusSearchInputRef = useRef(() => {});
const theme = useTheme(); const theme = useTheme();
return ( return (
<SearchTabContext.Provider value={{ focusSearchInputRef }}> <Tabs
<Tabs sceneContainerStyle={{
sceneContainerStyle={{ backgroundColor: theme.screenBackground.val,
backgroundColor: theme.screenBackground.val, }}
screenListeners={() => ({
tabPress: () => {
void Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
},
focus: () => {
void ScreenOrientation.lockAsync(
ScreenOrientation.OrientationLock.PORTRAIT_UP,
);
},
})}
screenOptions={{
headerShown: false,
tabBarActiveTintColor: theme.tabBarIconFocused.val,
tabBarStyle: {
backgroundColor: theme.tabBarBackground.val,
borderTopColor: "transparent",
borderTopRightRadius: 20,
borderTopLeftRadius: 20,
paddingBottom: Platform.select({ ios: 100 }),
height: 80,
},
tabBarItemStyle: {
paddingVertical: 18,
height: 82,
},
tabBarLabelStyle: [
{
marginTop: 2,
},
],
}}
>
<Tabs.Screen
name="index"
options={{
title: "Home",
tabBarIcon: ({ focused }) => (
<TabBarIcon name="home" focused={focused} />
),
}} }}
screenListeners={({ route }) => ({ />
tabPress: () => { <Tabs.Screen
void Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light); name="downloads"
switch (route.name) { options={{
case "search": title: "Downloads",
focusSearchInputRef.current(); tabBarIcon: ({ focused }) => (
break; <TabBarIcon name="download" focused={focused} />
} ),
},
focus: () => {
void ScreenOrientation.lockAsync(
ScreenOrientation.OrientationLock.PORTRAIT_UP,
);
},
})}
screenOptions={{
headerShown: false,
tabBarActiveTintColor: theme.tabBarIconFocused.val,
tabBarStyle: {
backgroundColor: theme.tabBarBackground.val,
borderTopColor: "transparent",
borderTopRightRadius: 20,
borderTopLeftRadius: 20,
paddingBottom: Platform.select({ ios: 100 }),
height: 80,
},
tabBarItemStyle: {
paddingVertical: 18,
height: 82,
},
tabBarLabelStyle: [
{
marginTop: 2,
},
],
}} }}
> />
<Tabs.Screen <Tabs.Screen
name="index" name="search"
options={{ options={{
title: "Home", title: "Search",
tabBarIcon: ({ focused }) => ( tabBarLabel: "",
<TabBarIcon name="home" focused={focused} /> tabBarIcon: ({ focused }) => (
), <View
}} top={2}
/> height={56}
<Tabs.Screen width={56}
name="downloads" alignItems="center"
options={{ justifyContent="center"
title: "Downloads", overflow="hidden"
tabBarIcon: ({ focused }) => ( borderRadius={100}
<TabBarIcon name="download" focused={focused} /> backgroundColor={
), focused ? theme.tabBarIconFocused : theme.tabBarIcon
}} }
/> >
<Tabs.Screen <TabBarIcon name="search" color="#FFF" />
name="search" </View>
options={{ ),
title: "Search", }}
tabBarLabel: "", />
tabBarIcon: ({ focused }) => ( <Tabs.Screen
<View name="movie-web"
top={2} options={{
height={56} title: "movie-web",
width={56} tabBarIcon: ({ focused }) => (
alignItems="center" <SvgTabBarIcon focused={focused}>
justifyContent="center" <MovieWebSvg />
overflow="hidden" </SvgTabBarIcon>
borderRadius={100} ),
backgroundColor={ }}
focused ? theme.tabBarIconFocused : theme.tabBarIcon />
} <Tabs.Screen
> name="settings"
<TabBarIcon name="search" color="#FFF" /> options={{
</View> title: "Settings",
), tabBarIcon: ({ focused }) => (
}} <TabBarIcon name="cog" focused={focused} />
/> ),
<Tabs.Screen }}
name="movie-web" />
options={{ </Tabs>
title: "movie-web",
tabBarIcon: ({ focused }) => (
<SvgTabBarIcon focused={focused}>
<MovieWebSvg />
</SvgTabBarIcon>
),
}}
/>
<Tabs.Screen
name="settings"
options={{
title: "Settings",
tabBarIcon: ({ focused }) => (
<TabBarIcon name="cog" focused={focused} />
),
}}
/>
</Tabs>
</SearchTabContext.Provider>
); );
} }

View File

@@ -11,7 +11,6 @@ import {
Select, Select,
Separator, Separator,
Sheet, Sheet,
Switch,
Text, Text,
useTheme, useTheme,
View, View,
@@ -21,6 +20,7 @@ import {
import type { ThemeStoreOption } from "~/stores/theme"; import type { ThemeStoreOption } from "~/stores/theme";
import ScreenLayout from "~/components/layout/ScreenLayout"; import ScreenLayout from "~/components/layout/ScreenLayout";
import { MWSwitch } from "~/components/ui/Switch";
import { checkForUpdate } from "~/lib/update"; import { checkForUpdate } from "~/lib/update";
import { getGestureControls, saveGestureControls } from "~/settings"; import { getGestureControls, saveGestureControls } from "~/settings";
import { useThemeStore } from "~/stores/theme"; import { useThemeStore } from "~/stores/theme";
@@ -76,14 +76,12 @@ export default function SettingsScreen() {
<XStack width={200} alignItems="center" gap="$4"> <XStack width={200} alignItems="center" gap="$4">
<Label minWidth={110}>Gesture controls</Label> <Label minWidth={110}>Gesture controls</Label>
<Separator minHeight={20} vertical /> <Separator minHeight={20} vertical />
<Switch <MWSwitch
size="$4"
native
checked={gestureControlsEnabled} checked={gestureControlsEnabled}
onCheckedChange={handleGestureControlsToggle} onCheckedChange={handleGestureControlsToggle}
> >
<Switch.Thumb animation="quicker" /> <MWSwitch.Thumb animation="quicker" />
</Switch> </MWSwitch>
</XStack> </XStack>
</YStack> </YStack>
</View> </View>

View File

@@ -1,51 +1,28 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import type { ButtonProps } from "tamagui";
import React from "react";
import { Button, styled } from "tamagui"; import { Button, styled } from "tamagui";
const PrimaryButton = styled(Button, { export const MWButton = styled(Button, {
backgroundColor: "$buttonPrimaryBackground", variants: {
color: "$buttonPrimaryText", type: {
fontWeight: "bold", primary: {
backgroundColor: "$buttonPrimaryBackground",
color: "$buttonPrimaryText",
fontWeight: "bold",
},
secondary: {
backgroundColor: "$buttonSecondaryBackground",
color: "$buttonSecondaryText",
fontWeight: "bold",
},
purple: {
backgroundColor: "$buttonPurpleBackground",
color: "white",
fontWeight: "bold",
},
cancel: {
backgroundColor: "$buttonCancelBackground",
color: "white",
fontWeight: "bold",
},
},
} as const,
}); });
const SecondaryButton = styled(Button, {
backgroundColor: "$buttonSecondaryBackground",
color: "$buttonSecondaryText",
fontWeight: "bold",
});
const PurpleButton = styled(Button, {
backgroundColor: "$buttonPurpleBackground",
color: "white",
fontWeight: "bold",
});
const CancelButton = styled(Button, {
backgroundColor: "$buttonCancelBackground",
color: "white",
fontWeight: "bold",
});
export const MWButton = React.forwardRef<
typeof Button,
ButtonProps & {
type?: "primary" | "secondary" | "purple" | "cancel";
}
>((props, ref) => {
const { type, ...rest } = props;
switch (type) {
case "primary":
return <PrimaryButton {...rest} ref={ref as any} />;
case "secondary":
return <SecondaryButton {...rest} ref={ref as any} />;
case "purple":
return <PurpleButton {...rest} ref={ref as any} />;
case "cancel":
return <CancelButton {...rest} ref={ref as any} />;
default:
return <Button {...rest} ref={ref as any} />;
}
});
MWButton.displayName = "MWButton";

View File

@@ -1,8 +0,0 @@
import React from "react";
const SearchTabContext = React.createContext({
// eslint-disable-next-line @typescript-eslint/no-empty-function
focusSearchInputRef: { current: () => {} },
});
export default SearchTabContext;

View File

@@ -1,10 +1,9 @@
import { useContext, useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { Keyboard } from "react-native"; import { Keyboard } from "react-native";
import { FontAwesome5 } from "@expo/vector-icons"; import { FontAwesome5 } from "@expo/vector-icons";
import { useIsFocused } from "@react-navigation/native";
import { Input, styled, useTheme, View } from "tamagui"; import { Input, styled, useTheme, View } from "tamagui";
import SearchTabContext from "./SearchTabContext";
const SearchInput = styled(Input, { const SearchInput = styled(Input, {
backgroundColor: "$searchBackground", backgroundColor: "$searchBackground",
borderColor: "$colorTransparent", borderColor: "$colorTransparent",
@@ -22,17 +21,16 @@ export function SearchBar({
onSearchChange: (text: string) => void; onSearchChange: (text: string) => void;
}) { }) {
const theme = useTheme(); const theme = useTheme();
const pageIsFocused = useIsFocused();
const [keyword, setKeyword] = useState(""); const [keyword, setKeyword] = useState("");
const [isFocused, setIsFocused] = useState(false); const [isFocused, setIsFocused] = useState(false);
const inputRef = useRef<Input>(null); const inputRef = useRef<Input>(null);
const { focusSearchInputRef } = useContext(SearchTabContext);
useEffect(() => { useEffect(() => {
focusSearchInputRef.current = () => { if (pageIsFocused) {
inputRef.current?.focus(); inputRef.current?.focus();
}; }
}, [focusSearchInputRef]); }, [pageIsFocused]);
useEffect(() => { useEffect(() => {
const keyboardDidShowListener = Keyboard.addListener( const keyboardDidShowListener = Keyboard.addListener(

View File

@@ -0,0 +1,27 @@
import type { SwitchProps } from "tamagui";
import { Switch, useTheme } from "tamagui";
const MWSwitch = (props: SwitchProps) => {
const theme = useTheme();
return (
<Switch
native
nativeProps={{
trackColor: {
true: theme.switchActiveTrackColor.val,
false: theme.switchInactiveTrackColor.val,
},
thumbColor: theme.switchThumbColor.val,
}}
{...props}
/>
);
};
const MWSwitchThumb = (props: any) => {
return <Switch.Thumb animation="quicker" {...props} />;
};
MWSwitch.Thumb = MWSwitchThumb;
export { MWSwitch };

View File

@@ -36,9 +36,8 @@ export async function checkForUpdate(): Promise<string | undefined> {
if (!res) return; if (!res) return;
const latestVersion: string = res.data.tag_name; const latestVersion = res.data.tag_name;
const currentVersion: string = const currentVersion = Application.nativeApplicationVersion ?? "0.0.0";
Application.nativeApplicationVersion ?? "0.0.0";
if (isVersionHigher(latestVersion, currentVersion)) { if (isVersionHigher(latestVersion, currentVersion)) {
return res.data.html_url; return res.data.html_url;

View File

@@ -73,6 +73,10 @@ const createThemeConfig = (tokens: Tokens) => ({
buttonPurpleBackgroundHover: tokens.purple.c400, buttonPurpleBackgroundHover: tokens.purple.c400,
buttonCancelBackground: tokens.ash.c500, buttonCancelBackground: tokens.ash.c500,
buttonCancelBackgroundHover: tokens.ash.c300, buttonCancelBackgroundHover: tokens.ash.c300,
switchActiveTrackColor: tokens.purple.c300,
switchInactiveTrackColor: tokens.ash.c500,
switchThumbColor: tokens.white,
}); });
const openSansFace = { const openSansFace = {

View File

@@ -29,7 +29,7 @@
}, },
"prettier": "@movie-web/prettier-config", "prettier": "@movie-web/prettier-config",
"dependencies": { "dependencies": {
"@movie-web/providers": "^2.2.2", "@movie-web/providers": "^2.2.4",
"parse-hls": "^1.0.7", "parse-hls": "^1.0.7",
"srt-webvtt": "^2.0.0", "srt-webvtt": "^2.0.0",
"tmdb-ts": "^1.6.1" "tmdb-ts": "^1.6.1"

8
pnpm-lock.yaml generated
View File

@@ -235,8 +235,8 @@ importers:
packages/provider-utils: packages/provider-utils:
dependencies: dependencies:
'@movie-web/providers': '@movie-web/providers':
specifier: ^2.2.2 specifier: ^2.2.4
version: 2.2.2 version: 2.2.4
parse-hls: parse-hls:
specifier: ^1.0.7 specifier: ^1.0.7
version: 1.0.7 version: 1.0.7
@@ -2865,8 +2865,8 @@ packages:
tslib: 2.6.2 tslib: 2.6.2
dev: false dev: false
/@movie-web/providers@2.2.2: /@movie-web/providers@2.2.4:
resolution: {integrity: sha512-pTlErE5bdu+b68mUW2YAKOJKz2hwSx63auGAfTkGQ+0SHDMlCV9QQ8S8O9IoSsvdXps7/YlWJWOMX8pmKuYbPQ==} resolution: {integrity: sha512-c10ffR7/oPMbVwpD+Lw0/k5jvx51NbywGJtogzRjeXqDr01o5+pitPeN1qSGaqTg5FBlipn7NSesrd+cczDDQw==}
dependencies: dependencies:
cheerio: 1.0.0-rc.12 cheerio: 1.0.0-rc.12
cookie: 0.6.0 cookie: 0.6.0