Change error prompts
This commit is contained in:
@@ -14,9 +14,9 @@ sealed class UpdateFailure with _$UpdateFailure, Failure {
|
||||
]) = UpdateUnexpectedFailure;
|
||||
|
||||
@override
|
||||
String present(TranslationsEn t) {
|
||||
({String type, String? message}) present(TranslationsEn t) {
|
||||
return switch (this) {
|
||||
UpdateUnexpectedFailure() => t.failure.unexpected,
|
||||
UpdateUnexpectedFailure() => (type: t.failure.unexpected, message: null),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,15 +25,20 @@ sealed class ConnectionFailure with _$ConnectionFailure, Failure {
|
||||
CoreConnectionFailure;
|
||||
|
||||
@override
|
||||
String present(TranslationsEn t) {
|
||||
({String type, String? message}) present(TranslationsEn t) {
|
||||
return switch (this) {
|
||||
UnexpectedConnectionFailure() => t.failure.connectivity.unexpected,
|
||||
MissingVpnPermission(:final message) =>
|
||||
t.failure.connectivity.missingVpnPermission +
|
||||
(message == null ? "" : ": $message"),
|
||||
MissingNotificationPermission(:final message) =>
|
||||
t.failure.connectivity.missingNotificationPermission +
|
||||
(message == null ? "" : ": $message"),
|
||||
UnexpectedConnectionFailure() => (
|
||||
type: t.failure.connectivity.unexpected,
|
||||
message: null
|
||||
),
|
||||
MissingVpnPermission(:final message) => (
|
||||
type: t.failure.connectivity.missingVpnPermission,
|
||||
message: message
|
||||
),
|
||||
MissingNotificationPermission(:final message) => (
|
||||
type: t.failure.connectivity.missingNotificationPermission,
|
||||
message: message
|
||||
),
|
||||
CoreConnectionFailure(:final failure) => failure.present(t),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -42,19 +42,32 @@ sealed class CoreServiceFailure with _$CoreServiceFailure, Failure {
|
||||
};
|
||||
|
||||
@override
|
||||
String present(TranslationsEn t) {
|
||||
({String type, String? message}) present(TranslationsEn t) {
|
||||
return switch (this) {
|
||||
UnexpectedCoreServiceFailure() => t.failure.singbox.unexpected,
|
||||
CoreServiceNotRunning(:final message) =>
|
||||
t.failure.singbox.serviceNotRunning +
|
||||
(message == null ? "" : ": $message"),
|
||||
InvalidConfig(:final message) =>
|
||||
t.failure.singbox.invalidConfig + (message == null ? "" : ": $message"),
|
||||
CoreServiceCreateFailure(:final message) =>
|
||||
t.failure.singbox.create + (message == null ? "" : ": $message"),
|
||||
CoreServiceStartFailure(:final message) =>
|
||||
t.failure.singbox.start + (message == null ? "" : ": $message"),
|
||||
CoreServiceOtherFailure(:final message) => message ?? "",
|
||||
UnexpectedCoreServiceFailure() => (
|
||||
type: t.failure.singbox.unexpected,
|
||||
message: null
|
||||
),
|
||||
CoreServiceNotRunning(:final message) => (
|
||||
type: t.failure.singbox.serviceNotRunning,
|
||||
message: message
|
||||
),
|
||||
InvalidConfig(:final message) => (
|
||||
type: t.failure.singbox.invalidConfig,
|
||||
message: message
|
||||
),
|
||||
CoreServiceCreateFailure(:final message) => (
|
||||
type: t.failure.singbox.create,
|
||||
message: message
|
||||
),
|
||||
CoreServiceStartFailure(:final message) => (
|
||||
type: t.failure.singbox.start,
|
||||
message: message
|
||||
),
|
||||
CoreServiceOtherFailure(:final message) => (
|
||||
type: t.failure.singbox.unexpected,
|
||||
message: message
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,20 @@ import 'package:hiddify/core/locale/locale.dart';
|
||||
|
||||
// TODO: rewrite
|
||||
mixin Failure {
|
||||
String present(TranslationsEn t);
|
||||
({String type, String? message}) present(TranslationsEn t);
|
||||
}
|
||||
|
||||
extension ErrorPresenter on TranslationsEn {
|
||||
String presentError(Object error) {
|
||||
if (error case Failure()) return error.present(this);
|
||||
String printError(Object error) {
|
||||
if (error case Failure()) {
|
||||
final err = error.present(this);
|
||||
return err.type + (err.message == null ? "" : ": ${err.message}");
|
||||
}
|
||||
return failure.unexpected;
|
||||
}
|
||||
|
||||
({String type, String? message}) presentError(Object error) {
|
||||
if (error case Failure()) return error.present(this);
|
||||
return (type: failure.unexpected, message: null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,13 +19,20 @@ sealed class ProfileFailure with _$ProfileFailure, Failure {
|
||||
ProfileInvalidConfigFailure;
|
||||
|
||||
@override
|
||||
String present(TranslationsEn t) {
|
||||
({String type, String? message}) present(TranslationsEn t) {
|
||||
return switch (this) {
|
||||
ProfileUnexpectedFailure() => t.failure.profiles.unexpected,
|
||||
ProfileNotFoundFailure() => t.failure.profiles.notFound,
|
||||
ProfileInvalidConfigFailure(:final message) =>
|
||||
t.failure.profiles.invalidConfig +
|
||||
(message == null ? "" : ": $message"),
|
||||
ProfileUnexpectedFailure() => (
|
||||
type: t.failure.profiles.unexpected,
|
||||
message: null
|
||||
),
|
||||
ProfileNotFoundFailure() => (
|
||||
type: t.failure.profiles.notFound,
|
||||
message: null
|
||||
),
|
||||
ProfileInvalidConfigFailure(:final message) => (
|
||||
type: t.failure.profiles.invalidConfig,
|
||||
message: message
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ class AboutPage extends HookConsumerWidget {
|
||||
if (next case AsyncData(:final value)) {
|
||||
switch (value.latestVersion) {
|
||||
case AsyncError(:final error):
|
||||
CustomToast.error(t.presentError(error)).show(context);
|
||||
CustomToast.error(t.printError(error)).show(context);
|
||||
default:
|
||||
if (value.newVersionAvailable) {
|
||||
await NewVersionDialog(
|
||||
|
||||
@@ -31,7 +31,7 @@ class ProfileTile extends HookConsumerWidget {
|
||||
|
||||
final selectActiveMutation = useMutation(
|
||||
initialOnFailure: (err) {
|
||||
CustomToast.error(t.presentError(err)).show(context);
|
||||
CustomToast.error(t.printError(err)).show(context);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -146,7 +146,8 @@ class ProfileActionButton extends HookConsumerWidget {
|
||||
|
||||
final updateProfileMutation = useMutation(
|
||||
initialOnFailure: (err) {
|
||||
CustomToast.error(t.presentError(err)).show(context);
|
||||
// CustomToast.error(t.printError(err)).show(context);
|
||||
CustomAlertDialog.fromErr(t.presentError(err)).show(context);
|
||||
},
|
||||
initialOnSuccess: () =>
|
||||
CustomToast.success(t.profile.update.successMsg).show(context),
|
||||
@@ -204,14 +205,14 @@ class ProfileActionsMenu extends HookConsumerWidget {
|
||||
|
||||
final updateProfileMutation = useMutation(
|
||||
initialOnFailure: (err) {
|
||||
CustomToast.error(t.presentError(err)).show(context);
|
||||
CustomAlertDialog.fromErr(t.presentError(err)).show(context);
|
||||
},
|
||||
initialOnSuccess: () =>
|
||||
CustomToast.success(t.profile.update.successMsg).show(context),
|
||||
);
|
||||
final deleteProfileMutation = useMutation(
|
||||
initialOnFailure: (err) {
|
||||
CustomToast.error(t.presentError(err)).show(context);
|
||||
CustomAlertDialog.fromErr(t.presentError(err)).show(context);
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ class HomePage extends HookConsumerWidget {
|
||||
_ => const EmptyProfilesHomeBody(),
|
||||
},
|
||||
AsyncError(:final error) =>
|
||||
SliverErrorBodyPlaceholder(t.presentError(error)),
|
||||
SliverErrorBodyPlaceholder(t.printError(error)),
|
||||
_ => const SliverToBoxAdapter(),
|
||||
},
|
||||
],
|
||||
|
||||
@@ -24,13 +24,12 @@ class ConnectionButton extends HookConsumerWidget {
|
||||
connectivityControllerProvider,
|
||||
(_, next) {
|
||||
if (next case AsyncError(:final error)) {
|
||||
CustomToast.error(t.presentError(error)).show(context);
|
||||
CustomAlertDialog.fromErr(t.presentError(error)).show(context);
|
||||
}
|
||||
if (next
|
||||
case AsyncData(value: Disconnected(:final connectionFailure?))) {
|
||||
CustomAlertDialog(
|
||||
message: connectionFailure.present(t),
|
||||
).show(context);
|
||||
CustomAlertDialog.fromErr(t.presentError(connectionFailure))
|
||||
.show(context);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
@@ -138,7 +138,7 @@ class LogsPage extends HookConsumerWidget with PresLogger {
|
||||
NestedTabAppBar(
|
||||
title: Text(t.logs.pageTitle.titleCase),
|
||||
),
|
||||
SliverErrorBodyPlaceholder(t.presentError(error)),
|
||||
SliverErrorBodyPlaceholder(t.printError(error)),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -38,7 +38,7 @@ class ProfileDetailPage extends HookConsumerWidget with PresLogger {
|
||||
if (asyncSave case AsyncData(value: final save)) {
|
||||
switch (save) {
|
||||
case MutationFailure(:final failure):
|
||||
CustomToast.error(t.presentError(failure)).show(context);
|
||||
CustomToast.error(t.printError(failure)).show(context);
|
||||
case MutationSuccess():
|
||||
CustomToast.success(t.profile.save.successMsg.sentenceCase)
|
||||
.show(context);
|
||||
@@ -58,7 +58,7 @@ class ProfileDetailPage extends HookConsumerWidget with PresLogger {
|
||||
if (asyncSave case AsyncData(value: final delete)) {
|
||||
switch (delete) {
|
||||
case MutationFailure(:final failure):
|
||||
CustomToast.error(t.presentError(failure)).show(context);
|
||||
CustomToast.error(t.printError(failure)).show(context);
|
||||
case MutationSuccess():
|
||||
CustomToast.success(t.profile.delete.successMsg.sentenceCase)
|
||||
.show(context);
|
||||
|
||||
@@ -30,7 +30,8 @@ class AddProfileModal extends HookConsumerWidget {
|
||||
final addProfileMutation = useMutation(
|
||||
initialOnFailure: (err) {
|
||||
mutationTriggered.value = false;
|
||||
CustomToast.error(t.presentError(err)).show(context);
|
||||
// CustomToast.error(t.presentError(err)).show(context);
|
||||
CustomAlertDialog.fromErr(t.presentError(err)).show(context);
|
||||
},
|
||||
initialOnSuccess: () {
|
||||
CustomToast.success(t.profile.save.successMsg.sentenceCase)
|
||||
|
||||
@@ -38,7 +38,7 @@ class ProfilesModal extends HookConsumerWidget {
|
||||
itemCount: profiles.length,
|
||||
),
|
||||
AsyncError(:final error) => SliverErrorBodyPlaceholder(
|
||||
t.presentError(error),
|
||||
t.printError(error),
|
||||
),
|
||||
AsyncLoading() => const SliverLoadingBodyPlaceholder(),
|
||||
_ => const SliverToBoxAdapter(),
|
||||
|
||||
@@ -22,7 +22,7 @@ class ProxiesPage extends HookConsumerWidget with PresLogger {
|
||||
|
||||
final selectActiveProxyMutation = useMutation(
|
||||
initialOnFailure: (error) =>
|
||||
CustomToast.error(t.presentError(error)).show(context),
|
||||
CustomToast.error(t.printError(error)).show(context),
|
||||
);
|
||||
|
||||
switch (asyncProxies) {
|
||||
@@ -148,7 +148,7 @@ class ProxiesPage extends HookConsumerWidget with PresLogger {
|
||||
title: Text(t.proxies.pageTitle.titleCase),
|
||||
),
|
||||
SliverErrorBodyPlaceholder(
|
||||
t.presentError(error),
|
||||
t.printError(error),
|
||||
icon: null,
|
||||
),
|
||||
],
|
||||
|
||||
@@ -11,6 +11,12 @@ class CustomAlertDialog extends StatelessWidget {
|
||||
final String? title;
|
||||
final String message;
|
||||
|
||||
factory CustomAlertDialog.fromErr(({String type, String? message}) err) =>
|
||||
CustomAlertDialog(
|
||||
title: err.message == null ? null : err.type,
|
||||
message: err.message ?? err.type,
|
||||
);
|
||||
|
||||
Future<void> show(BuildContext context) async {
|
||||
await showDialog(
|
||||
context: context,
|
||||
|
||||
Reference in New Issue
Block a user