♻️ Move the data part out of the chat list UI

This commit is contained in:
2025-12-04 22:20:03 +08:00
parent 31b83b2d27
commit 84bca9601a
14 changed files with 444 additions and 443 deletions

View File

@@ -1,5 +1,4 @@
import 'dart:async';
import 'package:dio/dio.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
@@ -7,10 +6,6 @@ import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:gap/gap.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/chat.dart';
import 'package:island/models/file.dart';
import 'package:island/models/account.dart';
import 'package:island/database/drift_db.dart';
import 'package:island/pods/database.dart';
import 'package:island/pods/chat/chat_summary.dart';
import 'package:island/pods/network.dart';
import 'package:island/pods/userinfo.dart';
@@ -25,11 +20,9 @@ import 'package:island/widgets/navigation/fab_menu.dart';
import 'package:island/widgets/response.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:relative_time/relative_time.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:styled_widget/styled_widget.dart';
import 'package:super_sliver_list/super_sliver_list.dart';
part 'chat.g.dart';
import 'package:island/pods/chat/chat_room.dart';
class ChatRoomListTile extends HookConsumerWidget {
final SnChatRoom room;
@@ -184,151 +177,6 @@ class ChatRoomListTile extends HookConsumerWidget {
}
}
@riverpod
class ChatRoomJoinedNotifier extends _$ChatRoomJoinedNotifier {
@override
Future<List<SnChatRoom>> build() async {
final db = ref.watch(databaseProvider);
try {
final localRoomsData = await db.select(db.chatRooms).get();
if (localRoomsData.isNotEmpty) {
final localRooms = await Future.wait(
localRoomsData.map((row) async {
final membersRows =
await (db.select(db.chatMembers)
..where((m) => m.chatRoomId.equals(row.id))).get();
final members =
membersRows.map((mRow) {
final account = SnAccount.fromJson(mRow.account);
return SnChatMember(
id: mRow.id,
chatRoomId: mRow.chatRoomId,
accountId: mRow.accountId,
account: account,
nick: mRow.nick,
notify: mRow.notify,
joinedAt: mRow.joinedAt,
breakUntil: mRow.breakUntil,
timeoutUntil: mRow.timeoutUntil,
status: null,
createdAt: mRow.createdAt,
updatedAt: mRow.updatedAt,
deletedAt: mRow.deletedAt,
chatRoom: null,
);
}).toList();
return SnChatRoom(
id: row.id,
name: row.name,
description: row.description,
type: row.type,
isPublic: row.isPublic!,
isCommunity: row.isCommunity!,
picture:
row.picture != null
? SnCloudFile.fromJson(row.picture!)
: null,
background:
row.background != null
? SnCloudFile.fromJson(row.background!)
: null,
realmId: row.realmId,
accountId: row.accountId,
realm: null,
createdAt: row.createdAt,
updatedAt: row.updatedAt,
deletedAt: row.deletedAt,
members: members,
);
}),
);
// Background sync
Future(() async {
try {
final client = ref.read(apiClientProvider);
final resp = await client.get('/sphere/chat');
final remoteRooms =
resp.data
.map((e) => SnChatRoom.fromJson(e))
.cast<SnChatRoom>()
.toList();
await db.saveChatRooms(remoteRooms, override: true);
// Update state with fresh data
state = AsyncData(await _buildRoomsFromDb(db));
} catch (_) {}
}).ignore();
return localRooms;
}
} catch (_) {}
// Fallback to API
final client = ref.watch(apiClientProvider);
final resp = await client.get('/sphere/chat');
final rooms =
resp.data
.map((e) => SnChatRoom.fromJson(e))
.cast<SnChatRoom>()
.toList();
await db.saveChatRooms(rooms, override: true);
return rooms;
}
Future<List<SnChatRoom>> _buildRoomsFromDb(AppDatabase db) async {
final localRoomsData = await db.select(db.chatRooms).get();
return Future.wait(
localRoomsData.map((row) async {
final membersRows =
await (db.select(db.chatMembers)
..where((m) => m.chatRoomId.equals(row.id))).get();
final members =
membersRows.map((mRow) {
final account = SnAccount.fromJson(mRow.account);
return SnChatMember(
id: mRow.id,
chatRoomId: mRow.chatRoomId,
accountId: mRow.accountId,
account: account,
nick: mRow.nick,
notify: mRow.notify,
joinedAt: mRow.joinedAt,
breakUntil: mRow.breakUntil,
timeoutUntil: mRow.timeoutUntil,
status: null,
createdAt: mRow.createdAt,
updatedAt: mRow.updatedAt,
deletedAt: mRow.deletedAt,
chatRoom: null,
);
}).toList();
return SnChatRoom(
id: row.id,
name: row.name,
description: row.description,
type: row.type,
isPublic: row.isPublic!,
isCommunity: row.isCommunity!,
picture:
row.picture != null ? SnCloudFile.fromJson(row.picture!) : null,
background:
row.background != null
? SnCloudFile.fromJson(row.background!)
: null,
realmId: row.realmId,
accountId: row.accountId,
realm: null,
createdAt: row.createdAt,
updatedAt: row.updatedAt,
deletedAt: row.deletedAt,
members: members,
);
}),
);
}
}
class ChatListBodyWidget extends HookConsumerWidget {
final bool isFloating;
final TabController tabController;
@@ -661,277 +509,6 @@ class ChatListScreen extends HookConsumerWidget {
}
}
@riverpod
class ChatRoomNotifier extends _$ChatRoomNotifier {
@override
Future<SnChatRoom?> build(String? identifier) async {
if (identifier == null) return null;
final db = ref.watch(databaseProvider);
try {
// Try to get from local database first
final localRoomData =
await (db.select(db.chatRooms)
..where((r) => r.id.equals(identifier))).getSingleOrNull();
if (localRoomData != null) {
// Fetch members for this room
final membersRows =
await (db.select(db.chatMembers)
..where((m) => m.chatRoomId.equals(localRoomData.id))).get();
final members =
membersRows.map((mRow) {
final account = SnAccount.fromJson(mRow.account);
return SnChatMember(
id: mRow.id,
chatRoomId: mRow.chatRoomId,
accountId: mRow.accountId,
account: account,
nick: mRow.nick,
notify: mRow.notify,
joinedAt: mRow.joinedAt,
breakUntil: mRow.breakUntil,
timeoutUntil: mRow.timeoutUntil,
status: null,
createdAt: mRow.createdAt,
updatedAt: mRow.updatedAt,
deletedAt: mRow.deletedAt,
chatRoom: null,
);
}).toList();
final localRoom = SnChatRoom(
id: localRoomData.id,
name: localRoomData.name,
description: localRoomData.description,
type: localRoomData.type,
isPublic: localRoomData.isPublic!,
isCommunity: localRoomData.isCommunity!,
picture:
localRoomData.picture != null
? SnCloudFile.fromJson(localRoomData.picture!)
: null,
background:
localRoomData.background != null
? SnCloudFile.fromJson(localRoomData.background!)
: null,
realmId: localRoomData.realmId,
accountId: localRoomData.accountId,
realm: null,
createdAt: localRoomData.createdAt,
updatedAt: localRoomData.updatedAt,
deletedAt: localRoomData.deletedAt,
members: members,
);
// Background sync
Future(() async {
try {
final client = ref.read(apiClientProvider);
final resp = await client.get('/sphere/chat/$identifier');
final remoteRoom = SnChatRoom.fromJson(resp.data);
await db.saveChatRooms([remoteRoom]);
// Update state with fresh data
state = AsyncData(await _buildRoomFromDb(db, identifier));
} catch (_) {}
}).ignore();
return localRoom;
}
} catch (_) {}
// Fallback to API
try {
final client = ref.watch(apiClientProvider);
final resp = await client.get('/sphere/chat/$identifier');
final room = SnChatRoom.fromJson(resp.data);
await db.saveChatRooms([room]);
return room;
} catch (err) {
if (err is DioException && err.response?.statusCode == 404) {
return null; // Chat room not found
}
rethrow; // Rethrow other errors
}
}
Future<SnChatRoom?> _buildRoomFromDb(
AppDatabase db,
String identifier,
) async {
final localRoomData =
await (db.select(db.chatRooms)
..where((r) => r.id.equals(identifier))).getSingleOrNull();
if (localRoomData == null) return null;
final membersRows =
await (db.select(db.chatMembers)
..where((m) => m.chatRoomId.equals(localRoomData.id))).get();
final members =
membersRows.map((mRow) {
final account = SnAccount.fromJson(mRow.account);
return SnChatMember(
id: mRow.id,
chatRoomId: mRow.chatRoomId,
accountId: mRow.accountId,
account: account,
nick: mRow.nick,
notify: mRow.notify,
joinedAt: mRow.joinedAt,
breakUntil: mRow.breakUntil,
timeoutUntil: mRow.timeoutUntil,
status: null,
createdAt: mRow.createdAt,
updatedAt: mRow.updatedAt,
deletedAt: mRow.deletedAt,
chatRoom: null,
);
}).toList();
return SnChatRoom(
id: localRoomData.id,
name: localRoomData.name,
description: localRoomData.description,
type: localRoomData.type,
isPublic: localRoomData.isPublic!,
isCommunity: localRoomData.isCommunity!,
picture:
localRoomData.picture != null
? SnCloudFile.fromJson(localRoomData.picture!)
: null,
background:
localRoomData.background != null
? SnCloudFile.fromJson(localRoomData.background!)
: null,
realmId: localRoomData.realmId,
accountId: localRoomData.accountId,
realm: null,
createdAt: localRoomData.createdAt,
updatedAt: localRoomData.updatedAt,
deletedAt: localRoomData.deletedAt,
members: members,
);
}
}
@riverpod
class ChatRoomIdentityNotifier extends _$ChatRoomIdentityNotifier {
@override
Future<SnChatMember?> build(String? identifier) async {
if (identifier == null) return null;
final db = ref.watch(databaseProvider);
final userInfo = ref.watch(userInfoProvider);
try {
// Try to get from local database first
if (userInfo.value != null) {
final localMemberData =
await (db.select(db.chatMembers)
..where((m) => m.chatRoomId.equals(identifier))
..where((m) => m.accountId.equals(userInfo.value!.id)))
.getSingleOrNull();
if (localMemberData != null) {
final account = SnAccount.fromJson(localMemberData.account);
final localMember = SnChatMember(
id: localMemberData.id,
chatRoomId: localMemberData.chatRoomId,
accountId: localMemberData.accountId,
account: account,
nick: localMemberData.nick,
notify: localMemberData.notify,
joinedAt: localMemberData.joinedAt,
breakUntil: localMemberData.breakUntil,
timeoutUntil: localMemberData.timeoutUntil,
status: null,
createdAt: localMemberData.createdAt,
updatedAt: localMemberData.updatedAt,
deletedAt: localMemberData.deletedAt,
chatRoom: null,
);
// Background sync
Future(() async {
try {
final client = ref.read(apiClientProvider);
final resp = await client.get(
'/sphere/chat/$identifier/members/me',
);
final remoteMember = SnChatMember.fromJson(resp.data);
await db.saveMember(remoteMember);
// Update state with fresh data
if (userInfo.value != null) {
state = AsyncData(
await _buildMemberFromDb(db, identifier, userInfo.value!.id),
);
}
} catch (_) {}
}).ignore();
return localMember;
}
}
} catch (_) {}
// Fallback to API
try {
final client = ref.watch(apiClientProvider);
final resp = await client.get('/sphere/chat/$identifier/members/me');
final member = SnChatMember.fromJson(resp.data);
await db.saveMember(member);
return member;
} catch (err) {
if (err is DioException && err.response?.statusCode == 404) {
return null; // Chat member not found
}
rethrow; // Rethrow other errors
}
}
Future<SnChatMember?> _buildMemberFromDb(
AppDatabase db,
String identifier,
String accountId,
) async {
final localMemberData =
await (db.select(db.chatMembers)
..where((m) => m.chatRoomId.equals(identifier))
..where((m) => m.accountId.equals(accountId)))
.getSingleOrNull();
if (localMemberData == null) return null;
final account = SnAccount.fromJson(localMemberData.account);
return SnChatMember(
id: localMemberData.id,
chatRoomId: localMemberData.chatRoomId,
accountId: localMemberData.accountId,
account: account,
nick: localMemberData.nick,
notify: localMemberData.notify,
joinedAt: localMemberData.joinedAt,
breakUntil: localMemberData.breakUntil,
timeoutUntil: localMemberData.timeoutUntil,
status: null,
createdAt: localMemberData.createdAt,
updatedAt: localMemberData.updatedAt,
deletedAt: localMemberData.deletedAt,
chatRoom: null,
);
}
}
@riverpod
Future<List<SnChatMember>> chatroomInvites(Ref ref) async {
final client = ref.watch(apiClientProvider);
final resp = await client.get('/sphere/chat/invites');
return resp.data
.map((e) => SnChatMember.fromJson(e))
.cast<SnChatMember>()
.toList();
}
class _ChatInvitesSheet extends HookConsumerWidget {
const _ChatInvitesSheet();

View File

@@ -1,355 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'chat.dart';
// **************************************************************************
// RiverpodGenerator
// **************************************************************************
String _$chatroomInvitesHash() => r'5cd6391b09c5517ede19bacce43b45c8d71dd087';
/// See also [chatroomInvites].
@ProviderFor(chatroomInvites)
final chatroomInvitesProvider =
AutoDisposeFutureProvider<List<SnChatMember>>.internal(
chatroomInvites,
name: r'chatroomInvitesProvider',
debugGetCreateSourceHash:
const bool.fromEnvironment('dart.vm.product')
? null
: _$chatroomInvitesHash,
dependencies: null,
allTransitiveDependencies: null,
);
@Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element
typedef ChatroomInvitesRef = AutoDisposeFutureProviderRef<List<SnChatMember>>;
String _$chatRoomJoinedNotifierHash() =>
r'c8092225ba0d9c08b2b5bca6f800f1877303b4ff';
/// See also [ChatRoomJoinedNotifier].
@ProviderFor(ChatRoomJoinedNotifier)
final chatRoomJoinedNotifierProvider = AutoDisposeAsyncNotifierProvider<
ChatRoomJoinedNotifier,
List<SnChatRoom>
>.internal(
ChatRoomJoinedNotifier.new,
name: r'chatRoomJoinedNotifierProvider',
debugGetCreateSourceHash:
const bool.fromEnvironment('dart.vm.product')
? null
: _$chatRoomJoinedNotifierHash,
dependencies: null,
allTransitiveDependencies: null,
);
typedef _$ChatRoomJoinedNotifier = AutoDisposeAsyncNotifier<List<SnChatRoom>>;
String _$chatRoomNotifierHash() => r'978bd602cf5e93e60e3c7b9f5799d46a87495c79';
/// Copied from Dart SDK
class _SystemHash {
_SystemHash._();
static int combine(int hash, int value) {
// ignore: parameter_assignments
hash = 0x1fffffff & (hash + value);
// ignore: parameter_assignments
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
return hash ^ (hash >> 6);
}
static int finish(int hash) {
// ignore: parameter_assignments
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
// ignore: parameter_assignments
hash = hash ^ (hash >> 11);
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
}
}
abstract class _$ChatRoomNotifier
extends BuildlessAutoDisposeAsyncNotifier<SnChatRoom?> {
late final String? identifier;
FutureOr<SnChatRoom?> build(String? identifier);
}
/// See also [ChatRoomNotifier].
@ProviderFor(ChatRoomNotifier)
const chatRoomNotifierProvider = ChatRoomNotifierFamily();
/// See also [ChatRoomNotifier].
class ChatRoomNotifierFamily extends Family<AsyncValue<SnChatRoom?>> {
/// See also [ChatRoomNotifier].
const ChatRoomNotifierFamily();
/// See also [ChatRoomNotifier].
ChatRoomNotifierProvider call(String? identifier) {
return ChatRoomNotifierProvider(identifier);
}
@override
ChatRoomNotifierProvider getProviderOverride(
covariant ChatRoomNotifierProvider provider,
) {
return call(provider.identifier);
}
static const Iterable<ProviderOrFamily>? _dependencies = null;
@override
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
@override
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
_allTransitiveDependencies;
@override
String? get name => r'chatRoomNotifierProvider';
}
/// See also [ChatRoomNotifier].
class ChatRoomNotifierProvider
extends
AutoDisposeAsyncNotifierProviderImpl<ChatRoomNotifier, SnChatRoom?> {
/// See also [ChatRoomNotifier].
ChatRoomNotifierProvider(String? identifier)
: this._internal(
() => ChatRoomNotifier()..identifier = identifier,
from: chatRoomNotifierProvider,
name: r'chatRoomNotifierProvider',
debugGetCreateSourceHash:
const bool.fromEnvironment('dart.vm.product')
? null
: _$chatRoomNotifierHash,
dependencies: ChatRoomNotifierFamily._dependencies,
allTransitiveDependencies:
ChatRoomNotifierFamily._allTransitiveDependencies,
identifier: identifier,
);
ChatRoomNotifierProvider._internal(
super._createNotifier, {
required super.name,
required super.dependencies,
required super.allTransitiveDependencies,
required super.debugGetCreateSourceHash,
required super.from,
required this.identifier,
}) : super.internal();
final String? identifier;
@override
FutureOr<SnChatRoom?> runNotifierBuild(covariant ChatRoomNotifier notifier) {
return notifier.build(identifier);
}
@override
Override overrideWith(ChatRoomNotifier Function() create) {
return ProviderOverride(
origin: this,
override: ChatRoomNotifierProvider._internal(
() => create()..identifier = identifier,
from: from,
name: null,
dependencies: null,
allTransitiveDependencies: null,
debugGetCreateSourceHash: null,
identifier: identifier,
),
);
}
@override
AutoDisposeAsyncNotifierProviderElement<ChatRoomNotifier, SnChatRoom?>
createElement() {
return _ChatRoomNotifierProviderElement(this);
}
@override
bool operator ==(Object other) {
return other is ChatRoomNotifierProvider && other.identifier == identifier;
}
@override
int get hashCode {
var hash = _SystemHash.combine(0, runtimeType.hashCode);
hash = _SystemHash.combine(hash, identifier.hashCode);
return _SystemHash.finish(hash);
}
}
@Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element
mixin ChatRoomNotifierRef on AutoDisposeAsyncNotifierProviderRef<SnChatRoom?> {
/// The parameter `identifier` of this provider.
String? get identifier;
}
class _ChatRoomNotifierProviderElement
extends
AutoDisposeAsyncNotifierProviderElement<ChatRoomNotifier, SnChatRoom?>
with ChatRoomNotifierRef {
_ChatRoomNotifierProviderElement(super.provider);
@override
String? get identifier => (origin as ChatRoomNotifierProvider).identifier;
}
String _$chatRoomIdentityNotifierHash() =>
r'27c17d55366d39be81d7209837e5c01f80a68a24';
abstract class _$ChatRoomIdentityNotifier
extends BuildlessAutoDisposeAsyncNotifier<SnChatMember?> {
late final String? identifier;
FutureOr<SnChatMember?> build(String? identifier);
}
/// See also [ChatRoomIdentityNotifier].
@ProviderFor(ChatRoomIdentityNotifier)
const chatRoomIdentityNotifierProvider = ChatRoomIdentityNotifierFamily();
/// See also [ChatRoomIdentityNotifier].
class ChatRoomIdentityNotifierFamily extends Family<AsyncValue<SnChatMember?>> {
/// See also [ChatRoomIdentityNotifier].
const ChatRoomIdentityNotifierFamily();
/// See also [ChatRoomIdentityNotifier].
ChatRoomIdentityNotifierProvider call(String? identifier) {
return ChatRoomIdentityNotifierProvider(identifier);
}
@override
ChatRoomIdentityNotifierProvider getProviderOverride(
covariant ChatRoomIdentityNotifierProvider provider,
) {
return call(provider.identifier);
}
static const Iterable<ProviderOrFamily>? _dependencies = null;
@override
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
@override
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
_allTransitiveDependencies;
@override
String? get name => r'chatRoomIdentityNotifierProvider';
}
/// See also [ChatRoomIdentityNotifier].
class ChatRoomIdentityNotifierProvider
extends
AutoDisposeAsyncNotifierProviderImpl<
ChatRoomIdentityNotifier,
SnChatMember?
> {
/// See also [ChatRoomIdentityNotifier].
ChatRoomIdentityNotifierProvider(String? identifier)
: this._internal(
() => ChatRoomIdentityNotifier()..identifier = identifier,
from: chatRoomIdentityNotifierProvider,
name: r'chatRoomIdentityNotifierProvider',
debugGetCreateSourceHash:
const bool.fromEnvironment('dart.vm.product')
? null
: _$chatRoomIdentityNotifierHash,
dependencies: ChatRoomIdentityNotifierFamily._dependencies,
allTransitiveDependencies:
ChatRoomIdentityNotifierFamily._allTransitiveDependencies,
identifier: identifier,
);
ChatRoomIdentityNotifierProvider._internal(
super._createNotifier, {
required super.name,
required super.dependencies,
required super.allTransitiveDependencies,
required super.debugGetCreateSourceHash,
required super.from,
required this.identifier,
}) : super.internal();
final String? identifier;
@override
FutureOr<SnChatMember?> runNotifierBuild(
covariant ChatRoomIdentityNotifier notifier,
) {
return notifier.build(identifier);
}
@override
Override overrideWith(ChatRoomIdentityNotifier Function() create) {
return ProviderOverride(
origin: this,
override: ChatRoomIdentityNotifierProvider._internal(
() => create()..identifier = identifier,
from: from,
name: null,
dependencies: null,
allTransitiveDependencies: null,
debugGetCreateSourceHash: null,
identifier: identifier,
),
);
}
@override
AutoDisposeAsyncNotifierProviderElement<
ChatRoomIdentityNotifier,
SnChatMember?
>
createElement() {
return _ChatRoomIdentityNotifierProviderElement(this);
}
@override
bool operator ==(Object other) {
return other is ChatRoomIdentityNotifierProvider &&
other.identifier == identifier;
}
@override
int get hashCode {
var hash = _SystemHash.combine(0, runtimeType.hashCode);
hash = _SystemHash.combine(hash, identifier.hashCode);
return _SystemHash.finish(hash);
}
}
@Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element
mixin ChatRoomIdentityNotifierRef
on AutoDisposeAsyncNotifierProviderRef<SnChatMember?> {
/// The parameter `identifier` of this provider.
String? get identifier;
}
class _ChatRoomIdentityNotifierProviderElement
extends
AutoDisposeAsyncNotifierProviderElement<
ChatRoomIdentityNotifier,
SnChatMember?
>
with ChatRoomIdentityNotifierRef {
_ChatRoomIdentityNotifierProviderElement(super.provider);
@override
String? get identifier =>
(origin as ChatRoomIdentityNotifierProvider).identifier;
}
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package

View File

@@ -10,8 +10,8 @@ import 'package:image_picker/image_picker.dart';
import 'package:island/models/chat.dart';
import 'package:island/models/file.dart';
import 'package:island/models/realm.dart';
import 'package:island/pods/chat/chat_room.dart';
import 'package:island/pods/network.dart';
import 'package:island/screens/chat/chat.dart';
import 'package:island/screens/realm/realms.dart';
import 'package:island/services/file.dart';
import 'package:island/services/file_uploader.dart';

View File

@@ -3,7 +3,7 @@ import "package:flutter_hooks/flutter_hooks.dart";
import "package:gap/gap.dart";
import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:island/database/message.dart";
import "package:island/screens/chat/chat.dart";
import "package:island/pods/chat/chat_room.dart";
import "package:island/widgets/content/cloud_files.dart";
import "package:super_sliver_list/super_sliver_list.dart";
import "package:easy_localization/easy_localization.dart";

View File

@@ -14,7 +14,7 @@ import "package:island/models/chat.dart";
import "package:island/models/file.dart";
import "package:island/models/poll.dart";
import "package:island/models/wallet.dart";
import "package:island/pods/chat/chat_rooms.dart";
import "package:island/pods/chat/chat_room.dart";
import "package:island/pods/chat/chat_subscribe.dart";
import "package:island/pods/chat/messages_notifier.dart";
import "package:island/pods/network.dart";
@@ -23,7 +23,6 @@ import "package:island/pods/config.dart";
import "package:island/pods/userinfo.dart";
import "package:island/screens/chat/search_messages.dart";
import "package:island/services/file_uploader.dart";
import "package:island/screens/chat/chat.dart";
import "package:island/services/responsive.dart";
import "package:island/widgets/alert.dart";
import "package:island/widgets/app_scaffold.dart";

View File

@@ -7,8 +7,8 @@ import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:gap/gap.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/chat.dart';
import 'package:island/pods/chat/chat_room.dart';
import 'package:island/pods/network.dart';
import 'package:island/screens/chat/chat.dart';
import 'package:island/widgets/account/account_pfc.dart';
import 'package:island/widgets/account/account_picker.dart';
import 'package:island/widgets/account/status.dart';

View File

@@ -3,8 +3,8 @@ import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/pods/chat/chat_room.dart';
import 'package:island/pods/chat/messages_notifier.dart';
import 'package:island/pods/chat/chat_rooms.dart';
import 'package:island/widgets/app_scaffold.dart';
import 'package:island/widgets/chat/message_list_tile.dart';
import 'package:material_symbols_icons/material_symbols_icons.dart';