refactor: conditionalize profile fields, update chat navigation transitions, and fix provider state management during widget lifecycle

This commit is contained in:
pradeepkumar
2026-03-31 13:05:49 +05:30
parent 418e350fad
commit a96a7b84d8
4 changed files with 36 additions and 17 deletions

View File

@@ -75,7 +75,8 @@ class MessagingNotifier extends StateNotifier<MessagingState> {
MessagingNotifier(this._repository, this._ref)
: super(const MessagingState()) {
_initSocketListeners();
loadUnreadCount();
// Defer to avoid modifying provider during widget tree build
Future.microtask(() => loadUnreadCount());
}
String? get _currentUserId => _ref.read(authProvider).user?.id;
@@ -529,6 +530,7 @@ class MessagingNotifier extends StateNotifier<MessagingState> {
Future<void> markAsRead(String conversationId) async {
try {
await _repository.markAsRead(conversationId);
if (!mounted) return;
final updatedConversations = state.conversations.map((c) {
if (c.id == conversationId) {
@@ -550,6 +552,7 @@ class MessagingNotifier extends StateNotifier<MessagingState> {
}
void setActiveConversation(String? conversationId) {
if (!mounted) return;
if (conversationId == null) {
state = state.copyWith(clearActiveConversation: true);
} else {
@@ -560,7 +563,7 @@ class MessagingNotifier extends StateNotifier<MessagingState> {
Future<void> loadUnreadCount() async {
try {
final count = await _repository.getUnreadCount();
state = state.copyWith(unreadCount: count);
if (mounted) state = state.copyWith(unreadCount: count);
} catch (_) {}
}

View File

@@ -90,16 +90,12 @@ class _ChatScreenState extends ConsumerState<ChatScreen>
}
}
@override
@override
void deactivate() {
// Clear active conversation while ref is still valid (before dispose)
ref.read(messagingProvider.notifier).setActiveConversation(null);
super.deactivate();
}
@override
void dispose() {
// Defer provider modification to avoid "modify during build" error
final notifier = ref.read(messagingProvider.notifier);
Future.microtask(() => notifier.setActiveConversation(null));
WidgetsBinding.instance.removeObserver(this);
_connectionSub?.cancel();
// Stop typing and leave room before disposing

View File

@@ -262,12 +262,14 @@ class _ProfileSettingsTabState extends ConsumerState<ProfileSettingsTab> {
const SizedBox(height: 24),
ProfileFormField(label: 'Full Name', controller: _fullNameController),
const SizedBox(height: 24),
ProfileFormField(
label: isAgent ? 'Career / Agent Type' : 'Professional Title',
controller: _titleController,
enabled: false,
),
if (isAgent) ...[
const SizedBox(height: 24),
ProfileFormField(
label: 'Career / Agent Type',
controller: _titleController,
enabled: false,
),
],
const SizedBox(height: 24),
ProfileFormField(
label: 'Email Address',

View File

@@ -160,7 +160,9 @@ final routerProvider = Provider<GoRouter>((ref) {
return CustomTransitionPage(
key: state.pageKey,
child: ChatScreen(conversationId: id),
transitionsBuilder: _fadeTransition,
transitionDuration: const Duration(milliseconds: 250),
reverseTransitionDuration: const Duration(milliseconds: 200),
transitionsBuilder: _slideTransition,
);
},
),
@@ -272,6 +274,22 @@ class _HomeRouteWrapper extends ConsumerWidget {
}
}
/// Slide from right transition for push-style navigation.
Widget _slideTransition(
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
Widget child,
) {
return SlideTransition(
position: Tween<Offset>(
begin: const Offset(1, 0),
end: Offset.zero,
).animate(CurvedAnimation(parent: animation, curve: Curves.easeOut)),
child: child,
);
}
/// Smooth fade transition for tab-to-tab navigation.
Widget _fadeTransition(
BuildContext context,