small refactors

This commit is contained in:
Henry Hiles 2026-09-25 13:01:32 -04:00
commit 24aa0cae1d
Signed by: Henry-Hiles
SSH key fingerprint: SHA256:VKQUdS31Q90KvX7EkKMHMBpUspcmItAh86a+v7PGiIs
5 changed files with 69 additions and 48 deletions

View file

@ -17,7 +17,7 @@ import "package:nexus/models/requests/send_message.dart";
import "package:nexus/models/room.dart";
import "package:nexus/models/room_chat.dart";
class RoomChatController(final (String roomId, String? withEventId) info)
class RoomChatController(final (String roomId, String? contextualEvent) info)
extends AsyncNotifier<RoomChat?> {
@override
Future<RoomChat?> build() async {
@ -34,9 +34,13 @@ class RoomChatController(final (String roomId, String? withEventId) info)
await ref.read(RoomsController.provider.notifier).addState(roomId, state);
}
if (info.$2 == null ||
room.events.values.map((e) => e.eventId).contains(info.$2)) {
return .new(
events: room.timeline
.toEntryIList(compare: (a, b) => (a?.key ?? 0).compareTo(b?.key ?? 0))
.toEntryIList(
compare: (a, b) => (a?.key ?? 0).compareTo(b?.key ?? 0),
)
.map((element) => element.value)
.toIList()
.addAll(room.clientSticky)
@ -60,6 +64,18 @@ class RoomChatController(final (String roomId, String? withEventId) info)
hasMore: room.hasMore,
);
}
{
final context = await client.getEventContext(
.new(roomId: roomId, eventId: info.$2!, limit: 20),
);
return .new(
events: context.events,
hasMore: true,
historicalData: .new(start: context.start, end: context.end),
);
}
}
Future<void> deleteMessage(Event event, {String? reason}) => ref
.watch(ClientController.provider.notifier)

View file

@ -92,19 +92,14 @@ final class ChatScroll({
(item) => item.eventId == itemId,
);
double? offset;
if (historyIndex != -1) {
// TODO: Replace SuperSliverView because of the bug that requires this: #94
// ignore: invalid_use_of_visible_for_testing_member
final offset = historyListController.value.getOffsetToReveal(
offset = historyListController.value.getOffsetToReveal(
historyIndex,
0.5,
);
await scrollController.animateTo(
offset,
duration: const Duration(milliseconds: 700),
curve: Curves.easeInOut,
);
} else {
final liveIndex = split.live.indexWhere(
(item) => item.eventId == itemId,
@ -112,11 +107,15 @@ final class ChatScroll({
if (liveIndex != -1) {
// ignore: invalid_use_of_visible_for_testing_member
final offset = liveListController.value.getOffsetToReveal(
liveIndex,
0.5,
);
offset = liveListController.value.getOffsetToReveal(liveIndex, 0.5);
}
}
if (offset == null) {
// not in current timeline
}
if (offset != null) {
await scrollController.animateTo(
offset,
duration: const Duration(milliseconds: 700),
@ -124,7 +123,6 @@ final class ChatScroll({
);
}
}
}
return .new(
historyItems: split.history,

View file

@ -12,17 +12,26 @@ part "room.g.dart";
class const Room({
@JsonKey(name: "meta") final RoomMetadata? metadata,
/// [timeline] is an IMap of timelineRowId to eventRowId
@JsonKey(fromJson: Room.timelineTupleJsonToIMap)
final IMap<int, int?> timeline = const IMap.empty(),
/// [clientSticky] is an ISet of eventRowId
@JsonKey(includeFromJson: false, includeToJson: false)
final ISet<int> clientSticky = const ISet.empty(),
/// [events] is an IMap of eventRowId to event
@JsonKey(fromJson: Room.eventsJsonToIMap)
final IMap<int, Event> events = const IMap.empty(),
final bool reset = false,
@JsonKey(includeFromJson: false, includeToJson: false)
final bool hasFetchedState = false,
@JsonKey(includeFromJson: false, includeToJson: false)
final bool hasFetchedMembers = false,
final IMap<String, IMap<String, int>> state = const IMap.empty(),
final IMap<String, IList<ReadReceipt>> receipts = const IMap.empty(),
@ -32,9 +41,6 @@ class const Room({
// IMap<String, AccountData> accountData,
// IList<Notification> notifications,
}) with _$Room {
/// [timeline] is an IMap of timelineRowId to eventRowId
/// [events] is an IMap of eventRowId to event
/// [clientSticky] is an ISet of eventRowId
static IMap<int, int?> timelineTupleJsonToIMap(List<dynamic> json) =>
IMap.fromEntries(
json.map(

View file

@ -21,8 +21,8 @@ class const RoomChat({
@Freezed(toJson: false, fromJson: false)
@JsonSerializable()
class const HistoricalData({
required final String end,
required final String start,
required final String end,
}) with _$HistoricalData {
Map<String, Object?> toJson() => _$HistoricalDataToJson(this);

View file

@ -31,6 +31,7 @@ final class const RoomChat({
Widget build(BuildContext context, WidgetRef ref) {
final relatedEvent = useState<Event?>(null);
final relationType = useState(RelationType.reply);
final contextualEvent = useState<String?>(initialHighlightedEvent);
final highlightedEvent = useState<String?>(initialHighlightedEvent);
final composerSize = useState<double>(64);
@ -62,7 +63,7 @@ final class const RoomChat({
final controllerProvider = RoomChatController.provider((
roomId,
initialHighlightedEvent,
contextualEvent.value,
));
final notifier = ref.watch(controllerProvider.notifier);