@@ -3,28 +3,23 @@ import {
33 StyleSheet ,
44 Text ,
55 Image ,
6- TextInput ,
7- TouchableOpacity ,
8- KeyboardAvoidingView ,
9- Platform ,
10- TouchableWithoutFeedback ,
116 Keyboard ,
7+ TouchableWithoutFeedback ,
128} from 'react-native' ;
139import React , { useContext , useEffect , useState } from 'react' ;
1410import Spinner from 'react-native-loading-spinner-overlay' ;
1511import { useTextToImage , BK_SDM_TINY_VPRED } from 'react-native-executorch' ;
1612import { GeneratingContext } from '../../context' ;
1713import ColorPalette from '../../colors' ;
1814import ProgressBar from '../../components/ProgressBar' ;
19-
20- type InputState =
21- | { kind : 'prompt' ; value : string }
22- | { kind : 'image' ; uri : string } ;
15+ import { BottomBarWithTextInput } from '../../components/BottomBarWithTextInput' ;
2316
2417export default function TextToImageScreen ( ) {
2518 const [ inferenceStepIdx , setInferenceStepIdx ] = useState < number > ( 0 ) ;
2619 const [ imageTitle , setImageTitle ] = useState < string | null > ( null ) ;
27- const [ numSteps , setNumSteps ] = useState < number > ( 10 ) ;
20+ const [ image , setImage ] = useState < string | null > ( null ) ;
21+ const [ steps , setSteps ] = useState < number > ( 10 ) ;
22+ const [ showTextInput , setShowTextInput ] = useState ( false ) ;
2823 const [ keyboardVisible , setKeyboardVisible ] = useState ( false ) ;
2924
3025 const imageSize = 352 ;
@@ -35,42 +30,37 @@ export default function TextToImageScreen() {
3530
3631 const { setGlobalGenerating } = useContext ( GeneratingContext ) ;
3732
38- const [ inputState , setInputState ] = useState < InputState > ( {
39- kind : 'prompt' ,
40- value : '' ,
41- } ) ;
42-
4333 useEffect ( ( ) => {
4434 setGlobalGenerating ( model . isGenerating ) ;
4535 } , [ model . isGenerating , setGlobalGenerating ] ) ;
4636
4737 useEffect ( ( ) => {
48- const onKeyboardShow = Keyboard . addListener ( 'keyboardDidShow' , ( ) =>
49- setKeyboardVisible ( true )
50- ) ;
51- const onKeyboardHide = Keyboard . addListener ( 'keyboardDidHide' , ( ) =>
52- setKeyboardVisible ( false )
53- ) ;
38+ const showSub = Keyboard . addListener ( 'keyboardDidShow' , ( ) => {
39+ setKeyboardVisible ( true ) ;
40+ } ) ;
41+ const hideSub = Keyboard . addListener ( 'keyboardDidHide' , ( ) => {
42+ setKeyboardVisible ( false ) ;
43+ } ) ;
5444 return ( ) => {
55- onKeyboardShow . remove ( ) ;
56- onKeyboardHide . remove ( ) ;
45+ showSub . remove ( ) ;
46+ hideSub . remove ( ) ;
5747 } ;
5848 } , [ ] ) ;
5949
60- const runForward = async ( ) => {
61- if ( inputState . kind !== 'prompt' || ! inputState . value . trim ( ) ) return ;
62- setImageTitle ( inputState . value ) ;
50+ const runForward = async ( input : string , numSteps : number ) => {
51+ if ( ! input || ! input . trim ( ) ) return ;
52+ setImageTitle ( input ) ;
53+ setSteps ( numSteps ) ;
6354 try {
64- const output = await model . generate (
65- inputState . value ,
66- imageSize ,
67- numSteps
68- ) ;
55+ const output = await model . generate ( input , imageSize , steps ) ;
56+ console . log ( 'Is output?' , ! ! output ) ;
57+ console . log ( output ) ;
6958 if ( ! output . length ) {
59+ console . log ( 'interrupted' ) ;
7060 setImageTitle ( null ) ;
7161 return ;
7262 }
73- setInputState ( { kind : 'image' , uri : output } ) ;
63+ setImage ( output ) ;
7464 } catch ( e ) {
7565 console . error ( e ) ;
7666 setImageTitle ( null ) ;
@@ -79,9 +69,6 @@ export default function TextToImageScreen() {
7969 }
8070 } ;
8171
82- const decreaseSteps = ( ) => setNumSteps ( ( prev ) => Math . max ( 5 , prev - 5 ) ) ;
83- const increaseSteps = ( ) => setNumSteps ( ( prev ) => Math . min ( 50 , prev + 5 ) ) ;
84-
8572 if ( ! model . isReady ) {
8673 return (
8774 < Spinner
@@ -91,24 +78,31 @@ export default function TextToImageScreen() {
9178 ) ;
9279 }
9380
94- if ( ! model . isGenerating ) {
95- return (
96- < TouchableWithoutFeedback onPress = { Keyboard . dismiss } >
97- < KeyboardAvoidingView
98- style = { styles . container }
99- collapsable = { false }
100- behavior = { Platform . OS === 'ios' ? 'padding' : undefined }
101- keyboardVerticalOffset = { Platform . OS === 'ios' ? 120 : 40 }
102- >
103- < View style = { styles . titleContainer } >
104- { imageTitle && < Text style = { styles . titleText } > { imageTitle } </ Text > }
105- </ View >
81+ return (
82+ < TouchableWithoutFeedback
83+ onPress = { ( ) => {
84+ Keyboard . dismiss ( ) ;
85+ setShowTextInput ( false ) ;
86+ } }
87+ >
88+ < View style = { styles . container } >
89+ { keyboardVisible && < View style = { styles . overlay } /> }
90+
91+ < View style = { styles . titleContainer } >
92+ { imageTitle && < Text style = { styles . titleText } > { imageTitle } </ Text > }
93+ </ View >
10694
95+ { model . isGenerating ? (
96+ < View style = { styles . progressContainer } >
97+ < Text style = { styles . text } > Generating...</ Text >
98+ < ProgressBar numSteps = { steps } currentStep = { inferenceStepIdx } />
99+ </ View >
100+ ) : (
107101 < View style = { styles . imageContainer } >
108- { inputState . kind === ' image' ? (
102+ { image ?. length ? (
109103 < Image
110104 style = { styles . image }
111- source = { { uri : `data:image/png;base64,${ inputState . uri } ` } }
105+ source = { { uri : `data:image/png;base64,${ image } ` } }
112106 />
113107 ) : (
114108 < Image
@@ -117,103 +111,38 @@ export default function TextToImageScreen() {
117111 />
118112 ) }
119113 </ View >
114+ ) }
120115
121- < View style = { styles . bottomContainer } >
122- < TextInput
123- style = { styles . input }
124- placeholder = "Enter prompt..."
125- value = { inputState . kind === 'prompt' ? inputState . value : '' }
126- onChangeText = { ( text ) => {
127- setInputState ( { kind : 'prompt' , value : text } ) ;
128- setImageTitle ( null ) ;
129- } }
130- editable = { ! model . isGenerating }
131- />
132- { ! keyboardVisible && (
133- < View style = { styles . stepsContainer } >
134- < Text style = { styles . text } > Steps: { numSteps } </ Text >
135- < View style = { styles . stepsButtons } >
136- < TouchableOpacity
137- style = { [ styles . button , styles . stepsButton ] }
138- onPress = { decreaseSteps }
139- >
140- < Text style = { styles . buttonText } > -</ Text >
141- </ TouchableOpacity >
142- < TouchableOpacity
143- style = { [ styles . button , styles . stepsButton ] }
144- onPress = { increaseSteps }
145- >
146- < Text style = { styles . buttonText } > +</ Text >
147- </ TouchableOpacity >
148- </ View >
149- </ View >
150- ) }
151- < TouchableOpacity
152- style = { styles . button }
153- onPress = { runForward }
154- disabled = { ! model . isReady }
155- >
156- < Text style = { styles . buttonText } > Run model</ Text >
157- </ TouchableOpacity >
158- </ View >
159- </ KeyboardAvoidingView >
160- </ TouchableWithoutFeedback >
161- ) ;
162- }
163-
164- return (
165- < KeyboardAvoidingView
166- style = { styles . container }
167- behavior = { Platform . OS === 'ios' ? 'padding' : 'height' }
168- keyboardVerticalOffset = { Platform . OS === 'ios' ? 120 : 40 }
169- >
170- < View style = { styles . titleContainer } >
171- { imageTitle && < Text style = { styles . titleText } > { imageTitle } </ Text > }
172- </ View >
173- < View style = { styles . progressContainer } >
174- < Text style = { styles . text } > Generating...</ Text >
175- < ProgressBar numSteps = { numSteps } currentStep = { inferenceStepIdx } />
176- </ View >
177- < View style = { styles . bottomContainer } >
178- < TouchableOpacity
179- style = { styles . button }
180- onPress = { ( ) => model . interrupt ( ) }
181- >
182- < Text style = { styles . buttonText } > Stop model</ Text >
183- </ TouchableOpacity >
116+ < View style = { styles . bottomContainer } >
117+ < BottomBarWithTextInput
118+ runModel = { runForward }
119+ stopModel = { model . interrupt }
120+ isGenerating = { model . isGenerating }
121+ isReady = { model . isReady }
122+ showTextInput = { showTextInput }
123+ setShowTextInput = { setShowTextInput }
124+ keyboardVisible = { keyboardVisible }
125+ />
126+ </ View >
184127 </ View >
185- </ KeyboardAvoidingView >
128+ </ TouchableWithoutFeedback >
186129 ) ;
187130}
188131
189132const styles = StyleSheet . create ( {
190133 container : {
191134 flex : 1 ,
192135 width : '100%' ,
193- padding : 20 ,
194- } ,
195- titleContainer : { alignItems : 'center' , marginTop : 20 } ,
196- bottomContainer : {
197- width : '100%' ,
198- gap : 15 ,
199136 alignItems : 'center' ,
200- padding : 16 ,
201137 } ,
202- imageContainer : { flex : 1 , alignItems : 'center' , justifyContent : 'center' } ,
203- button : {
204- width : '100%' ,
205- height : 50 ,
206- justifyContent : 'center' ,
207- alignItems : 'center' ,
208- backgroundColor : ColorPalette . primary ,
209- borderRadius : 8 ,
138+ overlay : {
139+ ...StyleSheet . absoluteFillObject ,
140+ backgroundColor : 'rgba(0,0,0,0.65)' ,
141+ zIndex : 5 ,
210142 } ,
211- buttonText : { color : '#fff' , fontSize : 16 } ,
212- image : {
213- width : 256 ,
214- height : 256 ,
215- marginVertical : 30 ,
216- resizeMode : 'contain' ,
143+ titleContainer : {
144+ alignItems : 'center' ,
145+ marginTop : 20 ,
217146 } ,
218147 titleText : {
219148 color : ColorPalette . primary ,
@@ -222,34 +151,34 @@ const styles = StyleSheet.create({
222151 marginBottom : 12 ,
223152 textAlign : 'center' ,
224153 } ,
225- text : { fontSize : 16 } ,
226- input : {
227- width : '100%' ,
228- height : 50 ,
229- borderColor : '#ccc' ,
230- borderWidth : 1 ,
231- borderRadius : 8 ,
232- padding : 10 ,
233- marginBottom : 10 ,
154+ text : {
234155 fontSize : 16 ,
156+ color : '#000' ,
235157 } ,
236- progressContainer : {
158+ imageContainer : {
237159 flex : 1 ,
238- justifyContent : 'center' ,
160+ position : 'absolute' ,
161+ top : 100 ,
239162 alignItems : 'center' ,
163+ justifyContent : 'center' ,
240164 } ,
241- stepsContainer : {
242- width : '100%' ,
243- flexDirection : 'row' ,
244- justifyContent : 'space-between' ,
245- alignItems : 'center ' ,
165+ image : {
166+ width : 256 ,
167+ height : 256 ,
168+ marginVertical : 30 ,
169+ resizeMode : 'contain ' ,
246170 } ,
247- stepsButtons : {
248- flexDirection : 'row' ,
249- gap : 10 ,
171+ progressContainer : {
172+ flex : 1 ,
173+ justifyContent : 'center' ,
174+ alignItems : 'center' ,
250175 } ,
251- stepsButton : {
252- width : 40 ,
253- height : 40 ,
176+ bottomContainer : {
177+ flex : 1 ,
178+ width : '90%' ,
179+ position : 'absolute' ,
180+ bottom : 0 ,
181+ marginBottom : 25 ,
182+ zIndex : 10 ,
254183 } ,
255184} ) ;
0 commit comments