feat: improve scaling in portrait mobile. Add close button for mobile chat (#157)
This commit is contained in:
parent
1a2fd9c271
commit
0a6fa7d7b0
13 changed files with 88 additions and 63 deletions
|
|
@ -2,8 +2,9 @@ import React from 'react'
|
|||
|
||||
import type { Preview } from "@storybook/react"
|
||||
|
||||
import '../src/styles.css'
|
||||
import './storybook.css'
|
||||
import '../src/styles.css'
|
||||
import '../src/scaleInterface'
|
||||
|
||||
const preview: Preview = {
|
||||
decorators: [
|
||||
|
|
|
|||
|
|
@ -4,10 +4,15 @@ export default async ({ tokenCaches, proxyBaseUrl, setProgressText = (text) => {
|
|||
// const sessionEndpoint = 'http://localhost:3000/session'
|
||||
let authEndpoint = ''
|
||||
let sessionEndpoint = ''
|
||||
if (!proxyBaseUrl.startsWith('http')) proxyBaseUrl = `${isPageSecure() ? 'https' : 'http'}://${proxyBaseUrl}`
|
||||
const url = proxyBaseUrl + '/api/vm/net/connect'
|
||||
let result: Response
|
||||
try {
|
||||
result = await fetch(url)
|
||||
} catch (err) {
|
||||
throw new Error(`Selected proxy server ${proxyBaseUrl} most likely is down`)
|
||||
}
|
||||
try {
|
||||
if (!proxyBaseUrl.startsWith('http')) proxyBaseUrl = `${isPageSecure() ? 'https' : 'http'}://${proxyBaseUrl}`
|
||||
const url = proxyBaseUrl + '/api/vm/net/connect'
|
||||
const result = await fetch(url)
|
||||
const json = await result.json()
|
||||
authEndpoint = urlWithBase(json.capabilities.authEndpoint, proxyBaseUrl)
|
||||
sessionEndpoint = urlWithBase(json.capabilities.sessionEndpoint, proxyBaseUrl)
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ export default ({ status, isError, hideDots = false, lastStatus = '', backAction
|
|||
|
||||
return (
|
||||
<Screen
|
||||
className='small-content'
|
||||
title={
|
||||
<>
|
||||
<span style={{ userSelect: isError ? 'text' : undefined }}>
|
||||
|
|
|
|||
|
|
@ -24,6 +24,13 @@ div.chat-wrapper {
|
|||
left: 1px;
|
||||
box-sizing: border-box;
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1px;
|
||||
}
|
||||
|
||||
.chat-input-wrapper form {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.chat-input {
|
||||
|
|
@ -103,7 +110,8 @@ div.chat-wrapper {
|
|||
}
|
||||
|
||||
.input-mobile #chatinput {
|
||||
height: 20px;
|
||||
height: 24px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.display-mobile {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import { MessageFormatPart } from '../botUtils'
|
|||
import { MessagePart } from './MessageFormatted'
|
||||
import './Chat.css'
|
||||
import { isIos, reactKeyForMessage } from './utils'
|
||||
import Button from './Button'
|
||||
import { pixelartIcons } from './PixelartIcon'
|
||||
|
||||
export type Message = {
|
||||
parts: MessageFormatPart[],
|
||||
|
|
@ -221,6 +223,8 @@ export default ({
|
|||
</div>
|
||||
|
||||
<div className={`chat-wrapper chat-input-wrapper ${usingTouch ? 'input-mobile' : ''}`} hidden={!opened}>
|
||||
{/* close button */}
|
||||
{usingTouch && <Button icon={pixelartIcons.close} onClick={() => onClose?.()} />}
|
||||
<div className="chat-input">
|
||||
{completionItems?.length ? (
|
||||
<div className="chat-completions">
|
||||
|
|
@ -307,6 +311,7 @@ export default ({
|
|||
onFocus={() => auxInputFocus('ArrowDown')}
|
||||
onChange={() => { }}
|
||||
/>}
|
||||
{/* for some reason this is needed to make Enter work on android chrome */}
|
||||
<button type='submit' style={{ visibility: 'hidden' }} />
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
import { useEffect, useState } from 'react'
|
||||
import { useSnapshot } from 'valtio'
|
||||
import { activeModalStack, miscUiState } from '../globalState'
|
||||
import Button from './Button'
|
||||
import { useUsingTouch } from './utilsApp'
|
||||
import { pixelartIcons } from './PixelartIcon'
|
||||
|
||||
const hideOnModals = new Set(['chat'])
|
||||
|
||||
export default () => {
|
||||
const [fullScreen, setFullScreen] = useState(false)
|
||||
|
|
@ -9,16 +14,23 @@ export default () => {
|
|||
setFullScreen(!!document.fullscreenElement)
|
||||
})
|
||||
}, [])
|
||||
const { gameLoaded } = useSnapshot(miscUiState)
|
||||
|
||||
const activeStack = useSnapshot(activeModalStack)
|
||||
|
||||
const inMainMenu = activeStack.length === 0 && !gameLoaded
|
||||
|
||||
const usingTouch = useUsingTouch()
|
||||
if (!usingTouch || !document.documentElement.requestFullscreen || fullScreen) return null
|
||||
const hideButton = activeStack.some(x => hideOnModals.has(x.reactType))
|
||||
|
||||
if (hideButton || !usingTouch || !document.documentElement.requestFullscreen || fullScreen) return null
|
||||
|
||||
return <Button
|
||||
icon='pixelarticons:scale'
|
||||
icon={pixelartIcons.scale}
|
||||
style={{
|
||||
position: 'fixed',
|
||||
top: 5,
|
||||
left: 5,
|
||||
left: inMainMenu ? 35 : 5,
|
||||
width: 22,
|
||||
}}
|
||||
onClick={() => {
|
||||
|
|
|
|||
|
|
@ -349,19 +349,20 @@ export const ButtonWithMatchesAlert = ({
|
|||
}
|
||||
|
||||
export const AwaitingInputOverlay = ({ isGamepad }) => {
|
||||
return <div style={{
|
||||
position: 'fixed',
|
||||
inset: 0,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
flexDirection: 'column',
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
||||
color: 'white',
|
||||
fontSize: 20,
|
||||
zIndex: 10,
|
||||
textAlign: 'center',
|
||||
}}
|
||||
return <div
|
||||
style={{
|
||||
position: 'fixed',
|
||||
inset: 0,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
flexDirection: 'column',
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
||||
color: 'white',
|
||||
fontSize: 20,
|
||||
zIndex: 10,
|
||||
textAlign: 'center',
|
||||
}}
|
||||
onContextMenu={e => e.preventDefault()}
|
||||
>
|
||||
<div>
|
||||
|
|
|
|||
|
|
@ -3,13 +3,14 @@ interface Props {
|
|||
children: React.ReactNode
|
||||
backdrop?: boolean | 'dirt'
|
||||
style?: React.CSSProperties
|
||||
className?: string
|
||||
}
|
||||
|
||||
export default ({ title, children, backdrop = true, style }: Props) => {
|
||||
export default ({ title, children, backdrop = true, style, className }: Props) => {
|
||||
return (
|
||||
<>
|
||||
{backdrop === 'dirt' ? <div className='dirt-bg'></div> : backdrop ? <div className="backdrop"></div> : null}
|
||||
<div className='fullscreen' style={{ overflow: 'auto', ...style }}>
|
||||
<div className={`fullscreen ${className}`} style={{ overflow: 'auto', ...style }}>
|
||||
<div className="screen-content">
|
||||
<div className="screen-title">{title}</div>
|
||||
{children}
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@
|
|||
padding-right: calc(env(safe-area-inset-right) / 2);
|
||||
}
|
||||
|
||||
@media only screen and (max-height: 313px) {
|
||||
@media only screen and (max-height: 420px) {
|
||||
.root {
|
||||
--top-offset: 10px
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { useSnapshot } from 'valtio'
|
||||
import { useEffect, useMemo } from 'react'
|
||||
import { useMedia } from 'react-use'
|
||||
import { activeModalStack, miscUiState } from '../globalState'
|
||||
|
||||
export const watchedModalsFromHooks = new Set<string>()
|
||||
|
|
@ -28,3 +29,7 @@ export const useIsModalActive = (modal: string, useIncludes = false) => {
|
|||
export const useIsWidgetActive = (name: string) => {
|
||||
return useIsModalActive(`widget-${name}`)
|
||||
}
|
||||
|
||||
export const useIsSmallWidth = () => {
|
||||
return useMedia('(max-width: 550px)')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,31 +1,37 @@
|
|||
import { proxy } from 'valtio'
|
||||
import { subscribeKey } from 'valtio/utils'
|
||||
import { options } from './optionsStorage'
|
||||
import { options, watchValue } from './optionsStorage'
|
||||
|
||||
export const currentScaling = proxy({
|
||||
scale: 1,
|
||||
})
|
||||
window.currentScaling = currentScaling
|
||||
|
||||
const setScale = () => {
|
||||
const scaleValues = [
|
||||
{ width: 971, height: 670, scale: 2 },
|
||||
{ width: null, height: 430, scale: 1.5 },
|
||||
{ width: 590, height: null, scale: 1 }
|
||||
{ maxWidth: 971, maxHeight: 670, scale: 2 },
|
||||
{ maxWidth: null, maxHeight: 390, scale: 1.5 }, // todo allow to set the scaling at 360-400 (dynamic scaling setting)
|
||||
{ maxWidth: 590, maxHeight: null, scale: 1 },
|
||||
|
||||
{ maxWidth: 590, minHeight: 240, scale: 1.4 },
|
||||
]
|
||||
|
||||
const { innerWidth, innerHeight } = window
|
||||
|
||||
let result = options.guiScale
|
||||
for (const { width, height, scale } of scaleValues) {
|
||||
if ((width && innerWidth <= width) || (height && innerHeight <= height)) {
|
||||
for (const { maxWidth, maxHeight, scale, minHeight } of scaleValues) {
|
||||
if ((!maxWidth || innerWidth <= maxWidth) && (!maxHeight || innerHeight <= maxHeight) && (!minHeight || innerHeight >= minHeight)) {
|
||||
result = scale
|
||||
}
|
||||
}
|
||||
|
||||
currentScaling.scale = result
|
||||
document.documentElement.style.setProperty('--guiScale', String(result))
|
||||
}
|
||||
|
||||
|
||||
setScale()
|
||||
subscribeKey(options, 'guiScale', setScale)
|
||||
watchValue(currentScaling, (c) => {
|
||||
document.documentElement.style.setProperty('--guiScale', String(c.scale))
|
||||
})
|
||||
window.addEventListener('resize', setScale)
|
||||
|
|
|
|||
|
|
@ -41,6 +41,18 @@
|
|||
gap: 10px;
|
||||
}
|
||||
|
||||
@media screen and (max-height: 426px) {
|
||||
.fullscreen:not(.small-content) {
|
||||
.screen-content {
|
||||
margin-top: 14px;
|
||||
}
|
||||
|
||||
.screen-title {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.screen-items {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
|
|
|
|||
|
|
@ -199,35 +199,3 @@ body::xr-overlay #viewer-canvas {
|
|||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 971px) {
|
||||
#ui-root {
|
||||
transform: scale(2);
|
||||
width: calc(100% / 2);
|
||||
height: calc(100% / 2);
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-height: 670px) {
|
||||
#ui-root {
|
||||
transform: scale(2);
|
||||
width: calc(100% / 2);
|
||||
height: calc(100% / 2);
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 590px) {
|
||||
#ui-root {
|
||||
transform: scale(1);
|
||||
width: calc(100% / 1);
|
||||
height: calc(100% / 1);
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-height: 430px) {
|
||||
#ui-root {
|
||||
transform: scale(1.5);
|
||||
width: calc(100% / 1.5);
|
||||
height: calc(100% / 1.5);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue