3c0806d8fd
Two changes to surface where detail-screen spinners hang: 1. Connectivity().checkConnectivity() goes over a platform channel that on some Android builds stalls. Wrap with a 2s timeout and default to "online" if it times out — being wrong about connectivity costs at most one failed fetch, but being stuck spins the UI forever. 2. albumProvider's cold-cache flow now debugPrints at every step: drift miss → connectivity result → API call → drift write → ack the re-emit. Also adds a 10s timeout on the API fetch and a 3s timeout on the connectivity await so a hang surfaces as an error-yielded empty AlbumRef instead of an infinite spinner. Once the operator's next test produces logs we can pinpoint which step is hanging. The diagnostic prints stay until the issue's root cause is confirmed; will be removed in a follow-up.
36 lines
1.5 KiB
Dart
36 lines
1.5 KiB
Dart
import 'package:connectivity_plus/connectivity_plus.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
|
|
/// Online if at least one connectivity result is non-none.
|
|
/// connectivity_plus reports the union (wifi, mobile, vpn, etc.) — operator
|
|
/// chose "no Wi-Fi gate" for #357, so any connection means "go ahead and
|
|
/// pull/cache".
|
|
///
|
|
/// IMPORTANT: onConnectivityChanged only emits on *changes*, not on
|
|
/// subscription. Without seeding an initial value via checkConnectivity(),
|
|
/// any consumer using `ref.read(connectivityProvider.future)` would
|
|
/// block until the OS happened to report a connectivity flip — which
|
|
/// is exactly what made album/artist/playlist detail screens spin
|
|
/// forever for tiles tapped before the first event landed.
|
|
final connectivityProvider = StreamProvider<bool>((ref) async* {
|
|
final c = Connectivity();
|
|
bool isOnline(List<ConnectivityResult> rs) =>
|
|
rs.any((r) => r != ConnectivityResult.none);
|
|
|
|
// checkConnectivity() goes over a platform channel and on some
|
|
// Android builds it can stall. Fall back to "assume online" after
|
|
// 2s so consumers waiting on .future never block forever — being
|
|
// wrong about connectivity costs at most one failed request, but
|
|
// being stuck spins the UI indefinitely.
|
|
try {
|
|
final initial = await c.checkConnectivity().timeout(
|
|
const Duration(seconds: 2),
|
|
onTimeout: () => const [ConnectivityResult.wifi],
|
|
);
|
|
yield isOnline(initial);
|
|
} catch (_) {
|
|
yield true;
|
|
}
|
|
yield* c.onConnectivityChanged.map(isOnline);
|
|
});
|