forked from Henry-Hiles/nexus
working sidebar
This commit is contained in:
parent
f51d773885
commit
7b0fea3a07
13 changed files with 491 additions and 436 deletions
|
|
@ -5,6 +5,7 @@ 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/space_edges_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";
|
||||
|
|
@ -52,9 +53,16 @@ class ClientController extends AsyncNotifier<int> {
|
|||
ref
|
||||
.watch(roomProvider.notifier)
|
||||
.update(syncData.rooms, syncData.leftRooms);
|
||||
ref
|
||||
.watch(TopLevelSpacesController.provider.notifier)
|
||||
.set(syncData.topLevelSpaces);
|
||||
if (syncData.topLevelSpaces != null) {
|
||||
ref
|
||||
.watch(TopLevelSpacesController.provider.notifier)
|
||||
.set(syncData.topLevelSpaces!);
|
||||
}
|
||||
if (syncData.spaceEdges != null) {
|
||||
ref
|
||||
.watch(SpaceEdgesController.provider.notifier)
|
||||
.set(syncData.spaceEdges!);
|
||||
}
|
||||
|
||||
// ref
|
||||
// .watch(SyncStatusController.provider.notifier)
|
||||
|
|
|
|||
|
|
@ -2,24 +2,23 @@ import "package:collection/collection.dart";
|
|||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/controllers/key_controller.dart";
|
||||
import "package:nexus/controllers/selected_space_controller.dart";
|
||||
import "package:nexus/models/full_room.dart";
|
||||
import "package:nexus/models/room.dart";
|
||||
|
||||
class SelectedRoomController extends AsyncNotifier<FullRoom?> {
|
||||
class SelectedRoomController extends Notifier<Room?> {
|
||||
@override
|
||||
Future<FullRoom?> build() async {
|
||||
final space = await ref.watch(SelectedSpaceController.provider.future);
|
||||
Room? build() {
|
||||
final space = ref.watch(SelectedSpaceController.provider);
|
||||
final selectedRoomId = ref.watch(
|
||||
KeyController.provider(KeyController.roomKey),
|
||||
);
|
||||
|
||||
return space.children.firstWhereOrNull(
|
||||
(room) => room.roomData.id == selectedRoomId,
|
||||
(room) => room.metadata?.id == selectedRoomId,
|
||||
) ??
|
||||
space.children.firstOrNull;
|
||||
}
|
||||
|
||||
static final provider =
|
||||
AsyncNotifierProvider<SelectedRoomController, FullRoom?>(
|
||||
SelectedRoomController.new,
|
||||
);
|
||||
static final provider = NotifierProvider<SelectedRoomController, Room?>(
|
||||
SelectedRoomController.new,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,12 +4,10 @@ import "package:nexus/controllers/key_controller.dart";
|
|||
import "package:nexus/controllers/spaces_controller.dart";
|
||||
import "package:nexus/models/space.dart";
|
||||
|
||||
class SelectedSpaceController extends AsyncNotifier<Space> {
|
||||
class SelectedSpaceController extends Notifier<Space> {
|
||||
@override
|
||||
Future<Space> build() async {
|
||||
final spaces = await ref.watch(
|
||||
SpacesController.provider.selectAsync((data) => data),
|
||||
);
|
||||
Space build() {
|
||||
final spaces = ref.watch(SpacesController.provider);
|
||||
final selectedSpaceId = ref.watch(
|
||||
KeyController.provider(KeyController.spaceKey),
|
||||
);
|
||||
|
|
@ -18,7 +16,7 @@ class SelectedSpaceController extends AsyncNotifier<Space> {
|
|||
spaces.first;
|
||||
}
|
||||
|
||||
static final provider = AsyncNotifierProvider<SelectedSpaceController, Space>(
|
||||
static final provider = NotifierProvider<SelectedSpaceController, Space>(
|
||||
SelectedSpaceController.new,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
15
lib/controllers/space_edges_controller.dart
Normal file
15
lib/controllers/space_edges_controller.dart
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/models/space_edge.dart";
|
||||
|
||||
class SpaceEdgesController extends Notifier<IMap<String, IList<SpaceEdge>>> {
|
||||
@override
|
||||
IMap<String, IList<SpaceEdge>> build() => const IMap.empty();
|
||||
|
||||
void set(IMap<String, IList<SpaceEdge>> newEdges) => state = newEdges;
|
||||
|
||||
static final provider =
|
||||
NotifierProvider<SpaceEdgesController, IMap<String, IList<SpaceEdge>>>(
|
||||
SpaceEdgesController.new,
|
||||
);
|
||||
}
|
||||
|
|
@ -1,55 +1,94 @@
|
|||
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/controllers/rooms_controller.dart";
|
||||
import "package:nexus/controllers/top_level_spaces_controller.dart";
|
||||
import "package:nexus/controllers/space_edges_controller.dart";
|
||||
import "package:nexus/models/space.dart";
|
||||
import "package:nexus/models/room.dart";
|
||||
import "package:nexus/models/space_edge.dart";
|
||||
|
||||
class SpacesController extends AsyncNotifier<IList<Space>> {
|
||||
class SpacesController extends Notifier<IList<Space>> {
|
||||
@override
|
||||
Future<IList<Space>> build() async {
|
||||
final topLevelSpaceIds = ref.watch(TopLevelSpacesController.provider);
|
||||
IList<Space> build() {
|
||||
final rooms = ref.watch(RoomsController.provider);
|
||||
final topLevelSpaceIds = ref.watch(TopLevelSpacesController.provider);
|
||||
final spaceEdges = ref.watch(SpaceEdgesController.provider);
|
||||
|
||||
final topLevelSpaces = topLevelSpaceIds
|
||||
.map((id) => rooms[id])
|
||||
.nonNulls
|
||||
.toIList();
|
||||
ISet<String> collectChildIds(String spaceId) {
|
||||
ISet<String> result = ISet<String>();
|
||||
void walk(String currentId) {
|
||||
final children = spaceEdges[currentId] ?? IList<SpaceEdge>();
|
||||
for (final edge in children) {
|
||||
final childId = edge.childId;
|
||||
if (!result.contains(childId)) {
|
||||
result = result.add(childId);
|
||||
walk(childId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
walk(spaceId);
|
||||
return result;
|
||||
}
|
||||
|
||||
final spaceIdToChildren = IMap.fromEntries(
|
||||
topLevelSpaceIds.map((spaceId) {
|
||||
final children = collectChildIds(
|
||||
spaceId,
|
||||
).map((id) => rooms[id]).nonNulls.toIList();
|
||||
return MapEntry(spaceId, children);
|
||||
}),
|
||||
);
|
||||
|
||||
final allNestedRoomIds = spaceIdToChildren.values
|
||||
.expand((l) => l)
|
||||
.map((r) => rooms.entries.firstWhere((e) => e.value == r).key)
|
||||
.toISet();
|
||||
|
||||
final dmRooms = rooms.values
|
||||
.where((room) => room.metadata?.dmUserId != null)
|
||||
.toIList();
|
||||
|
||||
final topLevelRooms = rooms.values
|
||||
.where((room) => room.metadata?.dmUserId == null)
|
||||
final homeRooms = rooms.entries
|
||||
.where(
|
||||
(room) => spaceRooms.every(
|
||||
(space) =>
|
||||
space.spaceChildren.every((child) => child.roomId != room.id),
|
||||
),
|
||||
(e) =>
|
||||
e.value.metadata?.dmUserId == null &&
|
||||
!allNestedRoomIds.contains(e.key) &&
|
||||
!topLevelSpaceIds.contains(e.key),
|
||||
)
|
||||
.map((e) => e.value)
|
||||
.toIList();
|
||||
|
||||
// 4️⃣ Combine all into a single IList
|
||||
return IList([
|
||||
Space(
|
||||
id: "home",
|
||||
title: "Home",
|
||||
children: topLevelRooms,
|
||||
icon: Icons.home,
|
||||
),
|
||||
final topLevelSpacesList = topLevelSpaceIds
|
||||
.map((id) {
|
||||
final room = rooms[id];
|
||||
if (room == null) return null;
|
||||
|
||||
final children = spaceIdToChildren[id] ?? IList<Room>();
|
||||
return Space(
|
||||
id: id,
|
||||
title: room.metadata?.name ?? "Unnamed Room",
|
||||
room: room,
|
||||
children: children,
|
||||
);
|
||||
})
|
||||
.nonNulls
|
||||
.toIList();
|
||||
|
||||
return <Space>[
|
||||
Space(id: "home", title: "Home", icon: Icons.home, children: homeRooms),
|
||||
Space(
|
||||
id: "dms",
|
||||
title: "Direct Messages",
|
||||
icon: Icons.people,
|
||||
children: dmRooms,
|
||||
icon: Icons.person,
|
||||
),
|
||||
...topLevelSpaces,
|
||||
]);
|
||||
...topLevelSpacesList,
|
||||
].toIList();
|
||||
}
|
||||
|
||||
static final provider = AsyncNotifierProvider<SpacesController, IList<Space>>(
|
||||
static final provider = NotifierProvider<SpacesController, IList<Space>>(
|
||||
SpacesController.new,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue