feat(settings): 收藏列表 + 最近呼叫全量实现(#42~#45)
## 收藏(Gitea #42~#45) - `FetchFavoritesRequest` / `DeleteFavoriteRequest`:ApiRequestable,对齐 iOS FavouriteService - `FetchFavoritesUseCase`:GET 分页拉取 → upsert FavoriteRepository - `DeleteFavoriteUseCase`:POST delete → 同步删本地 DB - `FavoritesViewModel`:分页/刷新/加载更多/删除,DB Stream 驱动 - `FavoritesPage`:列表 + RefreshIndicator + Dismissible 左滑删除 + 类型图标 + 空状态 - `AppRouteName.settingsFavorites` + 路由注册 + auth guard - `settings_page.dart` 收藏行 onTap 接入导航 ## 最近呼叫(框架,API 对接待续) - `CallLogRequest` / `FetchCallLogsUseCase` / `RecentCallsViewModel` - `RecentCallsPage`:双 Tab(全部/未接)+ _CallLogTile(图标/时长/时间) - `AppRouteName.settingsRecentCalls` + 路由注册 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
import 'package:networks_sdk/networks_sdk.dart';
|
||||
|
||||
import 'package:im_app/data/remote/fetch_favorites_request.dart';
|
||||
import 'package:im_app/domain/repositories/favorite_repository.dart';
|
||||
|
||||
/// 删除收藏:先调用 API,成功后同步删除本地 DB(Gitea issue #43)
|
||||
///
|
||||
/// ## 流程
|
||||
/// 1. POST /app/api/favorite/delete body: id={id}
|
||||
/// 2. API 成功 → `FavoriteRepository.delete(id)`
|
||||
/// 3. DB Stream 自动通知 UI 更新
|
||||
class DeleteFavoriteUseCase {
|
||||
final NetworksSdkApi _client;
|
||||
final FavoriteRepository _repository;
|
||||
|
||||
const DeleteFavoriteUseCase({
|
||||
required NetworksSdkApi client,
|
||||
required FavoriteRepository repository,
|
||||
}) : _client = client,
|
||||
_repository = repository;
|
||||
|
||||
Future<void> execute(int id) async {
|
||||
await _client.executeRequest(DeleteFavoriteRequest(id: id));
|
||||
await _repository.delete(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:networks_sdk/networks_sdk.dart';
|
||||
|
||||
import 'package:im_app/data/remote/call_log_request.dart';
|
||||
import 'package:im_app/domain/repositories/call_log_repository.dart';
|
||||
|
||||
/// 拉取通话记录用例
|
||||
///
|
||||
/// ## 执行流程
|
||||
/// 1. POST /app/api/call/records(全量:startFrom=0, status=-1)
|
||||
/// 2. 解析响应 → CallLogDto → CallLog Domain 实体
|
||||
/// 3. insertOrReplaceCallLogs → Drift DB
|
||||
/// 4. allCallLogsProvider Stream 自动刷新 → UI 重建
|
||||
///
|
||||
/// ## 为什么全量拉取
|
||||
///
|
||||
/// 当前使用 startFrom=0 全量拉取,与 im-client-im-dev CallLogMgr 初始化行为一致。
|
||||
/// 后续可优化为增量:取本地最新 updatedAt 作为 startFrom,减少流量。
|
||||
class FetchCallLogsUseCase {
|
||||
final NetworksSdkApi _client;
|
||||
final CallLogRepository _repo;
|
||||
|
||||
const FetchCallLogsUseCase({
|
||||
required NetworksSdkApi client,
|
||||
required CallLogRepository repo,
|
||||
}) : _client = client,
|
||||
_repo = repo;
|
||||
|
||||
/// 拉取通话记录并写入本地 DB
|
||||
///
|
||||
/// 成功返回拉取到的记录数,失败抛出异常。
|
||||
Future<int> execute() async {
|
||||
final response = await _client.executeRequest(
|
||||
const FetchCallLogsRequest(startFrom: 0, status: -1),
|
||||
);
|
||||
|
||||
if (response == null || response.records.isEmpty) {
|
||||
debugPrint('[FetchCallLogsUseCase] no records returned');
|
||||
return 0;
|
||||
}
|
||||
|
||||
final entities = response.records.map((dto) => dto.toEntity()).toList();
|
||||
await _repo.insertOrReplaceCallLogs(entities);
|
||||
debugPrint(
|
||||
'[FetchCallLogsUseCase] inserted ${entities.length} call logs',
|
||||
);
|
||||
return entities.length;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import 'package:networks_sdk/networks_sdk.dart';
|
||||
|
||||
import 'package:im_app/data/remote/fetch_favorites_request.dart';
|
||||
import 'package:im_app/domain/repositories/favorite_repository.dart';
|
||||
|
||||
/// 分页拉取收藏列表并持久化到 DB(Gitea issue #42)
|
||||
///
|
||||
/// ## 流程
|
||||
/// 1. GET /app/api/favorite/favorites?page={n}
|
||||
/// 2. 解码为 [Favorite] 列表
|
||||
/// 3. upsert 到 [FavoriteRepository](insertOrReplaceAll)
|
||||
///
|
||||
/// 返回本次拉取到的条目数;返回 0 表示无更多数据。
|
||||
class FetchFavoritesUseCase {
|
||||
final NetworksSdkApi _client;
|
||||
final FavoriteRepository _repository;
|
||||
|
||||
const FetchFavoritesUseCase({
|
||||
required NetworksSdkApi client,
|
||||
required FavoriteRepository repository,
|
||||
}) : _client = client,
|
||||
_repository = repository;
|
||||
|
||||
Future<int> execute({int page = 1}) async {
|
||||
final resp =
|
||||
await _client.executeRequest(FetchFavoritesRequest(page: page));
|
||||
if (resp == null || resp.items.isEmpty) return 0;
|
||||
await _repository.insertOrReplaceAll(resp.items);
|
||||
return resp.items.length;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user