Skip to content

Commit

Permalink
do a few important fixes (#49)
Browse files Browse the repository at this point in the history
  • Loading branch information
zardoy authored Jan 5, 2024
2 parents 4990d9f + bc38ea9 commit ae56415
Show file tree
Hide file tree
Showing 10 changed files with 129 additions and 52 deletions.
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ watchFov()

// Create three.js context, add to page
const renderer = new THREE.WebGLRenderer({
powerPreference: options.highPerformanceGpu ? 'high-performance' : 'default',
powerPreference: options.gpuPreference,
})
initWithRenderer(renderer.domElement)
window.renderer = renderer
Expand Down
8 changes: 6 additions & 2 deletions src/menus/hud.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { f3Keybinds } from '../controls'
import { showOptionsModal } from '../react/SelectOption'

const { LitElement, html, css, unsafeCSS } = require('lit')
const { showModal, miscUiState } = require('../globalState')
const { showModal, miscUiState, activeModalStack, hideCurrentModal } = require('../globalState')
const { options, watchValue } = require('../optionsStorage')
const { getGamemodeNumber } = require('../utils')
const { isMobile } = require('./components/common')
Expand Down Expand Up @@ -231,7 +231,11 @@ class Hud extends LitElement {
}}>F3</div>
<div class="chat-btn" @pointerdown=${(e) => {
e.stopPropagation()
this.shadowRoot.querySelector('#chat').enableChat()
if (activeModalStack.at(-1)?.reactType === 'chat') {
hideCurrentModal()
} else {
showModal({ reactType: 'chat' })
}
}}></div>
<div class="pause-btn" @pointerdown=${(e) => {
e.stopPropagation()
Expand Down
7 changes: 4 additions & 3 deletions src/optionsGuiScheme.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { getResourcePackName, resourcePackState, uninstallTexturePack } from './
import { resetLocalStorageWithoutWorld } from './browserfs'

export const guiOptionsScheme: {
[t in OptionsGroupType]: Array<{ [k in keyof AppOptions]?: Partial<OptionMeta> } & { custom?}>
[t in OptionsGroupType]: Array<{ [K in keyof AppOptions]?: Partial<OptionMeta<AppOptions[K]>> } & { custom?}>
} = {
render: [
{
Expand All @@ -31,10 +31,11 @@ export const guiOptionsScheme: {
}
},
{
highPerformanceGpu: {
gpuPreference: {
// todo reimplement to gpu preference to allow use low-energy instead
text: 'Use Dedicated GPU',
text: 'GPU Preference',
// willHaveNoEffect: isIos
values: [['default', 'Auto'], ['high-performance', 'Dedicated'], ['low-power', 'Low Power']]
},
},
{
Expand Down
12 changes: 10 additions & 2 deletions src/optionsStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const defaultOptions = {
touchButtonsSize: 40,
touchButtonsOpacity: 80,
touchButtonsPosition: 12,
highPerformanceGpu: false,
gpuPreference: 'default' as 'default' | 'high-performance' | 'low-power',
/** @unstable */
disableAssets: false,
/** @unstable */
Expand All @@ -52,11 +52,19 @@ const defaultOptions = {
mutedSounds: [] as string[]
}

const migrateOptions = (options) => {
if (options.highPerformanceGpu) {
options.gpuPreference = 'high-performance'
delete options.highPerformanceGpu
}
return options
}

export type AppOptions = typeof defaultOptions

export const options: AppOptions = proxy({
...defaultOptions,
...JSON.parse(localStorage.options || '{}')
...migrateOptions(JSON.parse(localStorage.options || '{}'))
})

window.options = window.settings = options
Expand Down
45 changes: 32 additions & 13 deletions src/react/Chat.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,33 @@
import type { Meta, StoryObj } from '@storybook/react'

import { useEffect, useState } from 'react'
import Chat, { fadeMessage } from './ChatContainer'
import Chat, { fadeMessage, initialChatOpenValue } from './ChatContainer'
import Button from './Button'

const meta: Meta<typeof Chat> = {
component: Chat,
render (args) {
const [messages, setMessages] = useState(args.messages)
const [autoSpam, setAutoSpam] = useState(false)
const [open, setOpen] = useState(args.opened)

useEffect(() => {
const abortController = new AbortController()
addEventListener('keyup', (e) => {
if (e.code === 'KeyY') {
initialChatOpenValue.value = '/'
setOpen(true)
e.stopImmediatePropagation()
}
if (e.code === 'Escape') {
setOpen(false)
e.stopImmediatePropagation()
}
}, {
signal: abortController.signal,
})
return () => abortController.abort()
})

useEffect(() => {
setMessages(args.messages)
Expand Down Expand Up @@ -46,7 +65,16 @@ const meta: Meta<typeof Chat> = {
}

return <div>
<Chat {...args} messages={messages} />
<Chat {...args} opened={open} messages={messages} onClose={() => setOpen(false)} fetchCompletionItems={async (triggerType, value) => {
console.log('fetchCompletionItems')
await new Promise(resolve => {
setTimeout(resolve, 700)
})
let items = ['test', ...Array.from({ length: 50 }).map((_, i) => `minecraft:hello${i}`)]
if (value === '/') items = items.map(item => `/${item}`)
return items
}} />
<Button onClick={() => setOpen(s => !s)}>Open: {open ? 'on' : 'off'}</Button>
<Button onClick={() => fadeMessages()}>Fade</Button>
<Button onClick={() => setAutoSpam(s => !s)}>Auto Spam: {autoSpam ? 'on' : 'off'}</Button>
<Button onClick={() => setMessages(args.messages)}>Clear</Button>
Expand Down Expand Up @@ -114,15 +142,6 @@ export const Primary: Story = {
],
id: 0,
}],
opened: false,
async fetchCompletionItems (triggerType, value) {
console.log('fetchCompletionItems')
await new Promise(resolve => {
setTimeout(resolve, 700)
})
let items = ['test', ...Array.from({ length: 50 }).map((_, i) => `minecraft:hello${i}`)]
if (value === '/') items = items.map(item => `/${item}`)
return items
},
},
// opened: false,
}
}
48 changes: 29 additions & 19 deletions src/react/ChatContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useUsingTouch } from '@dimaka/interface'
import { useEffect, useMemo, useRef, useState } from 'react'
import { isCypress } from '../standaloneUtils'
import { MessageFormatPart } from '../botUtils'
Expand Down Expand Up @@ -50,7 +51,9 @@ export const fadeMessage = (message: Message, initialTimeout: boolean, requestUp
}, initialTimeout ? 5000 : 0)
}

const ChatComponent = ({ messages, touch, opacity, fetchCompletionItems, opened, interceptMessage, onClose }: Props) => {
export default ({ messages, touch, opacity, fetchCompletionItems, opened, interceptMessage, onClose }: Props) => {
const usingTouch = useUsingTouch()

const [sendHistory, _setSendHistory] = useState(JSON.parse(window.sessionStorage.chatHistory || '[]'))

const [completePadText, setCompletePadText] = useState('')
Expand Down Expand Up @@ -80,7 +83,7 @@ const ChatComponent = ({ messages, touch, opacity, fetchCompletionItems, opened,

const updateInputValue = (newValue: string) => {
chatInput.current.value = newValue
chatInput.current.dispatchEvent(new Event('input'))
onMainInputChange()
setTimeout(() => {
chatInput.current.setSelectionRange(newValue.length, newValue.length)
}, 0)
Expand Down Expand Up @@ -114,14 +117,21 @@ const ChatComponent = ({ messages, touch, opacity, fetchCompletionItems, opened,
chatHistoryPos.current = messages.length
updateInputValue(initialChatOpenValue.value)
initialChatOpenValue.value = ''
chatInput.current.focus()
resetCompletionItems()
if (!usingTouch) {
chatInput.current.focus()
}
}
if (!opened) {
chatMessages.current.scrollTop = chatMessages.current.scrollHeight
}
}, [opened])

useMemo(() => {
if (opened) {
resetCompletionItems()
}
}, [opened])

useEffect(() => {
if (!opened || (opened && openedChatWasAtBottom.current)) {
openedChatWasAtBottom.current = false
Expand Down Expand Up @@ -175,6 +185,18 @@ const ChatComponent = ({ messages, touch, opacity, fetchCompletionItems, opened,
setCompletionItems(newCompleteItems)
}

const onMainInputChange = () => {
const completeValue = getCompleteValue()
setCompletePadText(completeValue === '/' ? '' : completeValue)
if (completeRequestValue.current === completeValue) {
updateFilteredCompleteItems(completionItemsSource)
return
}
if (completeValue === '/') {
void fetchCompletions(true)
}
}

return (
<>
<div className={`chat-wrapper chat-messages-wrapper ${touch ? 'display-mobile' : ''}`} hidden={isCypress()}>
Expand Down Expand Up @@ -205,7 +227,7 @@ const ChatComponent = ({ messages, touch, opacity, fetchCompletionItems, opened,
spellCheck={false}
autoComplete="off"
onFocus={() => auxInputFocus('ArrowUp')}
onChange={() => {}}
onChange={() => { }}
/>
<input
defaultValue=''
Expand All @@ -216,17 +238,7 @@ const ChatComponent = ({ messages, touch, opacity, fetchCompletionItems, opened,
spellCheck={false}
autoComplete="off"
aria-autocomplete="both"
onChange={({ target: { value } }) => {
const completeValue = getCompleteValue()
setCompletePadText(completeValue === '/' ? '' : completeValue)
if (completeRequestValue.current === completeValue) {
updateFilteredCompleteItems(completionItemsSource)
return
}
if (completeValue === '/') {
void fetchCompletions(true)
}
}}
onChange={onMainInputChange}
onKeyDown={(e) => {
if (e.code === 'ArrowUp') {
if (chatHistoryPos.current === 0) return
Expand Down Expand Up @@ -267,12 +279,10 @@ const ChatComponent = ({ messages, touch, opacity, fetchCompletionItems, opened,
spellCheck={false}
autoComplete="off"
onFocus={() => auxInputFocus('ArrowDown')}
onChange={() => {}}
onChange={() => { }}
/>
</div>
</div>
</>
)
}

export default ChatComponent
7 changes: 3 additions & 4 deletions src/react/ChatProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { formatMessage } from '../botUtils'
import { getBuiltinCommandsList, tryHandleBuiltinCommand } from '../builtinCommands'
import { hideCurrentModal } from '../globalState'
import { options } from '../optionsStorage'
import ChatComponent, { Message, fadeMessage } from './ChatContainer'
import ChatContainer, { Message, fadeMessage } from './ChatContainer'
import { useIsModalActive } from './utils'

export default () => {
Expand All @@ -23,16 +23,15 @@ export default () => {
faded: false,
}
fadeMessage(newMessage, true, () => {
// eslint-disable-next-line max-nested-callbacks
setMessages(m => [...m])
})
return [...m, newMessage].slice(-messagesLimit)
})

// todo update scrollbottom
})
}, [])

return <ChatComponent
return <ChatContainer
messages={messages}
opened={isChatActive}
interceptMessage={(message) => {
Expand Down
6 changes: 3 additions & 3 deletions src/react/OptionsGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { options } from '../optionsStorage'
import { OptionsGroupType, guiOptionsScheme } from '../optionsGuiScheme'
import OptionsItems, { OptionMeta } from './OptionsItems'

const optionValueToType = (optionValue: any) => {
if (typeof optionValue === 'boolean') return 'toggle'
const optionValueToType = (optionValue: any, item: OptionMeta) => {
if (typeof optionValue === 'boolean' || item.values) return 'toggle'
if (typeof optionValue === 'number') return 'slider'
if (typeof optionValue === 'string') return 'element'
}
Expand All @@ -14,7 +14,7 @@ const finalItemsScheme: Record<keyof typeof guiOptionsScheme, OptionMeta[]> = Ob
return Object.entries(optionsObj).map(([optionKey, metaMerge]) => {
const optionValue = options[optionKey]

const type = optionValueToType(optionValue)
const type = optionValueToType(optionValue, metaMerge)
const meta: OptionMeta = {
id: optionKey === 'custom' ? undefined : optionKey,
type,
Expand Down
44 changes: 40 additions & 4 deletions src/react/OptionsItems.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@ import Button from './Button'
import Slider from './Slider'
import Screen from './Screen'

type GeneralItem = {
type GeneralItem<T extends string | number | boolean> = {
id?: string
text?: string,
disabledReason?: string,
tooltip?: string
willHaveNoEffect?: boolean
values?: Array<T | [T, string]>
}

export type OptionMeta = GeneralItem & ({
export type OptionMeta<T = any> = GeneralItem<T & string> & ({
type: 'toggle',
} | {
type: 'slider'
Expand All @@ -32,10 +33,45 @@ export type OptionMeta = GeneralItem & ({
export const OptionButton = ({ item }: { item: Extract<OptionMeta, { type: 'toggle' }> }) => {
const optionValue = useSnapshot(options)[item.id!]

const valuesTitlesMap = useMemo(() => {
if (!item.values) {
return {
true: 'ON',
false: 'OFF',
}
}
return Object.fromEntries(item.values.map((value) => {
if (typeof value === 'string') {
return [value, titleCase(noCase(value))]
} else {
return [value[0], value[1]]
}
}))
}, [item.values])

return <Button
label={`${item.text}: ${optionValue ? 'ON' : 'OFF'}`}
label={`${item.text}: ${valuesTitlesMap[optionValue]}`}
onClick={() => {
options[item.id!] = !options[item.id!]
const { values } = item
if (values) {
const getOptionValue = (arrItem) => {
if (typeof arrItem === 'string') {
return arrItem
} else {
return arrItem[0]
}
}
const currentIndex = values.findIndex((value) => {
return getOptionValue(value) === optionValue
})
if (currentIndex === -1) {
options[item.id!] = getOptionValue(values[0])
} else {
options[item.id!] = getOptionValue(values[(currentIndex + 1) % values.length])
}
} else {
options[item.id!] = !options[item.id!]
}
}}
title={item.disabledReason ? `${item.disabledReason} | ${item.tooltip}` : item.tooltip}
disabled={!!item.disabledReason}
Expand Down
2 changes: 1 addition & 1 deletion src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export async function getScreenRefreshRate (): Promise<number> {
const fps = Math.floor(1000 * 10 / (DOMHighResTimeStamp - t0))

if (!callbackTriggered || fps > 1000) {
resolve(Math.max(fps, 1000)/* , DOMHighResTimeStampCollection */)
resolve(Math.min(fps, 1000)/* , DOMHighResTimeStampCollection */)
}

callbackTriggered = true
Expand Down

0 comments on commit ae56415

Please sign in to comment.