Front: Typecheck Elements
This commit is contained in:
@@ -12,7 +12,7 @@ import HomeView from './views/HomeView';
|
||||
import SearchView from './views/SearchView';
|
||||
import SetttingsNavigator from './views/settings/SettingsView';
|
||||
import { useQuery } from 'react-query';
|
||||
import API from './API';
|
||||
import API, { APIError } from './API';
|
||||
import PlayView from './views/PlayView';
|
||||
import ScoreView from './views/ScoreView';
|
||||
import { LoadingView } from './components/Loading';
|
||||
@@ -94,7 +94,7 @@ export const Router = () => {
|
||||
retry: 1,
|
||||
refetchOnWindowFocus: false,
|
||||
onError: (err) => {
|
||||
if (err.status === 401) {
|
||||
if (err instanceof APIError && err.status === 401) {
|
||||
dispatch(unsetAccessToken());
|
||||
}
|
||||
},
|
||||
|
||||
@@ -12,14 +12,18 @@ const cardBorder = (theme: ReturnType<typeof useTheme>) => ({
|
||||
borderWidth: 1
|
||||
})
|
||||
|
||||
const Card = (props: Parameters<typeof Box>[0] & { onPress: () => void }) => {
|
||||
type CardProps = Parameters<typeof Box>[0] & {
|
||||
onPress: () => void
|
||||
}
|
||||
|
||||
const Card = (props: CardProps) => {
|
||||
const theme = useTheme();
|
||||
const colorScheme = useSelector((state: RootState) => state.settings.local.colorScheme);
|
||||
const systemColorMode = useColorScheme();
|
||||
|
||||
return <Pressable onPress={props.onPress}>
|
||||
{({ isHovered, isPressed }) => (
|
||||
<Box {...props} style={{ ...(props.style ?? {}), ...cardBorder(theme) }}
|
||||
<Box {...props} style={[props.style, cardBorder(theme)]}
|
||||
bg={(colorScheme == 'system' ? systemColorMode : colorScheme) == 'dark'
|
||||
? (isHovered || isPressed) ? 'gray.800' : undefined
|
||||
: (isHovered || isPressed) ? 'coolGray.200' : undefined
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import React from "react";
|
||||
import { ElementProps } from "./ElementList";
|
||||
import { ElementProps } from "./ElementTypes";
|
||||
import { RawElement } from "./RawElement";
|
||||
import { Pressable } from "native-base";
|
||||
import { Pressable, IPressableProps } from "native-base";
|
||||
import { ElementTextProps, ElementToggleProps } from './ElementTypes';
|
||||
|
||||
export const Element = (props: ElementProps) => {
|
||||
let actionFunction = null as null | Function;
|
||||
export const Element = <T extends ElementProps,>(props: T) => {
|
||||
let actionFunction: IPressableProps['onPress'] = null;
|
||||
|
||||
switch (props.type) {
|
||||
case "text":
|
||||
|
||||
@@ -2,14 +2,7 @@ import React from "react";
|
||||
import { StyleProp, ViewStyle } from "react-native";
|
||||
import { Element } from "./Element";
|
||||
import useColorScheme from "../../hooks/colorScheme";
|
||||
|
||||
import {
|
||||
ElementTextProps,
|
||||
ElementToggleProps,
|
||||
ElementDropdownProps,
|
||||
ElementRangeProps,
|
||||
ElementType,
|
||||
} from "./ElementTypes";
|
||||
import { ElementProps } from "./ElementTypes";
|
||||
|
||||
import {
|
||||
Box,
|
||||
@@ -17,21 +10,6 @@ import {
|
||||
Divider,
|
||||
} from "native-base";
|
||||
|
||||
export type ElementProps = {
|
||||
title: string;
|
||||
icon?: React.ReactNode;
|
||||
type?: ElementType;
|
||||
helperText?: string;
|
||||
description?: string;
|
||||
disabled?: boolean;
|
||||
data?:
|
||||
| ElementTextProps
|
||||
| ElementToggleProps
|
||||
| ElementDropdownProps
|
||||
| ElementRangeProps
|
||||
| React.ReactNode;
|
||||
};
|
||||
|
||||
type ElementListProps = {
|
||||
elements: ElementProps[];
|
||||
style?: StyleProp<ViewStyle>;
|
||||
@@ -42,9 +20,11 @@ const ElementList = ({ elements, style }: ElementListProps) => {
|
||||
const isDark = colorScheme === "dark";
|
||||
const elementStyle = {
|
||||
borderRadius: 10,
|
||||
boxShadow: isDark ? "0px 0px 3px 0px rgba(255,255,255,0.6)" : "0px 0px 3px 0px rgba(0,0,0,0.4)",
|
||||
boxShadow: isDark
|
||||
? "0px 0px 3px 0px rgba(255,255,255,0.6)"
|
||||
: "0px 0px 3px 0px rgba(0,0,0,0.4)",
|
||||
overflow: "hidden",
|
||||
};
|
||||
} as const;
|
||||
|
||||
return (
|
||||
<Column style={[style, elementStyle]}>
|
||||
|
||||
@@ -1,12 +1,19 @@
|
||||
import { Select, Switch, Text, Icon, Row, Slider } from "native-base";
|
||||
import { MaterialIcons } from "@expo/vector-icons";
|
||||
export type ElementType =
|
||||
| "custom"
|
||||
| "default"
|
||||
| "text"
|
||||
| "toggle"
|
||||
| "dropdown"
|
||||
| "range";
|
||||
|
||||
export type ElementProps = {
|
||||
title: string;
|
||||
icon?: React.ReactNode;
|
||||
helperText?: string;
|
||||
description?: string;
|
||||
disabled?: boolean;
|
||||
} & (
|
||||
{ type: 'text', data : ElementTextProps } |
|
||||
{ type: 'toggle', data : ElementToggleProps } |
|
||||
{ type: 'dropdown', data : ElementDropdownProps } |
|
||||
{ type: 'range', data : ElementRangeProps } |
|
||||
{ type: 'custom', data : React.ReactNode }
|
||||
);
|
||||
|
||||
export type DropdownOption = {
|
||||
label: string;
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
} from "native-base";
|
||||
import useColorScheme from "../../hooks/colorScheme";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
import { ElementProps } from "./ElementList";
|
||||
import { ElementProps } from "./ElementTypes";
|
||||
import {
|
||||
getElementDropdownNode,
|
||||
getElementTextNode,
|
||||
@@ -121,28 +121,15 @@ export const RawElement = ({ element, isHovered }: RawElementProps) => {
|
||||
{(() => {
|
||||
switch (type) {
|
||||
case "text":
|
||||
return getElementTextNode(
|
||||
data as ElementTextProps,
|
||||
disabled ?? false
|
||||
);
|
||||
return getElementTextNode(data, disabled ?? false);
|
||||
case "toggle":
|
||||
return getElementToggleNode(
|
||||
data as ElementToggleProps,
|
||||
disabled ?? false
|
||||
);
|
||||
return getElementToggleNode(data, disabled ?? false);
|
||||
case "dropdown":
|
||||
return getElementDropdownNode(
|
||||
data as ElementDropdownProps,
|
||||
disabled ?? false
|
||||
);
|
||||
return getElementDropdownNode(data, disabled ?? false);
|
||||
case "range":
|
||||
return getElementRangeNode(
|
||||
data as ElementRangeProps,
|
||||
disabled ?? false,
|
||||
title
|
||||
);
|
||||
return getElementRangeNode(data, disabled ?? false, title);
|
||||
case "custom":
|
||||
return data as React.ReactNode;
|
||||
return data;
|
||||
default:
|
||||
return <Text>Unknown type</Text>;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ const handleChangePassword = async (oldPassword: string, newPassword: string): P
|
||||
}
|
||||
}
|
||||
|
||||
const MainView = ({navigation}) => {
|
||||
const MainView = ({ navigation }) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
@@ -73,7 +73,7 @@ const MainView = ({navigation}) => {
|
||||
)
|
||||
}
|
||||
|
||||
export const ChangePasswordView = ({navigation}) => {
|
||||
export const ChangePasswordView = ({ navigation }) => {
|
||||
return (
|
||||
<Center style={{ flex: 1}}>
|
||||
<Heading paddingBottom={'2%'}>{translate('changePassword')}</Heading>
|
||||
@@ -82,7 +82,7 @@ export const ChangePasswordView = ({navigation}) => {
|
||||
)
|
||||
}
|
||||
|
||||
export const ChangeEmailView = ({navigation}) => {
|
||||
export const ChangeEmailView = ({ navigation }) => {
|
||||
return (
|
||||
<Center style={{ flex: 1}}>
|
||||
<Heading paddingBottom={'2%'}>{translate('changeEmail')}</Heading>
|
||||
@@ -91,7 +91,7 @@ export const ChangeEmailView = ({navigation}) => {
|
||||
)
|
||||
}
|
||||
|
||||
export const GoogleAccountView = ({navigation}) => {
|
||||
export const GoogleAccountView = ({ navigation }) => {
|
||||
return (
|
||||
<Center style={{ flex: 1}}>
|
||||
<Text>GoogleAccount</Text>
|
||||
@@ -99,7 +99,7 @@ export const GoogleAccountView = ({navigation}) => {
|
||||
)
|
||||
}
|
||||
|
||||
export const PianoSettingsView = ({navigation}) => {
|
||||
export const PianoSettingsView = ({ navigation }) => {
|
||||
return (
|
||||
<Center style={{ flex: 1}}>
|
||||
<Text>Global settings for the virtual piano</Text>
|
||||
@@ -111,7 +111,7 @@ const TabRow = createTabRowNavigator();
|
||||
|
||||
const SetttingsNavigator = () => {
|
||||
const userQuery = useQuery(['user'], () => API.getUserInfo());
|
||||
const user = userQuery.data;
|
||||
const user = useMemo(() => userQuery.data, [userQuery]);
|
||||
|
||||
if (userQuery.isError) {
|
||||
user.isGuest = false;
|
||||
|
||||
+1394
-1139
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user