part of '../chat_view.dart'; // Shows a slim banner when the client loses its connection to the homeserver. // Debounced so brief transient sync errors don't flicker a banner. class _ConnectionBanner extends ConsumerStatefulWidget { const _ConnectionBanner(); @override ConsumerState<_ConnectionBanner> createState() => _ConnectionBannerState(); } class _ConnectionBannerState extends ConsumerState<_ConnectionBanner> { StreamSubscription? _sub; Timer? _debounce; bool _lost = false; @override void initState() { super.initState(); _attach(); } Future _attach() async { try { final client = await ref.read(matrixClientProvider.future); _sub = client.onSyncStatus.stream.listen((s) { if (s.status == SyncStatus.error) { // Only surface after the error persists a few seconds. _debounce ??= Timer(const Duration(seconds: 4), () { _debounce = null; if (mounted) setState(() => _lost = true); }); } else if (s.status == SyncStatus.finished || s.status == SyncStatus.processing) { _debounce?.cancel(); _debounce = null; if (_lost && mounted) setState(() => _lost = false); } }); } catch (_) {} } @override void dispose() { _sub?.cancel(); _debounce?.cancel(); super.dispose(); } @override Widget build(BuildContext context) { final pt = PyramidTheme.of(context); return AnimatedSize( duration: const Duration(milliseconds: 200), curve: Curves.easeOut, alignment: Alignment.topCenter, child: _lost ? Container( width: double.infinity, color: pt.danger.withAlpha(36), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.cloud_off_rounded, size: 14, color: pt.danger), const SizedBox(width: 8), Flexible( child: Text( 'Keine Verbindung zum Server – Wiederverbindung läuft…', style: TextStyle(color: pt.danger, fontSize: 12, fontWeight: FontWeight.w500), maxLines: 1, overflow: TextOverflow.ellipsis, ), ), ], ), ) : const SizedBox.shrink(), ); } }