@@ -53,6 +53,12 @@ export type WalletMeta = {
53
53
54
54
const maxAllowedImagesPerMessage = 4 ;
55
55
56
+ function showSigninToUploadImagesToast ( ) {
57
+ toast . error ( "Sign in to upload images to Nebula" , {
58
+ position : "top-right" ,
59
+ } ) ;
60
+ }
61
+
56
62
export function ChatBar ( props : {
57
63
sendMessage : ( message : NebulaUserMessage ) => void ;
58
64
isChatStreaming : boolean ;
@@ -105,6 +111,8 @@ export function ChatBar(props: {
105
111
} ,
106
112
} ) ;
107
113
114
+ const supportedFileTypes = [ "image/jpeg" , "image/png" , "image/webp" ] ;
115
+
108
116
async function handleImageUpload ( files : File [ ] ) {
109
117
const totalFiles = files . length + images . length ;
110
118
@@ -113,14 +121,22 @@ export function ChatBar(props: {
113
121
`You can only upload up to ${ maxAllowedImagesPerMessage } images at a time` ,
114
122
{
115
123
position : "top-right" ,
116
- }
124
+ } ,
117
125
) ;
118
126
return ;
119
127
}
120
128
121
129
const validFiles : File [ ] = [ ] ;
122
130
123
131
for ( const file of files ) {
132
+ if ( ! supportedFileTypes . includes ( file . type ) ) {
133
+ toast . error ( "Unsupported file type" , {
134
+ description : `File: ${ file . name } ` ,
135
+ position : "top-right" ,
136
+ } ) ;
137
+ continue ;
138
+ }
139
+
124
140
if ( file . size <= 5 * 1024 * 1024 ) {
125
141
validFiles . push ( file ) ;
126
142
} else {
@@ -136,7 +152,7 @@ export function ChatBar(props: {
136
152
validFiles . map ( async ( image ) => {
137
153
const b64 = await uploadImageMutation . mutateAsync ( image ) ;
138
154
return { file : image , b64 : b64 } ;
139
- } )
155
+ } ) ,
140
156
) ;
141
157
142
158
setImages ( ( prev ) => [ ...prev , ...urls ] ) ;
@@ -153,38 +169,43 @@ export function ChatBar(props: {
153
169
< div
154
170
className = { cn (
155
171
"overflow-hidden rounded-2xl border border-border bg-card transition-colors" ,
156
- isDragOver &&
157
- props . allowImageUpload &&
158
- "border-nebula-pink-foreground bg-nebula-pink/5" ,
159
- props . className
172
+ isDragOver && "border-nebula-pink-foreground bg-nebula-pink/5" ,
173
+ props . className ,
160
174
) }
161
175
onDrop = { ( e ) => {
162
- e . preventDefault ( ) ;
163
176
setIsDragOver ( false ) ;
164
- if ( ! props . allowImageUpload ) return ;
177
+ e . preventDefault ( ) ;
178
+ if ( ! props . allowImageUpload ) {
179
+ showSigninToUploadImagesToast ( ) ;
180
+ return ;
181
+ }
165
182
const files = Array . from ( e . dataTransfer . files ) ;
166
183
if ( files . length > 0 ) handleImageUpload ( files ) ;
167
184
} }
168
185
onDragOver = { ( e ) => {
169
186
e . preventDefault ( ) ;
170
- if ( props . allowImageUpload ) {
171
- setIsDragOver ( true ) ;
187
+ setIsDragOver ( true ) ;
188
+ if ( ! props . allowImageUpload ) {
189
+ return ;
172
190
}
173
191
} }
174
192
onDragEnter = { ( e ) => {
175
193
e . preventDefault ( ) ;
176
- if ( props . allowImageUpload ) {
177
- setIsDragOver ( true ) ;
194
+ setIsDragOver ( true ) ;
195
+ if ( ! props . allowImageUpload ) {
196
+ return ;
178
197
}
179
198
} }
180
199
onDragLeave = { ( e ) => {
181
200
e . preventDefault ( ) ;
201
+ if ( ! props . allowImageUpload ) {
202
+ return ;
203
+ }
182
204
// Only set drag over to false if we're leaving the container entirely
183
205
if ( ! e . currentTarget . contains ( e . relatedTarget as Node ) ) {
184
206
setIsDragOver ( false ) ;
185
207
}
186
208
} }
187
- aria-dropeffect = { props . allowImageUpload ? "copy" : "none" }
188
209
>
189
210
{ images . length > 0 && (
190
211
< ImagePreview
@@ -203,10 +224,13 @@ export function ChatBar(props: {
203
224
value = { message }
204
225
onChange = { ( e ) => setMessage ( e . target . value ) }
205
226
onPaste = { ( e ) => {
206
- if ( ! props . allowImageUpload ) return ;
207
227
const files = Array . from ( e . clipboardData . files ) ;
208
228
if ( files . length > 0 ) {
209
229
e . preventDefault ( ) ;
230
+ if ( ! props . allowImageUpload ) {
231
+ showSigninToUploadImagesToast ( ) ;
232
+ return ;
233
+ }
210
234
handleImageUpload ( files ) ;
211
235
}
212
236
} }
@@ -321,7 +345,7 @@ export function ChatBar(props: {
321
345
< ImageUploadButton
322
346
multiple
323
347
value = { undefined }
324
- accept = "image/jpeg,image/png,image/webp"
348
+ accept = { supportedFileTypes . join ( "," ) }
325
349
onChange = { ( files ) => {
326
350
handleImageUpload ( files ) ;
327
351
} }
@@ -582,7 +606,7 @@ function WalletSelector(props: {
582
606
key = { wallet . address }
583
607
className = { cn (
584
608
"flex cursor-pointer items-center justify-between px-3 py-4 hover:bg-accent/50" ,
585
- props . selectedAddress === wallet . address && "bg-accent/50"
609
+ props . selectedAddress === wallet . address && "bg-accent/50" ,
586
610
) }
587
611
onKeyDown = { ( e ) => {
588
612
if ( e . key === "Enter" || e . key === " " ) {
0 commit comments