Skip to content

Commit

Permalink
Merge 3d783b1 into 607d175
Browse files Browse the repository at this point in the history
  • Loading branch information
shakyShane authored Aug 7, 2024
2 parents 607d175 + 3d783b1 commit 3aab8b8
Show file tree
Hide file tree
Showing 91 changed files with 3,466 additions and 1,429 deletions.
1 change: 0 additions & 1 deletion packages/special-pages/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,6 @@ for (const buildJob of buildJobs) {
format: 'iife',
// external: ['../assets/img/*'],
sourcemap: NODE_ENV === 'development',
// publicPath: '/js',
loader: {
'.js': 'jsx',
'.module.css': 'local-css',
Expand Down
4 changes: 3 additions & 1 deletion packages/special-pages/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@
"test": "npm run test.unit && playwright test",
"test.windows": "npm run test -- --project windows",
"test.macos": "npm run test -- --project macos",
"test.ios": "npm run test -- --project ios",
"test.android": "npm run test -- --project android",
"test.headed": "npm run test -- --headed",
"test.ui": "npm run test -- --ui",
"test.unit": "node --test unit-test/* ",
"test.unit": "node --test unit-test/* pages/duckplayer/unit-tests/* ",
"pretest": "npm run build.dev",
"pretest.headed": "npm run build.dev",
"test-int-x": "npm run test",
Expand Down
35 changes: 35 additions & 0 deletions packages/special-pages/pages/duckplayer/app/base.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
*, *:after, *:before {
box-sizing: border-box
}
html[data-reduced-motion=true] * {
animation: none!important;
transition: none!important;
}
/* Base styles */
body {
font-family: system-ui, sans-serif;
font-size: 13px;
margin: 0;

height: 100vh;
width: 100%;
overflow-x: hidden;

/* Make it feel more like something native */
user-select: none;
-webkit-user-select: none;
cursor: default;
}
button {
font-family: system-ui, sans-serif;
font-size: 13px;
}
ul {
margin: 0;
padding: 0;
}
li {
list-style: none;
margin: 0;
padding: 0;
}
199 changes: 199 additions & 0 deletions packages/special-pages/pages/duckplayer/app/components/App.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
import { h, Fragment } from "preact";
import cn from "classnames";
import styles from "./App.module.css";
import { Background } from "./Background.jsx";
import { InfoBar, InfoBarContainer } from "./InfoBar.jsx";
import { PlayerContainer, PlayerInternal } from "./PlayerContainer.jsx";
import { Player, PlayerError } from "./Player.jsx";
import {
useLayout,
useOpenInfoHandler,
useOpenOnYoutubeHandler,
useOpenSettingsHandler, usePlatformName, useSettings
} from "../providers/SettingsProvider.jsx";
import { SwitchBarMobile } from "./SwitchBarMobile.jsx";
import { Button, Icon } from "./Button.jsx";
import info from "../img/info.data.svg";
import cog from "../img/cog.data.svg";
import { BottomNavBar, FloatingBar, TopBar } from "./FloatingBar.jsx";
import { Wordmark } from "./Wordmark.jsx";
import { SwitchProvider } from "../providers/SwitchProvider.jsx";
import { useOrientation } from "../providers/OrientationProvider.jsx";
import { createAppFeaturesFrom } from "../features/app.js";
import { useTypedTranslation } from "../types.js";
import { HideInFocusMode } from "./FocusMode.jsx";


/**
* @param {object} props
* @param {import("../embed-settings.js").EmbedSettings|null} props.embed
*/
export function App({ embed }) {
const layout = useLayout();
const orientation = useOrientation();
const settings = useSettings();
const features = createAppFeaturesFrom(settings)
return (
<>
<Background />
{features.focusMode()}
<main class={styles.app}>
{layout === 'desktop' && <DesktopLayout embed={embed} />}
{layout === 'mobile' && <MobileLayout embed={embed} orientation={orientation} />}
</main>
</>
)
}

/**
* @param {object} props
* @param {import("../embed-settings.js").EmbedSettings|null} props.embed
*/
function DesktopLayout({embed}) {
return (
<div class={styles.desktop}>
<PlayerContainer>
{embed === null && <PlayerError layout={'desktop'} kind={'invalid-id'} />}
{embed !== null && <Player src={embed.toEmbedUrl()} layout={'desktop'} />}
<HideInFocusMode style={"slide"}>
<InfoBarContainer>
<InfoBar embed={embed}/>
</InfoBarContainer>
</HideInFocusMode>
</PlayerContainer>
</div>
)
}

/**
* @param {object} props
* @param {ReturnType<useOrientation>} props.orientation
* @param {import("../embed-settings.js").EmbedSettings|null} props.embed
*/
function MobileLayout({orientation, embed}) {
const platformName = usePlatformName();
const insetPlayer = orientation === "portrait";
const classes = cn({
[styles.portrait]: orientation === "portrait",
[styles.landscape]: orientation === "landscape"
});
return (
<div class={classes}>
{orientation === "portrait" && (
<div class={styles.header}>
<HideInFocusMode>
<TopBar>
<Wordmark />
</TopBar>
</HideInFocusMode>
</div>
)}
<div class={styles.wrapper}>
<div class={styles.main}>
<PlayerContainer inset={insetPlayer}>
<PlayerInternal inset={insetPlayer}>
{embed === null && <PlayerError layout={'mobile'} kind={'invalid-id'}/>}
{embed !== null && <Player src={embed.toEmbedUrl()} layout={'mobile'}/>}
{orientation === "portrait" && (
<SwitchProvider>
<SwitchBarMobile platformName={platformName} />
</SwitchProvider>
)}
</PlayerInternal>
</PlayerContainer>
</div>
{orientation === "landscape" && <LandscapeControls embed={embed} platformName={platformName}/>}
{orientation === "portrait" && <PortraitControls embed={embed} />}
</div>
</div>
)
}

/**
* How the controls are rendered in Portrait mode.
* @param {object} props
* @param {import("../embed-settings.js").EmbedSettings|null} props.embed
*/
function PortraitControls({embed}) {
return (
<div className={styles.controls}>
<HideInFocusMode>
<BottomNavBar>
<FloatingBar inset>
<MobileFooter embed={embed}/>
</FloatingBar>
</BottomNavBar>
</HideInFocusMode>
</div>
)
}

/**
* How the controls are rendered in Landscape mode
* @param {object} props
* @param {import("../embed-settings.js").EmbedSettings|null} props.embed
* @param {ImportMeta['platform']} props.platformName - The name of the platform.
*/
function LandscapeControls({embed, platformName}) {
return (
<div className={styles.rhs}>
<div className={styles.header}>
<HideInFocusMode>
<TopBar>
<Wordmark />
</TopBar>
</HideInFocusMode>
</div>
<div className={styles.controls}>
<HideInFocusMode>
<FloatingBar>
<MobileFooter embed={embed}/>
</FloatingBar>
</HideInFocusMode>
</div>
<div className={styles.switch}>
<SwitchProvider>
<SwitchBarMobile platformName={platformName}/>
</SwitchProvider>
</div>
</div>
)
}

/**
* @param {object} props
* @param {import("../embed-settings.js").EmbedSettings|null} props.embed
*/
function MobileFooter({embed}) {
const openSettings = useOpenSettingsHandler();
const openInfo = useOpenInfoHandler();
const openOnYoutube = useOpenOnYoutubeHandler();
const {t} = useTypedTranslation();
return (
<>
<Button
icon={true}
buttonProps={{
"aria-label": t('openInfoButton'),
onClick: openInfo
}}
><Icon src={info}/></Button>
<Button
icon={true}
buttonProps={{
"aria-label": t('openSettingsButton'),
onClick: openSettings
}}
><Icon src={cog}/></Button>
<Button fill={true}
buttonProps={{
onClick: () => {
if (embed) openOnYoutube(embed)
}
}}
>{t('watchOnYoutube')}</Button>
</>
)
}


141 changes: 141 additions & 0 deletions packages/special-pages/pages/duckplayer/app/components/App.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
:root {
/* Set video to take up 80vw width */
--video-width: 80vw;
}

@media screen and (max-width: 1080px) {
:root {
--video-width: 85vw;
}
}

@media screen and (max-width: 740px) {
:root {
--video-width: 90vw;
}
}

:root [data-layout="desktop"] {
--frame-height: min(
calc(var(--video-width) * calc(9 / 16)),
80vh
)
}
:root [data-layout="mobile"][data-orientation="portrait"] {
--video-width: calc(100vw - 32px)
}
:root [data-layout="mobile"][data-orientation="landscape"] {
--video-width: calc(calc(100vw - 32px) * 0.6) /* 60% of the container */
}
@media screen and (max-width: 700px) {
:root [data-layout="mobile"][data-orientation="landscape"] {
--video-width: calc(calc(100vw - 32px) * 0.5) /* 60% of the container */
}
}

:root [data-layout="mobile"] {
--frame-height: min(
calc(var(--video-width) * calc(9 / 16)),
calc(100vh - 32px)
)
}

.app {
margin: 0 auto;
position: relative;
z-index: 1;
height: 100%;
width: 100%;
max-width: 3840px;
color: rgba(255, 255, 255, 0.85);
}

.portrait {
height: 100%;
display: grid;
align-self: center;
grid-template-areas:
'header'
'main';
grid-template-rows: max-content 1fr;
}

.landscape {
height: 100%;
display: grid;
align-self: center;
align-items: center;
align-content: center;
}

.wrapper {}

.portrait .wrapper {
grid-area: main;
display: grid;
grid-template-areas:
'main'
'controls';
grid-template-rows: auto max-content;
}

.landscape .wrapper {
display: grid;
grid-template-columns: 60% 1fr;
grid-column-gap: 8px;
background: rgba(0, 0, 0, 0.3);
border-radius: 16px;
padding: 8px;
@media screen and (max-width: 700px) {
grid-template-columns: 50% 1fr;
}
}

.desktop {
height: 100%;
width: var(--video-width);
margin: 0 auto;
display: flex;
flex-direction: column;
justify-content: center;
}

.rhs {
display: grid;
height: 100%;
grid-template-areas: 'header' 'controls' 'switch';
grid-template-rows: max-content max-content auto;
grid-template-columns: 1fr;
grid-row-gap: 12px;
}

/* When the RHS has a checked checkbox, we can center the other content */
.rhs:has([data-state=completed] [aria-checked="true"]) {
align-content: center;
}

.header {
grid-area: header;
padding-top: 48px;
@media screen and (max-height: 500px) {
padding-top: 32px;
}
}

.main {
align-self: center;
}

.controls {
grid-area: controls
}
.switch {
grid-area: switch
}

.landscape .header {
padding-top: 8px;
}
.landscape .switch {
align-self: end;
}
Loading

0 comments on commit 3aab8b8

Please sign in to comment.