UI Polish: Signup Screen, Callout, IconButton (#519)
* UI Polish: Signup Screen, Callout, IconButton * Update CHANGELOG.md * FadeTransition * Fix carousel close allowing taps during animation * The de di do * rm 'it stays private'
This commit is contained in:
@@ -35,6 +35,7 @@ and this project adheres to Calendar Versioning (CalVer).
|
||||
### Removed
|
||||
|
||||
### Fixed
|
||||
- UI Polish: Signup Screen, Callout, IconButton [PR #519](https://github.com/marmot-protocol/whitenoise/pull/519)
|
||||
|
||||
### Security
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8 2L3 7L3.705 7.705L7.5 3.915V14H8.5V3.915L12.295 7.705L13 7L8 2Z" fill="black" style="fill:black;fill-opacity:1;"/>
|
||||
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9 2.25L3.375 7.875L4.16812 8.66812L8.4375 4.40437V15.75H9.5625V4.40437L13.8319 8.66812L14.625 7.875L9 2.25Z" fill="black" style="fill:black;fill-opacity:1;"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 232 B After Width: | Height: | Size: 274 B |
+6
-3
@@ -11,10 +11,13 @@
|
||||
"enterPrivateKey": "Privaten Schlüssel eingeben",
|
||||
"nsecPlaceholder": "nsec...",
|
||||
"setupProfile": "Profil einrichten",
|
||||
"chooseName": "Namen wählen",
|
||||
"createProfile": "Profil erstellen",
|
||||
"chooseName": "Name",
|
||||
"enterYourName": "Namen eingeben",
|
||||
"introduceYourself": "Stell dich vor",
|
||||
"writeSomethingAboutYourself": "Schreib etwas über dich",
|
||||
"introduceYourself": "Über dich",
|
||||
"writeSomethingAboutYourself": "Stell dich vor",
|
||||
"profilePrivacyTitle": "Du bestimmst, was du teilst",
|
||||
"profilePrivacyDescription": "Name, Foto und Bio sind im globalen Nostr-Netzwerk sichtbar. Verwende Angaben, mit denen du dich wohlfühlst.",
|
||||
"cancel": "Abbrechen",
|
||||
"profileReady": "Dein Profil ist bereit!",
|
||||
"startConversationHint": "Starte ein Gespräch, indem du Freunde hinzufügst oder dein Profil teilst.",
|
||||
|
||||
+16
-4
@@ -46,11 +46,15 @@
|
||||
"@nsecPlaceholder": {
|
||||
"description": "Placeholder text for nsec input"
|
||||
},
|
||||
"setupProfile": "Setup profile",
|
||||
"setupProfile": "Set up profile",
|
||||
"@setupProfile": {
|
||||
"description": "Title on signup screen"
|
||||
},
|
||||
"chooseName": "Choose a name",
|
||||
"createProfile": "Create profile",
|
||||
"@createProfile": {
|
||||
"description": "Submit button text on signup screen"
|
||||
},
|
||||
"chooseName": "Name",
|
||||
"@chooseName": {
|
||||
"description": "Label for name input field"
|
||||
},
|
||||
@@ -58,14 +62,22 @@
|
||||
"@enterYourName": {
|
||||
"description": "Placeholder for name input"
|
||||
},
|
||||
"introduceYourself": "Introduce yourself",
|
||||
"introduceYourself": "About",
|
||||
"@introduceYourself": {
|
||||
"description": "Label for bio input field"
|
||||
},
|
||||
"writeSomethingAboutYourself": "Write something about yourself",
|
||||
"writeSomethingAboutYourself": "Introduce yourself",
|
||||
"@writeSomethingAboutYourself": {
|
||||
"description": "Placeholder for bio input"
|
||||
},
|
||||
"profilePrivacyTitle": "You control what you share",
|
||||
"@profilePrivacyTitle": {
|
||||
"description": "Title of the privacy notice on signup screen"
|
||||
},
|
||||
"profilePrivacyDescription": "Name, photo, and bio are visible on the global Nostr network. Use what you're comfortable sharing.",
|
||||
"@profilePrivacyDescription": {
|
||||
"description": "Description of the privacy notice on signup screen"
|
||||
},
|
||||
"cancel": "Cancel",
|
||||
"@cancel": {
|
||||
"description": "Cancel button text"
|
||||
|
||||
+6
-3
@@ -11,10 +11,13 @@
|
||||
"enterPrivateKey": "Introduce tu llave privada",
|
||||
"nsecPlaceholder": "nsec...",
|
||||
"setupProfile": "Configurar perfil",
|
||||
"chooseName": "Elige un nombre",
|
||||
"createProfile": "Crear perfil",
|
||||
"chooseName": "Nombre",
|
||||
"enterYourName": "Introduce tu nombre",
|
||||
"introduceYourself": "Preséntate",
|
||||
"writeSomethingAboutYourself": "Escribe algo sobre ti",
|
||||
"introduceYourself": "Acerca de",
|
||||
"writeSomethingAboutYourself": "Preséntate",
|
||||
"profilePrivacyTitle": "Tú controlas lo que compartes",
|
||||
"profilePrivacyDescription": "El nombre, la foto y la biografía son visibles en la red global de Nostr. Usa lo que te resulte cómodo compartir.",
|
||||
"cancel": "Cancelar",
|
||||
"profileReady": "¡Tu perfil está listo!",
|
||||
"startConversationHint": "Inicia una conversación añadiendo amigos o compartiendo tu perfil.",
|
||||
|
||||
+6
-3
@@ -11,10 +11,13 @@
|
||||
"enterPrivateKey": "Entrez votre clé privée",
|
||||
"nsecPlaceholder": "nsec...",
|
||||
"setupProfile": "Configurer le profil",
|
||||
"chooseName": "Choisissez un nom",
|
||||
"createProfile": "Créer le profil",
|
||||
"chooseName": "Nom",
|
||||
"enterYourName": "Entrez votre nom",
|
||||
"introduceYourself": "Présentez-vous",
|
||||
"writeSomethingAboutYourself": "Écrivez quelque chose sur vous",
|
||||
"introduceYourself": "À propos",
|
||||
"writeSomethingAboutYourself": "Présentez-vous",
|
||||
"profilePrivacyTitle": "Vous contrôlez ce que vous partagez",
|
||||
"profilePrivacyDescription": "Le nom, la photo et la bio sont visibles sur le réseau mondial de Nostr. Utilisez ce que vous êtes à l'aise de partager.",
|
||||
"cancel": "Annuler",
|
||||
"profileReady": "Votre profil est prêt !",
|
||||
"startConversationHint": "Démarrez une conversation en ajoutant des amis ou en partageant votre profil.",
|
||||
|
||||
+6
-3
@@ -11,10 +11,13 @@
|
||||
"enterPrivateKey": "Inserisci la tua chiave privata",
|
||||
"nsecPlaceholder": "nsec...",
|
||||
"setupProfile": "Configura profilo",
|
||||
"chooseName": "Scegli un nome",
|
||||
"createProfile": "Crea profilo",
|
||||
"chooseName": "Nome",
|
||||
"enterYourName": "Inserisci il tuo nome",
|
||||
"introduceYourself": "Presentati",
|
||||
"writeSomethingAboutYourself": "Scrivi qualcosa su di te",
|
||||
"introduceYourself": "Informazioni",
|
||||
"writeSomethingAboutYourself": "Presentati",
|
||||
"profilePrivacyTitle": "Controlli tu cosa condividi",
|
||||
"profilePrivacyDescription": "Nome, foto e bio sono visibili sulla rete globale di Nostr. Usa ciò che ti senti a tuo agio nel condividere.",
|
||||
"cancel": "Annulla",
|
||||
"profileReady": "Il tuo profilo è pronto!",
|
||||
"startConversationHint": "Inizia una conversazione aggiungendo amici o condividendo il tuo profilo.",
|
||||
|
||||
+6
-3
@@ -11,10 +11,13 @@
|
||||
"enterPrivateKey": "Digite sua chave privada",
|
||||
"nsecPlaceholder": "nsec...",
|
||||
"setupProfile": "Configurar perfil",
|
||||
"chooseName": "Escolha um nome",
|
||||
"createProfile": "Criar perfil",
|
||||
"chooseName": "Nome",
|
||||
"enterYourName": "Digite seu nome",
|
||||
"introduceYourself": "Apresente-se",
|
||||
"writeSomethingAboutYourself": "Escreva algo sobre você",
|
||||
"introduceYourself": "Sobre",
|
||||
"writeSomethingAboutYourself": "Apresente-se",
|
||||
"profilePrivacyTitle": "Você controla o que compartilha",
|
||||
"profilePrivacyDescription": "Nome, foto e bio são visíveis na rede global do Nostr. Use o que você se sentir confortável em compartilhar.",
|
||||
"cancel": "Cancelar",
|
||||
"profileReady": "Seu perfil está pronto!",
|
||||
"startConversationHint": "Inicie uma conversa adicionando amigos ou compartilhando seu perfil.",
|
||||
|
||||
+6
-3
@@ -11,10 +11,13 @@
|
||||
"enterPrivateKey": "Введите ваш приватный ключ",
|
||||
"nsecPlaceholder": "nsec...",
|
||||
"setupProfile": "Настройка профиля",
|
||||
"chooseName": "Выберите имя",
|
||||
"createProfile": "Создать профиль",
|
||||
"chooseName": "Имя",
|
||||
"enterYourName": "Введите ваше имя",
|
||||
"introduceYourself": "Расскажите о себе",
|
||||
"writeSomethingAboutYourself": "Напишите что-нибудь о себе",
|
||||
"introduceYourself": "О себе",
|
||||
"writeSomethingAboutYourself": "Расскажите о себе",
|
||||
"profilePrivacyTitle": "Вы контролируете, чем делитесь",
|
||||
"profilePrivacyDescription": "Имя, фото и биография видны в глобальной сети Nostr. Используйте то, чем вам комфортно делиться.",
|
||||
"cancel": "Отмена",
|
||||
"profileReady": "Ваш профиль готов!",
|
||||
"startConversationHint": "Начните разговор, добавив друзей или поделившись своим профилем.",
|
||||
|
||||
+7
-4
@@ -10,11 +10,14 @@
|
||||
"loginTitle": "Özel anahtarınızı girin",
|
||||
"enterPrivateKey": "Özel anahtarınızı girin",
|
||||
"nsecPlaceholder": "nsec...",
|
||||
"setupProfile": "Profil ayarla",
|
||||
"chooseName": "Bir isim seçin",
|
||||
"setupProfile": "Profil oluştur",
|
||||
"createProfile": "Profil oluştur",
|
||||
"chooseName": "İsim",
|
||||
"enterYourName": "Adınızı girin",
|
||||
"introduceYourself": "Kendinizi tanıtın",
|
||||
"writeSomethingAboutYourself": "Kendiniz hakkında bir şeyler yazın",
|
||||
"introduceYourself": "Hakkında",
|
||||
"writeSomethingAboutYourself": "Kendinizi tanıtın",
|
||||
"profilePrivacyTitle": "Ne paylaştığınızı siz kontrol edersiniz",
|
||||
"profilePrivacyDescription": "İsim, fotoğraf ve biyografi küresel Nostr ağında görünür. Paylaşırken kendinizi rahat hissedeceğiniz bilgileri kullanın.",
|
||||
"cancel": "İptal",
|
||||
"profileReady": "Profiliniz hazır!",
|
||||
"startConversationHint": "Arkadaş ekleyerek veya profilinizi paylaşarak bir sohbet başlatın.",
|
||||
|
||||
@@ -171,13 +171,19 @@ abstract class AppLocalizations {
|
||||
/// Title on signup screen
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Setup profile'**
|
||||
/// **'Set up profile'**
|
||||
String get setupProfile;
|
||||
|
||||
/// Submit button text on signup screen
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Create profile'**
|
||||
String get createProfile;
|
||||
|
||||
/// Label for name input field
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Choose a name'**
|
||||
/// **'Name'**
|
||||
String get chooseName;
|
||||
|
||||
/// Placeholder for name input
|
||||
@@ -189,15 +195,27 @@ abstract class AppLocalizations {
|
||||
/// Label for bio input field
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Introduce yourself'**
|
||||
/// **'About'**
|
||||
String get introduceYourself;
|
||||
|
||||
/// Placeholder for bio input
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Write something about yourself'**
|
||||
/// **'Introduce yourself'**
|
||||
String get writeSomethingAboutYourself;
|
||||
|
||||
/// Title of the privacy notice on signup screen
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'You control what you share'**
|
||||
String get profilePrivacyTitle;
|
||||
|
||||
/// Description of the privacy notice on signup screen
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Name, photo, and bio are visible on the global Nostr network. Use what you\'re comfortable sharing.'**
|
||||
String get profilePrivacyDescription;
|
||||
|
||||
/// Cancel button text
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
||||
@@ -50,16 +50,26 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||
String get setupProfile => 'Profil einrichten';
|
||||
|
||||
@override
|
||||
String get chooseName => 'Namen wählen';
|
||||
String get createProfile => 'Profil erstellen';
|
||||
|
||||
@override
|
||||
String get chooseName => 'Name';
|
||||
|
||||
@override
|
||||
String get enterYourName => 'Namen eingeben';
|
||||
|
||||
@override
|
||||
String get introduceYourself => 'Stell dich vor';
|
||||
String get introduceYourself => 'Über dich';
|
||||
|
||||
@override
|
||||
String get writeSomethingAboutYourself => 'Schreib etwas über dich';
|
||||
String get writeSomethingAboutYourself => 'Stell dich vor';
|
||||
|
||||
@override
|
||||
String get profilePrivacyTitle => 'Du bestimmst, was du teilst';
|
||||
|
||||
@override
|
||||
String get profilePrivacyDescription =>
|
||||
'Name, Foto und Bio sind im globalen Nostr-Netzwerk sichtbar. Verwende Angaben, mit denen du dich wohlfühlst.';
|
||||
|
||||
@override
|
||||
String get cancel => 'Abbrechen';
|
||||
|
||||
@@ -47,19 +47,29 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
String get nsecPlaceholder => 'nsec...';
|
||||
|
||||
@override
|
||||
String get setupProfile => 'Setup profile';
|
||||
String get setupProfile => 'Set up profile';
|
||||
|
||||
@override
|
||||
String get chooseName => 'Choose a name';
|
||||
String get createProfile => 'Create profile';
|
||||
|
||||
@override
|
||||
String get chooseName => 'Name';
|
||||
|
||||
@override
|
||||
String get enterYourName => 'Enter your name';
|
||||
|
||||
@override
|
||||
String get introduceYourself => 'Introduce yourself';
|
||||
String get introduceYourself => 'About';
|
||||
|
||||
@override
|
||||
String get writeSomethingAboutYourself => 'Write something about yourself';
|
||||
String get writeSomethingAboutYourself => 'Introduce yourself';
|
||||
|
||||
@override
|
||||
String get profilePrivacyTitle => 'You control what you share';
|
||||
|
||||
@override
|
||||
String get profilePrivacyDescription =>
|
||||
'Name, photo, and bio are visible on the global Nostr network. Use what you\'re comfortable sharing.';
|
||||
|
||||
@override
|
||||
String get cancel => 'Cancel';
|
||||
|
||||
@@ -50,16 +50,26 @@ class AppLocalizationsEs extends AppLocalizations {
|
||||
String get setupProfile => 'Configurar perfil';
|
||||
|
||||
@override
|
||||
String get chooseName => 'Elige un nombre';
|
||||
String get createProfile => 'Crear perfil';
|
||||
|
||||
@override
|
||||
String get chooseName => 'Nombre';
|
||||
|
||||
@override
|
||||
String get enterYourName => 'Introduce tu nombre';
|
||||
|
||||
@override
|
||||
String get introduceYourself => 'Preséntate';
|
||||
String get introduceYourself => 'Acerca de';
|
||||
|
||||
@override
|
||||
String get writeSomethingAboutYourself => 'Escribe algo sobre ti';
|
||||
String get writeSomethingAboutYourself => 'Preséntate';
|
||||
|
||||
@override
|
||||
String get profilePrivacyTitle => 'Tú controlas lo que compartes';
|
||||
|
||||
@override
|
||||
String get profilePrivacyDescription =>
|
||||
'El nombre, la foto y la biografía son visibles en la red global de Nostr. Usa lo que te resulte cómodo compartir.';
|
||||
|
||||
@override
|
||||
String get cancel => 'Cancelar';
|
||||
|
||||
@@ -50,16 +50,26 @@ class AppLocalizationsFr extends AppLocalizations {
|
||||
String get setupProfile => 'Configurer le profil';
|
||||
|
||||
@override
|
||||
String get chooseName => 'Choisissez un nom';
|
||||
String get createProfile => 'Créer le profil';
|
||||
|
||||
@override
|
||||
String get chooseName => 'Nom';
|
||||
|
||||
@override
|
||||
String get enterYourName => 'Entrez votre nom';
|
||||
|
||||
@override
|
||||
String get introduceYourself => 'Présentez-vous';
|
||||
String get introduceYourself => 'À propos';
|
||||
|
||||
@override
|
||||
String get writeSomethingAboutYourself => 'Écrivez quelque chose sur vous';
|
||||
String get writeSomethingAboutYourself => 'Présentez-vous';
|
||||
|
||||
@override
|
||||
String get profilePrivacyTitle => 'Vous contrôlez ce que vous partagez';
|
||||
|
||||
@override
|
||||
String get profilePrivacyDescription =>
|
||||
'Le nom, la photo et la bio sont visibles sur le réseau mondial de Nostr. Utilisez ce que vous êtes à l\'aise de partager.';
|
||||
|
||||
@override
|
||||
String get cancel => 'Annuler';
|
||||
|
||||
@@ -50,16 +50,26 @@ class AppLocalizationsIt extends AppLocalizations {
|
||||
String get setupProfile => 'Configura profilo';
|
||||
|
||||
@override
|
||||
String get chooseName => 'Scegli un nome';
|
||||
String get createProfile => 'Crea profilo';
|
||||
|
||||
@override
|
||||
String get chooseName => 'Nome';
|
||||
|
||||
@override
|
||||
String get enterYourName => 'Inserisci il tuo nome';
|
||||
|
||||
@override
|
||||
String get introduceYourself => 'Presentati';
|
||||
String get introduceYourself => 'Informazioni';
|
||||
|
||||
@override
|
||||
String get writeSomethingAboutYourself => 'Scrivi qualcosa su di te';
|
||||
String get writeSomethingAboutYourself => 'Presentati';
|
||||
|
||||
@override
|
||||
String get profilePrivacyTitle => 'Controlli tu cosa condividi';
|
||||
|
||||
@override
|
||||
String get profilePrivacyDescription =>
|
||||
'Nome, foto e bio sono visibili sulla rete globale di Nostr. Usa ciò che ti senti a tuo agio nel condividere.';
|
||||
|
||||
@override
|
||||
String get cancel => 'Annulla';
|
||||
|
||||
@@ -50,16 +50,26 @@ class AppLocalizationsPt extends AppLocalizations {
|
||||
String get setupProfile => 'Configurar perfil';
|
||||
|
||||
@override
|
||||
String get chooseName => 'Escolha um nome';
|
||||
String get createProfile => 'Criar perfil';
|
||||
|
||||
@override
|
||||
String get chooseName => 'Nome';
|
||||
|
||||
@override
|
||||
String get enterYourName => 'Digite seu nome';
|
||||
|
||||
@override
|
||||
String get introduceYourself => 'Apresente-se';
|
||||
String get introduceYourself => 'Sobre';
|
||||
|
||||
@override
|
||||
String get writeSomethingAboutYourself => 'Escreva algo sobre você';
|
||||
String get writeSomethingAboutYourself => 'Apresente-se';
|
||||
|
||||
@override
|
||||
String get profilePrivacyTitle => 'Você controla o que compartilha';
|
||||
|
||||
@override
|
||||
String get profilePrivacyDescription =>
|
||||
'Nome, foto e bio são visíveis na rede global do Nostr. Use o que você se sentir confortável em compartilhar.';
|
||||
|
||||
@override
|
||||
String get cancel => 'Cancelar';
|
||||
|
||||
@@ -50,16 +50,26 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
String get setupProfile => 'Настройка профиля';
|
||||
|
||||
@override
|
||||
String get chooseName => 'Выберите имя';
|
||||
String get createProfile => 'Создать профиль';
|
||||
|
||||
@override
|
||||
String get chooseName => 'Имя';
|
||||
|
||||
@override
|
||||
String get enterYourName => 'Введите ваше имя';
|
||||
|
||||
@override
|
||||
String get introduceYourself => 'Расскажите о себе';
|
||||
String get introduceYourself => 'О себе';
|
||||
|
||||
@override
|
||||
String get writeSomethingAboutYourself => 'Напишите что-нибудь о себе';
|
||||
String get writeSomethingAboutYourself => 'Расскажите о себе';
|
||||
|
||||
@override
|
||||
String get profilePrivacyTitle => 'Вы контролируете, чем делитесь';
|
||||
|
||||
@override
|
||||
String get profilePrivacyDescription =>
|
||||
'Имя, фото и биография видны в глобальной сети Nostr. Используйте то, чем вам комфортно делиться.';
|
||||
|
||||
@override
|
||||
String get cancel => 'Отмена';
|
||||
|
||||
@@ -47,19 +47,29 @@ class AppLocalizationsTr extends AppLocalizations {
|
||||
String get nsecPlaceholder => 'nsec...';
|
||||
|
||||
@override
|
||||
String get setupProfile => 'Profil ayarla';
|
||||
String get setupProfile => 'Profil oluştur';
|
||||
|
||||
@override
|
||||
String get chooseName => 'Bir isim seçin';
|
||||
String get createProfile => 'Profil oluştur';
|
||||
|
||||
@override
|
||||
String get chooseName => 'İsim';
|
||||
|
||||
@override
|
||||
String get enterYourName => 'Adınızı girin';
|
||||
|
||||
@override
|
||||
String get introduceYourself => 'Kendinizi tanıtın';
|
||||
String get introduceYourself => 'Hakkında';
|
||||
|
||||
@override
|
||||
String get writeSomethingAboutYourself => 'Kendiniz hakkında bir şeyler yazın';
|
||||
String get writeSomethingAboutYourself => 'Kendinizi tanıtın';
|
||||
|
||||
@override
|
||||
String get profilePrivacyTitle => 'Ne paylaştığınızı siz kontrol edersiniz';
|
||||
|
||||
@override
|
||||
String get profilePrivacyDescription =>
|
||||
'İsim, fotoğraf ve biyografi küresel Nostr ağında görünür. Paylaşırken kendinizi rahat hissedeceğiniz bilgileri kullanın.';
|
||||
|
||||
@override
|
||||
String get cancel => 'İptal';
|
||||
|
||||
+148
-114
@@ -22,8 +22,9 @@ import 'package:whitenoise/routes.dart' show Routes;
|
||||
import 'package:whitenoise/theme.dart';
|
||||
import 'package:whitenoise/widgets/wn_avatar.dart' show WnAvatar, WnAvatarSize;
|
||||
import 'package:whitenoise/widgets/wn_button.dart';
|
||||
import 'package:whitenoise/widgets/wn_callout.dart';
|
||||
import 'package:whitenoise/widgets/wn_carousel_indicator.dart' show WnCarouselIndicator;
|
||||
import 'package:whitenoise/widgets/wn_icon.dart' show WnIcons;
|
||||
import 'package:whitenoise/widgets/wn_icon.dart' show WnIcon, WnIcons;
|
||||
import 'package:whitenoise/widgets/wn_input.dart' show WnInput;
|
||||
import 'package:whitenoise/widgets/wn_input_text_area.dart' show WnInputTextArea;
|
||||
import 'package:whitenoise/widgets/wn_onboarding_carousel.dart' show WnOnboardingCarousel;
|
||||
@@ -67,6 +68,7 @@ class SignupScreen extends HookConsumerWidget {
|
||||
onImageSelected: onImageSelected,
|
||||
);
|
||||
final noticeMessage = useState<String?>(null);
|
||||
final privacyNoticeExpanded = useState(false);
|
||||
final showCarousel = useState(false);
|
||||
final carouselIndex = useState(0);
|
||||
final carouselAccentColor = useState<Color>(context.colors.accent.cyan.contentSecondary);
|
||||
@@ -163,132 +165,165 @@ class SignupScreen extends HookConsumerWidget {
|
||||
body: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
if (!showCarousel.value)
|
||||
Positioned.fill(
|
||||
Positioned.fill(
|
||||
child: IgnorePointer(
|
||||
ignoring: showCarousel.value,
|
||||
child: GestureDetector(
|
||||
key: const Key('signup_background'),
|
||||
onTap: () => Routes.goBack(context),
|
||||
behavior: HitTestBehavior.translucent,
|
||||
),
|
||||
),
|
||||
),
|
||||
SafeArea(
|
||||
child: Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: _LearnMoreButton(
|
||||
key: const Key('learn_more_button'),
|
||||
onTap: openCarousel,
|
||||
visible: !showCarousel.value,
|
||||
child: FadeTransition(
|
||||
opacity: CurvedAnimation(
|
||||
parent: ModalRoute.of(context)?.animation ?? kAlwaysCompleteAnimation,
|
||||
curve: const Interval(0.5, 1.0),
|
||||
),
|
||||
child: Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: SizedBox(
|
||||
height: 148.h,
|
||||
child: Center(
|
||||
child: _LearnMoreButton(
|
||||
key: const Key('learn_more_button'),
|
||||
onTap: openCarousel,
|
||||
visible: !showCarousel.value,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(height: 70.h),
|
||||
SizedBox(
|
||||
height: (148.h - MediaQuery.of(context).viewInsets.bottom).clamp(0.0, 148.h),
|
||||
),
|
||||
Expanded(
|
||||
child: SlideTransition(
|
||||
position: slideAnimation,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
Flexible(
|
||||
child: WnSlate(
|
||||
header: WnSlateNavigationHeader(
|
||||
title: context.l10n.setupProfile,
|
||||
onNavigate: () => Routes.goBack(context),
|
||||
),
|
||||
systemNotice: noticeMessage.value != null
|
||||
? WnSystemNotice(
|
||||
key: ValueKey(noticeMessage.value),
|
||||
title: noticeMessage.value!,
|
||||
type: WnSystemNoticeType.error,
|
||||
onDismiss: dismissNotice,
|
||||
)
|
||||
: null,
|
||||
child: SingleChildScrollView(
|
||||
controller: scrollController,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
14.w,
|
||||
0,
|
||||
14.w,
|
||||
14.h,
|
||||
child: FadeTransition(
|
||||
opacity: ReverseAnimation(fadeAnimation),
|
||||
child: SlideTransition(
|
||||
position: slideAnimation,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
Flexible(
|
||||
child: WnSlate(
|
||||
header: WnSlateNavigationHeader(
|
||||
title: context.l10n.setupProfile,
|
||||
onNavigate: () => Routes.goBack(context),
|
||||
),
|
||||
systemNotice: noticeMessage.value != null
|
||||
? WnSystemNotice(
|
||||
key: ValueKey(noticeMessage.value),
|
||||
title: noticeMessage.value!,
|
||||
type: WnSystemNoticeType.error,
|
||||
onDismiss: dismissNotice,
|
||||
)
|
||||
: null,
|
||||
footer: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
left: 14.w,
|
||||
right: 14.w,
|
||||
bottom: 14.h,
|
||||
),
|
||||
child: Column(
|
||||
spacing: 16.h,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Center(
|
||||
child: ValueListenableBuilder(
|
||||
valueListenable: displayNameController,
|
||||
builder: (context, value, child) {
|
||||
return WnAvatar(
|
||||
pictureUrl: state.selectedImagePath,
|
||||
displayName: value.text,
|
||||
size: WnAvatarSize.large,
|
||||
onEditTap: state.isLoading ? null : pickImage,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
WnInput(
|
||||
label: context.l10n.chooseName,
|
||||
placeholder: context.l10n.enterYourName,
|
||||
controller: displayNameController,
|
||||
errorText: state.displayNameError,
|
||||
onChanged: (_) => clearErrors(),
|
||||
inlineActionIcon: WnIcons.closeSmall,
|
||||
inlineActionKey: const Key(
|
||||
'signup_display_name_clear_button',
|
||||
),
|
||||
inlineActionOnPressed: () {
|
||||
displayNameController.clear();
|
||||
clearErrors();
|
||||
},
|
||||
),
|
||||
WnInputTextArea(
|
||||
key: const Key('signup_bio_field'),
|
||||
label: context.l10n.introduceYourself,
|
||||
placeholder: context.l10n.writeSomethingAboutYourself,
|
||||
controller: bioController,
|
||||
focusNode: bioFocusNode,
|
||||
textInputAction: TextInputAction.done,
|
||||
),
|
||||
Column(
|
||||
spacing: 8.h,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
WnButton(
|
||||
text: context.l10n.cancel,
|
||||
type: WnButtonType.outline,
|
||||
onPressed: () => Routes.goBack(context),
|
||||
disabled: state.isLoading,
|
||||
),
|
||||
WnButton(
|
||||
text: context.l10n.signUp,
|
||||
onPressed: onSubmit,
|
||||
ValueListenableBuilder(
|
||||
valueListenable: displayNameController,
|
||||
builder: (context, value, child) {
|
||||
final hasName = value.text.trim().isNotEmpty;
|
||||
return WnButton(
|
||||
text: context.l10n.createProfile,
|
||||
onPressed: hasName ? onSubmit : null,
|
||||
loading: state.isLoading,
|
||||
disabled: state.isLoading,
|
||||
),
|
||||
],
|
||||
disabled: !hasName || state.isLoading,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
controller: scrollController,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
14.w,
|
||||
8.h,
|
||||
14.w,
|
||||
14.h,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Center(
|
||||
child: ValueListenableBuilder(
|
||||
valueListenable: displayNameController,
|
||||
builder: (context, value, child) {
|
||||
return WnAvatar(
|
||||
pictureUrl: state.selectedImagePath,
|
||||
displayName: value.text,
|
||||
size: WnAvatarSize.large,
|
||||
onEditTap: state.isLoading ? null : pickImage,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
Gap(16.h),
|
||||
WnCallout(
|
||||
key: const Key('signup_privacy_notice'),
|
||||
title: context.l10n.profilePrivacyTitle,
|
||||
description: privacyNoticeExpanded.value
|
||||
? context.l10n.profilePrivacyDescription
|
||||
: null,
|
||||
isExpanded: privacyNoticeExpanded.value,
|
||||
onToggle: () {
|
||||
privacyNoticeExpanded.value =
|
||||
!privacyNoticeExpanded.value;
|
||||
},
|
||||
),
|
||||
Gap(16.h),
|
||||
WnInput(
|
||||
label: context.l10n.chooseName,
|
||||
placeholder: context.l10n.enterYourName,
|
||||
controller: displayNameController,
|
||||
errorText: state.displayNameError,
|
||||
onChanged: (_) => clearErrors(),
|
||||
),
|
||||
Gap(16.h),
|
||||
WnInputTextArea(
|
||||
key: const Key('signup_bio_field'),
|
||||
label: context.l10n.introduceYourself,
|
||||
placeholder: context.l10n.writeSomethingAboutYourself,
|
||||
controller: bioController,
|
||||
focusNode: bioFocusNode,
|
||||
textInputAction: TextInputAction.done,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Gap(10.h),
|
||||
],
|
||||
SizedBox(
|
||||
height: MediaQuery.of(context).viewInsets.bottom.clamp(0.0, 16.h),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (showCarousel.value)
|
||||
Positioned.fill(
|
||||
Positioned.fill(
|
||||
child: IgnorePointer(
|
||||
ignoring: !showCarousel.value,
|
||||
child: FadeTransition(
|
||||
opacity: fadeAnimation,
|
||||
child: SafeArea(
|
||||
@@ -312,6 +347,7 @@ class SignupScreen extends HookConsumerWidget {
|
||||
),
|
||||
SizedBox(height: 287.h),
|
||||
WnSlate(
|
||||
tag: 'wn-slate-carousel',
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
vertical: 14.h,
|
||||
@@ -337,6 +373,7 @@ class SignupScreen extends HookConsumerWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -367,26 +404,23 @@ class _LearnMoreButton extends HookWidget {
|
||||
child: GestureDetector(
|
||||
onTap: onTap,
|
||||
behavior: HitTestBehavior.opaque,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 24.h),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.arrow_upward,
|
||||
key: const Key('learn_more_arrow'),
|
||||
size: 20.sp,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
WnIcon(
|
||||
WnIcons.arrowUp,
|
||||
key: const Key('learn_more_arrow'),
|
||||
size: 20.sp,
|
||||
color: colors.backgroundContentPrimary,
|
||||
),
|
||||
SizedBox(height: 4.h),
|
||||
Text(
|
||||
l10n.learnMore,
|
||||
style: typography.medium14.copyWith(
|
||||
color: colors.backgroundContentPrimary,
|
||||
),
|
||||
SizedBox(height: 4.h),
|
||||
Text(
|
||||
l10n.learnMore,
|
||||
style: typography.medium14.copyWith(
|
||||
color: colors.backgroundContentPrimary,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -19,12 +19,16 @@ class WnCallout extends StatelessWidget {
|
||||
this.description,
|
||||
this.type = CalloutType.neutral,
|
||||
this.onDismiss,
|
||||
this.onToggle,
|
||||
this.isExpanded = false,
|
||||
});
|
||||
|
||||
final String title;
|
||||
final String? description;
|
||||
final CalloutType type;
|
||||
final VoidCallback? onDismiss;
|
||||
final VoidCallback? onToggle;
|
||||
final bool isExpanded;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -33,6 +37,7 @@ class WnCallout extends StatelessWidget {
|
||||
final colorScheme = _getColorScheme(colors);
|
||||
|
||||
return Container(
|
||||
constraints: BoxConstraints(minHeight: 56.h),
|
||||
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 10.h),
|
||||
decoration: BoxDecoration(
|
||||
color: colorScheme.backgroundColor,
|
||||
@@ -72,6 +77,13 @@ class WnCallout extends StatelessWidget {
|
||||
icon: WnIcons.closeLarge,
|
||||
onPressed: onDismiss,
|
||||
),
|
||||
if (onToggle != null)
|
||||
WnIconButton(
|
||||
key: const Key('callout_toggle'),
|
||||
icon: isExpanded ? WnIcons.chevronUp : WnIcons.chevronDown,
|
||||
size: WnIconButtonSize.size36,
|
||||
onPressed: onToggle,
|
||||
),
|
||||
],
|
||||
),
|
||||
if (description != null) ...[
|
||||
@@ -92,7 +104,7 @@ class WnCallout extends StatelessWidget {
|
||||
switch (type) {
|
||||
case CalloutType.neutral:
|
||||
return _CalloutColorScheme(
|
||||
backgroundColor: colors.fillSecondary,
|
||||
backgroundColor: colors.backgroundSecondary,
|
||||
iconColor: colors.backgroundContentPrimary,
|
||||
titleColor: colors.backgroundContentPrimary,
|
||||
descriptionColor: colors.backgroundContentSecondary,
|
||||
|
||||
@@ -5,7 +5,7 @@ import 'package:whitenoise/widgets/wn_icon.dart';
|
||||
|
||||
enum WnIconButtonType { primary, outline, ghost }
|
||||
|
||||
enum WnIconButtonSize { size44, size56 }
|
||||
enum WnIconButtonSize { size36, size44, size56 }
|
||||
|
||||
class WnIconButton extends StatelessWidget {
|
||||
const WnIconButton({
|
||||
@@ -26,8 +26,16 @@ class WnIconButton extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colors = context.colors;
|
||||
final dimension = size == WnIconButtonSize.size56 ? 56.w : 44.w;
|
||||
final iconSize = size == WnIconButtonSize.size56 ? 24.w : 18.w;
|
||||
final dimension = switch (size) {
|
||||
WnIconButtonSize.size36 => 36.w,
|
||||
WnIconButtonSize.size44 => 44.w,
|
||||
WnIconButtonSize.size56 => 56.w,
|
||||
};
|
||||
final iconSize = switch (size) {
|
||||
WnIconButtonSize.size36 => 20.w,
|
||||
WnIconButtonSize.size44 => 18.w,
|
||||
WnIconButtonSize.size56 => 24.w,
|
||||
};
|
||||
final borderRadius = 8.r;
|
||||
|
||||
return SizedBox.square(
|
||||
|
||||
@@ -66,14 +66,14 @@ void main() {
|
||||
}
|
||||
|
||||
group('SignupScreen', () {
|
||||
testWidgets('displays Setup profile title', (tester) async {
|
||||
testWidgets('displays Set up profile title', (tester) async {
|
||||
await pumpSignupScreen(tester);
|
||||
expect(find.text('Setup profile'), findsOneWidget);
|
||||
expect(find.text('Set up profile'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('displays name input field', (tester) async {
|
||||
await pumpSignupScreen(tester);
|
||||
expect(find.text('Choose a name'), findsOneWidget);
|
||||
expect(find.text('Name'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('prefills display name field with generated value', (
|
||||
@@ -98,32 +98,50 @@ void main() {
|
||||
expect(nameField.controller?.text, 'Custom Name');
|
||||
});
|
||||
|
||||
testWidgets('clears display name when clear button is tapped', (tester) async {
|
||||
await pumpSignupScreen(tester);
|
||||
|
||||
final nameFieldBefore = tester.widget<TextField>(find.byType(TextField).first);
|
||||
expect(nameFieldBefore.controller?.text, isNotEmpty);
|
||||
|
||||
await tester.tap(find.byKey(const Key('signup_display_name_clear_button')));
|
||||
await tester.pump();
|
||||
|
||||
final nameFieldAfter = tester.widget<TextField>(find.byType(TextField).first);
|
||||
expect(nameFieldAfter.controller?.text, isEmpty);
|
||||
});
|
||||
|
||||
testWidgets('displays bio input field', (tester) async {
|
||||
await pumpSignupScreen(tester);
|
||||
expect(find.text('Introduce yourself'), findsOneWidget);
|
||||
expect(find.text('About'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('displays Cancel button', (tester) async {
|
||||
testWidgets('displays privacy notice in collapsed state', (tester) async {
|
||||
await pumpSignupScreen(tester);
|
||||
expect(find.text('Cancel'), findsOneWidget);
|
||||
expect(find.byKey(const Key('signup_privacy_notice')), findsOneWidget);
|
||||
expect(find.text('You control what you share'), findsOneWidget);
|
||||
expect(
|
||||
find.textContaining('Name, photo, and bio are visible'),
|
||||
findsNothing,
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('displays Sign Up button', (tester) async {
|
||||
testWidgets('expands privacy notice on toggle tap', (tester) async {
|
||||
await pumpSignupScreen(tester);
|
||||
expect(find.text('Sign Up'), findsOneWidget);
|
||||
await tester.tap(find.byKey(const Key('callout_toggle')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
find.textContaining('Name, photo, and bio are visible'),
|
||||
findsOneWidget,
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('collapses privacy notice on toggle tap', (tester) async {
|
||||
await pumpSignupScreen(tester);
|
||||
await tester.tap(find.byKey(const Key('callout_toggle')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
find.textContaining('Name, photo, and bio are visible'),
|
||||
findsOneWidget,
|
||||
);
|
||||
await tester.tap(find.byKey(const Key('callout_toggle')));
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
find.textContaining('Name, photo, and bio are visible'),
|
||||
findsNothing,
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('displays Create profile button', (tester) async {
|
||||
await pumpSignupScreen(tester);
|
||||
expect(find.text('Create profile'), findsOneWidget);
|
||||
});
|
||||
|
||||
group('navigation', () {
|
||||
@@ -134,13 +152,6 @@ void main() {
|
||||
expect(find.byType(HomeScreen), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('tapping Cancel returns to home screen', (tester) async {
|
||||
await pumpSignupScreen(tester);
|
||||
await tester.tap(find.text('Cancel'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byType(HomeScreen), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('tapping outside slate returns to home screen', (
|
||||
tester,
|
||||
) async {
|
||||
@@ -163,12 +174,30 @@ void main() {
|
||||
tester,
|
||||
) async {
|
||||
await pumpSignupScreen(tester);
|
||||
expect(find.byType(WnOnboardingCarousel), findsNothing);
|
||||
|
||||
final carousel = find.byType(WnOnboardingCarousel);
|
||||
expect(
|
||||
tester
|
||||
.widget<FadeTransition>(
|
||||
find.ancestor(of: carousel, matching: find.byType(FadeTransition)).first,
|
||||
)
|
||||
.opacity
|
||||
.value,
|
||||
0.0,
|
||||
);
|
||||
|
||||
await tester.tap(find.byKey(const Key('learn_more_button')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byType(WnOnboardingCarousel), findsOneWidget);
|
||||
expect(
|
||||
tester
|
||||
.widget<FadeTransition>(
|
||||
find.ancestor(of: carousel, matching: find.byType(FadeTransition)).first,
|
||||
)
|
||||
.opacity
|
||||
.value,
|
||||
1.0,
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('carousel shows Back to sign up button', (tester) async {
|
||||
@@ -185,13 +214,30 @@ void main() {
|
||||
await tester.tap(find.byKey(const Key('learn_more_button')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byType(WnOnboardingCarousel), findsOneWidget);
|
||||
final carousel = find.byType(WnOnboardingCarousel);
|
||||
expect(
|
||||
tester
|
||||
.widget<FadeTransition>(
|
||||
find.ancestor(of: carousel, matching: find.byType(FadeTransition)).first,
|
||||
)
|
||||
.opacity
|
||||
.value,
|
||||
1.0,
|
||||
);
|
||||
|
||||
await tester.tap(find.byKey(const Key('back_to_signup_button')));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.byType(WnOnboardingCarousel), findsNothing);
|
||||
expect(find.text('Setup profile'), findsOneWidget);
|
||||
expect(
|
||||
tester
|
||||
.widget<FadeTransition>(
|
||||
find.ancestor(of: carousel, matching: find.byType(FadeTransition)).first,
|
||||
)
|
||||
.opacity
|
||||
.value,
|
||||
0.0,
|
||||
);
|
||||
expect(find.text('Set up profile'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('tapping outside does not dismiss when carousel is visible', (
|
||||
@@ -245,7 +291,7 @@ void main() {
|
||||
testWidgets('redirects to chat list on success', (tester) async {
|
||||
await pumpSignupScreen(tester, overrides: overrides);
|
||||
await tester.enterText(find.byType(TextField).first, 'Test User');
|
||||
await tester.tap(find.text('Sign Up'));
|
||||
await tester.tap(find.text('Create profile'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byType(ChatListScreen), findsOneWidget);
|
||||
});
|
||||
@@ -254,7 +300,7 @@ void main() {
|
||||
mockAuth.errorToThrow = Exception('Network error');
|
||||
await pumpSignupScreen(tester, overrides: overrides);
|
||||
await tester.enterText(find.byType(TextField).first, 'Test User');
|
||||
await tester.tap(find.text('Sign Up'));
|
||||
await tester.tap(find.text('Create profile'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byType(ChatListScreen), findsNothing);
|
||||
});
|
||||
@@ -293,14 +339,14 @@ void main() {
|
||||
) async {
|
||||
await pumpSignupWithSmallScreen(tester);
|
||||
|
||||
expect(find.text('Choose a name'), findsOneWidget);
|
||||
expect(find.text('Sign Up'), findsOneWidget);
|
||||
expect(find.text('Name'), findsOneWidget);
|
||||
expect(find.text('Create profile'), findsOneWidget);
|
||||
|
||||
tester.view.viewInsets = const FakeViewPadding(bottom: 300);
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 400));
|
||||
|
||||
expect(find.text('Choose a name'), findsOneWidget);
|
||||
expect(find.text('Name'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('scrolls when bio field is focused and keyboard appears', (
|
||||
@@ -323,7 +369,7 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(controller.offset, greaterThan(initialOffset));
|
||||
expect(find.text('Choose a name'), findsOneWidget);
|
||||
expect(find.text('Name'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('name field remains visible when focused', (
|
||||
@@ -339,7 +385,7 @@ void main() {
|
||||
await tester.pump(const Duration(milliseconds: 400));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('Choose a name'), findsOneWidget);
|
||||
expect(find.text('Name'), findsOneWidget);
|
||||
|
||||
addTearDown(() => tester.view.resetViewInsets());
|
||||
});
|
||||
|
||||
@@ -79,7 +79,7 @@ void main() {
|
||||
await mountTestApp(tester);
|
||||
await tester.tap(find.text('Sign Up'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Choose a name'), findsOneWidget);
|
||||
expect(find.text('Name'), findsOneWidget);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user