lots of stuff

This commit is contained in:
Henry Hiles 2025-11-14 15:50:38 -05:00
commit ba9e99a951
No known key found for this signature in database
19 changed files with 608 additions and 360 deletions

View file

@ -0,0 +1,17 @@
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:matrix/matrix.dart";
import "package:nexus/controllers/client_controller.dart";
class AvatarController extends AsyncNotifier<Uri> {
final String mxc;
AvatarController(this.mxc);
@override
Future<Uri> build() async => Uri.parse(mxc).getThumbnailUri(
await ref.watch(ClientController.provider.future),
width: 24,
height: 24,
);
static final provider = AsyncNotifierProvider.family
.autoDispose<AvatarController, Uri, String>(AvatarController.new);
}

View file

@ -1,5 +1,4 @@
import "dart:io";
import "package:flutter/foundation.dart";
import "package:matrix/matrix.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
@ -29,6 +28,8 @@ class ClientController extends AsyncNotifier<Client> {
if (client.accessToken == null) {
await client.login(
LoginType.mLoginPassword,
initialDeviceDisplayName: "Nexus Client",
deviceId: "temp", // TODO
identifier: AuthenticationUserIdentifier(user: "quadradical"),
password: File("./password.txt").readAsStringSync(),
);

View file

@ -0,0 +1,20 @@
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:matrix/matrix.dart";
class MembersController extends AsyncNotifier<List<MatrixEvent>> {
final Room room;
MembersController(this.room);
@override
Future<List<MatrixEvent>> build() async =>
(await room.client.getMembersByRoom(
room.id,
notMembership: Membership.leave,
)) ??
[];
static final provider =
AsyncNotifierProvider.family<MembersController, List<MatrixEvent>, Room>(
MembersController.new,
);
}

View file

@ -3,22 +3,26 @@ import "package:flutter_chat_core/flutter_chat_core.dart";
import "package:flutter_chat_core/flutter_chat_core.dart" as chat;
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:matrix/matrix.dart";
import "package:nexus/controllers/timeline_controller.dart";
import "package:nexus/helpers/extension_helper.dart";
class RoomChatController extends AsyncNotifier<ChatController> {
RoomChatController(this.room);
final Room room;
RoomChatController(this.room);
@override
Future<ChatController> build() async {
final timeline = await room.getTimeline();
room.client.onTimelineEvent.stream.listen((event) async {
if (event.roomId != room.id) return;
final message = await event.toMessage();
if (message != null) {
await insertMessage(message);
}
});
final timeline = await ref.watch(TimelineController.provider(room).future);
ref.onDispose(
room.client.onTimelineEvent.stream.listen((event) async {
if (event.roomId != room.id) return;
final message = await event.toMessage();
if (message != null) {
await insertMessage(message);
}
}).cancel,
);
return InMemoryChatController(
messages: (await Future.wait(
@ -29,15 +33,22 @@ class RoomChatController extends AsyncNotifier<ChatController> {
Future<void> insertMessage(Message message) async {
final controller = await future;
final oldMessage = controller.messages.firstWhereOrNull(
(element) => element.metadata?["txnId"] == message.metadata?["txnId"],
);
final oldMessage = message.metadata?["txnId"] == null
? null
: controller.messages.firstWhereOrNull(
(element) =>
element.metadata?["txnId"] == message.metadata?["txnId"],
);
return oldMessage == null
? controller.insertMessage(message)
: controller.updateMessage(oldMessage, message);
}
Future<void> loadOlder() async {
await ref.watch(TimelineController.provider(room).notifier).prev();
}
Future<void> updateMessage(Message message, Message newMessage) async {
final controller = await future;
return controller.updateMessage(message, newMessage);
@ -55,6 +66,7 @@ class RoomChatController extends AsyncNotifier<ChatController> {
id: id,
name: user.displayname,
imageSource: (await user.avatarUrl?.getThumbnailUri(
// TODO: Fix use of account avatar not room avatar
room.client,
width: 24,
height: 24,

View file

@ -30,24 +30,27 @@ class SpacesController extends AsyncNotifier<List<Space>> {
return [
Space(
client: client,
title: "Home",
children: topLevelRooms,
avatar: Icon(Icons.home),
icon: Icon(Icons.home),
fake: true,
),
Space(
client: client,
title: "Direct Messages",
children: await Future.wait(
client.rooms
.where((room) => room.isDirectChat)
.map((room) => room.fullRoom),
),
avatar: Icon(Icons.person),
icon: Icon(Icons.person),
fake: true,
),
...(await Future.wait(
topLevelSpaces.map(
(space) async => Space(
client: client,
title: space.title,
avatar: space.avatar,
children: await Future.wait(

View file

@ -0,0 +1,21 @@
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:matrix/matrix.dart";
class TimelineController extends AsyncNotifier<Timeline> {
TimelineController(this.room);
final Room room;
@override
Future<Timeline> build() => room.getTimeline();
Future<void> prev() async {
final timeline = await future;
await timeline.requestHistory();
state = AsyncValue.data(timeline);
}
static final provider =
AsyncNotifierProvider.family<TimelineController, Timeline, Room>(
TimelineController.new,
);
}