Surface/lib/widgets/dialog.dart
2024-11-09 18:28:45 +08:00

152 lines
3.8 KiB
Dart

import 'dart:math' as math;
import 'package:dio/dio.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
extension AppPromptExtension on BuildContext {
void showSnackbar(String content, {SnackBarAction? action}) {
ScaffoldMessenger.of(this).showSnackBar(SnackBar(
content: Text(content),
action: action,
));
}
void clearSnackbar() {
ScaffoldMessenger.of(this).clearSnackBars();
}
Future<void> showModalDialog(String title, desc) {
return showDialog<void>(
useRootNavigator: true,
context: this,
builder: (ctx) => AlertDialog(
title: Text(title),
content: Text(desc),
actions: [
TextButton(
onPressed: () => Navigator.pop(ctx),
child: Text('dialogDismiss').tr(),
)
],
),
);
}
Future<void> showInfoDialog(String title, body) {
return showDialog<void>(
useRootNavigator: true,
context: this,
builder: (ctx) => AlertDialog(
title: Text(title),
content: Text(body),
actions: [
TextButton(
onPressed: () => Navigator.pop(ctx),
child: Text('dialogDismiss').tr(),
)
],
),
);
}
Future<bool> showConfirmDialog(String title, body) async {
return await showDialog<bool>(
useRootNavigator: true,
context: this,
builder: (ctx) => AlertDialog(
title: Text(title),
content: Text(body),
actions: [
TextButton(
onPressed: () => Navigator.pop(ctx, false),
child: Text('dialogCancel').tr(),
),
TextButton(
onPressed: () => Navigator.pop(ctx, true),
child: Text('dialogConfirm').tr(),
)
],
),
) ??
false;
}
Future<void> showErrorDialog(dynamic exception) {
Widget content = Text(exception.toString().capitalize());
if (exception is DioException) {
String preview;
switch (exception.response?.statusCode) {
case 400:
preview = 'errorRequestBad'.tr();
break;
case 401:
preview = 'errorRequestUnauthorized'.tr();
break;
case 403:
preview = 'errorRequestForbidden'.tr();
break;
case 404:
preview = 'errorRequestNotFound'.tr();
break;
case null:
preview = 'errorRequestConnection'.tr();
break;
default:
preview = 'errorRequestUnknown'.tr();
break;
}
if (exception.response != null) {
content = Text(
'$preview\n\n(${exception.response?.statusCode}) ${exception.response?.data}',
);
} else {
content = Text(preview);
}
}
return showDialog<void>(
useRootNavigator: true,
context: this,
builder: (ctx) => AlertDialog(
title: Text('dialogError').tr(),
content: content,
actions: [
TextButton(
onPressed: () => Navigator.pop(ctx),
child: Text('dialogDismiss').tr(),
)
],
),
);
}
}
extension ByteFormatter on int {
String formatBytes({int decimals = 2}) {
if (this == 0) return '0 Bytes';
const k = 1024;
final dm = decimals < 0 ? 0 : decimals;
final sizes = [
'Bytes',
'KiB',
'MiB',
'GiB',
'TiB',
'PiB',
'EiB',
'ZiB',
'YiB'
];
final i = (math.log(this) / math.log(k)).floor().toInt();
return '${(this / math.pow(k, i)).toStringAsFixed(dm)} ${sizes[i]}';
}
}
extension StringFormatter on String {
String capitalize() {
return "${this[0].toUpperCase()}${substring(1)}";
}
}