Chat, chat local db, chat messaging retriving (no sync yet)

This commit is contained in:
2025-05-03 14:19:46 +08:00
parent b2c31bcf13
commit e2e6de965b
30 changed files with 258 additions and 206 deletions

View File

@ -1,100 +1,32 @@
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/database/drift_db.dart';
import 'package:island/database/message.dart';
import 'package:island/database/message_repository.dart';
import 'package:island/models/chat.dart';
import 'package:island/pods/network.dart';
import 'package:island/widgets/alert.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
// Global database instance
final databaseProvider = Provider<AppDatabase>((ref) {
final db = AppDatabase();
ref.onDispose(() => db.close());
return db;
});
final messageRepositoryProvider =
FutureProvider.family<MessageRepository, SnChat>((ref, chat) async {
final apiClient = ref.watch(apiClientProvider);
final database = ref.watch(databaseProvider);
return MessageRepository(chat, apiClient, database);
});
Future<void> resetDatabase(WidgetRef ref) async {
if (kIsWeb) return;
final chatMessagesProvider =
FutureProvider.family<List<LocalChatMessage>, SnChat>((ref, room) async {
final repository = await ref.watch(
messageRepositoryProvider(room).future,
);
return repository.listMessages();
});
final db = ref.read(databaseProvider);
final basepath = await getApplicationSupportDirectory();
final file = File(join(basepath.path, 'solar_network_data.sqlite'));
class ChatMessageNotifier
extends StateNotifier<AsyncValue<List<LocalChatMessage>>> {
final MessageRepository _repository;
final int roomId;
int _currentOffset = 0;
final int _pageSize = 20;
bool _hasMore = true;
// Close current database connection
db.close();
ChatMessageNotifier(this._repository, this.roomId)
: super(const AsyncValue.loading()) {
loadInitial();
// Delete database file
if (await file.exists()) {
await file.delete();
}
Future<void> loadInitial() async {
state = const AsyncValue.loading();
try {
final messages = await _repository.listMessages(
offset: 0,
take: _pageSize,
);
_currentOffset = messages.length;
_hasMore = messages.length >= _pageSize;
state = AsyncValue.data(messages);
} catch (e, stack) {
state = AsyncValue.error(e, stack);
}
}
Future<void> loadMore() async {
if (!_hasMore) return;
try {
final newMessages = await _repository.listMessages(
offset: _currentOffset,
take: _pageSize,
);
if (newMessages.isEmpty) {
_hasMore = false;
return;
}
_currentOffset += newMessages.length;
_hasMore = newMessages.length >= _pageSize;
state = AsyncValue.data([...state.value ?? [], ...newMessages]);
} catch (err) {
showErrorAlert(err);
}
}
Future<void> sendMessage(String content) async {
try {
final message = await _repository.sendMessage(roomId, content);
final currentMessages = state.value ?? [];
state = AsyncValue.data([message, ...currentMessages]);
} catch (err) {
showErrorAlert(err);
}
}
bool get hasMore => _hasMore;
// Force refresh the database provider
ref.invalidate(databaseProvider);
}
final chatMessageNotifierProvider = StateNotifierProvider.family<
ChatMessageNotifier,
AsyncValue<List<LocalChatMessage>>,
MessageRepository
>((ref, repository) => ChatMessageNotifier(repository, repository.room.id));

View File

@ -21,7 +21,6 @@ class UserInfoNotifier extends StateNotifier<AsyncValue<SnAccount?>> {
final user = SnAccount.fromJson(response.data);
state = AsyncValue.data(user);
} catch (error, stackTrace) {
print('Failed to fetch user: $error');
state = AsyncValue.error(error, stackTrace);
}
}