diff --git a/prismarine-viewer/viewer/lib/ui/newStats.ts b/prismarine-viewer/viewer/lib/ui/newStats.ts
index 4f4b5cee7..6fccac533 100644
--- a/prismarine-viewer/viewer/lib/ui/newStats.ts
+++ b/prismarine-viewer/viewer/lib/ui/newStats.ts
@@ -6,7 +6,6 @@ const stats = {}
let lastY = 20
export const addNewStat = (id: string, width = 80, x = rightOffset, y = lastY) => {
const pane = document.createElement('div')
- pane.id = 'fps-counter'
pane.style.position = 'fixed'
pane.style.top = `${y}px`
pane.style.right = `${x}px`
@@ -27,6 +26,7 @@ export const addNewStat = (id: string, width = 80, x = rightOffset, y = lastY) =
return {
updateText (text: string) {
+ if (pane.innerText === text) return
pane.innerText = text
},
setVisibility (visible: boolean) {
diff --git a/src/react/DebugEdges.tsx b/src/react/DebugEdges.tsx
new file mode 100644
index 000000000..a65b9f92f
--- /dev/null
+++ b/src/react/DebugEdges.tsx
@@ -0,0 +1,55 @@
+import { useState } from 'react'
+import { useIsHashActive } from './simpleHooks'
+
+export default () => {
+ const MODES_COUNT = 4
+ const [mode, setMode] = useState(0)
+ const isHashActive = useIsHashActive('#edges')
+
+ if (!isHashActive) return null
+
+ const styles: React.CSSProperties = {
+ display: 'flex',
+ fontSize: 18,
+ zIndex: 10_000,
+ background: 'rgba(0, 0, 255, 0.5)',
+ border: '2px solid red',
+ whiteSpace: 'pre',
+ }
+ let text = ''
+ if (mode === 0) {
+ styles.position = 'fixed'
+ styles.inset = 0
+ styles.height = '100%'
+ text = 'inset 0 fixed 100% height'
+ }
+ if (mode === 1) {
+ styles.position = 'fixed'
+ styles.inset = 0
+ text = 'inset 0 fixed'
+ }
+ if (mode === 2) {
+ styles.position = 'absolute'
+ styles.inset = 0
+ text = 'inset 0 absolute'
+ }
+ if (mode === 3) {
+ styles.position = 'fixed'
+ styles.top = 0
+ styles.left = 0
+ styles.right = 0
+ styles.height = '100dvh'
+ text = 'top 0 fixed 100dvh'
+ }
+
+ return
{
+ setMode((mode + 1) % MODES_COUNT)
+ }}
+ >
+ {mode}: {text}{'\n'}
+ inner: {window.innerWidth}x{window.innerHeight}{'\n'}
+ outer: {window.outerWidth}x{window.outerHeight}{'\n'}
+
+}
diff --git a/src/react/TouchControls.tsx b/src/react/TouchControls.tsx
index b49d57c4f..1b97ffd87 100644
--- a/src/react/TouchControls.tsx
+++ b/src/react/TouchControls.tsx
@@ -57,8 +57,8 @@ export default () => {
style={{ zIndex: modals.length ? 7 : 8 }}
className={css`
position: fixed;
- inset: 0;
- height: 100%;
+ bottom: 0;
+ /* height: 100%; */
display: flex;
width: 100%;
justify-content: space-between;
diff --git a/src/react/simpleHooks.ts b/src/react/simpleHooks.ts
index da8dd9e0e..ec9c88e11 100644
--- a/src/react/simpleHooks.ts
+++ b/src/react/simpleHooks.ts
@@ -1,4 +1,5 @@
import { useUtilsEffect } from '@zardoy/react-util'
+import { useEffect, useState } from 'react'
import { useMedia } from 'react-use'
const SMALL_SCREEN_MEDIA = '@media (max-width: 440px)'
@@ -25,3 +26,19 @@ export const useCopyKeybinding = (getCopyText: () => string | undefined) => {
}, { signal })
}, [getCopyText])
}
+
+export const useIsHashActive = (hash: `#${string}`) => {
+ const [isActive, setIsActive] = useState(false)
+
+ useEffect(() => {
+ const checkHash = () => {
+ setIsActive(location.hash === hash)
+ }
+ checkHash()
+ addEventListener('hashchange', checkHash)
+ return () => {
+ removeEventListener('hashchange', checkHash)
+ }
+ }, [])
+ return isActive
+}
diff --git a/src/reactUi.tsx b/src/reactUi.tsx
index f0144d140..b432c58d0 100644
--- a/src/reactUi.tsx
+++ b/src/reactUi.tsx
@@ -45,6 +45,7 @@ import SignInMessageProvider from './react/SignInMessageProvider'
import BookProvider from './react/BookProvider'
import { options } from './optionsStorage'
import BossBarOverlayProvider from './react/BossBarOverlayProvider'
+import DebugEdges from './react/DebugEdges'
const RobustPortal = ({ children, to }) => {
return createPortal({children}, to)
@@ -198,6 +199,7 @@ const App = () => {
+