Gomuks SDK Rewrite #2
15 changed files with 186 additions and 89 deletions
wip
commit
c2214fcc44
|
|
@ -15,6 +15,7 @@ import "package:nexus/models/event.dart";
|
||||||
import "package:nexus/models/paginate.dart";
|
import "package:nexus/models/paginate.dart";
|
||||||
import "package:nexus/models/requests/get_event_request.dart";
|
import "package:nexus/models/requests/get_event_request.dart";
|
||||||
import "package:nexus/models/requests/get_related_events_request.dart";
|
import "package:nexus/models/requests/get_related_events_request.dart";
|
||||||
|
import "package:nexus/models/requests/get_room_state_request.dart";
|
||||||
import "package:nexus/models/requests/login_request.dart";
|
import "package:nexus/models/requests/login_request.dart";
|
||||||
import "package:nexus/models/profile.dart";
|
import "package:nexus/models/profile.dart";
|
||||||
import "package:nexus/models/requests/paginate_request.dart";
|
import "package:nexus/models/requests/paginate_request.dart";
|
||||||
|
|
@ -117,7 +118,9 @@ class ClientController extends AsyncNotifier<int> {
|
||||||
|
|
||||||
calloc.free(bufferPointer);
|
calloc.free(bufferPointer);
|
||||||
|
|
||||||
return response.buf.toJson();
|
final json = response.buf.toJson();
|
||||||
|
if (json is String) throw json;
|
||||||
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> redactEvent(RedactEventRequest report) =>
|
Future<void> redactEvent(RedactEventRequest report) =>
|
||||||
|
|
@ -140,6 +143,12 @@ class ClientController extends AsyncNotifier<int> {
|
||||||
await _sendCommand("leave_room", {"room_id": room.metadata!.id});
|
await _sendCommand("leave_room", {"room_id": room.metadata!.id});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<IList<Event>> getRoomState(GetRoomStateRequest request) async {
|
||||||
|
final response =
|
||||||
|
(await _sendCommand("get_room_state", request.toJson())) as List;
|
||||||
|
return response.map((event) => Event.fromJson(event)).toIList();
|
||||||
|
}
|
||||||
|
|
||||||
Future<IList<Event>?> getRelatedEvents(
|
Future<IList<Event>?> getRelatedEvents(
|
||||||
GetRelatedEventsRequest request,
|
GetRelatedEventsRequest request,
|
||||||
) async {
|
) async {
|
||||||
|
|
@ -157,11 +166,8 @@ class ClientController extends AsyncNotifier<int> {
|
||||||
Future<Paginate> paginate(PaginateRequest request) async =>
|
Future<Paginate> paginate(PaginateRequest request) async =>
|
||||||
Paginate.fromJson(await _sendCommand("paginate", request.toJson()));
|
Paginate.fromJson(await _sendCommand("paginate", request.toJson()));
|
||||||
|
|
||||||
Future<Profile?> getProfile(String userId) async {
|
Future<Profile> getProfile(String userId) async =>
|
||||||
final json = await _sendCommand("get_profile", {"user_id": userId});
|
Profile.fromJson(await _sendCommand("get_profile", {"user_id": userId}));
|
||||||
|
|
||||||
return json == null ? null : Profile.fromJson(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> reportEvent(ReportRequest report) =>
|
Future<void> reportEvent(ReportRequest report) =>
|
||||||
_sendCommand("report_event", report.toJson());
|
_sendCommand("report_event", report.toJson());
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,26 @@
|
||||||
|
import "package:collection/collection.dart";
|
||||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
import "package:matrix/matrix.dart";
|
import "package:nexus/models/event.dart";
|
||||||
|
import "package:nexus/models/room.dart";
|
||||||
|
|
||||||
class MembersController extends AsyncNotifier<IList<MatrixEvent>> {
|
class MembersController extends AsyncNotifier<IList<Event>> {
|
||||||
final Room room;
|
final Room room;
|
||||||
MembersController(this.room);
|
MembersController(this.room);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<IList<MatrixEvent>> build() async => IList(
|
Future<IList<Event>> build() async =>
|
||||||
(await room.client.getMembersByRoom(
|
(room.state["m.room.member"]?.values ?? [])
|
||||||
room.id,
|
.map(
|
||||||
notMembership: Membership.leave,
|
(eventRowId) => room.events.firstWhereOrNull(
|
||||||
)) ??
|
(event) => event.rowId == eventRowId,
|
||||||
[],
|
),
|
||||||
);
|
)
|
||||||
|
.nonNulls
|
||||||
|
.toIList();
|
||||||
|
|
||||||
static final provider = AsyncNotifierProvider.family
|
static final provider = AsyncNotifierProvider.family
|
||||||
.autoDispose<MembersController, IList<MatrixEvent>, Room>(
|
.autoDispose<MembersController, IList<Event>, Room>(
|
||||||
MembersController.new,
|
MembersController.new,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
17
lib/controllers/profile_controller.dart
Normal file
17
lib/controllers/profile_controller.dart
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
|
import "package:nexus/controllers/client_controller.dart";
|
||||||
|
import "package:nexus/models/profile.dart";
|
||||||
|
|
||||||
|
class ProfileController extends AsyncNotifier<Profile> {
|
||||||
|
final String userId;
|
||||||
|
ProfileController(this.userId);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Profile> build() =>
|
||||||
|
ref.watch(ClientController.provider.notifier).getProfile(userId);
|
||||||
|
|
||||||
|
static final provider =
|
||||||
|
AsyncNotifierProvider.family<ProfileController, Profile, String>(
|
||||||
|
ProfileController.new,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -6,14 +6,17 @@ import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
import "package:fluttertagger/fluttertagger.dart" as tagger;
|
import "package:fluttertagger/fluttertagger.dart" as tagger;
|
||||||
import "package:nexus/controllers/client_controller.dart";
|
import "package:nexus/controllers/client_controller.dart";
|
||||||
import "package:nexus/controllers/new_events_controller.dart";
|
import "package:nexus/controllers/new_events_controller.dart";
|
||||||
|
import "package:nexus/controllers/rooms_controller.dart";
|
||||||
import "package:nexus/controllers/selected_room_controller.dart";
|
import "package:nexus/controllers/selected_room_controller.dart";
|
||||||
import "package:nexus/helpers/extensions/event_to_message.dart";
|
import "package:nexus/helpers/extensions/event_to_message.dart";
|
||||||
import "package:nexus/helpers/extensions/list_to_messages.dart";
|
import "package:nexus/helpers/extensions/list_to_messages.dart";
|
||||||
|
import "package:nexus/models/event.dart";
|
||||||
|
import "package:nexus/models/requests/get_room_state_request.dart";
|
||||||
|
import "package:nexus/models/requests/paginate_request.dart";
|
||||||
import "package:nexus/models/requests/redact_event_request.dart";
|
import "package:nexus/models/requests/redact_event_request.dart";
|
||||||
import "package:nexus/models/relation_type.dart";
|
import "package:nexus/models/relation_type.dart";
|
||||||
import "package:nexus/models/requests/send_message_request.dart";
|
import "package:nexus/models/requests/send_message_request.dart";
|
||||||
import "package:nexus/models/room.dart";
|
import "package:nexus/models/room.dart";
|
||||||
import "package:nexus/models/sync_data.dart";
|
|
||||||
|
|
||||||
class RoomChatController extends AsyncNotifier<ChatController> {
|
class RoomChatController extends AsyncNotifier<ChatController> {
|
||||||
final String roomId;
|
final String roomId;
|
||||||
|
|
@ -22,9 +25,8 @@ class RoomChatController extends AsyncNotifier<ChatController> {
|
||||||
@override
|
@override
|
||||||
Future<ChatController> build() async {
|
Future<ChatController> build() async {
|
||||||
final client = ref.watch(ClientController.provider.notifier);
|
final client = ref.watch(ClientController.provider.notifier);
|
||||||
final events =
|
final room = ref.read(SelectedRoomController.provider);
|
||||||
ref.read(SelectedRoomController.provider)?.events ??
|
if (room == null) return InMemoryChatController();
|
||||||
const IList.empty();
|
|
||||||
|
|
||||||
ref.onDispose(
|
ref.onDispose(
|
||||||
ref.listen(NewEventsController.provider(roomId), (_, next) async {
|
ref.listen(NewEventsController.provider(roomId), (_, next) async {
|
||||||
|
|
@ -38,7 +40,7 @@ class RoomChatController extends AsyncNotifier<ChatController> {
|
||||||
|
|
||||||
await controller.removeMessage(message);
|
await controller.removeMessage(message);
|
||||||
} else {
|
} else {
|
||||||
final message = await event.toMessage(client, includeEdits: true);
|
final message = await event.toMessage(ref, includeEdits: true);
|
||||||
if (event.relationType == "m.replace") {
|
if (event.relationType == "m.replace") {
|
||||||
final controller = await future;
|
final controller = await future;
|
||||||
final oldMessage = controller.messages.firstWhereOrNull(
|
final oldMessage = controller.messages.firstWhereOrNull(
|
||||||
|
|
@ -69,11 +71,26 @@ class RoomChatController extends AsyncNotifier<ChatController> {
|
||||||
}).close,
|
}).close,
|
||||||
);
|
);
|
||||||
|
|
||||||
final messages = await events.toMessages(client);
|
final messages = await room.timeline
|
||||||
|
.map(
|
||||||
|
(timelineRowTuple) => room.events.firstWhereOrNull(
|
||||||
|
(event) => event.rowId == timelineRowTuple.eventRowId,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.nonNulls
|
||||||
|
.toMessages(ref);
|
||||||
final controller = InMemoryChatController(messages: messages);
|
final controller = InMemoryChatController(messages: messages);
|
||||||
|
ref.onDispose(controller.dispose);
|
||||||
|
|
||||||
if (messages.length < 20) await loadOlder(controller);
|
if (messages.length < 20) await loadOlder(controller);
|
||||||
|
|
||||||
|
await client.getRoomState(
|
||||||
|
GetRoomStateRequest(
|
||||||
|
roomId: roomId,
|
||||||
|
fetchMembers: room.metadata?.hasMemberList == false,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
return controller;
|
return controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -109,23 +126,47 @@ class RoomChatController extends AsyncNotifier<ChatController> {
|
||||||
final controller = chatController ?? await future;
|
final controller = chatController ?? await future;
|
||||||
final client = ref.watch(ClientController.provider.notifier);
|
final client = ref.watch(ClientController.provider.notifier);
|
||||||
|
|
||||||
client.
|
final response = await client.paginate(
|
||||||
// await ref.watchInMemoryChatController? chatController(EventsController.provider(room).notifier).prev();
|
PaginateRequest(
|
||||||
// final timeline = await ref.watch(EventsController.provider(room).future);
|
roomId: roomId,
|
||||||
|
maxTimelineId: controller.messages.firstOrNull?.metadata?["timelineId"],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
// final controller = await future;
|
ref
|
||||||
// await controller.insertAllMessages(
|
.watch(RoomsController.provider.notifier)
|
||||||
// await timeline.events
|
.update(
|
||||||
// .where(
|
IMap({
|
||||||
// (event) => !currentEvents.messages.any(
|
roomId: Room(
|
||||||
// (existingEvent) => existingEvent.id == event.eventId,
|
events: response.events.addAll(response.relatedEvents),
|
||||||
// ),
|
hasMore: response.hasMore,
|
||||||
// )
|
timeline: response.events
|
||||||
// .toList()
|
.map(
|
||||||
// .toMessages(room, timeline),
|
(event) => TimelineRowTuple(
|
||||||
// index: 0,
|
timelineRowId: event.timelineRowId,
|
||||||
// );
|
eventRowId: event.rowId,
|
||||||
// ref.notifyListeners();
|
),
|
||||||
|
)
|
||||||
|
.toIList(),
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
const ISet.empty(),
|
||||||
|
);
|
||||||
|
|
||||||
|
final existingIds = controller.messages.map((m) => m.id).toSet();
|
||||||
|
|
||||||
|
final messages = await response.events
|
||||||
|
.where((event) => !existingIds.contains(event.eventId))
|
||||||
|
.fold(<String, Event>{}, (acc, event) {
|
||||||
|
acc[event.eventId] =
|
||||||
|
event; // overwrites duplicates in response.events
|
||||||
|
return acc;
|
||||||
|
})
|
||||||
|
.values
|
||||||
|
.toIList()
|
||||||
|
.reversed
|
||||||
|
.toMessages(ref);
|
||||||
|
await controller.insertAllMessages(messages, index: 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updateMessage(Message message, Message newMessage) async =>
|
Future<void> updateMessage(Message message, Message newMessage) async =>
|
||||||
|
|
@ -167,7 +208,7 @@ class RoomChatController extends AsyncNotifier<ChatController> {
|
||||||
.getProfile(id);
|
.getProfile(id);
|
||||||
return chat.User(
|
return chat.User(
|
||||||
id: id,
|
id: id,
|
||||||
name: user?.displayName,
|
name: user.displayName,
|
||||||
// imageSource: user.avatarUrl == null
|
// imageSource: user.avatarUrl == null
|
||||||
// ? null
|
// ? null
|
||||||
// : (await ref.watch(
|
// : (await ref.watch(
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import "package:collection/collection.dart";
|
||||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
import "package:nexus/controllers/new_events_controller.dart";
|
import "package:nexus/controllers/new_events_controller.dart";
|
||||||
|
|
@ -28,16 +29,22 @@ class RoomsController extends Notifier<IMap<String, Room>> {
|
||||||
),
|
),
|
||||||
state: incoming.state.entries.fold(
|
state: incoming.state.entries.fold(
|
||||||
existing.state,
|
existing.state,
|
||||||
(stateAcc, event) => stateAcc.add(
|
(previousValue, event) => previousValue.add(
|
||||||
event.key,
|
event.key,
|
||||||
(stateAcc[event.key] ?? IMap<dynamic, dynamic>()).addAll(
|
(previousValue[event.key] ?? const IMap.empty()).addAll(
|
||||||
event.value,
|
event.value,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
timeline: incoming.reset
|
timeline:
|
||||||
? incoming.timeline
|
(incoming.reset
|
||||||
: existing.timeline.addAll(incoming.timeline),
|
? incoming.timeline
|
||||||
|
: existing.timeline.updateById(
|
||||||
|
incoming.timeline,
|
||||||
|
(item) => item.timelineRowId,
|
||||||
|
))
|
||||||
|
.sortedBy((element) => element.timelineRowId)
|
||||||
|
.toIList(),
|
||||||
receipts: incoming.receipts.entries.fold(
|
receipts: incoming.receipts.entries.fold(
|
||||||
existing.receipts,
|
existing.receipts,
|
||||||
(receiptAcc, event) => receiptAcc.add(
|
(receiptAcc, event) => receiptAcc.add(
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,19 @@
|
||||||
import "package:flutter_chat_core/flutter_chat_core.dart";
|
import "package:flutter_chat_core/flutter_chat_core.dart";
|
||||||
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
import "package:nexus/controllers/client_controller.dart";
|
import "package:nexus/controllers/client_controller.dart";
|
||||||
|
import "package:nexus/controllers/profile_controller.dart";
|
||||||
import "package:nexus/models/event.dart";
|
import "package:nexus/models/event.dart";
|
||||||
import "package:nexus/models/requests/get_event_request.dart";
|
import "package:nexus/models/requests/get_event_request.dart";
|
||||||
import "package:nexus/models/requests/get_related_events_request.dart";
|
import "package:nexus/models/requests/get_related_events_request.dart";
|
||||||
|
|
||||||
extension EventToMessage on Event {
|
extension EventToMessage on Event {
|
||||||
Future<Message?> toMessage(
|
Future<Message?> toMessage(
|
||||||
ClientController client, {
|
Ref ref, {
|
||||||
bool mustBeText = false,
|
bool mustBeText = false,
|
||||||
bool includeEdits = false,
|
bool includeEdits = false,
|
||||||
}) async {
|
}) async {
|
||||||
if (relationType == "m.replace" && !includeEdits) return null;
|
if (relationType == "m.replace" && !includeEdits) return null;
|
||||||
|
final client = ref.watch(ClientController.provider.notifier);
|
||||||
|
|
||||||
final newEvents = await client.getRelatedEvents(
|
final newEvents = await client.getRelatedEvents(
|
||||||
GetRelatedEventsRequest(
|
GetRelatedEventsRequest(
|
||||||
|
|
@ -28,22 +31,25 @@ extension EventToMessage on Event {
|
||||||
GetEventRequest(roomId: roomId, eventId: replyId),
|
GetEventRequest(roomId: roomId, eventId: replyId),
|
||||||
);
|
);
|
||||||
|
|
||||||
final author = await client.getProfile(event.authorId);
|
final author = await ref.watch(
|
||||||
|
ProfileController.provider(event.authorId).future,
|
||||||
|
);
|
||||||
final content = (decrypted ?? this.content);
|
final content = (decrypted ?? this.content);
|
||||||
final type = (decryptedType ?? this.type);
|
final type = (decryptedType ?? this.type);
|
||||||
final newContent = content["m.new_content"] as Map?;
|
final newContent = content["m.new_content"] as Map?;
|
||||||
final metadata = {
|
final metadata = {
|
||||||
|
"timelineId": event.timelineRowId,
|
||||||
"formatted":
|
"formatted":
|
||||||
newContent?["formatted_body"] ??
|
newContent?["formatted_body"] ??
|
||||||
newContent?["body"] ??
|
newContent?["body"] ??
|
||||||
content["formatted_body"] ??
|
content["formatted_body"] ??
|
||||||
content["body"] ??
|
content["body"] ??
|
||||||
"",
|
"",
|
||||||
"reply": await replyEvent?.toMessage(client, mustBeText: true),
|
"reply": await replyEvent?.toMessage(ref, mustBeText: true),
|
||||||
"body": newContent?["body"] ?? content["body"],
|
"body": newContent?["body"] ?? content["body"],
|
||||||
"eventType": type,
|
"eventType": type,
|
||||||
"avatarUrl": author?.avatarUrl,
|
"avatarUrl": author.avatarUrl,
|
||||||
"displayName": author?.displayName ?? authorId,
|
"displayName": author.displayName ?? authorId,
|
||||||
"txnId": transactionId,
|
"txnId": transactionId,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,10 @@
|
||||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
|
||||||
import "package:flutter_chat_core/flutter_chat_core.dart";
|
import "package:flutter_chat_core/flutter_chat_core.dart";
|
||||||
import "package:nexus/controllers/client_controller.dart";
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
import "package:nexus/helpers/extensions/event_to_message.dart";
|
import "package:nexus/helpers/extensions/event_to_message.dart";
|
||||||
import "package:nexus/models/event.dart";
|
import "package:nexus/models/event.dart";
|
||||||
|
|
||||||
extension ListToMessages on IList<Event> {
|
extension ListToMessages on Iterable<Event> {
|
||||||
Future<List<Message>> toMessages(ClientController client) async =>
|
Future<List<Message>> toMessages(Ref ref) async => (await Future.wait(
|
||||||
(await Future.wait(
|
map((event) => event.toMessage(ref)),
|
||||||
map((event) => event.toMessage(client)),
|
)).nonNulls.toList();
|
||||||
)).nonNulls.toList();
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ part "paginate.g.dart";
|
||||||
abstract class Paginate with _$Paginate {
|
abstract class Paginate with _$Paginate {
|
||||||
const factory Paginate({
|
const factory Paginate({
|
||||||
required IList<Event> events,
|
required IList<Event> events,
|
||||||
|
required IList<Event> relatedEvents,
|
||||||
required bool hasMore,
|
required bool hasMore,
|
||||||
}) = _Paginate;
|
}) = _Paginate;
|
||||||
|
|
||||||
|
|
|
||||||
15
lib/models/requests/get_room_state_request.dart
Normal file
15
lib/models/requests/get_room_state_request.dart
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
import "package:freezed_annotation/freezed_annotation.dart";
|
||||||
|
part "get_room_state_request.freezed.dart";
|
||||||
|
part "get_room_state_request.g.dart";
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class GetRoomStateRequest with _$GetRoomStateRequest {
|
||||||
|
const factory GetRoomStateRequest({
|
||||||
|
required String roomId,
|
||||||
|
required bool fetchMembers,
|
||||||
|
@Default(false) bool includeMembers,
|
||||||
|
}) = _GetRoomStateRequest;
|
||||||
|
|
||||||
|
factory GetRoomStateRequest.fromJson(Map<String, Object?> json) =>
|
||||||
|
_$GetRoomStateRequestFromJson(json);
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ part "paginate_request.g.dart";
|
||||||
abstract class PaginateRequest with _$PaginateRequest {
|
abstract class PaginateRequest with _$PaginateRequest {
|
||||||
const factory PaginateRequest({
|
const factory PaginateRequest({
|
||||||
required String roomId,
|
required String roomId,
|
||||||
|
required int? maxTimelineId,
|
||||||
@Default(20) int limit,
|
@Default(20) int limit,
|
||||||
}) = _PaginateRequest;
|
}) = _PaginateRequest;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@ abstract class SendMessageRequest with _$SendMessageRequest {
|
||||||
const factory SendMessageRequest({
|
const factory SendMessageRequest({
|
||||||
required String roomId,
|
required String roomId,
|
||||||
required String text,
|
required String text,
|
||||||
@Default(Mentions()) @JsonKey(name: "m.mentions") Mentions mentions,
|
@Default(Mentions()) @JsonKey(name: "mentions") Mentions mentions,
|
||||||
@JsonKey(name: "m.relates_to") Relation? relation,
|
@JsonKey(name: "relates_to") Relation? relation,
|
||||||
}) = _SendMessageRequest;
|
}) = _SendMessageRequest;
|
||||||
|
|
||||||
factory SendMessageRequest.fromJson(Map<String, Object?> json) =>
|
factory SendMessageRequest.fromJson(Map<String, Object?> json) =>
|
||||||
|
|
@ -28,17 +28,16 @@ abstract class Mentions with _$Mentions {
|
||||||
_$MentionsFromJson(json);
|
_$MentionsFromJson(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@Freezed(toJson: false)
|
||||||
abstract class Relation with _$Relation {
|
abstract class Relation with _$Relation {
|
||||||
const Relation._(); // required for custom methods
|
const Relation._();
|
||||||
|
|
||||||
const factory Relation({
|
const factory Relation({
|
||||||
required String eventId,
|
required String eventId,
|
||||||
required RelationType relationType,
|
required RelationType relationType,
|
||||||
}) = _Relation;
|
}) = _Relation;
|
||||||
|
|
||||||
@override
|
Map<String, dynamic> toJson() {
|
||||||
Map<String, Object?> toJson() {
|
|
||||||
switch (relationType) {
|
switch (relationType) {
|
||||||
case RelationType.reply:
|
case RelationType.reply:
|
||||||
return {
|
return {
|
||||||
|
|
@ -50,6 +49,6 @@ abstract class Relation with _$Relation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
factory Relation.fromJson(Map<String, Object?> json) =>
|
factory Relation.fromJson(Map<String, dynamic> json) =>
|
||||||
_$RelationFromJson(json);
|
_$RelationFromJson(json);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,13 @@ abstract class Room with _$Room {
|
||||||
const factory Room({
|
const factory Room({
|
||||||
@JsonKey(name: "meta") RoomMetadata? metadata,
|
@JsonKey(name: "meta") RoomMetadata? metadata,
|
||||||
@Default(IList.empty()) IList<TimelineRowTuple> timeline,
|
@Default(IList.empty()) IList<TimelineRowTuple> timeline,
|
||||||
required bool reset,
|
@Default(false) bool reset,
|
||||||
required IMap<String, IMap> state,
|
@Default(IMap.empty()) IMap<String, IMap<String, int>> state,
|
||||||
// required IMap<String, AccountData> accountData,
|
// required IMap<String, AccountData> accountData,
|
||||||
required IList<Event> events,
|
@Default(IList.empty()) IList<Event> events,
|
||||||
@Default(IMap.empty()) IMap<String, IList<ReadReceipt>> receipts,
|
@Default(IMap.empty()) IMap<String, IList<ReadReceipt>> receipts,
|
||||||
required bool dismissNotifications,
|
@Default(false) bool dismissNotifications,
|
||||||
|
@Default(true) bool hasMore,
|
||||||
// required IList<Notification> notifications,
|
// required IList<Notification> notifications,
|
||||||
}) = _Room;
|
}) = _Room;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,8 @@
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:hooks_riverpod/hooks_riverpod.dart";
|
import "package:hooks_riverpod/hooks_riverpod.dart";
|
||||||
import "package:matrix/matrix.dart";
|
|
||||||
import "package:nexus/controllers/avatar_controller.dart";
|
|
||||||
import "package:nexus/controllers/members_controller.dart";
|
import "package:nexus/controllers/members_controller.dart";
|
||||||
import "package:nexus/helpers/extensions/better_when.dart";
|
import "package:nexus/helpers/extensions/better_when.dart";
|
||||||
import "package:nexus/helpers/extensions/get_headers.dart";
|
import "package:nexus/models/room.dart";
|
||||||
import "package:nexus/widgets/avatar_or_hash.dart";
|
|
||||||
|
|
||||||
class MemberList extends ConsumerWidget {
|
class MemberList extends ConsumerWidget {
|
||||||
final Room room;
|
final Room room;
|
||||||
|
|
@ -36,26 +33,30 @@ class MemberList extends ConsumerWidget {
|
||||||
.where(
|
.where(
|
||||||
(membership) =>
|
(membership) =>
|
||||||
membership.content["membership"] ==
|
membership.content["membership"] ==
|
||||||
Membership.join.name,
|
"join", // TODO: Show invites seperately
|
||||||
)
|
)
|
||||||
.map(
|
.map(
|
||||||
(member) => ListTile(
|
(member) => ListTile(
|
||||||
onTap: () {},
|
onTap: () {},
|
||||||
leading: AvatarOrHash(
|
// leading: AvatarOrHash( TODO
|
||||||
ref
|
// ref
|
||||||
.watch(
|
// .watch(
|
||||||
AvatarController.provider(
|
// AvatarController.provider(
|
||||||
member.content["avatar_url"].toString(),
|
// member.content["avatar_url"].toString(),
|
||||||
),
|
// ),
|
||||||
)
|
// )
|
||||||
.whenOrNull(data: (data) => data),
|
// .whenOrNull(data: (data) => data),
|
||||||
member.content["displayname"].toString(),
|
// member.content["displayname"].toString(),
|
||||||
headers: room.client.headers,
|
// headers: room.client.headers,
|
||||||
),
|
// ),
|
||||||
title: Text(
|
title: Text(
|
||||||
member.content["displayname"].toString(),
|
member.content["displayname"].toString(),
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
|
subtitle: Text(
|
||||||
|
member.authorId,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -21,12 +21,12 @@ import "package:nexus/models/relation_type.dart";
|
||||||
import "package:nexus/models/requests/report_request.dart";
|
import "package:nexus/models/requests/report_request.dart";
|
||||||
import "package:nexus/widgets/chat_page/chat_box.dart";
|
import "package:nexus/widgets/chat_page/chat_box.dart";
|
||||||
import "package:nexus/widgets/chat_page/html/html.dart";
|
import "package:nexus/widgets/chat_page/html/html.dart";
|
||||||
|
import "package:nexus/widgets/chat_page/member_list.dart";
|
||||||
import "package:nexus/widgets/chat_page/room_appbar.dart";
|
import "package:nexus/widgets/chat_page/room_appbar.dart";
|
||||||
import "package:nexus/widgets/chat_page/top_widget.dart";
|
import "package:nexus/widgets/chat_page/top_widget.dart";
|
||||||
import "package:nexus/widgets/form_text_input.dart";
|
import "package:nexus/widgets/form_text_input.dart";
|
||||||
import "package:nexus/widgets/loading.dart";
|
import "package:nexus/widgets/loading.dart";
|
||||||
// import "package:dynamic_polls/dynamic_polls.dart";
|
// import "package:dynamic_polls/dynamic_polls.dart";
|
||||||
// import "package:matrix/matrix.dart";
|
|
||||||
|
|
||||||
class RoomChat extends HookConsumerWidget {
|
class RoomChat extends HookConsumerWidget {
|
||||||
final bool isDesktop;
|
final bool isDesktop;
|
||||||
|
|
@ -534,12 +534,12 @@ class RoomChat extends HookConsumerWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
// if (memberListOpened.value == true && showMembersByDefault) TODO: Member list
|
if (memberListOpened.value == true && showMembersByDefault)
|
||||||
// MemberList(room),
|
MemberList(room),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
// endDrawer: showMembersByDefault ? null : MemberList(room),
|
endDrawer: showMembersByDefault ? null : MemberList(room),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -186,7 +186,7 @@ class Sidebar extends HookConsumerWidget {
|
||||||
? null
|
? null
|
||||||
: Icon(selectedSpace.icon),
|
: Icon(selectedSpace.icon),
|
||||||
|
|
||||||
selectedSpace.title, // TODO RM
|
selectedSpace.title,
|
||||||
headers: {},
|
headers: {},
|
||||||
// space.client.headers, TODO
|
// space.client.headers, TODO
|
||||||
),
|
),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue