Browse Source

neon: Always display error messages

pull/280/head
jld3103 2 years ago
parent
commit
91a7af1550
No known key found for this signature in database
GPG Key ID: 9062417B9E8EB7B3
  1. 12
      packages/neon/neon/lib/src/pages/home.dart
  2. 5
      packages/neon/neon/lib/src/utils/request_manager.dart
  3. 12
      packages/neon/neon/lib/src/widgets/account_avatar.dart
  4. 4
      packages/neon/neon/lib/src/widgets/cached_api_image.dart
  5. 54
      packages/neon/neon/lib/src/widgets/cached_image.dart
  6. 2
      packages/neon/neon/lib/src/widgets/cached_url_image.dart
  7. 14
      packages/neon/neon/lib/src/widgets/exception.dart

12
packages/neon/neon/lib/src/pages/home.dart

@ -482,10 +482,10 @@ class _HomePageState extends State<HomePage> {
const SizedBox(
width: 8,
),
Icon(
Icons.error_outline,
size: 30,
color: Theme.of(context).colorScheme.onPrimary,
NeonException(
appImplementations.error,
onRetry: _appsBloc.refresh,
onlyIcon: true,
),
],
if (appImplementations.loading) ...[
@ -563,10 +563,6 @@ class _HomePageState extends State<HomePage> {
Expanded(
child: Column(
children: [
NeonException(
appImplementations.error,
onRetry: _appsBloc.refresh,
),
if (appImplementations.data != null) ...[
if (appImplementations.data!.isEmpty) ...[
Expanded(

5
packages/neon/neon/lib/src/utils/request_manager.dart

@ -85,6 +85,7 @@ class RequestManager {
deserialize,
emitEmptyCache,
true,
null,
);
try {
@ -117,6 +118,7 @@ class RequestManager {
deserialize,
emitEmptyCache,
false,
e,
))) {
subject.add(Result.error(e));
}
@ -130,6 +132,7 @@ class RequestManager {
final R Function(String) deserialize,
final bool emitEmptyCache,
final bool loading,
final Object? error,
) async {
T? cached;
try {
@ -144,7 +147,7 @@ class RequestManager {
subject.add(
Result(
cached,
null,
error,
loading: loading,
cached: true,
),

12
packages/neon/neon/lib/src/widgets/account_avatar.dart

@ -14,6 +14,7 @@ class NeonAccountAvatar extends StatelessWidget {
Widget build(final BuildContext context) {
final isDark = Theme.of(context).brightness == Brightness.dark;
final size = (kAvatarSize * MediaQuery.of(context).devicePixelRatio).toInt();
final userStatusBloc = Provider.of<AccountsBloc>(context, listen: false).getUserStatusBloc(account);
return Stack(
alignment: Alignment.center,
children: [
@ -40,7 +41,7 @@ class NeonAccountAvatar extends StatelessWidget {
),
),
ResultBuilder<UserStatusBloc, NextcloudUserStatusStatus?>(
stream: Provider.of<AccountsBloc>(context, listen: false).getUserStatusBloc(account).userStatus,
stream: userStatusBloc.userStatus,
builder: (final context, final userStatus) {
final hasEmoji = userStatus.data?.icon != null;
final factor = hasEmoji ? 2 : 3;
@ -66,10 +67,11 @@ class NeonAccountAvatar extends StatelessWidget {
: userStatus.error != null &&
(userStatus.error is! NextcloudApiException ||
(userStatus.error! as NextcloudApiException).statusCode != 404)
? Icon(
Icons.error_outline,
size: kAvatarSize / factor,
color: Colors.red,
? NeonException(
userStatus.error,
onRetry: userStatusBloc.refresh,
onlyIcon: true,
iconSize: kAvatarSize / factor,
)
: hasEmoji
? Text(

4
packages/neon/neon/lib/src/widgets/cached_api_image.dart

@ -15,7 +15,7 @@ class NeonCachedApiImage extends NeonCachedImage {
super.iconColor,
super.key,
}) : super(
future: () async {
getImageFile: () async {
final realKey = '${account.id}-$cacheKey';
final cacheFile = await _cacheManager.getFileFromCache(realKey);
if (cacheFile != null && cacheFile.validTill.isAfter(DateTime.now())) {
@ -28,6 +28,6 @@ class NeonCachedApiImage extends NeonCachedImage {
maxAge: const Duration(days: 7),
eTag: etag,
);
}(),
},
);
}

54
packages/neon/neon/lib/src/widgets/cached_image.dart

@ -2,9 +2,9 @@ part of '../../neon.dart';
final _cacheManager = DefaultCacheManager();
abstract class NeonCachedImage extends StatelessWidget {
abstract class NeonCachedImage extends StatefulWidget {
const NeonCachedImage({
required this.future,
required this.getImageFile,
this.isSvgHint = false,
this.height,
this.width,
@ -14,7 +14,7 @@ abstract class NeonCachedImage extends StatelessWidget {
super.key,
});
final Future<File> future;
final Future<File> Function() getImageFile;
final bool isSvgHint;
final double? height;
@ -25,7 +25,15 @@ abstract class NeonCachedImage extends StatelessWidget {
final Color? iconColor;
@override
Widget build(final BuildContext context) => FutureBuilder<File>(
State<NeonCachedImage> createState() => _NeonCachedImageState();
}
class _NeonCachedImageState extends State<NeonCachedImage> {
late Future<File> future = widget.getImageFile();
@override
Widget build(final BuildContext context) => Center(
child: FutureBuilder<File>(
future: future,
builder: (final context, final fileSnapshot) {
if (fileSnapshot.hasData) {
@ -33,13 +41,13 @@ abstract class NeonCachedImage extends StatelessWidget {
try {
// TODO: Is this safe enough?
if (isSvgHint || utf8.decode(content).contains('<svg')) {
if (widget.isSvgHint || utf8.decode(content).contains('<svg')) {
return SvgPicture.memory(
content,
height: height,
width: width,
fit: fit ?? BoxFit.contain,
color: svgColor,
height: widget.height,
width: widget.width,
fit: widget.fit ?? BoxFit.contain,
color: widget.svgColor,
);
}
} catch (_) {
@ -48,25 +56,35 @@ abstract class NeonCachedImage extends StatelessWidget {
return Image.memory(
content,
height: height,
width: width,
fit: fit,
height: widget.height,
width: widget.width,
fit: widget.fit,
gaplessPlayback: true,
);
}
if (fileSnapshot.hasError) {
return Icon(
Icons.error_outline,
size: height != null && width != null ? min(height!, width!) : height ?? width,
color: iconColor,
return NeonException(
fileSnapshot.error,
onRetry: () {
setState(() {
// ignore: discarded_futures
future = widget.getImageFile();
});
},
onlyIcon: true,
iconSize: widget.height != null && widget.width != null
? min(widget.height!, widget.width!)
: widget.height ?? widget.width,
color: widget.iconColor ?? Colors.red,
);
}
return SizedBox(
width: width,
width: widget.width,
child: NeonLinearProgressIndicator(
color: iconColor,
color: widget.iconColor,
),
);
},
),
);
}

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

@ -10,7 +10,7 @@ class NeonCachedUrlImage extends NeonCachedImage {
super.iconColor,
super.key,
}) : super(
future: _cacheManager.getSingleFile(url),
getImageFile: () => _cacheManager.getSingleFile(url),
isSvgHint: Uri.parse(url).path.endsWith('.svg'),
);
}

14
packages/neon/neon/lib/src/widgets/exception.dart

@ -5,14 +5,16 @@ class NeonException extends StatelessWidget {
this.exception, {
required this.onRetry,
this.onlyIcon = false,
this.iconSize = 30,
this.iconSize,
this.color,
super.key,
});
final dynamic exception;
final Function() onRetry;
final bool onlyIcon;
final double iconSize;
final double? iconSize;
final Color? color;
static void showSnackbar(final BuildContext context, final dynamic exception) {
final details = _getExceptionDetails(context, exception);
@ -41,8 +43,8 @@ class NeonException extends StatelessWidget {
final errorIcon = Icon(
Icons.error_outline,
size: iconSize,
color: Colors.red,
size: iconSize ?? 30,
color: color ?? Colors.red,
);
if (onlyIcon) {
@ -71,8 +73,8 @@ class NeonException extends StatelessWidget {
Flexible(
child: Text(
details.text,
style: const TextStyle(
color: Colors.red,
style: TextStyle(
color: color ?? Colors.red,
),
),
),

Loading…
Cancel
Save