♻️ 使用 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 {
 | 
			
		||||
                },
 | 
			
		||||
              );
 | 
			
		||||
            },
 | 
			
		||||
          );
 | 
			
		||||
        }),
 | 
			
		||||
        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);
 | 
			
		||||
              },
 | 
			
		||||
            ),
 | 
			
		||||
            onFetchData: () {
 | 
			
		||||
              chatController.loadEvents(
 | 
			
		||||
                chatController.channel!,
 | 
			
		||||
                chatController.scope!,
 | 
			
		||||
              );
 | 
			
		||||
            },
 | 
			
		||||
          );
 | 
			
		||||
        }),
 | 
			
		||||
      ],
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user