Browse Source

Merge pull request #1073 from nextcloud/feat/neon/error_list_tile

feat(neon): add ability to display NeonError as a ListTile
pull/943/merge
Nikolas Rimikis 1 year ago committed by GitHub
parent
commit
b5c1ef278a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      packages/neon/neon/lib/src/widgets/account_tile.dart
  2. 2
      packages/neon/neon/lib/src/widgets/app_bar.dart
  3. 112
      packages/neon/neon/lib/src/widgets/error.dart
  4. 2
      packages/neon/neon/lib/src/widgets/image.dart

2
packages/neon/neon/lib/src/widgets/account_tile.dart

@ -80,7 +80,7 @@ class NeonAccountTile extends StatelessWidget {
if (userDetails.hasError) if (userDetails.hasError)
NeonError( NeonError(
userDetails.error, userDetails.error,
onlyIcon: true, type: NeonErrorType.iconOnly,
iconSize: 24, iconSize: 24,
onRetry: userDetailsBloc.refresh, onRetry: userDetailsBloc.refresh,
), ),

2
packages/neon/neon/lib/src/widgets/app_bar.dart

@ -94,7 +94,7 @@ class _NeonAppBarState extends State<NeonAppBar> {
NeonError( NeonError(
appImplementations.error, appImplementations.error,
onRetry: appsBloc.refresh, onRetry: appsBloc.refresh,
onlyIcon: true, type: NeonErrorType.iconOnly,
), ),
], ],
if (appImplementations.isLoading) ...[ if (appImplementations.isLoading) ...[

112
packages/neon/neon/lib/src/widgets/error.dart

@ -11,15 +11,32 @@ import 'package:neon/src/utils/provider.dart';
import 'package:nextcloud/nextcloud.dart'; import 'package:nextcloud/nextcloud.dart';
import 'package:universal_io/io.dart'; import 'package:universal_io/io.dart';
/// The display mode of the [NeonError] widget.
enum NeonErrorType {
/// Only shows the error icon.
///
/// This mode creates an IconButton that is usually used in size constrained
/// areas.
iconOnly,
/// Shows a column with the error message and a retry button.
column,
/// Shows a [ListTile] with the error.
listTile,
}
/// An indicator that an [error] has occurred. /// An indicator that an [error] has occurred.
/// ///
/// The action that lead to the error can be retried. /// The action that lead to the error can be retried.
/// The error can be indicated in various styles by providing [type] which
/// defaults to `NeonErrorType.column`.
class NeonError extends StatelessWidget { class NeonError extends StatelessWidget {
/// Creates a NeonError. /// Creates a NeonError.
const NeonError( const NeonError(
this.error, { this.error, {
required this.onRetry, required this.onRetry,
this.onlyIcon = false, this.type = NeonErrorType.column,
this.iconSize, this.iconSize,
this.color, this.color,
super.key, super.key,
@ -33,9 +50,6 @@ class NeonError extends StatelessWidget {
/// A function that's called when the user decides to retry the action that lead to the error. /// A function that's called when the user decides to retry the action that lead to the error.
final VoidCallback onRetry; final VoidCallback onRetry;
/// Changes whether the text is displayed additionally or not.
final bool onlyIcon;
/// The size of the icon in logical pixels. /// The size of the icon in logical pixels.
/// ///
/// Defaults to a size of `30`. /// Defaults to a size of `30`.
@ -46,6 +60,11 @@ class NeonError extends StatelessWidget {
/// Defaults to the nearest [IconTheme]'s [ColorScheme.error]. /// Defaults to the nearest [IconTheme]'s [ColorScheme.error].
final Color? color; final Color? color;
/// The display mode of this widget.
///
/// Defaults to `NeonErrorType.column`.
final NeonErrorType type;
/// Shows a [SnackBar] popup for the [error]. /// Shows a [SnackBar] popup for the [error].
static void showSnackbar(final BuildContext context, final Object? error) { static void showSnackbar(final BuildContext context, final Object? error) {
final details = getDetails(error); final details = getDetails(error);
@ -71,63 +90,70 @@ class NeonError extends StatelessWidget {
final details = getDetails(error); final details = getDetails(error);
final color = this.color ?? Theme.of(context).colorScheme.error; final color = this.color ?? Theme.of(context).colorScheme.error;
final textStyle = TextStyle(
color: color,
);
final message = details.getText(context);
final errorIcon = Icon( final errorIcon = Icon(
Icons.error_outline, Icons.error_outline,
size: iconSize ?? 30, size: iconSize ?? 30,
color: color, color: color,
); );
final message = final actionMessage =
details.isUnauthorized ? NeonLocalizations.of(context).loginAgain : NeonLocalizations.of(context).actionRetry; details.isUnauthorized ? NeonLocalizations.of(context).loginAgain : NeonLocalizations.of(context).actionRetry;
final onPressed = details.isUnauthorized ? () => _openLoginPage(context) : onRetry; final onPressed = details.isUnauthorized ? () => _openLoginPage(context) : onRetry;
if (onlyIcon) { switch (type) {
return Semantics( case NeonErrorType.iconOnly:
tooltip: details.getText(context), return Semantics(
child: IconButton( tooltip: details.getText(context),
icon: errorIcon, child: IconButton(
padding: EdgeInsets.zero, icon: errorIcon,
visualDensity: const VisualDensity( padding: EdgeInsets.zero,
horizontal: VisualDensity.minimumDensity, visualDensity: const VisualDensity(
vertical: VisualDensity.minimumDensity, horizontal: VisualDensity.minimumDensity,
vertical: VisualDensity.minimumDensity,
),
tooltip: actionMessage,
onPressed: onPressed,
), ),
tooltip: message, );
onPressed: onPressed, case NeonErrorType.column:
), return Padding(
); padding: const EdgeInsets.all(5),
} child: Column(
return Padding(
padding: const EdgeInsets.all(5),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
errorIcon, Row(
const SizedBox( mainAxisAlignment: MainAxisAlignment.center,
width: 10, children: [
), errorIcon,
Flexible( const SizedBox(
child: Text( width: 10,
details.getText(context),
style: TextStyle(
color: color,
), ),
), Flexible(
child: Text(message, style: textStyle),
),
],
),
ElevatedButton(
onPressed: onPressed,
child: Text(actionMessage),
), ),
], ],
), ),
ElevatedButton( );
onPressed: onPressed, case NeonErrorType.listTile:
child: Text(message), return ListTile(
), leading: errorIcon,
], title: Text(message),
), titleTextStyle: textStyle,
); onTap: onPressed,
);
}
} }
/// Gets the details for a given [error]. /// Gets the details for a given [error].

2
packages/neon/neon/lib/src/widgets/image.dart

@ -186,7 +186,7 @@ class _NeonCachedImageState extends State<NeonCachedImage> {
onRetry: () { onRetry: () {
setState(() {}); setState(() {});
}, },
onlyIcon: true, type: NeonErrorType.iconOnly,
iconSize: widget.size?.shortestSide, iconSize: widget.size?.shortestSide,
); );
} }

Loading…
Cancel
Save