diff --git a/packages/neon/neon/lib/src/utils/exceptions.dart b/packages/neon/neon/lib/src/utils/exceptions.dart index 6fb6c3c9..09084834 100644 --- a/packages/neon/neon/lib/src/utils/exceptions.dart +++ b/packages/neon/neon/lib/src/utils/exceptions.dart @@ -3,26 +3,41 @@ import 'package:neon/l10n/localizations.dart'; import 'package:neon/src/models/label_builder.dart'; import 'package:permission_handler/permission_handler.dart'; +/// Details of a [NeonException]. class NeonExceptionDetails { + /// Creates new [NeonExceptionDetails]. + /// + /// [isUnauthorized] defaults to false. const NeonExceptionDetails({ required this.getText, this.isUnauthorized = false, }); + /// Text that will be displayed in the UI final LabelBuilder getText; + + /// If the [Exception] is the result of an unauthorized API request this should be set to `true`. + /// + /// The user will then be shown a button to update the credentials of the account instead of retrying the action. final bool isUnauthorized; } +/// Extensible [Exception] to be used for displaying custom errors in the UI @immutable abstract class NeonException implements Exception { + /// Creates a NeonException const NeonException(); + /// Details that will be rendered by the UI NeonExceptionDetails get details; } +/// [Exception] that should be thrown when a native permission is denied. class MissingPermissionException extends NeonException { + /// Creates a MissingPermissionException const MissingPermissionException(this.permission); + /// Permission that was denied final Permission permission; @override diff --git a/packages/neon/neon/lib/src/widgets/error.dart b/packages/neon/neon/lib/src/widgets/error.dart index 3131c77e..4adb2282 100644 --- a/packages/neon/neon/lib/src/widgets/error.dart +++ b/packages/neon/neon/lib/src/widgets/error.dart @@ -11,7 +11,11 @@ import 'package:neon/src/utils/exceptions.dart'; import 'package:neon/src/utils/provider.dart'; import 'package:nextcloud/nextcloud.dart'; +/// An indicator that an [error] has occurred. +/// +/// The action that lead to the error can be retried. class NeonError extends StatelessWidget { + /// Creates a NeonError. const NeonError( this.error, { required this.onRetry, @@ -21,12 +25,28 @@ class NeonError extends StatelessWidget { super.key, }); + /// The error object. + /// + /// Can be of type [String] or [Exception], various subtypes of `Exception` are also handled separately. final dynamic error; + + /// A function that's called when the user decides to retry the action that lead to the error. final VoidCallback onRetry; + + /// Changes whether the text is displayed additionally or not. final bool onlyIcon; + + /// The size of the icon in logical pixels. + /// + /// Defaults to a size of `30`. final double? iconSize; + + /// The color to use when drawing the error indicator. + /// + /// Defaults to the nearest [IconTheme]'s [ColorScheme.error]. final Color? color; + /// Shows a [SnackBar] popup for the [error]. static void showSnackbar(final BuildContext context, final dynamic error) { final details = getDetails(error); @@ -110,6 +130,7 @@ class NeonError extends StatelessWidget { ); } + /// Gets the details for a given [error]. @internal static NeonExceptionDetails getDetails(final dynamic error) { switch (error) {