Merge remote-tracking branch 'origin/dev' into cody/netwrok_SDK

# Conflicts:
#	apps/im_app/lib/features/chat/presentation/chat_db_test_view_model.dart
#	apps/im_app/lib/features/login/presentation/login_view_model.dart

修复逻辑漏洞,性能优化
This commit is contained in:
Cody
2026-03-08 20:47:28 +08:00
88 changed files with 5695 additions and 593 deletions

View File

@@ -58,17 +58,16 @@ class ChatDbTestViewModel extends _$ChatDbTestViewModel {
return ChatDbTestState(testResults: testResults);
}
// ── 导航Demo 按钮,正式开发后随 UI 一并替换) ──────────────────────────
// ── 操作Demo 按钮,正式开发后随 UI 一并替换) ──────────────────────────
/// 开始测试
void startDBTest(BuildContext context) {
state = state.copyWith(testStarted: true, currentState: '开始测试');
_testDBInsert();
}
/// 结束测试
void stopDBTest(BuildContext context) {
state = state.copyWith(testStarted: false, currentState: '结束测试');
/// 切换测试状态(开始 / 停止)
void toggleDBTest() {
if (state.testStarted) {
state = state.copyWith(testStarted: false, currentState: '结束测试');
} else {
state = state.copyWith(testStarted: true, currentState: '开始测试');
_testDBInsert();
}
}
Future<void> _testDBInsert() async {
@@ -84,13 +83,11 @@ class ChatDbTestViewModel extends _$ChatDbTestViewModel {
for (var i = 0; i < count; i += chunkSize) {
final chunk = List.generate(
chunkSize.clamp(0, count - i),
(j) => UsersCompanion.insert(
uid: Value(i + j),
nickname: Value('User ${i + j}'),
),
(j) =>
UsersCompanion.insert(uid: i + j, nickname: Value('User ${i + j}')),
);
await db.batchInsertOrReplace<User>(chunk);
await db.batchInsertOrReplace<DriftUser>(chunk);
completed += chunk.length;
// 让出主线程

View File

@@ -3,19 +3,12 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:im_app/features/chat/presentation/chat_db_test_view_model.dart';
import '../../../core/ui/components/app_button.dart';
import '../presentation/chat_view_model.dart';
/// 聊天Demo 按钮
/// 数据库性能测试Demo
///
/// 包含五个演示按钮,覆盖 go_router 的常见导航场景:
/// - 「切换 Tab」 — go替换历史不可返回
/// - 「有参 pushextra」 — push + extraDart Record可返回
/// - 「有参 push路径参数」— push + URL 内嵌 id可返回
/// - 「无参 push」 — push可返回
/// - 「退出登录」 — 守卫自动重定向到 /login
///
/// 所有操作通过 [ChatViewModel] 处理View 不直接调用路由。
/// 正式开发后替换为会话列表,按钮相关代码一并清除。
/// 批量插入 10000 条用户记录,验证 Drift 批量写入性能。
/// 所有操作通过 [ChatDbTestViewModel] 处理View 只负责渲染。
/// 正式开发后此页面将被删除。
class ChatDbTestPage extends ConsumerWidget {
const ChatDbTestPage({super.key});
@@ -25,7 +18,7 @@ class ChatDbTestPage extends ConsumerWidget {
final state = ref.watch(chatDbTestViewModelProvider);
return Scaffold(
appBar: AppBar(title: const Text('测试数据库'), ),
appBar: AppBar(title: const Text('测试数据库')),
body: Column(
mainAxisSize: MainAxisSize.max,
spacing: 16,
@@ -38,17 +31,14 @@ class ChatDbTestPage extends ConsumerWidget {
children: [
AppButton.inverse(
label: state.testStarted ? '结束' : '开始',
onPressed: () => state.testStarted ? vm.stopDBTest(context) : vm.startDBTest(context),
onPressed: () => vm.toggleDBTest(),
),
SizedBox(width: 8),
Expanded(
child: Text(
state.currentState,
textAlign: TextAlign.end,
),
)
child: Text(state.currentState, textAlign: TextAlign.end),
),
],
)
),
),
Expanded(
child: ListView.builder(
@@ -63,7 +53,7 @@ class ChatDbTestPage extends ConsumerWidget {
);
},
),
)
),
],
),
);

View File

@@ -1,4 +1,8 @@
import 'package:flutter/foundation.dart';
import 'dart:convert';
import 'package:flutter/services.dart';
import 'package:im_app/data/models/user_dto.dart';
import 'package:im_app/data/remote/login_request.dart';
import 'package:networks_sdk/networks_sdk.dart';
import 'package:im_app/app/di/db_provider.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
@@ -55,16 +59,25 @@ class LoginViewModel extends _$LoginViewModel {
/// 仅用于演示路由守卫行为,正式 UI 就绪后删除此方法,改用 [login]。
/// 正式 [login] 成功后同样需要调用 [AuthNotifier.login] 更新守卫状态。
Future<void> demoLogin() async {
final storageApi = ref.read(storageSdkProvider);
try {
final storageApi = ref.read(storageSdkProvider);
final storageLifeCycle = storageApi as StorageSdkLifecycle;
///TODO: StorageSDKLifeCycle 需要只在主项目暴露
final storageLifeCycle = storageApi as StorageSdkLifecycle;
ref.read(authNotifierProvider).login();
// 读取 mock 数据
final raw = await rootBundle.loadString('assets/loginData.json');
final json = jsonDecode(raw) as Map<String, dynamic>;
final loginResponse = LoginResponse.fromJson(json);
final user = loginResponse.data.toEntity();
await storageLifeCycle.openDatabase(1234567);
final rows = await storageApi.rawQuery("PRAGMA table_info('user')");
for (final row in rows) {
debugPrint('Schema: ${row.data}');
// 先完成 DB 操作,再标记登录状态(失败时不会误标为已登录)
await storageLifeCycle.openDatabase(user.uid);
final userCompanion = UserDto.fromEntity(user).toCompanion();
await storageApi.insert(userCompanion);
// 全部成功后再更新登录状态,触发路由守卫重定向
ref.read(authNotifierProvider).login();
} catch (e) {
state = state.copyWith(error: e.toString(), isLoading: false);
}
}