start with movie-web page

This commit is contained in:
Jorrin
2024-04-15 19:34:42 +02:00
parent 0622e4338c
commit 07d313b1fd
6 changed files with 224 additions and 21 deletions

View File

@@ -1,5 +1,60 @@
import { useState } from "react";
import { Link } from "expo-router";
import { H2, H5, Paragraph, View } from "tamagui";
import ScreenLayout from "~/components/layout/ScreenLayout"; import ScreenLayout from "~/components/layout/ScreenLayout";
import { MWButton } from "~/components/ui/Button";
import { MWCard } from "~/components/ui/Card";
import { MWInput } from "~/components/ui/Input";
export default function MovieWebScreen() { export default function MovieWebScreen() {
return <ScreenLayout></ScreenLayout>; const [url, setUrl] = useState("https://mw-backend.lonelil.ru");
return (
<ScreenLayout
contentContainerStyle={{
flexGrow: 1,
alignItems: "center",
justifyContent: "center",
}}
>
<MWCard bordered>
<MWCard.Header padded>
<H2 fontWeight="$bold" paddingBottom="$1">
Sync to the cloud
</H2>
<H5 color="$ash50" fontWeight="$semibold" paddingVertical="$3">
Share your watch progress between devices and keep them synced.
</H5>
<Paragraph color="$ash50">
First choose the backend you want to use. If you do not know what
this does, use the default and click on &apos;Get started&apos;.
</Paragraph>
</MWCard.Header>
<View padding="$4">
<MWInput
placeholder="https://mw-backend.lonelil.ru"
type="search"
value={url}
onChangeText={setUrl}
/>
</View>
<MWCard.Footer padded justifyContent="center">
<MWButton type="purple">
<Link
href={{
pathname: "/sync/trust/[url]",
params: { url },
}}
style={{ color: "white", fontWeight: "bold" }}
>
Get started
</Link>
</MWButton>
</MWCard.Footer>
</MWCard>
</ScreenLayout>
);
} }

View File

@@ -0,0 +1,14 @@
import { Stack } from "expo-router";
import { BrandPill } from "~/components/BrandPill";
export default function Layout() {
return (
<Stack
screenOptions={{
headerTransparent: true,
headerRight: BrandPill,
}}
/>
);
}

View File

@@ -0,0 +1,117 @@
import { Stack, useLocalSearchParams } from "expo-router";
import { useQuery } from "@tanstack/react-query";
import { H4, Paragraph, Text, View } from "tamagui";
import ScreenLayout from "~/components/layout/ScreenLayout";
import { MWButton } from "~/components/ui/Button";
import { MWCard } from "~/components/ui/Card";
// TODO: extract to function with cleanup and types
const getBackendMeta = (
url: string,
): Promise<{
description: string;
hasCaptcha: boolean;
name: string;
url: string;
}> => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return fetch(`${url}/meta`).then((res) => res.json());
};
export default function Page() {
const { url } = useLocalSearchParams();
const meta = useQuery({
queryKey: ["backendMeta", url],
queryFn: () => getBackendMeta(url as string),
});
return (
<ScreenLayout
showHeader={false}
contentContainerStyle={{
flexGrow: 1,
alignItems: "center",
justifyContent: "center",
}}
>
<Stack.Screen
options={{
title: "",
}}
/>
<MWCard bordered>
<MWCard.Header padded>
<H4 fontWeight="$bold" textAlign="center">
Do you trust this server?
</H4>
<Paragraph
color="$ash50"
textAlign="center"
fontWeight="$semibold"
paddingVertical="$4"
>
{meta.isLoading && "Loading..."}
{meta.isError && "Error loading metadata"}
{meta.isSuccess && (
<>
You are connecting to{" "}
<Text
fontWeight="$bold"
color="white"
textDecorationLine="underline"
>
{url}
</Text>
. Please confirm you trust it before making an account.
</>
)}
</Paragraph>
</MWCard.Header>
{meta.isSuccess && (
<View
borderColor="$shade200"
borderWidth="$0.5"
borderRadius="$8"
paddingHorizontal="$5"
paddingVertical="$4"
width="90%"
alignSelf="center"
>
<Text
fontWeight="$bold"
paddingBottom="$1"
textAlign="center"
fontSize="$4"
>
{meta.data.name}
</Text>
<Paragraph color="$ash50" textAlign="center">
{meta.data.description}
</Paragraph>
</View>
)}
<MWCard.Footer
padded
justifyContent="center"
flexDirection="column"
gap="$4"
>
<MWButton type="purple">I trust this server</MWButton>
<MWButton type="secondary">Go back</MWButton>
<Paragraph color="$ash50" textAlign="center" fontWeight="$semibold">
Already have an account?{" "}
<Text color="$purple100" fontWeight="$bold">
Login here
</Text>
</Paragraph>
</MWCard.Footer>
</MWCard>
</ScreenLayout>
);
}

View File

@@ -1,3 +1,4 @@
import type { ScrollViewProps } from "tamagui";
import { useSafeAreaInsets } from "react-native-safe-area-context"; import { useSafeAreaInsets } from "react-native-safe-area-context";
import { ScrollView } from "tamagui"; import { ScrollView } from "tamagui";
import { LinearGradient } from "tamagui/linear-gradient"; import { LinearGradient } from "tamagui/linear-gradient";
@@ -5,26 +6,14 @@ import { LinearGradient } from "tamagui/linear-gradient";
import { Header } from "./Header"; import { Header } from "./Header";
interface Props { interface Props {
children?: React.ReactNode;
onScrollBeginDrag?: () => void;
onMomentumScrollEnd?: () => void;
showHeader?: boolean; showHeader?: boolean;
scrollEnabled?: boolean;
keyboardDismissMode?: "none" | "on-drag" | "interactive";
keyboardShouldPersistTaps?: "always" | "never" | "handled";
contentContainerStyle?: Record<string, unknown>;
} }
export default function ScreenLayout({ export default function ScreenLayout({
children, children,
onScrollBeginDrag,
onMomentumScrollEnd,
showHeader = true, showHeader = true,
scrollEnabled, ...props
keyboardDismissMode, }: ScrollViewProps & Props) {
keyboardShouldPersistTaps,
contentContainerStyle,
}: Props) {
const insets = useSafeAreaInsets(); const insets = useSafeAreaInsets();
return ( return (
@@ -47,15 +36,10 @@ export default function ScreenLayout({
> >
{showHeader && <Header />} {showHeader && <Header />}
<ScrollView <ScrollView
onScrollBeginDrag={onScrollBeginDrag}
onMomentumScrollEnd={onMomentumScrollEnd}
scrollEnabled={scrollEnabled}
keyboardDismissMode={keyboardDismissMode}
keyboardShouldPersistTaps={keyboardShouldPersistTaps}
contentContainerStyle={contentContainerStyle}
marginTop="$4" marginTop="$4"
flexGrow={1} flexGrow={1}
showsVerticalScrollIndicator={false} showsVerticalScrollIndicator={false}
{...props}
> >
{children} {children}
</ScrollView> </ScrollView>

View File

@@ -7,21 +7,33 @@ export const MWButton = styled(Button, {
backgroundColor: "$buttonPrimaryBackground", backgroundColor: "$buttonPrimaryBackground",
color: "$buttonPrimaryText", color: "$buttonPrimaryText",
fontWeight: "bold", fontWeight: "bold",
pressStyle: {
backgroundColor: "$buttonPrimaryBackgroundHover",
},
}, },
secondary: { secondary: {
backgroundColor: "$buttonSecondaryBackground", backgroundColor: "$buttonSecondaryBackground",
color: "$buttonSecondaryText", color: "$buttonSecondaryText",
fontWeight: "bold", fontWeight: "bold",
pressStyle: {
backgroundColor: "$buttonSecondaryBackgroundHover",
},
}, },
purple: { purple: {
backgroundColor: "$buttonPurpleBackground", backgroundColor: "$buttonPurpleBackground",
color: "white", color: "white",
fontWeight: "bold", fontWeight: "bold",
pressStyle: {
backgroundColor: "$buttonPurpleBackgroundHover",
},
}, },
cancel: { cancel: {
backgroundColor: "$buttonCancelBackground", backgroundColor: "$buttonCancelBackground",
color: "white", color: "white",
fontWeight: "bold", fontWeight: "bold",
pressStyle: {
backgroundColor: "$buttonCancelBackgroundHover",
},
}, },
}, },
} as const, } as const,

View File

@@ -0,0 +1,21 @@
import { Card, styled, withStaticProperties } from "tamagui";
export const MWCardFrame = styled(Card, {
backgroundColor: "$shade400",
borderColor: "$shade400",
variants: {
bordered: {
true: {
borderWidth: 1,
borderColor: "$shade500",
},
},
},
});
export const MWCard = withStaticProperties(MWCardFrame, {
Header: Card.Header,
Footer: Card.Footer,
Background: Card.Background,
});