feature: verification check mark

This commit is contained in:
otsmr 2026-02-21 01:01:25 +01:00
parent 09afd3dda0
commit f2b95386c6
17 changed files with 308 additions and 30 deletions

View file

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#57CC99" class="bi bi-patch-check" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M10.354 6.146a.5.5 0 0 1 0 .708l-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 1 1 .708-.708L7 8.793l2.646-2.647a.5.5 0 0 1 .708 0"/>
<path d="m10.273 2.513-.921-.944.715-.698.622.637.89-.011a2.89 2.89 0 0 1 2.924 2.924l-.01.89.636.622a2.89 2.89 0 0 1 0 4.134l-.637.622.011.89a2.89 2.89 0 0 1-2.924 2.924l-.89-.01-.622.636a2.89 2.89 0 0 1-4.134 0l-.622-.637-.89.011a2.89 2.89 0 0 1-2.924-2.924l.01-.89-.636-.622a2.89 2.89 0 0 1 0-4.134l.637-.622-.011-.89a2.89 2.89 0 0 1 2.924-2.924l.89.01.622-.636a2.89 2.89 0 0 1 4.134 0l-.715.698a1.89 1.89 0 0 0-2.704 0l-.92.944-1.32-.016a1.89 1.89 0 0 0-1.911 1.912l.016 1.318-.944.921a1.89 1.89 0 0 0 0 2.704l.944.92-.016 1.32a1.89 1.89 0 0 0 1.912 1.911l1.318-.016.921.944a1.89 1.89 0 0 0 2.704 0l.92-.944 1.32.016a1.89 1.89 0 0 0 1.911-1.912l-.016-1.318.944-.921a1.89 1.89 0 0 0 0-2.704l-.944-.92.016-1.32a1.89 1.89 0 0 0-1.912-1.911z"/>
</svg>

After

Width:  |  Height:  |  Size: 1 KiB

View file

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#ff0000" class="bi bi-patch-check" viewBox="0 0 16 16">
<path d="M7.002 11a1 1 0 1 1 2 0 1 1 0 0 1-2 0zM7.1 4.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0z"/>
<path d="m10.273 2.513-.921-.944.715-.698.622.637.89-.011a2.89 2.89 0 0 1 2.924 2.924l-.01.89.636.622a2.89 2.89 0 0 1 0 4.134l-.637.622.011.89a2.89 2.89 0 0 1-2.924 2.924l-.89-.01-.622.636a2.89 2.89 0 0 1-4.134 0l-.622-.637-.89.011a2.89 2.89 0 0 1-2.924-2.924l.01-.89-.636-.622a2.89 2.89 0 0 1 0-4.134l.637-.622-.011-.89a2.89 2.89 0 0 1 2.924-2.924l.89.01.622-.636a2.89 2.89 0 0 1 4.134 0l-.715.698a1.89 1.89 0 0 0-2.704 0l-.92.944-1.32-.016a1.89 1.89 0 0 0-1.911 1.912l.016 1.318-.944.921a1.89 1.89 0 0 0 0 2.704l.944.92-.016 1.32a1.89 1.89 0 0 0 1.912 1.911l1.318-.016.921.944a1.89 1.89 0 0 0 2.704 0l.92-.944 1.32.016a1.89 1.89 0 0 0 1.911-1.912l-.016-1.318.944-.921a1.89 1.89 0 0 0 0-2.704l-.944-.92.016-1.32a1.89 1.89 0 0 0-1.912-1.911z"/>
</svg>

After

Width:  |  Height:  |  Size: 995 B

View file

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#ffff00" class="bi bi-patch-check" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M10.354 6.146a.5.5 0 0 1 0 .708l-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 1 1 .708-.708L7 8.793l2.646-2.647a.5.5 0 0 1 .708 0"/>
<path d="m10.273 2.513-.921-.944.715-.698.622.637.89-.011a2.89 2.89 0 0 1 2.924 2.924l-.01.89.636.622a2.89 2.89 0 0 1 0 4.134l-.637.622.011.89a2.89 2.89 0 0 1-2.924 2.924l-.89-.01-.622.636a2.89 2.89 0 0 1-4.134 0l-.622-.637-.89.011a2.89 2.89 0 0 1-2.924-2.924l.01-.89-.636-.622a2.89 2.89 0 0 1 0-4.134l.637-.622-.011-.89a2.89 2.89 0 0 1 2.924-2.924l.89.01.622-.636a2.89 2.89 0 0 1 4.134 0l-.715.698a1.89 1.89 0 0 0-2.704 0l-.92.944-1.32-.016a1.89 1.89 0 0 0-1.911 1.912l.016 1.318-.944.921a1.89 1.89 0 0 0 0 2.704l.944.92-.016 1.32a1.89 1.89 0 0 0 1.912 1.911l1.318-.016.921.944a1.89 1.89 0 0 0 2.704 0l.92-.944 1.32.016a1.89 1.89 0 0 0 1.911-1.912l-.016-1.318.944-.921a1.89 1.89 0 0 0 0-2.704l-.944-.92.016-1.32a1.89 1.89 0 0 0-1.912-1.911z"/>
</svg>

After

Width:  |  Height:  |  Size: 1 KiB

View file

@ -39,6 +39,8 @@ class Routes {
static const String settingsStorageExport = '/settings/storage_data/export'; static const String settingsStorageExport = '/settings/storage_data/export';
static const String settingsHelp = '/settings/help'; static const String settingsHelp = '/settings/help';
static const String settingsHelpFaq = '/settings/help/faq'; static const String settingsHelpFaq = '/settings/help/faq';
static const String settingsHelpFaqVerifyBadge =
'/settings/help/faq/verifybadge';
static const String settingsHelpContactUs = '/settings/help/contact_us'; static const String settingsHelpContactUs = '/settings/help/contact_us';
static const String settingsHelpDiagnostics = '/settings/help/diagnostics'; static const String settingsHelpDiagnostics = '/settings/help/diagnostics';
static const String settingsHelpUserStudy = '/settings/help/user_study'; static const String settingsHelpUserStudy = '/settings/help/user_study';

View file

@ -943,7 +943,7 @@ abstract class AppLocalizations {
/// No description provided for @contactVerifyNumberTitle. /// No description provided for @contactVerifyNumberTitle.
/// ///
/// In en, this message translates to: /// In en, this message translates to:
/// **'Verify safety number'** /// **'Verify contact'**
String get contactVerifyNumberTitle; String get contactVerifyNumberTitle;
/// No description provided for @contactVerifyNumberTapToScan. /// No description provided for @contactVerifyNumberTapToScan.
@ -970,6 +970,12 @@ abstract class AppLocalizations {
/// **'To verify the end-to-end encryption with {username}, compare the numbers with their device. The person can also scan your code with their device.'** /// **'To verify the end-to-end encryption with {username}, compare the numbers with their device. The person can also scan your code with their device.'**
String contactVerifyNumberLongDesc(Object username); String contactVerifyNumberLongDesc(Object username);
/// No description provided for @contactViewMessage.
///
/// In en, this message translates to:
/// **'Message'**
String get contactViewMessage;
/// No description provided for @contactNickname. /// No description provided for @contactNickname.
/// ///
/// In en, this message translates to: /// In en, this message translates to:
@ -2991,6 +2997,42 @@ abstract class AppLocalizations {
/// In en, this message translates to: /// In en, this message translates to:
/// **'To see this message, you need to update twonly.'** /// **'To see this message, you need to update twonly.'**
String get updateTwonlyMessage; String get updateTwonlyMessage;
/// No description provided for @verificationBadgeNote.
///
/// In en, this message translates to:
/// **'You can verify your friends by scanning their public QR code. Click to learn more.'**
String get verificationBadgeNote;
/// No description provided for @verificationBadgeTitle.
///
/// In en, this message translates to:
/// **'Verification'**
String get verificationBadgeTitle;
/// No description provided for @verificationBadgeGeneralDesc.
///
/// In en, this message translates to:
/// **'The green checkmark gives you the certainty that you are messaging the right person.'**
String get verificationBadgeGeneralDesc;
/// No description provided for @verificationBadgeGreenDesc.
///
/// In en, this message translates to:
/// **'Contact that you have personally verified via QR code. This also verified their public key.'**
String get verificationBadgeGreenDesc;
/// No description provided for @verificationBadgeYellowDesc.
///
/// In en, this message translates to:
/// **'(Coming soon) Contact whose QR code was scanned by one of your personally verified contacts.'**
String get verificationBadgeYellowDesc;
/// No description provided for @verificationBadgeRedDesc.
///
/// In en, this message translates to:
/// **'Unknown contact whose identity has not yet been verified.'**
String get verificationBadgeRedDesc;
} }
class _AppLocalizationsDelegate class _AppLocalizationsDelegate

View file

@ -468,7 +468,7 @@ class AppLocalizationsDe extends AppLocalizations {
'Dein Konto wird gelöscht. Es gibt keine Möglichkeit, es wiederherzustellen.'; 'Dein Konto wird gelöscht. Es gibt keine Möglichkeit, es wiederherzustellen.';
@override @override
String get contactVerifyNumberTitle => 'Sicherheitsnummer verifizieren'; String get contactVerifyNumberTitle => 'Benutzer verifizieren';
@override @override
String get contactVerifyNumberTapToScan => 'Zum Scannen tippen'; String get contactVerifyNumberTapToScan => 'Zum Scannen tippen';
@ -484,6 +484,9 @@ class AppLocalizationsDe extends AppLocalizations {
return 'Um die Ende-zu-Ende-Verschlüsselung mit $username zu verifizieren, vergleiche die Zahlen mit ihrem Gerät. Die Person kann auch deinen Code mit ihrem Gerät scannen.'; return 'Um die Ende-zu-Ende-Verschlüsselung mit $username zu verifizieren, vergleiche die Zahlen mit ihrem Gerät. Die Person kann auch deinen Code mit ihrem Gerät scannen.';
} }
@override
String get contactViewMessage => 'Nachricht';
@override @override
String get contactNickname => 'Spitzname'; String get contactNickname => 'Spitzname';
@ -1669,4 +1672,27 @@ class AppLocalizationsDe extends AppLocalizations {
@override @override
String get updateTwonlyMessage => String get updateTwonlyMessage =>
'Um diese Nachricht zu sehen, musst du twonly aktualisieren.'; 'Um diese Nachricht zu sehen, musst du twonly aktualisieren.';
@override
String get verificationBadgeNote =>
'Du kannst deine Freunde verifizieren, indem du deren öffentlichen QR-Code scannst. Klicke, um mehr zu erfahren.';
@override
String get verificationBadgeTitle => 'Verifizierung';
@override
String get verificationBadgeGeneralDesc =>
'Der grüne Haken gibt dir die Sicherheit, dass du mit der richtigen Person schreibst.';
@override
String get verificationBadgeGreenDesc =>
'Kontakt, den du durch den QR-Code persönlich verifiziert hast. Dadurch wurde auch sein öffentlicher Schlüssel überprüft.';
@override
String get verificationBadgeYellowDesc =>
'(Coming soon) Kontakt, dessen QR-Code von einem deiner persönlich verifizierten Kontakte gescannt wurde.';
@override
String get verificationBadgeRedDesc =>
'Unbekannter Kontakt, dessen Identität bisher nicht verifiziert wurde.';
} }

View file

@ -463,7 +463,7 @@ class AppLocalizationsEn extends AppLocalizations {
'Your account will be deleted. There is no change to restore it.'; 'Your account will be deleted. There is no change to restore it.';
@override @override
String get contactVerifyNumberTitle => 'Verify safety number'; String get contactVerifyNumberTitle => 'Verify contact';
@override @override
String get contactVerifyNumberTapToScan => 'Tap to scan'; String get contactVerifyNumberTapToScan => 'Tap to scan';
@ -479,6 +479,9 @@ class AppLocalizationsEn extends AppLocalizations {
return 'To verify the end-to-end encryption with $username, compare the numbers with their device. The person can also scan your code with their device.'; return 'To verify the end-to-end encryption with $username, compare the numbers with their device. The person can also scan your code with their device.';
} }
@override
String get contactViewMessage => 'Message';
@override @override
String get contactNickname => 'Nickname'; String get contactNickname => 'Nickname';
@ -1657,4 +1660,27 @@ class AppLocalizationsEn extends AppLocalizations {
@override @override
String get updateTwonlyMessage => String get updateTwonlyMessage =>
'To see this message, you need to update twonly.'; 'To see this message, you need to update twonly.';
@override
String get verificationBadgeNote =>
'You can verify your friends by scanning their public QR code. Click to learn more.';
@override
String get verificationBadgeTitle => 'Verification';
@override
String get verificationBadgeGeneralDesc =>
'The green checkmark gives you the certainty that you are messaging the right person.';
@override
String get verificationBadgeGreenDesc =>
'Contact that you have personally verified via QR code. This also verified their public key.';
@override
String get verificationBadgeYellowDesc =>
'(Coming soon) Contact whose QR code was scanned by one of your personally verified contacts.';
@override
String get verificationBadgeRedDesc =>
'Unknown contact whose identity has not yet been verified.';
} }

View file

@ -463,7 +463,7 @@ class AppLocalizationsSv extends AppLocalizations {
'Your account will be deleted. There is no change to restore it.'; 'Your account will be deleted. There is no change to restore it.';
@override @override
String get contactVerifyNumberTitle => 'Verify safety number'; String get contactVerifyNumberTitle => 'Verify contact';
@override @override
String get contactVerifyNumberTapToScan => 'Tap to scan'; String get contactVerifyNumberTapToScan => 'Tap to scan';
@ -479,6 +479,9 @@ class AppLocalizationsSv extends AppLocalizations {
return 'To verify the end-to-end encryption with $username, compare the numbers with their device. The person can also scan your code with their device.'; return 'To verify the end-to-end encryption with $username, compare the numbers with their device. The person can also scan your code with their device.';
} }
@override
String get contactViewMessage => 'Message';
@override @override
String get contactNickname => 'Nickname'; String get contactNickname => 'Nickname';
@ -1657,4 +1660,27 @@ class AppLocalizationsSv extends AppLocalizations {
@override @override
String get updateTwonlyMessage => String get updateTwonlyMessage =>
'To see this message, you need to update twonly.'; 'To see this message, you need to update twonly.';
@override
String get verificationBadgeNote =>
'You can verify your friends by scanning their public QR code. Click to learn more.';
@override
String get verificationBadgeTitle => 'Verification';
@override
String get verificationBadgeGeneralDesc =>
'The green checkmark gives you the certainty that you are messaging the right person.';
@override
String get verificationBadgeGreenDesc =>
'Contact that you have personally verified via QR code. This also verified their public key.';
@override
String get verificationBadgeYellowDesc =>
'(Coming soon) Contact whose QR code was scanned by one of your personally verified contacts.';
@override
String get verificationBadgeRedDesc =>
'Unknown contact whose identity has not yet been verified.';
} }

@ -1 +1 @@
Subproject commit 69d295db737253e0c1b68aedc39bf757e8d642e6 Subproject commit 6147155ce50caa97864d56e42e49a6f54702785d

View file

@ -32,6 +32,7 @@ import 'package:twonly/src/views/settings/help/contact_us.view.dart';
import 'package:twonly/src/views/settings/help/credits.view.dart'; import 'package:twonly/src/views/settings/help/credits.view.dart';
import 'package:twonly/src/views/settings/help/diagnostics.view.dart'; import 'package:twonly/src/views/settings/help/diagnostics.view.dart';
import 'package:twonly/src/views/settings/help/faq.view.dart'; import 'package:twonly/src/views/settings/help/faq.view.dart';
import 'package:twonly/src/views/settings/help/faq/verifybadge.dart';
import 'package:twonly/src/views/settings/help/help.view.dart'; import 'package:twonly/src/views/settings/help/help.view.dart';
import 'package:twonly/src/views/settings/notification.view.dart'; import 'package:twonly/src/views/settings/notification.view.dart';
import 'package:twonly/src/views/settings/privacy.view.dart'; import 'package:twonly/src/views/settings/privacy.view.dart';
@ -227,6 +228,12 @@ final routerProvider = GoRouter(
GoRoute( GoRoute(
path: 'faq', path: 'faq',
builder: (context, state) => const FaqView(), builder: (context, state) => const FaqView(),
routes: [
GoRoute(
path: 'verifybadge',
builder: (context, state) => const VerificationBadeFaqView(),
),
],
), ),
GoRoute( GoRoute(
path: 'contact_us', path: 'contact_us',
@ -281,5 +288,10 @@ final routerProvider = GoRouter(
), ),
], ],
), ),
// Fallback instead of showing a Page Not Found error redirect to home
GoRoute(
path: '/:path(.*)',
redirect: (context, state) => '/',
),
], ],
); );

View file

@ -27,13 +27,9 @@ class BetterListTile extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListTile( return ListTile(
leading: Padding( leading: SizedBox(
padding: (padding == null) width: 50,
? const EdgeInsets.only( child: Center(
right: 10,
left: 19,
)
: padding!,
child: (leading != null) child: (leading != null)
? leading ? leading
: FaIcon( : FaIcon(
@ -42,6 +38,7 @@ class BetterListTile extends StatelessWidget {
color: color, color: color,
), ),
), ),
),
trailing: trailing, trailing: trailing,
title: Text( title: Text(
text, text,

View file

@ -0,0 +1,31 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
class SvgIcons {
static const String verifiedGreen = 'assets/icons/verified_badge_green.svg';
static const String verifiedYellow = 'assets/icons/verified_badge_yellow.svg';
static const String verifiedRed = 'assets/icons/verified_badge_red.svg';
}
class SvgIcon extends StatelessWidget {
const SvgIcon({
required this.assetPath,
super.key,
this.size = 24.0,
this.color,
});
final String assetPath;
final double? size;
final Color? color;
@override
Widget build(BuildContext context) {
return SvgPicture.asset(
assetPath,
width: size,
height: size,
colorFilter:
color != null ? ColorFilter.mode(color!, BlendMode.srcIn) : null,
);
}
}

View file

@ -1,17 +1,17 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:twonly/globals.dart'; import 'package:twonly/globals.dart';
import 'package:twonly/src/constants/routes.keys.dart'; import 'package:twonly/src/constants/routes.keys.dart';
import 'package:twonly/src/database/twonly.db.dart'; import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/views/components/svg_icon.dart';
class VerifiedShield extends StatefulWidget { class VerifiedShield extends StatefulWidget {
const VerifiedShield({ const VerifiedShield({
this.contact, this.contact,
this.group, this.group,
super.key, super.key,
this.size = 18, this.size = 15,
}); });
final Group? group; final Group? group;
final Contact? contact; final Contact? contact;
@ -64,13 +64,15 @@ class _VerifiedShieldState extends State<VerifiedShield> {
message: isVerified message: isVerified
? 'You verified this contact' ? 'You verified this contact'
: 'You have not verifies this contact.', : 'You have not verifies this contact.',
child: FaIcon( child: Padding(
isVerified ? FontAwesomeIcons.shieldHeart : Icons.gpp_maybe_rounded, padding: const EdgeInsetsGeometry.only(top: 2),
color: child: SvgIcon(
isVerified ? Theme.of(context).colorScheme.primary : Colors.red, assetPath:
isVerified ? SvgIcons.verifiedGreen : SvgIcons.verifiedRed,
size: widget.size, size: widget.size,
), ),
), ),
),
); );
} }
} }

View file

@ -14,6 +14,7 @@ import 'package:twonly/src/views/components/better_list_title.dart';
import 'package:twonly/src/views/components/flame.dart'; import 'package:twonly/src/views/components/flame.dart';
import 'package:twonly/src/views/components/max_flame_list_title.dart'; import 'package:twonly/src/views/components/max_flame_list_title.dart';
import 'package:twonly/src/views/components/select_chat_deletion_time.comp.dart'; import 'package:twonly/src/views/components/select_chat_deletion_time.comp.dart';
import 'package:twonly/src/views/components/svg_icon.dart';
import 'package:twonly/src/views/components/verified_shield.dart'; import 'package:twonly/src/views/components/verified_shield.dart';
import 'package:twonly/src/views/groups/group.view.dart'; import 'package:twonly/src/views/groups/group.view.dart';
@ -163,6 +164,21 @@ class _ContactViewState extends State<ContactView> {
if (getContactDisplayName(contact) != contact.username) if (getContactDisplayName(contact) != contact.username)
Center(child: Text('(${contact.username})')), Center(child: Text('(${contact.username})')),
const SizedBox(height: 50), const SizedBox(height: 50),
BetterListTile(
icon: FontAwesomeIcons.solidComments,
text: context.lang.contactViewMessage,
onTap: () async {
final group =
await twonlyDB.groupsDao.getDirectChat(contact.userId);
if (group != null && context.mounted) {
await context.push(
Routes.chatsMessages,
extra: group,
);
}
},
),
const Divider(),
BetterListTile( BetterListTile(
icon: FontAwesomeIcons.pencil, icon: FontAwesomeIcons.pencil,
text: context.lang.contactNickname, text: context.lang.contactNickname,
@ -176,7 +192,6 @@ class _ContactViewState extends State<ContactView> {
} }
}, },
), ),
const Divider(),
SelectChatDeletionTimeListTitle( SelectChatDeletionTimeListTitle(
groupId: getUUIDforDirectChat(widget.userId, gUser.userId), groupId: getUUIDforDirectChat(widget.userId, gUser.userId),
), ),
@ -185,7 +200,11 @@ class _ContactViewState extends State<ContactView> {
contactId: widget.userId, contactId: widget.userId,
), ),
BetterListTile( BetterListTile(
icon: FontAwesomeIcons.shieldHeart, leading: SvgIcon(
assetPath: SvgIcons.verifiedGreen,
size: 20,
color: IconTheme.of(context).color,
),
text: context.lang.contactVerifyNumberTitle, text: context.lang.contactVerifyNumberTitle,
onTap: () async { onTap: () async {
await context.push(Routes.settingsPublicProfile); await context.push(Routes.settingsPublicProfile);

View file

@ -45,9 +45,29 @@ class _PublicProfileViewState extends State<PublicProfileView> {
body: Column( body: Column(
children: [ children: [
Container(width: double.infinity), Container(width: double.infinity),
const SizedBox( const SizedBox(height: 10),
height: 30, GestureDetector(
onTap: () => context.push(Routes.settingsHelpFaqVerifyBadge),
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 30),
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12),
decoration: BoxDecoration(
color: context.color.surfaceContainerHighest,
borderRadius: BorderRadius.circular(12),
), ),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: Text(context.lang.verificationBadgeNote),
),
const SizedBox(width: 10),
const FaIcon(FontAwesomeIcons.angleRight),
],
),
),
),
const SizedBox(height: 20),
if (_qrCode != null && _userAvatar != null) if (_qrCode != null && _userAvatar != null)
Container( Container(
decoration: BoxDecoration( decoration: BoxDecoration(

View file

@ -0,0 +1,62 @@
import 'package:flutter/material.dart';
import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/views/components/svg_icon.dart';
class VerificationBadeFaqView extends StatefulWidget {
const VerificationBadeFaqView({super.key});
@override
State<VerificationBadeFaqView> createState() =>
_VerificationBadeFaqViewState();
}
class _VerificationBadeFaqViewState extends State<VerificationBadeFaqView> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(context.lang.verificationBadgeTitle),
),
body: ListView(
padding: const EdgeInsets.all(40),
children: [
Text(
context.lang.verificationBadgeGeneralDesc,
textAlign: TextAlign.center,
),
const SizedBox(height: 40),
_buildItem(
icon: const SvgIcon(assetPath: SvgIcons.verifiedGreen, size: 40),
description: context.lang.verificationBadgeGreenDesc,
),
_buildItem(
icon: const SvgIcon(assetPath: SvgIcons.verifiedYellow, size: 40),
description: context.lang.verificationBadgeYellowDesc,
),
_buildItem(
icon: const SvgIcon(assetPath: SvgIcons.verifiedRed, size: 40),
description: context.lang.verificationBadgeRedDesc,
),
],
),
);
}
Widget _buildItem({required Widget icon, required String description}) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 40),
child: Row(
children: [
icon,
const SizedBox(width: 20),
Expanded(
child: Text(
description,
style: const TextStyle(fontSize: 16, height: 1.4),
),
),
],
),
);
}
}

View file

@ -203,6 +203,7 @@ flutter:
assets: assets:
# Add assets from the images directory to the application. # Add assets from the images directory to the application.
- assets/images/ - assets/images/
- assets/icons/
- assets/animated_icons/ - assets/animated_icons/
- assets/animations/ - assets/animations/
- assets/passwords/ - assets/passwords/