mirror of
https://github.com/zapstore/zapstore.git
synced 2026-10-05 20:48:24 +00:00
Update to use connect/disconnect, better lifecycle tuning, improve debug info UI
This commit is contained in:
+12
-19
@@ -97,12 +97,12 @@ class ZapstoreApp extends HookConsumerWidget {
|
||||
|
||||
// Check initial connectivity state
|
||||
connectivity.checkConnectivity().then((results) {
|
||||
notifier.ensureConnected();
|
||||
notifier.connect();
|
||||
});
|
||||
|
||||
// Listen to connectivity changes
|
||||
subscription = connectivity.onConnectivityChanged.listen((results) {
|
||||
notifier.ensureConnected();
|
||||
notifier.connect();
|
||||
});
|
||||
|
||||
return () => subscription?.cancel();
|
||||
@@ -273,10 +273,7 @@ Future<void> onSignInSuccess(Ref ref) async {
|
||||
unawaited(
|
||||
storage.query(
|
||||
RequestFilter<AppCatalogRelayList>(authors: {pubkey}).toRequest(),
|
||||
source: const RemoteSource(
|
||||
relays: 'bootstrap',
|
||||
stream: false,
|
||||
),
|
||||
source: const RemoteSource(relays: 'bootstrap', stream: false),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -290,14 +287,15 @@ class _AppLifecycleObserver with WidgetsBindingObserver {
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
final downloadService = _ref.read(downloadServiceProvider.notifier);
|
||||
final notifier =
|
||||
_ref.read(storageNotifierProvider.notifier)
|
||||
as PurplebaseStorageNotifier;
|
||||
|
||||
if (state == AppLifecycleState.resumed) {
|
||||
// Notify download service that app is in foreground
|
||||
// This will process any pending installations
|
||||
// Process any pending installations
|
||||
unawaited(downloadService.setAppForeground(true));
|
||||
|
||||
// App regained focus - re-sync installed packages from Android system
|
||||
// This will detect any apps installed/uninstalled outside of Zapstore
|
||||
// Re-sync installed packages from Android system
|
||||
unawaited(
|
||||
_ref.read(packageManagerProvider.notifier).syncInstalledPackages(),
|
||||
);
|
||||
@@ -306,16 +304,11 @@ class _AppLifecycleObserver with WidgetsBindingObserver {
|
||||
|
||||
// Force immediate health check on storage/relay connections
|
||||
// This detects stale connections after system sleep and triggers reconnection
|
||||
final notifier =
|
||||
_ref.read(storageNotifierProvider.notifier)
|
||||
as PurplebaseStorageNotifier;
|
||||
notifier.ensureConnected();
|
||||
} else if (state == AppLifecycleState.paused ||
|
||||
state == AppLifecycleState.inactive ||
|
||||
state == AppLifecycleState.detached ||
|
||||
state == AppLifecycleState.hidden) {
|
||||
// Notify download service that app is in background
|
||||
notifier.connect();
|
||||
} else if (state == AppLifecycleState.paused) {
|
||||
// Note: paused corresponds to Android's `onStop`
|
||||
unawaited(downloadService.setAppForeground(false));
|
||||
notifier.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+61
-123
@@ -293,7 +293,6 @@ class _DebugMessagesSection extends HookConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final poolState = ref.watch(poolStateProvider);
|
||||
final isExpanded = useState(true);
|
||||
final selectedTab = useState(0); // 0=Subscriptions, 1=Logs
|
||||
final now = useState(DateTime.now());
|
||||
final expandedSubs = useState<Set<String>>({});
|
||||
@@ -308,45 +307,6 @@ class _DebugMessagesSection extends HookConsumerWidget {
|
||||
final subscriptions = poolState?.subscriptions ?? {};
|
||||
final logs = poolState?.logs ?? const [];
|
||||
|
||||
// Aggregate relay status across all subscriptions
|
||||
final allRelayUrls = <String>[];
|
||||
final relayDebugEntries =
|
||||
<
|
||||
({
|
||||
String url,
|
||||
String shortUrl,
|
||||
RelaySubPhase phase,
|
||||
String? lastError,
|
||||
String subscriptionId,
|
||||
})
|
||||
>[];
|
||||
final connectedRelayUrls = <String>{};
|
||||
for (final subEntry in subscriptions.entries) {
|
||||
final subscriptionId = subEntry.key;
|
||||
final sub = subEntry.value;
|
||||
for (final entry in sub.relays.entries) {
|
||||
final url = entry.key;
|
||||
final relay = entry.value;
|
||||
final phase = relay.phase;
|
||||
final shortUrl = url
|
||||
.replaceAll('wss://', '')
|
||||
.replaceAll('ws://', '')
|
||||
.replaceAll(RegExp(r'/$'), '');
|
||||
allRelayUrls.add(url);
|
||||
relayDebugEntries.add((
|
||||
url: url,
|
||||
shortUrl: shortUrl,
|
||||
phase: phase,
|
||||
lastError: relay.lastError,
|
||||
subscriptionId: subscriptionId,
|
||||
));
|
||||
if (phase == RelaySubPhase.streaming ||
|
||||
phase == RelaySubPhase.loading) {
|
||||
connectedRelayUrls.add(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void toggleSubscription(String id) {
|
||||
final next = {...expandedSubs.value};
|
||||
if (!next.remove(id)) {
|
||||
@@ -362,64 +322,53 @@ class _DebugMessagesSection extends HookConsumerWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Header
|
||||
InkWell(
|
||||
onTap: () => isExpanded.value = !isExpanded.value,
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.bug_report,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Debug Info',
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.bug_report,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Debug Info',
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Icon(
|
||||
isExpanded.value ? Icons.expand_less : Icons.expand_more,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
if (isExpanded.value) ...[
|
||||
const SizedBox(height: 10),
|
||||
|
||||
// Tab selector
|
||||
Row(
|
||||
children: [
|
||||
_TabButton(
|
||||
label: 'Subscriptions (${subscriptions.length})',
|
||||
isSelected: selectedTab.value == 0,
|
||||
onTap: () => selectedTab.value = 0,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
_TabButton(
|
||||
label: 'Log (${logs.length})',
|
||||
isSelected: selectedTab.value == 1,
|
||||
onTap: () => selectedTab.value = 1,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
// Tab content
|
||||
if (selectedTab.value == 0)
|
||||
_buildSubscriptionsTab(
|
||||
context,
|
||||
subscriptions,
|
||||
now.value,
|
||||
expandedSubs.value,
|
||||
toggleSubscription,
|
||||
),
|
||||
if (selectedTab.value == 1) _buildLogsTab(context, logs),
|
||||
],
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
|
||||
// Tab selector
|
||||
Row(
|
||||
children: [
|
||||
_TabButton(
|
||||
label: 'Subscriptions (${subscriptions.length})',
|
||||
isSelected: selectedTab.value == 0,
|
||||
onTap: () => selectedTab.value = 0,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
_TabButton(
|
||||
label: 'Log (${logs.length})',
|
||||
isSelected: selectedTab.value == 1,
|
||||
onTap: () => selectedTab.value = 1,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
// Tab content
|
||||
if (selectedTab.value == 0)
|
||||
_buildSubscriptionsTab(
|
||||
context,
|
||||
subscriptions,
|
||||
now.value,
|
||||
expandedSubs.value,
|
||||
toggleSubscription,
|
||||
),
|
||||
if (selectedTab.value == 1) _buildLogsTab(context, logs),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -428,7 +377,7 @@ class _DebugMessagesSection extends HookConsumerWidget {
|
||||
|
||||
Widget _buildSubscriptionsTab(
|
||||
BuildContext context,
|
||||
Map<String, Subscription> subscriptions,
|
||||
Map<String, RelaySubscription> subscriptions,
|
||||
DateTime now,
|
||||
Set<String> expandedSubs,
|
||||
void Function(String id) onToggleSub,
|
||||
@@ -481,7 +430,7 @@ class _DebugMessagesSection extends HookConsumerWidget {
|
||||
size: 16,
|
||||
color: allEose
|
||||
? Colors.green
|
||||
: Theme.of(context).colorScheme.primary,
|
||||
: Colors.amber.shade700,
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Expanded(
|
||||
@@ -495,6 +444,19 @@ class _DebugMessagesSection extends HookConsumerWidget {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
_StatusChip(
|
||||
icon: Icons.event,
|
||||
label: '${sub.eventCount}',
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
_StatusChip(
|
||||
icon: Icons.cloud_done,
|
||||
label: '$activeRelays/$totalRelays',
|
||||
color: allEose ? Colors.green : Colors.amber.shade700,
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Icon(
|
||||
isExpanded ? Icons.expand_less : Icons.expand_more,
|
||||
size: 16,
|
||||
@@ -504,30 +466,6 @@ class _DebugMessagesSection extends HookConsumerWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 6,
|
||||
children: [
|
||||
_StatusChip(
|
||||
icon: Icons.cloud_done,
|
||||
label: '$activeRelays/$totalRelays',
|
||||
color: allEose ? Colors.green : Colors.blue,
|
||||
),
|
||||
if (allEose)
|
||||
_StatusChip(
|
||||
icon: Icons.check_circle,
|
||||
label: 'EOSE',
|
||||
color: Colors.green,
|
||||
),
|
||||
if (sub.stream)
|
||||
_StatusChip(
|
||||
icon: Icons.wifi_tethering,
|
||||
label: 'Streaming',
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
],
|
||||
),
|
||||
if (relayEntries.isNotEmpty) ...[
|
||||
const SizedBox(height: 10),
|
||||
Container(
|
||||
@@ -792,7 +730,7 @@ class _DebugMessagesSection extends HookConsumerWidget {
|
||||
return hours > 0 ? '${days}d ${hours}h' : '${days}d';
|
||||
}
|
||||
|
||||
Widget _buildRequestView(BuildContext context, Subscription sub) {
|
||||
Widget _buildRequestView(BuildContext context, RelaySubscription sub) {
|
||||
final req = _formatReq(sub);
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(top: 10),
|
||||
@@ -858,7 +796,7 @@ class _DebugMessagesSection extends HookConsumerWidget {
|
||||
);
|
||||
}
|
||||
|
||||
String _formatReq(Subscription sub) {
|
||||
String _formatReq(RelaySubscription sub) {
|
||||
final payload = ['REQ', sub.id, ...sub.request.toMaps()];
|
||||
try {
|
||||
return const JsonEncoder.withIndent(' ').convert(payload);
|
||||
|
||||
Reference in New Issue
Block a user