pages235/src/react/MainMenu.tsx
2025-02-11 16:26:17 +03:00

191 lines
5.9 KiB
TypeScript

import React from 'react'
import { openURL } from 'renderer/viewer/lib/simpleUtils'
import { haveDirectoryPicker } from '../utils'
import { ConnectOptions } from '../connect'
import styles from './mainMenu.module.css'
import Button from './Button'
import ButtonWithTooltip from './ButtonWithTooltip'
import { pixelartIcons } from './PixelartIcon'
import useLongPress from './useLongPress'
type Action = (e: React.MouseEvent<HTMLButtonElement>) => void
interface Props {
connectToServerAction?: Action
singleplayerAction?: Action
optionsAction?: Action
githubAction?: Action
linksButton?: JSX.Element
openFileAction?: Action
mapsProvider?: string
versionStatus?: string
versionTitle?: string
onVersionStatusClick?: () => void
bottomRightLinks?: string
versionText?: string
onVersionTextClick?: () => void
}
const httpsRegex = /^https?:\/\//
export default ({
connectToServerAction,
mapsProvider,
singleplayerAction,
optionsAction,
githubAction,
linksButton,
openFileAction,
versionText,
onVersionTextClick,
versionStatus,
versionTitle,
onVersionStatusClick,
bottomRightLinks
}: Props) => {
if (!bottomRightLinks?.trim()) bottomRightLinks = undefined
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
const linksParsed = bottomRightLinks?.split(/;|\n/g).map(l => {
const parts = l.split(':')
return [parts[0], parts.slice(1).join(':')]
}) as Array<[string, string]> | undefined
const singleplayerLongPress = useLongPress(
() => {
window.location.href = window.location.pathname + '?sp=1'
},
() => singleplayerAction?.(null as any),
{ delay: 500 }
)
const versionLongPress = useLongPress(
() => {
const buildDate = process.env.BUILD_VERSION ? new Date(process.env.BUILD_VERSION) : null
alert(`BUILD INFO:\n${buildDate?.toLocaleString() || 'Development build'}`)
},
() => onVersionTextClick?.(),
)
const connectToServerLongPress = useLongPress(
() => {
if (process.env.NODE_ENV === 'development') {
// Connect to <origin>:25565
const origin = window.location.hostname
const connectOptions: ConnectOptions = {
server: `${origin}:25565`,
username: 'test',
}
dispatchEvent(new CustomEvent('connect', { detail: connectOptions }))
}
},
() => connectToServerAction?.(null as any),
{ delay: 500 }
)
return (
<div className={styles.root}>
<div className={styles['game-title']}>
<div className={styles.minecraft}>
<div className={styles.edition} />
<span className={styles.splash}>Prismarine is a beautiful block</span>
</div>
</div>
<div className={styles.menu}>
<ButtonWithTooltip
initialTooltip={{
content: 'Connect to Java servers!',
placement: 'top',
}}
{...connectToServerLongPress}
data-test-id='servers-screen-button'
>
Connect to server
</ButtonWithTooltip>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<ButtonWithTooltip
style={{ width: 150 }}
{...singleplayerLongPress}
data-test-id='singleplayer-button'
initialTooltip={{
content: 'Create worlds and play offline',
placement: 'left',
offset: -40
}}
>
Singleplayer
</ButtonWithTooltip>
<ButtonWithTooltip
disabled={!mapsProvider}
// className={styles['maps-provider']}
icon={pixelartIcons.map}
initialTooltip={{ content: 'Explore maps to play from provider!', placement: 'top-start' }}
onClick={() => mapsProvider && openURL(httpsRegex.test(mapsProvider) ? mapsProvider : 'https://' + mapsProvider, false)}
/>
<ButtonWithTooltip
data-test-id='select-file-folder'
icon={pixelartIcons.folder}
onClick={openFileAction}
initialTooltip={{
content: 'Load any Java world save' + (haveDirectoryPicker() ? '' : ' (zip)!'),
placement: 'bottom-start',
}}
/>
</div>
<Button
onClick={optionsAction}
>
Options
</Button>
<div className={styles['menu-row']}>
<ButtonWithTooltip
initialTooltip={{
content: 'Report bugs or request features!',
}}
style={{ width: '98px' }}
onClick={githubAction}
>
GitHub
</ButtonWithTooltip>
{linksButton}
</div>
</div>
<div className={styles['bottom-info']}>
<div style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
<span style={{ fontSize: 10, color: 'gray' }} {...versionLongPress}>{versionText}</span>
<span
title={`${versionTitle} (click to reload)`}
onClick={onVersionStatusClick}
className={styles['product-info']}
>
Prismarine Web Client {versionStatus}
</span>
</div>
<span className={styles['product-description']}>
<div className={styles['product-link']}>
{linksParsed?.map(([name, link], i, arr) => {
if (!link.startsWith('http')) link = `https://${link}`
return <div style={{
color: 'lightgray',
fontSize: 8,
}}>
<a
key={name}
style={{
whiteSpace: 'nowrap',
}} href={link}
>{name}
</a>
{i < arr.length - 1 && <span style={{ marginLeft: 2 }}>·</span>}
</div>
})}
</div>
<span>A Minecraft client in the browser!</span>
</span>
</div>
</div>
)
}