improve asnyc loading and error widgets

This commit is contained in:
Fabian Freund
2026-02-05 15:53:48 +01:00
parent 42c8ad986c
commit c7f9d6ec12
15 changed files with 63 additions and 15 deletions
@@ -99,7 +99,7 @@ class BangSearchScreen extends HookConsumerWidget {
error: (error, stackTrace) => Center( error: (error, stackTrace) => Center(
child: FailureWidget(title: 'Bang Search failed', exception: error), child: FailureWidget(title: 'Bang Search failed', exception: error),
), ),
loading: () => const SizedBox.shrink(), loading: () => const Center(child: CircularProgressIndicator()),
), ),
); );
} }
@@ -362,7 +362,7 @@ class BookmarkListScreen extends HookConsumerWidget {
}, },
), ),
), ),
loading: () => const SizedBox.shrink(), loading: () => const Center(child: CircularProgressIndicator()),
), ),
), ),
), ),
@@ -156,7 +156,7 @@ class FolderTreePicker extends HookConsumerWidget {
}, },
), ),
), ),
loading: () => const SizedBox.shrink(), loading: () => const Center(child: CircularProgressIndicator()),
), ),
], ],
); );
@@ -52,7 +52,14 @@ class TrackingProtectionSection extends HookConsumerWidget {
secondary: const Icon(Icons.shield_outlined), secondary: const Icon(Icons.shield_outlined),
), ),
), ),
error: (error, stack) => const SizedBox.shrink(), error: (error, stack) {
final colorScheme = Theme.of(context).colorScheme;
return ListTile(
title: const Text('Failed to load tracking protection'),
leading: Icon(Icons.error_outline, color: colorScheme.error),
);
},
); );
} }
} }
@@ -75,7 +75,8 @@ class ReaderButton extends HookConsumerWidget {
readerabilityState.active, readerabilityState.active,
icon, icon,
), ),
error: (error, stackTrace) => SizedBox.shrink(), error: (error, stackTrace) =>
Center(child: Icon(Icons.error_outline, color: colorScheme.error)),
loading: () => AnimateGradientShader( loading: () => AnimateGradientShader(
duration: const Duration(milliseconds: 500), duration: const Duration(milliseconds: 500),
primaryEnd: Alignment.bottomLeft, primaryEnd: Alignment.bottomLeft,
@@ -32,6 +32,7 @@ import 'package:weblibre/features/geckoview/features/tabs/domain/providers/selec
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/container.dart'; import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/container.dart';
import 'package:weblibre/features/geckoview/features/tabs/presentation/widgets/container_list_tile.dart'; import 'package:weblibre/features/geckoview/features/tabs/presentation/widgets/container_list_tile.dart';
import 'package:weblibre/features/tor/presentation/controllers/start_tor_proxy.dart'; import 'package:weblibre/features/tor/presentation/controllers/start_tor_proxy.dart';
import 'package:weblibre/presentation/widgets/failure_widget.dart';
class ContainerListScreen extends HookConsumerWidget { class ContainerListScreen extends HookConsumerWidget {
const ContainerListScreen(); const ContainerListScreen();
@@ -136,7 +137,13 @@ class ContainerListScreen extends HookConsumerWidget {
); );
}, },
), ),
error: (error, stackTrace) => SizedBox.shrink(), error: (error, stackTrace) => Center(
child: FailureWidget(
title: 'Failed to load containers',
exception: error,
onRetry: () => ref.invalidate(watchContainersWithCountProvider),
),
),
loading: () => ListView.builder( loading: () => ListView.builder(
itemCount: 3, itemCount: 3,
itemBuilder: (context, index) => ContainerListTile( itemBuilder: (context, index) => ContainerListTile(
@@ -30,6 +30,7 @@ import 'package:weblibre/features/geckoview/features/tabs/data/models/container_
import 'package:weblibre/features/geckoview/features/tabs/domain/providers.dart'; import 'package:weblibre/features/geckoview/features/tabs/domain/providers.dart';
import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/container.dart'; import 'package:weblibre/features/geckoview/features/tabs/domain/repositories/container.dart';
import 'package:weblibre/features/geckoview/features/tabs/presentation/widgets/container_list_tile.dart'; import 'package:weblibre/features/geckoview/features/tabs/presentation/widgets/container_list_tile.dart';
import 'package:weblibre/presentation/widgets/failure_widget.dart';
class ContainerSelectionScreen extends HookConsumerWidget { class ContainerSelectionScreen extends HookConsumerWidget {
const ContainerSelectionScreen(); const ContainerSelectionScreen();
@@ -62,7 +63,13 @@ class ContainerSelectionScreen extends HookConsumerWidget {
); );
}, },
), ),
error: (error, stackTrace) => SizedBox.shrink(), error: (error, stackTrace) => Center(
child: FailureWidget(
title: 'Failed to load containers',
exception: error,
onRetry: () => ref.invalidate(watchContainersWithCountProvider),
),
),
loading: () => ListView.builder( loading: () => ListView.builder(
itemCount: 3, itemCount: 3,
itemBuilder: (context, index) => ContainerListTile( itemBuilder: (context, index) => ContainerListTile(
@@ -256,7 +256,17 @@ class ContainerChips extends HookConsumerWidget {
), ),
); );
}, },
error: (error, stackTrace) => const SizedBox.shrink(), error: (error, stackTrace) => SizedBox(
height: 48,
width: double.infinity,
child: Center(
child: Icon(
Icons.error_outline,
size: 20,
color: Theme.of(context).colorScheme.error,
),
),
),
loading: () => const SizedBox(height: 48, width: double.infinity), loading: () => const SizedBox(height: 48, width: double.infinity),
); );
} }
@@ -29,6 +29,7 @@ import 'package:weblibre/features/settings/presentation/controllers/save_setting
import 'package:weblibre/features/settings/presentation/widgets/bang_icon.dart'; import 'package:weblibre/features/settings/presentation/widgets/bang_icon.dart';
import 'package:weblibre/features/user/data/models/general_settings.dart'; import 'package:weblibre/features/user/data/models/general_settings.dart';
import 'package:weblibre/features/user/domain/repositories/general_settings.dart'; import 'package:weblibre/features/user/domain/repositories/general_settings.dart';
import 'package:weblibre/presentation/widgets/failure_widget.dart';
import 'package:weblibre/presentation/widgets/url_icon.dart'; import 'package:weblibre/presentation/widgets/url_icon.dart';
const defaultBangs = ['ddg', 'brave', 'startpage', 'qwant']; const defaultBangs = ['ddg', 'brave', 'startpage', 'qwant'];
@@ -161,7 +162,14 @@ class DefaultSearchPage extends HookConsumerWidget {
], ],
); );
}, },
error: (error, stackTrace) => const SizedBox.shrink(), error: (error, stackTrace) => Center(
child: FailureWidget(
title: 'Could not load search engines',
exception: error,
onRetry: () =>
ref.refresh(bangListProvider(triggers: defaultBangs)),
),
),
loading: () => const SizedBox(height: 48, width: double.infinity), loading: () => const SizedBox(height: 48, width: double.infinity),
), ),
); );
@@ -129,7 +129,7 @@ class WebEngineHardeningScreen extends HookConsumerWidget {
), ),
), ),
), ),
loading: () => const SizedBox.shrink(), loading: () => const Center(child: CircularProgressIndicator()),
), ),
); );
} }
@@ -198,7 +198,7 @@ class WebEngineHardeningGroupScreen extends HookConsumerWidget {
), ),
), ),
), ),
loading: () => const SizedBox.shrink(), loading: () => const Center(child: CircularProgressIndicator()),
), ),
); );
} }
@@ -83,7 +83,9 @@ class DefaultSearchSelector extends HookConsumerWidget {
), ),
); );
}, },
error: (error, stackTrace) => const SizedBox.shrink(), error: (error, stackTrace) => Center(
child: Icon(Icons.error, color: Theme.of(context).colorScheme.error),
),
loading: () => const SizedBox(height: 48, width: double.infinity), loading: () => const SizedBox(height: 48, width: double.infinity),
); );
} }
@@ -190,7 +190,7 @@ class FeedArticleListScreen extends HookConsumerWidget {
exception: error, exception: error,
), ),
), ),
loading: () => const SizedBox.shrink(), loading: () => const Center(child: CircularProgressIndicator()),
), ),
), ),
); );
@@ -93,7 +93,7 @@ class FeedListScreen extends HookConsumerWidget {
}, },
), ),
), ),
loading: () => const SizedBox.shrink(), loading: () => const Center(child: CircularProgressIndicator()),
), ),
floatingActionButton: FloatingActionButton.extended( floatingActionButton: FloatingActionButton.extended(
label: const Text('Feed'), label: const Text('Feed'),
@@ -146,7 +146,13 @@ class FeedCard extends HookConsumerWidget {
); );
}, },
error: (error, stackTrace) => const Text('N/A'), error: (error, stackTrace) => const Text('N/A'),
loading: () => const SizedBox.shrink(), loading: () => const SizedBox(
height: 16,
width: 16,
child: Center(
child: CircularProgressIndicator(strokeWidth: 2),
),
),
); );
}, },
), ),