62 lines
1.7 KiB
Dart
62 lines
1.7 KiB
Dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:supabase_flutter/supabase_flutter.dart';
|
|
|
|
import '../models/chat_message.dart';
|
|
import 'supabase_provider.dart';
|
|
import 'stream_recovery.dart';
|
|
import 'realtime_controller.dart';
|
|
|
|
/// Real-time chat messages for a swap request thread.
|
|
final chatMessagesProvider = StreamProvider.family<List<ChatMessage>, String>((
|
|
ref,
|
|
threadId,
|
|
) {
|
|
final client = ref.watch(supabaseClientProvider);
|
|
|
|
final wrapper = StreamRecoveryWrapper<ChatMessage>(
|
|
stream: client
|
|
.from('chat_messages')
|
|
.stream(primaryKey: ['id'])
|
|
.eq('thread_id', threadId)
|
|
.order('created_at'),
|
|
onPollData: () async {
|
|
final data = await client
|
|
.from('chat_messages')
|
|
.select()
|
|
.eq('thread_id', threadId)
|
|
.order('created_at');
|
|
return data.map(ChatMessage.fromMap).toList();
|
|
},
|
|
fromMap: ChatMessage.fromMap,
|
|
channelName: 'chat_messages_$threadId',
|
|
onStatusChanged: ref.read(realtimeControllerProvider).handleChannelStatus,
|
|
);
|
|
|
|
ref.onDispose(wrapper.dispose);
|
|
return wrapper.stream.map((result) => result.data);
|
|
});
|
|
|
|
final chatControllerProvider = Provider<ChatController>((ref) {
|
|
final client = ref.watch(supabaseClientProvider);
|
|
return ChatController(client);
|
|
});
|
|
|
|
class ChatController {
|
|
ChatController(this._client);
|
|
|
|
final SupabaseClient _client;
|
|
|
|
Future<void> sendMessage({
|
|
required String threadId,
|
|
required String body,
|
|
}) async {
|
|
final userId = _client.auth.currentUser?.id;
|
|
if (userId == null) throw Exception('Not authenticated');
|
|
await _client.from('chat_messages').insert({
|
|
'thread_id': threadId,
|
|
'sender_id': userId,
|
|
'body': body,
|
|
});
|
|
}
|
|
}
|