Remake the appbar

This commit is contained in:
Zoe Roux 2022-11-30 14:54:25 +09:00
parent ca50b53bae
commit 9a9538d14d
No known key found for this signature in database
GPG Key ID: B2AB52A2636E5C46
12 changed files with 91 additions and 143 deletions

View File

@ -19,17 +19,18 @@
*/ */
import { Stack } from "expo-router"; import { Stack } from "expo-router";
import { ThemeSelector } from "@kyoo/primitives"; import { Avatar, ThemeSelector } from "@kyoo/primitives";
import { useTheme } from "yoshiki/native"; import { useTheme } from "yoshiki/native";
import { NavbarTitle } from "@kyoo/ui"; import { NavbarTitle } from "@kyoo/ui";
const ThemedStack = () => { const ThemedStack = () => {
const theme = useTheme(); const theme = useTheme();
return ( return (
<Stack <Stack
screenOptions={{ screenOptions={{
headerTitle: () => <NavbarTitle />, headerTitle: () => <NavbarTitle />,
headerRight: () => <Avatar alt="login" />,
headerStyle: { headerStyle: {
backgroundColor: theme.appbar, backgroundColor: theme.appbar,
}, },

View File

@ -18,8 +18,7 @@
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>. * along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
*/ */
import { View } from "react-native"; import { Text, View } from "react-native";
import { Navbar } from "@kyoo/ui";
import { useYoshiki } from "yoshiki/native"; import { useYoshiki } from "yoshiki/native";
const App = () => { const App = () => {
@ -27,7 +26,8 @@ const App = () => {
return ( return (
<View {...css({ backgroundColor: (theme) => theme.background })}> <View {...css({ backgroundColor: (theme) => theme.background })}>
<Navbar /> {/* <Navbar /> */}
<Text>toto</Text>
</View> </View>
); );
}; };

View File

@ -21,7 +21,7 @@
"react-native-safe-area-context": "4.4.1", "react-native-safe-area-context": "4.4.1",
"react-native-screens": "~3.18.0", "react-native-screens": "~3.18.0",
"react-native-svg": "13.4.0", "react-native-svg": "13.4.0",
"yoshiki": "0.2.4" "yoshiki": "0.2.7"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.19.3", "@babel/core": "^7.19.3",

View File

@ -84,6 +84,7 @@ const nextConfig = {
"solito", "solito",
"react-native", "react-native",
"react-native-web", "react-native-web",
"react-native-svg",
"yoshiki", "yoshiki",
"@expo/vector-icons", "@expo/vector-icons",
"@expo/html-elements", "@expo/html-elements",

View File

@ -34,7 +34,7 @@
"react-native-web": "^0.18.10", "react-native-web": "^0.18.10",
"solito": "^2.0.5", "solito": "^2.0.5",
"superjson": "^1.11.0", "superjson": "^1.11.0",
"yoshiki": "0.2.4", "yoshiki": "0.2.7",
"zod": "^3.19.1" "zod": "^3.19.1"
}, },
"devDependencies": { "devDependencies": {

View File

@ -19,15 +19,28 @@
*/ */
import { View, ViewStyle } from "react-native"; import { View, ViewStyle } from "react-native";
import { Image } from "./"; import { Image } from "./image";
import { useYoshiki, px } from "yoshiki/native"; import { useYoshiki, px } from "yoshiki/native";
import { Icon } from "./icons";
export const Avatar = ({ src, alt, size = px(24) }: { src: string; alt: string; size: number }) => { export const Avatar = ({
src,
alt,
size = px(24),
}: {
src?: string;
alt: string;
size?: number;
}) => {
const { css } = useYoshiki(); const { css } = useYoshiki();
return ( return (
<View {...css({ borderRadius: size / 2, width: size, height: size })}> <View {...css({ borderRadius: size / 2, width: size, height: size })}>
<Image src={src} alt={alt} width={size} height={size} /> {src ? (
<Image src={src} alt={alt} width={size} height={size} />
) : (
<Icon icon="account-circle" size={size} />
)}
</View> </View>
); );
}; };

View File

@ -29,7 +29,7 @@ export type IconProps = {
}; };
export const Icon = ({ icon, size, color }: IconProps) => { export const Icon = ({ icon, size, color }: IconProps) => {
return <MIcon name={icon} size={size ?? 24} color={color} />; return <MIcon name={icon} size={size ?? 24} color={color ?? "white"} />;
}; };
export const IconButton = ({ export const IconButton = ({

View File

@ -19,15 +19,11 @@
*/ */
import { useState } from "react"; import { useState } from "react";
import { import { View, Image as Img, ImageSourcePropType, ImageStyle } from "react-native";
View, import { percent, useYoshiki } from "yoshiki/native";
Image as Img,
ImageSourcePropType,
} from "react-native";
import type { Property } from "csstype";
type ImageOptions = { type ImageOptions = {
radius?: string; radius?: number;
fallback?: string | ImageSourcePropType; fallback?: string | ImageSourcePropType;
}; };
@ -40,8 +36,8 @@ type ImagePropsWithLoading =
| (ImageProps & { loading?: boolean }) | (ImageProps & { loading?: boolean })
| (Partial<ImageProps> & { loading: true }); | (Partial<ImageProps> & { loading: true });
type Width = Property.Width<(string & {}) | 0>; type Width = ImageStyle["width"];
type Height = Property.Height<(string & {}) | 0>; type Height = ImageStyle["height"];
export const Image = ({ export const Image = ({
src, src,
@ -55,9 +51,10 @@ export const Image = ({
...others ...others
}: ImagePropsWithLoading & }: ImagePropsWithLoading &
( (
| { aspectRatio?: string; width: Width; height: Height } | { aspectRatio?: number; width: Width; height: Height }
| { aspectRatio: string; width?: Width; height?: Height } | { aspectRatio: number; width?: Width; height?: Height }
)) => { )) => {
const { css } = useYoshiki();
const [showLoading, setLoading] = useState<boolean>(loading); const [showLoading, setLoading] = useState<boolean>(loading);
const [source, setSource] = useState(src); const [source, setSource] = useState(src);
/* const imgRef = useRef<Img>(null); */ /* const imgRef = useRef<Img>(null); */
@ -70,16 +67,18 @@ export const Image = ({
return ( return (
<View <View
css={{ {...css(
aspectRatio, {
width, aspectRatio,
height, width,
/* backgroundColor: "grey.300", */ height,
borderRadius: radius, /* backgroundColor: "grey.300", */
overflow: "hidden", borderRadius: radius,
"& > *": { width: "100%", height: "100%" }, overflow: "hidden",
}} /* "& > *": { width: "100%", height: "100%" }, */
{...others} },
others,
)}
> >
{/* {showLoading && <Skeleton variant="rectangular" height="100%" />} */} {/* {showLoading && <Skeleton variant="rectangular" height="100%" />} */}
{!loading && source && ( {!loading && source && (
@ -91,7 +90,12 @@ export const Image = ({
if (fallback) setSource(fallback); if (fallback) setSource(fallback);
else setLoading(false); else setLoading(false);
}} }}
css={{ objectFit: "cover", display: showLoading ? "hidden" : undefined }} {...css({
height: percent(100),
width: percent(100),
resizeMode: "cover",
/* display: showLoading ? "hidden" : undefined, */
})}
/> />
)} )}
</View> </View>
@ -99,5 +103,5 @@ export const Image = ({
}; };
export const Poster = (props: ImagePropsWithLoading & { width?: Width; height?: Height }) => ( export const Poster = (props: ImagePropsWithLoading & { width?: Width; height?: Height }) => (
<Image aspectRatio="2 / 3" {...props} /> <Image aspectRatio={2 / 3} {...props} />
); );

View File

@ -36,9 +36,11 @@ import Svg, { SvgProps, Path } from "react-native-svg";
/* </Svg> */ /* </Svg> */
/* ); */ /* ); */
export const KyooLongLogo = (props: SvgProps) => export const KyooLongLogo = ({
( height = 24,
<Svg viewBox="49.954 131.833 318.13 108.676" {...props}> ...props
}: Omit<SvgProps, "width" | "height"> & { height?: number }) => (
<Svg viewBox="49.954 131.833 318.13 108.676" height={height} width={height * 2.9272} {...props}>
<Path <Path
d="m164.844 186.759-114.89-53.76v107.51l114.89-53.75Z" d="m164.844 186.759-114.89-53.76v107.51l114.89-53.75Z"
fill="#121327" fill="#121327"

View File

@ -22,44 +22,14 @@ import useTranslation from "next-translate/useTranslation";
/* import { Library, LibraryP, Page, Paged } from "~/models"; */ /* import { Library, LibraryP, Page, Paged } from "~/models"; */
/* import { QueryIdentifier, useFetch } from "~/utils/query"; */ /* import { QueryIdentifier, useFetch } from "~/utils/query"; */
/* import { ErrorSnackbar } from "./errors"; */ /* import { ErrorSnackbar } from "./errors"; */
import { Stylable, useYoshiki } from "yoshiki/native"; import { useYoshiki } from "yoshiki/native";
import { IconButton, Header, P, A, ts } from "@kyoo/primitives"; import { IconButton, Header, Avatar, A, ts } from "@kyoo/primitives";
import { Image, View } from "react-native"; import { View } from "react-native";
import { KyooLongLogo } from "./icon";
const tooltip = (tooltip: string): object => ({}); const tooltip = (tooltip: string): object => ({});
export const NavbarTitle = (props: Stylable) => { export const NavbarTitle = KyooLongLogo;
const { css } = useYoshiki();
const { t } = useTranslation("common");
return (
<A
href="/"
{...tooltip(t("navbar.home"))}
{...css(
{
alignItems: "center",
display: "flex",
},
props,
)}
>
{/* <Image source={"/icon.svg"} width="24px" height="24px" alt="" /> */}
<P
{...css({
marginLeft: ts(1),
marginRight: ts(2),
fontFamily: "monospace",
fontWeight: "700",
textTransform: "uppercase",
color: "white",
})}
>
Kyoo
</P>
</A>
);
};
export const Navbar = () => { export const Navbar = () => {
const { css } = useYoshiki(); const { css } = useYoshiki();
@ -70,8 +40,19 @@ export const Navbar = () => {
<Header <Header
{...css({ {...css({
backgroundColor: (theme) => theme.appbar, backgroundColor: (theme) => theme.appbar,
paddingX: ts(2),
height: { xs: 48, sm: 64 },
flexDirection: "row", flexDirection: "row",
justifyContent: { xs: "space-between", sm: "flex-start" },
alignItems: "center", alignItems: "center",
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 4,
},
shadowOpacity: 0.3,
shadowRadius: 4.65,
elevation: 8,
})} })}
> >
<IconButton <IconButton
@ -82,10 +63,15 @@ export const Navbar = () => {
color="white" color="white"
{...css({ display: { xs: "flex", sm: "none" } })} {...css({ display: { xs: "flex", sm: "none" } })}
/> />
{/* <Box sx={{ flexGrow: 1, display: { sx: "flex", sm: "none" } }} /> */} <NavbarTitle {...css({ marginX: ts(2) })} />
<NavbarTitle {...css({ marginRight: ts(1) })} /> <View
{/* <Box sx={{ flexGrow: 1, display: { sx: "flex", sm: "none" } }} /> */} {...css({
<View {...css({ flexGrow: 1, flexDirection: "row", display: { xs: "none", sm: "flex" } })}> flexGrow: 1,
flexDirection: "row",
display: { xs: "none", sm: "flex" },
marginLeft: ts(2),
})}
>
{ {
/*isSuccess /*isSuccess
? data.items.map((library) => */ true ? data.items.map((library) => */ true
@ -111,8 +97,8 @@ export const Navbar = () => {
) )
} }
</View> </View>
<A href="/auth/login" {...tooltip(t("navbar.login"))} {...css({ p: 0 })}> <A href="/auth/login" {...tooltip(t("navbar.login"))}>
{/* <Avatar alt={t("navbar.login")} /> */} <Avatar alt={t("navbar.login")} size={30} />
</A> </A>
{/* {isError && <ErrorSnackbar error={error} />} */} {/* {isError && <ErrorSnackbar error={error} />} */}
</Header> </Header>

View File

@ -1,59 +0,0 @@
/*
* Kyoo - A portable and vast media library solution.
* Copyright (c) Kyoo.
*
* See AUTHORS.md and LICENSE file in the project root for full license information.
*
* Kyoo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* Kyoo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
*/
import { Paragraph } from "@kyoo/primitives";
import { View } from "react-native";
import { KyooLongLogo } from "./icon";
export const Navbar = () => {
/* const { t } = useTranslation("common"); */
/* const { data, error, isSuccess, isError } = useFetch(Navbar.query()); */
return (
<View css={(theme) => ({ backgroundColor: theme.appbar })}>
<KyooLongLogo height="64px" width="auto" />
<Paragraph>Toto</Paragraph>
{/* <Box sx={{ flexGrow: 1, display: { xs: "none", sm: "flex" } }}> */}
{/* {isSuccess */}
{/* ? data.items.map((library) => ( */}
{/* <ButtonLink */}
{/* href={`/browse/${library.slug}`} */}
{/* key={library.slug} */}
{/* sx={{ color: "white" }} */}
{/* > */}
{/* {library.name} */}
{/* </ButtonLink> */}
{/* )) */}
{/* : [...Array(4)].map((_, i) => ( */}
{/* <Typography key={i} variant="button" px=".25rem"> */}
{/* <Skeleton width="5rem" /> */}
{/* </Typography> */}
{/* ))} */}
{/* </Box> */}
<View>{/* <Avatar alt={t("navbar.login")} /> */}</View>
{/* {isError && <ErrorSnackbar error={error} />} */}
</View>
);
};
/* Navbar.query = (): QueryIdentifier<Page<Library>> => ({ */
/* parser: Paged(LibraryP), */
/* path: ["libraries"], */
/* }); */

View File

@ -9459,7 +9459,7 @@ __metadata:
react-native-screens: ~3.18.0 react-native-screens: ~3.18.0
react-native-svg: 13.4.0 react-native-svg: 13.4.0
typescript: ^4.6.3 typescript: ^4.6.3
yoshiki: 0.2.4 yoshiki: 0.2.7
languageName: unknown languageName: unknown
linkType: soft linkType: soft
@ -12935,7 +12935,7 @@ __metadata:
superjson: ^1.11.0 superjson: ^1.11.0
typescript: ^4.9.3 typescript: ^4.9.3
webpack: ^5.75.0 webpack: ^5.75.0
yoshiki: 0.2.4 yoshiki: 0.2.7
zod: ^3.19.1 zod: ^3.19.1
languageName: unknown languageName: unknown
linkType: soft linkType: soft
@ -13260,9 +13260,9 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"yoshiki@npm:0.2.4": "yoshiki@npm:0.2.7":
version: 0.2.4 version: 0.2.7
resolution: "yoshiki@npm:0.2.4" resolution: "yoshiki@npm:0.2.7"
dependencies: dependencies:
"@types/node": 18.x.x "@types/node": 18.x.x
"@types/react": 18.x.x "@types/react": 18.x.x
@ -13277,7 +13277,7 @@ __metadata:
optional: true optional: true
react-native-web: react-native-web:
optional: true optional: true
checksum: 7046d777a5726661ed7a4a0f6e67600740ccbbb23c833f5cb6a2f5029d6bbd3357426dd02a2b1c759b89faf832fec9ee712c8b10fbdb846dec4a2bd32f229ca4 checksum: 5589cde181d2825a9c25d0ec51b99873a335869989314c3cee3a4503444344a546ccc4705e1a0f76a4ec4faaa14433ae96fa8e2024d6550498b61b193c0fba5f
languageName: node languageName: node
linkType: hard linkType: hard