treewide cleanups
This commit is contained in:
parent
53d9c2b1e6
commit
853116ab2f
16 changed files with 88 additions and 138 deletions
|
|
@ -243,17 +243,14 @@ class RoomChatController(final ChatParams info)
|
|||
ref.invalidate(provider);
|
||||
}
|
||||
|
||||
var taggedMessage = text;
|
||||
|
||||
for (final tag in tags) {
|
||||
final escaped = RegExp.escape(tag.id);
|
||||
final pattern = RegExp(r"@+(" + escaped + r")(#[^#]*#)?");
|
||||
|
||||
taggedMessage = taggedMessage.replaceAllMapped(
|
||||
pattern,
|
||||
// Replaces each formatted tag, like "@id#name#", with its ID
|
||||
final taggedMessage = tags.fold(
|
||||
text,
|
||||
(message, tag) => message.replaceAllMapped(
|
||||
RegExp(r"@+(" + RegExp.escape(tag.id) + r")(#[^#]*#)?"),
|
||||
(match) => match.group(1)!,
|
||||
);
|
||||
}
|
||||
),
|
||||
);
|
||||
|
||||
final client = ref.read(ClientController.provider.notifier);
|
||||
final event = await client.sendMessage(
|
||||
|
|
|
|||
|
|
@ -25,55 +25,50 @@ class SpacesController extends AsyncNotifier<IList<Space>> {
|
|||
MapEntry(spaceId, edges.map((edge) => edge.childId).toList()),
|
||||
);
|
||||
|
||||
Set<String> collectDescendants(String startId) {
|
||||
final visited = <String>{};
|
||||
final stack = [startId];
|
||||
|
||||
while (stack.isNotEmpty) {
|
||||
final current = stack.removeLast();
|
||||
final children = childrenById[current] ?? const [];
|
||||
|
||||
for (final child in children) {
|
||||
if (visited.add(child)) {
|
||||
stack.add(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return visited;
|
||||
}
|
||||
/// Everything under [spaceId], however deep, skipping any already
|
||||
/// [visited] so cycles end.
|
||||
ISet<String> collectDescendants(
|
||||
String spaceId, [
|
||||
ISet<String> visited = const .empty(),
|
||||
]) => (childrenById[spaceId] ?? const []).fold(
|
||||
visited,
|
||||
(visited, childId) => visited.contains(childId)
|
||||
? visited
|
||||
: collectDescendants(childId, visited.add(childId)),
|
||||
);
|
||||
|
||||
Space buildSpace(String spaceId) {
|
||||
final space = rooms[spaceId];
|
||||
final directChildrenIds = childrenById[spaceId] ?? const [];
|
||||
|
||||
final directRooms = <Room>[];
|
||||
final subSpaces = <Subspace>[];
|
||||
|
||||
for (final childId in directChildrenIds) {
|
||||
final room = rooms[childId];
|
||||
if (room == null) continue;
|
||||
|
||||
if (childrenById.containsKey(childId)) {
|
||||
final descendants = collectDescendants(childId);
|
||||
|
||||
subSpaces.add(
|
||||
.new(
|
||||
room: room,
|
||||
children: .new(descendants.map((id) => rooms[id]).nonNulls),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
directRooms.add(room);
|
||||
}
|
||||
}
|
||||
|
||||
return .new(
|
||||
id: spaceId,
|
||||
room: space,
|
||||
title: space?.metadata?.name ?? "Unnamed Space",
|
||||
children: .new(directRooms),
|
||||
subSpaces: .new(subSpaces),
|
||||
children: .new(
|
||||
directChildrenIds
|
||||
.where((childId) => !childrenById.containsKey(childId))
|
||||
.map((childId) => rooms[childId])
|
||||
.nonNulls,
|
||||
),
|
||||
subSpaces: .new(
|
||||
directChildrenIds
|
||||
.where(childrenById.containsKey)
|
||||
.map(
|
||||
(childId) => switch (rooms[childId]) {
|
||||
final room? => Subspace(
|
||||
room: room,
|
||||
children: .new(
|
||||
collectDescendants(childId)
|
||||
.map((id) => rooms[id])
|
||||
.nonNulls,
|
||||
),
|
||||
),
|
||||
null => null,
|
||||
},
|
||||
)
|
||||
.nonNulls,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,53 +1,48 @@
|
|||
import "package:collection/collection.dart";
|
||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/controllers/client_state.dart";
|
||||
import "package:nexus/models/content/content.dart";
|
||||
import "package:nexus/models/content/membership.dart";
|
||||
import "package:nexus/models/content/power_levels.dart";
|
||||
import "package:nexus/models/event.dart";
|
||||
import "package:nexus/models/room.dart";
|
||||
|
||||
class ViaController(final Room room) extends Notifier<String> {
|
||||
@override
|
||||
String build() {
|
||||
final servers = <String>{};
|
||||
final powerLevelUsers =
|
||||
switch (room.state[EventType.powerLevels.type]?[""]) {
|
||||
final rowId? => switch (room.events[rowId]?.content) {
|
||||
PowerLevelsContent(:final users) => users.keys.toIList(),
|
||||
_ => null,
|
||||
},
|
||||
null => null,
|
||||
} ??
|
||||
.new([]);
|
||||
|
||||
void addUserId(String? userId) {
|
||||
final server = userId?.split(":").lastOrNull;
|
||||
if (server != null) {
|
||||
servers.add(server);
|
||||
}
|
||||
}
|
||||
final joinedMembers =
|
||||
(room.state[EventType.membership.type]?.values ?? const [])
|
||||
.map(
|
||||
(rowId) => switch (room.events[rowId]) {
|
||||
Event(
|
||||
stateKey: final userId?,
|
||||
content: MembershipContent(status: .join),
|
||||
) =>
|
||||
userId,
|
||||
_ => null,
|
||||
},
|
||||
)
|
||||
.nonNulls
|
||||
.toIList();
|
||||
|
||||
addUserId(ref.watch(ClientStateController.provider)?.userId);
|
||||
|
||||
final powerLevelsEventId = room.state[EventType.powerLevels.type]?[""];
|
||||
final powerLevels = powerLevelsEventId == null
|
||||
? null
|
||||
: room.events[powerLevelsEventId];
|
||||
|
||||
if (powerLevels?.content case PowerLevelsContent(:final users)) {
|
||||
for (final userId in users.keys) {
|
||||
addUserId(userId);
|
||||
if (servers.length >= 5) break;
|
||||
}
|
||||
}
|
||||
|
||||
final members = room.state[EventType.membership.type]?.values.toIList();
|
||||
for (var i = 0; servers.length < 5; i++) {
|
||||
final membershipEventId = members?.getOrNull(i);
|
||||
final member = membershipEventId == null
|
||||
? null
|
||||
: room.events[membershipEventId];
|
||||
|
||||
if (member?.content case MembershipContent(:final status)) {
|
||||
if (status == .join) {
|
||||
addUserId(member?.stateKey);
|
||||
}
|
||||
}
|
||||
|
||||
if (members?.getOrNull(i) == null) break;
|
||||
}
|
||||
final servers = [?ref.watch(ClientStateController.provider)?.userId]
|
||||
.toIList()
|
||||
.addAll(powerLevelUsers)
|
||||
.addAll(joinedMembers)
|
||||
.map((userId) => userId.substring(userId.indexOf(":") + 1))
|
||||
.whereNoDuplicates()
|
||||
.take(5)
|
||||
.toISet();
|
||||
|
||||
return servers.isEmpty
|
||||
? ""
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ class const App({super.key}) extends StatelessWidget {
|
|||
.watch(SettingsController.provider)
|
||||
.maybeWhen(
|
||||
data: (settings) => settings.theme,
|
||||
orElse: () => ThemeMode.system,
|
||||
orElse: () => .system,
|
||||
),
|
||||
home: child,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:freezed_annotation/freezed_annotation.dart";
|
||||
import "package:flutter/widgets.dart";
|
||||
part "emoji.freezed.dart";
|
||||
part "emoji.g.dart";
|
||||
|
||||
@Freezed(toJson: false, fromJson: false)
|
||||
@JsonSerializable(createToJson: false)
|
||||
class Emoji({
|
||||
@JsonKey(
|
||||
fromJson: Emoji.widgetFromJson,
|
||||
readValue: Emoji.readWidgetValueFromJson,
|
||||
)
|
||||
required final Widget widget,
|
||||
@JsonKey(name: "emoji") required final String value,
|
||||
required final IList<String> aliases,
|
||||
required final String description,
|
||||
required final IList<String> tags,
|
||||
}) with _$Emoji {
|
||||
static Widget widgetFromJson(String emoji) => Text(emoji);
|
||||
|
||||
static String readWidgetValueFromJson(Map<dynamic, dynamic> json, _) =>
|
||||
json["emoji"];
|
||||
factory Emoji.fromJson(Map<String, Object?> json) => _$EmojiFromJson(json);
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:freezed_annotation/freezed_annotation.dart";
|
||||
import "package:nexus/models/emoji.dart";
|
||||
import "package:flutter/widgets.dart";
|
||||
part "emoji_category.freezed.dart";
|
||||
|
||||
@Freezed(toJson: false, fromJson: false)
|
||||
class EmojiCategory({
|
||||
required final Widget icon,
|
||||
required final String name,
|
||||
required final IList<Emoji> emojis,
|
||||
}) with _$EmojiCategory;
|
||||
|
|
@ -399,11 +399,11 @@ class const Composer(
|
|||
|
||||
if (!shiftPressed) {
|
||||
send();
|
||||
return KeyEventResult.handled;
|
||||
return .handled;
|
||||
}
|
||||
}
|
||||
|
||||
return KeyEventResult.ignored;
|
||||
return .ignored;
|
||||
},
|
||||
// Overrides the keyboard shortcut for pasting
|
||||
child: Actions(
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class const RelationPreview(
|
|||
onPressed: toggleShouldMention,
|
||||
child: Text(
|
||||
shouldMention ? "@On" : "@Off",
|
||||
style: TextStyle(
|
||||
style: .new(
|
||||
fontWeight: .w900,
|
||||
color: shouldMention ? null : Theme.of(context).disabledColor,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ class const Html(
|
|||
src == null
|
||||
? SizedBox.shrink()
|
||||
: InlineCustomWidget(
|
||||
alignment: PlaceholderAlignment.middle,
|
||||
alignment: .middle,
|
||||
child: ExpandableImage(
|
||||
.new(mxc: src),
|
||||
downloadFilename: src.pathSegments.last,
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ class const MessageDisplayname(
|
|||
final children => Row(
|
||||
spacing: 4,
|
||||
mainAxisSize: .min,
|
||||
children: [for (final child in children) Flexible(child: child)],
|
||||
children: children.map((child) => Flexible(child: child)).toList(),
|
||||
),
|
||||
},
|
||||
),
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ final class const MessageImage(
|
|||
child: Image(
|
||||
image: MxcImage(ref, request),
|
||||
width: info?.width?.toDouble(),
|
||||
fit: BoxFit.fitWidth,
|
||||
fit: .fitWidth,
|
||||
loadingBuilder: (_, child, loadingProgress) =>
|
||||
loadingProgress == null
|
||||
? child
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ class const NotificationsList({super.key})
|
|||
listController: listController.value,
|
||||
controller: scrollController,
|
||||
itemCount: value.length,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
padding: const .symmetric(
|
||||
horizontal: 8,
|
||||
vertical: 12,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ final class const RoomMenuButton(
|
|||
),
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.logout, color: danger),
|
||||
title: Text("Leave", style: TextStyle(color: danger)),
|
||||
title: Text("Leave", style: .new(color: danger)),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ final class const DialogListTile<T>({
|
|||
child: Chip(
|
||||
label: Text(
|
||||
value is T ? getName(value as T) : "None",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
overflow: .ellipsis,
|
||||
style: onChanged == null || saving.active
|
||||
? .new(color: Colors.grey)
|
||||
: null,
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ final class const RadioSheet<T>({
|
|||
onChanged: (value) => chosen.value = (value as T,),
|
||||
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisSize: .min,
|
||||
children: options
|
||||
.map(
|
||||
(option) => RadioListTile<T>(
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ class const SyncStatusBanner({super.key}) extends ConsumerWidget {
|
|||
banner.title,
|
||||
maxLines: 1,
|
||||
overflow: .ellipsis,
|
||||
style: TextStyle(
|
||||
style: .new(
|
||||
color: banner.foreground,
|
||||
fontWeight: .bold,
|
||||
),
|
||||
|
|
|
|||
Loading…
Reference in a new issue