11import type { ReactNode , RefObject } from 'react' ;
2- import { useCallback , useRef , useState } from 'react' ;
2+ import { useCallback , useMemo , useRef , useState } from 'react' ;
33
44import { useRoute } from '@react-navigation/core' ;
55import { noop } from 'lodash' ;
@@ -10,6 +10,7 @@ import Animated, {
1010 useSharedValue ,
1111} from 'react-native-reanimated' ;
1212
13+ import type { IInputRef , ITextAreaInputProps } from '@onekeyhq/components' ;
1314import {
1415 Button ,
1516 HeightTransition ,
@@ -35,14 +36,134 @@ import {
3536
3637import backgroundApiProxy from '../../../background/instance/backgroundApiProxy' ;
3738import useAppNavigation from '../../../hooks/useAppNavigation' ;
38- import { useAppRoute } from '../../../hooks/useAppRoute' ;
3939import { fixInputImportSingleChain } from '../../Onboarding/pages/ImportWallet/ImportSingleChainBase' ;
4040import useScanQrCode from '../../ScanQrCode/hooks/useScanQrCode' ;
4141import { OnboardingLayout } from '../components/OnboardingLayout' ;
4242import { PhaseInputArea } from '../components/PhaseInputArea' ;
4343
4444import type { IPhaseInputAreaInstance } from '../components/PhaseInputArea' ;
4545import type { RouteProp } from '@react-navigation/core' ;
46+ import type {
47+ NativeSyntheticEvent ,
48+ TextInput ,
49+ TextInputSelectionChangeEventData ,
50+ } from 'react-native' ;
51+
52+ function PrivateKeyInput ( { value = '' , onChangeText } : ITextAreaInputProps ) {
53+ const intl = useIntl ( ) ;
54+ const [ privateKey , setPrivateKey ] = useState ( value ) ;
55+ const { start : startScanQrCode } = useScanQrCode ( ) ;
56+ const [ encrypted , setEncrypted ] = useState ( true ) ;
57+ const inputRef = useRef < IInputRef > ( null ) ;
58+
59+ const privateKeyRef = useRef ( privateKey ) ;
60+ privateKeyRef . current = privateKey ;
61+ const selectionRef = useRef ( { start : 0 , end : 0 } ) ;
62+
63+ const handleSelectionChange = useCallback (
64+ ( e : NativeSyntheticEvent < TextInputSelectionChangeEventData > ) => {
65+ const selection = e . nativeEvent . selection ;
66+ console . log ( 'handleSelectionChange' , selection ) ;
67+ selectionRef . current = selection ;
68+ } ,
69+ [ ] ,
70+ ) ;
71+
72+ const formattedValue = useMemo ( ( ) => {
73+ if ( encrypted ) {
74+ return '•' . repeat ( privateKey . length ) ;
75+ }
76+ return privateKey ;
77+ } , [ encrypted , privateKey ] ) ;
78+
79+ const updatePrivateKey = useCallback (
80+ ( text : string ) => {
81+ setPrivateKey ( text ) ;
82+ onChangeText ?.( text ) ;
83+ } ,
84+ [ onChangeText ] ,
85+ ) ;
86+
87+ const handleChangeText = useCallback (
88+ ( text : string ) => {
89+ if ( encrypted ) {
90+ // Find non-asterisk characters in text and merge with actual privateKey
91+ const selection = selectionRef . current ;
92+ let newPrivateKey = privateKeyRef . current ;
93+
94+ // Calculate the difference between old and new text
95+ const oldLength = privateKeyRef . current . length ;
96+ const newLength = text . length ;
97+
98+ const selectionRange = selection . end - selection . start ;
99+
100+ if ( selectionRange > 0 ) {
101+ // Text was selected and replaced - replace selected characters with new text
102+ const selectedText = text
103+ . slice ( selection . start , selection . end )
104+ . replace ( / • / g, '' ) ;
105+ newPrivateKey =
106+ privateKeyRef . current . slice ( 0 , selection . start ) +
107+ selectedText +
108+ privateKeyRef . current . slice ( selection . end ) ;
109+ } else if ( newLength > oldLength ) {
110+ // Text was added - insert new characters at selection position
111+ const addedText = text . slice (
112+ selection . start ,
113+ selection . start + ( newLength - oldLength ) ,
114+ ) ;
115+ newPrivateKey =
116+ privateKeyRef . current . slice ( 0 , selection . start ) +
117+ addedText +
118+ privateKeyRef . current . slice ( selection . start ) ;
119+ } else if ( newLength < oldLength ) {
120+ // Text was removed - remove characters from selection position
121+ const removedCount = oldLength - newLength ;
122+ const selectionStart = selection . start - 1 ;
123+ newPrivateKey =
124+ privateKeyRef . current . slice ( 0 , selectionStart ) +
125+ privateKeyRef . current . slice ( selectionStart + removedCount ) ;
126+ } else {
127+ // Text was replaced - replace characters at selection position
128+ const replacedText = text . slice ( selection . start , selection . end ) ;
129+ newPrivateKey =
130+ privateKeyRef . current . slice ( 0 , selection . start ) +
131+ replacedText +
132+ privateKeyRef . current . slice ( selection . end ) ;
133+ }
134+
135+ updatePrivateKey ( newPrivateKey ) ;
136+ } else {
137+ updatePrivateKey ( text ) ;
138+ }
139+ } ,
140+ [ encrypted , updatePrivateKey ] ,
141+ ) ;
142+
143+ return (
144+ < TextAreaInput
145+ ref = { inputRef as RefObject < TextInput > }
146+ allowPaste
147+ allowClear
148+ allowScan
149+ allowSecureTextEye // TextAreaInput not support allowSecureTextEye
150+ onSelectionChange = { handleSelectionChange }
151+ clearClipboardOnPaste
152+ onSecureTextEntryChange = { setEncrypted }
153+ startScanQrCode = { startScanQrCode }
154+ size = "large"
155+ numberOfLines = { 5 }
156+ value = { formattedValue }
157+ onChangeText = { handleChangeText }
158+ $platform-native = { {
159+ minHeight : 160 ,
160+ } }
161+ placeholder = { intl . formatMessage ( {
162+ id : ETranslations . form_enter_private_key_placeholder ,
163+ } ) }
164+ />
165+ ) ;
166+ }
46167
47168export default function ImportPhraseOrPrivateKey ( ) {
48169 const navigation = useAppNavigation ( ) ;
@@ -221,23 +342,9 @@ export default function ImportPhraseOrPrivateKey() {
221342 } }
222343 gap = "$5"
223344 >
224- < Input
225- allowPaste
226- allowClear
227- allowScan
228- allowSecureTextEye // TextAreaInput not support allowSecureTextEye
229- clearClipboardOnPaste
230- startScanQrCode = { startScanQrCode }
231- size = "large"
232- numberOfLines = { 5 }
345+ < PrivateKeyInput
233346 value = { privateKey }
234347 onChangeText = { setPrivateKey }
235- $platform-native = { {
236- minHeight : 160 ,
237- } }
238- placeholder = { intl . formatMessage ( {
239- id : ETranslations . form_enter_private_key_placeholder ,
240- } ) }
241348 />
242349 </ YStack >
243350 ) }
0 commit comments