2222 narrow-indicator
2323 v-if =" batchSendIsSupported"
2424 >
25- <q-tab name =" send" :disable =" isSending" :label =" $t('Send.single-send')" />
26- <q-tab name =" batch-send" :disable =" isSending" :label =" $t('Send.batch-send')" />
25+ <q-tab name =" send" :disable =" isSending" :label =" $t('Send.single-send')" @click = " handleTabClick() " />
26+ <q-tab name =" batch-send" :disable =" isSending" :label =" $t('Send.batch-send')" @click = " handleTabClick() " />
2727 </q-tabs >
2828
2929 <q-tab-panels v-model =" tab" animated >
114114 :debounce =" 500"
115115 :disable =" isSending"
116116 placeholder =" vitalik.eth"
117- lazy-rules
117+ : lazy-rules= " false "
118118 :hideBottomSpace =" true"
119- :rules =" isValidId"
119+ :rules =" (value: string) => isValidId(value, undefined) "
120120 ref =" recipientIdBaseInputRef"
121121 />
122122 <div class =" flex row text-caption warning-container q-pb-sm" v-if =" recipientIdWarning" >
314314 :debounce =" 500"
315315 :disable =" isSending"
316316 placeholder =" vitalik.eth"
317- lazy-rules
318- :rules =" isValidId"
317+ : lazy-rules= " false "
318+ :rules =" (value: string) => isValidId(value, index) "
319319 />
320-
320+ <div class =" text-caption warning-container" v-if =" batchSends[index].warning" >
321+ <br /><br />
322+ {{ batchSends[index].warning }}
323+ </div >
324+ <div
325+ class =" text-caption warning-container"
326+ v-if =" batchSends[index].validationError && !batchSends[index].warning"
327+ >
328+ <br /><br />
329+ </div >
321330 <!-- Token -->
322331 <div >{{ $t('Send.select-token') }}</div >
323332
348357 <q-separator />
349358 </q-card >
350359 </div >
351- <br /><br />
352360 </div >
353361
354362 <!-- Desktop Layout -->
355- <q-form v-else >
363+ <q-form v-else style = " display : flex ; flex-direction : column " >
356364 <div v-for =" (Send, index) in batchSends" :key =" index" >
357365 <!-- Identifier -->
358-
359366 <div class =" batch-send" >
360367 <p class =" batch-send-label text-grey" >{{ index + 1 }}</p >
361368 <div class =" input-container-address" >
365372 :disable =" isSending"
366373 placeholder =" vitalik.eth"
367374 :label =" $t('Send.receiver-addr-ens')"
368- lazy-rules
369- :rules =" isValidId"
375+ : lazy-rules= " false "
376+ :rules =" (value: string) => isValidId(value, index) "
370377 />
371378 </div >
372379
407414 icon =" fas fa-times"
408415 />
409416 </div >
417+ <div class =" batch-send" v-if =" batchSends[index].validationError" >
418+ <div ><br /></div >
419+ </div >
420+ <div v-for =" n in numberOfErrorOrWarningBreaksNeeded" :key =" n" >
421+ <br v-if =" batchSends[index].validationError" />
422+ </div >
423+ <div class =" batch-send" v-if =" batchSends[index].warning" >
424+ <div class =" text-caption batch-send-warning-container" >
425+ {{ batchSends[index].warning }}
426+ </div >
427+ <p class =" input-container-token" ></p >
428+ <p class =" input-container-token" ></p >
429+ </div >
410430 </div >
411431 </q-form >
412432 <!-- Toll + summary details -->
449469 </tbody >
450470 </q-markup-table >
451471 </div >
452-
453472 <!-- Send button -->
454473 <div class =" batch-send-buttons" >
455474 <base-button
465484 :flat =" true"
466485 :label =" $t('Send.add-send')"
467486 />
468-
469487 <div >
470488 <router-link :class =" { 'no-text-decoration': true, 'dark-toggle': true }" :to =" { name: 'sent' }" >
471489 <div class =" row items-center justify-center q-pa-sm link-container rounded-borders" >
@@ -522,6 +540,8 @@ interface BatchSendData {
522540 receiver: string | undefined ;
523541 token: TokenInfoExtended | null | undefined ;
524542 amount: string ;
543+ warning: string ;
544+ validationError: boolean ;
525545}
526546
527547function useSendForm() {
@@ -573,8 +593,10 @@ function useSendForm() {
573593 // Batch Send Form Parameters
574594 const batchSends = ref <BatchSendData []>([]);
575595 const tab = ref (' send' );
596+ const previousTabChecked = ref (' send' );
576597 const batchSendSupportedChains = [1 , 10 , 100 , 137 , 42161 , 11155111 ];
577598 const batchSendIsSupported = ref (false );
599+ const numberOfErrorOrWarningBreaksNeeded = ref (0 );
578600
579601 // Computed form parameters.
580602 const showAdvancedWarning = computed (() => advancedAcknowledged .value === false && useNormalPubKey .value === true );
@@ -729,15 +751,15 @@ function useSendForm() {
729751
730752 let validatedBatchSendForm = true ;
731753 const isValidRecipientPromises: Promise <boolean | string >[] = [];
732- for ( const batchSend of batchSends .value ) {
754+ batchSends .value . forEach (( batchSend , index ) => {
733755 if (validatedBatchSendForm ) {
734756 const { token, amount, receiver } = batchSend ;
735757 const isValidAmount = Boolean (amount ) && isValidTokenAmount (amount , token );
736758 const isValidToken = Boolean (token );
737- isValidRecipientPromises .push (isValidId (receiver ));
759+ isValidRecipientPromises .push (isValidId (receiver , index ));
738760 if (isValidAmount !== true || ! receiver || ! isValidToken ) validatedBatchSendForm = false ;
739761 }
740- }
762+ });
741763 if (validatedBatchSendForm ) {
742764 await Promise .all (isValidRecipientPromises ).then ((results ) => {
743765 for (const result of results ) {
@@ -753,8 +775,8 @@ function useSendForm() {
753775 onMounted (async () => {
754776 await setPaymentLinkData ();
755777 batchSends .value .push (
756- { id: 1 , receiver: ' ' , token: NATIVE_TOKEN .value , amount: ' ' },
757- { id: 2 , receiver: ' ' , token: NATIVE_TOKEN .value , amount: ' ' }
778+ { id: 1 , receiver: ' ' , token: NATIVE_TOKEN .value , amount: ' ' , warning: ' ' , validationError: false },
779+ { id: 2 , receiver: ' ' , token: NATIVE_TOKEN .value , amount: ' ' , warning: ' ' , validationError: false }
758780 );
759781 const chainId = BigNumber .from (currentChain .value ?.chainId || 0 ).toNumber ();
760782 batchSendIsSupported .value = batchSendSupportedChains .includes (chainId );
@@ -795,6 +817,8 @@ function useSendForm() {
795817 receiver: ' ' ,
796818 token: NATIVE_TOKEN .value ,
797819 amount: ' ' ,
820+ warning: ' ' ,
821+ validationError: false ,
798822 });
799823 }
800824
@@ -803,19 +827,57 @@ function useSendForm() {
803827 batchSends .value .splice (index , 1 );
804828 }
805829
830+ function calculateErrorOrWarningBreaks() {
831+ // Width setpoints for extra break(s) needed after error (or before warning) message on the batch send page
832+ // These are eeded to prevent the error message from overlapping with the warning field field,
833+ // as page width and layout dictate the number of error lines (and therefore) breaks needed.
834+ const warningWidths = [1140 , 955 , 790 , 710 , 685 , 645 , 630 ];
835+ numberOfErrorOrWarningBreaksNeeded .value = 0 ;
836+ for (const width of warningWidths ) {
837+ if (window .innerWidth < width ) numberOfErrorOrWarningBreaksNeeded .value += 1 ;
838+ }
839+ }
840+
841+ function setWarning(warning : string , index : number | undefined ) {
842+ if (index !== undefined ) {
843+ batchSends .value [index ].warning = warning ;
844+ } else {
845+ recipientIdWarning .value = warning ;
846+ }
847+ }
848+
849+ function handleTabClick() {
850+ setWarning (' ' , undefined );
851+ for (let i = 0 ; i < batchSends .value .length ; i ++ ) {
852+ setWarning (' ' , i );
853+ }
854+ }
855+
806856 // Validators
807- async function isValidId(val : string | undefined ) {
857+ async function isValidId(val : string | undefined , index : number | undefined ) {
858+ // Check if confusable chars in string, throws with warning if so
859+ checkConfusables (val , index );
860+
808861 // Return true if nothing is provided
809- checkConfusables ();
810862 if (! val ) return true ;
811863
812864 // Check if recipient ID is valid
813865 try {
814866 await umbraUtils .lookupRecipient (val , provider .value as Provider , {
815867 advanced: shouldUseNormalPubKey .value ,
816868 });
869+ if (index !== undefined ) {
870+ batchSends .value [index ].validationError = false ;
871+ }
817872 return true ;
818873 } catch (e : unknown ) {
874+ if (index !== undefined ) {
875+ batchSends .value [index ].validationError = true ;
876+ if (batchSends .value [index ].warning === ' ' ) {
877+ // checkConfusables didn't find a warning but we have an error, we may need breaks depending on page width
878+ calculateErrorOrWarningBreaks ();
879+ }
880+ }
819881 const toSentenceCase = (str : string ) => str [0 ].toUpperCase () + str .slice (1 );
820882 if (e instanceof Error && e .message ) return toSentenceCase (e .message );
821883 if ((e as { reason: string }).reason ) return toSentenceCase ((e as { reason: string }).reason );
@@ -1158,8 +1220,8 @@ function useSendForm() {
11581220
11591221 function resetBatchSendForm() {
11601222 batchSends .value = [
1161- { id: 1 , receiver: ' ' , token: NATIVE_TOKEN .value , amount: ' ' },
1162- { id: 2 , receiver: ' ' , token: NATIVE_TOKEN .value , amount: ' ' },
1223+ { id: 1 , receiver: ' ' , token: NATIVE_TOKEN .value , amount: ' ' , warning: ' ' , validationError: false },
1224+ { id: 2 , receiver: ' ' , token: NATIVE_TOKEN .value , amount: ' ' , warning: ' ' , validationError: false },
11631225 ];
11641226 }
11651227
@@ -1206,16 +1268,19 @@ function useSendForm() {
12061268 );
12071269 }
12081270
1209- function checkConfusables() {
1210- const recipientIdString = recipientId .value || ' ' ;
1271+ function checkConfusables(recipientIdString : string | undefined , index : number | undefined ) {
1272+ if (previousTabChecked .value !== tab .value ) {
1273+ previousTabChecked .value = tab .value ;
1274+ return ;
1275+ }
12111276 try {
12121277 if (recipientIdString && recipientIdString .endsWith (' eth' )) {
12131278 assertValidEnsName (recipientIdString );
12141279 }
1215- recipientIdWarning . value = undefined ;
1280+ setWarning ( ' ' , index ); // clear warning
12161281 } catch (e ) {
1217- if (e instanceof Error ) {
1218- recipientIdWarning . value = e .message ;
1282+ if (e instanceof Error && e . message ) {
1283+ setWarning ( e .message , index ) ;
12191284 }
12201285 }
12211286 }
@@ -1233,6 +1298,7 @@ function useSendForm() {
12331298 chainId ,
12341299 checkConfusables ,
12351300 currentChain ,
1301+ handleTabClick ,
12361302 humanAmount ,
12371303 humanAmountBaseInputRef ,
12381304 humanToll ,
@@ -1246,6 +1312,7 @@ function useSendForm() {
12461312 isValidTokenAmount ,
12471313 isValidBatchSendAmount ,
12481314 NATIVE_TOKEN ,
1315+ numberOfErrorOrWarningBreaksNeeded ,
12491316 onFormSubmit ,
12501317 onBatchSendFormSubmit ,
12511318 paymentLinkParams ,
@@ -1259,6 +1326,7 @@ function useSendForm() {
12591326 sendingString ,
12601327 sendMax ,
12611328 setHumanAmountMax ,
1329+ setWarning ,
12621330 showAdvancedSendWarning ,
12631331 showAdvancedWarning ,
12641332 summaryAmount ,
0 commit comments