feat: fullscreen

This commit is contained in:
tresabhi committed 2025-05-07 19:16:10 -05:00
1 parent f9c182e68c
commit d2e7a477bb
2 files changed
+191 -167

No files matched your search

@@ -90,6 +90,7 @@ export function Options({ thicknessRange, canvas, skeleton }: OptionsProps) {
const mutateTankopediaPersistent = TankopediaPersistent.useMutation(); const mutateTankopediaPersistent = TankopediaPersistent.useMutation();
const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation(); const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation();
const { strings, unwrap } = useLocale(); const { strings, unwrap } = useLocale();
const revealed = TankopediaEphemeral.use((state) => state.revealed);
const disturbed = TankopediaEphemeral.use((state) => state.disturbed); const disturbed = TankopediaEphemeral.use((state) => state.disturbed);
return ( return (
@@ -324,7 +325,7 @@ export function Options({ thicknessRange, canvas, skeleton }: OptionsProps) {
direction="column" direction="column"
align="center" align="center"
position="absolute" position="absolute"
bottom={disturbed ? '4' : '-100%'} bottom={revealed ? '4' : '-100%'}
left="50%" left="50%"
style={{ transform: 'translateX(-50%)', transitionDuration: '200ms' }} style={{ transform: 'translateX(-50%)', transitionDuration: '200ms' }}
> >
@@ -401,7 +402,7 @@ export function Options({ thicknessRange, canvas, skeleton }: OptionsProps) {
<Flex gap="3" align="center" mt="2"> <Flex gap="3" align="center" mt="2">
<SegmentedControl.Root <SegmentedControl.Root
value={`${display}`} value={`${disturbed ? display : -1}`}
onValueChange={(value) => { onValueChange={(value) => {
mutateTankopediaEphemeral((draft) => { mutateTankopediaEphemeral((draft) => {
draft.disturbed = true; draft.disturbed = true;
@@ -455,185 +456,214 @@ export function Options({ thicknessRange, canvas, skeleton }: OptionsProps) {
</SegmentedControl.Item> */} </SegmentedControl.Item> */}
</SegmentedControl.Root> </SegmentedControl.Root>
<DropdownMenu.Root> {disturbed && (
<DropdownMenu.Trigger> <>
<IconButton variant="ghost" color="gray"> <DropdownMenu.Root>
<EyeOpenIcon /> <DropdownMenu.Trigger>
</IconButton> <IconButton variant="ghost" color="gray">
</DropdownMenu.Trigger> <EyeOpenIcon />
</IconButton>
</DropdownMenu.Trigger>
<DropdownMenu.Content> <DropdownMenu.Content>
<DropdownMenu.Item onClick={() => poseEvent.emit(Pose.HullDown)}> <DropdownMenu.Item
{strings.website.tools.tankopedia.sandbox.poses.hull_down} onClick={() => poseEvent.emit(Pose.HullDown)}
</DropdownMenu.Item> >
{strings.website.tools.tankopedia.sandbox.poses.hull_down}
</DropdownMenu.Item>
<DropdownMenu.Item onClick={() => poseEvent.emit(Pose.FaceHug)}> <DropdownMenu.Item
{strings.website.tools.tankopedia.sandbox.poses.face_hug} onClick={() => poseEvent.emit(Pose.FaceHug)}
</DropdownMenu.Item> >
{strings.website.tools.tankopedia.sandbox.poses.face_hug}
</DropdownMenu.Item>
<DropdownMenu.Item onClick={() => poseEvent.emit(Pose.Default)}> <DropdownMenu.Item
{strings.website.tools.tankopedia.sandbox.poses.default} onClick={() => poseEvent.emit(Pose.Default)}
</DropdownMenu.Item> >
</DropdownMenu.Content> {strings.website.tools.tankopedia.sandbox.poses.default}
</DropdownMenu.Root> </DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu.Root>
<DropdownMenu.Root> <DropdownMenu.Root>
<DropdownMenu.Trigger> <DropdownMenu.Trigger>
<IconButton variant="ghost" color="gray"> <IconButton variant="ghost" color="gray">
<GearIcon /> <GearIcon />
</IconButton> </IconButton>
</DropdownMenu.Trigger> </DropdownMenu.Trigger>
<DropdownMenu.Content>
{display === TankopediaDisplay.DynamicArmor && (
<>
<DropdownMenu.Label>
{
strings.website.tools.tankopedia.sandbox.settings
.armor
}
</DropdownMenu.Label>
<DropdownMenu.CheckboxItem
checked={greenPenetration}
onCheckedChange={(checked) => {
mutateTankopediaPersistent((draft) => {
draft.greenPenetration = checked;
});
}}
>
{
strings.website.tools.tankopedia.sandbox.settings
.green_penetration
}
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={hideTankModelUnderArmor}
onCheckedChange={(checked) => {
mutateTankopediaPersistent((draft) => {
draft.hideTankModelUnderArmor = checked;
});
}}
>
{
strings.website.tools.tankopedia.sandbox.settings
.hide_model_under_armor
}
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem
checked={opaque}
onCheckedChange={(checked) => {
mutateTankopediaPersistent((draft) => {
draft.opaque = checked;
});
}}
>
{
strings.website.tools.tankopedia.sandbox.settings
.opaque
}
</DropdownMenu.CheckboxItem>
{developerMode && (
<DropdownMenu.CheckboxItem
checked={wireframe}
onCheckedChange={(checked) => {
mutateTankopediaPersistent((draft) => {
draft.wireframe = checked;
});
}}
>
{
strings.website.tools.tankopedia.sandbox.settings
.dev_wireframe
}
</DropdownMenu.CheckboxItem>
)}
</>
)}
<DropdownMenu.Content>
{display === TankopediaDisplay.DynamicArmor && (
<>
<DropdownMenu.Label> <DropdownMenu.Label>
{strings.website.tools.tankopedia.sandbox.settings.armor} {
strings.website.tools.tankopedia.sandbox.settings
.environment
}
</DropdownMenu.Label> </DropdownMenu.Label>
<DropdownMenu.CheckboxItem <DropdownMenu.CheckboxItem
checked={greenPenetration} checked={showGrid}
onCheckedChange={(checked) => { onCheckedChange={(checked) => {
mutateTankopediaPersistent((draft) => { mutateTankopediaPersistent((draft) => {
draft.greenPenetration = checked; draft.showGrid = checked;
}); });
}} }}
> >
{ {
strings.website.tools.tankopedia.sandbox.settings strings.website.tools.tankopedia.sandbox.settings
.green_penetration .show_grid
} }
</DropdownMenu.CheckboxItem> </DropdownMenu.CheckboxItem>
</DropdownMenu.Content>
</DropdownMenu.Root>
<DropdownMenu.CheckboxItem <Popover.Root>
checked={hideTankModelUnderArmor} <Popover.Trigger>
onCheckedChange={(checked) => { <IconButton color="gray" variant="ghost">
mutateTankopediaPersistent((draft) => { <CameraIcon />
draft.hideTankModelUnderArmor = checked; </IconButton>
}); </Popover.Trigger>
}}
>
{
strings.website.tools.tankopedia.sandbox.settings
.hide_model_under_armor
}
</DropdownMenu.CheckboxItem>
<DropdownMenu.CheckboxItem <Popover.Content>
checked={opaque} <Flex direction="column" gap="2">
onCheckedChange={(checked) => { <Popover.Close>
mutateTankopediaPersistent((draft) => { <Button
draft.opaque = checked; onClick={() => {
}); if (!canvas.current) return;
}}
>
{strings.website.tools.tankopedia.sandbox.settings.opaque}
</DropdownMenu.CheckboxItem>
{developerMode && ( const anchor = document.createElement('a');
<DropdownMenu.CheckboxItem
checked={wireframe} anchor.setAttribute(
onCheckedChange={(checked) => { 'download',
mutateTankopediaPersistent((draft) => { `${protagonistTank.name}.png`,
draft.wireframe = checked; );
}); anchor.setAttribute(
}} 'href',
> canvas.current.toDataURL('image/png'),
{ );
strings.website.tools.tankopedia.sandbox.settings anchor.click();
.dev_wireframe }}
} >
</DropdownMenu.CheckboxItem> <DownloadIcon />
{
strings.website.tools.tankopedia.sandbox.screenshot
.download
}
</Button>
</Popover.Close>
<Popover.Close>
<Button
variant="outline"
onClick={() => {
if (!canvas.current) return;
canvas.current.toBlob((blob) => {
if (!blob) return;
navigator.clipboard.write([
new ClipboardItem({ 'image/png': blob }),
]);
});
}}
>
<CopyIcon />
{
strings.website.tools.tankopedia.sandbox.screenshot
.copy
}
</Button>
</Popover.Close>
</Flex>
</Popover.Content>
</Popover.Root>
{fullScreenAvailable && (
<IconButton
color="gray"
variant="ghost"
onClick={() => {
if (isFullScreen) {
document.exitFullscreen();
} else document.body.requestFullscreen();
}}
>
{isFullScreen ? (
<ExitFullScreenIcon />
) : (
<EnterFullScreenIcon />
)} )}
</> </IconButton>
)} )}
</>
<DropdownMenu.Label>
{strings.website.tools.tankopedia.sandbox.settings.environment}
</DropdownMenu.Label>
<DropdownMenu.CheckboxItem
checked={showGrid}
onCheckedChange={(checked) => {
mutateTankopediaPersistent((draft) => {
draft.showGrid = checked;
});
}}
>
{strings.website.tools.tankopedia.sandbox.settings.show_grid}
</DropdownMenu.CheckboxItem>
</DropdownMenu.Content>
</DropdownMenu.Root>
<Popover.Root>
<Popover.Trigger>
<IconButton color="gray" variant="ghost">
<CameraIcon />
</IconButton>
</Popover.Trigger>
<Popover.Content>
<Flex direction="column" gap="2">
<Popover.Close>
<Button
onClick={() => {
if (!canvas.current) return;
const anchor = document.createElement('a');
anchor.setAttribute(
'download',
`${protagonistTank.name}.png`,
);
anchor.setAttribute(
'href',
canvas.current.toDataURL('image/png'),
);
anchor.click();
}}
>
<DownloadIcon />
{
strings.website.tools.tankopedia.sandbox.screenshot
.download
}
</Button>
</Popover.Close>
<Popover.Close>
<Button
variant="outline"
onClick={() => {
if (!canvas.current) return;
canvas.current.toBlob((blob) => {
if (!blob) return;
navigator.clipboard.write([
new ClipboardItem({ 'image/png': blob }),
]);
});
}}
>
<CopyIcon />
{strings.website.tools.tankopedia.sandbox.screenshot.copy}
</Button>
</Popover.Close>
</Flex>
</Popover.Content>
</Popover.Root>
{fullScreenAvailable && (
<IconButton
color="gray"
variant="ghost"
onClick={() => {
if (isFullScreen) {
document.exitFullscreen();
} else document.body.requestFullscreen();
}}
>
{isFullScreen ? <ExitFullScreenIcon /> : <EnterFullScreenIcon />}
</IconButton>
)} )}
</Flex> </Flex>
</Flex> </Flex>
@@ -14,7 +14,6 @@ import type { MaybeSkeletonComponentProps } from '../../../types/maybeSkeletonCo
import type { ThicknessRange } from '../../Armor/components/StaticArmor'; import type { ThicknessRange } from '../../Armor/components/StaticArmor';
import { classIcons } from '../../ClassIcon'; import { classIcons } from '../../ClassIcon';
import { Options } from './components/Options'; import { Options } from './components/Options';
import { ScrollHint } from './components/ScrollHint';
import { TankSandbox } from './components/TankSandbox'; import { TankSandbox } from './components/TankSandbox';
import { NATION_COLORS, Title } from './components/TankSandbox/Title'; import { NATION_COLORS, Title } from './components/TankSandbox/Title';
@@ -119,13 +118,14 @@ export function HeroSection({ skeleton }: MaybeSkeletonComponentProps) {
}} }}
/> />
<ScrollHint /> {/* <ScrollHint /> */}
<Flex <Flex
direction={{ initial: 'column-reverse', md: 'row' }} direction={{ initial: 'column-reverse', md: 'row' }}
style={{ style={{
zIndex: isFullScreen ? 2 : undefined, zIndex: isFullScreen ? 2 : undefined,
transitionDuration: '1s', transitionDuration: '1s',
background: isFullScreen ? 'black' : undefined,
}} }}
height={disturbed && !isFullScreen ? 'calc(100vh - 6rem)' : '100vh'} height={disturbed && !isFullScreen ? 'calc(100vh - 6rem)' : '100vh'}
maxHeight={isFullScreen ? undefined : '60rem'} maxHeight={isFullScreen ? undefined : '60rem'}
@@ -182,13 +182,7 @@ export function HeroSection({ skeleton }: MaybeSkeletonComponentProps) {
{!disturbed && ( {!disturbed && (
<Box <Box
onPointerDown={(event) => { onClick={(event) => {
event.stopPropagation();
mutateTankopediaEphemeral((draft) => {
draft.disturbed = true;
});
}}
onWheel={(event) => {
event.stopPropagation(); event.stopPropagation();
mutateTankopediaEphemeral((draft) => { mutateTankopediaEphemeral((draft) => {
draft.disturbed = true; draft.disturbed = true;