mirror of
https://github.com/zapstore/zapstore.git
synced 2026-10-05 20:48:24 +00:00
Minor fixes, app stacks screen
This commit is contained in:
+17
-3
@@ -6,6 +6,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:models/models.dart';
|
||||
import 'package:zapstore/screens/main_scaffold.dart';
|
||||
import 'package:zapstore/screens/app_detail_screen.dart';
|
||||
import 'package:zapstore/screens/all_stacks_screen.dart';
|
||||
import 'package:zapstore/screens/app_stack_screen.dart';
|
||||
import 'package:zapstore/screens/user_screen.dart';
|
||||
import 'package:zapstore/screens/search_screen.dart';
|
||||
@@ -84,6 +85,19 @@ GoRoute _stackDetailRoute() {
|
||||
);
|
||||
}
|
||||
|
||||
/// Helper to build all-stacks route
|
||||
GoRoute _allStacksRoute() {
|
||||
return GoRoute(
|
||||
path: 'stacks',
|
||||
pageBuilder: (context, state) {
|
||||
return _noTransitionPage(
|
||||
state: state,
|
||||
child: const AllStacksScreen(),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// Helper to build user route
|
||||
GoRoute _userRoute() {
|
||||
return GoRoute(
|
||||
@@ -123,7 +137,7 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||
state: state,
|
||||
child: const SearchScreen(),
|
||||
),
|
||||
routes: [_appDetailRoute(), _stackDetailRoute(), _userRoute()],
|
||||
routes: [_appDetailRoute(), _stackDetailRoute(), _allStacksRoute(), _userRoute()],
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -136,7 +150,7 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||
state: state,
|
||||
child: const UpdatesScreen(),
|
||||
),
|
||||
routes: [_appDetailRoute(), _stackDetailRoute(), _userRoute()],
|
||||
routes: [_appDetailRoute(), _stackDetailRoute(), _allStacksRoute(), _userRoute()],
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -149,7 +163,7 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||
state: state,
|
||||
child: const ProfileScreen(),
|
||||
),
|
||||
routes: [_appDetailRoute(), _stackDetailRoute(), _userRoute()],
|
||||
routes: [_appDetailRoute(), _stackDetailRoute(), _allStacksRoute(), _userRoute()],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:models/models.dart';
|
||||
import 'package:zapstore/services/package_manager/package_manager.dart';
|
||||
import 'package:zapstore/utils/extensions.dart';
|
||||
import 'package:zapstore/widgets/app_stack_container.dart';
|
||||
|
||||
const int _kPageSize = 10;
|
||||
|
||||
class AllStacksScreen extends HookConsumerWidget {
|
||||
const AllStacksScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final scrollController = useScrollController();
|
||||
final visibleCount = useState(_kPageSize);
|
||||
|
||||
final signedInPubkey = ref.watch(Signer.activePubkeyProvider);
|
||||
final platform = ref.read(packageManagerProvider.notifier).platform;
|
||||
|
||||
final appStacksState = ref.watch(
|
||||
query<AppStack>(
|
||||
limit: 100,
|
||||
tags: {
|
||||
'#f': {platform},
|
||||
},
|
||||
source: const LocalAndRemoteSource(relays: 'social'),
|
||||
subscriptionPrefix: 'app-all-stacks',
|
||||
schemaFilter: appStackEventFilter,
|
||||
),
|
||||
);
|
||||
|
||||
final contactListState = signedInPubkey != null
|
||||
? ref.watch(
|
||||
query<ContactList>(
|
||||
authors: {signedInPubkey},
|
||||
limit: 1,
|
||||
source: const LocalAndRemoteSource(
|
||||
relays: 'social',
|
||||
stream: false,
|
||||
cachedFor: Duration(hours: 1),
|
||||
),
|
||||
subscriptionPrefix: 'app-all-stacks-contacts',
|
||||
),
|
||||
)
|
||||
: null;
|
||||
|
||||
final followingPubkeys =
|
||||
contactListState?.models.firstOrNull?.followingPubkeys;
|
||||
|
||||
final allStacks = switch (appStacksState) {
|
||||
StorageData(:final models) => models.toList(),
|
||||
_ => <AppStack>[],
|
||||
};
|
||||
|
||||
final sortedStacks = _sortStacks(
|
||||
allStacks,
|
||||
signedInPubkey: signedInPubkey,
|
||||
followingPubkeys: followingPubkeys,
|
||||
);
|
||||
|
||||
final displayedStacks = sortedStacks.take(visibleCount.value).toList();
|
||||
final hasMore = visibleCount.value < sortedStacks.length;
|
||||
|
||||
// Batch load author profiles for displayed stacks
|
||||
final authorPubkeys = displayedStacks.map((s) => s.event.pubkey).toSet();
|
||||
final authorsState = authorPubkeys.isNotEmpty
|
||||
? ref.watch(
|
||||
query<Profile>(
|
||||
authors: authorPubkeys,
|
||||
source: const LocalAndRemoteSource(
|
||||
relays: {'social', 'vertex'},
|
||||
cachedFor: Duration(hours: 2),
|
||||
),
|
||||
subscriptionPrefix: 'app-all-stacks-authors',
|
||||
),
|
||||
)
|
||||
: null;
|
||||
final authorsMap = {
|
||||
for (final profile in authorsState?.models ?? <Profile>[])
|
||||
profile.pubkey: profile,
|
||||
};
|
||||
final isAuthorsLoading = authorsState is StorageLoading;
|
||||
|
||||
// Batch load preview apps for displayed stacks
|
||||
final allPreviewIdentifiers = <String>{};
|
||||
final stackPreviewIds = <String, List<String>>{};
|
||||
for (final stack in displayedStacks) {
|
||||
final ids = getPreviewIdentifiers(stack);
|
||||
stackPreviewIds[stack.id] = ids;
|
||||
allPreviewIdentifiers.addAll(ids);
|
||||
}
|
||||
|
||||
final previewAppsState = allPreviewIdentifiers.isNotEmpty
|
||||
? ref.watch(
|
||||
query<App>(
|
||||
tags: {'#d': allPreviewIdentifiers},
|
||||
source: const LocalAndRemoteSource(
|
||||
relays: 'AppCatalog',
|
||||
stream: false,
|
||||
),
|
||||
subscriptionPrefix: 'app-all-stacks-preview-apps',
|
||||
),
|
||||
)
|
||||
: null;
|
||||
|
||||
final appsMap = {
|
||||
for (final app in previewAppsState?.models ?? <App>[])
|
||||
app.identifier: app,
|
||||
};
|
||||
|
||||
// Infinite scroll: load more when near bottom
|
||||
useEffect(() {
|
||||
void onScroll() {
|
||||
if (!hasMore) return;
|
||||
if (scrollController.position.pixels >=
|
||||
scrollController.position.maxScrollExtent - 300) {
|
||||
visibleCount.value = (visibleCount.value + _kPageSize).clamp(
|
||||
0,
|
||||
sortedStacks.length,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
scrollController.addListener(onScroll);
|
||||
return () => scrollController.removeListener(onScroll);
|
||||
}, [scrollController, sortedStacks.length, hasMore]);
|
||||
|
||||
return Scaffold(
|
||||
body: CustomScrollView(
|
||||
controller: scrollController,
|
||||
slivers: [
|
||||
SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 16, 16, 8),
|
||||
child: Text('App Stacks', style: context.textTheme.headlineMedium),
|
||||
),
|
||||
),
|
||||
if (appStacksState is StorageLoading && allStacks.isEmpty)
|
||||
const SliverFillRemaining(
|
||||
child: Center(child: CircularProgressIndicator()),
|
||||
)
|
||||
else if (sortedStacks.isEmpty)
|
||||
SliverFillRemaining(
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(Icons.layers_outlined, size: 48, color: Colors.grey[400]),
|
||||
const SizedBox(height: 16),
|
||||
Text('No stacks found', style: context.textTheme.titleMedium),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
else
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
sliver: SliverGrid(
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 10,
|
||||
mainAxisSpacing: 10,
|
||||
childAspectRatio: 1.15,
|
||||
),
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, index) {
|
||||
final stack = displayedStacks[index];
|
||||
final author = authorsMap[stack.event.pubkey];
|
||||
return StackCard(
|
||||
stack: stack,
|
||||
author: author,
|
||||
isAuthorLoading: isAuthorsLoading && author == null,
|
||||
previewIdentifiers: stackPreviewIds[stack.id] ?? [],
|
||||
appsMap: appsMap,
|
||||
);
|
||||
},
|
||||
childCount: displayedStacks.length,
|
||||
),
|
||||
),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
child: hasMore
|
||||
? const Center(
|
||||
child: SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: CircularProgressIndicator(strokeWidth: 3),
|
||||
),
|
||||
)
|
||||
: sortedStacks.isNotEmpty
|
||||
? Center(
|
||||
child: Text(
|
||||
'No more stacks to load',
|
||||
style: Theme.of(context).textTheme.bodyMedium
|
||||
?.copyWith(color: Colors.grey[600]),
|
||||
),
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
),
|
||||
),
|
||||
const SliverToBoxAdapter(child: SizedBox(height: 16)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
List<AppStack> _sortStacks(
|
||||
List<AppStack> stacks, {
|
||||
String? signedInPubkey,
|
||||
Set<String>? followingPubkeys,
|
||||
}) {
|
||||
if (signedInPubkey != null &&
|
||||
followingPubkeys != null &&
|
||||
followingPubkeys.isNotEmpty) {
|
||||
final followed = <AppStack>[];
|
||||
final others = <AppStack>[];
|
||||
|
||||
for (final stack in stacks) {
|
||||
if (followingPubkeys.contains(stack.pubkey)) {
|
||||
followed.add(stack);
|
||||
} else {
|
||||
others.add(stack);
|
||||
}
|
||||
}
|
||||
|
||||
followed.sort((a, b) => b.event.createdAt.compareTo(a.event.createdAt));
|
||||
others.sort((a, b) => b.event.createdAt.compareTo(a.event.createdAt));
|
||||
return [...followed, ...others];
|
||||
} else {
|
||||
final franzapStacks =
|
||||
stacks.where((s) => s.pubkey == kFranzapPubkey).toList();
|
||||
final otherStacks =
|
||||
stacks.where((s) => s.pubkey != kFranzapPubkey).toList();
|
||||
|
||||
franzapStacks.sort((a, b) => b.event.createdAt.compareTo(a.event.createdAt));
|
||||
otherStacks.sort((a, b) => b.event.createdAt.compareTo(a.event.createdAt));
|
||||
return [...franzapStacks, ...otherStacks];
|
||||
}
|
||||
}
|
||||
@@ -61,7 +61,7 @@ extension AppExt on App {
|
||||
}
|
||||
|
||||
extension WidgetRefExt on WidgetRef {
|
||||
Ref get ref => read(Provider((ref) => ref));
|
||||
Ref get asRef => read(Provider((ref) => ref));
|
||||
}
|
||||
|
||||
/// Extension to handle both old and new format certificate hashes
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import 'dart:math';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:models/models.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:skeletonizer/skeletonizer.dart';
|
||||
import '../utils/extensions.dart';
|
||||
@@ -18,21 +18,21 @@ const int _kInitialStacks = 6;
|
||||
const int _kBatchSize = 6;
|
||||
|
||||
/// Get the raw `a` tag values from the stack's event (available immediately)
|
||||
Set<String> _getRawAppTagValues(AppStack stack) {
|
||||
Set<String> getRawAppTagValues(AppStack stack) {
|
||||
return stack.event.getTagSetValues('a');
|
||||
}
|
||||
|
||||
/// Extract just the d-tag (identifier) from a full addressable id
|
||||
String? _extractIdentifier(String addressableId) {
|
||||
String? extractStackIdentifier(String addressableId) {
|
||||
final parts = addressableId.split(':');
|
||||
return parts.length >= 3 ? parts.sublist(2).join(':') : null;
|
||||
}
|
||||
|
||||
/// Helper to compute preview app identifiers for a stack (3 apps max)
|
||||
List<String> _getPreviewIdentifiers(AppStack stack) {
|
||||
final rawTags = _getRawAppTagValues(stack).toList()
|
||||
List<String> getPreviewIdentifiers(AppStack stack) {
|
||||
final rawTags = getRawAppTagValues(stack).toList()
|
||||
..shuffle(Random(stack.id.hashCode));
|
||||
return rawTags.take(3).map(_extractIdentifier).whereType<String>().toList();
|
||||
return rawTags.take(3).map(extractStackIdentifier).whereType<String>().toList();
|
||||
}
|
||||
|
||||
/// Sort app stacks: franzap/following first, then by recency
|
||||
@@ -90,7 +90,13 @@ class AppStackContainer extends HookConsumerWidget {
|
||||
final visibleCount = useState(_kInitialStacks);
|
||||
|
||||
if (showSkeleton) {
|
||||
return _buildSkeleton(context);
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
_StackSectionHeader(showSeeAll: false),
|
||||
_buildSkeleton(context),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
final signedInPubkey = ref.watch(Signer.activePubkeyProvider);
|
||||
@@ -136,7 +142,13 @@ class AppStackContainer extends HookConsumerWidget {
|
||||
};
|
||||
|
||||
if (allStacks.isEmpty) {
|
||||
return _buildSkeleton(context);
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
_StackSectionHeader(showSeeAll: false),
|
||||
_buildSkeleton(context),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// Sort stacks
|
||||
@@ -174,7 +186,7 @@ class AppStackContainer extends HookConsumerWidget {
|
||||
final allPreviewIdentifiers = <String>{};
|
||||
final stackPreviewIds = <String, List<String>>{};
|
||||
for (final stack in displayedStacks) {
|
||||
final ids = _getPreviewIdentifiers(stack);
|
||||
final ids = getPreviewIdentifiers(stack);
|
||||
stackPreviewIds[stack.id] = ids;
|
||||
allPreviewIdentifiers.addAll(ids);
|
||||
}
|
||||
@@ -219,59 +231,58 @@ class AppStackContainer extends HookConsumerWidget {
|
||||
// 2-row horizontal scroll layout
|
||||
final numColumns = (displayedStacks.length + 1) ~/ 2;
|
||||
|
||||
return SingleChildScrollView(
|
||||
controller: scrollController,
|
||||
scrollDirection: Axis.horizontal,
|
||||
padding: const EdgeInsets.only(left: 12, right: 12),
|
||||
clipBehavior: Clip.none,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
for (int col = 0; col < numColumns; col++)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 10),
|
||||
child: SizedBox(
|
||||
width: 160,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// Top item
|
||||
if (col * 2 < displayedStacks.length)
|
||||
_StackCard(
|
||||
stack: displayedStacks[col * 2],
|
||||
author:
|
||||
authorsMap[displayedStacks[col * 2].event.pubkey],
|
||||
isAuthorLoading: isAuthorLoading(
|
||||
displayedStacks[col * 2].event.pubkey,
|
||||
),
|
||||
previewIdentifiers:
|
||||
stackPreviewIds[displayedStacks[col * 2].id] ?? [],
|
||||
appsMap: appsMap,
|
||||
),
|
||||
// Bottom item
|
||||
if (col * 2 + 1 < displayedStacks.length) ...[
|
||||
const SizedBox(height: 10),
|
||||
_StackCard(
|
||||
stack: displayedStacks[col * 2 + 1],
|
||||
author:
|
||||
authorsMap[displayedStacks[col * 2 + 1]
|
||||
.event
|
||||
.pubkey],
|
||||
isAuthorLoading: isAuthorLoading(
|
||||
displayedStacks[col * 2 + 1].event.pubkey,
|
||||
),
|
||||
previewIdentifiers:
|
||||
stackPreviewIds[displayedStacks[col * 2 + 1].id] ??
|
||||
[],
|
||||
appsMap: appsMap,
|
||||
),
|
||||
],
|
||||
],
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
_StackSectionHeader(showSeeAll: sortedStacks.length > _kInitialStacks),
|
||||
SingleChildScrollView(
|
||||
controller: scrollController,
|
||||
scrollDirection: Axis.horizontal,
|
||||
padding: const EdgeInsets.only(left: 12, right: 12),
|
||||
clipBehavior: Clip.none,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
for (int col = 0; col < numColumns; col++)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 10),
|
||||
child: SizedBox(
|
||||
width: 160,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (col * 2 < displayedStacks.length)
|
||||
StackCard(
|
||||
stack: displayedStacks[col * 2],
|
||||
author: authorsMap[displayedStacks[col * 2].event.pubkey],
|
||||
isAuthorLoading: isAuthorLoading(
|
||||
displayedStacks[col * 2].event.pubkey,
|
||||
),
|
||||
previewIdentifiers:
|
||||
stackPreviewIds[displayedStacks[col * 2].id] ?? [],
|
||||
appsMap: appsMap,
|
||||
),
|
||||
if (col * 2 + 1 < displayedStacks.length) ...[
|
||||
const SizedBox(height: 10),
|
||||
StackCard(
|
||||
stack: displayedStacks[col * 2 + 1],
|
||||
author: authorsMap[displayedStacks[col * 2 + 1].event.pubkey],
|
||||
isAuthorLoading: isAuthorLoading(
|
||||
displayedStacks[col * 2 + 1].event.pubkey,
|
||||
),
|
||||
previewIdentifiers:
|
||||
stackPreviewIds[displayedStacks[col * 2 + 1].id] ?? [],
|
||||
appsMap: appsMap,
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -308,6 +319,44 @@ class AppStackContainer extends HookConsumerWidget {
|
||||
}
|
||||
}
|
||||
|
||||
/// Section header with title and optional "See all" button
|
||||
class _StackSectionHeader extends StatelessWidget {
|
||||
const _StackSectionHeader({required this.showSeeAll});
|
||||
|
||||
final bool showSeeAll;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(14, 0, 6, 8),
|
||||
child: Row(
|
||||
children: [
|
||||
Text('App Stacks', style: context.textTheme.titleLarge),
|
||||
const Spacer(),
|
||||
if (showSeeAll)
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
final segments = GoRouterState.of(context).uri.pathSegments;
|
||||
final first = segments.isNotEmpty ? segments.first : 'search';
|
||||
context.push('/$first/stacks');
|
||||
},
|
||||
style: TextButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
visualDensity: VisualDensity.compact,
|
||||
),
|
||||
child: Text(
|
||||
'See all',
|
||||
style: context.textTheme.bodyMedium?.copyWith(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Skeleton card for loading state
|
||||
class _SkeletonStackCard extends StatelessWidget {
|
||||
const _SkeletonStackCard();
|
||||
@@ -357,8 +406,9 @@ class _SkeletonStackCard extends StatelessWidget {
|
||||
}
|
||||
|
||||
/// Individual stack card with vertical layout
|
||||
class _StackCard extends StatelessWidget {
|
||||
const _StackCard({
|
||||
class StackCard extends StatelessWidget {
|
||||
const StackCard({
|
||||
super.key,
|
||||
required this.stack,
|
||||
required this.author,
|
||||
required this.previewIdentifiers,
|
||||
@@ -374,7 +424,7 @@ class _StackCard extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final totalApps = _getRawAppTagValues(stack).length;
|
||||
final totalApps = getRawAppTagValues(stack).length;
|
||||
|
||||
// Resolve preview apps from the pre-loaded map
|
||||
final previewApps = previewIdentifiers
|
||||
|
||||
@@ -294,7 +294,7 @@ class LatestReleasesNotifier extends StateNotifier<LatestReleasesState> {
|
||||
}
|
||||
|
||||
final Ref ref;
|
||||
static const int _pageSize = 10;
|
||||
static const int _pageSize = 5;
|
||||
ProviderSubscription<StorageState<App>>? _sub;
|
||||
// We keep a fixed live head window from query(); older pages are appended
|
||||
|
||||
|
||||
@@ -416,7 +416,7 @@ class ZapAmountDialog extends HookConsumerWidget {
|
||||
if (signer == null) {
|
||||
signer = Bip340PrivateKeySigner(
|
||||
Utils.generateRandomHex64(),
|
||||
ref.ref,
|
||||
ref.asRef,
|
||||
);
|
||||
await signer.signIn(registerSigner: false);
|
||||
}
|
||||
@@ -456,7 +456,7 @@ class ZapAmountDialog extends HookConsumerWidget {
|
||||
await _executeZapPayment(
|
||||
signedZapRequest,
|
||||
nwcString,
|
||||
ref.ref,
|
||||
ref.asRef,
|
||||
);
|
||||
if (toastContext != null && toastContext.mounted) {
|
||||
toastContext.showInfo('⚡ Zap sent! $amount sats');
|
||||
@@ -690,7 +690,7 @@ class NWCZapDialog extends HookConsumerWidget {
|
||||
try {
|
||||
await secureStorage.setNWCString(nwcString.trim());
|
||||
ref.invalidate(hasNwcStringProvider);
|
||||
await _executeZapPayment(signedZapRequest, nwcString, ref.ref);
|
||||
await _executeZapPayment(signedZapRequest, nwcString, ref.asRef);
|
||||
if (toastContext != null && toastContext.mounted) {
|
||||
toastContext.showInfo('⚡ Zap sent! $amount sats');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user