diff --git a/lib/screens/settings_screen.dart b/lib/screens/settings_screen.dart index a2aedf5..5364b15 100644 --- a/lib/screens/settings_screen.dart +++ b/lib/screens/settings_screen.dart @@ -53,18 +53,21 @@ class SettingsScreen extends HookConsumerWidget { maxLines: 10, ), Gap(20), - if (signedInUser == null) SignInButton(minimal: true), + if (signedInUser == null || + signedInUser.settings.value!.signInMethod != SignInMethod.nip55) + Column( + children: [ + Text( + 'To send a message you must be signed in with an external signer like Amber.', + softWrap: true, + style: TextStyle( + color: Colors.red[300], fontWeight: FontWeight.bold)), + Gap(5), + SignInButton(minimal: true, requireNip55: true), + ], + ), if (signedInUser != null && - signedInUser.settings.value!.signInMethod != - SignInMethod.nip55 || - !amberSigner.isAvailable) - Text( - 'To share feedback, you must be signed in with Amber. You can also message us on nostr!', - style: TextStyle( - color: Colors.red[300], fontWeight: FontWeight.bold)), - if (signedInUser != null && - signedInUser.settings.value!.signInMethod == SignInMethod.nip55 && - amberSigner.isAvailable) + signedInUser.settings.value!.signInMethod == SignInMethod.nip55) AsyncButtonBuilder( loadingWidget: SmallCircularProgressIndicator(), onPressed: () async { diff --git a/lib/utils/extensions.dart b/lib/utils/extensions.dart index 2337154..ba42cf6 100644 --- a/lib/utils/extensions.dart +++ b/lib/utils/extensions.dart @@ -5,6 +5,7 @@ import 'package:dart_emoji/dart_emoji.dart'; import 'package:flutter/material.dart'; import 'package:flutter_data/flutter_data.dart'; import 'package:go_router/go_router.dart'; +import 'package:intl/intl.dart'; import 'package:toastification/toastification.dart'; import 'package:zapstore/models/app.dart'; @@ -160,6 +161,8 @@ extension TextExt on Text { const kZapstoreAppIdentifier = 'dev.zapstore.app'; +final kNumberFormatter = NumberFormat('#,###'); + // stream utils Stream> bufferByTime(Stream source, Duration duration) { diff --git a/lib/widgets/sign_in_container.dart b/lib/widgets/sign_in_container.dart index 96051b9..b25deef 100644 --- a/lib/widgets/sign_in_container.dart +++ b/lib/widgets/sign_in_container.dart @@ -16,17 +16,23 @@ import 'package:zapstore/widgets/rounded_image.dart'; class SignInButton extends ConsumerWidget { final bool minimal; final String label; - final bool publicKeyAllowed; + final bool requireNip55; + SignInButton({ super.key, this.minimal = false, this.label = 'Sign in', - this.publicKeyAllowed = true, + this.requireNip55 = false, }); @override Widget build(BuildContext context, WidgetRef ref) { - final user = ref.watch(signedInUserProvider); + var user = ref.watch(signedInUserProvider); + final signedInWithPubkey = + user != null && user.settings.value!.signInMethod != SignInMethod.nip55; + if (requireNip55 && signedInWithPubkey) { + user = null; + } return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -71,7 +77,7 @@ class SignInButton extends ConsumerWidget { style: TextStyle(fontWeight: FontWeight.bold), ), content: SignInDialogBox( - publicKeyAllowed: publicKeyAllowed, + publicKeyAllowed: !requireNip55, ), ), ); diff --git a/lib/widgets/zap_button.dart b/lib/widgets/zap_button.dart index 53346cb..8b37983 100644 --- a/lib/widgets/zap_button.dart +++ b/lib/widgets/zap_button.dart @@ -1,9 +1,12 @@ import 'package:async_button_builder/async_button_builder.dart'; +import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:gap/gap.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:zapstore/main.data.dart'; import 'package:zapstore/models/app.dart'; +import 'package:zapstore/models/settings.dart'; import 'package:zapstore/models/user.dart'; import 'package:zapstore/navigation/app_initializer.dart'; import 'package:zapstore/screens/settings_screen.dart'; @@ -64,61 +67,77 @@ class ZapButton extends HookConsumerWidget { builder: (context) { return AlertDialog( title: Text('Zap this release').bold, - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Consumer( - builder: (context, ref, _) { - final signedInUser = - ref.watch(signedInUserProvider); + content: SizedBox( + width: double.maxFinite, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Consumer( + builder: (context, ref, _) { + final signedInUser = + ref.watch(signedInUserProvider); - if (signedInUser == null) { - return Column( - children: [ - Text( - '⚠️ If you do not sign in, you will be zapping anonymously'), - SignInButton( - publicKeyAllowed: false, - minimal: true, - ), - ], - ); - } - return Container(); - }, - ), - TextField( - controller: amountController, - keyboardType: TextInputType.number, - decoration: - InputDecoration(hintText: 'Enter amount in sats'), - ), - Gap(20), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ElevatedButton( - onPressed: () => amountController.text = '21', - child: Text('⚡️21'), + if (signedInUser == null || + signedInUser.settings.value!.signInMethod != + SignInMethod.nip55) { + return Column( + children: [ + Text( + '⚠️ If you do not sign in (with an external signer like Amber), you will be zapping anonymously'), + SignInButton( + requireNip55: true, + minimal: true, + ), + ], + ); + } + return Container(); + }, + ), + TextField( + controller: amountController, + keyboardType: TextInputType.number, + decoration: InputDecoration( + hintText: 'Enter amount in sats', ), - Gap(3), - ElevatedButton( - onPressed: () => amountController.text = '210', - child: Text('⚡️210'), + inputFormatters: [ + FilteringTextInputFormatter.digitsOnly + ], + ), + Gap(20), + SizedBox( + width: double.maxFinite, + child: Wrap( + alignment: WrapAlignment.start, + spacing: 4, + children: [ + ('🤙 21', 21), + ('💜 210', 210), + ('🤩 420', 420), + ('🚀 2100', 2100), + ('💯 10K', 10000), + ('💎 21K', 21000), + ] + .map( + (r) => ElevatedButton( + onPressed: () => amountController.text = + r.$2.toString(), + child: AutoSizeText( + r.$1, + style: TextStyle(fontSize: 12.5), + ), + ), + ) + .toList(), ), - Gap(3), - ElevatedButton( - onPressed: () => amountController.text = '2100', - child: Text('⚡️2100'), - ), - ], - ), - TextField( - controller: commentController, - decoration: InputDecoration( - hintText: 'Add a comment (optional)'), - ), - ], + ), + TextField( + controller: commentController, + decoration: InputDecoration( + hintText: 'Add a comment (optional)'), + ), + ], + ), ), actions: [ TextButton( diff --git a/lib/widgets/zap_receipts.dart b/lib/widgets/zap_receipts.dart index f22e8ce..e19e0c0 100644 --- a/lib/widgets/zap_receipts.dart +++ b/lib/widgets/zap_receipts.dart @@ -47,7 +47,8 @@ class ZapReceipts extends HookConsumerWidget { } final receipts = zapReceipts.value!; - final totalAmountInSats = receipts.fold(0, (acc, e) => acc + e.amount); + final satsAmount = receipts.fold(0, (acc, e) => acc + e.amount); + final formattedSatsAmount = kNumberFormatter.format(satsAmount); final zapperIds = receipts.map((r) => r.senderPubkey).toSet(); final zappers = ref.users.findManyLocalByIds(zapperIds); @@ -60,14 +61,14 @@ class ZapReceipts extends HookConsumerWidget { children: [ TextSpan(text: '⚡'), TextSpan( - text: ' $totalAmountInSats sats ', + text: ' $formattedSatsAmount sats ', style: TextStyle(fontWeight: FontWeight.bold)), TextSpan(text: 'zapped by'), ], ), users: zappers, signedInUser: signedInUser, - maxUsersToDisplay: 5, + maxUsersToDisplay: 6, ), ); }