diff --git a/RELEASE.md b/RELEASE.md index 79b11900..19a4d16f 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,7 +1,7 @@ ### Updates -1. Fix: Bug with a minimal ad edit. -2. Fix: Markdown doesn't function in the app when viewing Terms of… -3. Fix: Mark notifications as read - if a trade is opened and the app receives a notification about it, it should mark it as read. +1. Added an additional price check before initiating a trade. If the ad price has changed, prompt the user for confirmation. +2. Now displaying the usernames of those who leave feedback in a user's profile. This allows users to see who has provided feedback and to improve their service accordingly. +3. Changed instructions for importing reputation from the Paxful platform. diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 628523d5..4974251d 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -24,9 +24,9 @@ PODS: - FirebaseCoreInternal (~> 10.0) - GoogleUtilities/Environment (~> 7.8) - GoogleUtilities/Logger (~> 7.8) - - FirebaseCoreInternal (10.16.0): + - FirebaseCoreInternal (10.18.0): - "GoogleUtilities/NSData+zlib (~> 7.8)" - - FirebaseInstallations (10.16.0): + - FirebaseInstallations (10.18.0): - FirebaseCore (~> 10.0) - GoogleUtilities/Environment (~> 7.8) - GoogleUtilities/UserDefaults (~> 7.8) @@ -61,37 +61,37 @@ PODS: - FMDB (2.7.5): - FMDB/standard (= 2.7.5) - FMDB/standard (2.7.5) - - GoogleDataTransport (9.2.5): + - GoogleDataTransport (9.3.0): - GoogleUtilities/Environment (~> 7.7) - nanopb (< 2.30910.0, >= 2.30908.0) - PromisesObjC (< 3.0, >= 1.2) - - GoogleUtilities/AppDelegateSwizzler (7.11.5): + - GoogleUtilities/AppDelegateSwizzler (7.12.0): - GoogleUtilities/Environment - GoogleUtilities/Logger - GoogleUtilities/Network - - GoogleUtilities/Environment (7.11.5): + - GoogleUtilities/Environment (7.12.0): - PromisesObjC (< 3.0, >= 1.2) - - GoogleUtilities/Logger (7.11.5): + - GoogleUtilities/Logger (7.12.0): - GoogleUtilities/Environment - - GoogleUtilities/Network (7.11.5): + - GoogleUtilities/Network (7.12.0): - GoogleUtilities/Logger - "GoogleUtilities/NSData+zlib" - GoogleUtilities/Reachability - - "GoogleUtilities/NSData+zlib (7.11.5)" - - GoogleUtilities/Reachability (7.11.5): + - "GoogleUtilities/NSData+zlib (7.12.0)" + - GoogleUtilities/Reachability (7.12.0): - GoogleUtilities/Logger - - GoogleUtilities/UserDefaults (7.11.5): + - GoogleUtilities/UserDefaults (7.12.0): - GoogleUtilities/Logger - image_picker_ios (0.0.1): - Flutter - local_auth_ios (0.0.1): - Flutter - MTBBarcodeScanner (5.0.11) - - nanopb (2.30909.0): - - nanopb/decode (= 2.30909.0) - - nanopb/encode (= 2.30909.0) - - nanopb/decode (2.30909.0) - - nanopb/encode (2.30909.0) + - nanopb (2.30909.1): + - nanopb/decode (= 2.30909.1) + - nanopb/encode (= 2.30909.1) + - nanopb/decode (2.30909.1) + - nanopb/encode (2.30909.1) - OrderedSet (5.0.0) - package_info_plus (0.4.5): - Flutter @@ -119,7 +119,7 @@ PODS: - FMDB (>= 2.7.5) - store_checker (0.0.1): - Flutter - - SwiftProtobuf (1.24.0) + - SwiftProtobuf (1.25.2) - uni_links (0.0.1): - Flutter - url_launcher_ios (0.0.1): @@ -233,8 +233,8 @@ SPEC CHECKSUMS: firebase_core: 85b6664038311940ad60584eaabc73103c61f5de firebase_messaging: c55f70dd48a998dea00a29ccf94572e1e4d454b2 FirebaseCore: d027ff503d37edb78db98429b11f580a24a7df2a - FirebaseCoreInternal: 26233f705cc4531236818a07ac84d20c333e505a - FirebaseInstallations: b822f91a61f7d1ba763e5ccc9d4f2e6f2ed3b3ee + FirebaseCoreInternal: 8eb002e564b533bdcf1ba011f33f2b5c10e2ed4a + FirebaseInstallations: e842042ec6ac1fd2e37d7706363ebe7f662afea4 FirebaseMessaging: 8a3b9a8b98ce72a42d22e69865cf662e38d2d6f5 Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 flutter_app_badger: b87fc231847b03b92ce1412aa351842e7e97932f @@ -244,12 +244,12 @@ SPEC CHECKSUMS: flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743 flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a - GoogleDataTransport: 54dee9d48d14580407f8f5fbf2f496e92437a2f2 - GoogleUtilities: 13e2c67ede716b8741c7989e26893d151b2b2084 + GoogleDataTransport: 57c22343ab29bc686febbf7cbb13bad167c2d8fe + GoogleUtilities: 0759d1a57ebb953965c2dfe0ba4c82e95ccc2e34 image_picker_ios: 4a8aadfbb6dc30ad5141a2ce3832af9214a705b5 local_auth_ios: c6cf091ded637a88f24f86a8875d8b0f526e2605 MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb - nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431 + nanopb: d4d75c12cd1316f4a64e3c6963f879ecd4b5e0d5 OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c package_info_plus: fd030dabf36271f146f1f3beacd48f564b0f17f7 path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8 @@ -263,7 +263,7 @@ SPEC CHECKSUMS: shared_preferences_foundation: e2dae3258e06f44cc55f49d42024fd8dd03c590c sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904 store_checker: 359c5051d9ec30ff0a8fa39eb5ec9df021bb745d - SwiftProtobuf: bcfd2bc231cf9ae552cdc7c4e877bd3b41fe57b1 + SwiftProtobuf: 407a385e97fd206c4fbe880cc84123989167e0d1 uni_links: d97da20c7701486ba192624d99bffaaffcfc298a url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4 video_player_avfoundation: 81e49bb3d9fb63dccf9fa0f6d877dc3ddbeac126 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 3997f486..97692889 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -432,7 +432,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 110; + CURRENT_PROJECT_VERSION = 111; DEVELOPMENT_TEAM = G8RXR25D89; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -441,7 +441,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.1.14; + MARKETING_VERSION = 1.1.15; PRODUCT_BUNDLE_IDENTIFIER = com.agoradesk.app; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -522,7 +522,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 110; + CURRENT_PROJECT_VERSION = 111; DEVELOPMENT_TEAM = G8RXR25D89; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -531,7 +531,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.1.14; + MARKETING_VERSION = 1.1.15; PRODUCT_BUNDLE_IDENTIFIER = com.agoradesk.app; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -611,7 +611,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 110; + CURRENT_PROJECT_VERSION = 111; DEVELOPMENT_TEAM = G8RXR25D89; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -620,7 +620,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.1.14; + MARKETING_VERSION = 1.1.15; PRODUCT_BUNDLE_IDENTIFIER = co.localmonero.app; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -703,7 +703,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 110; + CURRENT_PROJECT_VERSION = 111; DEVELOPMENT_TEAM = G8RXR25D89; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -712,7 +712,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.1.14; + MARKETING_VERSION = 1.1.15; PRODUCT_BUNDLE_IDENTIFIER = co.localmonero.app; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -791,7 +791,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 110; + CURRENT_PROJECT_VERSION = 111; DEVELOPMENT_TEAM = G8RXR25D89; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -800,7 +800,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.1.14; + MARKETING_VERSION = 1.1.15; PRODUCT_BUNDLE_IDENTIFIER = com.agoradesk.app; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -878,7 +878,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 110; + CURRENT_PROJECT_VERSION = 111; DEVELOPMENT_TEAM = G8RXR25D89; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -887,7 +887,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.1.14; + MARKETING_VERSION = 1.1.15; PRODUCT_BUNDLE_IDENTIFIER = co.localmonero.app; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/lib/core/widgets/branded/agora_dialog_close_link.dart b/lib/core/widgets/branded/agora_dialog_close_link.dart index e60a7202..a3804c02 100644 --- a/lib/core/widgets/branded/agora_dialog_close_link.dart +++ b/lib/core/widgets/branded/agora_dialog_close_link.dart @@ -22,7 +22,7 @@ class AgoraDialogCloseLink extends StatelessWidget { showDialog( barrierDismissible: true, context: context, - builder: (_) => AgoraDialogClose( + builder: (context) => AgoraDialogClose( title: title ?? linkTitle, text: text, ), diff --git a/lib/core/widgets/branded/agora_dialog_info_link.dart b/lib/core/widgets/branded/agora_dialog_info_link.dart index cf72760c..89a8efe7 100644 --- a/lib/core/widgets/branded/agora_dialog_info_link.dart +++ b/lib/core/widgets/branded/agora_dialog_info_link.dart @@ -22,7 +22,7 @@ class AgoraDialogInfoWithMarkdown extends StatelessWidget { showDialog( barrierDismissible: true, context: context, - builder: (_) => AgoraDialogInfo( + builder: (context) => AgoraDialogInfo( title: title ?? linkTitle, text: text, ), diff --git a/lib/features/account/data/models/feedback_model.dart b/lib/features/account/data/models/feedback_model.dart index cb2aa9e0..867dca10 100644 --- a/lib/features/account/data/models/feedback_model.dart +++ b/lib/features/account/data/models/feedback_model.dart @@ -14,6 +14,7 @@ class FeedbackModel with _$FeedbackModel { @JsonKey(name: 'feedback_type', includeIfNull: false) required FeedbackType feedbackType, @JsonKey(name: 'given_at', includeIfNull: false, fromJson: fromJsonDate, toJson: toJsonDate) required DateTime date, @JsonKey(name: 'msg', includeIfNull: false) String? text, + String? giver, }) = _FeedbackModel; factory FeedbackModel.fromJson(Map json) => _$FeedbackModelFromJson(json); diff --git a/lib/features/account/data/models/feedback_model.freezed.dart b/lib/features/account/data/models/feedback_model.freezed.dart index 20c8f3ca..f07bcd61 100644 --- a/lib/features/account/data/models/feedback_model.freezed.dart +++ b/lib/features/account/data/models/feedback_model.freezed.dart @@ -30,6 +30,7 @@ mixin _$FeedbackModel { DateTime get date => throw _privateConstructorUsedError; @JsonKey(name: 'msg', includeIfNull: false) String? get text => throw _privateConstructorUsedError; + String? get giver => throw _privateConstructorUsedError; Map toJson() => throw _privateConstructorUsedError; @JsonKey(ignore: true) @@ -49,7 +50,8 @@ abstract class $FeedbackModelCopyWith<$Res> { @JsonKey(name: 'given_at', includeIfNull: false, fromJson: fromJsonDate, toJson: toJsonDate) DateTime date, @JsonKey(name: 'msg', includeIfNull: false) - String? text}); + String? text, + String? giver}); } /// @nodoc @@ -68,6 +70,7 @@ class _$FeedbackModelCopyWithImpl<$Res, $Val extends FeedbackModel> Object? feedbackType = null, Object? date = null, Object? text = freezed, + Object? giver = freezed, }) { return _then(_value.copyWith( feedbackType: null == feedbackType @@ -82,6 +85,10 @@ class _$FeedbackModelCopyWithImpl<$Res, $Val extends FeedbackModel> ? _value.text : text // ignore: cast_nullable_to_non_nullable as String?, + giver: freezed == giver + ? _value.giver + : giver // ignore: cast_nullable_to_non_nullable + as String?, ) as $Val); } } @@ -100,7 +107,8 @@ abstract class _$$_FeedbackModelCopyWith<$Res> @JsonKey(name: 'given_at', includeIfNull: false, fromJson: fromJsonDate, toJson: toJsonDate) DateTime date, @JsonKey(name: 'msg', includeIfNull: false) - String? text}); + String? text, + String? giver}); } /// @nodoc @@ -117,6 +125,7 @@ class __$$_FeedbackModelCopyWithImpl<$Res> Object? feedbackType = null, Object? date = null, Object? text = freezed, + Object? giver = freezed, }) { return _then(_$_FeedbackModel( feedbackType: null == feedbackType @@ -131,6 +140,10 @@ class __$$_FeedbackModelCopyWithImpl<$Res> ? _value.text : text // ignore: cast_nullable_to_non_nullable as String?, + giver: freezed == giver + ? _value.giver + : giver // ignore: cast_nullable_to_non_nullable + as String?, )); } } @@ -145,7 +158,8 @@ class _$_FeedbackModel implements _FeedbackModel { @JsonKey(name: 'given_at', includeIfNull: false, fromJson: fromJsonDate, toJson: toJsonDate) required this.date, @JsonKey(name: 'msg', includeIfNull: false) - this.text}); + this.text, + this.giver}); factory _$_FeedbackModel.fromJson(Map json) => _$$_FeedbackModelFromJson(json); @@ -163,10 +177,12 @@ class _$_FeedbackModel implements _FeedbackModel { @override @JsonKey(name: 'msg', includeIfNull: false) final String? text; + @override + final String? giver; @override String toString() { - return 'FeedbackModel(feedbackType: $feedbackType, date: $date, text: $text)'; + return 'FeedbackModel(feedbackType: $feedbackType, date: $date, text: $text, giver: $giver)'; } @override @@ -177,12 +193,13 @@ class _$_FeedbackModel implements _FeedbackModel { (identical(other.feedbackType, feedbackType) || other.feedbackType == feedbackType) && (identical(other.date, date) || other.date == date) && - (identical(other.text, text) || other.text == text)); + (identical(other.text, text) || other.text == text) && + (identical(other.giver, giver) || other.giver == giver)); } @JsonKey(ignore: true) @override - int get hashCode => Object.hash(runtimeType, feedbackType, date, text); + int get hashCode => Object.hash(runtimeType, feedbackType, date, text, giver); @JsonKey(ignore: true) @override @@ -205,7 +222,8 @@ abstract class _FeedbackModel implements FeedbackModel { @JsonKey(name: 'given_at', includeIfNull: false, fromJson: fromJsonDate, toJson: toJsonDate) required final DateTime date, @JsonKey(name: 'msg', includeIfNull: false) - final String? text}) = _$_FeedbackModel; + final String? text, + final String? giver}) = _$_FeedbackModel; factory _FeedbackModel.fromJson(Map json) = _$_FeedbackModel.fromJson; @@ -224,6 +242,8 @@ abstract class _FeedbackModel implements FeedbackModel { @JsonKey(name: 'msg', includeIfNull: false) String? get text; @override + String? get giver; + @override @JsonKey(ignore: true) _$$_FeedbackModelCopyWith<_$_FeedbackModel> get copyWith => throw _privateConstructorUsedError; diff --git a/lib/features/account/data/models/feedback_model.g.dart b/lib/features/account/data/models/feedback_model.g.dart index 0bdf3341..ecc3b77c 100644 --- a/lib/features/account/data/models/feedback_model.g.dart +++ b/lib/features/account/data/models/feedback_model.g.dart @@ -11,6 +11,7 @@ _$_FeedbackModel _$$_FeedbackModelFromJson(Map json) => feedbackType: $enumDecode(_$FeedbackTypeEnumMap, json['feedback_type']), date: fromJsonDate(json['given_at'] as String), text: json['msg'] as String?, + giver: json['giver'] as String?, ); Map _$$_FeedbackModelToJson(_$_FeedbackModel instance) { @@ -26,6 +27,7 @@ Map _$$_FeedbackModelToJson(_$_FeedbackModel instance) { } writeNotNull('msg', instance.text); + val['giver'] = instance.giver; return val; } diff --git a/lib/features/account/screens/widgets/feedback_tile.dart b/lib/features/account/screens/widgets/feedback_tile.dart index 5811d7bd..1abb472a 100644 --- a/lib/features/account/screens/widgets/feedback_tile.dart +++ b/lib/features/account/screens/widgets/feedback_tile.dart @@ -35,6 +35,15 @@ class FeedbackTile extends StatelessWidget with DateMixin { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ + feedback.giver != null && feedback.giver!.isNotEmpty + ? Padding( + padding: const EdgeInsets.fromLTRB(0, 0, 0, 4), + child: Text( + feedback.giver!, + style: context.txtBodyXSmallN80, + ), + ) + : const SizedBox(), feedback.text != null && feedback.text!.isNotEmpty ? Padding( padding: const EdgeInsets.fromLTRB(0, 0, 0, 4), diff --git a/lib/features/ads/screens/ad_edit_screen.dart b/lib/features/ads/screens/ad_edit_screen.dart index 82eaeeae..fd208ea3 100644 --- a/lib/features/ads/screens/ad_edit_screen.dart +++ b/lib/features/ads/screens/ad_edit_screen.dart @@ -559,7 +559,7 @@ class _PopupMenu extends StatelessWidget { showDialog( barrierDismissible: true, context: context, - builder: (_) => AgoraDialogTwoButtons( + builder: (context) => AgoraDialogTwoButtons( body: Text(context.intl.ask_delete_ad), mainAction: model.deleteAd, mainActionText: context.intl.delete, diff --git a/lib/features/ads/screens/ad_info_screen.dart b/lib/features/ads/screens/ad_info_screen.dart index ce20f737..7fca92bd 100644 --- a/lib/features/ads/screens/ad_info_screen.dart +++ b/lib/features/ads/screens/ad_info_screen.dart @@ -215,7 +215,7 @@ class _PopupMenu extends StatelessWidget { showDialog( barrierDismissible: true, context: context, - builder: (_) => AgoraDialogTwoButtons( + builder: (context) => AgoraDialogTwoButtons( body: Text( context.intl.ask_delete_ad, style: context.txtBodySmallN80, diff --git a/lib/features/ads/screens/ads_screen.dart b/lib/features/ads/screens/ads_screen.dart index 4bf298cb..c0fa7fe1 100644 --- a/lib/features/ads/screens/ads_screen.dart +++ b/lib/features/ads/screens/ads_screen.dart @@ -98,7 +98,7 @@ class _AdsScreenState extends State with TickerProviderStateMixin, Co onPressed: () { showDialog( context: context, - builder: (_) => _dialogBulkDeleteAds(context, model), + builder: (context) => _dialogBulkDeleteAds(context, model), ); }, ) diff --git a/lib/features/ads/screens/widgets/ad_tile.dart b/lib/features/ads/screens/widgets/ad_tile.dart index 65299321..48acd785 100644 --- a/lib/features/ads/screens/widgets/ad_tile.dart +++ b/lib/features/ads/screens/widgets/ad_tile.dart @@ -252,7 +252,7 @@ class AdTile extends StatelessWidget with DateMixin, CountryInfoMixin, PaymentMe onTap: () { showDialog( context: context, - builder: (_) => AgoraDialogInfoNoTitle( + builder: (context) => AgoraDialogInfoNoTitle( child: Text( context.intl.warning250Sbmin8722Sbamount8722Sbless8722Sbthan8722Sbbalance8722Sb0, style: context.txtBodySmallN80N30, @@ -264,7 +264,7 @@ class AdTile extends StatelessWidget with DateMixin, CountryInfoMixin, PaymentMe onTap: () { showDialog( context: context, - builder: (_) => AgoraDialogInfoNoTitle( + builder: (context) => AgoraDialogInfoNoTitle( child: Text( context .intl.warning250Sbmin8722Sbamount8722Sbless8722Sbthan8722Sbbalance8722Sb0, diff --git a/lib/features/ads/screens/widgets/post_ad_step_1.dart b/lib/features/ads/screens/widgets/post_ad_step_1.dart index ff92eaed..496002d6 100644 --- a/lib/features/ads/screens/widgets/post_ad_step_1.dart +++ b/lib/features/ads/screens/widgets/post_ad_step_1.dart @@ -64,7 +64,7 @@ class _PostAdStep1State extends State { showDialog( barrierDismissible: true, context: context, - builder: (_) => DialogInfoS4WithCloseChildContinue( + builder: (context) => DialogInfoS4WithCloseChildContinue( title: context.intl.post8722Sbad250Sbrules8722Sbtitle, child: const AdsTerms(), ), diff --git a/lib/features/auth/models/forgot_password_view_model.dart b/lib/features/auth/models/forgot_password_view_model.dart index 603eb5c3..214422b3 100644 --- a/lib/features/auth/models/forgot_password_view_model.dart +++ b/lib/features/auth/models/forgot_password_view_model.dart @@ -70,7 +70,7 @@ class ForgotPasswordViewModel extends ViewModel with ValidatorMixin, ErrorParseM _captchaInput = await showDialog( context: context, barrierDismissible: true, - builder: (_) => DialogCaptcha( + builder: (context) => DialogCaptcha( path: captchaPath, ), ); diff --git a/lib/features/auth/models/login_view_model.dart b/lib/features/auth/models/login_view_model.dart index 09d87a6e..f396ee86 100644 --- a/lib/features/auth/models/login_view_model.dart +++ b/lib/features/auth/models/login_view_model.dart @@ -137,7 +137,7 @@ class LoginViewModel extends ViewModel with ValidatorMixin, ErrorParseMixin { _captchaInput = await showDialog( context: context, barrierDismissible: true, - builder: (_) => DialogCaptcha( + builder: (context) => DialogCaptcha( path: captchaPath, ), ); diff --git a/lib/features/auth/models/pin_code_view_model.dart b/lib/features/auth/models/pin_code_view_model.dart index a3387138..540086ca 100644 --- a/lib/features/auth/models/pin_code_view_model.dart +++ b/lib/features/auth/models/pin_code_view_model.dart @@ -100,7 +100,7 @@ class PinCodeViewModel extends ViewModel { eventBus.fire(const LogOutEvent()); } AppSharedPrefs().setInt(AppSharedPrefsKey.pinAttemptsLeft, attemptsLeft); - showDialog(context: context, builder: (_) => _dialogInputPinWrong(context, attemptsLeft)); + showDialog(context: context, builder: (context) => _dialogInputPinWrong(context, attemptsLeft)); return false; } AppSharedPrefs().setInt(AppSharedPrefsKey.pinAttemptsLeft, kPinAttempts); @@ -110,7 +110,7 @@ class PinCodeViewModel extends ViewModel { void handlePinInput(String pin, {bool onFull = false}) async { if (hasCurrentPin && !currentPinChecked && currentPin != null) { if (pin != currentPin) { - showDialog(context: context, builder: (_) => _dialogSetPinWrong(context)); + showDialog(context: context, builder: (context) => _dialogSetPinWrong(context)); } else if (pin.length == currentPin!.length) { currentPinChecked = true; if (pin.length < kMaxPinLength) { @@ -122,7 +122,7 @@ class PinCodeViewModel extends ViewModel { isFirstPin = false; firstPinCode = pin; } else { - showDialog(context: context, builder: (_) => _dialogWrongLength(context)); + showDialog(context: context, builder: (context) => _dialogWrongLength(context)); isFirstPin = true; clearPins(); } @@ -132,7 +132,7 @@ class PinCodeViewModel extends ViewModel { await setPin(); AutoRouter.of(context).pop(); } else { - showDialog(context: context, builder: (_) => _dialogNotMatch(context)); + showDialog(context: context, builder: (context) => _dialogNotMatch(context)); isFirstPin = true; clearPins(); } diff --git a/lib/features/auth/models/sign_up_view_model.dart b/lib/features/auth/models/sign_up_view_model.dart index 5e3c7317..b032a51f 100644 --- a/lib/features/auth/models/sign_up_view_model.dart +++ b/lib/features/auth/models/sign_up_view_model.dart @@ -137,7 +137,7 @@ class SignUpViewModel extends ViewModel with ValidatorMixin, ErrorParseMixin { _captchaInput = await showDialog( context: context, barrierDismissible: true, - builder: (_) => DialogCaptcha( + builder: (context) => DialogCaptcha( path: captchaPath, ), ); diff --git a/lib/features/main/main_screen.dart b/lib/features/main/main_screen.dart index b2c17414..47cf2343 100644 --- a/lib/features/main/main_screen.dart +++ b/lib/features/main/main_screen.dart @@ -58,7 +58,7 @@ class _MainScreenState extends State { backgroundColor: Theme.of(context).colorScheme.surface1, animationCurve: Curves.easeInOut, animationDuration: const Duration(milliseconds: 500), - bottomNavigationBuilder: (_, t) { + bottomNavigationBuilder: (context, t) { tabsRouter = t; return Theme( data: ThemeData( diff --git a/lib/features/market/models/market_ad_info_view_model.dart b/lib/features/market/models/market_ad_info_view_model.dart index d6863573..632a7275 100644 --- a/lib/features/market/models/market_ad_info_view_model.dart +++ b/lib/features/market/models/market_ad_info_view_model.dart @@ -94,10 +94,19 @@ class MarketAdInfoViewModel extends ViewModel BtcFeesModel? btcFees; String address = ''; bool _fieldHasValue = false; + bool _checkingPrice = false; + String? _changedAdPrice = ''; + bool _userAgreeToChangedPrice = false; late final bool isSell; late final bool isAdOwner; + bool get userAgreeToChangedPrice => _userAgreeToChangedPrice; + set userAgreeToChangedPrice(bool v) => updateWith(userAgreeToChangedPrice: v); + + String? get changedAdPrice => _changedAdPrice; + set changedAdPrice(String? v) => updateWith(changedAdPrice: v); + bool get fieldHasValue => _fieldHasValue; set fieldHasValue(bool v) => updateWith(fieldHasValue: v); @@ -423,6 +432,30 @@ class MarketAdInfoViewModel extends ViewModel } } + /// returns true if prices are the same + Future checkTheAdPrice() async { + if (!_checkingPrice) { + // if (!isSell || (isSell && checkWalletAddressCorrect)) + _checkingPrice = true; + final adRes = await _adsRepository.getAd(adId!); + _checkingPrice = false; + if (adRes.isRight) { + final latestAd = adRes.right; + if (latestAd.tempPrice != ad?.tempPrice) { + changedAdPrice = latestAd.tempPrice; + return false; + } else { + return true; + } + } else { + _checkingPrice = false; + handleApiError(adRes.left, context); + return null; + } + } + return null; + } + String howMuchSign(BuildContext context) { return context.intl.app_buy_sell(ad!.tradeType.isSell() ? context.intl.ad8722Sbpage250Sbhow8722Sbmuch8722Sbdo8722Sbyou8722Sbwish8722Sbto8722Sbbuy @@ -462,6 +495,8 @@ class MarketAdInfoViewModel extends ViewModel bool? loadingSettings, bool? loadingFees, bool? startingTrade, + String? changedAdPrice, + bool? userAgreeToChangedPrice, }) async { bool reloadAds = false; _loadingAds = loadingAds ?? _loadingAds; @@ -470,6 +505,8 @@ class MarketAdInfoViewModel extends ViewModel _loadingFees = loadingFees ?? _loadingFees; _startingTrade = startingTrade ?? _startingTrade; _btcFeesEnum = btcFeesEnum ?? _btcFeesEnum; + _changedAdPrice = changedAdPrice ?? _changedAdPrice; + _userAgreeToChangedPrice = userAgreeToChangedPrice ?? _userAgreeToChangedPrice; if ((_asset != asset && asset != null || _tradeType != tradeType && tradeType != null) && !_loadingAds) { reloadAds = true; } diff --git a/lib/features/market/screens/initiate_trade_screen.dart b/lib/features/market/screens/initiate_trade_screen.dart index 4ee280ff..9a577dd6 100644 --- a/lib/features/market/screens/initiate_trade_screen.dart +++ b/lib/features/market/screens/initiate_trade_screen.dart @@ -12,13 +12,16 @@ import 'package:agoradesk/core/widgets/branded/button_icon_text_p70.dart'; import 'package:agoradesk/core/widgets/branded/container_surface2_radius12_border1.dart'; import 'package:agoradesk/core/widgets/branded/container_surface3_radius12_border1.dart'; import 'package:agoradesk/core/widgets/branded/container_surface5_radius12.dart'; +import 'package:agoradesk/core/widgets/branded/dialog_outline_and_filled_buttons.dart'; import 'package:agoradesk/features/ads/data/models/asset.dart'; import 'package:agoradesk/features/market/models/market_ad_info_view_model.dart'; import 'package:agoradesk/features/market/screens/widgets/btc_fees_radio_buttons.dart'; +import 'package:agoradesk/features/market/screens/widgets/line_with_dot.dart'; import 'package:agoradesk/features/market/screens/widgets/suffix_icon.dart'; import 'package:agoradesk/features/market/screens/widgets/text_with_dot.dart'; import 'package:agoradesk/features/wallet/screens/widgets/send_asset_text_field.dart'; import 'package:agoradesk/generated/i18n.dart'; +import 'package:auto_route/auto_route.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart'; @@ -258,12 +261,27 @@ class InitiateTradeScreen extends StatelessWidget with CountryInfoMixin, Clipboa filledButtonTitle: model.isSell ? context.intl.ad8722Sbpage250Sbterms8722Sbdialog250Sbagree8722Sbbtn : context.intl.ad8722Sbpage250Sbterms8722Sbdialog250Sbagree8722Sbcontinue, - onPressedFilled: () { - if (model.isSell) { - model.startTrade(context); - } else { - Navigator.of(context).pop(); - _displayAddressDialog(context, model); + onPressedFilled: () async { + // check that the Ad price is still the same + // Urgent fix required: right before opening a trade the app must send a request to the ad + // info to make sure that the price is still the same as shown to the user currently. + // If not, it should notify the user with a dialogue and ask whether the user wishes to proceed + // the reason this is urgent is that there's a user exploiting the pause while the user is + // looking at the offer to change the ad's price to be 3x the market rate and scam buyers that way + + final res = await model.checkTheAdPrice(); + + if (res == false) { + await _showPriceChangeDialog(context, model); + } + + if (res == true || model.userAgreeToChangedPrice) { + if (model.isSell) { + model.startTrade(context); + } else { + Navigator.of(context).pop(); + _displayAddressDialog(context, model); + } } }, loadingFilled: model.startingTrade, @@ -275,7 +293,7 @@ class InitiateTradeScreen extends StatelessWidget with CountryInfoMixin, Clipboa void _displayAddressDialog(BuildContext context, MarketAdInfoViewModel model) async { showDialog( context: context, - builder: (_) => KeyboardDismissOnTap( + builder: (context) => KeyboardDismissOnTap( child: ViewModelBuilder( model: model, disposable: false, @@ -323,7 +341,7 @@ class InitiateTradeScreen extends StatelessWidget with CountryInfoMixin, Clipboa // ), const SizedBox(height: 12), Text( - context.intl.ad250Sbconfirmation250Sbprovide8722Sbaddress250Sbyou8722Sbown + '.', + '${context.intl.ad250Sbconfirmation250Sbprovide8722Sbaddress250Sbyou8722Sbown}.', style: context.txtBodySmallN80, ), const SizedBox(height: 6), @@ -351,7 +369,7 @@ class InitiateTradeScreen extends StatelessWidget with CountryInfoMixin, Clipboa void _displayBtcFeesDialog(BuildContext context, MarketAdInfoViewModel model) async { showDialog( context: context, - builder: (_) => KeyboardDismissOnTap( + builder: (context) => KeyboardDismissOnTap( child: ViewModelBuilder( model: model, disposable: false, @@ -375,8 +393,7 @@ class InitiateTradeScreen extends StatelessWidget with CountryInfoMixin, Clipboa mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - context.intl.wallet250Sbwithdraw250Sbconfirmation8722Sbdialog250Sbnetwork8722Sbfees + - ':', + '${context.intl.wallet250Sbwithdraw250Sbconfirmation8722Sbdialog250Sbnetwork8722Sbfees}:', style: context.txtLabelMediumN80, ), model.btcFees == null @@ -415,4 +432,32 @@ class InitiateTradeScreen extends StatelessWidget with CountryInfoMixin, Clipboa fiatName: model.fiatName, ); } + + Future _showPriceChangeDialog(BuildContext context, MarketAdInfoViewModel model) async { + await Future.delayed(Duration.zero); + await showDialog( + barrierDismissible: true, + context: context, + builder: (context) => DialogOutlineAndFilledButtons( + title: 'The ad price was changed!!!', + content: Column( + children: [ + const SizedBox(height: 6), + LineWithDot(text: 'Old price was ${model.ad!.tempPrice} ${model.ad!.currency}'), + const SizedBox(height: 6), + LineWithDot(text: 'New price is ${model.ad!.tempPrice} ${model.ad!.currency}'), + const SizedBox(height: 6), + ], + ), + outlineButtonTitle: 'Cancel trade', + onPressedOutline: () => Navigator.of(context).pop(), + filledButtonTitle: 'I agree', + onPressedFilled: () { + model.userAgreeToChangedPrice = true; + Navigator.of(context).pop(); + }, + ), + ); + + } } diff --git a/lib/features/market/screens/market_ad_info_screen.dart b/lib/features/market/screens/market_ad_info_screen.dart index 8c4014a5..5127c6f5 100644 --- a/lib/features/market/screens/market_ad_info_screen.dart +++ b/lib/features/market/screens/market_ad_info_screen.dart @@ -12,6 +12,7 @@ import 'package:agoradesk/core/widgets/branded/box_info_with_label.dart'; import 'package:agoradesk/core/widgets/branded/box_surface5_copy_on_title_readmore.dart'; import 'package:agoradesk/core/widgets/branded/button_icon_text_p70.dart'; import 'package:agoradesk/core/widgets/branded/dialog_info_s4_with_close_child.dart'; +import 'package:agoradesk/core/widgets/branded/dialog_outline_and_filled_buttons.dart'; import 'package:agoradesk/features/account/data/services/account_service.dart'; import 'package:agoradesk/features/ads/data/models/ad_model.dart'; import 'package:agoradesk/features/ads/data/models/asset.dart'; @@ -26,6 +27,7 @@ import 'package:agoradesk/features/market/screens/widgets/text_with_dot.dart'; import 'package:agoradesk/features/trades/data/repository/trade_repository.dart'; import 'package:agoradesk/features/wallet/data/services/wallet_service.dart'; import 'package:agoradesk/generated/i18n.dart'; +import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:vm/vm.dart'; @@ -141,16 +143,13 @@ class MarketAdInfoScreen extends StatelessWidget with CountryInfoMixin, Clipboar : const SizedBox(); } - // Widget _buildReportAd(BuildContext context, MarketAdInfoViewModel model) { - // return - // } void _showDialog(BuildContext context, Asset? asset) { WidgetsBinding.instance.addPostFrameCallback((_) { showDialog( barrierDismissible: true, context: context, - builder: (_) => DialogInfoS4WithCloseChild( + builder: (context) => DialogInfoS4WithCloseChild( title: context.intl.ad8722Sbpage250Sbtips, child: SingleChildScrollView( child: Column( diff --git a/lib/features/profile/models/account_view_model.dart b/lib/features/profile/models/account_view_model.dart index 6b8889f5..334d0a1d 100644 --- a/lib/features/profile/models/account_view_model.dart +++ b/lib/features/profile/models/account_view_model.dart @@ -77,7 +77,7 @@ class AccountViewModel extends ViewModel with ValidatorMixin { showDialog( barrierDismissible: true, context: context, - builder: (_) => AgoraDialogTwoButtons( + builder: (context) => AgoraDialogTwoButtons( body: Text(context.intl.app_anonymous_crash_diagnostics_restart), mainAction: Restart.restartApp, mainActionText: context.intl.app_restart_now, @@ -102,7 +102,7 @@ class AccountViewModel extends ViewModel with ValidatorMixin { await showDialog( barrierDismissible: true, context: context, - builder: (_) => AgoraDialogTwoButtons( + builder: (context) => AgoraDialogTwoButtons( title: context.intl.app_biometric_authentication, body: Text(context.intl.app_biometric_authentication_message), mainActionText: context.intl.pin_set, diff --git a/lib/features/profile/models/email_view_model.dart b/lib/features/profile/models/email_view_model.dart index 3d69cc5d..eafc90d0 100644 --- a/lib/features/profile/models/email_view_model.dart +++ b/lib/features/profile/models/email_view_model.dart @@ -99,7 +99,7 @@ class EmailViewModel extends ViewModel with ValidatorMixin, ErrorParseMixin, Cli _captchaInput = await showDialog( context: context, barrierDismissible: true, - builder: (_) => DialogCaptcha( + builder: (context) => DialogCaptcha( path: captchaPath, ), ); @@ -130,7 +130,7 @@ class EmailViewModel extends ViewModel with ValidatorMixin, ErrorParseMixin, Cli deletePassword = await showDialog( context: context, barrierDismissible: true, - builder: (_) => DialogPassword( + builder: (context) => DialogPassword( title: context.intl.email_confirm_delete, ), ); @@ -163,7 +163,7 @@ class EmailViewModel extends ViewModel with ValidatorMixin, ErrorParseMixin, Cli _captchaInput = await showDialog( context: context, barrierDismissible: true, - builder: (_) => DialogCaptcha( + builder: (context) => DialogCaptcha( path: captchaPath, ), ); diff --git a/lib/features/profile/models/proxy_view_model.dart b/lib/features/profile/models/proxy_view_model.dart index 20eccf81..5b9599db 100644 --- a/lib/features/profile/models/proxy_view_model.dart +++ b/lib/features/profile/models/proxy_view_model.dart @@ -191,7 +191,7 @@ class ProxyViewModel extends ViewModel with ValidatorMixin, ErrorParseMixin { showDialog( barrierDismissible: true, context: context, - builder: (_) => AgoraDialogClose( + builder: (context) => AgoraDialogClose( title: context.intl.app_proxy_unavailable, text: context.intl.app_proxy_unavailable_decr, ), diff --git a/lib/features/profile/models/reputation_import_view_model.dart b/lib/features/profile/models/reputation_import_view_model.dart index a78dbc49..105a9d45 100644 --- a/lib/features/profile/models/reputation_import_view_model.dart +++ b/lib/features/profile/models/reputation_import_view_model.dart @@ -145,6 +145,7 @@ class ReputationImportViewModel extends ViewModel with ValidatorMixin, ErrorPars username: username, platform: platform.name, ); + requesting = false; if (res.isRight) { reputations[platform.index] = reputations[platform.index].copyWith(verificationCode: res.right); diff --git a/lib/features/profile/screens/link_account_screen.dart b/lib/features/profile/screens/link_account_screen.dart index 39243879..9bcd438b 100644 --- a/lib/features/profile/screens/link_account_screen.dart +++ b/lib/features/profile/screens/link_account_screen.dart @@ -144,7 +144,9 @@ class LinkAccountScreen extends StatelessWidget with ClipboardMixin { ), const SizedBox(height: 12), Text( - I18n.of(context)!.reputation_import__step__code__message(reputationPlatform.title()), + model.reputationPlatform == ReputationPlatform.paxful + ? 'Put the code as a label on one of your offers, such that it\'s visible on your public profile. Once we\'ve verified the code, you can remove it.' + : I18n.of(context)!.reputation_import__step__code__message(reputationPlatform.title()), style: context.txtBodyMediumNeutral80, ), const SizedBox(height: 12), diff --git a/lib/features/trades/screens/trade_screen.dart b/lib/features/trades/screens/trade_screen.dart index c0181be8..9c8009ff 100644 --- a/lib/features/trades/screens/trade_screen.dart +++ b/lib/features/trades/screens/trade_screen.dart @@ -50,7 +50,11 @@ class TradeScreen extends StatefulWidget { } class _TradeScreenState extends State - with TickerProviderStateMixin, DateMixin, CountryInfoMixin, WidgetsBindingObserver { + with + TickerProviderStateMixin, + DateMixin, + CountryInfoMixin, + WidgetsBindingObserver { late final TradeViewModel _model; @override @@ -74,7 +78,8 @@ class _TradeScreenState extends State @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.resumed) { - _model.secureStorage.write(SecureStorageKey.openedTradeId, widget.tradeId ?? widget.tradeModel?.tradeId ?? ''); + _model.secureStorage.write(SecureStorageKey.openedTradeId, + widget.tradeId ?? widget.tradeModel?.tradeId ?? ''); } super.didChangeAppLifecycleState(state); } @@ -86,7 +91,8 @@ class _TradeScreenState extends State builder: (context, model, child) { return Scaffold( appBar: AgoraAppBar( - title: context.intl.document8722Sbtitle250Sbtrade(model.barTitle(), ''), + title: context.intl + .document8722Sbtitle250Sbtrade(model.barTitle(), ''), rightAction: TradePopupMenu(model: model), ), body: GestureDetector( @@ -159,14 +165,16 @@ class _TradeScreenState extends State TradeStepOne(model: model), TradeStepTwo(model: model), TradeStepThree(model: model), - model.tradeStatus.index < 6 || model.tradeStatus == TradeStatus.disputed + model.tradeStatus.index < 6 || + model.tradeStatus == TradeStatus.disputed ? Padding( padding: const EdgeInsets.fromLTRB(0, 0, 0, 8), child: BoxInfoWithLabel( label: context.intl.trade250Sbstatus250Sbescrowed, child: Text( context.intl - .trade250Sbstatus250Sbfunded8722Sbescrowed8722Sbtext8722Sb1(GetIt.I().appName), + .trade250Sbstatus250Sbfunded8722Sbescrowed8722Sbtext8722Sb1( + GetIt.I().appName), style: context.txtBodyXSmallN80, ), ), diff --git a/lib/features/trades/screens/widgets/trade_step_one.dart b/lib/features/trades/screens/widgets/trade_step_one.dart index 95a8e618..b54b95f7 100644 --- a/lib/features/trades/screens/widgets/trade_step_one.dart +++ b/lib/features/trades/screens/widgets/trade_step_one.dart @@ -38,7 +38,8 @@ class TradeStepOne extends StatelessWidget with DateMixin, ClipboardMixin { disposable: false, builder: (context, model, child) { if (model.isLocalTrade) { - if (model.tradeStatus == TradeStatus.notFunded && model.tradeForScreen.isSelling == true) { + if (model.tradeStatus == TradeStatus.notFunded && + model.tradeForScreen.isSelling == true) { return ContainerSurface5Radius12( child: Padding( padding: const EdgeInsets.fromLTRB(12, 14, 12, 14), @@ -46,7 +47,8 @@ class TradeStepOne extends StatelessWidget with DateMixin, ClipboardMixin { children: [ LineIconTextPrimary90( icon: const CircleWithNum(num: 1), - text: context.intl.trade250Sblocal250Sbstep8722Sb0250Sbseller250Sbtitle, + text: context.intl + .trade250Sblocal250Sbstep8722Sb0250Sbseller250Sbtitle, ), const SizedBox(height: 14), ContainerSurface3Radius12Border1( @@ -63,8 +65,8 @@ class TradeStepOne extends StatelessWidget with DateMixin, ClipboardMixin { ), const SizedBox(height: 12), LineDotText( - text: context - .intl.trade250Sblocal250Sbstep8722Sb0250Sbseller250Sbpress8722Sbfund8722Sbbtn, + text: context.intl + .trade250Sblocal250Sbstep8722Sb0250Sbseller250Sbpress8722Sbfund8722Sbbtn, ), ], ), @@ -77,20 +79,27 @@ class TradeStepOne extends StatelessWidget with DateMixin, ClipboardMixin { model.escrowed() ? const SizedBox() : Padding( - padding: const EdgeInsets.fromLTRB(0, 0, 12, 0), + padding: + const EdgeInsets.fromLTRB(0, 0, 12, 0), child: ButtonOutlinedWithIconP80( - title: context.intl.trade250Sbcancel8722Sbtrade8722Sbbtn, - insidePadding: const EdgeInsets.fromLTRB(10, 10, 16, 10), + title: context.intl + .trade250Sbcancel8722Sbtrade8722Sbbtn, + insidePadding: const EdgeInsets.fromLTRB( + 10, 10, 16, 10), icon: Icon( AgoraFont.check_circle_alt, - color: Theme.of(context).colorScheme.p80P70, + color: + Theme.of(context).colorScheme.p80P70, ), - onPressed: () => _cancelTradeDialog(model, context), + onPressed: () => + _cancelTradeDialog(model, context), ), ), ButtonFilledWithIconP80( - title: context.intl.trade250Sbfund8722Sbtrade8722Sbbtn, - insidePadding: const EdgeInsets.fromLTRB(10, 10, 16, 10), + title: + context.intl.trade250Sbfund8722Sbtrade8722Sbbtn, + insidePadding: + const EdgeInsets.fromLTRB(10, 10, 16, 10), icon: Icon( AgoraFont.check_circle_alt, color: Theme.of(context).colorScheme.primary20, @@ -105,8 +114,10 @@ class TradeStepOne extends StatelessWidget with DateMixin, ClipboardMixin { padding: const EdgeInsets.fromLTRB(0, 20, 0, 0), child: ButtonIconTextP70( iconData: AgoraFont.lock, - text: context.intl.trade250Sbenable8722Sbescrow8722Sbbtn, - onPressed: () => _enableEscrowDialog(model, context), + text: context + .intl.trade250Sbenable8722Sbescrow8722Sbbtn, + onPressed: () => + _enableEscrowDialog(model, context), ), ), ], @@ -114,56 +125,12 @@ class TradeStepOne extends StatelessWidget with DateMixin, ClipboardMixin { ), ); } - if (model.tradeStatus == TradeStatus.notFunded) { - return Padding( - padding: const EdgeInsets.fromLTRB(0, 0, 0, 8), - child: ContainerSurface5Radius12( - child: Padding( - padding: const EdgeInsets.fromLTRB(12, 14, 12, 14), - child: Column( - children: [ - LineIconTextPrimary90( - icon: const CircleWithNum(num: 1), - text: context.intl.trade250Sblocal250Sbstep8722Sb0250Sbbuyer250Sbwait8722Sbfor8722Sbfunding( - GetIt.I().appName, - ), - ), - const SizedBox(height: 14), - ContainerSurface3Radius12Border1( - child: Padding( - padding: const EdgeInsets.all(12), - child: Column( - children: [ - LineDotText( - text: context.intl.trade250Sblocal250Sbbuyer250Sbnot8722Sbescrowed, - ), - const SizedBox(height: 12), - LineDotText( - text: context.intl.trade250Sblocal250Sbbuyer250Sbnot8722Sbescrowed, - ), - ], - ), - ), - ), - const SizedBox(height: 12), - Padding( - padding: const EdgeInsets.fromLTRB(0, 0, 12, 0), - child: ButtonOutlinedWithIconP80( - title: context.intl.trade250Sbcancel8722Sbtrade8722Sbbtn, - insidePadding: const EdgeInsets.fromLTRB(10, 10, 16, 10), - icon: Icon( - AgoraFont.check_circle_alt, - color: Theme.of(context).colorScheme.p80P70, - ), - onPressed: () => _cancelTradeDialog(model, context), - ), - ), - ], - ), - ), - ), - ); + + if (model.tradeStatus == TradeStatus.notFunded && + model.tradeForScreen.isSelling == false) { + _buildNotFundedBuyer(context, model); } + return Padding( padding: const EdgeInsets.fromLTRB(0, 0, 0, 8), child: ContainerSurface5Radius12( @@ -171,15 +138,19 @@ class TradeStepOne extends StatelessWidget with DateMixin, ClipboardMixin { padding: const EdgeInsets.fromLTRB(12, 14, 12, 14), child: LineIconTextPrimary90( icon: const CircleWithIcon(icon: CupertinoIcons.check_mark), - text: context.intl.trade250Sblocal250Sbstep8722Sb0250Sbbuyer250Sbtitle, + text: context.intl + .trade250Sblocal250Sbstep8722Sb0250Sbbuyer250Sbtitle, ), ), ), ); } - if (model.tradeStatus.index > 5 && model.tradeStatus != TradeStatus.disputed) { + + if (model.tradeStatus.index > 5 && + model.tradeStatus != TradeStatus.disputed) { return const SizedBox(); } + return Padding( padding: const EdgeInsets.fromLTRB(0, 0, 0, 8), child: model.tradeForScreen.isSelling! @@ -190,7 +161,8 @@ class TradeStepOne extends StatelessWidget with DateMixin, ClipboardMixin { } Widget _buildFirstStepSellerView(TradeViewModel model, BuildContext context) { - return model.tradeStatus.index < 3 || model.tradeStatus == TradeStatus.disputed + return model.tradeStatus.index < 3 || + model.tradeStatus == TradeStatus.disputed ? ContainerSurface5Radius12( child: Padding( padding: const EdgeInsets.fromLTRB(12, 14, 12, 14), @@ -198,7 +170,8 @@ class TradeStepOne extends StatelessWidget with DateMixin, ClipboardMixin { children: [ LineIconTextPrimary90( icon: const CircleWithNum(num: 1), - text: context.intl.agoradesk250Sbtrade250Sboption250Sbcall250Sbstep8722Sbfive250Sbseller250Sbtitle, + text: context.intl + .agoradesk250Sbtrade250Sboption250Sbcall250Sbstep8722Sbfive250Sbseller250Sbtitle, ), const SizedBox(height: 14), ContainerSurface3Radius12Border1( @@ -207,48 +180,62 @@ class TradeStepOne extends StatelessWidget with DateMixin, ClipboardMixin { child: Column( children: [ LineDotText( - text: context.intl.trade250Sbamount8722Sbto8722Sbreceive( - '${model.tradeForScreen.amount} ${model.tradeForScreen.currency}'), + text: context.intl + .trade250Sbamount8722Sbto8722Sbreceive( + '${model.tradeForScreen.amount} ${model.tradeForScreen.currency}'), ), const SizedBox(height: 12), LineDotText( - text: context.intl.trade250Sbbuyer8722Sbhasnt8722Sbcompleted8722Sbpayment8722Sbtext( - model.minutesBeforeCancel), + text: context.intl + .trade250Sbbuyer8722Sbhasnt8722Sbcompleted8722Sbpayment8722Sbtext( + model.minutesBeforeCancel), ), const SizedBox(height: 12), LineDotText( - text: context.intl.app_trade_option_payment_receiver_cancel_notice, + text: context.intl + .app_trade_option_payment_receiver_cancel_notice, ), const SizedBox(height: 12), Row( - mainAxisAlignment: model.displayCancelStepOneSeller() - ? MainAxisAlignment.spaceBetween - : MainAxisAlignment.center, + mainAxisAlignment: + model.displayCancelStepOneSeller() + ? MainAxisAlignment.spaceBetween + : MainAxisAlignment.center, children: [ model.displayCancelStepOneSeller() ? ButtonOutlinedWithIconP80( title: context.intl.cancel, - insidePadding: const EdgeInsets.fromLTRB(16, 10, 22, 10), + insidePadding: const EdgeInsets.fromLTRB( + 16, 10, 22, 10), icon: Icon( AgoraFont.x_circle, - color: Theme.of(context).colorScheme.p80P70, + color: Theme.of(context) + .colorScheme + .p80P70, ), - onPressed: () => _cancelTradeSellerDialog(context, model), + onPressed: () => _cancelTradeSellerDialog( + context, model), ) : const SizedBox(), ButtonFilledWithIconP80( - title: context.intl.trade250Sbrelease8722Sbmonero8722Sbbtn, - insidePadding: const EdgeInsets.fromLTRB(16, 10, 16, 10), + title: context.intl + .trade250Sbrelease8722Sbmonero8722Sbbtn, + insidePadding: + const EdgeInsets.fromLTRB(16, 10, 16, 10), icon: Icon( AgoraFont.check_circle_alt, - color: Theme.of(context).colorScheme.primary20, + color: + Theme.of(context).colorScheme.primary20, ), onPressed: () { showDialog( barrierDismissible: true, context: context, - barrierColor: Theme.of(context).colorScheme.dialogOverlay, - builder: (_) => FinalizeTradeDialog(tradeModel: model), + barrierColor: Theme.of(context) + .colorScheme + .dialogOverlay, + builder: (_) => + FinalizeTradeDialog(tradeModel: model), ); }, ), @@ -267,14 +254,20 @@ class TradeStepOne extends StatelessWidget with DateMixin, ClipboardMixin { padding: const EdgeInsets.fromLTRB(12, 14, 12, 14), child: LineIconTextPrimary90( icon: const CircleWithIcon(icon: CupertinoIcons.check_mark), - text: context.intl.agoradesk250Sbtrade250Sboption250Sbcall250Sbstep8722Sbfive250Sbseller250Sbtitle, + text: context.intl + .agoradesk250Sbtrade250Sboption250Sbcall250Sbstep8722Sbfive250Sbseller250Sbtitle, ), ), ); } Widget _buildFirstStepBuyerView(TradeViewModel model, BuildContext context) { - return model.tradeStatus.index < 3 || model.tradeStatus == TradeStatus.disputed + if (model.tradeStatus == TradeStatus.notFunded && + model.tradeForScreen.isSelling == false) { + return _buildNotFundedBuyer(context, model); + } + return model.tradeStatus.index < 3 || + model.tradeStatus == TradeStatus.disputed ? ContainerSurface5Radius12( child: Padding( padding: const EdgeInsets.fromLTRB(12, 14, 12, 14), @@ -282,7 +275,8 @@ class TradeStepOne extends StatelessWidget with DateMixin, ClipboardMixin { children: [ LineIconTextPrimary90( icon: const CircleWithNum(num: 1), - text: context.intl.agoradesk250Sbtrade250Sboption250Sbcall250Sbstep8722Sbfive250Sbbuyer250Sbtitle, + text: context.intl + .agoradesk250Sbtrade250Sboption250Sbcall250Sbstep8722Sbfive250Sbbuyer250Sbtitle, ), const SizedBox(height: 14), ContainerSurface3Radius12Border1( @@ -304,12 +298,14 @@ class TradeStepOne extends StatelessWidget with DateMixin, ClipboardMixin { ), const SizedBox(height: 12), LineDotText( - text: context.intl.trade250Sbsettlement8722Sbfees8722Sbnotice, + text: context.intl + .trade250Sbsettlement8722Sbfees8722Sbnotice, ), const SizedBox(height: 12), LineDotText( - text: context.intl.trade250Sbbuyer8722Sbinstruction8722Sbstep8722Sbtwo8722Sbtext8722Sb1( - model.minutesBeforeCancel), + text: context.intl + .trade250Sbbuyer8722Sbinstruction8722Sbstep8722Sbtwo8722Sbtext8722Sb1( + model.minutesBeforeCancel), ), const SizedBox(height: 12), LineDotText( @@ -317,7 +313,8 @@ class TradeStepOne extends StatelessWidget with DateMixin, ClipboardMixin { ), const SizedBox(height: 12), AgoraBoxOpenCloseLineS5S3( - title: context.intl.trade250Sbbuyer8722Sbsettlement8722Sbaddress8722Sbwarning250Sbtoggle, + title: context.intl + .trade250Sbbuyer8722Sbsettlement8722Sbaddress8722Sbwarning250Sbtoggle, icon: Icon( AgoraFont.check_circle_alt, color: Theme.of(context).colorScheme.p80P70, @@ -326,9 +323,12 @@ class TradeStepOne extends StatelessWidget with DateMixin, ClipboardMixin { content: SelectableText( model.tradeForScreen.buyerSettlementAddress!, style: context.txtBodyXSmallN80N30, - onTap: () => copyToClipboard(model.tradeForScreen.buyerSettlementAddress!, context), + onTap: () => copyToClipboard( + model.tradeForScreen.buyerSettlementAddress!, + context), ), - description: context.intl.trade250Sbbuyer8722Sbsettlement8722Sbaddress8722Sbwarning, + description: context.intl + .trade250Sbbuyer8722Sbsettlement8722Sbaddress8722Sbwarning, ), const SizedBox(height: 12), AgoraBoxOpenCloseLineS5S3( @@ -341,37 +341,45 @@ class TradeStepOne extends StatelessWidget with DateMixin, ClipboardMixin { content: SelectableText( model.paymentDetailsText(context), style: context.txtBodyXSmallN80N30, - onTap: () => copyToClipboard(model.paymentDetailsText(context), context), + onTap: () => copyToClipboard( + model.paymentDetailsText(context), context), ), ), const SizedBox(height: 12), Row( - mainAxisAlignment: model.tradeForScreen.paymentCompletedAt != null - ? MainAxisAlignment.center - : MainAxisAlignment.spaceBetween, + mainAxisAlignment: + model.tradeForScreen.paymentCompletedAt != null + ? MainAxisAlignment.center + : MainAxisAlignment.spaceBetween, children: [ model.tradeForScreen.paymentCompletedAt != null ? const SizedBox() : ButtonFilledWithIconP80( - title: context.intl.trade250Sbi8722Sbhave8722Sbpaid8722Sbbtn, - insidePadding: const EdgeInsets.fromLTRB(16, 10, 16, 10), + title: context.intl + .trade250Sbi8722Sbhave8722Sbpaid8722Sbbtn, + insidePadding: const EdgeInsets.fromLTRB( + 16, 10, 16, 10), loading: model.markingAsPaid, icon: Icon( AgoraFont.check_circle_alt, color: context.colP40, ), - onPressed: () => _markAsPaidDialog(context, model), + onPressed: () => + _markAsPaidDialog(context, model), ), const SizedBox(width: 10), ButtonOutlinedWithIconP80( - title: context.intl.trade250Sbcancel8722Sbtrade8722Sbbtn, - insidePadding: const EdgeInsets.fromLTRB(14, 10, 14, 10), + title: context + .intl.trade250Sbcancel8722Sbtrade8722Sbbtn, + insidePadding: + const EdgeInsets.fromLTRB(14, 10, 14, 10), loading: model.cancelingTrade, icon: Icon( AgoraFont.x_circle, color: context.colP80, ), - onPressed: () => _cancelTradeBuyerDialog(context, model), + onPressed: () => + _cancelTradeBuyerDialog(context, model), ) ], ), @@ -388,12 +396,66 @@ class TradeStepOne extends StatelessWidget with DateMixin, ClipboardMixin { padding: const EdgeInsets.fromLTRB(12, 14, 12, 14), child: LineIconTextPrimary90( icon: const CircleWithIcon(icon: CupertinoIcons.check_mark), - text: context.intl.agoradesk250Sbtrade250Sboption250Sbcall250Sbstep8722Sbfive250Sbbuyer250Sbtitle, + text: context.intl + .agoradesk250Sbtrade250Sboption250Sbcall250Sbstep8722Sbfive250Sbbuyer250Sbtitle, ), ), ); } + Widget _buildNotFundedBuyer(BuildContext context, TradeViewModel model) { + return Padding( + padding: const EdgeInsets.fromLTRB(0, 0, 0, 8), + child: ContainerSurface5Radius12( + child: Padding( + padding: const EdgeInsets.fromLTRB(12, 14, 12, 14), + child: Column( + children: [ + LineIconTextPrimary90( + icon: const CircleWithNum(num: 1), + text: model.isLocalTrade + ? context.intl + .trade250Sblocal250Sbstep8722Sb0250Sbbuyer250Sbwait8722Sbfor8722Sbfunding( + GetIt.I().appName, + ) + : 'Waiting for the seller to fund the trade.', + ), + const SizedBox(height: 14), + ContainerSurface3Radius12Border1( + child: Padding( + padding: const EdgeInsets.all(12), + child: Column( + children: [ + LineDotText( + text: model.isLocalTrade + ? context.intl + .trade250Sblocal250Sbbuyer250Sbnot8722Sbescrowed + : 'Do not pay now! The trade can be canceled anytime until the seller accepts.', + ), + ], + ), + ), + ), + const SizedBox(height: 12), + Padding( + padding: const EdgeInsets.fromLTRB(0, 0, 12, 0), + child: ButtonOutlinedWithIconP80( + title: context.intl.trade250Sbcancel8722Sbtrade8722Sbbtn, + insidePadding: const EdgeInsets.fromLTRB(10, 10, 16, 10), + icon: Icon( + AgoraFont.check_circle_alt, + color: Theme.of(context).colorScheme.p80P70, + ), + onPressed: () => _cancelTradeDialog(model, context), + ), + ), + ], + ), + ), + ), + ); + } + void _cancelTradeSellerDialog(BuildContext context, TradeViewModel model) { showDialog( barrierDismissible: true, @@ -423,7 +485,8 @@ class TradeStepOne extends StatelessWidget with DateMixin, ClipboardMixin { title: context.intl.trade250Sbcancel8722Sbtrade8722Sbbtn, content: Text(context.intl.app_cancel_trade_message), filledButtonTitle: context.intl.trade250Sbcancel8722Sbtrade8722Sbbtn, - outlineButtonTitle: context.intl.post8722Sbad250Sberror250Sbdialog8722Sbbtn, + outlineButtonTitle: + context.intl.post8722Sbad250Sberror250Sbdialog8722Sbbtn, onPressedOutline: () => Navigator.of(context).pop(), onPressedFilled: () => model.cancelTrade(), loadingFilled: model.cancelingTrade, @@ -437,11 +500,15 @@ class TradeStepOne extends StatelessWidget with DateMixin, ClipboardMixin { context: context, barrierColor: Theme.of(context).colorScheme.dialogOverlay, builder: (_) => DialogOutlineAndFilledButtons( - title: context.intl.trade250Sbdialog8722Sbconfirm8722Sbpayment8722Sbtitle, - content: Text( - context.intl.trade250Sbdialog8722Sbconfirm8722Sbpayment8722Sbtext(model.tradeForScreen.buyer.username!)), - filledButtonTitle: context.intl.trade250Sbdialog250Sbconfirm8722Sbcancel8722Sbbtn, - outlineButtonTitle: context.intl.post8722Sbad250Sberror250Sbdialog8722Sbbtn, + title: + context.intl.trade250Sbdialog8722Sbconfirm8722Sbpayment8722Sbtitle, + content: Text(context.intl + .trade250Sbdialog8722Sbconfirm8722Sbpayment8722Sbtext( + model.tradeForScreen.buyer.username!)), + filledButtonTitle: + context.intl.trade250Sbdialog250Sbconfirm8722Sbcancel8722Sbbtn, + outlineButtonTitle: + context.intl.post8722Sbad250Sberror250Sbdialog8722Sbbtn, onPressedFilled: () => model.markAsPaid(), onPressedOutline: () => Navigator.of(context).pop(), loadingFilled: model.markingAsPaid, @@ -458,7 +525,8 @@ class TradeStepOne extends StatelessWidget with DateMixin, ClipboardMixin { title: context.intl.trade250Sbcancel8722Sbtrade8722Sbbtn, content: Text(context.intl.app_cancel_trade_message), filledButtonTitle: context.intl.trade250Sbcancel8722Sbtrade8722Sbbtn, - outlineButtonTitle: context.intl.post8722Sbad250Sberror250Sbdialog8722Sbbtn, + outlineButtonTitle: + context.intl.post8722Sbad250Sberror250Sbdialog8722Sbbtn, onPressedOutline: () => AutoRouter.of(context).pop(), onPressedFilled: () => model.cancelTrade(), loadingFilled: model.cancelingTrade, @@ -473,9 +541,12 @@ class TradeStepOne extends StatelessWidget with DateMixin, ClipboardMixin { barrierColor: Theme.of(context).colorScheme.dialogOverlay, builder: (_) => DialogOutlineAndFilledButtons( title: context.intl.trade250Sbdialog250Sbconfirm8722Sbescrow8722Sbtitle, - content: Text(context.intl.trade250Sbdialog250Sbconfirm8722Sbescrow8722Sbtext), - filledButtonTitle: context.intl.trade250Sbdialog250Sbconfirm8722Sbcancel8722Sbbtn, - outlineButtonTitle: context.intl.post8722Sbad250Sberror250Sbdialog8722Sbbtn, + content: Text( + context.intl.trade250Sbdialog250Sbconfirm8722Sbescrow8722Sbtext), + filledButtonTitle: + context.intl.trade250Sbdialog250Sbconfirm8722Sbcancel8722Sbbtn, + outlineButtonTitle: + context.intl.post8722Sbad250Sberror250Sbdialog8722Sbbtn, onPressedOutline: () => AutoRouter.of(context).pop(), onPressedFilled: () => model.enableEscrow(), loadingFilled: model.enablingEscrow, @@ -489,11 +560,15 @@ class TradeStepOne extends StatelessWidget with DateMixin, ClipboardMixin { context: context, barrierColor: Theme.of(context).colorScheme.dialogOverlay, builder: (_) => DialogOutlineAndFilledButtons( - title: context.intl.trade250Sbdialog250Sbfunding8722Sbconfirm8722Sbtitle, - content: - Text(context.intl.trade250Sbdialog250Sbfunding8722Sbconfirm8722Sbtext(GetIt.I().appName)), - filledButtonTitle: context.intl.trade250Sbdialog250Sbconfirm8722Sbcancel8722Sbbtn, - outlineButtonTitle: context.intl.post8722Sbad250Sberror250Sbdialog8722Sbbtn, + title: + context.intl.trade250Sbdialog250Sbfunding8722Sbconfirm8722Sbtitle, + content: Text(context.intl + .trade250Sbdialog250Sbfunding8722Sbconfirm8722Sbtext( + GetIt.I().appName)), + filledButtonTitle: + context.intl.trade250Sbdialog250Sbconfirm8722Sbcancel8722Sbbtn, + outlineButtonTitle: + context.intl.post8722Sbad250Sberror250Sbdialog8722Sbbtn, onPressedOutline: () => AutoRouter.of(context).pop(), onPressedFilled: () => model.fundTrade(), loadingFilled: model.enablingEscrow, diff --git a/pubspec.lock b/pubspec.lock index a8fd9e67..79c9c169 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -165,26 +165,26 @@ packages: dependency: "direct main" description: name: cached_network_image - sha256: fd3d0dc1d451f9a252b32d95d3f0c3c487bc41a75eba2e6097cb0b9c71491b15 + sha256: f98972704692ba679db144261172a8e20feb145636c617af0eb4022132a6797f url: "https://pub.dev" source: hosted - version: "3.2.3" + version: "3.3.0" cached_network_image_platform_interface: dependency: transitive description: name: cached_network_image_platform_interface - sha256: bb2b8403b4ccdc60ef5f25c70dead1f3d32d24b9d6117cfc087f496b178594a7 + sha256: "56aa42a7a01e3c9db8456d9f3f999931f1e05535b5a424271e9a38cabf066613" url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "3.0.0" cached_network_image_web: dependency: transitive description: name: cached_network_image_web - sha256: b8eb814ebfcb4dea049680f8c1ffb2df399e4d03bf7a352c775e26fa06e02fa0 + sha256: "759b9a9f8f6ccbb66c185df805fac107f05730b1dab9c64626d1008cca532257" url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "1.1.0" characters: dependency: transitive description: @@ -237,10 +237,10 @@ packages: dependency: "direct main" description: name: collection - sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.2" + version: "1.18.0" connectivity_plus: dependency: "direct main" description: @@ -567,14 +567,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.0" - flutter_blurhash: - dependency: transitive - description: - name: flutter_blurhash - sha256: "05001537bd3fac7644fa6558b09ec8c0a3f2eba78c0765f88912882b1331a5c6" - url: "https://pub.dev" - source: hosted - version: "0.7.0" flutter_cache_manager: dependency: transitive description: @@ -1163,10 +1155,10 @@ packages: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" mime: dependency: transitive description: @@ -1211,10 +1203,10 @@ packages: dependency: transitive description: name: octo_image - sha256: "107f3ed1330006a3bea63615e81cf637433f5135a52466c7caa0e7152bca9143" + sha256: "45b40f99622f11901238e18d48f5f12ea36426d8eced9f4cbf58479c7aa2430d" url: "https://pub.dev" source: hosted - version: "1.0.2" + version: "2.0.0" overlay_support: dependency: "direct main" description: @@ -1736,10 +1728,10 @@ packages: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" state_notifier: dependency: transitive description: @@ -1768,10 +1760,10 @@ packages: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" stream_transform: dependency: transitive description: @@ -1808,26 +1800,26 @@ packages: dependency: transitive description: name: test - sha256: "13b41f318e2a5751c3169137103b60c584297353d4b1761b66029bae6411fe46" + sha256: a1f7595805820fcc05e5c52e3a231aedd0b72972cb333e8c738a8b1239448b6f url: "https://pub.dev" source: hosted - version: "1.24.3" + version: "1.24.9" test_api: dependency: transitive description: name: test_api - sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.6.0" + version: "0.6.1" test_core: dependency: transitive description: name: test_core - sha256: "99806e9e6d95c7b059b7a0fc08f07fc53fabe54a829497f0d9676299f1e8637e" + sha256: a757b14fc47507060a162cc2530d9a4a2f92f5100a952c7443b5cad5ef5b106a url: "https://pub.dev" source: hosted - version: "0.5.3" + version: "0.5.9" timeago: dependency: "direct main" description: @@ -2080,10 +2072,10 @@ packages: dependency: transitive description: name: web - sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 url: "https://pub.dev" source: hosted - version: "0.1.4-beta" + version: "0.3.0" web_socket_channel: dependency: transitive description: @@ -2141,5 +2133,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.1.0-185.0.dev <4.0.0" + dart: ">=3.2.0-194.0.dev <4.0.0" flutter: ">=3.13.0" diff --git a/pubspec.yaml b/pubspec.yaml index 77a32a22..e0e904b5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: Person-to-person platform to allow anyone to trade their local curr publish_to: 'none' -version: 1.1.14+110 +version: 1.1.15+111 environment: sdk: ">=3.0.0 <4.0.0" @@ -33,7 +33,7 @@ dependencies: collection: ^1.15.0 rating_dialog: ^2.0.3 visibility_detector: ^0.3.3 - cached_network_image: ^3.2.0 + cached_network_image: ^3.3.0 json_annotation: ^4.4.0 share_plus: ^7.0.0 hive: ^2.2.3