1
- import { useCallback , useEffect , useRef , useState } from "react" ;
1
+ import { useCallback , useEffect , useMemo , useRef , useState } from "react" ;
2
2
import { LuCornerDownLeft } from "react-icons/lu" ;
3
3
import { ExclamationCircleIcon } from "@heroicons/react/16/solid" ;
4
4
import { useClose } from "@headlessui/react" ;
@@ -39,6 +39,13 @@ export default function PasteModal() {
39
39
state => state . setKeyboardLayout ,
40
40
) ;
41
41
42
+ // this ensures we always get the original en-US if it hasn't been set yet
43
+ const safeKeyboardLayout = useMemo ( ( ) => {
44
+ if ( keyboardLayout && keyboardLayout . length > 0 )
45
+ return keyboardLayout ;
46
+ return "en-US" ;
47
+ } , [ keyboardLayout ] ) ;
48
+
42
49
useEffect ( ( ) => {
43
50
send ( "getKeyboardLayout" , { } , resp => {
44
51
if ( "error" in resp ) return ;
@@ -56,29 +63,28 @@ export default function PasteModal() {
56
63
setPasteMode ( false ) ;
57
64
setDisableVideoFocusTrap ( false ) ;
58
65
if ( rpcDataChannel ?. readyState !== "open" || ! TextAreaRef . current ) return ;
59
- if ( ! keyboardLayout ) return ;
60
- if ( ! chars [ keyboardLayout ] ) return ;
61
-
66
+ if ( ! safeKeyboardLayout ) return ;
67
+ if ( ! chars [ safeKeyboardLayout ] ) return ;
62
68
const text = TextAreaRef . current . value ;
63
69
64
70
try {
65
71
for ( const char of text ) {
66
- const { key, shift, altRight, deadKey, accentKey } = chars [ keyboardLayout ] [ char ]
72
+ const { key, shift, altRight, deadKey, accentKey } = chars [ safeKeyboardLayout ] [ char ]
67
73
if ( ! key ) continue ;
68
74
69
- const keyz = [ keys [ key ] ] ;
70
- const modz = [ modifierCode ( shift , altRight ) ] ;
75
+ const keyz = [ keys [ key ] ] ;
76
+ const modz = [ modifierCode ( shift , altRight ) ] ;
71
77
72
- if ( deadKey ) {
78
+ if ( deadKey ) {
73
79
keyz . push ( keys [ "Space" ] ) ;
74
80
modz . push ( noModifier ) ;
75
- }
76
- if ( accentKey ) {
81
+ }
82
+ if ( accentKey ) {
77
83
keyz . unshift ( keys [ accentKey . key ] )
78
84
modz . unshift ( modifierCode ( accentKey . shift , accentKey . altRight ) )
79
- }
85
+ }
80
86
81
- for ( const [ index , kei ] of keyz . entries ( ) ) {
87
+ for ( const [ index , kei ] of keyz . entries ( ) ) {
82
88
await new Promise < void > ( ( resolve , reject ) => {
83
89
send (
84
90
"keyboardReport" ,
@@ -92,13 +98,13 @@ export default function PasteModal() {
92
98
} ,
93
99
) ;
94
100
} ) ;
95
- }
101
+ }
96
102
}
97
103
} catch ( error ) {
98
104
console . error ( error ) ;
99
105
notifications . error ( "Failed to paste text" ) ;
100
106
}
101
- } , [ rpcDataChannel ?. readyState , send , setDisableVideoFocusTrap , setPasteMode , keyboardLayout ] ) ;
107
+ } , [ rpcDataChannel ?. readyState , send , setDisableVideoFocusTrap , setPasteMode , safeKeyboardLayout ] ) ;
102
108
103
109
useEffect ( ( ) => {
104
110
if ( TextAreaRef . current ) {
@@ -148,7 +154,7 @@ export default function PasteModal() {
148
154
// @ts -expect-error TS doesn't recognize Intl.Segmenter in some environments
149
155
[ ...new Intl . Segmenter ( ) . segment ( value ) ]
150
156
. map ( x => x . segment )
151
- . filter ( char => ! chars [ keyboardLayout ] [ char ] ) ,
157
+ . filter ( char => ! chars [ safeKeyboardLayout ] [ char ] ) ,
152
158
) ,
153
159
] ;
154
160
@@ -167,11 +173,11 @@ export default function PasteModal() {
167
173
) }
168
174
</ div >
169
175
</ div >
170
- < div className = "space-y-4" >
176
+ < div className = "space-y-4" >
171
177
< p className = "text-xs text-slate-600 dark:text-slate-400" >
172
- Sending text using keyboard layout: { layouts [ keyboardLayout ] }
178
+ Sending text using keyboard layout: { layouts [ safeKeyboardLayout ] }
173
179
</ p >
174
- </ div >
180
+ </ div >
175
181
</ div >
176
182
</ div >
177
183
</ div >
0 commit comments