forked from eatvio/eatvio_app
feat(push_notifications): issue-660, fix: issue-908
This commit is contained in:
@@ -2,10 +2,12 @@ import 'dart:developer';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:eatvio_app/core/error_reporting/report_from.dart';
|
||||
import 'package:eatvio_app/features/menu/presentation/bloc/notification_settings_cubit/notification_settings_state.dart';
|
||||
import 'package:eatvio_app/features/menu/presentation/notification_settings_user_message.dart';
|
||||
import 'package:eatvio_app/features/menu/repositories/notification_settings_repository.dart';
|
||||
|
||||
class NotificationSettingsCubit extends Cubit<NotificationSettingsState> {
|
||||
final NotificationSettingsRepository _notificationSettingsRepository;
|
||||
int _alertSeq = 0;
|
||||
|
||||
NotificationSettingsCubit({required NotificationSettingsRepository notificationSettingsRepository})
|
||||
: _notificationSettingsRepository = notificationSettingsRepository,
|
||||
@@ -30,6 +32,17 @@ class NotificationSettingsCubit extends Cubit<NotificationSettingsState> {
|
||||
} catch (e, stackTrace) {
|
||||
await reportFrom(e, stackTrace, this);
|
||||
log('Error updating notification settings: $e', stackTrace: stackTrace);
|
||||
final current = state;
|
||||
if (current is NotificationSettingsStateLoaded) {
|
||||
emit(
|
||||
NotificationSettingsStateLoaded(
|
||||
notificationSettings: current.notificationSettings,
|
||||
alertMessage: notificationSettingsUpdateAlertMessage(e),
|
||||
alertId: ++_alertSeq,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
emit(NotificationSettingsStateError(errorMessage: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,11 +14,17 @@ class NotificationSettingsStateLoading extends NotificationSettingsState {
|
||||
|
||||
class NotificationSettingsStateLoaded extends NotificationSettingsState {
|
||||
final NotificationSettingsModel notificationSettings;
|
||||
final String? alertMessage;
|
||||
final int? alertId;
|
||||
|
||||
const NotificationSettingsStateLoaded({required this.notificationSettings});
|
||||
const NotificationSettingsStateLoaded({
|
||||
required this.notificationSettings,
|
||||
this.alertMessage,
|
||||
this.alertId,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [notificationSettings];
|
||||
List<Object?> get props => [notificationSettings, alertMessage, alertId];
|
||||
}
|
||||
|
||||
class NotificationSettingsStateError extends NotificationSettingsState {
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import 'package:dio/dio.dart';
|
||||
|
||||
const notificationSettingsSaveFailedMessage =
|
||||
'Не удалось сохранить настройки уведомлений';
|
||||
|
||||
|
||||
String notificationSettingsUpdateAlertMessage(Object error) {
|
||||
final validationMessage = _validationMessage(error);
|
||||
if (validationMessage != null) return validationMessage;
|
||||
return notificationSettingsSaveFailedMessage;
|
||||
}
|
||||
|
||||
String? _validationMessage(Object error) {
|
||||
if (error is! DioException || error.response?.statusCode != 422) return null;
|
||||
|
||||
final data = error.response?.data;
|
||||
if (data is! Map) return null;
|
||||
|
||||
final errors = data['errors'];
|
||||
if (errors is Map) {
|
||||
for (final value in errors.values) {
|
||||
final text = _firstErrorText(value);
|
||||
if (text != null) return text;
|
||||
}
|
||||
}
|
||||
|
||||
final message = data['message'];
|
||||
if (message is String && message.trim().isNotEmpty) return message.trim();
|
||||
return null;
|
||||
}
|
||||
|
||||
String? _firstErrorText(Object? value) {
|
||||
if (value is List) {
|
||||
for (final item in value) {
|
||||
final text = item.toString().trim();
|
||||
if (text.isNotEmpty) return text;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (value is String && value.trim().isNotEmpty) return value.trim();
|
||||
return null;
|
||||
}
|
||||
@@ -27,7 +27,37 @@ class NotificationsSettingsContent extends StatelessWidget {
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: Text(s.notifications)),
|
||||
body: BlocBuilder<NotificationSettingsCubit, NotificationSettingsState>(
|
||||
body: BlocConsumer<NotificationSettingsCubit, NotificationSettingsState>(
|
||||
listenWhen: (previous, current) {
|
||||
if (current is! NotificationSettingsStateLoaded || current.alertId == null) {
|
||||
return false;
|
||||
}
|
||||
final previousId = previous is NotificationSettingsStateLoaded ? previous.alertId : null;
|
||||
return current.alertId != previousId;
|
||||
},
|
||||
listener: (context, state) {
|
||||
if (state is! NotificationSettingsStateLoaded) {
|
||||
return;
|
||||
}
|
||||
final message = state.alertMessage;
|
||||
if (message == null || message.isEmpty) {
|
||||
return;
|
||||
}
|
||||
showCupertinoDialog<void>(
|
||||
context: context,
|
||||
builder: (dialogContext) {
|
||||
return CupertinoAlertDialog(
|
||||
content: Text(message),
|
||||
actions: [
|
||||
CupertinoDialogAction(
|
||||
onPressed: () => Navigator.of(dialogContext).pop(),
|
||||
child: const Text('OK'),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
builder: (context, state) {
|
||||
if (state is NotificationSettingsStateLoading) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:eatvio_app/core/app_config.dart';
|
||||
import 'package:eatvio_app/core/locator_service.dart';
|
||||
import 'package:eatvio_app/core/utils/url_utils.dart';
|
||||
import 'package:eatvio_app/features/menu/presentation/blocked_user_cubit/blocked_users_cubit.dart';
|
||||
import 'package:eatvio_app/features/profile/models/profile_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -18,16 +19,20 @@ class _BlockedUserWidgetState extends State<BlockedUserWidget> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InkWell(
|
||||
onTap: () => GoRouter.of(context).pushNamed(
|
||||
'profileScreen',
|
||||
extra: widget.profile.slug,
|
||||
),
|
||||
onTap: () => GoRouter.of(
|
||||
context,
|
||||
).pushNamed('profileScreen', extra: widget.profile.slug),
|
||||
child: Ink(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
|
||||
child: Row(
|
||||
children: [
|
||||
CircleAvatar(
|
||||
foregroundImage: NetworkImage(sl<AppConfig>().baseUrl + widget.profile.profilePhotoUrl),
|
||||
foregroundImage: NetworkImage(
|
||||
joinBaseUrl(
|
||||
sl<AppConfig>().baseUrl,
|
||||
widget.profile.profilePhotoUrl,
|
||||
),
|
||||
),
|
||||
backgroundImage: const AssetImage('assets/images/no_avatar.png'),
|
||||
radius: 28,
|
||||
),
|
||||
@@ -50,11 +55,16 @@ class _BlockedUserWidgetState extends State<BlockedUserWidget> {
|
||||
const Spacer(),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
context.read<BlockedUsersCubit>().unblockUser(widget.profile.slug);
|
||||
context.read<BlockedUsersCubit>().unblockUser(
|
||||
widget.profile.slug,
|
||||
);
|
||||
},
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
child: Ink(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 8,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFF1F2F6),
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
|
||||
Reference in New Issue
Block a user