wip
This commit is contained in:
parent
97f2673b55
commit
c084bc4caf
12 changed files with 182 additions and 156 deletions
|
|
@ -1,11 +1,12 @@
|
|||
import "dart:convert";
|
||||
import "dart:developer";
|
||||
import "dart:ffi";
|
||||
import "dart:isolate";
|
||||
import "package:ffi/ffi.dart";
|
||||
import "package:flutter/foundation.dart";
|
||||
import "package:nexus/controllers/client_state_controller.dart";
|
||||
import "package:nexus/controllers/rooms_controller.dart";
|
||||
import "package:nexus/controllers/sync_status_controller.dart";
|
||||
import "package:nexus/controllers/top_level_spaces_controller.dart";
|
||||
import "package:nexus/helpers/extensions/gomuks_buffer.dart";
|
||||
import "package:nexus/models/client_state.dart";
|
||||
import "package:nexus/models/login.dart";
|
||||
|
|
@ -18,55 +19,64 @@ class ClientController extends AsyncNotifier<int> {
|
|||
@override
|
||||
Future<int> build() async {
|
||||
final handle = await Isolate.run(GomuksInit);
|
||||
ref.onDispose(() => GomuksDestroy(handle));
|
||||
|
||||
final errorCode = GomuksStart(
|
||||
handle,
|
||||
NativeCallable<
|
||||
Void Function(Pointer<Char>, Int64, GomuksOwnedBuffer)
|
||||
>.listener((
|
||||
Pointer<Char> command,
|
||||
int requestId,
|
||||
GomuksOwnedBuffer data,
|
||||
) {
|
||||
try {
|
||||
final muksEventType = command.cast<Utf8>().toDartString();
|
||||
debugPrint("Handling $muksEventType...");
|
||||
final Map<String, dynamic> decodedMuksEvent = data.toJson();
|
||||
final callable =
|
||||
NativeCallable<
|
||||
Void Function(Pointer<Char>, Int64, GomuksOwnedBuffer)
|
||||
>.listener((
|
||||
Pointer<Char> command,
|
||||
int requestId,
|
||||
GomuksOwnedBuffer data,
|
||||
) {
|
||||
try {
|
||||
final muksEventType = command.cast<Utf8>().toDartString();
|
||||
debugPrint("Handling $muksEventType...");
|
||||
final Map<String, dynamic> decodedMuksEvent = data.toJson();
|
||||
|
||||
switch (muksEventType) {
|
||||
case "client_state":
|
||||
ref
|
||||
.watch(ClientStateController.provider.notifier)
|
||||
.set(ClientState.fromJson(decodedMuksEvent));
|
||||
break;
|
||||
case "sync_status":
|
||||
ref
|
||||
.watch(SyncStatusController.provider.notifier)
|
||||
.set(SyncStatus.fromJson(decodedMuksEvent));
|
||||
break;
|
||||
case "sync_complete":
|
||||
final syncData = SyncData.fromJson(decodedMuksEvent);
|
||||
debugPrint(jsonEncode(syncData.toJson()));
|
||||
switch (muksEventType) {
|
||||
case "client_state":
|
||||
ref
|
||||
.watch(ClientStateController.provider.notifier)
|
||||
.set(ClientState.fromJson(decodedMuksEvent));
|
||||
break;
|
||||
case "sync_status":
|
||||
ref
|
||||
.watch(SyncStatusController.provider.notifier)
|
||||
.set(SyncStatus.fromJson(decodedMuksEvent));
|
||||
break;
|
||||
case "sync_complete":
|
||||
final syncData = SyncData.fromJson(decodedMuksEvent);
|
||||
final roomProvider = RoomsController.provider;
|
||||
|
||||
// ref
|
||||
// .watch(SyncStatusController.provider.notifier)
|
||||
// .set(SyncStatus.fromJson(decodedMuksEvent));
|
||||
break;
|
||||
case "typing":
|
||||
//TODO: IMPL
|
||||
break;
|
||||
default:
|
||||
debugPrint("Unhandled event: $muksEventType");
|
||||
}
|
||||
debugPrint("Finished handling $muksEventType...");
|
||||
} catch (error, stackTrace) {
|
||||
debugger();
|
||||
debugPrintStack(stackTrace: stackTrace, label: error.toString());
|
||||
if (syncData.clearState) ref.invalidate(roomProvider);
|
||||
ref
|
||||
.watch(roomProvider.notifier)
|
||||
.update(syncData.rooms, syncData.leftRooms);
|
||||
ref
|
||||
.watch(TopLevelSpacesController.provider.notifier)
|
||||
.set(syncData.topLevelSpaces);
|
||||
|
||||
// ref
|
||||
// .watch(SyncStatusController.provider.notifier)
|
||||
// .set(SyncStatus.fromJson(decodedMuksEvent));
|
||||
break;
|
||||
case "typing":
|
||||
//TODO: IMPL
|
||||
break;
|
||||
default:
|
||||
debugPrint("Unhandled event: $muksEventType");
|
||||
}
|
||||
})
|
||||
.nativeFunction,
|
||||
);
|
||||
debugPrint("Finished handling $muksEventType...");
|
||||
} catch (error, stackTrace) {
|
||||
debugger();
|
||||
debugPrintStack(stackTrace: stackTrace, label: error.toString());
|
||||
}
|
||||
});
|
||||
|
||||
ref.onDispose(() => GomuksDestroy(handle));
|
||||
ref.onDispose(callable.close);
|
||||
|
||||
final errorCode = GomuksStart(handle, callable.nativeFunction);
|
||||
|
||||
if (errorCode == 0) return handle;
|
||||
throw Exception("GomuksStart returned error code $errorCode");
|
||||
|
|
|
|||
|
|
@ -1,23 +1,57 @@
|
|||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/controllers/client_controller.dart";
|
||||
import "package:nexus/helpers/extensions/get_full_room.dart";
|
||||
import "package:nexus/models/full_room.dart";
|
||||
import "package:nexus/models/read_receipt.dart";
|
||||
import "package:nexus/models/room.dart";
|
||||
|
||||
class RoomsController extends AsyncNotifier<IList<FullRoom>> {
|
||||
class RoomsController extends Notifier<IMap<String, Room>> {
|
||||
@override
|
||||
Future<IList<FullRoom>> build() async {
|
||||
final client = await ref.watch(ClientController.provider.future);
|
||||
IMap<String, Room> build() => const IMap.empty();
|
||||
|
||||
ref.onDispose(
|
||||
client.onSync.stream.listen((_) => ref.invalidateSelf()).cancel,
|
||||
void update(IMap<String, Room> rooms, ISet<String> leftRooms) {
|
||||
final merged = rooms.entries.fold(state, (acc, entry) {
|
||||
final roomId = entry.key;
|
||||
final incoming = entry.value;
|
||||
final existing = acc[roomId];
|
||||
|
||||
return acc.add(
|
||||
roomId,
|
||||
existing?.copyWith(
|
||||
metadata: incoming.metadata ?? existing.metadata,
|
||||
events: existing.events.addAll(incoming.events),
|
||||
state: incoming.state.entries.fold(
|
||||
existing.state,
|
||||
(stateAcc, event) => stateAcc.add(
|
||||
event.key,
|
||||
(stateAcc[event.key] ?? IMap<dynamic, dynamic>()).addAll(
|
||||
event.value,
|
||||
),
|
||||
),
|
||||
),
|
||||
timeline: incoming.reset
|
||||
? incoming.timeline
|
||||
: existing.timeline.addAll(incoming.timeline),
|
||||
receipts: incoming.receipts.entries.fold(
|
||||
existing.receipts,
|
||||
(receiptAcc, event) => receiptAcc.add(
|
||||
event.key,
|
||||
(receiptAcc[event.key] ?? IList<ReadReceipt>()).addAll(
|
||||
event.value,
|
||||
),
|
||||
),
|
||||
),
|
||||
) ??
|
||||
incoming,
|
||||
);
|
||||
});
|
||||
|
||||
final prunedList = leftRooms.fold(
|
||||
merged,
|
||||
(acc, roomId) => acc.remove(roomId),
|
||||
);
|
||||
|
||||
return IList(await Future.wait(client.rooms.map((room) => room.fullRoom)));
|
||||
state = prunedList;
|
||||
}
|
||||
|
||||
static final provider =
|
||||
AsyncNotifierProvider<RoomsController, IList<FullRoom>>(
|
||||
RoomsController.new,
|
||||
);
|
||||
static final provider = NotifierProvider<RoomsController, IMap<String, Room>>(
|
||||
RoomsController.new,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,72 +2,50 @@ import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
|||
import "package:flutter/material.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/controllers/client_controller.dart";
|
||||
import "package:nexus/helpers/extensions/get_full_room.dart";
|
||||
import "package:nexus/helpers/extensions/room_to_children.dart";
|
||||
import "package:nexus/controllers/rooms_controller.dart";
|
||||
import "package:nexus/controllers/top_level_spaces_controller.dart";
|
||||
import "package:nexus/models/space.dart";
|
||||
|
||||
class SpacesController extends AsyncNotifier<IList<Space>> {
|
||||
@override
|
||||
Future<IList<Space>> build() async {
|
||||
final client = await ref.watch(ClientController.provider.future);
|
||||
final topLevelSpaceIds = ref.watch(TopLevelSpacesController.provider);
|
||||
final rooms = ref.watch(RoomsController.provider);
|
||||
|
||||
ref.onDispose(
|
||||
client.onSync.stream.listen((_) => ref.invalidateSelf()).cancel,
|
||||
);
|
||||
final topLevelSpaces = topLevelSpaceIds
|
||||
.map((id) => rooms[id])
|
||||
.nonNulls
|
||||
.toIList();
|
||||
|
||||
final topLevel = IList(
|
||||
await Future.wait(
|
||||
client.rooms
|
||||
.where((room) => !room.isDirectChat)
|
||||
.where(
|
||||
(room) => client.rooms
|
||||
.where((room) => room.isSpace)
|
||||
.every(
|
||||
(match) => match.spaceChildren.every(
|
||||
(child) => child.roomId != room.id,
|
||||
),
|
||||
),
|
||||
)
|
||||
.map((room) => room.fullRoom),
|
||||
),
|
||||
);
|
||||
final dmRooms = rooms.values
|
||||
.where((room) => room.metadata?.dmUserId != null)
|
||||
.toIList();
|
||||
|
||||
final topLevelSpaces = topLevel.where((r) => r.roomData.isSpace).toIList();
|
||||
final topLevelRooms = topLevel.where((r) => !r.roomData.isSpace).toIList();
|
||||
final topLevelRooms = rooms.values
|
||||
.where((room) => room.metadata?.dmUserId == null)
|
||||
.where(
|
||||
(room) => spaceRooms.every(
|
||||
(space) =>
|
||||
space.spaceChildren.every((child) => child.roomId != room.id),
|
||||
),
|
||||
)
|
||||
.toIList();
|
||||
|
||||
// 4️⃣ Combine all into a single IList
|
||||
return IList([
|
||||
Space(
|
||||
client: client,
|
||||
title: "Home",
|
||||
id: "home",
|
||||
title: "Home",
|
||||
children: topLevelRooms,
|
||||
icon: Icons.home,
|
||||
),
|
||||
Space(
|
||||
client: client,
|
||||
title: "Direct Messages",
|
||||
id: "dms",
|
||||
children: IList(
|
||||
await Future.wait(
|
||||
client.rooms
|
||||
.where((room) => room.isDirectChat)
|
||||
.map((room) => room.fullRoom),
|
||||
),
|
||||
),
|
||||
title: "Direct Messages",
|
||||
children: dmRooms,
|
||||
icon: Icons.person,
|
||||
),
|
||||
...(await Future.wait(
|
||||
topLevelSpaces.map(
|
||||
(space) async => Space(
|
||||
client: client,
|
||||
title: space.title,
|
||||
avatar: space.avatar,
|
||||
id: space.roomData.id,
|
||||
roomData: space.roomData,
|
||||
children: IList(await space.roomData.getAllChildren()),
|
||||
),
|
||||
),
|
||||
)),
|
||||
...topLevelSpaces,
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
|||
14
lib/controllers/top_level_spaces_controller.dart
Normal file
14
lib/controllers/top_level_spaces_controller.dart
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
|
||||
class TopLevelSpacesController extends Notifier<IList<String>> {
|
||||
@override
|
||||
IList<String> build() => const IList.empty();
|
||||
|
||||
void set(IList<String> newSpaces) => state = newSpaces;
|
||||
|
||||
static final provider =
|
||||
NotifierProvider<TopLevelSpacesController, IList<String>>(
|
||||
TopLevelSpacesController.new,
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue