♻️ 使用 SQLITE 来存储本地消息记录 #1

Merged
LittleSheep merged 6 commits from features/local-message-history into master 2024-06-23 11:13:42 +00:00
3 changed files with 61 additions and 32 deletions
Showing only changes of commit 2038d33a31 - Show all commits

View File

@ -32,13 +32,14 @@ extension MessageHistoryHelper on MessageHistoryDb {
await localMessages.delete(id);
}
syncMessages(Channel channel, {String scope = 'global'}) async {
syncMessages(Channel channel, {String scope = 'global', offset = 0}) async {
final lastOne = await localMessages.findLastByChannel(channel.id);
final data = await _getRemoteMessages(
channel,
scope,
remainBreath: 5,
remainBreath: 3,
offset: offset,
onBrake: (items) {
return items.any((x) => x.id == lastOne?.id);
},

View File

@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:get/get.dart';
import 'package:solian/exts.dart';
import 'package:solian/models/call.dart';
@ -40,16 +41,20 @@ class ChannelChatScreen extends StatefulWidget {
}
class _ChannelChatScreenState extends State<ChannelChatScreen> {
final _chatScrollController = ScrollController();
bool _isBusy = false;
bool _isLoadingMore = false;
int? _accountId;
String? _overrideAlias;
Channel? _channel;
ChannelMember? _channelProfile;
Call? _ongoingCall;
ChannelMember? _channelProfile;
StreamSubscription<NetworkPackage>? _subscription;
int _nextHistorySyncOffset = 0;
MessageHistoryDb? _db;
List<LocalMessage> _currentHistory = List.empty();
@ -107,13 +112,19 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
}
Future<void> getMessages() async {
await _db!.syncMessages(_channel!, scope: widget.realm);
await _db!.syncMessages(
_channel!,
scope: widget.realm,
offset: _nextHistorySyncOffset,
);
await syncHistory();
}
Future<void> syncHistory() async {
_currentHistory = await _db!.localMessages.findAllByChannel(_channel!.id);
setState(() {});
final data = await _db!.localMessages.findAllByChannel(_channel!.id);
setState(() {
_currentHistory = data;
});
}
void listenMessages() {
@ -171,6 +182,31 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
Message? _messageToReplying;
Message? _messageToEditing;
Widget buildHistoryBody(Message item, {bool isMerged = false}) {
if (item.replyTo != null) {
return Column(
children: [
ChatMessage(
key: Key('m${item.replyTo!.uuid}'),
item: item.replyTo!,
isReply: true,
).paddingOnly(left: 24, right: 4, bottom: 2),
ChatMessage(
key: Key('m${item.uuid}'),
item: item,
isMerged: isMerged,
),
],
);
}
return ChatMessage(
key: Key('m${item.uuid}'),
item: item,
isMerged: isMerged,
);
}
Widget buildHistory(context, index) {
bool isMerged = false, hasMerged = false;
if (index > 0) {
@ -188,33 +224,9 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
final item = _currentHistory[index].data;
Widget content;
if (item.replyTo != null) {
content = Column(
children: [
ChatMessage(
key: Key('m${item.replyTo!.uuid}'),
item: item.replyTo!,
isReply: true,
).paddingOnly(left: 24, right: 4, bottom: 2),
ChatMessage(
key: Key('m${item.uuid}'),
item: item,
isMerged: isMerged,
),
],
);
} else {
content = ChatMessage(
key: Key('m${item.uuid}'),
item: item,
isMerged: isMerged,
);
}
return InkWell(
child: Container(
child: content.paddingOnly(
child: buildHistoryBody(item, isMerged: isMerged).paddingOnly(
top: !isMerged ? 8 : 0,
bottom: !hasMerged ? 8 : 0,
),
@ -241,6 +253,16 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
@override
void initState() {
_chatScrollController.addListener(() async {
if (_chatScrollController.position.pixels ==
_chatScrollController.position.maxScrollExtent) {
setState(() => _isLoadingMore = true);
_nextHistorySyncOffset = _currentHistory.length;
await getMessages();
setState(() => _isLoadingMore = false);
}
});
createHistoryDb().then((db) async {
_db = db;
@ -330,8 +352,14 @@ class _ChannelChatScreenState extends State<ChannelChatScreen> {
children: [
Column(
children: [
if (_isLoadingMore)
const LinearProgressIndicator()
.paddingOnly(bottom: 4)
.animate()
.slideY(),
Expanded(
child: ListView.builder(
controller: _chatScrollController,
itemCount: _currentHistory.length,
clipBehavior: Clip.none,
reverse: true,

View File

@ -101,7 +101,7 @@ class _ChatScreenState extends State<ChatScreen> {
context),
sliver: SliverAppBar(
title: AppBarTitle('chat'.tr),
centerTitle: true,
centerTitle: false,
floating: true,
titleSpacing: SolianTheme.titleSpacing(context),
toolbarHeight: SolianTheme.toolbarHeight(context),