Skip to content

Commit 45bc76d

Browse files
committed
hotfix(chat): fix all annoying issues on mobile. fix chat was not visible on mobile at all!
1 parent 01567ea commit 45bc76d

File tree

2 files changed

+91
-7
lines changed

2 files changed

+91
-7
lines changed

src/react/Chat.css

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ div.chat-wrapper {
55
padding-left: calc(env(safe-area-inset-left) / 2);
66
padding-right: calc(env(safe-area-inset-right, 4px) / 2);
77
box-sizing: content-box;
8+
}
9+
10+
/* Only apply overflow hidden when not in mobile mode */
11+
div.chat-wrapper:not(.display-mobile):not(.input-mobile) {
812
overflow: hidden;
913
}
1014

@@ -69,7 +73,7 @@ div.chat-wrapper {
6973
top: 100%;
7074
padding-left: calc(env(safe-area-inset-left) / 2);
7175
margin-top: 14px;
72-
margin-left: 20px;
76+
margin-left: 40px;
7377
/* input height */
7478
}
7579

@@ -116,6 +120,11 @@ div.chat-wrapper {
116120
justify-content: flex-start;
117121
}
118122

123+
.input-mobile .chat-completions-items > div {
124+
padding: 4px 0;
125+
font-size: 10px;
126+
}
127+
119128
.input-mobile {
120129
top: 15px;
121130
position: absolute;

src/react/Chat.tsx

Lines changed: 81 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,9 @@ export default ({
112112

113113
const sendHistoryRef = useRef(JSON.parse(window.sessionStorage.chatHistory || '[]'))
114114
const [isInputFocused, setIsInputFocused] = useState(false)
115-
const spellCheckEnabled = false
115+
const [spellCheckEnabled, setSpellCheckEnabled] = useState(false)
116+
const [preservedInputValue, setPreservedInputValue] = useState('')
117+
const [inputKey, setInputKey] = useState(0)
116118
const pingHistoryRef = useRef(JSON.parse(window.localStorage.pingHistory || '[]'))
117119

118120
const [completePadText, setCompletePadText] = useState('')
@@ -237,12 +239,16 @@ export default ({
237239
if (opened) {
238240
completeRequestValue.current = ''
239241
resetCompletionItems()
242+
} else {
243+
setPreservedInputValue('')
240244
}
241245
}, [opened])
242246

243247
const onMainInputChange = () => {
244248
const lastWord = chatInput.current.value.slice(0, chatInput.current.selectionEnd ?? chatInput.current.value.length).split(' ').at(-1)!
245-
if (lastWord.startsWith('@') && getPingComplete) {
249+
const isCommand = chatInput.current.value.startsWith('/')
250+
251+
if (lastWord.startsWith('@') && getPingComplete && !isCommand) {
246252
setCompletePadText(lastWord)
247253
void fetchPingCompletions(true, lastWord.slice(1))
248254
return
@@ -322,6 +328,29 @@ export default ({
322328
return completeValue
323329
}
324330

331+
const handleSlashCommand = () => {
332+
remountInput('/')
333+
}
334+
335+
const handleAcceptFirstCompletion = () => {
336+
if (completionItems.length > 0) {
337+
acceptComplete(completionItems[0])
338+
}
339+
}
340+
341+
const remountInput = (newValue?: string) => {
342+
if (newValue !== undefined) {
343+
setPreservedInputValue(newValue)
344+
}
345+
setInputKey(k => k + 1)
346+
}
347+
348+
useEffect(() => {
349+
if (preservedInputValue && chatInput.current) {
350+
chatInput.current.focus()
351+
}
352+
}, [inputKey]) // Changed from spellCheckEnabled to inputKey
353+
325354
return (
326355
<>
327356
<div
@@ -386,8 +415,53 @@ export default ({
386415
</div>
387416

388417
<div className={`chat-wrapper chat-input-wrapper ${usingTouch ? 'input-mobile' : ''}`} hidden={!opened}>
389-
{/* close button */}
390-
{usingTouch && <Button icon={pixelartIcons.close} onClick={() => onClose?.()} />}
418+
{usingTouch && (
419+
<>
420+
<Button
421+
icon={pixelartIcons.close}
422+
onClick={() => onClose?.()}
423+
style={{
424+
width: 20,
425+
flexShrink: 0,
426+
}}
427+
/>
428+
429+
{(chatInput.current?.value && !chatInput.current.value.startsWith('/')) ? (
430+
// TOGGLE SPELL CHECK
431+
<Button
432+
style={{
433+
width: 20,
434+
flexShrink: 0,
435+
}}
436+
overlayColor={spellCheckEnabled ? '#00ff00' : '#ff0000'}
437+
icon={pixelartIcons['text-wrap']}
438+
onClick={() => {
439+
setPreservedInputValue(chatInput.current?.value || '')
440+
setSpellCheckEnabled(!spellCheckEnabled)
441+
remountInput()
442+
}}
443+
/>
444+
) : (
445+
// SLASH COMMAND
446+
<Button
447+
style={{
448+
width: 20,
449+
flexShrink: 0,
450+
}}
451+
label={chatInput.current?.value ? undefined : '/'}
452+
icon={chatInput.current?.value ? pixelartIcons['arrow-right'] : undefined}
453+
onClick={() => {
454+
const inputValue = chatInput.current.value
455+
if (!inputValue) {
456+
handleSlashCommand()
457+
} else if (completionItems.length > 0) {
458+
handleAcceptFirstCompletion()
459+
}
460+
}}
461+
/>
462+
)}
463+
</>
464+
)}
391465
<div className="chat-input">
392466
{isInputFocused && completionItems?.length ? (
393467
<div className="chat-completions">
@@ -431,9 +505,10 @@ export default ({
431505
/>}
432506
<input
433507
maxLength={chatVanillaRestrictions ? 256 : undefined}
434-
defaultValue=''
508+
defaultValue={preservedInputValue}
435509
// ios doesn't support toggling autoCorrect on the fly so we need to re-create the input
436-
key={spellCheckEnabled ? 'true' : 'false'}
510+
key={`${inputKey}`}
511+
autoCapitalize={preservedInputValue ? 'off' : 'on'}
437512
ref={chatInput}
438513
type="text"
439514
className="chat-input"

0 commit comments

Comments
 (0)