⚡ Use cached chat rooms for first time render chat
This commit is contained in:
@@ -273,6 +273,65 @@ class AppDatabase extends _$AppDatabase {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChatRoomsCompanion companionFromRoom(SnChatRoom room) {
|
||||||
|
return ChatRoomsCompanion(
|
||||||
|
id: Value(room.id),
|
||||||
|
name: Value(room.name),
|
||||||
|
description: Value(room.description),
|
||||||
|
type: Value(room.type),
|
||||||
|
isPublic: Value(room.isPublic),
|
||||||
|
isCommunity: Value(room.isCommunity),
|
||||||
|
picture: Value(room.picture?.toJson()),
|
||||||
|
background: Value(room.background?.toJson()),
|
||||||
|
realmId: Value(room.realmId),
|
||||||
|
createdAt: Value(room.createdAt),
|
||||||
|
updatedAt: Value(room.updatedAt),
|
||||||
|
deletedAt: Value(room.deletedAt),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatMembersCompanion companionFromMember(SnChatMember member) {
|
||||||
|
return ChatMembersCompanion(
|
||||||
|
id: Value(member.id),
|
||||||
|
chatRoomId: Value(member.chatRoomId),
|
||||||
|
accountId: Value(member.accountId),
|
||||||
|
account: Value(member.account.toJson()),
|
||||||
|
nick: Value(member.nick),
|
||||||
|
role: Value(member.role),
|
||||||
|
notify: Value(member.notify),
|
||||||
|
joinedAt: Value(member.joinedAt),
|
||||||
|
breakUntil: Value(member.breakUntil),
|
||||||
|
timeoutUntil: Value(member.timeoutUntil),
|
||||||
|
isBot: Value(member.isBot),
|
||||||
|
status: Value(
|
||||||
|
member.status == null ? null : jsonEncode(member.status!.toJson()),
|
||||||
|
),
|
||||||
|
lastTyped: Value(member.lastTyped),
|
||||||
|
createdAt: Value(member.createdAt),
|
||||||
|
updatedAt: Value(member.updatedAt),
|
||||||
|
deletedAt: Value(member.deletedAt),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> saveChatRooms(List<SnChatRoom> rooms) async {
|
||||||
|
await batch((batch) {
|
||||||
|
for (final room in rooms) {
|
||||||
|
batch.insert(
|
||||||
|
chatRooms,
|
||||||
|
companionFromRoom(room),
|
||||||
|
mode: InsertMode.insertOrReplace,
|
||||||
|
);
|
||||||
|
for (final member in room.members ?? []) {
|
||||||
|
batch.insert(
|
||||||
|
chatMembers,
|
||||||
|
companionFromMember(member),
|
||||||
|
mode: InsertMode.insertOrReplace,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Methods for post drafts
|
// Methods for post drafts
|
||||||
Future<List<SnPost>> getAllPostDrafts() async {
|
Future<List<SnPost>> getAllPostDrafts() async {
|
||||||
final drafts = await select(postDrafts).get();
|
final drafts = await select(postDrafts).get();
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:convert';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -6,6 +8,9 @@ import 'package:flutter_hooks/flutter_hooks.dart';
|
|||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/chat.dart';
|
import 'package:island/models/chat.dart';
|
||||||
|
import 'package:island/models/file.dart';
|
||||||
|
import 'package:island/models/account.dart';
|
||||||
|
import 'package:island/pods/database.dart';
|
||||||
import 'package:island/pods/chat/call.dart';
|
import 'package:island/pods/chat/call.dart';
|
||||||
import 'package:island/pods/chat/chat_summary.dart';
|
import 'package:island/pods/chat/chat_summary.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
@@ -121,6 +126,17 @@ class ChatRoomListTile extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String titleText;
|
||||||
|
if (isDirect && room.name == null) {
|
||||||
|
if (room.members?.isNotEmpty ?? false) {
|
||||||
|
titleText = room.members!.map((e) => e.account.nick).join(', ');
|
||||||
|
} else {
|
||||||
|
titleText = 'Direct Message';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
titleText = room.name ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
return ListTile(
|
return ListTile(
|
||||||
leading: Badge(
|
leading: Badge(
|
||||||
isLabelVisible: summary.when(
|
isLabelVisible: summary.when(
|
||||||
@@ -140,11 +156,7 @@ class ChatRoomListTile extends HookConsumerWidget {
|
|||||||
? CircleAvatar(child: Text(room.name![0].toUpperCase()))
|
? CircleAvatar(child: Text(room.name![0].toUpperCase()))
|
||||||
: ProfilePictureWidget(fileId: room.picture?.id),
|
: ProfilePictureWidget(fileId: room.picture?.id),
|
||||||
),
|
),
|
||||||
title: Text(
|
title: Text(titleText),
|
||||||
(isDirect && room.name == null)
|
|
||||||
? room.members!.map((e) => e.account.nick).join(', ')
|
|
||||||
: room.name ?? '',
|
|
||||||
),
|
|
||||||
subtitle: buildSubtitle(),
|
subtitle: buildSubtitle(),
|
||||||
trailing: trailing, // Add this line
|
trailing: trailing, // Add this line
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
@@ -162,12 +174,92 @@ class ChatRoomListTile extends HookConsumerWidget {
|
|||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
Future<List<SnChatRoom>> chatroomsJoined(Ref ref) async {
|
Future<List<SnChatRoom>> chatroomsJoined(Ref ref) 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);
|
||||||
|
SnAccountStatus? status;
|
||||||
|
if (mRow.status != null) {
|
||||||
|
status = SnAccountStatus.fromJson(jsonDecode(mRow.status!));
|
||||||
|
}
|
||||||
|
return SnChatMember(
|
||||||
|
id: mRow.id,
|
||||||
|
chatRoomId: mRow.chatRoomId,
|
||||||
|
accountId: mRow.accountId,
|
||||||
|
account: account,
|
||||||
|
nick: mRow.nick,
|
||||||
|
role: mRow.role,
|
||||||
|
notify: mRow.notify,
|
||||||
|
joinedAt: mRow.joinedAt,
|
||||||
|
breakUntil: mRow.breakUntil,
|
||||||
|
timeoutUntil: mRow.timeoutUntil,
|
||||||
|
isBot: mRow.isBot,
|
||||||
|
status: status,
|
||||||
|
lastTyped: mRow.lastTyped,
|
||||||
|
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,
|
||||||
|
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);
|
||||||
|
ref.invalidateSelf();
|
||||||
|
} catch (_) {}
|
||||||
|
}).ignore();
|
||||||
|
|
||||||
|
return localRooms;
|
||||||
|
}
|
||||||
|
} catch (_) {}
|
||||||
|
|
||||||
|
// Fallback to API
|
||||||
final client = ref.watch(apiClientProvider);
|
final client = ref.watch(apiClientProvider);
|
||||||
final resp = await client.get('/sphere/chat');
|
final resp = await client.get('/sphere/chat');
|
||||||
return resp.data
|
final rooms =
|
||||||
.map((e) => SnChatRoom.fromJson(e))
|
resp.data.map((e) => SnChatRoom.fromJson(e)).cast<SnChatRoom>().toList();
|
||||||
.cast<SnChatRoom>()
|
await db.saveChatRooms(rooms);
|
||||||
.toList();
|
return rooms;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChatListBodyWidget extends HookConsumerWidget {
|
class ChatListBodyWidget extends HookConsumerWidget {
|
||||||
|
|||||||
Reference in New Issue
Block a user