Feedback: offline, the social layer stops working with no clear reason. A slim amber strip now shows above every screen when there's no network (connectivity_ plus), so it's obvious WHY sharing is paused — the inventory keeps working. Wrapped once via the MaterialApp builder; connectivity check is guarded so it no-ops where the plugin is absent (tests/unsupported platforms). i18n en/es/pt. Analyzer clean.
87 lines
2.6 KiB
Dart
87 lines
2.6 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:connectivity_plus/connectivity_plus.dart';
|
|
import 'package:flutter/material.dart';
|
|
|
|
import '../i18n/strings.g.dart';
|
|
|
|
/// Wraps the app and shows a slim strip at the very top when there's no network,
|
|
/// so it's clear WHY the social layer (market, chat, profile) is paused — the
|
|
/// inventory keeps working offline. Wrap the whole app once (MaterialApp builder).
|
|
class OfflineBanner extends StatefulWidget {
|
|
const OfflineBanner({required this.child, super.key});
|
|
|
|
final Widget child;
|
|
|
|
@override
|
|
State<OfflineBanner> createState() => _OfflineBannerState();
|
|
}
|
|
|
|
class _OfflineBannerState extends State<OfflineBanner> {
|
|
bool _offline = false;
|
|
StreamSubscription<List<ConnectivityResult>>? _sub;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_init();
|
|
}
|
|
|
|
Future<void> _init() async {
|
|
try {
|
|
final current = await Connectivity().checkConnectivity();
|
|
if (mounted) setState(() => _offline = _isOffline(current));
|
|
_sub = Connectivity().onConnectivityChanged.listen((results) {
|
|
if (mounted) setState(() => _offline = _isOffline(results));
|
|
});
|
|
} catch (_) {
|
|
// Platform without connectivity support → assume online, hide the banner.
|
|
}
|
|
}
|
|
|
|
bool _isOffline(List<ConnectivityResult> results) =>
|
|
results.isEmpty ||
|
|
results.every((r) => r == ConnectivityResult.none);
|
|
|
|
@override
|
|
void dispose() {
|
|
_sub?.cancel();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Column(
|
|
children: [
|
|
if (_offline)
|
|
Material(
|
|
color: const Color(0xFFE8A200), // amber — not an error, just paused
|
|
child: SafeArea(
|
|
bottom: false,
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
const Icon(Icons.cloud_off, size: 16, color: Colors.white),
|
|
const SizedBox(width: 8),
|
|
Flexible(
|
|
child: Text(
|
|
context.t.common.offline,
|
|
style: const TextStyle(
|
|
color: Colors.white,
|
|
fontSize: 12.5,
|
|
fontWeight: FontWeight.w500,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
Expanded(child: widget.child),
|
|
],
|
|
);
|
|
}
|
|
}
|