feat: Implement real-time agent connection state updates and enhance app shell navigation transitions.
This commit is contained in:
@@ -41,9 +41,17 @@ class _AppShellState extends State<AppShell> {
|
|||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: AnimatedSwitcher(
|
child: AnimatedSwitcher(
|
||||||
duration: const Duration(milliseconds: 200),
|
duration: const Duration(milliseconds: 150),
|
||||||
switchInCurve: Curves.easeOut,
|
|
||||||
switchOutCurve: Curves.easeIn,
|
switchOutCurve: Curves.easeIn,
|
||||||
|
switchInCurve: Curves.easeOut,
|
||||||
|
layoutBuilder: (currentChild, previousChildren) {
|
||||||
|
return Stack(
|
||||||
|
children: [
|
||||||
|
...previousChildren,
|
||||||
|
if (currentChild != null) currentChild,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
transitionBuilder: (child, animation) {
|
transitionBuilder: (child, animation) {
|
||||||
return FadeTransition(
|
return FadeTransition(
|
||||||
opacity: animation,
|
opacity: animation,
|
||||||
@@ -51,7 +59,7 @@ class _AppShellState extends State<AppShell> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: KeyedSubtree(
|
child: KeyedSubtree(
|
||||||
key: ValueKey(widget.child.runtimeType),
|
key: ValueKey(GoRouterState.of(context).uri.toString()),
|
||||||
child: widget.child,
|
child: widget.child,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:real_estate_mobile/features/agents/data/agents_repository.dart';
|
import 'package:real_estate_mobile/features/agents/data/agents_repository.dart';
|
||||||
import 'package:real_estate_mobile/features/agents/data/models/agent_profile.dart';
|
import 'package:real_estate_mobile/features/agents/data/models/agent_profile.dart';
|
||||||
import 'package:real_estate_mobile/features/agents/presentation/providers/agents_provider.dart';
|
import 'package:real_estate_mobile/features/agents/presentation/providers/agents_provider.dart';
|
||||||
|
import 'package:real_estate_mobile/features/messaging/data/socket_service.dart';
|
||||||
|
|
||||||
class AgentDetailState {
|
class AgentDetailState {
|
||||||
final AgentProfile? agent;
|
final AgentProfile? agent;
|
||||||
@@ -375,10 +378,22 @@ class SpecializationCard {
|
|||||||
class AgentDetailNotifier extends StateNotifier<AgentDetailState> {
|
class AgentDetailNotifier extends StateNotifier<AgentDetailState> {
|
||||||
final AgentsRepository _repo;
|
final AgentsRepository _repo;
|
||||||
final String agentId;
|
final String agentId;
|
||||||
|
StreamSubscription? _connectionResponseSub;
|
||||||
|
|
||||||
AgentDetailNotifier(this._repo, this.agentId)
|
AgentDetailNotifier(this._repo, this.agentId)
|
||||||
: super(const AgentDetailState()) {
|
: super(const AgentDetailState()) {
|
||||||
_load();
|
_load();
|
||||||
|
// Listen for real-time connection response (accepted/rejected)
|
||||||
|
_connectionResponseSub =
|
||||||
|
SocketService().onConnectionResponse.listen((_) {
|
||||||
|
if (mounted) loadConnectionStatus();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_connectionResponseSub?.cancel();
|
||||||
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _load() async {
|
Future<void> _load() async {
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:real_estate_mobile/features/agents/data/agents_repository.dart';
|
import 'package:real_estate_mobile/features/agents/data/agents_repository.dart';
|
||||||
|
import 'package:real_estate_mobile/features/messaging/data/socket_service.dart';
|
||||||
|
|
||||||
class AgentNetworkState {
|
class AgentNetworkState {
|
||||||
final List<Map<String, dynamic>> pendingRequests;
|
final List<Map<String, dynamic>> pendingRequests;
|
||||||
@@ -36,9 +39,21 @@ class AgentNetworkState {
|
|||||||
|
|
||||||
class AgentNetworkNotifier extends StateNotifier<AgentNetworkState> {
|
class AgentNetworkNotifier extends StateNotifier<AgentNetworkState> {
|
||||||
final AgentsRepository _repo;
|
final AgentsRepository _repo;
|
||||||
|
StreamSubscription? _connectionRequestSub;
|
||||||
|
|
||||||
AgentNetworkNotifier(this._repo) : super(const AgentNetworkState()) {
|
AgentNetworkNotifier(this._repo) : super(const AgentNetworkState()) {
|
||||||
loadData();
|
loadData();
|
||||||
|
// Listen for real-time connection request events
|
||||||
|
_connectionRequestSub =
|
||||||
|
SocketService().onConnectionRequest.listen((_) {
|
||||||
|
if (mounted) loadData();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_connectionRequestSub?.cancel();
|
||||||
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> loadData() async {
|
Future<void> loadData() async {
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ class SocketService {
|
|||||||
final _supportMessageController = StreamController<SupportMessage>.broadcast();
|
final _supportMessageController = StreamController<SupportMessage>.broadcast();
|
||||||
final _supportTypingStartController = StreamController<Map<String, dynamic>>.broadcast();
|
final _supportTypingStartController = StreamController<Map<String, dynamic>>.broadcast();
|
||||||
final _supportTypingStopController = StreamController<Map<String, dynamic>>.broadcast();
|
final _supportTypingStopController = StreamController<Map<String, dynamic>>.broadcast();
|
||||||
|
final _connectionRequestController = StreamController<Map<String, dynamic>>.broadcast();
|
||||||
|
final _connectionResponseController = StreamController<Map<String, dynamic>>.broadcast();
|
||||||
|
|
||||||
Stream<ChatMessage> get onNewMessage => _messageController.stream;
|
Stream<ChatMessage> get onNewMessage => _messageController.stream;
|
||||||
Stream<Map<String, dynamic>> get onTypingStart => _typingStartController.stream;
|
Stream<Map<String, dynamic>> get onTypingStart => _typingStartController.stream;
|
||||||
@@ -42,6 +44,8 @@ class SocketService {
|
|||||||
Stream<SupportMessage> get onSupportMessage => _supportMessageController.stream;
|
Stream<SupportMessage> get onSupportMessage => _supportMessageController.stream;
|
||||||
Stream<Map<String, dynamic>> get onSupportTypingStart => _supportTypingStartController.stream;
|
Stream<Map<String, dynamic>> get onSupportTypingStart => _supportTypingStartController.stream;
|
||||||
Stream<Map<String, dynamic>> get onSupportTypingStop => _supportTypingStopController.stream;
|
Stream<Map<String, dynamic>> get onSupportTypingStop => _supportTypingStopController.stream;
|
||||||
|
Stream<Map<String, dynamic>> get onConnectionRequest => _connectionRequestController.stream;
|
||||||
|
Stream<Map<String, dynamic>> get onConnectionResponse => _connectionResponseController.stream;
|
||||||
bool get isConnected => _isConnected;
|
bool get isConnected => _isConnected;
|
||||||
|
|
||||||
Future<void> connect() async {
|
Future<void> connect() async {
|
||||||
@@ -153,6 +157,15 @@ class SocketService {
|
|||||||
_supportTypingStopController.add(Map<String, dynamic>.from(data as Map));
|
_supportTypingStopController.add(Map<String, dynamic>.from(data as Map));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Connection request events (real-time updates)
|
||||||
|
_socket!.on('connection_request', (data) {
|
||||||
|
_connectionRequestController.add(Map<String, dynamic>.from(data as Map));
|
||||||
|
});
|
||||||
|
|
||||||
|
_socket!.on('connection_response', (data) {
|
||||||
|
_connectionResponseController.add(Map<String, dynamic>.from(data as Map));
|
||||||
|
});
|
||||||
|
|
||||||
_socket!.connect();
|
_socket!.connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,5 +287,7 @@ class SocketService {
|
|||||||
_supportMessageController.close();
|
_supportMessageController.close();
|
||||||
_supportTypingStartController.close();
|
_supportTypingStartController.close();
|
||||||
_supportTypingStopController.close();
|
_supportTypingStopController.close();
|
||||||
|
_connectionRequestController.close();
|
||||||
|
_connectionResponseController.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user