refactor: perf improvements

This commit is contained in:
cogwheel0
2025-09-23 11:00:25 +05:30
parent 41216ea432
commit 8da8a78001
7 changed files with 205 additions and 93 deletions

View File

@@ -20,6 +20,7 @@ class OfflineIndicator extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final connectivityStatus = ref.watch(connectivityStatusProvider);
final wasOffline = ref.watch(_wasOfflineProvider);
return Stack(
children: [
@@ -30,6 +31,10 @@ class OfflineIndicator extends ConsumerWidget {
if (status == ConnectivityStatus.offline) {
return _OfflineBanner();
}
// Announce back-online briefly if we were previously offline
if (wasOffline) {
return const _BackOnlineToast();
}
return const SizedBox.shrink();
},
loading: () => const SizedBox.shrink(),
@@ -40,6 +45,90 @@ class OfflineIndicator extends ConsumerWidget {
}
}
// Tracks if the app was recently offline to enable a one-shot back-online toast
final _wasOfflineProvider = NotifierProvider<_WasOfflineNotifier, bool>(
_WasOfflineNotifier.new,
);
class _WasOfflineNotifier extends Notifier<bool> {
@override
bool build() {
// Initialize based on current connectivity (assume online until proven otherwise)
ref.listen<AsyncValue<ConnectivityStatus>>(connectivityStatusProvider, (
prev,
next,
) {
next.when(
data: (status) {
if (status == ConnectivityStatus.offline) {
state = true; // mark that we have been offline
} else if (status == ConnectivityStatus.online && state) {
// After we emit the toast once, clear flag shortly after
Future.microtask(() => state = false);
}
},
loading: () {},
error: (_, __) {},
);
});
return false;
}
}
class _BackOnlineToast extends StatelessWidget {
const _BackOnlineToast();
@override
Widget build(BuildContext context) {
return Positioned(
top: kToolbarHeight + 8,
left: 0,
right: 0,
child: SafeArea(
bottom: false,
child: Semantics(
container: true,
liveRegion: true,
label: AppLocalizations.of(context)!.checkConnection,
child: Align(
alignment: Alignment.topCenter,
child:
Container(
margin: const EdgeInsets.symmetric(
horizontal: Spacing.md,
),
padding: const EdgeInsets.symmetric(
horizontal: Spacing.md,
vertical: Spacing.xs,
),
decoration: BoxDecoration(
color: context.conduitTheme.success,
borderRadius: BorderRadius.circular(
AppBorderRadius.round,
),
boxShadow: ConduitShadows.low,
),
child: Text(
// Reuse existing l10n; otherwise add a dedicated "Back online" key later
AppLocalizations.of(context)!.loadingContent,
style: TextStyle(
color: context.conduitTheme.textInverse,
fontSize: AppTypography.labelLarge,
fontWeight: FontWeight.w600,
),
),
)
.animate(onPlay: (c) => c.forward())
.fadeIn(duration: const Duration(milliseconds: 200))
.then(delay: const Duration(milliseconds: 1200))
.fadeOut(duration: const Duration(milliseconds: 250)),
),
),
),
);
}
}
class _OfflineBanner extends StatelessWidget {
@override
Widget build(BuildContext context) {
@@ -50,36 +139,41 @@ class _OfflineBanner extends StatelessWidget {
child: SafeArea(
bottom: false,
child:
Container(
padding: const EdgeInsets.symmetric(
horizontal: Spacing.md,
vertical: Spacing.xs,
),
decoration: BoxDecoration(
color: context.conduitTheme.warning,
boxShadow: ConduitShadows.low,
),
child: Row(
children: [
Icon(
Platform.isIOS
? CupertinoIcons.wifi_slash
: Icons.wifi_off,
color: context.conduitTheme.textInverse,
size: AppTypography.headlineMedium,
),
const SizedBox(width: Spacing.xs),
Expanded(
child: Text(
AppLocalizations.of(context)!.offlineBanner,
style: TextStyle(
color: context.conduitTheme.textInverse,
fontSize: AppTypography.labelLarge,
fontWeight: FontWeight.w500,
Semantics(
container: true,
liveRegion: true,
label: AppLocalizations.of(context)!.offlineBanner,
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: Spacing.md,
vertical: Spacing.xs,
),
decoration: BoxDecoration(
color: context.conduitTheme.warning,
boxShadow: ConduitShadows.low,
),
child: Row(
children: [
Icon(
Platform.isIOS
? CupertinoIcons.wifi_slash
: Icons.wifi_off,
color: context.conduitTheme.textInverse,
size: AppTypography.headlineMedium,
),
const SizedBox(width: Spacing.xs),
Expanded(
child: Text(
AppLocalizations.of(context)!.offlineBanner,
style: TextStyle(
color: context.conduitTheme.textInverse,
fontSize: AppTypography.labelLarge,
fontWeight: FontWeight.w500,
),
),
),
),
],
],
),
),
)
.animate(onPlay: (controller) => controller.forward())