diff --git a/lib/main.dart b/lib/main.dart index 68114c60..be6bf8ff 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -155,7 +155,7 @@ Future runMigrations() async { if (u.avatarSvg == null) { u.currentSetupPage = SetupPages.profile.name; } else { - u.currentSetupPage = SetupPages.userDiscovery.name; + u.currentSetupPage = SetupPages.shareYourFriends.name; } }); } diff --git a/lib/src/localization/generated/app_localizations.dart b/lib/src/localization/generated/app_localizations.dart index d36abcd2..dc422f1a 100644 --- a/lib/src/localization/generated/app_localizations.dart +++ b/lib/src/localization/generated/app_localizations.dart @@ -2399,7 +2399,7 @@ abstract class AppLocalizations { /// No description provided for @onboardingUserDiscoveryShareFriendsDesc. /// /// In en, this message translates to: - /// **'Share with your friends who you know and who you have verified. Friends can *only see mutual friends* from your friend list.'** + /// **'Share with your friends who you know and who you have verified. Friends can *only see mutual friends* from your friend list. You can change your mind at *any time* or *hide specific people*.'** String get onboardingUserDiscoveryShareFriendsDesc; /// No description provided for @onboardingUserDiscoveryContactsVerifiedBadge. @@ -2429,7 +2429,7 @@ abstract class AppLocalizations { /// No description provided for @userDiscoverySettingsManualApprovalDesc. /// /// In en, this message translates to: - /// **'Before sharing someone, you will be asked every time someone reaches the number of send images.'** + /// **'Before someone is shared, you\'ll be asked first.'** String get userDiscoverySettingsManualApprovalDesc; /// No description provided for @onboardingUserDiscoveryLetFriendsFindYou. @@ -2989,6 +2989,18 @@ abstract class AppLocalizations { /// In en, this message translates to: /// **'Share contact'** String get userDiscoveryManualApprovalShareContact; + + /// No description provided for @onboardingSetupCompleteTitle. + /// + /// In en, this message translates to: + /// **'You\'re all set, {username}!'** + String onboardingSetupCompleteTitle(Object username); + + /// No description provided for @onboardingSetupCompleteDesc. + /// + /// In en, this message translates to: + /// **'You can now share your moments with your friends securely without distractions like ads.'** + String get onboardingSetupCompleteDesc; } class _AppLocalizationsDelegate diff --git a/lib/src/localization/generated/app_localizations_de.dart b/lib/src/localization/generated/app_localizations_de.dart index 0c3f90b4..62244a11 100644 --- a/lib/src/localization/generated/app_localizations_de.dart +++ b/lib/src/localization/generated/app_localizations_de.dart @@ -1328,7 +1328,7 @@ class AppLocalizationsDe extends AppLocalizations { @override String get userDiscoverySettingsManualApprovalDesc => - 'Bevor du jemanden teilst, wirst du jedes Mal gefragt, sobald jemand die Anzahl der gesendeten Bilder erreicht hat.'; + 'Bevor jemand geteilt wird, wirst du zuerst gefragt.'; @override String get onboardingUserDiscoveryLetFriendsFindYou => @@ -1683,4 +1683,13 @@ class AppLocalizationsDe extends AppLocalizations { @override String get userDiscoveryManualApprovalShareContact => 'Kontakt teilen'; + + @override + String onboardingSetupCompleteTitle(Object username) { + return 'Du bist startklar, $username!'; + } + + @override + String get onboardingSetupCompleteDesc => + 'Du kannst jetzt deine Momente sicher mit deinen Freunden teilen, ohne Ablenkungen wie Werbung.'; } diff --git a/lib/src/localization/generated/app_localizations_en.dart b/lib/src/localization/generated/app_localizations_en.dart index eca519ff..136a2369 100644 --- a/lib/src/localization/generated/app_localizations_en.dart +++ b/lib/src/localization/generated/app_localizations_en.dart @@ -1300,7 +1300,7 @@ class AppLocalizationsEn extends AppLocalizations { @override String get onboardingUserDiscoveryShareFriendsDesc => - 'Share with your friends who you know and who you have verified. Friends can *only see mutual friends* from your friend list.'; + 'Share with your friends who you know and who you have verified. Friends can *only see mutual friends* from your friend list. You can change your mind at *any time* or *hide specific people*.'; @override String get onboardingUserDiscoveryContactsVerifiedBadge => @@ -1319,7 +1319,7 @@ class AppLocalizationsEn extends AppLocalizations { @override String get userDiscoverySettingsManualApprovalDesc => - 'Before sharing someone, you will be asked every time someone reaches the number of send images.'; + 'Before someone is shared, you\'ll be asked first.'; @override String get onboardingUserDiscoveryLetFriendsFindYou => @@ -1667,4 +1667,13 @@ class AppLocalizationsEn extends AppLocalizations { @override String get userDiscoveryManualApprovalShareContact => 'Share contact'; + + @override + String onboardingSetupCompleteTitle(Object username) { + return 'You\'re all set, $username!'; + } + + @override + String get onboardingSetupCompleteDesc => + 'You can now share your moments with your friends securely without distractions like ads.'; } diff --git a/lib/src/localization/translations b/lib/src/localization/translations index 492bef11..96fc996e 160000 --- a/lib/src/localization/translations +++ b/lib/src/localization/translations @@ -1 +1 @@ -Subproject commit 492bef11cf6bd472a71bd1c1b3007d731adea433 +Subproject commit 96fc996e06f96a7a26438bba0421cb26eb721427 diff --git a/lib/src/visual/views/camera/camera_preview_components/camera_preview.dart b/lib/src/visual/views/camera/camera_preview_components/camera_preview.dart index 823798fd..15f05ad3 100644 --- a/lib/src/visual/views/camera/camera_preview_components/camera_preview.dart +++ b/lib/src/visual/views/camera/camera_preview_components/camera_preview.dart @@ -48,10 +48,6 @@ class MainCameraPreview extends StatelessWidget { mainCameraController.cameraController!, child: Stack( children: [ - if (mainCameraController.customPaint != null) - Positioned.fill( - child: mainCameraController.customPaint!, - ), if (mainCameraController.facePaint != null) Positioned.fill( child: mainCameraController.facePaint!, @@ -64,8 +60,7 @@ class MainCameraPreview extends StatelessWidget { ), ), ), - if (mainCameraController.focusPointOffset != null && - !mainCameraController.isSharePreviewIsShown) + if (!mainCameraController.isSharePreviewIsShown) AspectRatio( aspectRatio: 9 / 16, child: ClipRect( @@ -84,22 +79,30 @@ class MainCameraPreview extends StatelessWidget { .width, child: Stack( children: [ - Positioned( - top: mainCameraController.focusPointOffset!.dy - 40, - left: - mainCameraController.focusPointOffset!.dx - 40, - child: Container( - height: 80, - width: 80, - clipBehavior: Clip.antiAliasWithSaveLayer, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: Colors.white.withAlpha(150), + if (mainCameraController.qrCodePain != null) + Positioned.fill( + child: mainCameraController.qrCodePain!, + ), + if (mainCameraController.focusPointOffset != null) + Positioned( + top: + mainCameraController.focusPointOffset!.dy - + 40, + left: + mainCameraController.focusPointOffset!.dx - + 40, + child: Container( + height: 80, + width: 80, + clipBehavior: Clip.antiAliasWithSaveLayer, + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: Colors.white.withAlpha(150), + ), ), ), ), - ), ], ), ), diff --git a/lib/src/visual/views/camera/camera_preview_components/main_camera_controller.dart b/lib/src/visual/views/camera/camera_preview_components/main_camera_controller.dart index 3fc516d8..d0d0672a 100644 --- a/lib/src/visual/views/camera/camera_preview_components/main_camera_controller.dart +++ b/lib/src/visual/views/camera/camera_preview_components/main_camera_controller.dart @@ -76,7 +76,7 @@ class MainCameraController { ); bool _isBusy = false; bool _isBusyFaces = false; - CustomPaint? customPaint; + CustomPaint? qrCodePain; CustomPaint? facePaint; Offset? focusPointOffset; @@ -183,7 +183,7 @@ class MainCameraController { ..cameraId = cameraId; facePaint = null; - customPaint = null; + qrCodePain = null; isSelectingFaceFilters = false; setFilter(FaceFilterType.none); zoomButtonKey = GlobalKey(); @@ -334,7 +334,7 @@ class MainCameraController { inputImage.metadata!.rotation, cameraController!.description.lensDirection, ); - customPaint = CustomPaint(painter: painter); + qrCodePain = CustomPaint(painter: painter); if (barcodes.isEmpty && timeSharedLinkWasSetWithQr != null) { if (timeSharedLinkWasSetWithQr!.isAfter( diff --git a/lib/src/visual/views/contact/contact.view.dart b/lib/src/visual/views/contact/contact.view.dart index 628e5540..9fe183ad 100644 --- a/lib/src/visual/views/contact/contact.view.dart +++ b/lib/src/visual/views/contact/contact.view.dart @@ -286,10 +286,17 @@ class _ContactViewState extends State { ..._transferredTrust.map( (tt) => ListTile( dense: true, - title: Text( - context.lang.contactVerifiedBy( - getContactDisplayName(tt.$1), - ), + title: Row( + children: [ + Text( + context.lang.contactVerifiedBy( + getContactDisplayName(tt.$1), + ), + ), + VerificationBadgeComp( + contact: tt.$1, + ), + ], ), trailing: Text( DateFormat.yMd( diff --git a/lib/src/visual/views/onboarding/setup.view.dart b/lib/src/visual/views/onboarding/setup.view.dart index 47306df0..048f8b23 100644 --- a/lib/src/visual/views/onboarding/setup.view.dart +++ b/lib/src/visual/views/onboarding/setup.view.dart @@ -4,18 +4,21 @@ import 'package:flutter/material.dart'; import 'package:twonly/locator.dart'; import 'package:twonly/src/services/user.service.dart'; import 'package:twonly/src/utils/misc.dart'; -import 'package:twonly/src/visual/views/onboarding/setup/add_new_contacts_setup.view.dart'; -import 'package:twonly/src/visual/views/onboarding/setup/backup_setup.view.dart'; -import 'package:twonly/src/visual/views/onboarding/setup/profile_setup.view.dart'; -import 'package:twonly/src/visual/views/onboarding/setup/user_discovery_setup.view.dart'; -import 'package:twonly/src/visual/views/onboarding/setup/verification_badge_setup.view.dart'; +import 'package:twonly/src/visual/views/onboarding/setup/add_new_contacts.setup.dart'; +import 'package:twonly/src/visual/views/onboarding/setup/backup.setup.dart'; +import 'package:twonly/src/visual/views/onboarding/setup/let_your_friends_find_you.setup.dart'; +import 'package:twonly/src/visual/views/onboarding/setup/profile.setup.dart'; +import 'package:twonly/src/visual/views/onboarding/setup/share_your_friends.setup.dart'; +import 'package:twonly/src/visual/views/onboarding/setup/verification_badge.setup.dart'; +import 'package:twonly/src/visual/views/settings/privacy/user_discovery/components/user_discovery_setup.comp.dart'; enum SetupPages { profile, backup, addNewContact, verificationBadge, - userDiscovery, + shareYourFriends, + letYourFriendsFindYou, } extension SetupPagesExtension on SetupPages { @@ -28,7 +31,7 @@ extension SetupPagesExtension on SetupPages { int get pageNumber => index + 1; int get totalPages => SetupPages.values.length; - int get progressPercentage => (pageNumber / totalPages * 100).round(); + int get progressPercentage => ((pageNumber - 1) / totalPages * 100).round(); String get progressText => '$pageNumber / $totalPages'; bool get isLast => index == SetupPages.values.length - 1; @@ -53,10 +56,13 @@ class SetupView extends StatefulWidget { class _SetupViewState extends State { StreamSubscription? _userUpdateStream; + late UserDiscoverySetupState state; @override void initState() { super.initState(); + state = UserDiscoverySetupState(setState: setState); + if (widget.onUpdate != null) { _userUpdateStream = userService.onUserUpdated.listen((u) { if (userService.currentUser.currentSetupPage == null) { @@ -115,7 +121,7 @@ class _SetupViewState extends State { key: ValueKey(currentPage.name), padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 30), children: [ - _buildPage(currentPage), + _buildPage(currentPage, state), if (!currentPage.isLast) SizedBox( height: 50, @@ -145,7 +151,7 @@ class _SetupViewState extends State { ); } - Widget _buildPage(SetupPages page) { + Widget _buildPage(SetupPages page, UserDiscoverySetupState state) { switch (page) { case SetupPages.profile: return const ProfileSetupPage(); @@ -155,8 +161,10 @@ class _SetupViewState extends State { return const AddNewContactsPage(); case SetupPages.verificationBadge: return const VerificationBadgeSetupPage(); - case SetupPages.userDiscovery: - return const UserDiscoverySetupPage(); + case SetupPages.shareYourFriends: + return ShareYourFriendsSetupPage(state: state); + case SetupPages.letYourFriendsFindYou: + return LetYourFriendsFindYou(state: state); } } } diff --git a/lib/src/visual/views/onboarding/setup/add_new_contacts_setup.view.dart b/lib/src/visual/views/onboarding/setup/add_new_contacts.setup.dart similarity index 100% rename from lib/src/visual/views/onboarding/setup/add_new_contacts_setup.view.dart rename to lib/src/visual/views/onboarding/setup/add_new_contacts.setup.dart diff --git a/lib/src/visual/views/onboarding/setup/backup_setup.view.dart b/lib/src/visual/views/onboarding/setup/backup.setup.dart similarity index 100% rename from lib/src/visual/views/onboarding/setup/backup_setup.view.dart rename to lib/src/visual/views/onboarding/setup/backup.setup.dart diff --git a/lib/src/visual/views/onboarding/setup/components/finish_setup.comp.dart b/lib/src/visual/views/onboarding/setup/components/finish_setup.comp.dart index a57a00d8..c091586d 100644 --- a/lib/src/visual/views/onboarding/setup/components/finish_setup.comp.dart +++ b/lib/src/visual/views/onboarding/setup/components/finish_setup.comp.dart @@ -15,7 +15,9 @@ class _FinishSetupCompState extends State { await context.navPush( SetupView( onUpdate: () { - Navigator.pop(context); + if (mounted) { + Navigator.pop(context); + } }, ), ); diff --git a/lib/src/visual/views/onboarding/setup/let_your_friends_find_you.setup.dart b/lib/src/visual/views/onboarding/setup/let_your_friends_find_you.setup.dart new file mode 100644 index 00000000..3f7275ef --- /dev/null +++ b/lib/src/visual/views/onboarding/setup/let_your_friends_find_you.setup.dart @@ -0,0 +1,88 @@ +import 'package:flutter/material.dart'; +import 'package:lottie/lottie.dart'; +import 'package:twonly/locator.dart'; +import 'package:twonly/src/services/user.service.dart'; +import 'package:twonly/src/utils/misc.dart'; +import 'package:twonly/src/visual/views/onboarding/setup.view.dart'; +import 'package:twonly/src/visual/views/onboarding/setup/components/next_button.comp.dart'; +import 'package:twonly/src/visual/views/settings/privacy/user_discovery/components/user_discovery_setup.comp.dart'; + +class LetYourFriendsFindYou extends StatefulWidget { + const LetYourFriendsFindYou({required this.state, super.key}); + + final UserDiscoverySetupState state; + + @override + State createState() => _LetYourFriendsFindYouState(); +} + +class _LetYourFriendsFindYouState extends State { + @override + void initState() { + super.initState(); + + WidgetsBinding.instance.addPostFrameCallback((_) { + if (userService.currentUser.isUserDiscoveryEnabled && + userService.currentUser.userDiscoverySharePromotion) { + // feature is already configured... + UserService.update((user) { + user.currentSetupPage = SetupPages.letYourFriendsFindYou.next()?.name; + }); + } + }); + } + + @override + Widget build(BuildContext context) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + if (widget.state.isUserDiscoveryEnabled) + UserDiscoverySetupComp( + state: widget.state, + showOnlySpecificPage: UserDiscoveryPages.letYourFriendsFindYou, + ) + else + Container( + padding: const EdgeInsets.all(32), + child: Column( + children: [ + Lottie.asset( + 'assets/animations/takephoto.lottie', + repeat: true, + height: 150, + ), + const SizedBox(height: 60), + Text( + context.lang.onboardingSetupCompleteTitle( + userService.currentUser.username, + ), + style: const TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + ), + textAlign: TextAlign.center, + ), + const SizedBox(height: 12), + Text( + context.lang.onboardingSetupCompleteDesc, + style: const TextStyle( + fontSize: 16, + ), + textAlign: TextAlign.center, + ), + ], + ), + ), + const SizedBox(height: 50), + NextButtonComp( + onPressed: () async { + return !(await widget.state.initializeOrUpdate()); + }, + ), + ], + ), + ); + } +} diff --git a/lib/src/visual/views/onboarding/setup/profile_setup.view.dart b/lib/src/visual/views/onboarding/setup/profile.setup.dart similarity index 100% rename from lib/src/visual/views/onboarding/setup/profile_setup.view.dart rename to lib/src/visual/views/onboarding/setup/profile.setup.dart diff --git a/lib/src/visual/views/onboarding/setup/user_discovery_setup.view.dart b/lib/src/visual/views/onboarding/setup/share_your_friends.setup.dart similarity index 54% rename from lib/src/visual/views/onboarding/setup/user_discovery_setup.view.dart rename to lib/src/visual/views/onboarding/setup/share_your_friends.setup.dart index 5cf9423e..c2b6220e 100644 --- a/lib/src/visual/views/onboarding/setup/user_discovery_setup.view.dart +++ b/lib/src/visual/views/onboarding/setup/share_your_friends.setup.dart @@ -1,30 +1,30 @@ import 'package:flutter/material.dart'; import 'package:twonly/locator.dart'; import 'package:twonly/src/services/user.service.dart'; -import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/visual/views/onboarding/setup.view.dart'; import 'package:twonly/src/visual/views/onboarding/setup/components/next_button.comp.dart'; import 'package:twonly/src/visual/views/settings/privacy/user_discovery/components/user_discovery_setup.comp.dart'; -class UserDiscoverySetupPage extends StatefulWidget { - const UserDiscoverySetupPage({super.key}); +class ShareYourFriendsSetupPage extends StatefulWidget { + const ShareYourFriendsSetupPage({required this.state, super.key}); + + final UserDiscoverySetupState state; @override - State createState() => _UserDiscoverySetupPageState(); + State createState() => + _ShareYourFriendsSetupPageState(); } -class _UserDiscoverySetupPageState extends State { - late UserDiscoverySetupState state; - +class _ShareYourFriendsSetupPageState extends State { @override void initState() { super.initState(); - state = UserDiscoverySetupState(setState: setState); + WidgetsBinding.instance.addPostFrameCallback((_) { if (userService.currentUser.isUserDiscoveryEnabled) { // feature is already configured... UserService.update((user) { - user.currentSetupPage = SetupPages.userDiscovery.next()?.name; + user.currentSetupPage = SetupPages.shareYourFriends.next()?.name; }); } }); @@ -36,17 +36,15 @@ class _UserDiscoverySetupPageState extends State { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Text( - context.lang.onboardingUserDiscoveryShareFriends, - style: Theme.of(context).textTheme.headlineSmall, + UserDiscoverySetupComp( + state: widget.state, + showOnlySpecificPage: UserDiscoveryPages.shareYourFriends, ), - const SizedBox(height: 32), - UserDiscoverySetupComp(state: state), const SizedBox(height: 60), - NextButtonComp( - onPressed: () async { - return !(await state.initializeOrUpdate()); - }, + const NextButtonComp( + // onPressed: () async { + // return !(await widget.state.initializeOrUpdate()); + // }, ), ], ), diff --git a/lib/src/visual/views/onboarding/setup/verification_badge_setup.view.dart b/lib/src/visual/views/onboarding/setup/verification_badge.setup.dart similarity index 100% rename from lib/src/visual/views/onboarding/setup/verification_badge_setup.view.dart rename to lib/src/visual/views/onboarding/setup/verification_badge.setup.dart diff --git a/lib/src/visual/views/settings/developer/developer.view.dart b/lib/src/visual/views/settings/developer/developer.view.dart index 81fa8b15..8fd830e8 100644 --- a/lib/src/visual/views/settings/developer/developer.view.dart +++ b/lib/src/visual/views/settings/developer/developer.view.dart @@ -14,6 +14,7 @@ import 'package:twonly/src/services/user.service.dart'; import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/storage.dart'; import 'package:twonly/src/visual/components/alert.dialog.dart'; +import 'package:twonly/src/visual/views/onboarding/setup.view.dart'; import 'package:twonly/src/visual/views/settings/developer/user_discovery_developer.view.dart'; class DeveloperSettingsView extends StatefulWidget { @@ -131,6 +132,16 @@ class _DeveloperSettingsViewState extends State { onTap: () => context.push(Routes.settingsDeveloperAutomatedTesting), ), + ListTile( + title: const Text('Reopen Setup'), + onTap: () async { + await UserService.update((u) { + u + ..currentSetupPage = SetupPages.profile.name + ..isUserDiscoveryEnabled = false; + }); + }, + ), ], ); }, diff --git a/lib/src/visual/views/settings/privacy/user_discovery/components/user_discovery_setup.comp.dart b/lib/src/visual/views/settings/privacy/user_discovery/components/user_discovery_setup.comp.dart index 5484031c..ddc74eb1 100644 --- a/lib/src/visual/views/settings/privacy/user_discovery/components/user_discovery_setup.comp.dart +++ b/lib/src/visual/views/settings/privacy/user_discovery/components/user_discovery_setup.comp.dart @@ -11,15 +11,16 @@ import 'package:twonly/src/visual/views/onboarding/setup/components/setup_switch const exampleUsers = [ 'james', - 'john', - 'robert', - 'michael', - 'william', - 'david', 'mary', + 'john', 'patricia', + 'robert', 'jennifer', + 'michael', 'linda', + 'william', + 'lena', + 'david', ]; class UserDiscoverySetupState { @@ -27,7 +28,6 @@ class UserDiscoverySetupState { required this.setState, this.isUserDiscoveryEnabled = true, this.sharePromotion = true, - this.isShareAllContacts = false, this.isManualApprovalEnabled = false, this.threshold = 2, this.requiredSendImages = 4, @@ -39,7 +39,6 @@ class UserDiscoverySetupState { int threshold; bool sharePromotion; - bool isShareAllContacts; bool isManualApprovalEnabled; int requiredSendImages; @@ -53,11 +52,6 @@ class UserDiscoverySetupState { } Future initializeOrUpdate() async { - if (isShareAllContacts) { - requiredSendImages = 0; - isManualApprovalEnabled = false; - } - if (isUserDiscoveryEnabled) { await UserDiscoveryService.initializeOrUpdate( threshold: threshold, @@ -76,13 +70,17 @@ class UserDiscoverySetupState { } } +enum UserDiscoveryPages { all, shareYourFriends, letYourFriendsFindYou } + class UserDiscoverySetupComp extends StatelessWidget { const UserDiscoverySetupComp({ required this.state, + this.showOnlySpecificPage = UserDiscoveryPages.all, super.key, }); final UserDiscoverySetupState state; + final UserDiscoveryPages showOnlySpecificPage; @override Widget build(BuildContext context) { @@ -90,330 +88,65 @@ class UserDiscoverySetupComp extends StatelessWidget { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - RichText( - text: TextSpan( - children: formattedText( - context, - context.lang.userDiscoveryDisabledIntro, - ), + if (showOnlySpecificPage == UserDiscoveryPages.all || + showOnlySpecificPage == UserDiscoveryPages.shareYourFriends) ...[ + Text( + context.lang.onboardingUserDiscoveryShareFriends, + style: Theme.of(context).textTheme.headlineSmall, ), - textAlign: TextAlign.center, - ), + const SizedBox(height: 32), - const SizedBox(height: 80), - - Text( - context.lang.onboardingUserDiscoveryIncreaseTrust, - style: const TextStyle( - fontSize: 17, - fontWeight: FontWeight.bold, - ), - textAlign: TextAlign.center, - ), - - const SizedBox(height: 8), - - RichText( - text: TextSpan( - children: formattedText( - context, - context.lang.onboardingUserDiscoveryShareFriendsDesc, - ), - ), - textAlign: TextAlign.center, - ), - - const SizedBox(height: 24), - - SetupSwitchCard( - value: state.isUserDiscoveryEnabled, - onChanged: (val) => state.update(() { - state.isUserDiscoveryEnabled = val; - if (!val) { - state.sharePromotion = false; - } - }), - title: context.lang.onboardingUserDiscoveryShareFriends, - expandedChild: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Text( - context.lang.onboardingUserDiscoveryContactsVerifiedBadge, - style: TextStyle( - color: context.color.onSurfaceVariant, - fontSize: 12, - ), - textAlign: TextAlign.center, + RichText( + text: TextSpan( + children: formattedText( + context, + context.lang.onboardingUserDiscoveryShareFriendsDesc, ), - const SizedBox(height: 16), - Center( - child: Container( - width: 100, - height: 40, - decoration: BoxDecoration( - border: Border.all(color: Colors.grey, width: 0.5), - borderRadius: BorderRadius.circular(12), - ), - child: const Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - AvatarIcon(fontSize: 12), - SizedBox(width: 5), - Text( - 'jane', - style: TextStyle( - fontWeight: FontWeight.bold, - ), - ), - SizedBox(width: 5), - VerificationBadgeComp( - isVerifiedByTransferredTrust: true, - size: 14, - clickable: false, - ), - ], - ), - ), - ), - const SizedBox(height: 24), - Text( - context.lang.onboardingUserDiscoveryWhoIsRequesting, - style: TextStyle( - color: context.color.onSurfaceVariant, - fontSize: 12, - ), - textAlign: TextAlign.center, - ), - const SizedBox(height: 16), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 24), - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 6, - vertical: 3, - ), - decoration: BoxDecoration( - border: Border.all(color: Colors.grey, width: 0.5), - borderRadius: BorderRadius.circular(12), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const AvatarIcon(fontSize: 14), - const SizedBox(width: 5), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Text( - 'jane', - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 13, - ), - ), - RichText( - text: TextSpan( - children: buildFriendsListTextString( - context, - [ - 'mary', - 'james', - ], - ), - style: const TextStyle(fontSize: 10), - ), - ), - ], - ), - ), - const MockContactRequestActionsComp(), - ], - ), - ), - ), - const SizedBox(height: 16), - ], - ), - ), - - const SizedBox(height: 80), - - Text( - context.lang.userDiscoveryDisabledYouHaveControl, - style: const TextStyle( - fontSize: 17, - fontWeight: FontWeight.bold, - ), - textAlign: TextAlign.center, - ), - const SizedBox(height: 8), - - RichText( - text: TextSpan( - children: formattedText( - context, - context.lang.userDiscoveryDisabledDecide, ), + textAlign: TextAlign.center, ), - textAlign: TextAlign.center, - ), - const SizedBox(height: 24), + const SizedBox(height: 32), - if (state.isUserDiscoveryEnabled) - Container( - decoration: BoxDecoration( - color: context.color.surfaceContainerLow, - borderRadius: BorderRadius.circular(12), - ), - child: Column( - mainAxisSize: MainAxisSize.min, + SetupSwitchCard( + value: state.isUserDiscoveryEnabled, + onChanged: (val) => state.update(() { + state.isUserDiscoveryEnabled = val; + if (!val) { + state.sharePromotion = false; + } + }), + title: context.lang.onboardingUserDiscoveryShareFriends, + expandedChild: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ SwitchListTile( - value: state.isShareAllContacts, - onChanged: (val) => state.update(() { - state.isShareAllContacts = val; - }), + value: state.isManualApprovalEnabled, + onChanged: (val) => state.update( + () => state.isManualApprovalEnabled = val, + ), title: Text( - context.lang.userDiscoverySettingsEnableAllContacts, + context.lang.userDiscoverySettingsManualApproval, style: const TextStyle(fontSize: 13), ), + subtitle: Text( + context.lang.userDiscoverySettingsManualApprovalDesc, + style: const TextStyle(fontSize: 10), + ), tileColor: context.color.surfaceContainerLow, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), - contentPadding: const EdgeInsets.symmetric(horizontal: 16), - ), - if (!state.isShareAllContacts) - ListTile( - title: Text( - context.lang.userDiscoverySettingsMinImagesTitle, - style: const TextStyle(fontSize: 13), - ), - trailing: DropdownButtonHideUnderline( - child: DropdownButton( - value: state.requiredSendImages, - items: List.generate( - 9, - (index) { - final value = index + 2; - return DropdownMenuItem( - value: value, - child: Text('$value'), - ); - }, - ), - onChanged: (newValue) { - if (newValue != null) { - state.update( - () => state.requiredSendImages = newValue, - ); - } - }, - ), - ), + contentPadding: const EdgeInsets.symmetric( + horizontal: 16, ), - if (!state.isShareAllContacts) - SwitchListTile( - value: state.isManualApprovalEnabled, - onChanged: (val) => state.update( - () => state.isManualApprovalEnabled = val, - ), - title: Text( - context.lang.userDiscoverySettingsManualApproval, - style: const TextStyle(fontSize: 13), - ), - subtitle: Text( - context.lang.userDiscoverySettingsManualApprovalDesc, - style: const TextStyle(fontSize: 10), - ), - tileColor: context.color.surfaceContainerLow, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12), - ), - contentPadding: const EdgeInsets.symmetric( - horizontal: 16, - ), - ), - ], - ), - ), - const SizedBox(height: 80), - - Text( - context.lang.onboardingUserDiscoveryLetFriendsFindYou, - style: const TextStyle( - fontSize: 17, - fontWeight: FontWeight.bold, - ), - textAlign: TextAlign.center, - ), - const SizedBox(height: 8), - - RichText( - text: TextSpan( - children: formattedText( - context, - context.lang.onboardingUserDiscoveryLetFriendsFindYouDesc, - ), - ), - textAlign: TextAlign.center, - ), - - const SizedBox(height: 24), - - SetupSwitchCard( - value: state.sharePromotion, - onChanged: (val) => state.update(() { - if (val) { - state.isUserDiscoveryEnabled = true; - } - state.sharePromotion = val; - }), - title: context.lang.onboardingUserDiscoveryBeRecommended, - expandedChild: Padding( - padding: const EdgeInsets.all(12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Row( - children: [ - Expanded( - child: Text( - context.lang.userDiscoverySettingsMutualFriends, - style: const TextStyle(fontSize: 12), - ), - ), - const SizedBox(width: 6), - DropdownButtonHideUnderline( - child: DropdownButton( - value: state.threshold, - items: List.generate( - 9, - (index) { - final value = index + 2; - return DropdownMenuItem( - value: value, - child: Text('$value'), - ); - }, - ), - onChanged: (newValue) { - if (newValue != null) { - state.update(() { - state.threshold = newValue; - }); - } - }, - ), - ), - ], ), - const SizedBox(height: 16), + const Padding( + padding: EdgeInsets.symmetric(vertical: 8), + child: Divider(), + ), Text( - context.lang.onboardingUserDiscoveryWhatOthersSee, + context.lang.onboardingUserDiscoveryContactsVerifiedBadge, style: TextStyle( color: context.color.onSurfaceVariant, fontSize: 12, @@ -421,55 +154,38 @@ class UserDiscoverySetupComp extends StatelessWidget { textAlign: TextAlign.center, ), const SizedBox(height: 16), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + Center( child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 6, - vertical: 3, - ), + width: 100, + height: 40, decoration: BoxDecoration( border: Border.all(color: Colors.grey, width: 0.5), borderRadius: BorderRadius.circular(12), ), - child: Row( + child: const Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - const AvatarIcon(fontSize: 14), - const SizedBox(width: 5), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - userService.currentUser.username, - style: const TextStyle( - fontWeight: FontWeight.bold, - ), - ), - RichText( - text: TextSpan( - children: buildFriendsListTextString( - context, - exampleUsers.sublist( - 0, - state.threshold, - ), - ), - style: const TextStyle(fontSize: 11), - ), - ), - ], + AvatarIcon(fontSize: 12), + SizedBox(width: 5), + Text( + 'jane', + style: TextStyle( + fontWeight: FontWeight.bold, ), ), - const MockContactSuggestedActionsComp(), + SizedBox(width: 5), + VerificationBadgeComp( + isVerifiedByTransferredTrust: true, + size: 14, + clickable: false, + ), ], ), ), ), - const SizedBox(height: 16), + const SizedBox(height: 24), Text( - context.lang.onboardingUserDiscoveryWhatYouSee, + context.lang.onboardingUserDiscoveryWhoIsRequesting, style: TextStyle( color: context.color.onSurfaceVariant, fontSize: 12, @@ -478,7 +194,7 @@ class UserDiscoverySetupComp extends StatelessWidget { ), const SizedBox(height: 16), Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), + padding: const EdgeInsets.symmetric(horizontal: 24), child: Container( padding: const EdgeInsets.symmetric( horizontal: 6, @@ -508,10 +224,10 @@ class UserDiscoverySetupComp extends StatelessWidget { text: TextSpan( children: buildFriendsListTextString( context, - exampleUsers.sublist( - 0, - state.threshold, - ), + [ + 'mary', + 'james', + ], ), style: const TextStyle(fontSize: 10), ), @@ -524,10 +240,201 @@ class UserDiscoverySetupComp extends StatelessWidget { ), ), ), + const SizedBox(height: 16), ], ), ), - ), + + if (showOnlySpecificPage == UserDiscoveryPages.all) + const SizedBox(height: 80), + ], + + if (showOnlySpecificPage == UserDiscoveryPages.all || + showOnlySpecificPage == + UserDiscoveryPages.letYourFriendsFindYou) ...[ + Text( + context.lang.onboardingUserDiscoveryLetFriendsFindYou, + style: Theme.of(context).textTheme.headlineSmall, + ), + const SizedBox(height: 32), + + RichText( + text: TextSpan( + children: formattedText( + context, + context.lang.userDiscoveryDisabledIntro, + ), + ), + textAlign: TextAlign.center, + ), + + const SizedBox(height: 32), + + SetupSwitchCard( + value: state.sharePromotion, + onChanged: (val) => state.update(() { + if (val) { + state.isUserDiscoveryEnabled = true; + } + state.sharePromotion = val; + }), + title: context.lang.onboardingUserDiscoveryBeRecommended, + expandedChild: Padding( + padding: const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Row( + children: [ + Expanded( + child: Text( + context.lang.userDiscoverySettingsMutualFriends, + style: const TextStyle(fontSize: 12), + ), + ), + const SizedBox(width: 12), + DropdownButtonHideUnderline( + child: DropdownButton( + value: state.threshold, + items: List.generate( + 9, + (index) { + final value = index + 2; + return DropdownMenuItem( + value: value, + child: Text('$value'), + ); + }, + ), + onChanged: (newValue) { + if (newValue != null) { + state.update(() { + state.threshold = newValue; + }); + } + }, + ), + ), + ], + ), + const SizedBox(height: 16), + Text( + context.lang.onboardingUserDiscoveryWhatOthersSee, + style: TextStyle( + color: context.color.onSurfaceVariant, + fontSize: 12, + ), + textAlign: TextAlign.center, + ), + const SizedBox(height: 16), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 6, + vertical: 3, + ), + decoration: BoxDecoration( + border: Border.all(color: Colors.grey, width: 0.5), + borderRadius: BorderRadius.circular(12), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const AvatarIcon(fontSize: 14), + const SizedBox(width: 5), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + userService.currentUser.username, + style: const TextStyle( + fontWeight: FontWeight.bold, + ), + ), + RichText( + text: TextSpan( + children: buildFriendsListTextString( + context, + exampleUsers.sublist( + 0, + state.threshold, + ), + ), + style: const TextStyle(fontSize: 11), + ), + ), + ], + ), + ), + const MockContactSuggestedActionsComp(), + ], + ), + ), + ), + const SizedBox(height: 16), + Text( + context.lang.onboardingUserDiscoveryWhatYouSee, + style: TextStyle( + color: context.color.onSurfaceVariant, + fontSize: 12, + ), + textAlign: TextAlign.center, + ), + const SizedBox(height: 16), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 6, + vertical: 3, + ), + decoration: BoxDecoration( + border: Border.all(color: Colors.grey, width: 0.5), + borderRadius: BorderRadius.circular(12), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const AvatarIcon(fontSize: 14), + const SizedBox(width: 5), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + 'jane', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 13, + ), + ), + RichText( + text: TextSpan( + children: buildFriendsListTextString( + context, + exampleUsers.sublist( + 0, + state.threshold, + ), + ), + style: const TextStyle(fontSize: 10), + ), + ), + ], + ), + ), + const MockContactRequestActionsComp(), + ], + ), + ), + ), + ], + ), + ), + ), + ], ], ), ); diff --git a/lib/src/visual/views/settings/privacy/user_discovery/user_discovery_settings.view.dart b/lib/src/visual/views/settings/privacy/user_discovery/user_discovery_settings.view.dart index 6ebc456a..06b926ad 100644 --- a/lib/src/visual/views/settings/privacy/user_discovery/user_discovery_settings.view.dart +++ b/lib/src/visual/views/settings/privacy/user_discovery/user_discovery_settings.view.dart @@ -25,8 +25,6 @@ class _UserDiscoverySettingsViewState extends State { requiredSendImages: u.requiredSendImages, isUserDiscoveryEnabled: u.isUserDiscoveryEnabled, sharePromotion: u.userDiscoverySharePromotion, - isShareAllContacts: - u.requiredSendImages == 0 && !u.userDiscoveryRequiresManualApproval, isManualApprovalEnabled: u.userDiscoveryRequiresManualApproval, threshold: u.userDiscoveryThreshold, );