diff --git a/src/components/player/atoms/SkipIntroButton.tsx b/src/components/player/atoms/SkipIntroButton.tsx
new file mode 100644
index 00000000..487bfc39
--- /dev/null
+++ b/src/components/player/atoms/SkipIntroButton.tsx
@@ -0,0 +1,92 @@
+import classNames from "classnames";
+import { useCallback } from "react";
+
+import { Icon, Icons } from "@/components/Icon";
+import { Transition } from "@/components/utils/Transition";
+import { usePlayerStore } from "@/stores/player/store";
+
+function shouldShowSkipButton(
+ currentTime: number,
+ skipTime?: number | null,
+): "always" | "hover" | "none" {
+ if (typeof skipTime !== "number") return "none";
+
+ // Show button from beginning until the skip point
+ if (currentTime >= 0 && currentTime < skipTime) {
+ return "always";
+ }
+
+ return "none";
+}
+
+function Button(props: {
+ className: string;
+ onClick?: () => void;
+ children: React.ReactNode;
+}) {
+ return (
+
+ );
+}
+
+export function SkipIntroButton(props: {
+ controlsShowing: boolean;
+ skipTime?: number | null;
+}) {
+ const time = usePlayerStore((s) => s.progress.time);
+ const status = usePlayerStore((s) => s.status);
+ const display = usePlayerStore((s) => s.display);
+
+ const showingState = shouldShowSkipButton(time, props.skipTime);
+
+ let show = false;
+ if (showingState === "always") show = true;
+ else if (showingState === "hover" && props.controlsShowing) show = true;
+ if (status !== "playing") show = false;
+
+ const animation = showingState === "hover" ? "slide-up" : "fade";
+ let bottom = "bottom-[calc(6rem+env(safe-area-inset-bottom))]";
+ if (showingState === "always") {
+ bottom = props.controlsShowing
+ ? bottom
+ : "bottom-[calc(3rem+env(safe-area-inset-bottom))]";
+ }
+
+ const handleSkip = useCallback(() => {
+ if (typeof props.skipTime === "number" && display) {
+ display.setTime(props.skipTime);
+ }
+ }, [props.skipTime, display]);
+
+ return (
+
+
+
+
+
+ );
+}
diff --git a/src/pages/parts/player/PlayerPart.tsx b/src/pages/parts/player/PlayerPart.tsx
index d52e6de5..e2af264a 100644
--- a/src/pages/parts/player/PlayerPart.tsx
+++ b/src/pages/parts/player/PlayerPart.tsx
@@ -1,10 +1,11 @@
-import { ReactNode, useCallback, useEffect, useState } from "react";
+import { ReactNode, useState } from "react";
import { useParams } from "react-router-dom";
import IosPwaLimitations from "@/components/buttons/IosPwaLimitations";
import { Icon, Icons } from "@/components/Icon";
import { BrandPill } from "@/components/layout/BrandPill";
import { Player } from "@/components/player";
+import { SkipIntroButton } from "@/components/player/atoms/SkipIntroButton";
import { Widescreen } from "@/components/player/atoms/Widescreen";
import { usePlayerMeta } from "@/components/player/hooks/usePlayerMeta";
import { useShouldShowControls } from "@/components/player/hooks/useShouldShowControls";
@@ -33,7 +34,6 @@ export function PlayerPart(props: PlayerPartProps) {
const { isMobile } = useIsMobile();
const isLoading = usePlayerStore((s) => s.mediaPlaying.isLoading);
const { playerMeta: meta } = usePlayerMeta();
- const display = usePlayerStore((s) => s.display);
const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
const isIOSPWA =
@@ -54,22 +54,7 @@ export function PlayerPart(props: PlayerPartProps) {
}
});
- // Fullscreen on rotation horizontal
- const onRotate = useCallback(() => {
- if (window.orientation === 90 || window.orientation === -90) {
- if (!document.fullscreenElement && status === playerStatus.PLAYING) {
- display?.toggleFullscreen();
- }
- } else if (document.fullscreenElement && status === playerStatus.PLAYING) {
- display?.toggleFullscreen();
- }
- }, [display, status]);
- useEffect(() => {
- window.addEventListener("orientationchange", onRotate);
- return () => {
- window.removeEventListener("orientationchange", onRotate);
- };
- }, [onRotate]);
+ const skiptime = null;
return (
@@ -237,6 +222,8 @@ export function PlayerPart(props: PlayerPartProps) {
controlsShowing={showTargets}
onChange={props.onMetaChange}
/>
+
+
);
}