mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-24 02:02:36 -04:00
Add basics touch controls for the player
This commit is contained in:
parent
d593eb3134
commit
e13f2a7e42
@ -26,6 +26,7 @@ export default withRoute(
|
||||
{
|
||||
options: {
|
||||
headerShown: false,
|
||||
navigationBarHidden: true,
|
||||
},
|
||||
statusBar: { hidden: true },
|
||||
fullscreen: true,
|
||||
|
@ -26,6 +26,7 @@ export default withRoute(
|
||||
{
|
||||
options: {
|
||||
headerShown: false,
|
||||
navigationBarHidden: true,
|
||||
},
|
||||
statusBar: { hidden: true },
|
||||
fullscreen: true,
|
||||
|
@ -22,7 +22,7 @@ import "../polyfill";
|
||||
|
||||
import { HydrationBoundary, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
||||
import { HiddenIfNoJs, SkeletonCss, ThemeSelector } from "@kyoo/primitives";
|
||||
import { HiddenIfNoJs, TouchOnlyCss, SkeletonCss, ThemeSelector } from "@kyoo/primitives";
|
||||
import { WebTooltip } from "@kyoo/primitives/src/tooltip.web";
|
||||
import {
|
||||
AccountProvider,
|
||||
@ -96,6 +96,7 @@ const GlobalCssTheme = () => {
|
||||
`}</style>
|
||||
<WebTooltip theme={theme} />
|
||||
<SkeletonCss />
|
||||
<TouchOnlyCss />
|
||||
<HiddenIfNoJs />
|
||||
</>
|
||||
);
|
||||
|
@ -23,3 +23,4 @@ export * from "./nojs";
|
||||
export * from "./head";
|
||||
export * from "./spacing";
|
||||
export * from "./capitalize";
|
||||
export * from "./touchonly";
|
||||
|
41
front/packages/primitives/src/utils/touchonly.tsx
Normal file
41
front/packages/primitives/src/utils/touchonly.tsx
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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 { Platform, ViewProps } from "react-native";
|
||||
|
||||
export const TouchOnlyCss = () => {
|
||||
return (
|
||||
<style jsx global>{`
|
||||
:where(body.noHover) .noTouch {
|
||||
display: none;
|
||||
}
|
||||
:where(body:not(.noHover)) .touchOnly {
|
||||
display: none;
|
||||
}
|
||||
`}</style>
|
||||
);
|
||||
};
|
||||
|
||||
export const touchOnly: ViewProps = {
|
||||
style: Platform.OS === "web" ? ({ $$css: true, touchOnly: "touchOnly" } as any) : {},
|
||||
};
|
||||
export const noTouch: ViewProps = {
|
||||
style: Platform.OS === "web" ? ({ $$css: true, noTouch: "noTouch" } as any) : { display: "none" },
|
||||
};
|
@ -31,6 +31,7 @@ import {
|
||||
Skeleton,
|
||||
Slider,
|
||||
tooltip,
|
||||
touchOnly,
|
||||
ts,
|
||||
} from "@kyoo/primitives";
|
||||
import { Chapter, KyooImage, Subtitle, Audio } from "@kyoo/models";
|
||||
@ -40,7 +41,7 @@ import { useTranslation } from "react-i18next";
|
||||
import { percent, rem, useYoshiki } from "yoshiki/native";
|
||||
import { useRouter } from "solito/router";
|
||||
import ArrowBack from "@material-symbols/svg-400/rounded/arrow_back-fill.svg";
|
||||
import { LeftButtons } from "./left-buttons";
|
||||
import { LeftButtons, TouchControls } from "./left-buttons";
|
||||
import { RightButtons } from "./right-buttons";
|
||||
import { bufferedAtom, durationAtom, loadAtom, playAtom, progressAtom } from "../state";
|
||||
|
||||
@ -84,6 +85,7 @@ export const Hover = ({
|
||||
{({ css }) => (
|
||||
<>
|
||||
<Back isLoading={isLoading} name={showName} href={href} {...css(opacity, props)} />
|
||||
<TouchControls previousSlug={previousSlug} nextSlug={nextSlug} />
|
||||
<Pressable
|
||||
tabIndex={-1}
|
||||
onPointerDown={onPointerDown}
|
||||
@ -144,7 +146,7 @@ export const Hover = ({
|
||||
);
|
||||
};
|
||||
|
||||
export const ProgressBar = ({ chapters }: { chapters?: Chapter[] }) => {
|
||||
const ProgressBar = ({ chapters }: { chapters?: Chapter[] }) => {
|
||||
const [progress, setProgress] = useAtom(progressAtom);
|
||||
const buffered = useAtomValue(bufferedAtom);
|
||||
const duration = useAtomValue(durationAtom);
|
||||
@ -163,7 +165,7 @@ export const ProgressBar = ({ chapters }: { chapters?: Chapter[] }) => {
|
||||
);
|
||||
};
|
||||
|
||||
export const Back = ({
|
||||
const Back = ({
|
||||
isLoading,
|
||||
name,
|
||||
href,
|
||||
|
@ -18,10 +18,20 @@
|
||||
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { IconButton, Link, P, Slider, tooltip, ts } from "@kyoo/primitives";
|
||||
import {
|
||||
IconButton,
|
||||
Link,
|
||||
NoTouch,
|
||||
P,
|
||||
Slider,
|
||||
noTouch,
|
||||
tooltip,
|
||||
touchOnly,
|
||||
ts,
|
||||
} from "@kyoo/primitives";
|
||||
import { useAtom, useAtomValue } from "jotai";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { View } from "react-native";
|
||||
import { Platform, View } from "react-native";
|
||||
import SkipPrevious from "@material-symbols/svg-400/rounded/skip_previous-fill.svg";
|
||||
import SkipNext from "@material-symbols/svg-400/rounded/skip_next-fill.svg";
|
||||
import PlayArrow from "@material-symbols/svg-400/rounded/play_arrow-fill.svg";
|
||||
@ -31,7 +41,8 @@ import VolumeMute from "@material-symbols/svg-400/rounded/volume_mute-fill.svg";
|
||||
import VolumeDown from "@material-symbols/svg-400/rounded/volume_down-fill.svg";
|
||||
import VolumeUp from "@material-symbols/svg-400/rounded/volume_up-fill.svg";
|
||||
import { durationAtom, mutedAtom, playAtom, progressAtom, volumeAtom } from "../state";
|
||||
import { px, useYoshiki } from "yoshiki/native";
|
||||
import { Stylable, px, useYoshiki } from "yoshiki/native";
|
||||
import { Component, ComponentProps } from "react";
|
||||
|
||||
export const LeftButtons = ({
|
||||
previousSlug,
|
||||
@ -48,12 +59,76 @@ export const LeftButtons = ({
|
||||
|
||||
return (
|
||||
<View {...css({ flexDirection: "row" })}>
|
||||
<View {...css({ flexDirection: "row" }, noTouch)}>
|
||||
{previousSlug && (
|
||||
<IconButton
|
||||
icon={SkipPrevious}
|
||||
as={Link}
|
||||
href={previousSlug}
|
||||
replace
|
||||
{...tooltip(t("player.previous"), true)}
|
||||
{...spacing}
|
||||
/>
|
||||
)}
|
||||
<IconButton
|
||||
icon={isPlaying ? Pause : PlayArrow}
|
||||
onPress={() => setPlay(!isPlaying)}
|
||||
{...tooltip(isPlaying ? t("player.pause") : t("player.play"), true)}
|
||||
{...spacing}
|
||||
/>
|
||||
{nextSlug && (
|
||||
<IconButton
|
||||
icon={SkipNext}
|
||||
as={Link}
|
||||
href={nextSlug}
|
||||
replace
|
||||
{...tooltip(t("player.next"), true)}
|
||||
{...spacing}
|
||||
/>
|
||||
)}
|
||||
{Platform.OS === "web" && <VolumeSlider />}
|
||||
</View>
|
||||
<ProgressText {...css({ marginLeft: ts(1) })} />
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export const TouchControls = ({
|
||||
previousSlug,
|
||||
nextSlug,
|
||||
}: {
|
||||
previousSlug?: string | null;
|
||||
nextSlug?: string | null;
|
||||
}) => {
|
||||
const { css } = useYoshiki();
|
||||
const { t } = useTranslation();
|
||||
const [isPlaying, setPlay] = useAtom(playAtom);
|
||||
|
||||
const spacing = css({ backgroundColor: (theme) => theme.darkOverlay, marginHorizontal: ts(3) });
|
||||
|
||||
return (
|
||||
<View
|
||||
{...css(
|
||||
{
|
||||
flexDirection: "row",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
},
|
||||
touchOnly,
|
||||
)}
|
||||
>
|
||||
{previousSlug && (
|
||||
<IconButton
|
||||
icon={SkipPrevious}
|
||||
as={Link}
|
||||
href={previousSlug}
|
||||
replace
|
||||
size={ts(4)}
|
||||
{...tooltip(t("player.previous"), true)}
|
||||
{...spacing}
|
||||
/>
|
||||
@ -61,6 +136,7 @@ export const LeftButtons = ({
|
||||
<IconButton
|
||||
icon={isPlaying ? Pause : PlayArrow}
|
||||
onPress={() => setPlay(!isPlaying)}
|
||||
size={ts(8)}
|
||||
{...tooltip(isPlaying ? t("player.pause") : t("player.play"), true)}
|
||||
{...spacing}
|
||||
/>
|
||||
@ -70,16 +146,14 @@ export const LeftButtons = ({
|
||||
as={Link}
|
||||
href={nextSlug}
|
||||
replace
|
||||
size={ts(4)}
|
||||
{...tooltip(t("player.next"), true)}
|
||||
{...spacing}
|
||||
/>
|
||||
)}
|
||||
<VolumeSlider />
|
||||
<ProgressText />
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const VolumeSlider = () => {
|
||||
const [volume, setVolume] = useAtom(volumeAtom);
|
||||
const [isMuted, setMuted] = useAtom(mutedAtom);
|
||||
@ -119,13 +193,13 @@ const VolumeSlider = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const ProgressText = () => {
|
||||
const ProgressText = (props: Stylable) => {
|
||||
const progress = useAtomValue(progressAtom);
|
||||
const duration = useAtomValue(durationAtom);
|
||||
const { css } = useYoshiki();
|
||||
|
||||
return (
|
||||
<P {...css({ alignSelf: "center" })}>
|
||||
<P {...css({ alignSelf: "center" }, props)}>
|
||||
{toTimerString(progress, duration)} : {toTimerString(duration)}
|
||||
</P>
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user