Phase 3.2 docs + Phase 3.1 testing fixes

- Add phase3.2.md requirement: overlay UX, mitra activity log
- Add phase3.2-plan.md implementation plan
- Fix stale request validation: add GET /:sessionId/status endpoint
- Fix notification tap flow: setIncomingFromNotification + onChatRequestTapped
- IncomingRequestSheet shows stale message instead of auto-dismiss
- Home screen validates on resume, shows immediately on fresh WS

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-09 22:09:25 +08:00
parent e3da863f3c
commit 4158fb9432
7 changed files with 427 additions and 13 deletions

View File

@@ -130,19 +130,26 @@ class ChatRequest extends _$ChatRequest {
}
}
/// Called when user taps a chat_request notification. Sets the incoming state
/// with the given session and validates it's still pending.
Future<void> setIncomingFromNotification(String sessionId) async {
state = ChatRequestIncomingData(sessionId);
await validateIncomingRequest();
}
/// Check if the current incoming request is still valid (pending_acceptance).
/// If stale, reset to listening state.
Future<void> validateIncomingRequest() async {
if (state is! ChatRequestIncomingData) return;
final sessionId = (state as ChatRequestIncomingData).sessionId;
try {
final response = await _apiClient.get('/api/shared/chat/$sessionId/info');
final response = await _apiClient.get('/api/mitra/chat-requests/$sessionId/status');
final status = response['data']?['status'] as String?;
if (status != 'pending_acceptance') {
state = const ChatRequestListeningData();
}
} catch (_) {
state = const ChatRequestListeningData();
// On error, keep current state — don't dismiss valid requests
}
}

View File

@@ -8,6 +8,10 @@ class NotificationService {
static final _localNotifications = FlutterLocalNotificationsPlugin();
static GoRouter? _router;
/// Callback for when a chat request notification is tapped.
/// Set this from the app to bridge notifications → Riverpod state.
static void Function(String sessionId)? onChatRequestTapped;
static const _channel = AndroidNotificationChannel(
'chat_messages',
'Chat Messages',
@@ -119,8 +123,9 @@ class NotificationService {
final type = data['type'] as String?;
final action = data['action'] as String?;
if (type == 'chat_request' && action == 'open_accept') {
// Navigate to home where incoming request sheet will show
if (type == 'chat_request' && action == 'open_accept' && sessionId != null) {
// Update the notifier state with this session, then navigate
onChatRequestTapped?.call(sessionId);
_router!.go('/home');
} else if (type == 'session_closing' || type == 'session_expired') {
// Navigate to the chat session closure screen