♻️ Remove platform alert and use flutter dialog instead
This commit is contained in:
@@ -5,7 +5,8 @@ import 'package:dio/dio.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:firebase_analytics/firebase_analytics.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_platform_alert/flutter_platform_alert.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:island/widgets/alert.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/models/account.dart';
|
||||
@@ -36,9 +37,12 @@ class UserInfoNotifier extends StateNotifier<AsyncValue<SnAccount?>> {
|
||||
} catch (error, stackTrace) {
|
||||
if (!kIsWeb) {
|
||||
if (error is DioException) {
|
||||
FlutterPlatformAlert.showCustomAlert(
|
||||
windowTitle: 'failedToLoadUserInfo'.tr(),
|
||||
text: [
|
||||
showOverlayDialog<bool>(
|
||||
builder:
|
||||
(context, close) => AlertDialog(
|
||||
title: Text('failedToLoadUserInfo'.tr()),
|
||||
content: Text(
|
||||
[
|
||||
(error.response?.statusCode == 401
|
||||
? 'failedToLoadUserInfoUnauthorized'
|
||||
: 'failedToLoadUserInfoNetwork')
|
||||
@@ -46,31 +50,52 @@ class UserInfoNotifier extends StateNotifier<AsyncValue<SnAccount?>> {
|
||||
.trim(),
|
||||
'',
|
||||
'${error.response?.statusCode ?? 'Network Error'}',
|
||||
if (error.response?.headers != null) error.response?.headers,
|
||||
if (error.response?.headers != null)
|
||||
error.response?.headers,
|
||||
if (error.response?.data != null)
|
||||
jsonEncode(error.response?.data),
|
||||
].join('\n'),
|
||||
iconStyle: IconStyle.error,
|
||||
neutralButtonTitle: 'retry'.tr(),
|
||||
negativeButtonTitle: 'okay'.tr(),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => close(false),
|
||||
child: Text('okay'.tr()),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => close(true),
|
||||
child: Text('retry'.tr()),
|
||||
),
|
||||
],
|
||||
),
|
||||
).then((value) {
|
||||
if (value == CustomButton.neutralButton) {
|
||||
if (value == true) {
|
||||
fetchUser();
|
||||
}
|
||||
});
|
||||
}
|
||||
FlutterPlatformAlert.showCustomAlert(
|
||||
windowTitle: 'failedToLoadUserInfo'.tr(),
|
||||
text:
|
||||
showOverlayDialog<bool>(
|
||||
builder:
|
||||
(context, close) => AlertDialog(
|
||||
title: Text('failedToLoadUserInfo'.tr()),
|
||||
content: Text(
|
||||
[
|
||||
'failedToLoadUserInfoNetwork'.tr(),
|
||||
error.toString(),
|
||||
].join('\n\n').trim(),
|
||||
iconStyle: IconStyle.error,
|
||||
neutralButtonTitle: 'retry'.tr(),
|
||||
negativeButtonTitle: 'okay'.tr(),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => close(false),
|
||||
child: Text('okay'.tr()),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => close(true),
|
||||
child: Text('retry'.tr()),
|
||||
),
|
||||
],
|
||||
),
|
||||
).then((value) {
|
||||
if (value == CustomButton.neutralButton) {
|
||||
if (value == true) {
|
||||
fetchUser();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:island/main.dart';
|
||||
import 'package:island/talker.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
import 'package:top_snackbar_flutter/top_snack_bar.dart';
|
||||
|
||||
export 'content/alert.native.dart'
|
||||
if (dart.library.html) 'content/alert.web.dart';
|
||||
|
||||
void showSnackBar(String message, {SnackBarAction? action}) {
|
||||
final context = globalOverlay.currentState!.context;
|
||||
final screenWidth = MediaQuery.of(context).size.width;
|
||||
@@ -56,6 +57,11 @@ class _FadeOverlayState extends State<_FadeOverlay> {
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> animateOut() async {
|
||||
setState(() => _visible = false);
|
||||
await Future.delayed(const Duration(milliseconds: 200));
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnimatedOpacity(
|
||||
@@ -106,10 +112,138 @@ void hideLoadingModal(BuildContext context) async {
|
||||
final state = entry.mounted ? _loadingOverlayKey.currentState : null;
|
||||
|
||||
if (state != null) {
|
||||
// ignore: invalid_use_of_protected_member
|
||||
state.setState(() => state._visible = false);
|
||||
await Future.delayed(const Duration(milliseconds: 200));
|
||||
await state.animateOut();
|
||||
}
|
||||
|
||||
entry.remove();
|
||||
}
|
||||
|
||||
String _parseRemoteError(DioException err) {
|
||||
String? message;
|
||||
if (err.response?.data is String) {
|
||||
message = err.response?.data;
|
||||
} else if (err.response?.data?['message'] != null) {
|
||||
message = <String?>[
|
||||
err.response?.data?['message']?.toString(),
|
||||
err.response?.data?['detail']?.toString(),
|
||||
].where((e) => e != null).cast<String>().map((e) => e.trim()).join('\n');
|
||||
} else if (err.response?.data?['errors'] != null) {
|
||||
final errors = err.response?.data['errors'] as Map<String, dynamic>;
|
||||
message = errors.values
|
||||
.map(
|
||||
(ele) =>
|
||||
(ele as List<dynamic>).map((ele) => ele.toString()).join('\n'),
|
||||
)
|
||||
.join('\n');
|
||||
}
|
||||
if (message == null || message.isEmpty) message = err.response?.statusMessage;
|
||||
message ??= err.message;
|
||||
return message ?? err.toString();
|
||||
}
|
||||
|
||||
Future<T?> showOverlayDialog<T>({
|
||||
required Widget Function(BuildContext context, void Function(T? result) close)
|
||||
builder,
|
||||
bool barrierDismissible = true,
|
||||
}) {
|
||||
final completer = Completer<T?>();
|
||||
final key = GlobalKey<_FadeOverlayState>();
|
||||
late OverlayEntry entry;
|
||||
|
||||
void close(T? result) async {
|
||||
if (completer.isCompleted) return;
|
||||
|
||||
final state = key.currentState;
|
||||
if (state != null) {
|
||||
await state.animateOut();
|
||||
}
|
||||
|
||||
entry.remove();
|
||||
completer.complete(result);
|
||||
}
|
||||
|
||||
entry = OverlayEntry(
|
||||
builder:
|
||||
(context) => _FadeOverlay(
|
||||
key: key,
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: GestureDetector(
|
||||
onTap: barrierDismissible ? () => close(null) : null,
|
||||
behavior: HitTestBehavior.opaque,
|
||||
child: const ColoredBox(color: Colors.black54),
|
||||
),
|
||||
),
|
||||
Center(child: builder(context, close)),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
globalOverlay.currentState!.insert(entry);
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
void showErrorAlert(dynamic err) {
|
||||
if (err is Error) {
|
||||
talker.error('Something went wrong...', err, err.stackTrace);
|
||||
}
|
||||
final text = switch (err) {
|
||||
String _ => err,
|
||||
DioException _ => _parseRemoteError(err),
|
||||
Exception _ => err.toString(),
|
||||
_ => err.toString(),
|
||||
};
|
||||
|
||||
showOverlayDialog<void>(
|
||||
builder:
|
||||
(context, close) => AlertDialog(
|
||||
title: Text('somethingWentWrong'.tr()),
|
||||
content: Text(text),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => close(null),
|
||||
child: Text(MaterialLocalizations.of(context).okButtonLabel),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void showInfoAlert(String message, String title) {
|
||||
showOverlayDialog<void>(
|
||||
builder:
|
||||
(context, close) => AlertDialog(
|
||||
title: Text(title),
|
||||
content: Text(message),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => close(null),
|
||||
child: Text(MaterialLocalizations.of(context).okButtonLabel),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<bool> showConfirmAlert(String message, String title) async {
|
||||
final result = await showOverlayDialog<bool>(
|
||||
builder:
|
||||
(context, close) => AlertDialog(
|
||||
title: Text(title),
|
||||
content: Text(message),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => close(false),
|
||||
child: Text(MaterialLocalizations.of(context).cancelButtonLabel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => close(true),
|
||||
child: Text(MaterialLocalizations.of(context).okButtonLabel),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
return result ?? false;
|
||||
}
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter_platform_alert/flutter_platform_alert.dart';
|
||||
import 'package:island/talker.dart';
|
||||
|
||||
String _parseRemoteError(DioException err) {
|
||||
String? message;
|
||||
if (err.response?.data is String) {
|
||||
message = err.response?.data;
|
||||
} else if (err.response?.data?['message'] != null) {
|
||||
message = <String?>[
|
||||
err.response?.data?['message']?.toString(),
|
||||
err.response?.data?['detail']?.toString(),
|
||||
].where((e) => e != null).cast<String>().map((e) => e.trim()).join('\n');
|
||||
} else if (err.response?.data?['errors'] != null) {
|
||||
final errors = err.response?.data['errors'] as Map<String, dynamic>;
|
||||
message = errors.values
|
||||
.map(
|
||||
(ele) =>
|
||||
(ele as List<dynamic>).map((ele) => ele.toString()).join('\n'),
|
||||
)
|
||||
.join('\n');
|
||||
}
|
||||
if (message == null || message.isEmpty) message = err.response?.statusMessage;
|
||||
message ??= err.message;
|
||||
return message ?? err.toString();
|
||||
}
|
||||
|
||||
void showErrorAlert(dynamic err) async {
|
||||
if (err is Error) {
|
||||
talker.error('Something went wrong...', err, err.stackTrace);
|
||||
}
|
||||
final text = switch (err) {
|
||||
String _ => err,
|
||||
DioException _ => _parseRemoteError(err),
|
||||
Exception _ => err.toString(),
|
||||
_ => err.toString(),
|
||||
};
|
||||
FlutterPlatformAlert.showAlert(
|
||||
windowTitle: 'somethingWentWrong'.tr(),
|
||||
text: text,
|
||||
alertStyle: AlertButtonStyle.ok,
|
||||
iconStyle: IconStyle.error,
|
||||
);
|
||||
}
|
||||
|
||||
void showInfoAlert(String message, String title) async {
|
||||
FlutterPlatformAlert.showAlert(
|
||||
windowTitle: title,
|
||||
text: message,
|
||||
alertStyle: AlertButtonStyle.ok,
|
||||
iconStyle: IconStyle.information,
|
||||
);
|
||||
}
|
||||
|
||||
Future<bool> showConfirmAlert(String message, String title) async {
|
||||
final result = await FlutterPlatformAlert.showAlert(
|
||||
windowTitle: title,
|
||||
text: message,
|
||||
alertStyle: AlertButtonStyle.okCancel,
|
||||
iconStyle: IconStyle.question,
|
||||
);
|
||||
return result == AlertButton.okButton;
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
// ignore_for_file: avoid_web_libraries_in_flutter
|
||||
|
||||
import 'dart:js' as js;
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
|
||||
String _parseRemoteError(DioException err) {
|
||||
String? message;
|
||||
if (err.response?.data is String) {
|
||||
message = err.response?.data;
|
||||
} else if (err.response?.data?['message'] != null) {
|
||||
message = <String?>[
|
||||
err.response?.data?['message']?.toString(),
|
||||
err.response?.data?['detail']?.toString(),
|
||||
].where((e) => e != null).cast<String>().map((e) => e.trim()).join('\n');
|
||||
} else if (err.response?.data?['errors'] != null) {
|
||||
final errors = err.response?.data['errors'] as Map<String, dynamic>;
|
||||
message = errors.values
|
||||
.map(
|
||||
(ele) =>
|
||||
(ele as List<dynamic>).map((ele) => ele.toString()).join('\n'),
|
||||
)
|
||||
.join('\n');
|
||||
}
|
||||
if (message == null || message.isEmpty) message = err.response?.statusMessage;
|
||||
message ??= err.message;
|
||||
return message ?? err.toString();
|
||||
}
|
||||
|
||||
void showErrorAlert(dynamic err) async {
|
||||
final text = switch (err) {
|
||||
String _ => err,
|
||||
DioException _ => _parseRemoteError(err),
|
||||
Exception _ => err.toString(),
|
||||
_ => err.toString(),
|
||||
};
|
||||
js.context.callMethod('swal', ['somethingWentWrong'.tr(), text, 'error']);
|
||||
}
|
||||
|
||||
void showInfoAlert(String message, String title) async {
|
||||
js.context.callMethod('swal', [title, message, 'info']);
|
||||
}
|
||||
|
||||
Future<bool> showConfirmAlert(String message, String title) async {
|
||||
final result = await js.context.callMethod('swal', [
|
||||
title,
|
||||
message,
|
||||
'question',
|
||||
{'buttons': true},
|
||||
]);
|
||||
return result == true;
|
||||
}
|
||||
@@ -9,7 +9,6 @@
|
||||
#include <desktop_drop/desktop_drop_plugin.h>
|
||||
#include <file_saver/file_saver_plugin.h>
|
||||
#include <file_selector_linux/file_selector_plugin.h>
|
||||
#include <flutter_platform_alert/flutter_platform_alert_plugin.h>
|
||||
#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h>
|
||||
#include <flutter_timezone/flutter_timezone_plugin.h>
|
||||
#include <flutter_udid/flutter_udid_plugin.h>
|
||||
@@ -38,9 +37,6 @@ void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
|
||||
file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
|
||||
g_autoptr(FlPluginRegistrar) flutter_platform_alert_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterPlatformAlertPlugin");
|
||||
flutter_platform_alert_plugin_register_with_registrar(flutter_platform_alert_registrar);
|
||||
g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin");
|
||||
flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar);
|
||||
|
||||
@@ -6,7 +6,6 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
||||
desktop_drop
|
||||
file_saver
|
||||
file_selector_linux
|
||||
flutter_platform_alert
|
||||
flutter_secure_storage_linux
|
||||
flutter_timezone
|
||||
flutter_udid
|
||||
|
||||
@@ -17,7 +17,6 @@ import firebase_crashlytics
|
||||
import firebase_messaging
|
||||
import flutter_inappwebview_macos
|
||||
import flutter_local_notifications
|
||||
import flutter_platform_alert
|
||||
import flutter_secure_storage_macos
|
||||
import flutter_timezone
|
||||
import flutter_udid
|
||||
@@ -59,7 +58,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin"))
|
||||
InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin"))
|
||||
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
|
||||
FlutterPlatformAlertPlugin.register(with: registry.registrar(forPlugin: "FlutterPlatformAlertPlugin"))
|
||||
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
|
||||
FlutterTimezonePlugin.register(with: registry.registrar(forPlugin: "FlutterTimezonePlugin"))
|
||||
FlutterUdidPlugin.register(with: registry.registrar(forPlugin: "FlutterUdidPlugin"))
|
||||
|
||||
@@ -1019,14 +1019,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.1+1"
|
||||
flutter_platform_alert:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_platform_alert
|
||||
sha256: "70f4979a617388cd890ec32e9acc1a6a425bcdf3d8b444eb976be1834e79dc0c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.8.0"
|
||||
flutter_plugin_android_lifecycle:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -61,7 +61,7 @@ dependencies:
|
||||
media_kit_video: ^2.0.0
|
||||
media_kit_libs_video: ^1.0.7
|
||||
flutter_cache_manager: ^3.4.1
|
||||
flutter_platform_alert: ^0.8.0
|
||||
|
||||
email_validator: ^3.0.0
|
||||
easy_localization: ^3.0.8
|
||||
flutter_inappwebview: ^6.1.5
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include <file_selector_windows/file_selector_windows.h>
|
||||
#include <firebase_core/firebase_core_plugin_c_api.h>
|
||||
#include <flutter_inappwebview_windows/flutter_inappwebview_windows_plugin_c_api.h>
|
||||
#include <flutter_platform_alert/flutter_platform_alert_plugin.h>
|
||||
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
|
||||
#include <flutter_timezone/flutter_timezone_plugin_c_api.h>
|
||||
#include <flutter_udid/flutter_udid_plugin_c_api.h>
|
||||
@@ -52,8 +51,6 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
registry->GetRegistrarForPlugin("FirebaseCorePluginCApi"));
|
||||
FlutterInappwebviewWindowsPluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FlutterInappwebviewWindowsPluginCApi"));
|
||||
FlutterPlatformAlertPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FlutterPlatformAlertPlugin"));
|
||||
FlutterSecureStorageWindowsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
|
||||
FlutterTimezonePluginCApiRegisterWithRegistrar(
|
||||
|
||||
@@ -10,7 +10,6 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
||||
file_selector_windows
|
||||
firebase_core
|
||||
flutter_inappwebview_windows
|
||||
flutter_platform_alert
|
||||
flutter_secure_storage_windows
|
||||
flutter_timezone
|
||||
flutter_udid
|
||||
|
||||
Reference in New Issue
Block a user