diff --git a/apps/im_app/lib/app/di/api_retry_provider.dart b/apps/im_app/lib/app/di/api_retry_provider.dart new file mode 100644 index 0000000..9fdc0cf --- /dev/null +++ b/apps/im_app/lib/app/di/api_retry_provider.dart @@ -0,0 +1,28 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:im_app/app/di/db_provider.dart'; +import 'package:im_app/data/repositories/api_retry_repository_impl.dart'; +import 'package:im_app/domain/entities/api_retry.dart'; +import 'package:im_app/domain/repositories/api_retry_repository.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'api_retry_provider.g.dart'; + +// ── Repository ──────────────────────────────────────────────────────────────── + +final apiRetryRepositoryProvider = Provider((ref) { + return ApiRetryRepositoryImpl(ref.watch(storageSdkProvider)); +}); + +// ── Streams ─────────────────────────────────────────────────────────────────── + +/// 监听所有重试任务 +@riverpod +Stream> allApiRetries(Ref ref) { + return ref.watch(apiRetryRepositoryProvider).watchAll(); +} + +/// 监听未同步的重试任务 +@riverpod +Stream> pendingApiRetries(Ref ref) { + return ref.watch(apiRetryRepositoryProvider).watchPending(); +} diff --git a/apps/im_app/lib/app/di/sound_provider.dart b/apps/im_app/lib/app/di/sound_provider.dart new file mode 100644 index 0000000..4647188 --- /dev/null +++ b/apps/im_app/lib/app/di/sound_provider.dart @@ -0,0 +1,34 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:im_app/app/di/db_provider.dart'; +import 'package:im_app/data/repositories/sound_repository_impl.dart'; +import 'package:im_app/domain/entities/sound.dart'; +import 'package:im_app/domain/repositories/sound_repository.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'sound_provider.g.dart'; + +// ── Repository ──────────────────────────────────────────────────────────────── + +final soundRepositoryProvider = Provider((ref) { + return SoundRepositoryImpl(ref.watch(storageSdkProvider)); +}); + +// ── Streams ─────────────────────────────────────────────────────────────────── + +/// 监听所有音效 +@riverpod +Stream> allSounds(Ref ref) { + return ref.watch(soundRepositoryProvider).watchAll(); +} + +/// 监听指定类型音效 +@riverpod +Stream> soundsByType(Ref ref, int typ) { + return ref.watch(soundRepositoryProvider).watchByType(typ); +} + +/// 监听指定音效 +@riverpod +Stream soundById(Ref ref, int id) { + return ref.watch(soundRepositoryProvider).watchById(id); +} diff --git a/apps/im_app/lib/app/di/tag_provider.dart b/apps/im_app/lib/app/di/tag_provider.dart new file mode 100644 index 0000000..f3bb04a --- /dev/null +++ b/apps/im_app/lib/app/di/tag_provider.dart @@ -0,0 +1,40 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:im_app/app/di/db_provider.dart'; +import 'package:im_app/data/repositories/tag_repository_impl.dart'; +import 'package:im_app/domain/entities/tag.dart'; +import 'package:im_app/domain/repositories/tag_repository.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'tag_provider.g.dart'; + +// ── Repository ──────────────────────────────────────────────────────────────── + +final tagRepositoryProvider = Provider((ref) { + return TagRepositoryImpl(ref.watch(storageSdkProvider)); +}); + +// ── Streams ─────────────────────────────────────────────────────────────────── + +/// 监听所有标签 +@riverpod +Stream> allTags(Ref ref) { + return ref.watch(tagRepositoryProvider).watchAll(); +} + +/// 监听指定 uid 的标签 +@riverpod +Stream> tagsByUid(Ref ref, int uid) { + return ref.watch(tagRepositoryProvider).watchByUid(uid); +} + +/// 监听指定类型的标签 +@riverpod +Stream> tagsByType(Ref ref, int type) { + return ref.watch(tagRepositoryProvider).watchByType(type); +} + +/// 监听指定标签 +@riverpod +Stream tagById(Ref ref, int id) { + return ref.watch(tagRepositoryProvider).watchById(id); +} diff --git a/apps/im_app/lib/data/local/drift/app_database.dart b/apps/im_app/lib/data/local/drift/app_database.dart index 935c7e3..0bab7f7 100644 --- a/apps/im_app/lib/data/local/drift/app_database.dart +++ b/apps/im_app/lib/data/local/drift/app_database.dart @@ -1,17 +1,17 @@ import 'package:drift/drift.dart'; -import 'package:im_app/data/local/drift/tables/favourites.dart'; import 'package:im_app/data/local/drift/tables/sounds.dart'; import 'package:im_app/data/local/drift/tables/tags.dart'; +import 'package:im_app/data/local/drift/tables/favorite_details.dart'; import 'package:im_app/data/local/drift/tables/pending_friend_request_histories.dart'; +import 'package:im_app/data/local/drift/tables/favorites.dart'; import 'package:im_app/data/local/drift/tables/message.dart'; import 'package:im_app/data/local/drift/tables/recent_mini_apps.dart'; -import 'package:im_app/data/local/drift/tables/retries.dart'; import 'package:im_app/data/local/drift/tables/groups.dart'; import 'package:im_app/data/local/drift/tables/favorite_mini_apps.dart'; import 'package:im_app/data/local/drift/tables/discover_mini_apps.dart'; import 'package:im_app/data/local/drift/tables/chat_categories.dart'; +import 'package:im_app/data/local/drift/tables/api_retries.dart'; import 'package:im_app/data/local/drift/tables/chat_bots.dart'; -import 'package:im_app/data/local/drift/tables/favourite_details.dart'; import 'package:im_app/data/local/drift/tables/user_request_histories.dart'; import 'package:im_app/data/local/drift/tables/workspaces.dart'; import 'package:im_app/data/local/drift/tables/users.dart'; @@ -23,19 +23,19 @@ part 'app_database.g.dart'; @DriftDatabase( tables: [ - Favourites, + Favorites, Sounds, Tags, PendingFriendRequestHistories, Messages, RecentMiniApps, - Retries, + ApiRetries, Groups, FavoriteMiniApps, DiscoverMiniApps, ChatCategories, ChatBots, - FavouriteDetails, + FavoriteDetails, UserRequestHistories, Workspaces, Users, @@ -50,19 +50,19 @@ class AppDatabase extends _$AppDatabase { return {}; } return { - DriftFavourite: database.favourites, DriftSound: database.sounds, DriftTag: database.tags, + DriftFavoriteDetail: database.favoriteDetails, DriftPendingFriendRequestHistory: database.pendingFriendRequestHistories, + DriftFavorite: database.favorites, DriftMessage: database.messages, DriftRecentMiniApp: database.recentMiniApps, - DriftRetry: database.retries, DriftGroup: database.groups, DriftFavoriteMiniApp: database.favoriteMiniApps, DriftDiscoverMiniApp: database.discoverMiniApps, DriftChatCategory: database.chatCategories, + DriftApiRetry: database.apiRetries, DriftChatBot: database.chatBots, - DriftFavouriteDetail: database.favouriteDetails, DriftUserRequestHistory: database.userRequestHistories, DriftWorkspace: database.workspaces, DriftUser: database.users, diff --git a/apps/im_app/lib/data/local/drift/tables/retries.dart b/apps/im_app/lib/data/local/drift/tables/api_retries.dart similarity index 86% rename from apps/im_app/lib/data/local/drift/tables/retries.dart rename to apps/im_app/lib/data/local/drift/tables/api_retries.dart index 10b0f13..4d20fd8 100644 --- a/apps/im_app/lib/data/local/drift/tables/retries.dart +++ b/apps/im_app/lib/data/local/drift/tables/api_retries.dart @@ -1,20 +1,31 @@ import 'package:drift/drift.dart'; -@DataClassName('DriftRetry') -class Retries extends Table { +@DataClassName('DriftApiRetry') +class ApiRetries extends Table { IntColumn get id => integer().autoIncrement()(); + IntColumn get uid => integer().nullable()(); + TextColumn get apiType => text().withDefault(const Constant(''))(); + TextColumn get endPoint => text().withDefault(const Constant(''))(); + TextColumn get requestData => text().withDefault(const Constant(''))(); + IntColumn get synced => integer().nullable()(); + TextColumn get callbackFun => text().withDefault(const Constant(''))(); + IntColumn get expired => integer().nullable()(); + IntColumn get replace => integer().nullable()(); + IntColumn get expireTime => integer().nullable()(); + IntColumn get createTime => integer().nullable()(); + IntColumn get addIndex => integer().nullable()(); @override - String get tableName => 'retry'; + String get tableName => 'api_retry'; } diff --git a/apps/im_app/lib/data/local/drift/tables/discover_mini_apps.dart b/apps/im_app/lib/data/local/drift/tables/discover_mini_apps.dart index 6cec9e0..53524d1 100644 --- a/apps/im_app/lib/data/local/drift/tables/discover_mini_apps.dart +++ b/apps/im_app/lib/data/local/drift/tables/discover_mini_apps.dart @@ -1,36 +1,8 @@ import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/tables/mixin/mini_app_table_mixin.dart'; @DataClassName('DriftDiscoverMiniApp') -class DiscoverMiniApps extends Table { - TextColumn get id => text()(); - TextColumn get name => text().nullable()(); - TextColumn get openuid => text().nullable()(); - TextColumn get devId => text().nullable()(); - TextColumn get icon => text().nullable()(); - TextColumn get iconGaussian => text().nullable()(); - TextColumn get downloadUrl => text().nullable()(); - TextColumn get description => text().nullable()(); - IntColumn get version => integer().nullable()(); - IntColumn get typ => integer().nullable()(); - IntColumn get flag => integer().nullable()(); - IntColumn get reviewStatus => integer().nullable()(); - IntColumn get favoriteAt => integer().nullable()(); - IntColumn get isActive => integer().nullable()(); - IntColumn get createdAt => integer().nullable()(); - IntColumn get updatedAt => integer().nullable()(); - IntColumn get deletedAt => integer().nullable()(); - RealColumn get score => real().nullable()(); - TextColumn get channels => text().nullable()(); - TextColumn get devName => text().nullable()(); - TextColumn get pictureGaussian => text().nullable()(); - TextColumn get picture => text().nullable()(); - IntColumn get commentNum => integer().nullable()(); - TextColumn get lastLoginAt => text().nullable()(); - TextColumn get screen => text().nullable()(); - - @override - Set get primaryKey => {id}; - +class DiscoverMiniApps extends Table with MiniAppTableMixin { @override String get tableName => 'discover_mini_app'; } diff --git a/apps/im_app/lib/data/local/drift/tables/explore_mini_apps.dart b/apps/im_app/lib/data/local/drift/tables/explore_mini_apps.dart index af55a46..8029cc8 100644 --- a/apps/im_app/lib/data/local/drift/tables/explore_mini_apps.dart +++ b/apps/im_app/lib/data/local/drift/tables/explore_mini_apps.dart @@ -1,36 +1,8 @@ import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/tables/mixin/mini_app_table_mixin.dart'; @DataClassName('DriftExploreMiniApp') -class ExploreMiniApps extends Table { - TextColumn get id => text()(); - TextColumn get name => text().nullable()(); - TextColumn get openuid => text().nullable()(); - TextColumn get devId => text().nullable()(); - TextColumn get icon => text().nullable()(); - TextColumn get iconGaussian => text().nullable()(); - TextColumn get downloadUrl => text().nullable()(); - TextColumn get description => text().nullable()(); - IntColumn get version => integer().nullable()(); - IntColumn get typ => integer().nullable()(); - IntColumn get flag => integer().nullable()(); - IntColumn get reviewStatus => integer().nullable()(); - IntColumn get favoriteAt => integer().nullable()(); - IntColumn get isActive => integer().nullable()(); - IntColumn get createdAt => integer().nullable()(); - IntColumn get updatedAt => integer().nullable()(); - IntColumn get deletedAt => integer().nullable()(); - RealColumn get score => real().nullable()(); - TextColumn get channels => text().nullable()(); - TextColumn get devName => text().nullable()(); - TextColumn get pictureGaussian => text().nullable()(); - TextColumn get picture => text().nullable()(); - IntColumn get commentNum => integer().nullable()(); - IntColumn get lastLoginAt => integer().nullable()(); - TextColumn get screen => text().nullable()(); - - @override - Set get primaryKey => {id}; - +class ExploreMiniApps extends Table with MiniAppTableMixin { @override String get tableName => 'explore_mini_app'; } diff --git a/apps/im_app/lib/data/local/drift/tables/favourite_details.dart b/apps/im_app/lib/data/local/drift/tables/favorite_details.dart similarity index 79% rename from apps/im_app/lib/data/local/drift/tables/favourite_details.dart rename to apps/im_app/lib/data/local/drift/tables/favorite_details.dart index 463bb18..34e6068 100644 --- a/apps/im_app/lib/data/local/drift/tables/favourite_details.dart +++ b/apps/im_app/lib/data/local/drift/tables/favorite_details.dart @@ -1,16 +1,23 @@ import 'package:drift/drift.dart'; -@DataClassName('DriftFavouriteDetail') -class FavouriteDetails extends Table { +@DataClassName('DriftFavoriteDetail') +class FavoriteDetails extends Table { IntColumn get id => integer().autoIncrement()(); + TextColumn get relatedId => text().withDefault(const Constant(''))(); + TextColumn get content => text().withDefault(const Constant(''))(); + IntColumn get typ => integer().nullable()(); + IntColumn get messageId => integer().nullable()(); + IntColumn get sendId => integer().nullable()(); + IntColumn get chatId => integer().nullable()(); + IntColumn get sendTime => integer().nullable()(); @override - String get tableName => 'favourite_detail'; + String get tableName => 'favorite_detail'; } diff --git a/apps/im_app/lib/data/local/drift/tables/favorite_mini_apps.dart b/apps/im_app/lib/data/local/drift/tables/favorite_mini_apps.dart index 8bb732e..d13edc0 100644 --- a/apps/im_app/lib/data/local/drift/tables/favorite_mini_apps.dart +++ b/apps/im_app/lib/data/local/drift/tables/favorite_mini_apps.dart @@ -1,36 +1,8 @@ import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/tables/mixin/mini_app_table_mixin.dart'; @DataClassName('DriftFavoriteMiniApp') -class FavoriteMiniApps extends Table { - TextColumn get id => text()(); - TextColumn get name => text().nullable()(); - TextColumn get openuid => text().nullable()(); - TextColumn get devId => text().nullable()(); - TextColumn get icon => text().nullable()(); - TextColumn get iconGaussian => text().nullable()(); - TextColumn get downloadUrl => text().nullable()(); - TextColumn get description => text().nullable()(); - IntColumn get version => integer().nullable()(); - IntColumn get typ => integer().nullable()(); - IntColumn get flag => integer().nullable()(); - IntColumn get reviewStatus => integer().nullable()(); - IntColumn get favoriteAt => integer().nullable()(); - IntColumn get isActive => integer().nullable()(); - IntColumn get createdAt => integer().nullable()(); - IntColumn get updatedAt => integer().nullable()(); - IntColumn get deletedAt => integer().nullable()(); - RealColumn get score => real().nullable()(); - TextColumn get channels => text().nullable()(); - TextColumn get devName => text().nullable()(); - TextColumn get pictureGaussian => text().nullable()(); - TextColumn get picture => text().nullable()(); - IntColumn get commentNum => integer().nullable()(); - IntColumn get lastLoginAt => integer().nullable()(); - TextColumn get screen => text().nullable()(); - - @override - Set get primaryKey => {id}; - +class FavoriteMiniApps extends Table with MiniAppTableMixin { @override String get tableName => 'favorite_mini_app'; } diff --git a/apps/im_app/lib/data/local/drift/tables/favourites.dart b/apps/im_app/lib/data/local/drift/tables/favorites.dart similarity index 90% rename from apps/im_app/lib/data/local/drift/tables/favourites.dart rename to apps/im_app/lib/data/local/drift/tables/favorites.dart index 09ae027..3b25352 100644 --- a/apps/im_app/lib/data/local/drift/tables/favourites.dart +++ b/apps/im_app/lib/data/local/drift/tables/favorites.dart @@ -1,26 +1,40 @@ import 'package:drift/drift.dart'; -@DataClassName('DriftFavourite') -class Favourites extends Table { +@DataClassName('DriftFavorite') +class Favorites extends Table { IntColumn get id => integer()(); + TextColumn get parentId => text().withDefault(const Constant(''))(); + TextColumn get data => text().withDefault(const Constant(''))(); + IntColumn get createdAt => integer().withDefault(const Constant(0))(); + IntColumn get updatedAt => integer().withDefault(const Constant(0))(); + IntColumn get deletedAt => integer().withDefault(const Constant(0))(); + IntColumn get source => integer().nullable()(); + IntColumn get userId => integer().nullable()(); + IntColumn get authorId => integer().nullable()(); + TextColumn get typ => text().withDefault(const Constant('[]'))(); + TextColumn get tag => text().withDefault(const Constant('[]'))(); + IntColumn get isPin => integer().withDefault(const Constant(0))(); + IntColumn get chatTyp => integer().withDefault(const Constant(0))(); + IntColumn get isUploaded => integer().withDefault(const Constant(1))(); + TextColumn get urls => text().withDefault(const Constant('[]'))(); @override Set get primaryKey => {id}; @override - String get tableName => 'favourite'; + String get tableName => 'favorite'; } diff --git a/apps/im_app/lib/data/local/drift/tables/mixin/mini_app_table_mixin.dart b/apps/im_app/lib/data/local/drift/tables/mixin/mini_app_table_mixin.dart new file mode 100644 index 0000000..f86accb --- /dev/null +++ b/apps/im_app/lib/data/local/drift/tables/mixin/mini_app_table_mixin.dart @@ -0,0 +1,58 @@ +import 'package:drift/drift.dart'; + +/// 小程序表共用列 mixin +/// discover / explore / favorite / recent 四张表共用 +mixin MiniAppTableMixin on Table { + TextColumn get id => text()(); + + TextColumn get name => text().nullable()(); + + TextColumn get openuid => text().nullable()(); + + TextColumn get devId => text().nullable()(); + + TextColumn get icon => text().nullable()(); + + TextColumn get iconGaussian => text().nullable()(); + + TextColumn get downloadUrl => text().nullable()(); + + TextColumn get description => text().nullable()(); + + IntColumn get version => integer().nullable()(); + + IntColumn get typ => integer().nullable()(); + + IntColumn get flag => integer().nullable()(); + + IntColumn get reviewStatus => integer().nullable()(); + + IntColumn get favoriteAt => integer().nullable()(); + + IntColumn get isActive => integer().nullable()(); + + IntColumn get createdAt => integer().nullable()(); + + IntColumn get updatedAt => integer().nullable()(); + + IntColumn get deletedAt => integer().nullable()(); + + RealColumn get score => real().nullable()(); + + TextColumn get channels => text().nullable()(); + + TextColumn get devName => text().nullable()(); + + TextColumn get pictureGaussian => text().nullable()(); + + TextColumn get picture => text().nullable()(); + + IntColumn get commentNum => integer().nullable()(); + + TextColumn get lastLoginAt => text().nullable()(); + + TextColumn get screen => text().nullable()(); + + @override + Set get primaryKey => {id}; +} diff --git a/apps/im_app/lib/data/local/drift/tables/recent_mini_apps.dart b/apps/im_app/lib/data/local/drift/tables/recent_mini_apps.dart index e3e1cad..dbb5043 100644 --- a/apps/im_app/lib/data/local/drift/tables/recent_mini_apps.dart +++ b/apps/im_app/lib/data/local/drift/tables/recent_mini_apps.dart @@ -1,36 +1,8 @@ import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/tables/mixin/mini_app_table_mixin.dart'; @DataClassName('DriftRecentMiniApp') -class RecentMiniApps extends Table { - TextColumn get id => text()(); - TextColumn get name => text().nullable()(); - TextColumn get openuid => text().nullable()(); - TextColumn get devId => text().nullable()(); - TextColumn get icon => text().nullable()(); - TextColumn get iconGaussian => text().nullable()(); - TextColumn get downloadUrl => text().nullable()(); - TextColumn get description => text().nullable()(); - IntColumn get version => integer().nullable()(); - IntColumn get typ => integer().nullable()(); - IntColumn get flag => integer().nullable()(); - IntColumn get reviewStatus => integer().nullable()(); - IntColumn get favoriteAt => integer().nullable()(); - IntColumn get isActive => integer().nullable()(); - IntColumn get createdAt => integer().nullable()(); - IntColumn get updatedAt => integer().nullable()(); - IntColumn get deletedAt => integer().nullable()(); - RealColumn get score => real().nullable()(); - TextColumn get channels => text().nullable()(); - TextColumn get devName => text().nullable()(); - TextColumn get pictureGaussian => text().nullable()(); - TextColumn get picture => text().nullable()(); - IntColumn get commentNum => integer().nullable()(); - IntColumn get lastLoginAt => integer().nullable()(); - TextColumn get screen => text().nullable()(); - - @override - Set get primaryKey => {id}; - +class RecentMiniApps extends Table with MiniAppTableMixin { @override String get tableName => 'recent_mini_app'; } diff --git a/apps/im_app/lib/data/models/chat_bot_dto.dart b/apps/im_app/lib/data/models/chat_bot_dto.dart deleted file mode 100644 index 4bf7f9d..0000000 --- a/apps/im_app/lib/data/models/chat_bot_dto.dart +++ /dev/null @@ -1,179 +0,0 @@ -import 'package:drift/drift.dart'; -import 'package:im_app/data/local/drift/app_database.dart'; -import 'package:im_app/domain/entities/chat_bot.dart'; - -/// 聊天机器人 DTO -class ChatBotDto { - final int id; - final String? name; - final String? username; - final int? botUserId; - final String? icon; - final String? iconGaussian; - final String? description; - final String? token; - final int? flag; - final int? status; - final String? webhook; - final String? commands; - final String? banner; - final int? channelId; - final int? channelGroupId; - final int? deletedAt; - final String? internalWebhook; - final int? mode; - final String? redirectUrl; - final int? isInvitable; - final int? isAllowForward; - final String? tips; - - const ChatBotDto({ - required this.id, - this.name, - this.username, - this.botUserId, - this.icon, - this.iconGaussian, - this.description, - this.token, - this.flag, - this.status, - this.webhook, - this.commands, - this.banner, - this.channelId, - this.channelGroupId, - this.deletedAt, - this.internalWebhook, - this.mode, - this.redirectUrl, - this.isInvitable, - this.isAllowForward, - this.tips, - }); - - factory ChatBotDto.fromJson(Map json) => ChatBotDto( - id: json['id'] as int, - name: json['name'], - username: json['username'], - botUserId: json['bot_user_id'], - icon: json['icon'], - iconGaussian: json['icon_gaussian'], - description: json['description'], - token: json['token'], - flag: json['flag'], - status: json['status'], - webhook: json['webhook'], - commands: json['commands'], - banner: json['banner'], - channelId: json['channel_id'], - channelGroupId: json['channel_group_id'], - deletedAt: json['deleted_at'], - internalWebhook: json['internal_webhook'], - mode: json['mode'], - redirectUrl: json['redirect_url'], - isInvitable: json['is_invitable'], - isAllowForward: json['is_allow_forward'], - tips: json['tips'], - ); - - Map toJson() => { - 'id': id, - 'name': name, - 'username': username, - 'bot_user_id': botUserId, - 'icon': icon, - 'icon_gaussian': iconGaussian, - 'description': description, - 'token': token, - 'flag': flag, - 'status': status, - 'webhook': webhook, - 'commands': commands, - 'banner': banner, - 'channel_id': channelId, - 'channel_group_id': channelGroupId, - 'deleted_at': deletedAt, - 'internal_webhook': internalWebhook, - 'mode': mode, - 'redirect_url': redirectUrl, - 'is_invitable': isInvitable, - 'is_allow_forward': isAllowForward, - 'tips': tips, - }; - - ChatBot toEntity() => ChatBot( - id: id, - name: name, - username: username, - botUserId: botUserId, - icon: icon, - iconGaussian: iconGaussian, - description: description, - token: token, - flag: flag, - status: status, - webhook: webhook, - commands: commands, - banner: banner, - channelId: channelId, - channelGroupId: channelGroupId, - deletedAt: deletedAt, - internalWebhook: internalWebhook, - mode: mode, - redirectUrl: redirectUrl, - isInvitable: isInvitable, - isAllowForward: isAllowForward, - tips: tips, - ); - - factory ChatBotDto.fromEntity(ChatBot chatBot) => ChatBotDto( - id: chatBot.id, - name: chatBot.name, - username: chatBot.username, - botUserId: chatBot.botUserId, - icon: chatBot.icon, - iconGaussian: chatBot.iconGaussian, - description: chatBot.description, - token: chatBot.token, - flag: chatBot.flag, - status: chatBot.status, - webhook: chatBot.webhook, - commands: chatBot.commands, - banner: chatBot.banner, - channelId: chatBot.channelId, - channelGroupId: chatBot.channelGroupId, - deletedAt: chatBot.deletedAt, - internalWebhook: chatBot.internalWebhook, - mode: chatBot.mode, - redirectUrl: chatBot.redirectUrl, - isInvitable: chatBot.isInvitable, - isAllowForward: chatBot.isAllowForward, - tips: chatBot.tips, - ); - - ChatBotsCompanion toCompanion() => ChatBotsCompanion( - id: Value(id), - name: Value(name), - username: Value(username), - botUserId: Value(botUserId), - icon: Value(icon), - iconGaussian: Value(iconGaussian), - description: Value(description), - token: Value(token), - flag: Value(flag), - status: Value(status), - webhook: Value(webhook ?? ''), - commands: Value(commands ?? '[]'), - banner: Value(banner), - channelId: Value(channelId), - channelGroupId: Value(channelGroupId), - deletedAt: Value(deletedAt), - internalWebhook: Value(internalWebhook), - mode: Value(mode), - redirectUrl: Value(redirectUrl), - isInvitable: Value(isInvitable), - isAllowForward: Value(isAllowForward), - tips: Value(tips), - ); -} diff --git a/apps/im_app/lib/data/models/chat_category_dto.dart b/apps/im_app/lib/data/models/chat_category_dto.dart deleted file mode 100644 index 65daf61..0000000 --- a/apps/im_app/lib/data/models/chat_category_dto.dart +++ /dev/null @@ -1,90 +0,0 @@ -import 'package:drift/drift.dart'; -import 'package:im_app/data/local/drift/app_database.dart'; -import 'package:im_app/domain/entities/chat_category.dart'; - -/// 聊天分类 DTO -class ChatCategoryDto { - final int id; - final String? name; - final String? includedChatIds; - final String? excludedChatIds; - final int? seq; - final int isHide; - final int createdAt; - final int updatedAt; - final int deletedAt; - - const ChatCategoryDto({ - required this.id, - this.name, - this.includedChatIds, - this.excludedChatIds, - this.seq, - this.isHide = 0, - this.createdAt = 0, - this.updatedAt = 0, - this.deletedAt = 0, - }); - - factory ChatCategoryDto.fromJson(Map json) => - ChatCategoryDto( - id: json['id'] as int, - name: json['name'], - includedChatIds: json['included_chat_ids'], - excludedChatIds: json['excluded_chat_ids'], - seq: json['seq'], - isHide: json['is_hide'] ?? 0, - createdAt: json['created_at'] ?? 0, - updatedAt: json['updated_at'] ?? 0, - deletedAt: json['deleted_at'] ?? 0, - ); - - Map toJson() => { - 'id': id, - 'name': name, - 'included_chat_ids': includedChatIds, - 'excluded_chat_ids': excludedChatIds, - 'seq': seq, - 'is_hide': isHide, - 'created_at': createdAt, - 'updated_at': updatedAt, - 'deleted_at': deletedAt, - }; - - ChatCategory toEntity() => ChatCategory( - id: id, - name: name, - includedChatIds: includedChatIds, - excludedChatIds: excludedChatIds, - seq: seq, - isHide: isHide, - createdAt: createdAt, - updatedAt: updatedAt, - deletedAt: deletedAt, - ); - - factory ChatCategoryDto.fromEntity(ChatCategory chatCategory) => - ChatCategoryDto( - id: chatCategory.id, - name: chatCategory.name, - includedChatIds: chatCategory.includedChatIds, - excludedChatIds: chatCategory.excludedChatIds, - seq: chatCategory.seq, - isHide: chatCategory.isHide, - createdAt: chatCategory.createdAt, - updatedAt: chatCategory.updatedAt, - deletedAt: chatCategory.deletedAt, - ); - - ChatCategoriesCompanion toCompanion() => ChatCategoriesCompanion( - id: Value(id), - name: Value(name), - includedChatIds: Value(includedChatIds), - excludedChatIds: Value(excludedChatIds), - seq: Value(seq), - isHide: Value(isHide), - createdAt: Value(createdAt), - updatedAt: Value(updatedAt), - deletedAt: Value(deletedAt), - ); -} diff --git a/apps/im_app/lib/data/models/chat_dto.dart b/apps/im_app/lib/data/models/chat_dto.dart deleted file mode 100644 index 5f15487..0000000 --- a/apps/im_app/lib/data/models/chat_dto.dart +++ /dev/null @@ -1,200 +0,0 @@ -/// 聊天 Domain 实体 -class Chat { - final int id; - final int? typ; - final int? lastId; - final int? lastTyp; - final String? lastMsg; - final int? lastTime; - final int lastPos; - final int firstPos; - final int? msgIdx; - final String? profile; - final String? pin; - final String? icon; - final String iconGaussian; - final String? name; - final int? userId; - final int? chatId; - final int? friendId; - final int? sort; - final int? unreadNum; - final int? unreadCount; - final int? hideChatMsgIdx; - final int? readChatMsgIdx; - final int? otherReadIdx; - final String? unreadAtMsgIdx; - final int? deleteTime; - final int? addIndex; - final int flag; - final int? flagMy; - final int? autoDeleteInterval; - final int? mute; - final int? verified; - final int? createTime; - final int? startIdx; - final int? isReadMsg; - final String translateOutgoing; - final String translateIncoming; - final int incomingIdx; - final int outgoingIdx; - final int incomingSoundId; - final int outgoingSoundId; - final int notificationSoundId; - final String chatKey; - final String activeChatKey; - final int coverIdx; - final int round; - final int workspaceId; - final int localPermission; - - const Chat({ - required this.id, - this.typ, - this.lastId, - this.lastTyp, - this.lastMsg, - this.lastTime, - this.lastPos = 0, - this.firstPos = -1, - this.msgIdx, - this.profile, - this.pin, - this.icon, - this.iconGaussian = '', - this.name, - this.userId, - this.chatId, - this.friendId, - this.sort, - this.unreadNum, - this.unreadCount, - this.hideChatMsgIdx, - this.readChatMsgIdx, - this.otherReadIdx, - this.unreadAtMsgIdx, - this.deleteTime, - this.addIndex, - this.flag = 0, - this.flagMy, - this.autoDeleteInterval, - this.mute, - this.verified, - this.createTime, - this.startIdx, - this.isReadMsg, - this.translateOutgoing = '', - this.translateIncoming = '', - this.incomingIdx = 0, - this.outgoingIdx = 0, - this.incomingSoundId = 0, - this.outgoingSoundId = 0, - this.notificationSoundId = 0, - this.chatKey = '', - this.activeChatKey = '', - this.coverIdx = 0, - this.round = 0, - this.workspaceId = 0, - this.localPermission = 0, - }); - - Chat copyWith({ - int? id, - int? typ, - int? lastId, - int? lastTyp, - String? lastMsg, - int? lastTime, - int? lastPos, - int? firstPos, - int? msgIdx, - String? profile, - String? pin, - String? icon, - String? iconGaussian, - String? name, - int? userId, - int? chatId, - int? friendId, - int? sort, - int? unreadNum, - int? unreadCount, - int? hideChatMsgIdx, - int? readChatMsgIdx, - int? otherReadIdx, - String? unreadAtMsgIdx, - int? deleteTime, - int? addIndex, - int? flag, - int? flagMy, - int? autoDeleteInterval, - int? mute, - int? verified, - int? createTime, - int? startIdx, - int? isReadMsg, - String? translateOutgoing, - String? translateIncoming, - int? incomingIdx, - int? outgoingIdx, - int? incomingSoundId, - int? outgoingSoundId, - int? notificationSoundId, - String? chatKey, - String? activeChatKey, - int? coverIdx, - int? round, - int? workspaceId, - int? localPermission, - }) { - return Chat( - id: id ?? this.id, - typ: typ ?? this.typ, - lastId: lastId ?? this.lastId, - lastTyp: lastTyp ?? this.lastTyp, - lastMsg: lastMsg ?? this.lastMsg, - lastTime: lastTime ?? this.lastTime, - lastPos: lastPos ?? this.lastPos, - firstPos: firstPos ?? this.firstPos, - msgIdx: msgIdx ?? this.msgIdx, - profile: profile ?? this.profile, - pin: pin ?? this.pin, - icon: icon ?? this.icon, - iconGaussian: iconGaussian ?? this.iconGaussian, - name: name ?? this.name, - userId: userId ?? this.userId, - chatId: chatId ?? this.chatId, - friendId: friendId ?? this.friendId, - sort: sort ?? this.sort, - unreadNum: unreadNum ?? this.unreadNum, - unreadCount: unreadCount ?? this.unreadCount, - hideChatMsgIdx: hideChatMsgIdx ?? this.hideChatMsgIdx, - readChatMsgIdx: readChatMsgIdx ?? this.readChatMsgIdx, - otherReadIdx: otherReadIdx ?? this.otherReadIdx, - unreadAtMsgIdx: unreadAtMsgIdx ?? this.unreadAtMsgIdx, - deleteTime: deleteTime ?? this.deleteTime, - addIndex: addIndex ?? this.addIndex, - flag: flag ?? this.flag, - flagMy: flagMy ?? this.flagMy, - autoDeleteInterval: autoDeleteInterval ?? this.autoDeleteInterval, - mute: mute ?? this.mute, - verified: verified ?? this.verified, - createTime: createTime ?? this.createTime, - startIdx: startIdx ?? this.startIdx, - isReadMsg: isReadMsg ?? this.isReadMsg, - translateOutgoing: translateOutgoing ?? this.translateOutgoing, - translateIncoming: translateIncoming ?? this.translateIncoming, - incomingIdx: incomingIdx ?? this.incomingIdx, - outgoingIdx: outgoingIdx ?? this.outgoingIdx, - incomingSoundId: incomingSoundId ?? this.incomingSoundId, - outgoingSoundId: outgoingSoundId ?? this.outgoingSoundId, - notificationSoundId: notificationSoundId ?? this.notificationSoundId, - chatKey: chatKey ?? this.chatKey, - activeChatKey: activeChatKey ?? this.activeChatKey, - coverIdx: coverIdx ?? this.coverIdx, - round: round ?? this.round, - workspaceId: workspaceId ?? this.workspaceId, - localPermission: localPermission ?? this.localPermission, - ); - } -} diff --git a/apps/im_app/lib/data/models/explore_mini_app_dto.dart b/apps/im_app/lib/data/models/explore_mini_app_dto.dart deleted file mode 100644 index 20ae5a0..0000000 --- a/apps/im_app/lib/data/models/explore_mini_app_dto.dart +++ /dev/null @@ -1,201 +0,0 @@ -import 'package:drift/drift.dart'; -import 'package:im_app/data/local/drift/app_database.dart'; -import 'package:im_app/domain/entities/explore_mini_app.dart'; - -/// 探索小程序 DTO -class ExploreMiniAppDto { - final String id; - final String? name; - final String? openuid; - final String? devId; - final String? icon; - final String? iconGaussian; - final String? downloadUrl; - final String? description; - final int? version; - final int? typ; - final int? flag; - final int? reviewStatus; - final int? favoriteAt; - final int? isActive; - final int? createdAt; - final int? updatedAt; - final int? deletedAt; - final double? score; - final String? channels; - final String? devName; - final String? pictureGaussian; - final String? picture; - final int? commentNum; - final int? lastLoginAt; - final String? screen; - - const ExploreMiniAppDto({ - required this.id, - this.name, - this.openuid, - this.devId, - this.icon, - this.iconGaussian, - this.downloadUrl, - this.description, - this.version, - this.typ, - this.flag, - this.reviewStatus, - this.favoriteAt, - this.isActive, - this.createdAt, - this.updatedAt, - this.deletedAt, - this.score, - this.channels, - this.devName, - this.pictureGaussian, - this.picture, - this.commentNum, - this.lastLoginAt, - this.screen, - }); - - factory ExploreMiniAppDto.fromJson(Map json) => - ExploreMiniAppDto( - id: json['id'] as String, - name: json['name'], - openuid: json['openuid'], - devId: json['dev_id'], - icon: json['icon'], - iconGaussian: json['icon_gaussian'], - downloadUrl: json['download_url'], - description: json['description'], - version: json['version'], - typ: json['typ'], - flag: json['flag'], - reviewStatus: json['review_status'], - favoriteAt: json['favorite_at'], - isActive: json['is_active'], - createdAt: json['created_at'], - updatedAt: json['updated_at'], - deletedAt: json['deleted_at'], - score: json['score']?.toDouble(), - channels: json['channels'], - devName: json['dev_name'], - pictureGaussian: json['picture_gaussian'], - picture: json['picture'], - commentNum: json['comment_num'], - lastLoginAt: json['last_login_at'], - screen: json['screen'], - ); - - Map toJson() => { - 'id': id, - 'name': name, - 'openuid': openuid, - 'dev_id': devId, - 'icon': icon, - 'icon_gaussian': iconGaussian, - 'download_url': downloadUrl, - 'description': description, - 'version': version, - 'typ': typ, - 'flag': flag, - 'review_status': reviewStatus, - 'favorite_at': favoriteAt, - 'is_active': isActive, - 'created_at': createdAt, - 'updated_at': updatedAt, - 'deleted_at': deletedAt, - 'score': score, - 'channels': channels, - 'dev_name': devName, - 'picture_gaussian': pictureGaussian, - 'picture': picture, - 'comment_num': commentNum, - 'last_login_at': lastLoginAt, - 'screen': screen, - }; - - ExploreMiniApp toEntity() => ExploreMiniApp( - id: id, - name: name, - openuid: openuid, - devId: devId, - icon: icon, - iconGaussian: iconGaussian, - downloadUrl: downloadUrl, - description: description, - version: version, - typ: typ, - flag: flag, - reviewStatus: reviewStatus, - favoriteAt: favoriteAt, - isActive: isActive, - createdAt: createdAt, - updatedAt: updatedAt, - deletedAt: deletedAt, - score: score, - channels: channels, - devName: devName, - pictureGaussian: pictureGaussian, - picture: picture, - commentNum: commentNum, - lastLoginAt: lastLoginAt, - screen: screen, - ); - - factory ExploreMiniAppDto.fromEntity(ExploreMiniApp app) => ExploreMiniAppDto( - id: app.id, - name: app.name, - openuid: app.openuid, - devId: app.devId, - icon: app.icon, - iconGaussian: app.iconGaussian, - downloadUrl: app.downloadUrl, - description: app.description, - version: app.version, - typ: app.typ, - flag: app.flag, - reviewStatus: app.reviewStatus, - favoriteAt: app.favoriteAt, - isActive: app.isActive, - createdAt: app.createdAt, - updatedAt: app.updatedAt, - deletedAt: app.deletedAt, - score: app.score, - channels: app.channels, - devName: app.devName, - pictureGaussian: app.pictureGaussian, - picture: app.picture, - commentNum: app.commentNum, - lastLoginAt: app.lastLoginAt, - screen: app.screen, - ); - - ExploreMiniAppsCompanion toCompanion() => ExploreMiniAppsCompanion( - id: Value(id), - name: Value(name), - openuid: Value(openuid), - devId: Value(devId), - icon: Value(icon), - iconGaussian: Value(iconGaussian), - downloadUrl: Value(downloadUrl), - description: Value(description), - version: Value(version), - typ: Value(typ), - flag: Value(flag), - reviewStatus: Value(reviewStatus), - favoriteAt: Value(favoriteAt), - isActive: Value(isActive), - createdAt: Value(createdAt), - updatedAt: Value(updatedAt), - deletedAt: Value(deletedAt), - score: Value(score), - channels: Value(channels), - devName: Value(devName), - pictureGaussian: Value(pictureGaussian), - picture: Value(picture), - commentNum: Value(commentNum), - lastLoginAt: Value(lastLoginAt), - screen: Value(screen), - ); -} diff --git a/apps/im_app/lib/data/models/favorite_mini_app_dto.dart b/apps/im_app/lib/data/models/favorite_mini_app_dto.dart deleted file mode 100644 index f035765..0000000 --- a/apps/im_app/lib/data/models/favorite_mini_app_dto.dart +++ /dev/null @@ -1,202 +0,0 @@ -import 'package:drift/drift.dart'; -import 'package:im_app/data/local/drift/app_database.dart'; -import 'package:im_app/domain/entities/favorite_mini_app.dart'; - -/// 收藏小程序 DTO -class FavoriteMiniAppDto { - final String id; - final String? name; - final String? openuid; - final String? devId; - final String? icon; - final String? iconGaussian; - final String? downloadUrl; - final String? description; - final int? version; - final int? typ; - final int? flag; - final int? reviewStatus; - final int? favoriteAt; - final int? isActive; - final int? createdAt; - final int? updatedAt; - final int? deletedAt; - final double? score; - final String? channels; - final String? devName; - final String? pictureGaussian; - final String? picture; - final int? commentNum; - final int? lastLoginAt; - final String? screen; - - const FavoriteMiniAppDto({ - required this.id, - this.name, - this.openuid, - this.devId, - this.icon, - this.iconGaussian, - this.downloadUrl, - this.description, - this.version, - this.typ, - this.flag, - this.reviewStatus, - this.favoriteAt, - this.isActive, - this.createdAt, - this.updatedAt, - this.deletedAt, - this.score, - this.channels, - this.devName, - this.pictureGaussian, - this.picture, - this.commentNum, - this.lastLoginAt, - this.screen, - }); - - factory FavoriteMiniAppDto.fromJson(Map json) => - FavoriteMiniAppDto( - id: json['id'] as String, - name: json['name'], - openuid: json['openuid'], - devId: json['dev_id'], - icon: json['icon'], - iconGaussian: json['icon_gaussian'], - downloadUrl: json['download_url'], - description: json['description'], - version: json['version'], - typ: json['typ'], - flag: json['flag'], - reviewStatus: json['review_status'], - favoriteAt: json['favorite_at'], - isActive: json['is_active'], - createdAt: json['created_at'], - updatedAt: json['updated_at'], - deletedAt: json['deleted_at'], - score: json['score']?.toDouble(), - channels: json['channels'], - devName: json['dev_name'], - pictureGaussian: json['picture_gaussian'], - picture: json['picture'], - commentNum: json['comment_num'], - lastLoginAt: json['last_login_at'], - screen: json['screen'], - ); - - Map toJson() => { - 'id': id, - 'name': name, - 'openuid': openuid, - 'dev_id': devId, - 'icon': icon, - 'icon_gaussian': iconGaussian, - 'download_url': downloadUrl, - 'description': description, - 'version': version, - 'typ': typ, - 'flag': flag, - 'review_status': reviewStatus, - 'favorite_at': favoriteAt, - 'is_active': isActive, - 'created_at': createdAt, - 'updated_at': updatedAt, - 'deleted_at': deletedAt, - 'score': score, - 'channels': channels, - 'dev_name': devName, - 'picture_gaussian': pictureGaussian, - 'picture': picture, - 'comment_num': commentNum, - 'last_login_at': lastLoginAt, - 'screen': screen, - }; - - FavoriteMiniApp toEntity() => FavoriteMiniApp( - id: id, - name: name, - openuid: openuid, - devId: devId, - icon: icon, - iconGaussian: iconGaussian, - downloadUrl: downloadUrl, - description: description, - version: version, - typ: typ, - flag: flag, - reviewStatus: reviewStatus, - favoriteAt: favoriteAt, - isActive: isActive, - createdAt: createdAt, - updatedAt: updatedAt, - deletedAt: deletedAt, - score: score, - channels: channels, - devName: devName, - pictureGaussian: pictureGaussian, - picture: picture, - commentNum: commentNum, - lastLoginAt: lastLoginAt, - screen: screen, - ); - - factory FavoriteMiniAppDto.fromEntity(FavoriteMiniApp app) => - FavoriteMiniAppDto( - id: app.id, - name: app.name, - openuid: app.openuid, - devId: app.devId, - icon: app.icon, - iconGaussian: app.iconGaussian, - downloadUrl: app.downloadUrl, - description: app.description, - version: app.version, - typ: app.typ, - flag: app.flag, - reviewStatus: app.reviewStatus, - favoriteAt: app.favoriteAt, - isActive: app.isActive, - createdAt: app.createdAt, - updatedAt: app.updatedAt, - deletedAt: app.deletedAt, - score: app.score, - channels: app.channels, - devName: app.devName, - pictureGaussian: app.pictureGaussian, - picture: app.picture, - commentNum: app.commentNum, - lastLoginAt: app.lastLoginAt, - screen: app.screen, - ); - - FavoriteMiniAppsCompanion toCompanion() => FavoriteMiniAppsCompanion( - id: Value(id), - name: Value(name), - openuid: Value(openuid), - devId: Value(devId), - icon: Value(icon), - iconGaussian: Value(iconGaussian), - downloadUrl: Value(downloadUrl), - description: Value(description), - version: Value(version), - typ: Value(typ), - flag: Value(flag), - reviewStatus: Value(reviewStatus), - favoriteAt: Value(favoriteAt), - isActive: Value(isActive), - createdAt: Value(createdAt), - updatedAt: Value(updatedAt), - deletedAt: Value(deletedAt), - score: Value(score), - channels: Value(channels), - devName: Value(devName), - pictureGaussian: Value(pictureGaussian), - picture: Value(picture), - commentNum: Value(commentNum), - lastLoginAt: Value(lastLoginAt), - screen: Value(screen), - ); -} diff --git a/apps/im_app/lib/data/models/favourite_detail_dto.dart b/apps/im_app/lib/data/models/favourite_detail_dto.dart deleted file mode 100644 index 6300e6c..0000000 --- a/apps/im_app/lib/data/models/favourite_detail_dto.dart +++ /dev/null @@ -1,83 +0,0 @@ -import 'package:drift/drift.dart'; -import 'package:im_app/data/local/drift/app_database.dart'; -import 'package:im_app/domain/entities/favourite_detail.dart'; - -/// 收藏详情 DTO -class FavouriteDetailDto { - final int? id; - final String relatedId; - final String content; - final int? typ; - final int? messageId; - final int? sendId; - final int? chatId; - final int? sendTime; - - const FavouriteDetailDto({ - this.id, - this.relatedId = '', - this.content = '', - this.typ, - this.messageId, - this.sendId, - this.chatId, - this.sendTime, - }); - - factory FavouriteDetailDto.fromJson(Map json) => - FavouriteDetailDto( - id: json['id'], - relatedId: json['related_id'] ?? '', - content: json['content'] ?? '', - typ: json['typ'], - messageId: json['messageId'], - sendId: json['sendId'], - chatId: json['chatId'], - sendTime: json['sendTime'], - ); - - Map toJson() => { - 'id': id, - 'related_id': relatedId, - 'content': content, - 'typ': typ, - 'messageId': messageId, - 'sendId': sendId, - 'chatId': chatId, - 'sendTime': sendTime, - }; - - FavouriteDetail toEntity() => FavouriteDetail( - id: id, - relatedId: relatedId, - content: content, - typ: typ, - messageId: messageId, - sendId: sendId, - chatId: chatId, - sendTime: sendTime, - ); - - factory FavouriteDetailDto.fromEntity(FavouriteDetail detail) => - FavouriteDetailDto( - id: detail.id, - relatedId: detail.relatedId, - content: detail.content, - typ: detail.typ, - messageId: detail.messageId, - sendId: detail.sendId, - chatId: detail.chatId, - sendTime: detail.sendTime, - ); - - FavouriteDetailsCompanion toCompanion() => FavouriteDetailsCompanion( - id: id != null ? Value(id!) : const Value.absent(), - relatedId: Value(relatedId), - content: Value(content), - typ: Value(typ), - messageId: Value(messageId), - sendId: Value(sendId), - chatId: Value(chatId), - sendTime: Value(sendTime), - ); -} diff --git a/apps/im_app/lib/data/models/favourite_dto.dart b/apps/im_app/lib/data/models/favourite_dto.dart deleted file mode 100644 index 434d424..0000000 --- a/apps/im_app/lib/data/models/favourite_dto.dart +++ /dev/null @@ -1,130 +0,0 @@ -import 'package:drift/drift.dart'; -import 'package:im_app/data/local/drift/app_database.dart'; -import 'package:im_app/domain/entities/favourite.dart'; - -/// 收藏 DTO -class FavouriteDto { - final int id; - final String parentId; - final String data; - final int createdAt; - final int updatedAt; - final int deletedAt; - final int? source; - final int? userId; - final int? authorId; - final String typ; - final String tag; - final int isPin; - final int chatTyp; - final int isUploaded; - final String urls; - - const FavouriteDto({ - required this.id, - this.parentId = '', - this.data = '', - this.createdAt = 0, - this.updatedAt = 0, - this.deletedAt = 0, - this.source, - this.userId, - this.authorId, - this.typ = '[]', - this.tag = '[]', - this.isPin = 0, - this.chatTyp = 0, - this.isUploaded = 1, - this.urls = '[]', - }); - - factory FavouriteDto.fromJson(Map json) => FavouriteDto( - id: json['id'] as int, - parentId: json['parent_id'] ?? '', - data: json['data'] ?? '', - createdAt: json['created_at'] ?? 0, - updatedAt: json['updated_at'] ?? 0, - deletedAt: json['deleted_at'] ?? 0, - source: json['source'], - userId: json['user_id'], - authorId: json['author_id'], - typ: json['typ'] ?? '[]', - tag: json['tag'] ?? '[]', - isPin: json['is_pin'] ?? 0, - chatTyp: json['chat_typ'] ?? 0, - isUploaded: json['is_uploaded'] ?? 1, - urls: json['urls'] ?? '[]', - ); - - Map toJson() => { - 'id': id, - 'parent_id': parentId, - 'data': data, - 'created_at': createdAt, - 'updated_at': updatedAt, - 'deleted_at': deletedAt, - 'source': source, - 'user_id': userId, - 'author_id': authorId, - 'typ': typ, - 'tag': tag, - 'is_pin': isPin, - 'chat_typ': chatTyp, - 'is_uploaded': isUploaded, - 'urls': urls, - }; - - Favourite toEntity() => Favourite( - id: id, - parentId: parentId, - data: data, - createdAt: createdAt, - updatedAt: updatedAt, - deletedAt: deletedAt, - source: source, - userId: userId, - authorId: authorId, - typ: typ, - tag: tag, - isPin: isPin, - chatTyp: chatTyp, - isUploaded: isUploaded, - urls: urls, - ); - - factory FavouriteDto.fromEntity(Favourite favourite) => FavouriteDto( - id: favourite.id, - parentId: favourite.parentId, - data: favourite.data, - createdAt: favourite.createdAt, - updatedAt: favourite.updatedAt, - deletedAt: favourite.deletedAt, - source: favourite.source, - userId: favourite.userId, - authorId: favourite.authorId, - typ: favourite.typ, - tag: favourite.tag, - isPin: favourite.isPin, - chatTyp: favourite.chatTyp, - isUploaded: favourite.isUploaded, - urls: favourite.urls, - ); - - FavouritesCompanion toCompanion() => FavouritesCompanion( - id: Value(id), - parentId: Value(parentId), - data: Value(data), - createdAt: Value(createdAt), - updatedAt: Value(updatedAt), - deletedAt: Value(deletedAt), - source: Value(source), - userId: Value(userId), - authorId: Value(authorId), - typ: Value(typ), - tag: Value(tag), - isPin: Value(isPin), - chatTyp: Value(chatTyp), - isUploaded: Value(isUploaded), - urls: Value(urls), - ); -} diff --git a/apps/im_app/lib/data/models/group_dto.dart b/apps/im_app/lib/data/models/group_dto.dart deleted file mode 100644 index 8f14838..0000000 --- a/apps/im_app/lib/data/models/group_dto.dart +++ /dev/null @@ -1,221 +0,0 @@ -import 'package:drift/drift.dart'; -import 'package:im_app/data/local/drift/app_database.dart'; -import 'package:im_app/domain/entities/group.dart'; - -/// 群组 DTO -class GroupDto { - final int id; - final int? userJoinDate; - final String? name; - final String? profile; - final String? icon; - final String iconGaussian; - final int? permission; - final int? admin; - final String? members; - final int? owner; - final String? admins; - final int? visible; - final int? speakInterval; - final int? groupType; - final int? roomType; - final int? maxNumber; - final int? channelId; - final int? channelGroupId; - final int? createTime; - final int? updateTime; - final int? addIndex; - final int? maxMember; - final int? expireTime; - final int workspaceId; - final int mode; - final int redpacketPlay; - final String? topic; - final String? rp; - - const GroupDto({ - required this.id, - this.userJoinDate, - this.name, - this.profile, - this.icon, - this.iconGaussian = '', - this.permission, - this.admin, - this.members, - this.owner, - this.admins, - this.visible, - this.speakInterval, - this.groupType, - this.roomType, - this.maxNumber, - this.channelId, - this.channelGroupId, - this.createTime, - this.updateTime, - this.addIndex, - this.maxMember, - this.expireTime, - this.workspaceId = 0, - this.mode = 0, - this.redpacketPlay = 0, - this.topic, - this.rp, - }); - - factory GroupDto.fromJson(Map json) => GroupDto( - id: json['id'] as int, - userJoinDate: json['user_join_date'], - name: json['name'], - profile: json['profile'], - icon: json['icon'], - iconGaussian: json['icon_gaussian'] ?? '', - permission: json['permission'], - admin: json['admin'], - members: json['members'], - owner: json['owner'], - admins: json['admins'], - visible: json['visible'], - speakInterval: json['speak_interval'], - groupType: json['group_type'], - roomType: json['room_type'], - maxNumber: json['max_number'], - channelId: json['channel_id'], - channelGroupId: json['channel_group_id'], - createTime: json['create_time'], - updateTime: json['update_time'], - addIndex: json['__add_index'], - maxMember: json['max_member'], - expireTime: json['expire_time'], - workspaceId: json['workspace_id'] ?? 0, - mode: json['mode'] ?? 0, - redpacketPlay: json['redpacket_play'] ?? 0, - topic: json['topic'], - rp: json['rp'], - ); - - Map toJson() => { - 'id': id, - 'user_join_date': userJoinDate, - 'name': name, - 'profile': profile, - 'icon': icon, - 'icon_gaussian': iconGaussian, - 'permission': permission, - 'admin': admin, - 'members': members, - 'owner': owner, - 'admins': admins, - 'visible': visible, - 'speak_interval': speakInterval, - 'group_type': groupType, - 'room_type': roomType, - 'max_number': maxNumber, - 'channel_id': channelId, - 'channel_group_id': channelGroupId, - 'create_time': createTime, - 'update_time': updateTime, - '__add_index': addIndex, - 'max_member': maxMember, - 'expire_time': expireTime, - 'workspace_id': workspaceId, - 'mode': mode, - 'redpacket_play': redpacketPlay, - 'topic': topic, - 'rp': rp, - }; - - Group toEntity() => Group( - id: id, - userJoinDate: userJoinDate, - name: name, - profile: profile, - icon: icon, - iconGaussian: iconGaussian, - permission: permission, - admin: admin, - members: members, - owner: owner, - admins: admins, - visible: visible, - speakInterval: speakInterval, - groupType: groupType, - roomType: roomType, - maxNumber: maxNumber, - channelId: channelId, - channelGroupId: channelGroupId, - createTime: createTime, - updateTime: updateTime, - addIndex: addIndex, - maxMember: maxMember, - expireTime: expireTime, - workspaceId: workspaceId, - mode: mode, - redpacketPlay: redpacketPlay, - topic: topic, - rp: rp, - ); - - factory GroupDto.fromEntity(Group group) => GroupDto( - id: group.id, - userJoinDate: group.userJoinDate, - name: group.name, - profile: group.profile, - icon: group.icon, - iconGaussian: group.iconGaussian, - permission: group.permission, - admin: group.admin, - members: group.members, - owner: group.owner, - admins: group.admins, - visible: group.visible, - speakInterval: group.speakInterval, - groupType: group.groupType, - roomType: group.roomType, - maxNumber: group.maxNumber, - channelId: group.channelId, - channelGroupId: group.channelGroupId, - createTime: group.createTime, - updateTime: group.updateTime, - addIndex: group.addIndex, - maxMember: group.maxMember, - expireTime: group.expireTime, - workspaceId: group.workspaceId, - mode: group.mode, - redpacketPlay: group.redpacketPlay, - topic: group.topic, - rp: group.rp, - ); - - GroupsCompanion toCompanion() => GroupsCompanion( - id: Value(id), - userJoinDate: Value(userJoinDate), - name: Value(name), - profile: Value(profile), - icon: Value(icon), - iconGaussian: Value(iconGaussian), - permission: Value(permission), - admin: Value(admin), - members: Value(members), - owner: Value(owner), - admins: Value(admins), - visible: Value(visible), - speakInterval: Value(speakInterval), - groupType: Value(groupType), - roomType: Value(roomType), - maxNumber: Value(maxNumber), - channelId: Value(channelId), - channelGroupId: Value(channelGroupId), - createTime: Value(createTime), - updateTime: Value(updateTime), - addIndex: Value(addIndex), - maxMember: Value(maxMember), - expireTime: Value(expireTime), - workspaceId: Value(workspaceId), - mode: Value(mode), - redpacketPlay: Value(redpacketPlay), - topic: Value(topic), - rp: Value(rp), - ); -} diff --git a/apps/im_app/lib/data/models/message_dto.dart b/apps/im_app/lib/data/models/message_dto.dart deleted file mode 100644 index 762b4eb..0000000 --- a/apps/im_app/lib/data/models/message_dto.dart +++ /dev/null @@ -1,137 +0,0 @@ -import 'package:drift/drift.dart'; -import 'package:im_app/data/local/drift/app_database.dart'; -import 'package:im_app/domain/entities/message.dart'; - -/// 消息 DTO -class MessageDto { - final int id; - final int? messageId; - final int? chatId; - final int? chatIdx; - final int? sendId; - final String? content; - final int? typ; - final int? sendTime; - final int? expireTime; - final int? createTime; - final String? atUsers; - final String emojis; - final int editTime; - final int refTyp; - final int flag; - final String cmid; - - const MessageDto({ - required this.id, - this.messageId, - this.chatId, - this.chatIdx, - this.sendId, - this.content, - this.typ, - this.sendTime, - this.expireTime, - this.createTime, - this.atUsers, - this.emojis = '[]', - this.editTime = 0, - this.refTyp = 0, - this.flag = 0, - this.cmid = '', - }); - - factory MessageDto.fromJson(Map json) => MessageDto( - id: json['id'] as int, - messageId: json['message_id'], - chatId: json['chat_id'], - chatIdx: json['chat_idx'], - sendId: json['send_id'], - content: json['content'], - typ: json['typ'], - sendTime: json['send_time'], - expireTime: json['expire_time'], - createTime: json['create_time'], - atUsers: json['at_users'], - emojis: json['emojis'] ?? '[]', - editTime: json['edit_time'] ?? 0, - refTyp: json['ref_typ'] ?? 0, - flag: json['flag'] ?? 0, - cmid: json['cmid'] ?? '', - ); - - Map toJson() => { - 'id': id, - 'message_id': messageId, - 'chat_id': chatId, - 'chat_idx': chatIdx, - 'send_id': sendId, - 'content': content, - 'typ': typ, - 'send_time': sendTime, - 'expire_time': expireTime, - 'create_time': createTime, - 'at_users': atUsers, - 'emojis': emojis, - 'edit_time': editTime, - 'ref_typ': refTyp, - 'flag': flag, - 'cmid': cmid, - }; - - Message toEntity() => Message( - id: id, - messageId: messageId, - chatId: chatId, - chatIdx: chatIdx, - sendId: sendId, - content: content, - typ: typ, - sendTime: sendTime, - expireTime: expireTime, - createTime: createTime, - atUsers: atUsers, - emojis: emojis, - editTime: editTime, - refTyp: refTyp, - flag: flag, - cmid: cmid, - ); - - factory MessageDto.fromEntity(Message message) => MessageDto( - id: message.id, - messageId: message.messageId, - chatId: message.chatId, - chatIdx: message.chatIdx, - sendId: message.sendId, - content: message.content, - typ: message.typ, - sendTime: message.sendTime, - expireTime: message.expireTime, - createTime: message.createTime, - atUsers: message.atUsers, - emojis: message.emojis, - editTime: message.editTime, - refTyp: message.refTyp, - flag: message.flag, - cmid: message.cmid, - ); - - MessagesCompanion toCompanion() => MessagesCompanion( - id: Value(id), - messageId: Value(messageId), - chatId: Value(chatId), - chatIdx: Value(chatIdx), - sendId: Value(sendId), - content: Value(content), - typ: Value(typ), - sendTime: Value(sendTime), - expireTime: Value(expireTime), - createTime: Value(createTime), - atUsers: Value(atUsers), - emojis: Value(emojis), - editTime: Value(editTime), - refTyp: Value(refTyp), - flag: Value(flag), - cmid: Value(cmid), - ); -} diff --git a/apps/im_app/lib/data/models/pending_friend_request_history_dto.dart b/apps/im_app/lib/data/models/pending_friend_request_history_dto.dart deleted file mode 100644 index 209ed45..0000000 --- a/apps/im_app/lib/data/models/pending_friend_request_history_dto.dart +++ /dev/null @@ -1,71 +0,0 @@ -import 'package:drift/drift.dart'; -import 'package:im_app/data/local/drift/app_database.dart'; -import 'package:im_app/domain/entities/pending_friend_request_history.dart'; - -/// 待处理好友请求历史 DTO -class PendingFriendRequestHistoryDto { - final int id; - final int uid; - final int requestTime; - final String? remarks; - final String? source; - final int? rs; - - const PendingFriendRequestHistoryDto({ - required this.id, - required this.uid, - required this.requestTime, - this.remarks, - this.source, - this.rs, - }); - - factory PendingFriendRequestHistoryDto.fromJson(Map json) => - PendingFriendRequestHistoryDto( - id: json['id'] as int, - uid: json['uid'] as int, - requestTime: json['request_time'] as int, - remarks: json['remarks'], - source: json['source'], - rs: json['rs'], - ); - - Map toJson() => { - 'id': id, - 'uid': uid, - 'request_time': requestTime, - 'remarks': remarks, - 'source': source, - 'rs': rs, - }; - - PendingFriendRequestHistory toEntity() => PendingFriendRequestHistory( - id: id, - uid: uid, - requestTime: requestTime, - remarks: remarks, - source: source, - rs: rs, - ); - - factory PendingFriendRequestHistoryDto.fromEntity( - PendingFriendRequestHistory history, - ) => PendingFriendRequestHistoryDto( - id: history.id, - uid: history.uid, - requestTime: history.requestTime, - remarks: history.remarks, - source: history.source, - rs: history.rs, - ); - - PendingFriendRequestHistoriesCompanion toCompanion() => - PendingFriendRequestHistoriesCompanion( - id: Value(id), - uid: Value(uid), - requestTime: Value(requestTime), - remarks: Value(remarks), - source: Value(source), - rs: Value(rs), - ); -} diff --git a/apps/im_app/lib/data/models/recent_mini_app_dto.dart b/apps/im_app/lib/data/models/recent_mini_app_dto.dart deleted file mode 100644 index 915f2aa..0000000 --- a/apps/im_app/lib/data/models/recent_mini_app_dto.dart +++ /dev/null @@ -1,201 +0,0 @@ -import 'package:drift/drift.dart'; -import 'package:im_app/data/local/drift/app_database.dart'; -import 'package:im_app/domain/entities/recent_mini_app.dart'; - -/// 最近小程序 DTO -class RecentMiniAppDto { - final String id; - final String? name; - final String? openuid; - final String? devId; - final String? icon; - final String? iconGaussian; - final String? downloadUrl; - final String? description; - final int? version; - final int? typ; - final int? flag; - final int? reviewStatus; - final int? favoriteAt; - final int? isActive; - final int? createdAt; - final int? updatedAt; - final int? deletedAt; - final double? score; - final String? channels; - final String? devName; - final String? pictureGaussian; - final String? picture; - final int? commentNum; - final int? lastLoginAt; - final String? screen; - - const RecentMiniAppDto({ - required this.id, - this.name, - this.openuid, - this.devId, - this.icon, - this.iconGaussian, - this.downloadUrl, - this.description, - this.version, - this.typ, - this.flag, - this.reviewStatus, - this.favoriteAt, - this.isActive, - this.createdAt, - this.updatedAt, - this.deletedAt, - this.score, - this.channels, - this.devName, - this.pictureGaussian, - this.picture, - this.commentNum, - this.lastLoginAt, - this.screen, - }); - - factory RecentMiniAppDto.fromJson(Map json) => - RecentMiniAppDto( - id: json['id'] as String, - name: json['name'], - openuid: json['openuid'], - devId: json['dev_id'], - icon: json['icon'], - iconGaussian: json['icon_gaussian'], - downloadUrl: json['download_url'], - description: json['description'], - version: json['version'], - typ: json['typ'], - flag: json['flag'], - reviewStatus: json['review_status'], - favoriteAt: json['favorite_at'], - isActive: json['is_active'], - createdAt: json['created_at'], - updatedAt: json['updated_at'], - deletedAt: json['deleted_at'], - score: json['score']?.toDouble(), - channels: json['channels'], - devName: json['dev_name'], - pictureGaussian: json['picture_gaussian'], - picture: json['picture'], - commentNum: json['comment_num'], - lastLoginAt: json['last_login_at'], - screen: json['screen'], - ); - - Map toJson() => { - 'id': id, - 'name': name, - 'openuid': openuid, - 'dev_id': devId, - 'icon': icon, - 'icon_gaussian': iconGaussian, - 'download_url': downloadUrl, - 'description': description, - 'version': version, - 'typ': typ, - 'flag': flag, - 'review_status': reviewStatus, - 'favorite_at': favoriteAt, - 'is_active': isActive, - 'created_at': createdAt, - 'updated_at': updatedAt, - 'deleted_at': deletedAt, - 'score': score, - 'channels': channels, - 'dev_name': devName, - 'picture_gaussian': pictureGaussian, - 'picture': picture, - 'comment_num': commentNum, - 'last_login_at': lastLoginAt, - 'screen': screen, - }; - - RecentMiniApp toEntity() => RecentMiniApp( - id: id, - name: name, - openuid: openuid, - devId: devId, - icon: icon, - iconGaussian: iconGaussian, - downloadUrl: downloadUrl, - description: description, - version: version, - typ: typ, - flag: flag, - reviewStatus: reviewStatus, - favoriteAt: favoriteAt, - isActive: isActive, - createdAt: createdAt, - updatedAt: updatedAt, - deletedAt: deletedAt, - score: score, - channels: channels, - devName: devName, - pictureGaussian: pictureGaussian, - picture: picture, - commentNum: commentNum, - lastLoginAt: lastLoginAt, - screen: screen, - ); - - factory RecentMiniAppDto.fromEntity(RecentMiniApp app) => RecentMiniAppDto( - id: app.id, - name: app.name, - openuid: app.openuid, - devId: app.devId, - icon: app.icon, - iconGaussian: app.iconGaussian, - downloadUrl: app.downloadUrl, - description: app.description, - version: app.version, - typ: app.typ, - flag: app.flag, - reviewStatus: app.reviewStatus, - favoriteAt: app.favoriteAt, - isActive: app.isActive, - createdAt: app.createdAt, - updatedAt: app.updatedAt, - deletedAt: app.deletedAt, - score: app.score, - channels: app.channels, - devName: app.devName, - pictureGaussian: app.pictureGaussian, - picture: app.picture, - commentNum: app.commentNum, - lastLoginAt: app.lastLoginAt, - screen: app.screen, - ); - - RecentMiniAppsCompanion toCompanion() => RecentMiniAppsCompanion( - id: Value(id), - name: Value(name), - openuid: Value(openuid), - devId: Value(devId), - icon: Value(icon), - iconGaussian: Value(iconGaussian), - downloadUrl: Value(downloadUrl), - description: Value(description), - version: Value(version), - typ: Value(typ), - flag: Value(flag), - reviewStatus: Value(reviewStatus), - favoriteAt: Value(favoriteAt), - isActive: Value(isActive), - createdAt: Value(createdAt), - updatedAt: Value(updatedAt), - deletedAt: Value(deletedAt), - score: Value(score), - channels: Value(channels), - devName: Value(devName), - pictureGaussian: Value(pictureGaussian), - picture: Value(picture), - commentNum: Value(commentNum), - lastLoginAt: Value(lastLoginAt), - screen: Value(screen), - ); -} diff --git a/apps/im_app/lib/data/models/retry_dto.dart b/apps/im_app/lib/data/models/retry_dto.dart deleted file mode 100644 index feb9bd5..0000000 --- a/apps/im_app/lib/data/models/retry_dto.dart +++ /dev/null @@ -1,109 +0,0 @@ -import 'package:drift/drift.dart'; -import 'package:im_app/data/local/drift/app_database.dart'; -import 'package:im_app/domain/entities/retry.dart'; - -/// 重试 DTO -class RetryDto { - final int? id; - final int? uid; - final String apiType; - final String endPoint; - final String requestData; - final int? synced; - final String callbackFun; - final int? expired; - final int? replace; - final int? expireTime; - final int? createTime; - final int? addIndex; - - const RetryDto({ - this.id, - this.uid, - this.apiType = '', - this.endPoint = '', - this.requestData = '', - this.synced, - this.callbackFun = '', - this.expired, - this.replace, - this.expireTime, - this.createTime, - this.addIndex, - }); - - factory RetryDto.fromJson(Map json) => RetryDto( - id: json['id'], - uid: json['uid'], - apiType: json['api_type'] ?? '', - endPoint: json['end_point'] ?? '', - requestData: json['request_data'] ?? '', - synced: json['synced'], - callbackFun: json['callback_fun'] ?? '', - expired: json['expired'], - replace: json['replace'], - expireTime: json['expire_time'], - createTime: json['create_time'], - addIndex: json['__add_index'], - ); - - Map toJson() => { - 'id': id, - 'uid': uid, - 'api_type': apiType, - 'end_point': endPoint, - 'request_data': requestData, - 'synced': synced, - 'callback_fun': callbackFun, - 'expired': expired, - 'replace': replace, - 'expire_time': expireTime, - 'create_time': createTime, - '__add_index': addIndex, - }; - - Retry toEntity() => Retry( - id: id, - uid: uid, - apiType: apiType, - endPoint: endPoint, - requestData: requestData, - synced: synced, - callbackFun: callbackFun, - expired: expired, - replace: replace, - expireTime: expireTime, - createTime: createTime, - addIndex: addIndex, - ); - - factory RetryDto.fromEntity(Retry retry) => RetryDto( - id: retry.id, - uid: retry.uid, - apiType: retry.apiType, - endPoint: retry.endPoint, - requestData: retry.requestData, - synced: retry.synced, - callbackFun: retry.callbackFun, - expired: retry.expired, - replace: retry.replace, - expireTime: retry.expireTime, - createTime: retry.createTime, - addIndex: retry.addIndex, - ); - - RetriesCompanion toCompanion() => RetriesCompanion( - id: id != null ? Value(id!) : const Value.absent(), - uid: Value(uid), - apiType: Value(apiType), - endPoint: Value(endPoint), - requestData: Value(requestData), - synced: Value(synced), - callbackFun: Value(callbackFun), - expired: Value(expired), - replace: Value(replace), - expireTime: Value(expireTime), - createTime: Value(createTime), - addIndex: Value(addIndex), - ); -} diff --git a/apps/im_app/lib/data/models/sound_dto.dart b/apps/im_app/lib/data/models/sound_dto.dart deleted file mode 100644 index 281561f..0000000 --- a/apps/im_app/lib/data/models/sound_dto.dart +++ /dev/null @@ -1,88 +0,0 @@ -import 'package:drift/drift.dart'; -import 'package:im_app/data/local/drift/app_database.dart'; -import 'package:im_app/domain/entities/sound.dart'; - -/// 音效 DTO -class SoundDto { - final int id; - final String filePath; - final int typ; - final String name; - final int createdAt; - final int updatedAt; - final int deletedAt; - final int channelGroupId; - final int isDefault; - - const SoundDto({ - required this.id, - this.filePath = '', - required this.typ, - this.name = '', - required this.createdAt, - required this.updatedAt, - this.deletedAt = 0, - required this.channelGroupId, - required this.isDefault, - }); - - factory SoundDto.fromJson(Map json) => SoundDto( - id: json['id'] as int, - filePath: json['file_path'] ?? '', - typ: json['typ'] as int, - name: json['name'] ?? '', - createdAt: json['created_at'] as int, - updatedAt: json['updated_at'] as int, - deletedAt: json['deleted_at'] ?? 0, - channelGroupId: json['channel_group_id'] as int, - isDefault: json['is_default'] as int, - ); - - Map toJson() => { - 'id': id, - 'file_path': filePath, - 'typ': typ, - 'name': name, - 'created_at': createdAt, - 'updated_at': updatedAt, - 'deleted_at': deletedAt, - 'channel_group_id': channelGroupId, - 'is_default': isDefault, - }; - - Sound toEntity() => Sound( - id: id, - filePath: filePath, - typ: typ, - name: name, - createdAt: createdAt, - updatedAt: updatedAt, - deletedAt: deletedAt, - channelGroupId: channelGroupId, - isDefault: isDefault, - ); - - factory SoundDto.fromEntity(Sound sound) => SoundDto( - id: sound.id, - filePath: sound.filePath, - typ: sound.typ, - name: sound.name, - createdAt: sound.createdAt, - updatedAt: sound.updatedAt, - deletedAt: sound.deletedAt, - channelGroupId: sound.channelGroupId, - isDefault: sound.isDefault, - ); - - SoundsCompanion toCompanion() => SoundsCompanion( - id: Value(id), - filePath: Value(filePath), - typ: Value(typ), - name: Value(name), - createdAt: Value(createdAt), - updatedAt: Value(updatedAt), - deletedAt: Value(deletedAt), - channelGroupId: Value(channelGroupId), - isDefault: Value(isDefault), - ); -} diff --git a/apps/im_app/lib/data/models/tag_dto.dart b/apps/im_app/lib/data/models/tag_dto.dart deleted file mode 100644 index 32d9910..0000000 --- a/apps/im_app/lib/data/models/tag_dto.dart +++ /dev/null @@ -1,74 +0,0 @@ -import 'package:drift/drift.dart'; -import 'package:im_app/data/local/drift/app_database.dart'; -import 'package:im_app/domain/entities/tag.dart'; - -/// 标签 DTO -class TagDto { - final int? id; - final int? uid; - final String name; - final int? type; - final int? createdAt; - final int? updatedAt; - final int? addIndex; - - const TagDto({ - this.id, - this.uid, - this.name = '', - this.type, - this.createdAt, - this.updatedAt, - this.addIndex, - }); - - factory TagDto.fromJson(Map json) => TagDto( - id: json['id'], - uid: json['uid'], - name: json['name'] ?? '', - type: json['type'], - createdAt: json['created_at'], - updatedAt: json['updated_at'], - addIndex: json['__add_index'], - ); - - Map toJson() => { - 'id': id, - 'uid': uid, - 'name': name, - 'type': type, - 'created_at': createdAt, - 'updated_at': updatedAt, - '__add_index': addIndex, - }; - - Tag toEntity() => Tag( - id: id, - uid: uid, - name: name, - type: type, - createdAt: createdAt, - updatedAt: updatedAt, - addIndex: addIndex, - ); - - factory TagDto.fromEntity(Tag tag) => TagDto( - id: tag.id, - uid: tag.uid, - name: tag.name, - type: tag.type, - createdAt: tag.createdAt, - updatedAt: tag.updatedAt, - addIndex: tag.addIndex, - ); - - TagsCompanion toCompanion() => TagsCompanion( - id: id != null ? Value(id!) : const Value.absent(), - uid: Value(uid), - name: Value(name), - type: Value(type), - createdAt: Value(createdAt), - updatedAt: Value(updatedAt), - addIndex: Value(addIndex), - ); -} diff --git a/apps/im_app/lib/data/models/user_request_history_dto.dart b/apps/im_app/lib/data/models/user_request_history_dto.dart deleted file mode 100644 index 0749a74..0000000 --- a/apps/im_app/lib/data/models/user_request_history_dto.dart +++ /dev/null @@ -1,41 +0,0 @@ -import 'package:drift/drift.dart'; -import 'package:im_app/data/local/drift/app_database.dart'; -import 'package:im_app/domain/entities/user_request_history.dart'; - -/// 用户请求历史 DTO -class UserRequestHistoryDto { - final int id; - final int? status; - final int? createdAt; - - const UserRequestHistoryDto({required this.id, this.status, this.createdAt}); - - factory UserRequestHistoryDto.fromJson(Map json) => - UserRequestHistoryDto( - id: json['id'] as int, - status: json['status'], - createdAt: json['created_at'], - ); - - Map toJson() => { - 'id': id, - 'status': status, - 'created_at': createdAt, - }; - - UserRequestHistory toEntity() => - UserRequestHistory(id: id, status: status, createdAt: createdAt); - - factory UserRequestHistoryDto.fromEntity(UserRequestHistory history) => - UserRequestHistoryDto( - id: history.id, - status: history.status, - createdAt: history.createdAt, - ); - - UserRequestHistoriesCompanion toCompanion() => UserRequestHistoriesCompanion( - id: Value(id), - status: Value(status), - createdAt: Value(createdAt), - ); -} diff --git a/apps/im_app/lib/data/models/workspace_dto.dart b/apps/im_app/lib/data/models/workspace_dto.dart deleted file mode 100644 index a404765..0000000 --- a/apps/im_app/lib/data/models/workspace_dto.dart +++ /dev/null @@ -1,116 +0,0 @@ -import 'package:drift/drift.dart'; -import 'package:im_app/data/local/drift/app_database.dart'; -import 'package:im_app/domain/entities/workspace.dart'; - -/// 工作空间 DTO -class WorkspaceDto { - final int id; - final String? name; - final int? ownerId; - final String? description; - final String? logo; - final int? grade; - final int? cap; - final String? currency; - final int? status; - final int? createdAt; - final int? updatedAt; - final int? deletedAt; - final int? channelGroupId; - - const WorkspaceDto({ - required this.id, - this.name, - this.ownerId, - this.description, - this.logo, - this.grade, - this.cap, - this.currency, - this.status, - this.createdAt, - this.updatedAt, - this.deletedAt, - this.channelGroupId, - }); - - factory WorkspaceDto.fromJson(Map json) => WorkspaceDto( - id: json['id'] as int, - name: json['name'], - ownerId: json['owner_id'], - description: json['description'], - logo: json['logo'], - grade: json['grade'], - cap: json['cap'], - currency: json['currency'], - status: json['status'], - createdAt: json['created_at'], - updatedAt: json['updated_at'], - deletedAt: json['deleted_at'], - channelGroupId: json['channel_group_id'], - ); - - Map toJson() => { - 'id': id, - 'name': name, - 'owner_id': ownerId, - 'description': description, - 'logo': logo, - 'grade': grade, - 'cap': cap, - 'currency': currency, - 'status': status, - 'created_at': createdAt, - 'updated_at': updatedAt, - 'deleted_at': deletedAt, - 'channel_group_id': channelGroupId, - }; - - Workspace toEntity() => Workspace( - id: id, - name: name, - ownerId: ownerId, - description: description, - logo: logo, - grade: grade, - cap: cap, - currency: currency, - status: status, - createdAt: createdAt, - updatedAt: updatedAt, - deletedAt: deletedAt, - channelGroupId: channelGroupId, - ); - - factory WorkspaceDto.fromEntity(Workspace workspace) => WorkspaceDto( - id: workspace.id, - name: workspace.name, - ownerId: workspace.ownerId, - description: workspace.description, - logo: workspace.logo, - grade: workspace.grade, - cap: workspace.cap, - currency: workspace.currency, - status: workspace.status, - createdAt: workspace.createdAt, - updatedAt: workspace.updatedAt, - deletedAt: workspace.deletedAt, - channelGroupId: workspace.channelGroupId, - ); - - WorkspacesCompanion toCompanion() => WorkspacesCompanion( - id: Value(id), - name: Value(name), - ownerId: Value(ownerId), - description: Value(description), - logo: Value(logo), - grade: Value(grade), - cap: Value(cap), - currency: Value(currency), - status: Value(status), - createdAt: Value(createdAt), - updatedAt: Value(updatedAt), - deletedAt: Value(deletedAt), - channelGroupId: Value(channelGroupId), - ); -} diff --git a/apps/im_app/lib/data/repositories/api_retry_repository_impl.dart b/apps/im_app/lib/data/repositories/api_retry_repository_impl.dart new file mode 100644 index 0000000..9c12fdc --- /dev/null +++ b/apps/im_app/lib/data/repositories/api_retry_repository_impl.dart @@ -0,0 +1,214 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/api_retry.dart'; +import 'package:im_app/domain/enums/retry_status.dart'; +import 'package:im_app/domain/repositories/api_retry_repository.dart'; +import 'package:storage_sdk/storage_sdk.dart'; + +class ApiRetryRepositoryImpl implements ApiRetryRepository { + final StorageSdkApi _storage; + + ApiRetryRepositoryImpl(this._storage); + + // ── DB row → Domain ────────────────────────────────────────────────────── + + ApiRetry _toEntity(DriftApiRetry row) => ApiRetry( + id: row.id, + uid: row.uid, + apiType: row.apiType, + endPoint: row.endPoint, + requestData: row.requestData, + synced: row.synced, + callbackFun: row.callbackFun, + expired: row.expired, + replace: row.replace, + expireTime: row.expireTime, + createTime: row.createTime, + addIndex: row.addIndex, + ); + + // ── Domain → DB companion (internal only) ──────────────────────────────── + + ApiRetriesCompanion _toCompanion(ApiRetry apiRetry) => ApiRetriesCompanion( + // id is autoIncrement — omit if null so DB generates it + id: apiRetry.id != null ? Value(apiRetry.id!) : const Value.absent(), + uid: Value(apiRetry.uid), + apiType: Value(apiRetry.apiType), + endPoint: Value(apiRetry.endPoint), + requestData: Value(apiRetry.requestData), + synced: Value(apiRetry.synced), + callbackFun: Value(apiRetry.callbackFun), + expired: Value(apiRetry.expired), + replace: Value(apiRetry.replace), + expireTime: Value(apiRetry.expireTime), + createTime: Value(apiRetry.createTime), + addIndex: Value(apiRetry.addIndex), + ); + + // ── rawQuery row → Domain ───────────────────────────────────────────────── + + ApiRetry _fromRow(QueryRow row) => ApiRetry( + id: row.read('id'), + uid: row.readNullable('uid'), + apiType: row.read('api_type'), + endPoint: row.read('end_point'), + requestData: row.read('request_data'), + synced: row.readNullable('synced'), + callbackFun: row.read('callback_fun'), + expired: row.readNullable('expired'), + replace: row.readNullable('replace'), + expireTime: row.readNullable('expire_time'), + createTime: row.readNullable('create_time'), + addIndex: row.readNullable('add_index'), + ); + + // ── 监听 ───────────────────────────────────────────────────────────────── + + @override + Stream> watchAll() { + return _storage.watchAll().map( + (rows) => rows.map(_toEntity).toList(), + ); + } + + @override + Stream> watchPending() { + return _storage + .watchWhere((t) => t.synced.equals(0)) + .map((rows) => rows.map(_toEntity).toList()); + } + + // ── 读取 ───────────────────────────────────────────────────────────────── + + @override + Future> getAll() async { + final rows = await _storage.selectAll(); + return rows.map(_toEntity).toList(); + } + + @override + Future getById(int id) async { + final row = await _storage.selectFirst( + (t) => t.id.equals(id), + ); + return row != null ? _toEntity(row) : null; + } + + @override + Future getByUid(int uid) async { + final row = await _storage.selectFirst( + (t) => t.uid.equals(uid), + ); + return row != null ? _toEntity(row) : null; + } + + @override + Future> getPending() async { + final rows = await _storage.selectWhere( + (t) => t.synced.equals(0), + ); + return rows.map(_toEntity).toList(); + } + + @override + Future> getActive() async { + final rows = await _storage.selectWhere( + (t) => t.expired.equals(0), + ); + return rows.map(_toEntity).toList(); + } + + @override + Future> getByEndPointPending(String endPoint) async { + final rows = await _storage.rawQuery( + 'SELECT * FROM api_retry WHERE end_point = ? AND synced = 0 ORDER BY create_time ASC', + [endPoint], + ); + return rows.map(_fromRow).toList(); + } + + @override + Future> getBySynced(int synced) async { + final rows = await _storage.rawQuery( + 'SELECT * FROM api_retry WHERE synced = ? ORDER BY create_time ASC', + [synced], + ); + return rows.map(_fromRow).toList(); + } + + // ── 写入 ───────────────────────────────────────────────────────────────── + + @override + Future insert(ApiRetry apiRetry) async { + await _storage.insert(_toCompanion(apiRetry)); + } + + @override + Future insertOrReplace(ApiRetry apiRetry) async { + await _storage.insertOrReplace(_toCompanion(apiRetry)); + } + + @override + Future update(ApiRetry apiRetry) async { + if (apiRetry.id == null) return; + await _storage.updateWhere( + _toCompanion(apiRetry), + (t) => t.id.equals(apiRetry.id!), + ); + } + + @override + Future markSynced(int id) async { + await _storage.updateWhere( + const ApiRetriesCompanion(synced: Value(1)), + (t) => t.id.equals(id), + ); + } + + @override + Future markExpired(int id) async { + await _storage.updateWhere( + const ApiRetriesCompanion(expired: Value(1)), + (t) => t.id.equals(id), + ); + } + + // ── 删除 ───────────────────────────────────────────────────────────────── + + @override + Future delete(int id) async { + await _storage.deleteWhere( + (t) => t.id.equals(id), + ); + } + + @override + Future deleteByUid(int uid) async { + await _storage.deleteWhere( + (t) => t.uid.equals(uid), + ); + } + + @override + Future deleteFinished() async { + await _storage + .rawQuery('DELETE FROM api_retry WHERE synced IN (?, ?, ?, ?)', [ + RetryStatus.success.value, + RetryStatus.failed.value, + RetryStatus.cancel.value, + RetryStatus.replace.value, + ]); + } + + @override + Future deleteSynced() async { + await _storage.deleteWhere( + (t) => t.synced.equals(1), + ); + } + + @override + Future clear() async { + await _storage.deleteAll(); + } +} diff --git a/apps/im_app/lib/data/repositories/base/base_mini_app_repository_impl.dart b/apps/im_app/lib/data/repositories/base/base_mini_app_repository_impl.dart new file mode 100644 index 0000000..072f252 --- /dev/null +++ b/apps/im_app/lib/data/repositories/base/base_mini_app_repository_impl.dart @@ -0,0 +1,118 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/domain/entities/mini_app.dart'; +import 'package:im_app/domain/repositories/mini_app_repository.dart'; +import 'package:storage_sdk/storage_sdk.dart'; + +/// 小程序仓储基类 +/// +/// discover / explore / favorite / recent 四张表共用同一套映射逻辑。 +/// 子类只需提供泛型类型参数 + 实现 [toCompanion]。 +abstract class BaseMiniAppRepositoryImpl + implements MiniAppRepository { + final StorageSdkApi _storage; + + BaseMiniAppRepositoryImpl(this._storage); + + // ── DB row → Domain ────────────────────────────────────────────────────── + + MiniApp _toEntity(dynamic row) => MiniApp( + id: row.id as String, + name: row.name as String?, + openuid: row.openuid as String?, + devId: row.devId as String?, + icon: row.icon as String?, + iconGaussian: row.iconGaussian as String?, + downloadUrl: row.downloadUrl as String?, + description: row.description as String?, + version: row.version as int?, + typ: row.typ as int?, + flag: row.flag as int?, + reviewStatus: row.reviewStatus as int?, + favoriteAt: row.favoriteAt as int?, + isActive: row.isActive as int?, + createdAt: row.createdAt as int?, + updatedAt: row.updatedAt as int?, + deletedAt: row.deletedAt as int?, + score: row.score as double?, + channels: row.channels as String?, + devName: row.devName as String?, + pictureGaussian: row.pictureGaussian as String?, + picture: row.picture as String?, + commentNum: row.commentNum as int?, + lastLoginAt: row.lastLoginAt as String?, + screen: row.screen as String?, + ); + + /// 子类提供对应表的 Companion + Insertable toCompanion(MiniApp miniApp); + + // ── 监听 ───────────────────────────────────────────────────────────────── + + @override + Stream> watchAll() { + return _storage.watchAll().map((rows) => rows.map(_toEntity).toList()); + } + + @override + Stream watch(String id) { + return _storage + .watchFirst((t) => (t as dynamic).id.equals(id)) + .map((row) => row != null ? _toEntity(row) : null); + } + + // ── 读取 ───────────────────────────────────────────────────────────────── + + @override + Future> getAll() async { + final rows = await _storage.selectAll(); + return rows.map(_toEntity).toList(); + } + + @override + Future get(String id) async { + final row = await _storage.selectFirst( + (t) => (t as dynamic).id.equals(id), + ); + return row != null ? _toEntity(row) : null; + } + + @override + Future isExist(String id) async { + final row = await _storage.selectFirst( + (t) => (t as dynamic).id.equals(id), + ); + return row != null; + } + + // ── 写入 ───────────────────────────────────────────────────────────────── + + @override + Future insertOrReplace(MiniApp miniApp) async { + await _storage.insertOrReplace(toCompanion(miniApp)); + } + + @override + Future insertOrReplaceAll(List miniApps) async { + await _storage.batchInsertOrReplace(miniApps.map(toCompanion).toList()); + } + + @override + Future update(MiniApp miniApp) async { + await _storage.updateWhere( + toCompanion(miniApp), + (t) => (t as dynamic).id.equals(miniApp.id), + ); + } + + // ── 删除 ───────────────────────────────────────────────────────────────── + + @override + Future delete(String id) async { + await _storage.deleteWhere((t) => (t as dynamic).id.equals(id)); + } + + @override + Future clear() async { + await _storage.deleteAll(); + } +} diff --git a/apps/im_app/lib/data/repositories/chat_category_repository_impl.dart b/apps/im_app/lib/data/repositories/chat_category_repository_impl.dart new file mode 100644 index 0000000..847fd0e --- /dev/null +++ b/apps/im_app/lib/data/repositories/chat_category_repository_impl.dart @@ -0,0 +1,127 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/chat_category.dart'; +import 'package:im_app/domain/repositories/chat_category_repository.dart'; +import 'package:storage_sdk/storage_sdk.dart'; + +/// 聊天分类仓储实现 +/// +/// ## 职责 +/// - 所有 DB 操作通过 [StorageSdkApi],不直接接触 AppDatabase +/// - DriftChatCategory ↔ Domain ChatCategory 映射 +/// - 所有公开接口只接受 Domain 实体,Companion 转换完全内聚在此类 +/// +/// ## 数据流 +/// ``` +/// 网络:ChatCategory.fromJson(json) → insertOrReplaceChatCategory(chatCategory) → StorageSdkApi → DB +/// 监听:StorageSdkApi.watchAll → DriftChatCategory → _toEntity() → UI +/// ``` +class ChatCategoryRepositoryImpl implements ChatCategoryRepository { + final StorageSdkApi _storage; + + ChatCategoryRepositoryImpl(this._storage); + + // ── DB row → Domain ────────────────────────────────────────────────────── + + ChatCategory _toEntity(DriftChatCategory row) => ChatCategory( + id: row.id, + name: row.name, + includedChatIds: row.includedChatIds, + excludedChatIds: row.excludedChatIds, + seq: row.seq, + isHide: row.isHide, + createdAt: row.createdAt, + updatedAt: row.updatedAt, + deletedAt: row.deletedAt, + ); + + // ── Domain → DB companion (internal only) ──────────────────────────────── + + ChatCategoriesCompanion _toCompanion(ChatCategory chatCategory) => + ChatCategoriesCompanion( + id: Value(chatCategory.id), + name: Value(chatCategory.name), + includedChatIds: Value(chatCategory.includedChatIds), + excludedChatIds: Value(chatCategory.excludedChatIds), + seq: Value(chatCategory.seq), + isHide: Value(chatCategory.isHide), + createdAt: Value(chatCategory.createdAt), + updatedAt: Value(chatCategory.updatedAt), + deletedAt: Value(chatCategory.deletedAt), + ); + + // ── 监听 ───────────────────────────────────────────────────────────────── + + @override + Stream> watchAllChatCategories() { + return _storage.watchAll().map( + (rows) => rows.map(_toEntity).toList(), + ); + } + + @override + Stream watchChatCategory(int id) { + return _storage + .watchFirst( + (t) => t.id.equals(id), + ) + .map((row) => row != null ? _toEntity(row) : null); + } + + // ── 读取 ───────────────────────────────────────────────────────────────── + + @override + Future> getChatCategories() async { + final rows = await _storage.selectAll(); + return rows.map(_toEntity).toList(); + } + + @override + Future getChatCategory(int id) async { + final row = await _storage + .selectFirst( + (t) => t.id.equals(id), + ); + return row != null ? _toEntity(row) : null; + } + + // ── 写入 ───────────────────────────────────────────────────────────────── + + @override + Future insertOrReplaceChatCategory(ChatCategory chatCategory) async { + await _storage.insertOrReplace( + _toCompanion(chatCategory), + ); + } + + @override + Future insertOrReplaceChatCategories( + List chatCategories, + ) async { + await _storage.batchInsertOrReplace( + chatCategories.map(_toCompanion).toList(), + ); + } + + @override + Future updateChatCategory(ChatCategory chatCategory) async { + await _storage.updateWhere( + _toCompanion(chatCategory), + (t) => t.id.equals(chatCategory.id), + ); + } + + // ── 删除 ───────────────────────────────────────────────────────────────── + + @override + Future deleteChatCategory(int id) async { + await _storage.deleteWhere( + (t) => t.id.equals(id), + ); + } + + @override + Future clearChatCategories() async { + await _storage.deleteAll(); + } +} diff --git a/apps/im_app/lib/data/repositories/chat_repository_impl.dart b/apps/im_app/lib/data/repositories/chat_repository_impl.dart new file mode 100644 index 0000000..6c84d02 --- /dev/null +++ b/apps/im_app/lib/data/repositories/chat_repository_impl.dart @@ -0,0 +1,272 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/chat.dart'; +import 'package:im_app/domain/repositories/chat_repository.dart'; +import 'package:storage_sdk/storage_sdk.dart'; + +/// 聊天仓储实现 +/// +/// ## 职责 +/// - 所有 DB 操作通过 [StorageSdkApi],不直接接触 AppDatabase +/// - DriftChat ↔ Domain Chat 映射 +/// - 所有公开接口只接受 Domain 实体,Companion 转换完全内聚在此类 +/// +/// ## 数据流 +/// ``` +/// 网络:Chat.fromJson(json) → insertOrReplaceChat(chat) → StorageSdkApi → DB +/// 监听:StorageSdkApi.watchAll → DriftChat → _toEntity() → UI +/// ``` +class ChatRepositoryImpl implements ChatRepository { + final StorageSdkApi _storage; + + ChatRepositoryImpl(this._storage); + + // ── DB row → Domain ────────────────────────────────────────────────────── + + Chat _toEntity(DriftChat row) => Chat( + id: row.id, + typ: row.typ, + lastId: row.lastId, + lastTyp: row.lastTyp, + lastMsg: row.lastMsg, + lastTime: row.lastTime, + lastPos: row.lastPos, + firstPos: row.firstPos, + msgIdx: row.msgIdx, + profile: row.profile, + pin: row.pin, + icon: row.icon, + iconGaussian: row.iconGaussian, + name: row.name, + userId: row.userId, + chatId: row.chatId, + friendId: row.friendId, + sort: row.sort, + unreadNum: row.unreadNum, + unreadCount: row.unreadCount, + hideChatMsgIdx: row.hideChatMsgIdx, + readChatMsgIdx: row.readChatMsgIdx, + otherReadIdx: row.otherReadIdx, + unreadAtMsgIdx: row.unreadAtMsgIdx, + deleteTime: row.deleteTime, + addIndex: row.addIndex, + flag: row.flag, + flagMy: row.flagMy, + autoDeleteInterval: row.autoDeleteInterval, + mute: row.mute, + verified: row.verified, + createTime: row.createTime, + startIdx: row.startIdx, + isReadMsg: row.isReadMsg, + translateOutgoing: row.translateOutgoing, + translateIncoming: row.translateIncoming, + incomingIdx: row.incomingIdx, + outgoingIdx: row.outgoingIdx, + incomingSoundId: row.incomingSoundId, + outgoingSoundId: row.outgoingSoundId, + notificationSoundId: row.notificationSoundId, + chatKey: row.chatKey, + activeChatKey: row.activeChatKey, + coverIdx: row.coverIdx, + round: row.round, + workspaceId: row.workspaceId, + localPermission: row.localPermission, + ); + + // ── Domain → DB companion (internal only) ──────────────────────────────── + + ChatsCompanion _toCompanion(Chat chat) => ChatsCompanion( + id: Value(chat.id), + typ: Value(chat.typ), + lastId: Value(chat.lastId), + lastTyp: Value(chat.lastTyp), + lastMsg: Value(chat.lastMsg), + lastTime: Value(chat.lastTime), + lastPos: Value(chat.lastPos), + firstPos: Value(chat.firstPos), + msgIdx: Value(chat.msgIdx), + profile: Value(chat.profile), + pin: Value(chat.pin), + icon: Value(chat.icon), + iconGaussian: Value(chat.iconGaussian), + name: Value(chat.name), + userId: Value(chat.userId), + chatId: Value(chat.chatId), + friendId: Value(chat.friendId), + sort: Value(chat.sort), + unreadNum: Value(chat.unreadNum), + unreadCount: Value(chat.unreadCount), + hideChatMsgIdx: Value(chat.hideChatMsgIdx), + readChatMsgIdx: Value(chat.readChatMsgIdx), + otherReadIdx: Value(chat.otherReadIdx), + unreadAtMsgIdx: Value(chat.unreadAtMsgIdx), + deleteTime: Value(chat.deleteTime), + addIndex: Value(chat.addIndex), + flag: Value(chat.flag), + flagMy: Value(chat.flagMy), + autoDeleteInterval: Value(chat.autoDeleteInterval), + mute: Value(chat.mute), + verified: Value(chat.verified), + createTime: Value(chat.createTime), + startIdx: Value(chat.startIdx), + isReadMsg: Value(chat.isReadMsg), + translateOutgoing: Value(chat.translateOutgoing), + translateIncoming: Value(chat.translateIncoming), + incomingIdx: Value(chat.incomingIdx), + outgoingIdx: Value(chat.outgoingIdx), + incomingSoundId: Value(chat.incomingSoundId), + outgoingSoundId: Value(chat.outgoingSoundId), + notificationSoundId: Value(chat.notificationSoundId), + chatKey: Value(chat.chatKey), + activeChatKey: Value(chat.activeChatKey), + coverIdx: Value(chat.coverIdx), + round: Value(chat.round), + workspaceId: Value(chat.workspaceId), + localPermission: Value(chat.localPermission), + ); + + // ── 监听 ───────────────────────────────────────────────────────────────── + + @override + Stream> watchAllChats() { + return _storage.watchAll().map( + (rows) => rows.map(_toEntity).toList(), + ); + } + + @override + Stream watchChat(int id) { + return _storage + .watchFirst((t) => t.id.equals(id)) + .map((row) => row != null ? _toEntity(row) : null); + } + + // ── 读取 ───────────────────────────────────────────────────────────────── + + @override + Future> getChats() async { + final rows = await _storage.selectAll(); + return rows.map(_toEntity).toList(); + } + + @override + Future getChat(int id) async { + final row = await _storage.selectFirst( + (t) => t.id.equals(id), + ); + return row != null ? _toEntity(row) : null; + } + + @override + Future> getChatsPage({ + required int offset, + required int limit, + }) async { + final rows = await _storage.rawQuery( + 'SELECT * FROM chat ORDER BY id LIMIT ? OFFSET ?', + [limit, offset], + ); + return rows + .map( + (row) => Chat( + id: row.read('id'), + typ: row.readNullable('typ'), + lastId: row.readNullable('last_id'), + lastTyp: row.readNullable('last_typ'), + lastMsg: row.readNullable('last_msg'), + lastTime: row.readNullable('last_time'), + lastPos: row.read('last_pos'), + firstPos: row.read('first_pos'), + msgIdx: row.readNullable('msg_idx'), + profile: row.readNullable('profile'), + pin: row.readNullable('pin'), + icon: row.readNullable('icon'), + iconGaussian: row.read('icon_gaussian'), + name: row.readNullable('name'), + userId: row.readNullable('user_id'), + chatId: row.readNullable('chat_id'), + friendId: row.readNullable('friend_id'), + sort: row.readNullable('sort'), + unreadNum: row.readNullable('unread_num'), + unreadCount: row.readNullable('unread_count'), + hideChatMsgIdx: row.readNullable('hide_chat_msg_idx'), + readChatMsgIdx: row.readNullable('read_chat_msg_idx'), + otherReadIdx: row.readNullable('other_read_idx'), + unreadAtMsgIdx: row.readNullable('unread_at_msg_idx'), + deleteTime: row.readNullable('delete_time'), + addIndex: row.readNullable('add_index'), + flag: row.read('flag'), + flagMy: row.readNullable('flag_my'), + autoDeleteInterval: row.readNullable('auto_delete_interval'), + mute: row.readNullable('mute'), + verified: row.readNullable('verified'), + createTime: row.readNullable('create_time'), + startIdx: row.readNullable('start_idx'), + isReadMsg: row.readNullable('is_read_msg'), + translateOutgoing: row.read('translate_outgoing'), + translateIncoming: row.read('translate_incoming'), + incomingIdx: row.read('incoming_idx'), + outgoingIdx: row.read('outgoing_idx'), + incomingSoundId: row.read('incoming_sound_id'), + outgoingSoundId: row.read('outgoing_sound_id'), + notificationSoundId: row.read('notification_sound_id'), + chatKey: row.read('chat_key'), + activeChatKey: row.read('active_chat_key'), + coverIdx: row.read('cover_idx'), + round: row.read('round'), + workspaceId: row.read('workspace_id'), + localPermission: row.read('local_permission'), + ), + ) + .toList(); + } + + @override + Future countChats() async { + return _storage.count(); + } + + // ── 写入 ───────────────────────────────────────────────────────────────── + + @override + Future insertOrReplaceChat(Chat chat) async { + await _storage.insertOrReplace(_toCompanion(chat)); + } + + @override + Future insertOrReplaceChats(List chats) async { + await _storage.batchInsertOrReplace( + chats.map(_toCompanion).toList(), + ); + } + + @override + Future updateChat(Chat chat) async { + await _storage.updateWhere( + _toCompanion(chat), + (t) => t.id.equals(chat.id), + ); + } + + @override + Future updateChatsBatch(List chats) async { + for (final chat in chats) { + await _storage.updateWhere( + _toCompanion(chat), + (t) => t.id.equals(chat.id), + ); + } + } + + // ── 删除 ───────────────────────────────────────────────────────────────── + + @override + Future deleteChat(int id) async { + await _storage.deleteWhere((t) => t.id.equals(id)); + } + + @override + Future clearChats() async { + await _storage.deleteAll(); + } +} diff --git a/apps/im_app/lib/data/repositories/discover_mini_app_repository_impl.dart b/apps/im_app/lib/data/repositories/discover_mini_app_repository_impl.dart new file mode 100644 index 0000000..692d58b --- /dev/null +++ b/apps/im_app/lib/data/repositories/discover_mini_app_repository_impl.dart @@ -0,0 +1,43 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/data/repositories/base/base_mini_app_repository_impl.dart'; +import 'package:im_app/domain/entities/mini_app.dart'; + +class DiscoverMiniAppRepositoryImpl + extends + BaseMiniAppRepositoryImpl< + DriftDiscoverMiniApp, + $DiscoverMiniAppsTable + > { + DiscoverMiniAppRepositoryImpl(super.storage); + + @override + Insertable toCompanion(MiniApp miniApp) => + DiscoverMiniAppsCompanion( + id: Value(miniApp.id), + name: Value(miniApp.name), + openuid: Value(miniApp.openuid), + devId: Value(miniApp.devId), + icon: Value(miniApp.icon), + iconGaussian: Value(miniApp.iconGaussian), + downloadUrl: Value(miniApp.downloadUrl), + description: Value(miniApp.description), + version: Value(miniApp.version), + typ: Value(miniApp.typ), + flag: Value(miniApp.flag), + reviewStatus: Value(miniApp.reviewStatus), + favoriteAt: Value(miniApp.favoriteAt), + isActive: Value(miniApp.isActive), + createdAt: Value(miniApp.createdAt), + updatedAt: Value(miniApp.updatedAt), + deletedAt: Value(miniApp.deletedAt), + score: Value(miniApp.score), + channels: Value(miniApp.channels), + devName: Value(miniApp.devName), + pictureGaussian: Value(miniApp.pictureGaussian), + picture: Value(miniApp.picture), + commentNum: Value(miniApp.commentNum), + lastLoginAt: Value(miniApp.lastLoginAt), + screen: Value(miniApp.screen), + ); +} diff --git a/apps/im_app/lib/data/repositories/explore_mini_app_repository_impl.dart b/apps/im_app/lib/data/repositories/explore_mini_app_repository_impl.dart new file mode 100644 index 0000000..5d89ed3 --- /dev/null +++ b/apps/im_app/lib/data/repositories/explore_mini_app_repository_impl.dart @@ -0,0 +1,40 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/data/repositories/base/base_mini_app_repository_impl.dart'; +import 'package:im_app/domain/entities/mini_app.dart'; + +class ExploreMiniAppRepositoryImpl + extends + BaseMiniAppRepositoryImpl { + ExploreMiniAppRepositoryImpl(super.storage); + + @override + Insertable toCompanion(MiniApp miniApp) => + ExploreMiniAppsCompanion( + id: Value(miniApp.id), + name: Value(miniApp.name), + openuid: Value(miniApp.openuid), + devId: Value(miniApp.devId), + icon: Value(miniApp.icon), + iconGaussian: Value(miniApp.iconGaussian), + downloadUrl: Value(miniApp.downloadUrl), + description: Value(miniApp.description), + version: Value(miniApp.version), + typ: Value(miniApp.typ), + flag: Value(miniApp.flag), + reviewStatus: Value(miniApp.reviewStatus), + favoriteAt: Value(miniApp.favoriteAt), + isActive: Value(miniApp.isActive), + createdAt: Value(miniApp.createdAt), + updatedAt: Value(miniApp.updatedAt), + deletedAt: Value(miniApp.deletedAt), + score: Value(miniApp.score), + channels: Value(miniApp.channels), + devName: Value(miniApp.devName), + pictureGaussian: Value(miniApp.pictureGaussian), + picture: Value(miniApp.picture), + commentNum: Value(miniApp.commentNum), + lastLoginAt: Value(miniApp.lastLoginAt), + screen: Value(miniApp.screen), + ); +} diff --git a/apps/im_app/lib/data/repositories/favorite_detail_repository_impl.dart b/apps/im_app/lib/data/repositories/favorite_detail_repository_impl.dart new file mode 100644 index 0000000..d1cc085 --- /dev/null +++ b/apps/im_app/lib/data/repositories/favorite_detail_repository_impl.dart @@ -0,0 +1,139 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/favorite_detail.dart'; +import 'package:im_app/domain/repositories/favorite_detail_repository.dart'; +import 'package:storage_sdk/storage_sdk.dart'; + +/// 收藏详情仓储实现 +/// +/// ## 注意 +/// - id 为 autoIncrement — insert 时不传 id,由 DB 自动生成 +/// - insertOrReplace 时若 id 为 null 则作为新增处理 +class FavoriteDetailRepositoryImpl implements FavoriteDetailRepository { + final StorageSdkApi _storage; + + FavoriteDetailRepositoryImpl(this._storage); + + // ── DB row → Domain ────────────────────────────────────────────────────── + + FavoriteDetail _toEntity(DriftFavoriteDetail row) => FavoriteDetail( + id: row.id, + relatedId: row.relatedId, + content: row.content, + typ: row.typ, + messageId: row.messageId, + sendId: row.sendId, + chatId: row.chatId, + sendTime: row.sendTime, + ); + + // ── Domain → DB companion (internal only) ──────────────────────────────── + + FavoriteDetailsCompanion _toCompanion(FavoriteDetail detail) => + FavoriteDetailsCompanion( + // id is autoIncrement — omit if null so DB generates it + id: detail.id != null ? Value(detail.id!) : const Value.absent(), + relatedId: Value(detail.relatedId), + content: Value(detail.content), + typ: Value(detail.typ), + messageId: Value(detail.messageId), + sendId: Value(detail.sendId), + chatId: Value(detail.chatId), + sendTime: Value(detail.sendTime), + ); + + // ── 监听 ───────────────────────────────────────────────────────────────── + + @override + Stream> watchAll() { + return _storage.watchAll().map( + (rows) => rows.map(_toEntity).toList(), + ); + } + + @override + Stream> watchByRelatedId(String relatedId) { + return _storage + .watchWhere( + (t) => t.relatedId.equals(relatedId), + ) + .map((rows) => rows.map(_toEntity).toList()); + } + + // ── 读取 ───────────────────────────────────────────────────────────────── + + @override + Future> getAll() async { + final rows = await _storage.selectAll(); + return rows.map(_toEntity).toList(); + } + + @override + Future getById(int id) async { + final row = await _storage + .selectFirst( + (t) => t.id.equals(id), + ); + return row != null ? _toEntity(row) : null; + } + + @override + Future> getByRelatedId(String relatedId) async { + final rows = await _storage + .selectWhere( + (t) => t.relatedId.equals(relatedId), + ); + return rows.map(_toEntity).toList(); + } + + // ── 写入 ───────────────────────────────────────────────────────────────── + + @override + Future insert(FavoriteDetail favoriteDetail) async { + await _storage.insert(_toCompanion(favoriteDetail)); + } + + @override + Future insertAll(List favoriteDetails) async { + for (final detail in favoriteDetails) { + await _storage.insert(_toCompanion(detail)); + } + } + + @override + Future insertOrReplace(FavoriteDetail favoriteDetail) async { + await _storage.insertOrReplace( + _toCompanion(favoriteDetail), + ); + } + + @override + Future update(FavoriteDetail favoriteDetail) async { + if (favoriteDetail.id == null) return; + await _storage.updateWhere( + _toCompanion(favoriteDetail), + (t) => t.id.equals(favoriteDetail.id!), + ); + } + + // ── 删除 ───────────────────────────────────────────────────────────────── + + @override + Future delete(int id) async { + await _storage.deleteWhere( + (t) => t.id.equals(id), + ); + } + + @override + Future deleteByRelatedId(String relatedId) async { + await _storage.deleteWhere( + (t) => t.relatedId.equals(relatedId), + ); + } + + @override + Future clear() async { + await _storage.deleteAll(); + } +} diff --git a/apps/im_app/lib/data/repositories/favorite_mini_app_repository_impl.dart b/apps/im_app/lib/data/repositories/favorite_mini_app_repository_impl.dart new file mode 100644 index 0000000..1f33dcb --- /dev/null +++ b/apps/im_app/lib/data/repositories/favorite_mini_app_repository_impl.dart @@ -0,0 +1,43 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/data/repositories/base/base_mini_app_repository_impl.dart'; +import 'package:im_app/domain/entities/mini_app.dart'; + +class FavoriteMiniAppRepositoryImpl + extends + BaseMiniAppRepositoryImpl< + DriftFavoriteMiniApp, + $FavoriteMiniAppsTable + > { + FavoriteMiniAppRepositoryImpl(super.storage); + + @override + Insertable toCompanion(MiniApp miniApp) => + FavoriteMiniAppsCompanion( + id: Value(miniApp.id), + name: Value(miniApp.name), + openuid: Value(miniApp.openuid), + devId: Value(miniApp.devId), + icon: Value(miniApp.icon), + iconGaussian: Value(miniApp.iconGaussian), + downloadUrl: Value(miniApp.downloadUrl), + description: Value(miniApp.description), + version: Value(miniApp.version), + typ: Value(miniApp.typ), + flag: Value(miniApp.flag), + reviewStatus: Value(miniApp.reviewStatus), + favoriteAt: Value(miniApp.favoriteAt), + isActive: Value(miniApp.isActive), + createdAt: Value(miniApp.createdAt), + updatedAt: Value(miniApp.updatedAt), + deletedAt: Value(miniApp.deletedAt), + score: Value(miniApp.score), + channels: Value(miniApp.channels), + devName: Value(miniApp.devName), + pictureGaussian: Value(miniApp.pictureGaussian), + picture: Value(miniApp.picture), + commentNum: Value(miniApp.commentNum), + lastLoginAt: Value(miniApp.lastLoginAt), + screen: Value(miniApp.screen), + ); +} diff --git a/apps/im_app/lib/data/repositories/favorite_repository_impl.dart b/apps/im_app/lib/data/repositories/favorite_repository_impl.dart new file mode 100644 index 0000000..bfb174d --- /dev/null +++ b/apps/im_app/lib/data/repositories/favorite_repository_impl.dart @@ -0,0 +1,151 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/favorite.dart'; +import 'package:im_app/domain/repositories/favorite_repository.dart'; +import 'package:storage_sdk/storage_sdk.dart'; + +class FavoriteRepositoryImpl implements FavoriteRepository { + final StorageSdkApi _storage; + + FavoriteRepositoryImpl(this._storage); + + // ── DB row → Domain ────────────────────────────────────────────────────── + + Favorite _toEntity(DriftFavorite row) => Favorite( + id: row.id, + parentId: row.parentId, + data: row.data, + createdAt: row.createdAt, + updatedAt: row.updatedAt, + deletedAt: row.deletedAt, + source: row.source, + userId: row.userId, + authorId: row.authorId, + typ: row.typ, + tag: row.tag, + isPin: row.isPin, + chatTyp: row.chatTyp, + isUploaded: row.isUploaded, + urls: row.urls, + ); + + // ── Domain → DB companion (internal only) ──────────────────────────────── + + FavoritesCompanion _toCompanion(Favorite favorite) => FavoritesCompanion( + id: Value(favorite.id), + parentId: Value(favorite.parentId), + data: Value(favorite.data), + createdAt: Value(favorite.createdAt), + updatedAt: Value(favorite.updatedAt), + deletedAt: Value(favorite.deletedAt), + source: Value(favorite.source), + userId: Value(favorite.userId), + authorId: Value(favorite.authorId), + typ: Value(favorite.typ), + tag: Value(favorite.tag), + isPin: Value(favorite.isPin), + chatTyp: Value(favorite.chatTyp), + isUploaded: Value(favorite.isUploaded), + urls: Value(favorite.urls), + ); + + // ── 监听 ───────────────────────────────────────────────────────────────── + + @override + Stream> watchAll() { + return _storage.watchAll().map( + (rows) => rows.map(_toEntity).toList(), + ); + } + + @override + Stream watchById(int id) { + return _storage + .watchFirst((t) => t.id.equals(id)) + .map((row) => row != null ? _toEntity(row) : null); + } + + @override + Stream> watchByParentId(String parentId) { + return _storage + .watchWhere( + (t) => t.parentId.equals(parentId), + ) + .map((rows) => rows.map(_toEntity).toList()); + } + + // ── 读取 ───────────────────────────────────────────────────────────────── + + @override + Future> getAll() async { + final rows = await _storage.selectAll(); + return rows.map(_toEntity).toList(); + } + + @override + Future getById(int id) async { + final row = await _storage.selectFirst( + (t) => t.id.equals(id), + ); + return row != null ? _toEntity(row) : null; + } + + @override + Future> getByParentId(String parentId) async { + final rows = await _storage.selectWhere( + (t) => t.parentId.equals(parentId), + ); + return rows.map(_toEntity).toList(); + } + + @override + Future> getUnuploaded() async { + final rows = await _storage.selectWhere( + (t) => t.isUploaded.equals(0), + ); + return rows.map(_toEntity).toList(); + } + + // ── 写入 ───────────────────────────────────────────────────────────────── + + @override + Future insertOrReplace(Favorite favorite) async { + await _storage.insertOrReplace(_toCompanion(favorite)); + } + + @override + Future insertOrReplaceAll(List favorites) async { + await _storage.batchInsertOrReplace( + favorites.map(_toCompanion).toList(), + ); + } + + @override + Future update(Favorite favorite) async { + await _storage.updateWhere( + _toCompanion(favorite), + (t) => t.id.equals(favorite.id), + ); + } + + // ── 删除 ───────────────────────────────────────────────────────────────── + + @override + Future delete(int id) async { + await _storage.deleteWhere( + (t) => t.id.equals(id), + ); + } + + @override + Future deleteByParentId(String parentId) async { + await _storage.deleteWhere( + (t) => t.parentId.equals(parentId), + ); + } + + @override + Future clear() async { + await _storage.deleteAll(); + } +} diff --git a/apps/im_app/lib/data/repositories/group_repository_impl.dart b/apps/im_app/lib/data/repositories/group_repository_impl.dart new file mode 100644 index 0000000..b5341d0 --- /dev/null +++ b/apps/im_app/lib/data/repositories/group_repository_impl.dart @@ -0,0 +1,163 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/group.dart'; +import 'package:im_app/domain/repositories/group_repository.dart'; +import 'package:storage_sdk/storage_sdk.dart'; + +class GroupRepositoryImpl implements GroupRepository { + final StorageSdkApi _storage; + + GroupRepositoryImpl(this._storage); + + // ── DB row → Domain ────────────────────────────────────────────────────── + + Group _toEntity(DriftGroup row) => Group( + id: row.id, + userJoinDate: row.userJoinDate, + name: row.name, + profile: row.profile, + icon: row.icon, + iconGaussian: row.iconGaussian, + permission: row.permission, + admin: row.admin, + members: row.members, + owner: row.owner, + admins: row.admins, + visible: row.visible, + speakInterval: row.speakInterval, + groupType: row.groupType, + roomType: row.roomType, + maxNumber: row.maxNumber, + channelId: row.channelId, + channelGroupId: row.channelGroupId, + createTime: row.createTime, + updateTime: row.updateTime, + addIndex: row.addIndex, + maxMember: row.maxMember, + expireTime: row.expireTime, + workspaceId: row.workspaceId, + mode: row.mode, + redpacketPlay: row.redpacketPlay, + topic: row.topic, + rp: row.rp, + ); + + // ── Domain → DB companion (internal only) ──────────────────────────────── + + GroupsCompanion _toCompanion(Group group) => GroupsCompanion( + id: Value(group.id), + userJoinDate: Value(group.userJoinDate), + name: Value(group.name), + profile: Value(group.profile), + icon: Value(group.icon), + iconGaussian: Value(group.iconGaussian), + permission: Value(group.permission), + admin: Value(group.admin), + members: Value(group.members), + owner: Value(group.owner), + admins: Value(group.admins), + visible: Value(group.visible), + speakInterval: Value(group.speakInterval), + groupType: Value(group.groupType), + roomType: Value(group.roomType), + maxNumber: Value(group.maxNumber), + channelId: Value(group.channelId), + channelGroupId: Value(group.channelGroupId), + createTime: Value(group.createTime), + updateTime: Value(group.updateTime), + addIndex: Value(group.addIndex), + maxMember: Value(group.maxMember), + expireTime: Value(group.expireTime), + workspaceId: Value(group.workspaceId), + mode: Value(group.mode), + redpacketPlay: Value(group.redpacketPlay), + topic: Value(group.topic), + rp: Value(group.rp), + ); + + // ── 监听 ───────────────────────────────────────────────────────────────── + + @override + Stream> watchAll() { + return _storage.watchAll().map( + (rows) => rows.map(_toEntity).toList(), + ); + } + + @override + Stream watchById(int id) { + return _storage + .watchFirst((t) => t.id.equals(id)) + .map((row) => row != null ? _toEntity(row) : null); + } + + // ── 读取 ───────────────────────────────────────────────────────────────── + + @override + Future> getAll() async { + final rows = await _storage.selectAll(); + return rows.map(_toEntity).toList(); + } + + @override + Future getById(int id) async { + final row = await _storage.selectFirst( + (t) => t.id.equals(id), + ); + return row != null ? _toEntity(row) : null; + } + + @override + Future> getByWorkspace(int workspaceId) async { + final rows = await _storage.selectWhere( + (t) => t.workspaceId.equals(workspaceId), + ); + return rows.map(_toEntity).toList(); + } + + // ── 写入 ───────────────────────────────────────────────────────────────── + + @override + Future insertOrReplace(Group group) async { + await _storage.insertOrReplace(_toCompanion(group)); + } + + @override + Future insertOrReplaceAll(List groups) async { + await _storage.batchInsertOrReplace( + groups.map(_toCompanion).toList(), + ); + } + + @override + Future update(Group group) async { + await _storage.updateWhere( + _toCompanion(group), + (t) => t.id.equals(group.id), + ); + } + + @override + Future updateBatch(List groups) async { + for (final group in groups) { + await _storage.updateWhere( + _toCompanion(group), + (t) => t.id.equals(group.id), + ); + } + } + + // ── 删除 ───────────────────────────────────────────────────────────────── + + @override + Future delete(int id) async { + await _storage.deleteWhere( + (t) => t.id.equals(id), + ); + } + + @override + Future clear() async { + await _storage.deleteAll(); + } +} diff --git a/apps/im_app/lib/data/repositories/message_repository_impl.dart b/apps/im_app/lib/data/repositories/message_repository_impl.dart new file mode 100644 index 0000000..04cf0ae --- /dev/null +++ b/apps/im_app/lib/data/repositories/message_repository_impl.dart @@ -0,0 +1,203 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/message.dart'; +import 'package:im_app/domain/repositories/message_repository.dart'; +import 'package:storage_sdk/storage_sdk.dart'; + +class MessageRepositoryImpl implements MessageRepository { + final StorageSdkApi _storage; + + MessageRepositoryImpl(this._storage); + + // ── DB row → Domain ────────────────────────────────────────────────────── + + Message _toEntity(DriftMessage row) => Message( + id: row.id, + messageId: row.messageId, + chatId: row.chatId, + chatIdx: row.chatIdx, + sendId: row.sendId, + content: row.content, + typ: row.typ, + sendTime: row.sendTime, + expireTime: row.expireTime, + createTime: row.createTime, + atUsers: row.atUsers, + emojis: row.emojis, + editTime: row.editTime, + refTyp: row.refTyp, + flag: row.flag, + cmid: row.cmid, + ); + + // ── Domain → DB companion (internal only) ──────────────────────────────── + + MessagesCompanion _toCompanion(Message message) => MessagesCompanion( + id: Value(message.id), + messageId: Value(message.messageId), + chatId: Value(message.chatId), + chatIdx: Value(message.chatIdx), + sendId: Value(message.sendId), + content: Value(message.content), + typ: Value(message.typ), + sendTime: Value(message.sendTime), + expireTime: Value(message.expireTime), + createTime: Value(message.createTime), + atUsers: Value(message.atUsers), + emojis: Value(message.emojis), + editTime: Value(message.editTime), + refTyp: Value(message.refTyp), + flag: Value(message.flag), + cmid: Value(message.cmid), + ); + + // ── 监听 ───────────────────────────────────────────────────────────────── + + @override + Stream> watchByChatId(int chatId) { + return _storage + .watchWhere( + (t) => t.chatId.equals(chatId), + ) + .map((rows) => rows.map(_toEntity).toList()); + } + + @override + Stream watchById(int id) { + return _storage + .watchFirst((t) => t.id.equals(id)) + .map((row) => row != null ? _toEntity(row) : null); + } + + // ── 读取 ───────────────────────────────────────────────────────────────── + + @override + Future> getByChatId(int chatId) async { + final rows = await _storage.rawQuery( + 'SELECT * FROM message WHERE chat_id = ? ORDER BY chat_idx ASC', + [chatId], + ); + return rows + .map( + (row) => Message( + id: row.read('id'), + messageId: row.readNullable('message_id'), + chatId: row.readNullable('chat_id'), + chatIdx: row.readNullable('chat_idx'), + sendId: row.readNullable('send_id'), + content: row.readNullable('content'), + typ: row.readNullable('typ'), + sendTime: row.readNullable('send_time'), + expireTime: row.readNullable('expire_time'), + createTime: row.readNullable('create_time'), + atUsers: row.readNullable('at_users'), + emojis: row.read('emojis'), + editTime: row.read('edit_time'), + refTyp: row.read('ref_typ'), + flag: row.read('flag'), + cmid: row.read('cmid'), + ), + ) + .toList(); + } + + @override + Future> getByChatIdPage({ + required int chatId, + required int offset, + required int limit, + }) async { + final rows = await _storage.rawQuery( + 'SELECT * FROM message WHERE chat_id = ? ORDER BY chat_idx ASC LIMIT ? OFFSET ?', + [chatId, limit, offset], + ); + return rows + .map( + (row) => Message( + id: row.read('id'), + messageId: row.readNullable('message_id'), + chatId: row.readNullable('chat_id'), + chatIdx: row.readNullable('chat_idx'), + sendId: row.readNullable('send_id'), + content: row.readNullable('content'), + typ: row.readNullable('typ'), + sendTime: row.readNullable('send_time'), + expireTime: row.readNullable('expire_time'), + createTime: row.readNullable('create_time'), + atUsers: row.readNullable('at_users'), + emojis: row.read('emojis'), + editTime: row.read('edit_time'), + refTyp: row.read('ref_typ'), + flag: row.read('flag'), + cmid: row.read('cmid'), + ), + ) + .toList(); + } + + @override + Future getById(int id) async { + final row = await _storage.selectFirst( + (t) => t.id.equals(id), + ); + return row != null ? _toEntity(row) : null; + } + + @override + Future getByMessageId(int messageId) async { + final row = await _storage.selectFirst( + (t) => t.messageId.equals(messageId), + ); + return row != null ? _toEntity(row) : null; + } + + @override + Future countByChatId(int chatId) async { + return _storage.count( + filter: (t) => t.chatId.equals(chatId), + ); + } + + // ── 写入 ───────────────────────────────────────────────────────────────── + + @override + Future insertOrReplace(Message message) async { + await _storage.insertOrReplace(_toCompanion(message)); + } + + @override + Future insertOrReplaceAll(List messages) async { + await _storage.batchInsertOrReplace( + messages.map(_toCompanion).toList(), + ); + } + + @override + Future update(Message message) async { + await _storage.updateWhere( + _toCompanion(message), + (t) => t.id.equals(message.id), + ); + } + + // ── 删除 ───────────────────────────────────────────────────────────────── + + @override + Future delete(int id) async { + await _storage.deleteWhere( + (t) => t.id.equals(id), + ); + } + + @override + Future deleteByChatId(int chatId) async { + await _storage.deleteWhere( + (t) => t.chatId.equals(chatId), + ); + } + + @override + Future clear() async { + await _storage.deleteAll(); + } +} diff --git a/apps/im_app/lib/data/repositories/pending_friend_request_history_repository_impl.dart b/apps/im_app/lib/data/repositories/pending_friend_request_history_repository_impl.dart new file mode 100644 index 0000000..1abb3b7 --- /dev/null +++ b/apps/im_app/lib/data/repositories/pending_friend_request_history_repository_impl.dart @@ -0,0 +1,143 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/pending_friend_request_history.dart'; +import 'package:im_app/domain/repositories/pending_friend_request_history_repository.dart'; +import 'package:storage_sdk/storage_sdk.dart'; + +class PendingFriendRequestHistoryRepositoryImpl + implements PendingFriendRequestHistoryRepository { + final StorageSdkApi _storage; + + PendingFriendRequestHistoryRepositoryImpl(this._storage); + + // ── DB row → Domain ────────────────────────────────────────────────────── + + PendingFriendRequestHistory _toEntity(DriftPendingFriendRequestHistory row) => + PendingFriendRequestHistory( + id: row.id, + uid: row.uid, + requestTime: row.requestTime, + remarks: row.remarks, + source: row.source, + rs: row.rs, + ); + + // ── Domain → DB companion (internal only) ──────────────────────────────── + + PendingFriendRequestHistoriesCompanion _toCompanion( + PendingFriendRequestHistory history, + ) => PendingFriendRequestHistoriesCompanion( + id: Value(history.id), + uid: Value(history.uid), + requestTime: Value(history.requestTime), + remarks: Value(history.remarks), + source: Value(history.source), + rs: Value(history.rs), + ); + + // ── 监听 ───────────────────────────────────────────────────────────────── + + @override + Stream> watchAll() { + return _storage.watchAll().map( + (rows) => rows.map(_toEntity).toList(), + ); + } + + @override + Stream watchById(int id) { + return _storage + .watchFirst< + DriftPendingFriendRequestHistory, + $PendingFriendRequestHistoriesTable + >((t) => t.id.equals(id)) + .map((row) => row != null ? _toEntity(row) : null); + } + + @override + Stream> watchByUid(int uid) { + return _storage + .watchWhere< + DriftPendingFriendRequestHistory, + $PendingFriendRequestHistoriesTable + >((t) => t.uid.equals(uid)) + .map((rows) => rows.map(_toEntity).toList()); + } + + // ── 读取 ───────────────────────────────────────────────────────────────── + + @override + Future> getAll() async { + final rows = await _storage.selectAll(); + return rows.map(_toEntity).toList(); + } + + @override + Future getById(int id) async { + final row = await _storage + .selectFirst< + DriftPendingFriendRequestHistory, + $PendingFriendRequestHistoriesTable + >((t) => t.id.equals(id)); + return row != null ? _toEntity(row) : null; + } + + @override + Future> getByUid(int uid) async { + final rows = await _storage + .selectWhere< + DriftPendingFriendRequestHistory, + $PendingFriendRequestHistoriesTable + >((t) => t.uid.equals(uid)); + return rows.map(_toEntity).toList(); + } + + // ── 写入 ───────────────────────────────────────────────────────────────── + + @override + Future insertOrReplace(PendingFriendRequestHistory history) async { + await _storage.insertOrReplace( + _toCompanion(history), + ); + } + + @override + Future insertOrReplaceAll( + List histories, + ) async { + await _storage.batchInsertOrReplace( + histories.map(_toCompanion).toList(), + ); + } + + @override + Future update(PendingFriendRequestHistory history) async { + await _storage.updateWhere< + DriftPendingFriendRequestHistory, + $PendingFriendRequestHistoriesTable + >(_toCompanion(history), (t) => t.id.equals(history.id)); + } + + // ── 删除 ───────────────────────────────────────────────────────────────── + + @override + Future delete(int id) async { + await _storage.deleteWhere< + DriftPendingFriendRequestHistory, + $PendingFriendRequestHistoriesTable + >((t) => t.id.equals(id)); + } + + @override + Future deleteByUid(int uid) async { + await _storage.deleteWhere< + DriftPendingFriendRequestHistory, + $PendingFriendRequestHistoriesTable + >((t) => t.uid.equals(uid)); + } + + @override + Future clear() async { + await _storage.deleteAll(); + } +} diff --git a/apps/im_app/lib/data/repositories/recent_mini_app_repository_impl.dart b/apps/im_app/lib/data/repositories/recent_mini_app_repository_impl.dart new file mode 100644 index 0000000..4607d8c --- /dev/null +++ b/apps/im_app/lib/data/repositories/recent_mini_app_repository_impl.dart @@ -0,0 +1,40 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/data/repositories/base/base_mini_app_repository_impl.dart'; +import 'package:im_app/domain/entities/mini_app.dart'; + +class RecentMiniAppRepositoryImpl + extends + BaseMiniAppRepositoryImpl { + RecentMiniAppRepositoryImpl(super.storage); + + @override + Insertable toCompanion(MiniApp miniApp) => + RecentMiniAppsCompanion( + id: Value(miniApp.id), + name: Value(miniApp.name), + openuid: Value(miniApp.openuid), + devId: Value(miniApp.devId), + icon: Value(miniApp.icon), + iconGaussian: Value(miniApp.iconGaussian), + downloadUrl: Value(miniApp.downloadUrl), + description: Value(miniApp.description), + version: Value(miniApp.version), + typ: Value(miniApp.typ), + flag: Value(miniApp.flag), + reviewStatus: Value(miniApp.reviewStatus), + favoriteAt: Value(miniApp.favoriteAt), + isActive: Value(miniApp.isActive), + createdAt: Value(miniApp.createdAt), + updatedAt: Value(miniApp.updatedAt), + deletedAt: Value(miniApp.deletedAt), + score: Value(miniApp.score), + channels: Value(miniApp.channels), + devName: Value(miniApp.devName), + pictureGaussian: Value(miniApp.pictureGaussian), + picture: Value(miniApp.picture), + commentNum: Value(miniApp.commentNum), + lastLoginAt: Value(miniApp.lastLoginAt), + screen: Value(miniApp.screen), + ); +} diff --git a/apps/im_app/lib/data/repositories/sound_repository_impl.dart b/apps/im_app/lib/data/repositories/sound_repository_impl.dart new file mode 100644 index 0000000..d550b64 --- /dev/null +++ b/apps/im_app/lib/data/repositories/sound_repository_impl.dart @@ -0,0 +1,138 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/sound.dart'; +import 'package:im_app/domain/repositories/sound_repository.dart'; +import 'package:storage_sdk/storage_sdk.dart'; + +class SoundRepositoryImpl implements SoundRepository { + final StorageSdkApi _storage; + + SoundRepositoryImpl(this._storage); + + // ── DB row → Domain ────────────────────────────────────────────────────── + + Sound _toEntity(DriftSound row) => Sound( + id: row.id, + filePath: row.filePath, + typ: row.typ, + name: row.name, + createdAt: row.createdAt, + updatedAt: row.updatedAt, + deletedAt: row.deletedAt, + channelGroupId: row.channelGroupId, + isDefault: row.isDefault, + ); + + // ── Domain → DB companion (internal only) ──────────────────────────────── + + SoundsCompanion _toCompanion(Sound sound) => SoundsCompanion( + id: Value(sound.id), + filePath: Value(sound.filePath), + typ: Value(sound.typ), + name: Value(sound.name), + createdAt: Value(sound.createdAt), + updatedAt: Value(sound.updatedAt), + deletedAt: Value(sound.deletedAt), + channelGroupId: Value(sound.channelGroupId), + isDefault: Value(sound.isDefault), + ); + + // ── 监听 ───────────────────────────────────────────────────────────────── + + @override + Stream> watchAll() { + return _storage.watchAll().map( + (rows) => rows.map(_toEntity).toList(), + ); + } + + @override + Stream watchById(int id) { + return _storage + .watchFirst((t) => t.id.equals(id)) + .map((row) => row != null ? _toEntity(row) : null); + } + + @override + Stream> watchByType(int typ) { + return _storage + .watchWhere((t) => t.typ.equals(typ)) + .map((rows) => rows.map(_toEntity).toList()); + } + + // ── 读取 ───────────────────────────────────────────────────────────────── + + @override + Future> getAll() async { + final rows = await _storage.selectAll(); + return rows.map(_toEntity).toList(); + } + + @override + Future getById(int id) async { + final row = await _storage.selectFirst( + (t) => t.id.equals(id), + ); + return row != null ? _toEntity(row) : null; + } + + @override + Future> getByType(int typ) async { + final rows = await _storage.selectWhere( + (t) => t.typ.equals(typ), + ); + return rows.map(_toEntity).toList(); + } + + @override + Future> getByChannelGroup(int channelGroupId) async { + final rows = await _storage.selectWhere( + (t) => t.channelGroupId.equals(channelGroupId), + ); + return rows.map(_toEntity).toList(); + } + + @override + Future> getDefaults() async { + final rows = await _storage.selectWhere( + (t) => t.isDefault.equals(1), + ); + return rows.map(_toEntity).toList(); + } + + // ── 写入 ───────────────────────────────────────────────────────────────── + + @override + Future insertOrReplace(Sound sound) async { + await _storage.insertOrReplace(_toCompanion(sound)); + } + + @override + Future insertOrReplaceAll(List sounds) async { + await _storage.batchInsertOrReplace( + sounds.map(_toCompanion).toList(), + ); + } + + @override + Future update(Sound sound) async { + await _storage.updateWhere( + _toCompanion(sound), + (t) => t.id.equals(sound.id), + ); + } + + // ── 删除 ───────────────────────────────────────────────────────────────── + + @override + Future delete(int id) async { + await _storage.deleteWhere( + (t) => t.id.equals(id), + ); + } + + @override + Future clear() async { + await _storage.deleteAll(); + } +} diff --git a/apps/im_app/lib/data/repositories/tag_repository_impl.dart b/apps/im_app/lib/data/repositories/tag_repository_impl.dart new file mode 100644 index 0000000..f1a1465 --- /dev/null +++ b/apps/im_app/lib/data/repositories/tag_repository_impl.dart @@ -0,0 +1,142 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/tag.dart'; +import 'package:im_app/domain/repositories/tag_repository.dart'; +import 'package:storage_sdk/storage_sdk.dart'; + +class TagRepositoryImpl implements TagRepository { + final StorageSdkApi _storage; + + TagRepositoryImpl(this._storage); + + // ── DB row → Domain ────────────────────────────────────────────────────── + + Tag _toEntity(DriftTag row) => Tag( + id: row.id, + uid: row.uid, + name: row.name, + type: row.type, + createdAt: row.createdAt, + updatedAt: row.updatedAt, + addIndex: row.addIndex, + ); + + // ── Domain → DB companion (internal only) ──────────────────────────────── + + TagsCompanion _toCompanion(Tag tag) => TagsCompanion( + id: tag.id != null ? Value(tag.id!) : const Value.absent(), + uid: Value(tag.uid), + name: Value(tag.name), + type: Value(tag.type), + createdAt: Value(tag.createdAt), + updatedAt: Value(tag.updatedAt), + addIndex: Value(tag.addIndex), + ); + + // ── 监听 ───────────────────────────────────────────────────────────────── + + @override + Stream> watchAll() { + return _storage.watchAll().map( + (rows) => rows.map(_toEntity).toList(), + ); + } + + @override + Stream watchById(int id) { + return _storage + .watchFirst((t) => t.id.equals(id)) + .map((row) => row != null ? _toEntity(row) : null); + } + + @override + Stream> watchByUid(int uid) { + return _storage + .watchWhere((t) => t.uid.equals(uid)) + .map((rows) => rows.map(_toEntity).toList()); + } + + @override + Stream> watchByType(int type) { + return _storage + .watchWhere((t) => t.type.equals(type)) + .map((rows) => rows.map(_toEntity).toList()); + } + + // ── 读取 ───────────────────────────────────────────────────────────────── + + @override + Future> getAll() async { + final rows = await _storage.selectAll(); + return rows.map(_toEntity).toList(); + } + + @override + Future getById(int id) async { + final row = await _storage.selectFirst( + (t) => t.id.equals(id), + ); + return row != null ? _toEntity(row) : null; + } + + @override + Future> getByUid(int uid) async { + final rows = await _storage.selectWhere( + (t) => t.uid.equals(uid), + ); + return rows.map(_toEntity).toList(); + } + + @override + Future> getByType(int type) async { + final rows = await _storage.selectWhere( + (t) => t.type.equals(type), + ); + return rows.map(_toEntity).toList(); + } + + // ── 写入 ───────────────────────────────────────────────────────────────── + + @override + Future insert(Tag tag) async { + await _storage.insert(_toCompanion(tag)); + } + + @override + Future insertOrReplace(Tag tag) async { + await _storage.insertOrReplace(_toCompanion(tag)); + } + + @override + Future insertOrReplaceAll(List tags) async { + await _storage.batchInsertOrReplace( + tags.map(_toCompanion).toList(), + ); + } + + @override + Future update(Tag tag) async { + if (tag.id == null) return; + await _storage.updateWhere( + _toCompanion(tag), + (t) => t.id.equals(tag.id!), + ); + } + + // ── 删除 ───────────────────────────────────────────────────────────────── + + @override + Future delete(int id) async { + await _storage.deleteWhere((t) => t.id.equals(id)); + } + + @override + Future deleteByUid(int uid) async { + await _storage.deleteWhere((t) => t.uid.equals(uid)); + } + + @override + Future clear() async { + await _storage.deleteAll(); + } +} diff --git a/apps/im_app/lib/data/repositories/user_repository_impl.dart b/apps/im_app/lib/data/repositories/user_repository_impl.dart index b32f153..e42f00f 100644 --- a/apps/im_app/lib/data/repositories/user_repository_impl.dart +++ b/apps/im_app/lib/data/repositories/user_repository_impl.dart @@ -282,8 +282,10 @@ class UserRepositoryImpl implements UserRepository { @override Future insertOrReplaceUser(User user) async { if (user.requireUpsert) { - await _storage.insertOrReplace(_toCompanion(user)); + await upsertUser(user); } + + await _storage.insertOrReplace(_toCompanion(user)); } @override @@ -331,7 +333,9 @@ class UserRepositoryImpl implements UserRepository { /// /// 内部委托给 [upsertUsers]。 @override - Future upsertUser(User user) => upsertUsers([user]); + Future upsertUser(User user) async { + await _storage.insertOnConflictUpdate(_toPartialCompanion(user)); + } /// 批量 upsert:不存在则插入,存在则仅更新非 null 字段。 /// @@ -343,15 +347,9 @@ class UserRepositoryImpl implements UserRepository { /// 适用场景:从服务端收到部分用户信息,不希望覆盖本地已有的其他字段。 @override Future upsertUsers(List users) async { - await _storage.transaction(() async { - for (final user in users) { - await _storage.insert(_toCompanion(user)); - await _storage.updateWhere( - _toPartialCompanion(user), - (t) => t.uid.equals(user.uid), - ); - } - }); + await _storage.batchInsertOnConflictUpdate( + users.map(_toPartialCompanion).toList(), + ); } // ── 删除 ───────────────────────────────────────────────────────────────── diff --git a/apps/im_app/lib/data/repositories/user_request_history_repository_impl.dart b/apps/im_app/lib/data/repositories/user_request_history_repository_impl.dart new file mode 100644 index 0000000..f3b5346 --- /dev/null +++ b/apps/im_app/lib/data/repositories/user_request_history_repository_impl.dart @@ -0,0 +1,122 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/user_request_history.dart'; +import 'package:im_app/domain/repositories/user_request_history_repository.dart'; +import 'package:storage_sdk/storage_sdk.dart'; + +class UserRequestHistoryRepositoryImpl implements UserRequestHistoryRepository { + final StorageSdkApi _storage; + + UserRequestHistoryRepositoryImpl(this._storage); + + // ── DB row → Domain ────────────────────────────────────────────────────── + + UserRequestHistory _toEntity(DriftUserRequestHistory row) => + UserRequestHistory( + id: row.id, + status: row.status, + createdAt: row.createdAt, + ); + + // ── Domain → DB companion (internal only) ──────────────────────────────── + + UserRequestHistoriesCompanion _toCompanion(UserRequestHistory history) => + UserRequestHistoriesCompanion( + id: Value(history.id), + status: Value(history.status), + createdAt: Value(history.createdAt), + ); + + // ── 监听 ───────────────────────────────────────────────────────────────── + + @override + Stream> watchAll() { + return _storage.watchAll().map( + (rows) => rows.map(_toEntity).toList(), + ); + } + + @override + Stream watchById(int id) { + return _storage + .watchFirst( + (t) => t.id.equals(id), + ) + .map((row) => row != null ? _toEntity(row) : null); + } + + @override + Stream> watchByStatus(int status) { + return _storage + .watchWhere( + (t) => t.status.equals(status), + ) + .map((rows) => rows.map(_toEntity).toList()); + } + + // ── 读取 ───────────────────────────────────────────────────────────────── + + @override + Future> getAll() async { + final rows = await _storage.selectAll(); + return rows.map(_toEntity).toList(); + } + + @override + Future getById(int id) async { + final row = await _storage + .selectFirst( + (t) => t.id.equals(id), + ); + return row != null ? _toEntity(row) : null; + } + + @override + Future> getByStatus(int status) async { + final rows = await _storage + .selectWhere( + (t) => t.status.equals(status), + ); + return rows.map(_toEntity).toList(); + } + + // ── 写入 ───────────────────────────────────────────────────────────────── + + @override + Future insertOrReplace(UserRequestHistory history) async { + await _storage.insertOrReplace( + _toCompanion(history), + ); + } + + @override + Future insertOrReplaceAll(List histories) async { + await _storage.batchInsertOrReplace( + histories.map(_toCompanion).toList(), + ); + } + + @override + Future update(UserRequestHistory history) async { + await _storage + .updateWhere( + _toCompanion(history), + (t) => t.id.equals(history.id), + ); + } + + // ── 删除 ───────────────────────────────────────────────────────────────── + + @override + Future delete(int id) async { + await _storage + .deleteWhere( + (t) => t.id.equals(id), + ); + } + + @override + Future clear() async { + await _storage.deleteAll(); + } +} diff --git a/apps/im_app/lib/data/repositories/workspace_repository_impl.dart b/apps/im_app/lib/data/repositories/workspace_repository_impl.dart new file mode 100644 index 0000000..8565162 --- /dev/null +++ b/apps/im_app/lib/data/repositories/workspace_repository_impl.dart @@ -0,0 +1,123 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/workspace.dart'; +import 'package:im_app/domain/repositories/workspace_repository.dart'; +import 'package:storage_sdk/storage_sdk.dart'; + +class WorkspaceRepositoryImpl implements WorkspaceRepository { + final StorageSdkApi _storage; + + WorkspaceRepositoryImpl(this._storage); + + // ── DB row → Domain ────────────────────────────────────────────────────── + + Workspace _toEntity(DriftWorkspace row) => Workspace( + id: row.id, + name: row.name, + ownerId: row.ownerId, + description: row.description, + logo: row.logo, + grade: row.grade, + cap: row.cap, + currency: row.currency, + status: row.status, + createdAt: row.createdAt, + updatedAt: row.updatedAt, + deletedAt: row.deletedAt, + channelGroupId: row.channelGroupId, + ); + + // ── Domain → DB companion (internal only) ──────────────────────────────── + + WorkspacesCompanion _toCompanion(Workspace workspace) => WorkspacesCompanion( + id: Value(workspace.id), + name: Value(workspace.name), + ownerId: Value(workspace.ownerId), + description: Value(workspace.description), + logo: Value(workspace.logo), + grade: Value(workspace.grade), + cap: Value(workspace.cap), + currency: Value(workspace.currency), + status: Value(workspace.status), + createdAt: Value(workspace.createdAt), + updatedAt: Value(workspace.updatedAt), + deletedAt: Value(workspace.deletedAt), + channelGroupId: Value(workspace.channelGroupId), + ); + + // ── 监听 ───────────────────────────────────────────────────────────────── + + @override + Stream> watchAll() { + return _storage.watchAll().map( + (rows) => rows.map(_toEntity).toList(), + ); + } + + @override + Stream watchById(int id) { + return _storage + .watchFirst((t) => t.id.equals(id)) + .map((row) => row != null ? _toEntity(row) : null); + } + + // ── 读取 ───────────────────────────────────────────────────────────────── + + @override + Future> getAll() async { + final rows = await _storage.selectAll(); + return rows.map(_toEntity).toList(); + } + + @override + Future getById(int id) async { + final row = await _storage.selectFirst( + (t) => t.id.equals(id), + ); + return row != null ? _toEntity(row) : null; + } + + @override + Future> getByOwner(int ownerId) async { + final rows = await _storage.selectWhere( + (t) => t.ownerId.equals(ownerId), + ); + return rows.map(_toEntity).toList(); + } + + // ── 写入 ───────────────────────────────────────────────────────────────── + + @override + Future insertOrReplace(Workspace workspace) async { + await _storage.insertOrReplace(_toCompanion(workspace)); + } + + @override + Future insertOrReplaceAll(List workspaces) async { + await _storage.batchInsertOrReplace( + workspaces.map(_toCompanion).toList(), + ); + } + + @override + Future update(Workspace workspace) async { + await _storage.updateWhere( + _toCompanion(workspace), + (t) => t.id.equals(workspace.id), + ); + } + + // ── 删除 ───────────────────────────────────────────────────────────────── + + @override + Future delete(int id) async { + await _storage.deleteWhere( + (t) => t.id.equals(id), + ); + } + + @override + Future clear() async { + await _storage.deleteAll(); + } +} diff --git a/apps/im_app/lib/domain/entities/retry.dart b/apps/im_app/lib/domain/entities/api_retry.dart similarity index 94% rename from apps/im_app/lib/domain/entities/retry.dart rename to apps/im_app/lib/domain/entities/api_retry.dart index b481708..373d3c7 100644 --- a/apps/im_app/lib/domain/entities/retry.dart +++ b/apps/im_app/lib/domain/entities/api_retry.dart @@ -1,5 +1,5 @@ /// 重试 Domain 实体 -class Retry { +class ApiRetry { final int? id; final int? uid; final String apiType; @@ -13,7 +13,7 @@ class Retry { final int? createTime; final int? addIndex; - const Retry({ + const ApiRetry({ this.id, this.uid, this.apiType = '', @@ -28,7 +28,7 @@ class Retry { this.addIndex, }); - Retry copyWith({ + ApiRetry copyWith({ int? id, int? uid, String? apiType, @@ -42,7 +42,7 @@ class Retry { int? createTime, int? addIndex, }) { - return Retry( + return ApiRetry( id: id ?? this.id, uid: uid ?? this.uid, apiType: apiType ?? this.apiType, diff --git a/apps/im_app/lib/domain/entities/discover_mini_app.dart b/apps/im_app/lib/domain/entities/discover_mini_app.dart index e558a85..3d48c24 100644 --- a/apps/im_app/lib/domain/entities/discover_mini_app.dart +++ b/apps/im_app/lib/domain/entities/discover_mini_app.dart @@ -1,112 +1,31 @@ -/// 发现小程序 Domain 实体 -class DiscoverMiniApp { - final String id; - final String? name; - final String? openuid; - final String? devId; - final String? icon; - final String? iconGaussian; - final String? downloadUrl; - final String? description; - final int? version; - final int? typ; - final int? flag; - final int? reviewStatus; - final int? favoriteAt; - final int? isActive; - final int? createdAt; - final int? updatedAt; - final int? deletedAt; - final double? score; - final String? channels; - final String? devName; - final String? pictureGaussian; - final String? picture; - final int? commentNum; - final String? lastLoginAt; - final String? screen; +import 'package:im_app/domain/entities/mini_app.dart'; +class DiscoverMiniApp extends MiniApp { const DiscoverMiniApp({ - required this.id, - this.name, - this.openuid, - this.devId, - this.icon, - this.iconGaussian, - this.downloadUrl, - this.description, - this.version, - this.typ, - this.flag, - this.reviewStatus, - this.favoriteAt, - this.isActive, - this.createdAt, - this.updatedAt, - this.deletedAt, - this.score, - this.channels, - this.devName, - this.pictureGaussian, - this.picture, - this.commentNum, - this.lastLoginAt, - this.screen, + required super.id, + super.name, + super.openuid, + super.devId, + super.icon, + super.iconGaussian, + super.downloadUrl, + super.description, + super.version, + super.typ, + super.flag, + super.reviewStatus, + super.favoriteAt, + super.isActive, + super.createdAt, + super.updatedAt, + super.deletedAt, + super.score, + super.channels, + super.devName, + super.pictureGaussian, + super.picture, + super.commentNum, + super.lastLoginAt, + super.screen, }); - - DiscoverMiniApp copyWith({ - String? id, - String? name, - String? openuid, - String? devId, - String? icon, - String? iconGaussian, - String? downloadUrl, - String? description, - int? version, - int? typ, - int? flag, - int? reviewStatus, - int? favoriteAt, - int? isActive, - int? createdAt, - int? updatedAt, - int? deletedAt, - double? score, - String? channels, - String? devName, - String? pictureGaussian, - String? picture, - int? commentNum, - String? lastLoginAt, - String? screen, - }) { - return DiscoverMiniApp( - id: id ?? this.id, - name: name ?? this.name, - openuid: openuid ?? this.openuid, - devId: devId ?? this.devId, - icon: icon ?? this.icon, - iconGaussian: iconGaussian ?? this.iconGaussian, - downloadUrl: downloadUrl ?? this.downloadUrl, - description: description ?? this.description, - version: version ?? this.version, - typ: typ ?? this.typ, - flag: flag ?? this.flag, - reviewStatus: reviewStatus ?? this.reviewStatus, - favoriteAt: favoriteAt ?? this.favoriteAt, - isActive: isActive ?? this.isActive, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, - deletedAt: deletedAt ?? this.deletedAt, - score: score ?? this.score, - channels: channels ?? this.channels, - devName: devName ?? this.devName, - pictureGaussian: pictureGaussian ?? this.pictureGaussian, - picture: picture ?? this.picture, - commentNum: commentNum ?? this.commentNum, - lastLoginAt: lastLoginAt ?? this.lastLoginAt, - screen: screen ?? this.screen, - ); - } } diff --git a/apps/im_app/lib/domain/entities/explore_mini_app.dart b/apps/im_app/lib/domain/entities/explore_mini_app.dart index b108649..677004c 100644 --- a/apps/im_app/lib/domain/entities/explore_mini_app.dart +++ b/apps/im_app/lib/domain/entities/explore_mini_app.dart @@ -1,112 +1,31 @@ -/// 探索小程序 Domain 实体 -class ExploreMiniApp { - final String id; - final String? name; - final String? openuid; - final String? devId; - final String? icon; - final String? iconGaussian; - final String? downloadUrl; - final String? description; - final int? version; - final int? typ; - final int? flag; - final int? reviewStatus; - final int? favoriteAt; - final int? isActive; - final int? createdAt; - final int? updatedAt; - final int? deletedAt; - final double? score; - final String? channels; - final String? devName; - final String? pictureGaussian; - final String? picture; - final int? commentNum; - final int? lastLoginAt; - final String? screen; +import 'package:im_app/domain/entities/mini_app.dart'; +class ExploreMiniApp extends MiniApp { const ExploreMiniApp({ - required this.id, - this.name, - this.openuid, - this.devId, - this.icon, - this.iconGaussian, - this.downloadUrl, - this.description, - this.version, - this.typ, - this.flag, - this.reviewStatus, - this.favoriteAt, - this.isActive, - this.createdAt, - this.updatedAt, - this.deletedAt, - this.score, - this.channels, - this.devName, - this.pictureGaussian, - this.picture, - this.commentNum, - this.lastLoginAt, - this.screen, + required super.id, + super.name, + super.openuid, + super.devId, + super.icon, + super.iconGaussian, + super.downloadUrl, + super.description, + super.version, + super.typ, + super.flag, + super.reviewStatus, + super.favoriteAt, + super.isActive, + super.createdAt, + super.updatedAt, + super.deletedAt, + super.score, + super.channels, + super.devName, + super.pictureGaussian, + super.picture, + super.commentNum, + super.lastLoginAt, + super.screen, }); - - ExploreMiniApp copyWith({ - String? id, - String? name, - String? openuid, - String? devId, - String? icon, - String? iconGaussian, - String? downloadUrl, - String? description, - int? version, - int? typ, - int? flag, - int? reviewStatus, - int? favoriteAt, - int? isActive, - int? createdAt, - int? updatedAt, - int? deletedAt, - double? score, - String? channels, - String? devName, - String? pictureGaussian, - String? picture, - int? commentNum, - int? lastLoginAt, - String? screen, - }) { - return ExploreMiniApp( - id: id ?? this.id, - name: name ?? this.name, - openuid: openuid ?? this.openuid, - devId: devId ?? this.devId, - icon: icon ?? this.icon, - iconGaussian: iconGaussian ?? this.iconGaussian, - downloadUrl: downloadUrl ?? this.downloadUrl, - description: description ?? this.description, - version: version ?? this.version, - typ: typ ?? this.typ, - flag: flag ?? this.flag, - reviewStatus: reviewStatus ?? this.reviewStatus, - favoriteAt: favoriteAt ?? this.favoriteAt, - isActive: isActive ?? this.isActive, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, - deletedAt: deletedAt ?? this.deletedAt, - score: score ?? this.score, - channels: channels ?? this.channels, - devName: devName ?? this.devName, - pictureGaussian: pictureGaussian ?? this.pictureGaussian, - picture: picture ?? this.picture, - commentNum: commentNum ?? this.commentNum, - lastLoginAt: lastLoginAt ?? this.lastLoginAt, - screen: screen ?? this.screen, - ); - } } diff --git a/apps/im_app/lib/domain/entities/favourite.dart b/apps/im_app/lib/domain/entities/favorite.dart similarity index 94% rename from apps/im_app/lib/domain/entities/favourite.dart rename to apps/im_app/lib/domain/entities/favorite.dart index 9739eaa..1212109 100644 --- a/apps/im_app/lib/domain/entities/favourite.dart +++ b/apps/im_app/lib/domain/entities/favorite.dart @@ -1,5 +1,5 @@ /// 收藏 Domain 实体 -class Favourite { +class Favorite { final int id; final String parentId; final String data; @@ -16,7 +16,7 @@ class Favourite { final int isUploaded; final String urls; - const Favourite({ + const Favorite({ required this.id, this.parentId = '', this.data = '', @@ -34,7 +34,7 @@ class Favourite { this.urls = '[]', }); - Favourite copyWith({ + Favorite copyWith({ int? id, String? parentId, String? data, @@ -51,7 +51,7 @@ class Favourite { int? isUploaded, String? urls, }) { - return Favourite( + return Favorite( id: id ?? this.id, parentId: parentId ?? this.parentId, data: data ?? this.data, diff --git a/apps/im_app/lib/domain/entities/favourite_detail.dart b/apps/im_app/lib/domain/entities/favorite_detail.dart similarity index 88% rename from apps/im_app/lib/domain/entities/favourite_detail.dart rename to apps/im_app/lib/domain/entities/favorite_detail.dart index 9d59cff..6535fbb 100644 --- a/apps/im_app/lib/domain/entities/favourite_detail.dart +++ b/apps/im_app/lib/domain/entities/favorite_detail.dart @@ -1,5 +1,5 @@ /// 收藏详情 Domain 实体 -class FavouriteDetail { +class FavoriteDetail { final int? id; final String relatedId; final String content; @@ -9,7 +9,7 @@ class FavouriteDetail { final int? chatId; final int? sendTime; - const FavouriteDetail({ + const FavoriteDetail({ this.id, this.relatedId = '', this.content = '', @@ -20,7 +20,7 @@ class FavouriteDetail { this.sendTime, }); - FavouriteDetail copyWith({ + FavoriteDetail copyWith({ int? id, String? relatedId, String? content, @@ -30,7 +30,7 @@ class FavouriteDetail { int? chatId, int? sendTime, }) { - return FavouriteDetail( + return FavoriteDetail( id: id ?? this.id, relatedId: relatedId ?? this.relatedId, content: content ?? this.content, diff --git a/apps/im_app/lib/domain/entities/favorite_mini_app.dart b/apps/im_app/lib/domain/entities/favorite_mini_app.dart index 6fb0890..1af2e5b 100644 --- a/apps/im_app/lib/domain/entities/favorite_mini_app.dart +++ b/apps/im_app/lib/domain/entities/favorite_mini_app.dart @@ -1,112 +1,32 @@ +import 'package:im_app/domain/entities/mini_app.dart'; + /// 收藏小程序 Domain 实体 -class FavoriteMiniApp { - final String id; - final String? name; - final String? openuid; - final String? devId; - final String? icon; - final String? iconGaussian; - final String? downloadUrl; - final String? description; - final int? version; - final int? typ; - final int? flag; - final int? reviewStatus; - final int? favoriteAt; - final int? isActive; - final int? createdAt; - final int? updatedAt; - final int? deletedAt; - final double? score; - final String? channels; - final String? devName; - final String? pictureGaussian; - final String? picture; - final int? commentNum; - final int? lastLoginAt; - final String? screen; - +class FavoriteMiniApp extends MiniApp { const FavoriteMiniApp({ - required this.id, - this.name, - this.openuid, - this.devId, - this.icon, - this.iconGaussian, - this.downloadUrl, - this.description, - this.version, - this.typ, - this.flag, - this.reviewStatus, - this.favoriteAt, - this.isActive, - this.createdAt, - this.updatedAt, - this.deletedAt, - this.score, - this.channels, - this.devName, - this.pictureGaussian, - this.picture, - this.commentNum, - this.lastLoginAt, - this.screen, + required super.id, + super.name, + super.openuid, + super.devId, + super.icon, + super.iconGaussian, + super.downloadUrl, + super.description, + super.version, + super.typ, + super.flag, + super.reviewStatus, + super.favoriteAt, + super.isActive, + super.createdAt, + super.updatedAt, + super.deletedAt, + super.score, + super.channels, + super.devName, + super.pictureGaussian, + super.picture, + super.commentNum, + super.lastLoginAt, + super.screen, }); - - FavoriteMiniApp copyWith({ - String? id, - String? name, - String? openuid, - String? devId, - String? icon, - String? iconGaussian, - String? downloadUrl, - String? description, - int? version, - int? typ, - int? flag, - int? reviewStatus, - int? favoriteAt, - int? isActive, - int? createdAt, - int? updatedAt, - int? deletedAt, - double? score, - String? channels, - String? devName, - String? pictureGaussian, - String? picture, - int? commentNum, - int? lastLoginAt, - String? screen, - }) { - return FavoriteMiniApp( - id: id ?? this.id, - name: name ?? this.name, - openuid: openuid ?? this.openuid, - devId: devId ?? this.devId, - icon: icon ?? this.icon, - iconGaussian: iconGaussian ?? this.iconGaussian, - downloadUrl: downloadUrl ?? this.downloadUrl, - description: description ?? this.description, - version: version ?? this.version, - typ: typ ?? this.typ, - flag: flag ?? this.flag, - reviewStatus: reviewStatus ?? this.reviewStatus, - favoriteAt: favoriteAt ?? this.favoriteAt, - isActive: isActive ?? this.isActive, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, - deletedAt: deletedAt ?? this.deletedAt, - score: score ?? this.score, - channels: channels ?? this.channels, - devName: devName ?? this.devName, - pictureGaussian: pictureGaussian ?? this.pictureGaussian, - picture: picture ?? this.picture, - commentNum: commentNum ?? this.commentNum, - lastLoginAt: lastLoginAt ?? this.lastLoginAt, - screen: screen ?? this.screen, - ); - } } diff --git a/apps/im_app/lib/data/models/discover_mini_app_dto.dart b/apps/im_app/lib/domain/entities/mini_app.dart similarity index 93% rename from apps/im_app/lib/data/models/discover_mini_app_dto.dart rename to apps/im_app/lib/domain/entities/mini_app.dart index e558a85..d8abc0c 100644 --- a/apps/im_app/lib/data/models/discover_mini_app_dto.dart +++ b/apps/im_app/lib/domain/entities/mini_app.dart @@ -1,5 +1,7 @@ -/// 发现小程序 Domain 实体 -class DiscoverMiniApp { +/// 小程序 Domain 实体 +/// +/// discover / explore / favorite / recent 四张表共用同一个实体 +class MiniApp { final String id; final String? name; final String? openuid; @@ -26,7 +28,7 @@ class DiscoverMiniApp { final String? lastLoginAt; final String? screen; - const DiscoverMiniApp({ + const MiniApp({ required this.id, this.name, this.openuid, @@ -54,7 +56,7 @@ class DiscoverMiniApp { this.screen, }); - DiscoverMiniApp copyWith({ + MiniApp copyWith({ String? id, String? name, String? openuid, @@ -81,7 +83,7 @@ class DiscoverMiniApp { String? lastLoginAt, String? screen, }) { - return DiscoverMiniApp( + return MiniApp( id: id ?? this.id, name: name ?? this.name, openuid: openuid ?? this.openuid, diff --git a/apps/im_app/lib/domain/entities/recent_mini_app.dart b/apps/im_app/lib/domain/entities/recent_mini_app.dart index 367a684..851acde 100644 --- a/apps/im_app/lib/domain/entities/recent_mini_app.dart +++ b/apps/im_app/lib/domain/entities/recent_mini_app.dart @@ -1,112 +1,32 @@ +import 'package:im_app/domain/entities/mini_app.dart'; + /// 最近小程序 Domain 实体 -class RecentMiniApp { - final String id; - final String? name; - final String? openuid; - final String? devId; - final String? icon; - final String? iconGaussian; - final String? downloadUrl; - final String? description; - final int? version; - final int? typ; - final int? flag; - final int? reviewStatus; - final int? favoriteAt; - final int? isActive; - final int? createdAt; - final int? updatedAt; - final int? deletedAt; - final double? score; - final String? channels; - final String? devName; - final String? pictureGaussian; - final String? picture; - final int? commentNum; - final int? lastLoginAt; - final String? screen; - +class RecentMiniApp extends MiniApp { const RecentMiniApp({ - required this.id, - this.name, - this.openuid, - this.devId, - this.icon, - this.iconGaussian, - this.downloadUrl, - this.description, - this.version, - this.typ, - this.flag, - this.reviewStatus, - this.favoriteAt, - this.isActive, - this.createdAt, - this.updatedAt, - this.deletedAt, - this.score, - this.channels, - this.devName, - this.pictureGaussian, - this.picture, - this.commentNum, - this.lastLoginAt, - this.screen, + required super.id, + super.name, + super.openuid, + super.devId, + super.icon, + super.iconGaussian, + super.downloadUrl, + super.description, + super.version, + super.typ, + super.flag, + super.reviewStatus, + super.favoriteAt, + super.isActive, + super.createdAt, + super.updatedAt, + super.deletedAt, + super.score, + super.channels, + super.devName, + super.pictureGaussian, + super.picture, + super.commentNum, + super.lastLoginAt, + super.screen, }); - - RecentMiniApp copyWith({ - String? id, - String? name, - String? openuid, - String? devId, - String? icon, - String? iconGaussian, - String? downloadUrl, - String? description, - int? version, - int? typ, - int? flag, - int? reviewStatus, - int? favoriteAt, - int? isActive, - int? createdAt, - int? updatedAt, - int? deletedAt, - double? score, - String? channels, - String? devName, - String? pictureGaussian, - String? picture, - int? commentNum, - int? lastLoginAt, - String? screen, - }) { - return RecentMiniApp( - id: id ?? this.id, - name: name ?? this.name, - openuid: openuid ?? this.openuid, - devId: devId ?? this.devId, - icon: icon ?? this.icon, - iconGaussian: iconGaussian ?? this.iconGaussian, - downloadUrl: downloadUrl ?? this.downloadUrl, - description: description ?? this.description, - version: version ?? this.version, - typ: typ ?? this.typ, - flag: flag ?? this.flag, - reviewStatus: reviewStatus ?? this.reviewStatus, - favoriteAt: favoriteAt ?? this.favoriteAt, - isActive: isActive ?? this.isActive, - createdAt: createdAt ?? this.createdAt, - updatedAt: updatedAt ?? this.updatedAt, - deletedAt: deletedAt ?? this.deletedAt, - score: score ?? this.score, - channels: channels ?? this.channels, - devName: devName ?? this.devName, - pictureGaussian: pictureGaussian ?? this.pictureGaussian, - picture: picture ?? this.picture, - commentNum: commentNum ?? this.commentNum, - lastLoginAt: lastLoginAt ?? this.lastLoginAt, - screen: screen ?? this.screen, - ); - } } diff --git a/apps/im_app/lib/domain/enums/retry_status.dart b/apps/im_app/lib/domain/enums/retry_status.dart new file mode 100644 index 0000000..6151ddf --- /dev/null +++ b/apps/im_app/lib/domain/enums/retry_status.dart @@ -0,0 +1,21 @@ +/// 重试同步状态 +/// +/// 对应 api_retry 表中 synced 字段的值 +enum RetryStatus { + notYet(0), + success(1), + failed(-1), + cancel(2), + replace(3); + + const RetryStatus(this.value); + + final int value; + + static RetryStatus fromValue(int value) { + return RetryStatus.values.firstWhere( + (e) => e.value == value, + orElse: () => RetryStatus.notYet, + ); + } +} diff --git a/apps/im_app/lib/domain/repositories/api_retry_repository.dart b/apps/im_app/lib/domain/repositories/api_retry_repository.dart new file mode 100644 index 0000000..40bf457 --- /dev/null +++ b/apps/im_app/lib/domain/repositories/api_retry_repository.dart @@ -0,0 +1,61 @@ +import 'package:im_app/domain/entities/api_retry.dart'; + +/// API 重试仓储接口 +abstract class ApiRetryRepository { + // ── 监听 ───────────────────────────────────────────────────────────────── + + Stream> watchAll(); + + Stream> watchPending(); + + // ── 读取 ───────────────────────────────────────────────────────────────── + + Future> getAll(); + + Future getById(int id); + + /// 读取指定 uid 的第一条重试任务 + Future getByUid(int uid); + + /// 读取未同步的重试任务 + Future> getPending(); + + /// 读取未过期的重试任务 + Future> getActive(); + + /// 读取指定 endPoint 且未同步的重试任务,按 createTime 升序 + Future> getByEndPointPending(String endPoint); + + /// 读取指定同步状态的所有重试任务,按 createTime 升序 + /// synced: 0 未同步 / 1 已同步 / -1 失败 + Future> getBySynced(int synced); + + // ── 写入 ───────────────────────────────────────────────────────────────── + + /// 插入重试任务(autoIncrement id,无需提供) + Future insert(ApiRetry apiRetry); + + Future insertOrReplace(ApiRetry apiRetry); + + Future update(ApiRetry apiRetry); + + /// 标记为已同步 + Future markSynced(int id); + + /// 标记为已过期 + Future markExpired(int id); + + // ── 删除 ───────────────────────────────────────────────────────────────── + + Future delete(int id); + + Future deleteByUid(int uid); + + /// 删除已完成的重试任务(synced = success / failed / cancel / replace) + Future deleteFinished(); + + /// 清除已同步的重试任务 + Future deleteSynced(); + + Future clear(); +} diff --git a/apps/im_app/lib/domain/repositories/chat_category_repository.dart b/apps/im_app/lib/domain/repositories/chat_category_repository.dart new file mode 100644 index 0000000..feb229e --- /dev/null +++ b/apps/im_app/lib/domain/repositories/chat_category_repository.dart @@ -0,0 +1,51 @@ +import 'package:im_app/domain/entities/chat_category.dart'; + +/// 聊天分类仓储接口 +/// +/// ## 职责 +/// - StorageSdkApi ↔ Domain ChatCategory 映射 +/// - CRUD 操作(通过 StorageSdkApi,不直接接触 DB) +/// - 所有公开接口只接受 Domain 实体,Companion 转换完全内聚在 Impl +/// +/// ## 数据流 +/// ``` +/// 写入:Domain ChatCategory → _toCompanion() → StorageSdkApi → DB +/// 读取:DB row (DriftChatCategory) → _toEntity() → Domain ChatCategory +/// 监听:DB 变化 → stream → Domain ChatCategory → UI +/// ``` +abstract class ChatCategoryRepository { + // ── 监听 ───────────────────────────────────────────────────────────────── + + /// 监听所有聊天分类,DB 变化自动反映 + Stream> watchAllChatCategories(); + + /// 监听指定聊天分类 + Stream watchChatCategory(int id); + + // ── 读取 ───────────────────────────────────────────────────────────────── + + /// 读取所有聊天分类 + Future> getChatCategories(); + + /// 读取指定聊天分类,不存在返回 null + Future getChatCategory(int id); + + // ── 写入 ───────────────────────────────────────────────────────────────── + + /// 插入或替换聊天分类 + Future insertOrReplaceChatCategory(ChatCategory chatCategory); + + /// 批量插入或替换聊天分类 + Future insertOrReplaceChatCategories(List chatCategories); + + /// 更新聊天分类 + Future updateChatCategory(ChatCategory chatCategory); + + // ── 删除 ───────────────────────────────────────────────────────────────── + + /// 删除指定聊天分类 + Future deleteChatCategory(int id); + + /// 清空所有聊天分类 + Future clearChatCategories(); +} diff --git a/apps/im_app/lib/domain/repositories/chat_repository.dart b/apps/im_app/lib/domain/repositories/chat_repository.dart new file mode 100644 index 0000000..189648c --- /dev/null +++ b/apps/im_app/lib/domain/repositories/chat_repository.dart @@ -0,0 +1,60 @@ +import 'package:im_app/domain/entities/chat.dart'; + +/// 聊天仓储接口 +/// +/// ## 职责 +/// - StorageSdkApi ↔ Domain Chat 映射 +/// - CRUD 操作(通过 StorageSdkApi,不直接接触 DB) +/// - 所有公开接口只接受 Domain 实体,Companion 转换完全内聚在 Impl +/// +/// ## 数据流 +/// ``` +/// 写入:Domain Chat → _toCompanion() → StorageSdkApi → DB +/// 读取:DB row (DriftChat) → _toEntity() → Domain Chat +/// 监听:DB 变化 → stream → Domain Chat → UI +/// ``` +abstract class ChatRepository { + // ── 监听 ───────────────────────────────────────────────────────────────── + + /// 监听所有聊天,DB 变化自动反映 + Stream> watchAllChats(); + + /// 监听指定聊天 + Stream watchChat(int id); + + // ── 读取 ───────────────────────────────────────────────────────────────── + + /// 读取所有聊天 + Future> getChats(); + + /// 读取指定聊天,不存在返回 null + Future getChat(int id); + + /// 分页读取聊天 + Future> getChatsPage({required int offset, required int limit}); + + /// 统计聊天总数 + Future countChats(); + + // ── 写入 ───────────────────────────────────────────────────────────────── + + /// 插入或替换聊天 + Future insertOrReplaceChat(Chat chat); + + /// 批量插入或替换聊天 + Future insertOrReplaceChats(List chats); + + /// 更新聊天 + Future updateChat(Chat chat); + + /// 批量更新聊天 + Future updateChatsBatch(List chats); + + // ── 删除 ───────────────────────────────────────────────────────────────── + + /// 删除指定聊天 + Future deleteChat(int id); + + /// 清空所有聊天 + Future clearChats(); +} diff --git a/apps/im_app/lib/domain/repositories/favorite_detail_repository.dart b/apps/im_app/lib/domain/repositories/favorite_detail_repository.dart new file mode 100644 index 0000000..01fa8f6 --- /dev/null +++ b/apps/im_app/lib/domain/repositories/favorite_detail_repository.dart @@ -0,0 +1,60 @@ +import 'package:im_app/domain/entities/favorite_detail.dart'; + +/// 收藏详情仓储接口 +/// +/// ## 职责 +/// - StorageSdkApi ↔ Domain FavoriteDetail 映射 +/// - CRUD 操作(通过 StorageSdkApi,不直接接触 DB) +/// - 所有公开接口只接受 Domain 实体,Companion 转换完全内聚在 Impl +/// +/// ## 数据流 +/// ``` +/// 写入:Domain FavoriteDetail → _toCompanion() → StorageSdkApi → DB +/// 读取:DB row (DriftFavoriteDetail) → _toEntity() → Domain FavoriteDetail +/// 监听:DB 变化 → stream → Domain FavoriteDetail → UI +/// ``` +abstract class FavoriteDetailRepository { + // ── 监听 ───────────────────────────────────────────────────────────────── + + /// 监听所有收藏详情,DB 变化自动反映 + Stream> watchAll(); + + /// 监听指定 relatedId 的收藏详情 + Stream> watchByRelatedId(String relatedId); + + // ── 读取 ───────────────────────────────────────────────────────────────── + + /// 读取所有收藏详情 + Future> getAll(); + + /// 读取指定 id,不存在返回 null + Future getById(int id); + + /// 读取指定 relatedId 的所有收藏详情 + Future> getByRelatedId(String relatedId); + + // ── 写入 ───────────────────────────────────────────────────────────────── + + /// 插入收藏详情(autoIncrement id,无需提供) + Future insert(FavoriteDetail favoriteDetail); + + /// 批量插入收藏详情 + Future insertAll(List favoriteDetails); + + /// 插入或替换收藏详情 + Future insertOrReplace(FavoriteDetail favoriteDetail); + + /// 更新收藏详情 + Future update(FavoriteDetail favoriteDetail); + + // ── 删除 ───────────────────────────────────────────────────────────────── + + /// 删除指定 id + Future delete(int id); + + /// 删除指定 relatedId 的所有收藏详情 + Future deleteByRelatedId(String relatedId); + + /// 清空所有收藏详情 + Future clear(); +} diff --git a/apps/im_app/lib/domain/repositories/favorite_repository.dart b/apps/im_app/lib/domain/repositories/favorite_repository.dart new file mode 100644 index 0000000..02aba0c --- /dev/null +++ b/apps/im_app/lib/domain/repositories/favorite_repository.dart @@ -0,0 +1,63 @@ +import 'package:im_app/domain/entities/favorite.dart'; + +/// 收藏仓储接口 +/// +/// ## 职责 +/// - StorageSdkApi ↔ Domain Favorite 映射 +/// - CRUD 操作(通过 StorageSdkApi,不直接接触 DB) +/// - 所有公开接口只接受 Domain 实体,Companion 转换完全内聚在 Impl +/// +/// ## 数据流 +/// ``` +/// 写入:Domain Favorite → _toCompanion() → StorageSdkApi → DB +/// 读取:DB row (DriftFavorite) → _toEntity() → Domain Favorite +/// 监听:DB 变化 → stream → Domain Favorite → UI +/// ``` +abstract class FavoriteRepository { + // ── 监听 ───────────────────────────────────────────────────────────────── + + /// 监听所有收藏,DB 变化自动反映 + Stream> watchAll(); + + /// 监听指定收藏 + Stream watchById(int id); + + /// 监听指定 parentId 的收藏 + Stream> watchByParentId(String parentId); + + // ── 读取 ───────────────────────────────────────────────────────────────── + + /// 读取所有收藏 + Future> getAll(); + + /// 读取指定收藏,不存在返回 null + Future getById(int id); + + /// 读取指定 parentId 的所有收藏 + Future> getByParentId(String parentId); + + /// 读取未上传的收藏 + Future> getUnuploaded(); + + // ── 写入 ───────────────────────────────────────────────────────────────── + + /// 插入或替换收藏 + Future insertOrReplace(Favorite favorite); + + /// 批量插入或替换收藏 + Future insertOrReplaceAll(List favorites); + + /// 更新收藏 + Future update(Favorite favorite); + + // ── 删除 ───────────────────────────────────────────────────────────────── + + /// 删除指定收藏 + Future delete(int id); + + /// 删除指定 parentId 的所有收藏 + Future deleteByParentId(String parentId); + + /// 清空所有收藏 + Future clear(); +} diff --git a/apps/im_app/lib/domain/repositories/group_repository.dart b/apps/im_app/lib/domain/repositories/group_repository.dart new file mode 100644 index 0000000..0f5d286 --- /dev/null +++ b/apps/im_app/lib/domain/repositories/group_repository.dart @@ -0,0 +1,57 @@ +import 'package:im_app/domain/entities/group.dart'; + +/// 群组仓储接口 +/// +/// ## 职责 +/// - StorageSdkApi ↔ Domain Group 映射 +/// - CRUD 操作(通过 StorageSdkApi,不直接接触 DB) +/// - 所有公开接口只接受 Domain 实体,Companion 转换完全内聚在 Impl +/// +/// ## 数据流 +/// ``` +/// 写入:Domain Group → _toCompanion() → StorageSdkApi → DB +/// 读取:DB row (DriftGroup) → _toEntity() → Domain Group +/// 监听:DB 变化 → stream → Domain Group → UI +/// ``` +abstract class GroupRepository { + // ── 监听 ───────────────────────────────────────────────────────────────── + + /// 监听所有群组,DB 变化自动反映 + Stream> watchAll(); + + /// 监听指定群组 + Stream watchById(int id); + + // ── 读取 ───────────────────────────────────────────────────────────────── + + /// 读取所有群组 + Future> getAll(); + + /// 读取指定群组,不存在返回 null + Future getById(int id); + + /// 读取指定 workspaceId 的所有群组 + Future> getByWorkspace(int workspaceId); + + // ── 写入 ───────────────────────────────────────────────────────────────── + + /// 插入或替换群组 + Future insertOrReplace(Group group); + + /// 批量插入或替换群组 + Future insertOrReplaceAll(List groups); + + /// 更新群组 + Future update(Group group); + + /// 批量更新群组 + Future updateBatch(List groups); + + // ── 删除 ───────────────────────────────────────────────────────────────── + + /// 删除指定群组 + Future delete(int id); + + /// 清空所有群组 + Future clear(); +} diff --git a/apps/im_app/lib/domain/repositories/message_repository.dart b/apps/im_app/lib/domain/repositories/message_repository.dart new file mode 100644 index 0000000..3292a1a --- /dev/null +++ b/apps/im_app/lib/domain/repositories/message_repository.dart @@ -0,0 +1,67 @@ +import 'package:im_app/domain/entities/message.dart'; + +/// 消息仓储接口 +/// +/// ## 职责 +/// - StorageSdkApi ↔ Domain Message 映射 +/// - CRUD 操作(通过 StorageSdkApi,不直接接触 DB) +/// - 所有公开接口只接受 Domain 实体,Companion 转换完全内聚在 Impl +/// +/// ## 数据流 +/// ``` +/// 写入:Domain Message → _toCompanion() → StorageSdkApi → DB +/// 读取:DB row (DriftMessage) → _toEntity() → Domain Message +/// 监听:DB 变化 → stream → Domain Message → UI +/// ``` +abstract class MessageRepository { + // ── 监听 ───────────────────────────────────────────────────────────────── + + /// 监听指定 chatId 的所有消息,按 chatIdx 升序 + Stream> watchByChatId(int chatId); + + /// 监听指定消息 + Stream watchById(int id); + + // ── 读取 ───────────────────────────────────────────────────────────────── + + /// 读取指定 chatId 的所有消息,按 chatIdx 升序 + Future> getByChatId(int chatId); + + /// 分页读取指定 chatId 的消息 + Future> getByChatIdPage({ + required int chatId, + required int offset, + required int limit, + }); + + /// 读取指定消息,不存在返回 null + Future getById(int id); + + /// 读取指定 messageId,不存在返回 null + Future getByMessageId(int messageId); + + /// 统计指定 chatId 的消息数量 + Future countByChatId(int chatId); + + // ── 写入 ───────────────────────────────────────────────────────────────── + + /// 插入或替换消息 + Future insertOrReplace(Message message); + + /// 批量插入或替换消息 + Future insertOrReplaceAll(List messages); + + /// 更新消息 + Future update(Message message); + + // ── 删除 ───────────────────────────────────────────────────────────────── + + /// 删除指定消息 + Future delete(int id); + + /// 删除指定 chatId 的所有消息 + Future deleteByChatId(int chatId); + + /// 清空所有消息 + Future clear(); +} diff --git a/apps/im_app/lib/domain/repositories/mini_app_repository.dart b/apps/im_app/lib/domain/repositories/mini_app_repository.dart new file mode 100644 index 0000000..8f2c42b --- /dev/null +++ b/apps/im_app/lib/domain/repositories/mini_app_repository.dart @@ -0,0 +1,47 @@ +import 'package:im_app/domain/entities/mini_app.dart'; + +/// 小程序仓储接口(discover / explore / favorite / recent 共用) +/// +/// ## 职责 +/// - StorageSdkApi ↔ Domain MiniApp 映射 +/// - CRUD 操作(通过 StorageSdkApi,不直接接触 DB) +/// - 所有公开接口只接受 Domain 实体,Companion 转换完全内聚在 Impl +abstract class MiniAppRepository { + // ── 监听 ───────────────────────────────────────────────────────────────── + + /// 监听所有小程序,DB 变化自动反映 + Stream> watchAll(); + + /// 监听指定小程序 + Stream watch(String id); + + // ── 读取 ───────────────────────────────────────────────────────────────── + + /// 读取所有小程序 + Future> getAll(); + + /// 读取指定小程序,不存在返回 null + Future get(String id); + + /// 检查是否存在 + Future isExist(String id); + + // ── 写入 ───────────────────────────────────────────────────────────────── + + /// 插入或替换小程序 + Future insertOrReplace(MiniApp miniApp); + + /// 批量插入或替换小程序 + Future insertOrReplaceAll(List miniApps); + + /// 更新小程序 + Future update(MiniApp miniApp); + + // ── 删除 ───────────────────────────────────────────────────────────────── + + /// 删除指定小程序 + Future delete(String id); + + /// 清空所有小程序 + Future clear(); +} diff --git a/apps/im_app/lib/domain/repositories/pending_friend_request_history_repository.dart b/apps/im_app/lib/domain/repositories/pending_friend_request_history_repository.dart new file mode 100644 index 0000000..9a44917 --- /dev/null +++ b/apps/im_app/lib/domain/repositories/pending_friend_request_history_repository.dart @@ -0,0 +1,36 @@ +import 'package:im_app/domain/entities/pending_friend_request_history.dart'; + +/// 待处理好友请求历史仓储接口 +abstract class PendingFriendRequestHistoryRepository { + // ── 监听 ───────────────────────────────────────────────────────────────── + + Stream> watchAll(); + + Stream watchById(int id); + + Stream> watchByUid(int uid); + + // ── 读取 ───────────────────────────────────────────────────────────────── + + Future> getAll(); + + Future getById(int id); + + Future> getByUid(int uid); + + // ── 写入 ───────────────────────────────────────────────────────────────── + + Future insertOrReplace(PendingFriendRequestHistory history); + + Future insertOrReplaceAll(List histories); + + Future update(PendingFriendRequestHistory history); + + // ── 删除 ───────────────────────────────────────────────────────────────── + + Future delete(int id); + + Future deleteByUid(int uid); + + Future clear(); +} diff --git a/apps/im_app/lib/domain/repositories/sound_repository.dart b/apps/im_app/lib/domain/repositories/sound_repository.dart new file mode 100644 index 0000000..571422e --- /dev/null +++ b/apps/im_app/lib/domain/repositories/sound_repository.dart @@ -0,0 +1,38 @@ +import 'package:im_app/domain/entities/sound.dart'; + +/// 音效仓储接口 +abstract class SoundRepository { + // ── 监听 ───────────────────────────────────────────────────────────────── + + Stream> watchAll(); + + Stream watchById(int id); + + Stream> watchByType(int typ); + + // ── 读取 ───────────────────────────────────────────────────────────────── + + Future> getAll(); + + Future getById(int id); + + Future> getByType(int typ); + + Future> getByChannelGroup(int channelGroupId); + + Future> getDefaults(); + + // ── 写入 ───────────────────────────────────────────────────────────────── + + Future insertOrReplace(Sound sound); + + Future insertOrReplaceAll(List sounds); + + Future update(Sound sound); + + // ── 删除 ───────────────────────────────────────────────────────────────── + + Future delete(int id); + + Future clear(); +} diff --git a/apps/im_app/lib/domain/repositories/tag_repository.dart b/apps/im_app/lib/domain/repositories/tag_repository.dart new file mode 100644 index 0000000..87ca93a --- /dev/null +++ b/apps/im_app/lib/domain/repositories/tag_repository.dart @@ -0,0 +1,43 @@ +import 'package:im_app/domain/entities/tag.dart'; + +/// 标签仓储接口 +abstract class TagRepository { + // ── 监听 ───────────────────────────────────────────────────────────────── + + Stream> watchAll(); + + Stream watchById(int id); + + Stream> watchByUid(int uid); + + Stream> watchByType(int type); + + // ── 读取 ───────────────────────────────────────────────────────────────── + + Future> getAll(); + + Future getById(int id); + + Future> getByUid(int uid); + + Future> getByType(int type); + + // ── 写入 ───────────────────────────────────────────────────────────────── + + /// 插入标签(autoIncrement id,无需提供) + Future insert(Tag tag); + + Future insertOrReplace(Tag tag); + + Future insertOrReplaceAll(List tags); + + Future update(Tag tag); + + // ── 删除 ───────────────────────────────────────────────────────────────── + + Future delete(int id); + + Future deleteByUid(int uid); + + Future clear(); +} diff --git a/apps/im_app/lib/domain/repositories/user_request_history_repository.dart b/apps/im_app/lib/domain/repositories/user_request_history_repository.dart new file mode 100644 index 0000000..97ce73d --- /dev/null +++ b/apps/im_app/lib/domain/repositories/user_request_history_repository.dart @@ -0,0 +1,34 @@ +import 'package:im_app/domain/entities/user_request_history.dart'; + +/// 用户请求历史仓储接口 +abstract class UserRequestHistoryRepository { + // ── 监听 ───────────────────────────────────────────────────────────────── + + Stream> watchAll(); + + Stream watchById(int id); + + Stream> watchByStatus(int status); + + // ── 读取 ───────────────────────────────────────────────────────────────── + + Future> getAll(); + + Future getById(int id); + + Future> getByStatus(int status); + + // ── 写入 ───────────────────────────────────────────────────────────────── + + Future insertOrReplace(UserRequestHistory history); + + Future insertOrReplaceAll(List histories); + + Future update(UserRequestHistory history); + + // ── 删除 ───────────────────────────────────────────────────────────────── + + Future delete(int id); + + Future clear(); +} diff --git a/apps/im_app/lib/domain/repositories/workspace_repository.dart b/apps/im_app/lib/domain/repositories/workspace_repository.dart new file mode 100644 index 0000000..4d469e7 --- /dev/null +++ b/apps/im_app/lib/domain/repositories/workspace_repository.dart @@ -0,0 +1,32 @@ +import 'package:im_app/domain/entities/workspace.dart'; + +/// 工作空间仓储接口 +abstract class WorkspaceRepository { + // ── 监听 ───────────────────────────────────────────────────────────────── + + Stream> watchAll(); + + Stream watchById(int id); + + // ── 读取 ───────────────────────────────────────────────────────────────── + + Future> getAll(); + + Future getById(int id); + + Future> getByOwner(int ownerId); + + // ── 写入 ───────────────────────────────────────────────────────────────── + + Future insertOrReplace(Workspace workspace); + + Future insertOrReplaceAll(List workspaces); + + Future update(Workspace workspace); + + // ── 删除 ───────────────────────────────────────────────────────────────── + + Future delete(int id); + + Future clear(); +} diff --git a/apps/im_app/lib/features/app_tab/di/.gitkeep b/apps/im_app/lib/features/app_tab/di/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/apps/im_app/lib/features/app_tab/di/favorite_detail_provider.dart b/apps/im_app/lib/features/app_tab/di/favorite_detail_provider.dart new file mode 100644 index 0000000..81c0f63 --- /dev/null +++ b/apps/im_app/lib/features/app_tab/di/favorite_detail_provider.dart @@ -0,0 +1,36 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:im_app/app/di/db_provider.dart'; +import 'package:im_app/data/repositories/favorite_detail_repository_impl.dart'; +import 'package:im_app/domain/repositories/favorite_detail_repository.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; +import 'package:im_app/domain/entities/favorite_detail.dart'; + +part 'favorite_detail_provider.g.dart'; + +// ── Repository ──────────────────────────────────────────────────────────────── + +/// 收藏详情仓储 Provider +final favoriteDetailRepositoryProvider = Provider(( + ref, +) { + return FavoriteDetailRepositoryImpl(ref.watch(storageSdkProvider)); +}); + +// ── Streams ─────────────────────────────────────────────────────────────────── + +/// 监听所有收藏详情 +@riverpod +Stream> allFavoriteDetails(Ref ref) { + return ref.watch(favoriteDetailRepositoryProvider).watchAll(); +} + +/// 监听指定 relatedId 的收藏详情 +@riverpod +Stream> favoriteDetailsByRelatedId( + Ref ref, + String relatedId, +) { + return ref + .watch(favoriteDetailRepositoryProvider) + .watchByRelatedId(relatedId); +} diff --git a/apps/im_app/lib/features/app_tab/di/favorite_provider.dart b/apps/im_app/lib/features/app_tab/di/favorite_provider.dart new file mode 100644 index 0000000..d949272 --- /dev/null +++ b/apps/im_app/lib/features/app_tab/di/favorite_provider.dart @@ -0,0 +1,35 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:im_app/app/di/db_provider.dart'; +import 'package:im_app/data/repositories/favorite_repository_impl.dart'; +import 'package:im_app/domain/entities/favorite.dart'; +import 'package:im_app/domain/repositories/favorite_repository.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'favorite_provider.g.dart'; + +// ── Repository ──────────────────────────────────────────────────────────────── + +/// 收藏仓储 Provider +final favoriteRepositoryProvider = Provider((ref) { + return FavoriteRepositoryImpl(ref.watch(storageSdkProvider)); +}); + +// ── Streams ─────────────────────────────────────────────────────────────────── + +/// 监听所有收藏 +@riverpod +Stream> allFavorites(Ref ref) { + return ref.watch(favoriteRepositoryProvider).watchAll(); +} + +/// 监听指定收藏 +@riverpod +Stream favoriteById(Ref ref, int id) { + return ref.watch(favoriteRepositoryProvider).watchById(id); +} + +/// 监听指定 parentId 的收藏 +@riverpod +Stream> favoritesByParentId(Ref ref, String parentId) { + return ref.watch(favoriteRepositoryProvider).watchByParentId(parentId); +} diff --git a/apps/im_app/lib/features/chat/di/.gitkeep b/apps/im_app/lib/features/chat/di/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/apps/im_app/lib/features/chat/di/chat_category_provider.dart b/apps/im_app/lib/features/chat/di/chat_category_provider.dart new file mode 100644 index 0000000..3903c47 --- /dev/null +++ b/apps/im_app/lib/features/chat/di/chat_category_provider.dart @@ -0,0 +1,29 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:im_app/app/di/db_provider.dart'; +import 'package:im_app/data/repositories/chat_category_repository_impl.dart'; +import 'package:im_app/domain/entities/chat_category.dart'; +import 'package:im_app/domain/repositories/chat_category_repository.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'chat_category_provider.g.dart'; + +// ── Repository ──────────────────────────────────────────────────────────────── + +/// 聊天分类仓储 Provider +final chatCategoryRepositoryProvider = Provider((ref) { + return ChatCategoryRepositoryImpl(ref.watch(storageSdkProvider)); +}); + +// ── Streams ─────────────────────────────────────────────────────────────────── + +/// 监听所有聊天分类 +@riverpod +Stream> allChatCategories(Ref ref) { + return ref.watch(chatCategoryRepositoryProvider).watchAllChatCategories(); +} + +/// 监听指定聊天分类 +@riverpod +Stream chatCategory(Ref ref, int id) { + return ref.watch(chatCategoryRepositoryProvider).watchChatCategory(id); +} diff --git a/apps/im_app/lib/features/chat/di/chat_provider.dart b/apps/im_app/lib/features/chat/di/chat_provider.dart new file mode 100644 index 0000000..10288ba --- /dev/null +++ b/apps/im_app/lib/features/chat/di/chat_provider.dart @@ -0,0 +1,29 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:im_app/app/di/db_provider.dart'; +import 'package:im_app/data/repositories/chat_repository_impl.dart'; +import 'package:im_app/domain/entities/chat.dart'; +import 'package:im_app/domain/repositories/chat_repository.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'chat_provider.g.dart'; + +// ── Repository ──────────────────────────────────────────────────────────────── + +/// 聊天仓储 Provider +final chatRepositoryProvider = Provider((ref) { + return ChatRepositoryImpl(ref.watch(storageSdkProvider)); +}); + +// ── Streams ─────────────────────────────────────────────────────────────────── + +/// 监听所有聊天 +@riverpod +Stream> allChats(Ref ref) { + return ref.watch(chatRepositoryProvider).watchAllChats(); +} + +/// 监听指定聊天 +@riverpod +Stream chat(Ref ref, int id) { + return ref.watch(chatRepositoryProvider).watchChat(id); +} diff --git a/apps/im_app/lib/features/chat/di/group_provider.dart b/apps/im_app/lib/features/chat/di/group_provider.dart new file mode 100644 index 0000000..f9b39a0 --- /dev/null +++ b/apps/im_app/lib/features/chat/di/group_provider.dart @@ -0,0 +1,29 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:im_app/app/di/db_provider.dart'; +import 'package:im_app/data/repositories/group_repository_impl.dart'; +import 'package:im_app/domain/entities/group.dart'; +import 'package:im_app/domain/repositories/group_repository.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'group_provider.g.dart'; + +// ── Repository ──────────────────────────────────────────────────────────────── + +/// 群组仓储 Provider +final groupRepositoryProvider = Provider((ref) { + return GroupRepositoryImpl(ref.watch(storageSdkProvider)); +}); + +// ── Streams ─────────────────────────────────────────────────────────────────── + +/// 监听所有群组 +@riverpod +Stream> allGroups(Ref ref) { + return ref.watch(groupRepositoryProvider).watchAll(); +} + +/// 监听指定群组 +@riverpod +Stream groupById(Ref ref, int id) { + return ref.watch(groupRepositoryProvider).watchById(id); +} diff --git a/apps/im_app/lib/features/chat/di/message_provider.dart b/apps/im_app/lib/features/chat/di/message_provider.dart new file mode 100644 index 0000000..3faa9bd --- /dev/null +++ b/apps/im_app/lib/features/chat/di/message_provider.dart @@ -0,0 +1,29 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:im_app/app/di/db_provider.dart'; +import 'package:im_app/data/repositories/message_repository_impl.dart'; +import 'package:im_app/domain/entities/message.dart'; +import 'package:im_app/domain/repositories/message_repository.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'message_provider.g.dart'; + +// ── Repository ──────────────────────────────────────────────────────────────── + +/// 消息仓储 Provider +final messageRepositoryProvider = Provider((ref) { + return MessageRepositoryImpl(ref.watch(storageSdkProvider)); +}); + +// ── Streams ─────────────────────────────────────────────────────────────────── + +/// 监听指定 chatId 的消息列表 +@riverpod +Stream> messagesByChatId(Ref ref, int chatId) { + return ref.watch(messageRepositoryProvider).watchByChatId(chatId); +} + +/// 监听指定消息 +@riverpod +Stream messageById(Ref ref, int id) { + return ref.watch(messageRepositoryProvider).watchById(id); +} diff --git a/apps/im_app/lib/features/contact/di/.gitkeep b/apps/im_app/lib/features/contact/di/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/apps/im_app/lib/features/contact/di/pending_friend_request_history_provider.dart b/apps/im_app/lib/features/contact/di/pending_friend_request_history_provider.dart new file mode 100644 index 0000000..9648e59 --- /dev/null +++ b/apps/im_app/lib/features/contact/di/pending_friend_request_history_provider.dart @@ -0,0 +1,38 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:im_app/app/di/db_provider.dart'; +import 'package:im_app/data/repositories/pending_friend_request_history_repository_impl.dart'; +import 'package:im_app/domain/entities/pending_friend_request_history.dart'; +import 'package:im_app/domain/repositories/pending_friend_request_history_repository.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'pending_friend_request_history_provider.g.dart'; + +// ── Repository ──────────────────────────────────────────────────────────────── + +final pendingFriendRequestHistoryRepositoryProvider = + Provider((ref) { + return PendingFriendRequestHistoryRepositoryImpl( + ref.watch(storageSdkProvider), + ); + }); + +// ── Streams ─────────────────────────────────────────────────────────────────── + +/// 监听所有好友请求历史 +@riverpod +Stream> allPendingFriendRequestHistories( + Ref ref, +) { + return ref.watch(pendingFriendRequestHistoryRepositoryProvider).watchAll(); +} + +/// 监听指定 uid 的好友请求历史 +@riverpod +Stream> pendingFriendRequestHistoriesByUid( + Ref ref, + int uid, +) { + return ref + .watch(pendingFriendRequestHistoryRepositoryProvider) + .watchByUid(uid); +} diff --git a/apps/im_app/lib/features/contact/di/user_request_history_provider.dart b/apps/im_app/lib/features/contact/di/user_request_history_provider.dart new file mode 100644 index 0000000..7acc693 --- /dev/null +++ b/apps/im_app/lib/features/contact/di/user_request_history_provider.dart @@ -0,0 +1,38 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:im_app/app/di/db_provider.dart'; +import 'package:im_app/data/repositories/user_request_history_repository_impl.dart'; +import 'package:im_app/domain/entities/user_request_history.dart'; +import 'package:im_app/domain/repositories/user_request_history_repository.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'user_request_history_provider.g.dart'; + +// ── Repository ──────────────────────────────────────────────────────────────── + +final userRequestHistoryRepositoryProvider = + Provider((ref) { + return UserRequestHistoryRepositoryImpl(ref.watch(storageSdkProvider)); + }); + +// ── Streams ─────────────────────────────────────────────────────────────────── + +/// 监听所有用户请求历史 +@riverpod +Stream> allUserRequestHistories(Ref ref) { + return ref.watch(userRequestHistoryRepositoryProvider).watchAll(); +} + +/// 监听指定状态的用户请求历史 +@riverpod +Stream> userRequestHistoriesByStatus( + Ref ref, + int status, +) { + return ref.watch(userRequestHistoryRepositoryProvider).watchByStatus(status); +} + +/// 监听指定用户请求历史 +@riverpod +Stream userRequestHistoryById(Ref ref, int id) { + return ref.watch(userRequestHistoryRepositoryProvider).watchById(id); +} diff --git a/apps/im_app/lib/features/mini_app/mini_app_provider.dart b/apps/im_app/lib/features/mini_app/mini_app_provider.dart new file mode 100644 index 0000000..b736468 --- /dev/null +++ b/apps/im_app/lib/features/mini_app/mini_app_provider.dart @@ -0,0 +1,25 @@ +import 'package:im_app/app/di/db_provider.dart'; +import 'package:im_app/data/repositories/discover_mini_app_repository_impl.dart'; +import 'package:im_app/data/repositories/explore_mini_app_repository_impl.dart'; +import 'package:im_app/data/repositories/favorite_mini_app_repository_impl.dart'; +import 'package:im_app/data/repositories/recent_mini_app_repository_impl.dart'; +import 'package:im_app/domain/repositories/mini_app_repository.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'mini_app_provider.g.dart'; + +@riverpod +MiniAppRepository discoverMiniAppRepository(Ref ref) => + DiscoverMiniAppRepositoryImpl(ref.watch(storageSdkProvider)); + +@riverpod +MiniAppRepository exploreMiniAppRepository(Ref ref) => + ExploreMiniAppRepositoryImpl(ref.watch(storageSdkProvider)); + +@riverpod +MiniAppRepository favoriteMiniAppRepository(Ref ref) => + FavoriteMiniAppRepositoryImpl(ref.watch(storageSdkProvider)); + +@riverpod +MiniAppRepository recentMiniAppRepository(Ref ref) => + RecentMiniAppRepositoryImpl(ref.watch(storageSdkProvider)); diff --git a/apps/im_app/lib/features/workspace/di/workspace_provider.dart b/apps/im_app/lib/features/workspace/di/workspace_provider.dart new file mode 100644 index 0000000..8254354 --- /dev/null +++ b/apps/im_app/lib/features/workspace/di/workspace_provider.dart @@ -0,0 +1,28 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:im_app/app/di/db_provider.dart'; +import 'package:im_app/data/repositories/workspace_repository_impl.dart'; +import 'package:im_app/domain/entities/workspace.dart'; +import 'package:im_app/domain/repositories/workspace_repository.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'workspace_provider.g.dart'; + +// ── Repository ──────────────────────────────────────────────────────────────── + +final workspaceRepositoryProvider = Provider((ref) { + return WorkspaceRepositoryImpl(ref.watch(storageSdkProvider)); +}); + +// ── Streams ─────────────────────────────────────────────────────────────────── + +/// 监听所有工作空间 +@riverpod +Stream> allWorkspaces(Ref ref) { + return ref.watch(workspaceRepositoryProvider).watchAll(); +} + +/// 监听指定工作空间 +@riverpod +Stream workspaceById(Ref ref, int id) { + return ref.watch(workspaceRepositoryProvider).watchById(id); +} diff --git a/packages/storage_sdk/lib/src/data/repositories/database_repository_impl.dart b/packages/storage_sdk/lib/src/data/repositories/database_repository_impl.dart index 41cbfde..7c71440 100644 --- a/packages/storage_sdk/lib/src/data/repositories/database_repository_impl.dart +++ b/packages/storage_sdk/lib/src/data/repositories/database_repository_impl.dart @@ -49,6 +49,30 @@ class DatabaseRepositoryImpl implements DatabaseRepository { ); } + @override + Future insertOnConflictUpdate( + TableInfo table, + Insertable companion, + ) async { + final db = _db; + if (db == null) return; + await db.into(table).insertOnConflictUpdate(companion); + } + + @override + Future batchInsertOnConflictUpdate( + TableInfo table, + List> companions, + ) async { + final db = _db; + if (db == null) return; + await db.transaction(() async { + for (final companion in companions) { + await db.into(table).insertOnConflictUpdate(companion); + } + }); + } + // ── 更新 ───────────────────────────────────────────────────────────────── @override diff --git a/packages/storage_sdk/lib/src/domain/repositories/database_repository.dart b/packages/storage_sdk/lib/src/domain/repositories/database_repository.dart index 4e8ec1e..228b818 100644 --- a/packages/storage_sdk/lib/src/domain/repositories/database_repository.dart +++ b/packages/storage_sdk/lib/src/domain/repositories/database_repository.dart @@ -13,7 +13,10 @@ import 'package:drift/drift.dart'; abstract class DatabaseRepository { // ── 插入 ───────────────────────────────────────────────────────────────── - /// 插入或替换(主键冲突时覆盖)。 + /// 插入或替换(主键冲突时删除原行再插入)。 + /// + /// 注意:底层是 DELETE + INSERT,rowid 变更,触发 DELETE 级联。 + /// 如需原地更新,请使用 [insertOnConflictUpdate]。 Future insertOrReplace( TableInfo table, Insertable companion, @@ -25,12 +28,35 @@ abstract class DatabaseRepository { Insertable companion, ); - /// 批量插入或替换。 + /// 批量插入或替换(主键冲突时删除原行再插入)。 + /// + /// 注意:底层是 DELETE + INSERT,rowid 变更,触发 DELETE 级联。 + /// 如需原地更新,请使用 [batchInsertOnConflictUpdate]。 Future batchInsertOrReplace( TableInfo table, List> companions, ); + /// 插入,主键冲突时原地更新全部字段(INSERT ... ON CONFLICT DO UPDATE SET)。 + /// + /// 与 [insertOrReplace] 的区别: + /// - [insertOrReplace] → DELETE + INSERT,rowid 变更,触发 DELETE 级联 + /// - [insertOnConflictUpdate] → 原地 UPDATE,rowid 不变,不触发 DELETE 级联 + /// + /// 适用场景:upsert 语义,且不希望影响依赖 rowid 的其他逻辑。 + Future insertOnConflictUpdate( + TableInfo table, + Insertable companion, + ); + + /// 批量插入,主键冲突时原地更新全部字段。 + /// + /// 与 [batchInsertOrReplace] 的区别同 [insertOnConflictUpdate]。 + Future batchInsertOnConflictUpdate( + TableInfo table, + List> companions, + ); + // ── 更新 ───────────────────────────────────────────────────────────────── /// 按条件更新。 diff --git a/packages/storage_sdk/lib/src/presentation/facade/storage_sdk_api.dart b/packages/storage_sdk/lib/src/presentation/facade/storage_sdk_api.dart index d6e6861..17b3873 100644 --- a/packages/storage_sdk/lib/src/presentation/facade/storage_sdk_api.dart +++ b/packages/storage_sdk/lib/src/presentation/facade/storage_sdk_api.dart @@ -79,7 +79,10 @@ abstract class StorageSdkApi { // ── 插入 ───────────────────────────────────────────────────────────────── - /// 插入或替换(主键冲突时覆盖)。 + /// 插入或替换(主键冲突时删除原行再插入)。 + /// + /// 注意:底层是 DELETE + INSERT,会导致 rowid 变更,并触发 DELETE 级联。 + /// 如需原地更新,请使用 [insertOnConflictUpdate]。 /// /// 示例: /// ```dart @@ -92,9 +95,26 @@ abstract class StorageSdkApi { /// 插入或忽略(主键冲突时跳过)。 Future insert(Insertable companion); - /// 批量插入或替换。 + /// 批量插入或替换(主键冲突时删除原行再插入)。 + /// + /// 注意:底层是 DELETE + INSERT,rowid 变更,触发 DELETE 级联。 + /// 如需原地更新,请使用 [batchInsertOnConflictUpdate]。 Future batchInsertOrReplace(List> companions); + /// 插入,主键冲突时原地更新全部字段(INSERT ... ON CONFLICT DO UPDATE SET)。 + /// + /// 与 [insertOrReplace] 的区别: + /// - [insertOrReplace] → DELETE + INSERT,rowid 变更,触发 DELETE 级联 + /// - [insertOnConflictUpdate] → 原地 UPDATE,rowid 不变,不触发 DELETE 级联 + /// + /// 适用场景:upsert 语义,且不希望影响依赖 rowid 的其他逻辑。 + Future insertOnConflictUpdate(Insertable companion); + + /// 批量插入,主键冲突时原地更新全部字段。 + /// + /// 与 [batchInsertOrReplace] 的区别同 [insertOnConflictUpdate]。 + Future batchInsertOnConflictUpdate(List> companions); + // ── 更新 ───────────────────────────────────────────────────────────────── /// 按条件更新。 diff --git a/packages/storage_sdk/lib/src/presentation/wiring/storage_sdk_api_impl.dart b/packages/storage_sdk/lib/src/presentation/wiring/storage_sdk_api_impl.dart index a5e8cba..ab5b118 100644 --- a/packages/storage_sdk/lib/src/presentation/wiring/storage_sdk_api_impl.dart +++ b/packages/storage_sdk/lib/src/presentation/wiring/storage_sdk_api_impl.dart @@ -67,6 +67,14 @@ class StorageSdkApiImpl implements StorageSdkApi, StorageSdkLifecycle { Future batchInsertOrReplace(List> companions) => _core.repo.batchInsertOrReplace(_tableFor(), companions); + @override + Future insertOnConflictUpdate(Insertable companion) => + _core.repo.insertOnConflictUpdate(_tableFor(), companion); + + @override + Future batchInsertOnConflictUpdate(List> companions) => + _core.repo.batchInsertOnConflictUpdate(_tableFor(), companions); + // ── 更新 ───────────────────────────────────────────────────────────────── @override