♻️ 使用 Drift 作为本地数据库 #3

Merged
LittleSheep merged 3 commits from refactor/drift-as-local-db into master 2024-09-15 02:56:59 +00:00
5 changed files with 29 additions and 49 deletions
Showing only changes of commit 2183a2ca55 - Show all commits

View File

@ -51,6 +51,14 @@
to determine the Window background behind the Flutter UI. --> to determine the Window background behind the Flutter UI. -->
<meta-data android:name="flutter_deeplinking_enabled" android:value="true" /> <meta-data android:name="flutter_deeplinking_enabled" android:value="true" />
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="solink" />
</intent-filter>
<intent-filter android:autoVerify="true"> <intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
@ -61,14 +69,6 @@
<data android:scheme="https" /> <data android:scheme="https" />
</intent-filter> </intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="solink" />
</intent-filter>
<meta-data <meta-data
android:name="io.flutter.embedding.android.NormalTheme" android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme" android:resource="@style/NormalTheme"

View File

@ -12,7 +12,7 @@ class ChatEventController {
RxList.empty(growable: true); RxList.empty(growable: true);
final RxInt totalEvents = 0.obs; final RxInt totalEvents = 0.obs;
final RxBool isLoading = false.obs; final RxBool isLoading = true.obs;
Channel? channel; Channel? channel;
String? scope; String? scope;
@ -27,7 +27,7 @@ class ChatEventController {
return await src.getEvent(id, channel!, scope: scope!); return await src.getEvent(id, channel!, scope: scope!);
} }
Future<void> getEvents(Channel channel, String scope) async { Future<void> getInitialEvents(Channel channel, String scope) async {
this.channel = channel; this.channel = channel;
this.scope = scope; this.scope = scope;
@ -38,7 +38,7 @@ class ChatEventController {
final result = await src.fetchRemoteEvents( final result = await src.fetchRemoteEvents(
channel, channel,
scope, scope,
remainDepth: 3, depth: 1,
offset: 0, offset: 0,
); );
totalEvents.value = result?.$2 ?? 0; totalEvents.value = result?.$2 ?? 0;
@ -58,6 +58,7 @@ class ChatEventController {
final result = await src.pullRemoteEvents( final result = await src.pullRemoteEvents(
channel, channel,
scope: scope, scope: scope,
depth: 1,
); );
totalEvents.value = result?.$2 ?? 0; totalEvents.value = result?.$2 ?? 0;
await syncLocal(channel); await syncLocal(channel);
@ -71,7 +72,7 @@ class ChatEventController {
final result = await src.fetchRemoteEvents( final result = await src.fetchRemoteEvents(
channel, channel,
scope, scope,
remainDepth: 3, depth: 3,
offset: currentEvents.length, offset: currentEvents.length,
); );
if (result != null) { if (result != null) {
@ -123,6 +124,7 @@ class ChatEventController {
entry = await src.receiveEvent(remote); entry = await src.receiveEvent(remote);
} }
totalEvents.value++;
insertEvent(entry); insertEvent(entry);
applyEvent(entry); applyEvent(entry);
} }

View File

@ -51,12 +51,12 @@ class MessagesFetchingProvider extends GetxController {
Future<(List<Event>, int)?> fetchRemoteEvents( Future<(List<Event>, int)?> fetchRemoteEvents(
Channel channel, Channel channel,
String scope, { String scope, {
required int remainDepth, required int depth,
bool Function(List<Event> items)? onBrake, bool Function(List<Event> items)? onBrake,
take = 10, take = 10,
offset = 0, offset = 0,
}) async { }) async {
if (remainDepth <= 0) { if (depth <= 0) {
return null; return null;
} }
@ -84,7 +84,7 @@ class MessagesFetchingProvider extends GetxController {
final expandResult = (await fetchRemoteEvents( final expandResult = (await fetchRemoteEvents(
channel, channel,
scope, scope,
remainDepth: remainDepth - 1, depth: depth - 1,
take: take, take: take,
offset: offset + result.length, offset: offset + result.length,
)) ))
@ -162,7 +162,7 @@ class MessagesFetchingProvider extends GetxController {
final data = await fetchRemoteEvents( final data = await fetchRemoteEvents(
channel, channel,
scope, scope,
remainDepth: depth, depth: depth,
offset: offset, offset: offset,
onBrake: (items) { onBrake: (items) {
return items.any((x) => x.id == lastOne?.id); return items.any((x) => x.id == lastOne?.id);

View File

@ -2,7 +2,6 @@ import 'dart:async';
import 'dart:ui'; import 'dart:ui';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_animate/flutter_animate.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:solian/controllers/chat_events_controller.dart'; import 'package:solian/controllers/chat_events_controller.dart';
import 'package:solian/exts.dart'; import 'package:solian/exts.dart';
@ -156,7 +155,7 @@ class _ChannelChatScreenState extends State<ChannelChatScreen>
void _keepUpdateWithServer() { void _keepUpdateWithServer() {
_getOngoingCall(); _getOngoingCall();
_chatController.getEvents(_channel!, widget.realm); _chatController.getInitialEvents(_channel!, widget.realm);
setState(() => _isOutOfSyncSince = null); setState(() => _isOutOfSyncSince = null);
} }
@ -193,7 +192,7 @@ class _ChannelChatScreenState extends State<ChannelChatScreen>
_getOngoingCall(); _getOngoingCall();
_getChannel().then((_) { _getChannel().then((_) {
_chatController.getEvents(_channel!, widget.realm); _chatController.getInitialEvents(_channel!, widget.realm);
_listenMessages(); _listenMessages();
}); });
} }
@ -295,13 +294,6 @@ class _ChannelChatScreenState extends State<ChannelChatScreen>
}, },
), ),
), ),
Obx(() {
if (_chatController.isLoading.isTrue) {
return const LinearProgressIndicator().animate().slideY();
} else {
return const SizedBox.shrink();
}
}),
ClipRect( ClipRect(
child: BackdropFilter( child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 50, sigmaY: 50), filter: ImageFilter.blur(sigmaX: 50, sigmaY: 50),

View File

@ -6,6 +6,7 @@ import 'package:solian/models/event.dart';
import 'package:solian/providers/last_read.dart'; import 'package:solian/providers/last_read.dart';
import 'package:solian/widgets/chat/chat_event.dart'; import 'package:solian/widgets/chat/chat_event.dart';
import 'package:solian/widgets/chat/chat_event_action.dart'; import 'package:solian/widgets/chat/chat_event_action.dart';
import 'package:very_good_infinite_list/very_good_infinite_list.dart';
class ChatEventList extends StatelessWidget { class ChatEventList extends StatelessWidget {
final String scope; final String scope;
@ -36,8 +37,9 @@ class ChatEventList extends StatelessWidget {
reverse: true, reverse: true,
slivers: [ slivers: [
Obx(() { Obx(() {
return SliverList.builder( return SliverInfiniteList(
key: Key('chat-history#${channel.id}'), key: Key('chat-history#${channel.id}'),
isLoading: chatController.isLoading.value,
itemCount: chatController.currentEvents.length, itemCount: chatController.currentEvents.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
Get.find<LastReadProvider>().messagesLastReadAt = Get.find<LastReadProvider>().messagesLastReadAt =
@ -89,28 +91,12 @@ class ChatEventList extends StatelessWidget {
}, },
); );
}, },
onFetchData: () {
chatController.loadEvents(
chatController.channel!,
chatController.scope!,
); );
}),
Obx(() {
final amount =
chatController.totalEvents - chatController.currentEvents.length;
if (amount.value <= 0 || chatController.isLoading.isTrue) {
return const SliverToBoxAdapter(child: SizedBox.shrink());
}
return SliverToBoxAdapter(
child: ListTile(
tileColor: Theme.of(context).colorScheme.surfaceContainerLow,
leading: const Icon(Icons.sync_disabled),
title: Text('messageUnSync'.tr),
subtitle: Text('messageUnSyncCaption'.trParams({
'count': amount.string,
})),
onTap: () {
chatController.loadEvents(channel, scope);
}, },
),
); );
}), }),
], ],