♻️ 使用 Drift 作为本地数据库 #3
@ -51,6 +51,14 @@
|
||||
to determine the Window background behind the Flutter UI. -->
|
||||
<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">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
@ -61,14 +69,6 @@
|
||||
<data android:scheme="https" />
|
||||
</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
|
||||
android:name="io.flutter.embedding.android.NormalTheme"
|
||||
android:resource="@style/NormalTheme"
|
||||
|
@ -12,7 +12,7 @@ class ChatEventController {
|
||||
RxList.empty(growable: true);
|
||||
final RxInt totalEvents = 0.obs;
|
||||
|
||||
final RxBool isLoading = false.obs;
|
||||
final RxBool isLoading = true.obs;
|
||||
|
||||
Channel? channel;
|
||||
String? scope;
|
||||
@ -27,7 +27,7 @@ class ChatEventController {
|
||||
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.scope = scope;
|
||||
|
||||
@ -38,7 +38,7 @@ class ChatEventController {
|
||||
final result = await src.fetchRemoteEvents(
|
||||
channel,
|
||||
scope,
|
||||
remainDepth: 3,
|
||||
depth: 1,
|
||||
offset: 0,
|
||||
);
|
||||
totalEvents.value = result?.$2 ?? 0;
|
||||
@ -58,6 +58,7 @@ class ChatEventController {
|
||||
final result = await src.pullRemoteEvents(
|
||||
channel,
|
||||
scope: scope,
|
||||
depth: 1,
|
||||
);
|
||||
totalEvents.value = result?.$2 ?? 0;
|
||||
await syncLocal(channel);
|
||||
@ -71,7 +72,7 @@ class ChatEventController {
|
||||
final result = await src.fetchRemoteEvents(
|
||||
channel,
|
||||
scope,
|
||||
remainDepth: 3,
|
||||
depth: 3,
|
||||
offset: currentEvents.length,
|
||||
);
|
||||
if (result != null) {
|
||||
@ -123,6 +124,7 @@ class ChatEventController {
|
||||
entry = await src.receiveEvent(remote);
|
||||
}
|
||||
|
||||
totalEvents.value++;
|
||||
insertEvent(entry);
|
||||
applyEvent(entry);
|
||||
}
|
||||
|
@ -51,12 +51,12 @@ class MessagesFetchingProvider extends GetxController {
|
||||
Future<(List<Event>, int)?> fetchRemoteEvents(
|
||||
Channel channel,
|
||||
String scope, {
|
||||
required int remainDepth,
|
||||
required int depth,
|
||||
bool Function(List<Event> items)? onBrake,
|
||||
take = 10,
|
||||
offset = 0,
|
||||
}) async {
|
||||
if (remainDepth <= 0) {
|
||||
if (depth <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -84,7 +84,7 @@ class MessagesFetchingProvider extends GetxController {
|
||||
final expandResult = (await fetchRemoteEvents(
|
||||
channel,
|
||||
scope,
|
||||
remainDepth: remainDepth - 1,
|
||||
depth: depth - 1,
|
||||
take: take,
|
||||
offset: offset + result.length,
|
||||
))
|
||||
@ -162,7 +162,7 @@ class MessagesFetchingProvider extends GetxController {
|
||||
final data = await fetchRemoteEvents(
|
||||
channel,
|
||||
scope,
|
||||
remainDepth: depth,
|
||||
depth: depth,
|
||||
offset: offset,
|
||||
onBrake: (items) {
|
||||
return items.any((x) => x.id == lastOne?.id);
|
||||
|
@ -2,7 +2,6 @@ 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/controllers/chat_events_controller.dart';
|
||||
import 'package:solian/exts.dart';
|
||||
@ -156,7 +155,7 @@ class _ChannelChatScreenState extends State<ChannelChatScreen>
|
||||
|
||||
void _keepUpdateWithServer() {
|
||||
_getOngoingCall();
|
||||
_chatController.getEvents(_channel!, widget.realm);
|
||||
_chatController.getInitialEvents(_channel!, widget.realm);
|
||||
setState(() => _isOutOfSyncSince = null);
|
||||
}
|
||||
|
||||
@ -193,7 +192,7 @@ class _ChannelChatScreenState extends State<ChannelChatScreen>
|
||||
|
||||
_getOngoingCall();
|
||||
_getChannel().then((_) {
|
||||
_chatController.getEvents(_channel!, widget.realm);
|
||||
_chatController.getInitialEvents(_channel!, widget.realm);
|
||||
_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(
|
||||
child: BackdropFilter(
|
||||
filter: ImageFilter.blur(sigmaX: 50, sigmaY: 50),
|
||||
|
@ -6,6 +6,7 @@ import 'package:solian/models/event.dart';
|
||||
import 'package:solian/providers/last_read.dart';
|
||||
import 'package:solian/widgets/chat/chat_event.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 {
|
||||
final String scope;
|
||||
@ -36,8 +37,9 @@ class ChatEventList extends StatelessWidget {
|
||||
reverse: true,
|
||||
slivers: [
|
||||
Obx(() {
|
||||
return SliverList.builder(
|
||||
return SliverInfiniteList(
|
||||
key: Key('chat-history#${channel.id}'),
|
||||
isLoading: chatController.isLoading.value,
|
||||
itemCount: chatController.currentEvents.length,
|
||||
itemBuilder: (context, index) {
|
||||
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);
|
||||
},
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
|
Loading…
Reference in New Issue
Block a user