Remove flutter chat #26

Manually merged
Henry-Hiles merged 108 commits from remove-flutter-chat into main 2026-05-22 15:26:28 -04:00
10 changed files with 69 additions and 101 deletions
Showing only changes of commit ad14f2207e - Show all commits

Fixes to power level controller

Henry Hiles 2026-05-16 21:21:33 -04:00
Signed by: Henry-Hiles
SSH key fingerprint: SHA256:VKQUdS31Q90KvX7EkKMHMBpUspcmItAh86a+v7PGiIs

View file

@ -26,37 +26,32 @@ class PowerLevelController extends Notifier<bool> {
content.users[userId] ?? content.usersDefault; content.users[userId] ?? content.usersDefault;
final userLevel = powerLevelOf(user); final userLevel = powerLevelOf(user);
final targetLevel = config.targetUser != null
? powerLevelOf(config.targetUser!)
: null;
if (config.action != null) { return switch (config) {
return switch (config.action!) { EventPowerLevelConfig(:final eventType) =>
MembershipAction.invite => userLevel >= content.invite, userLevel > (content.events[eventType.type] ?? content.eventsDefault),
MembershipActionPowerLevelConfig(:final action, :final targetUser) =>
switch (action) {
MembershipAction.invite => userLevel >= content.invite,
MembershipAction.kick => MembershipAction.kick =>
targetLevel != null && userLevel >= content.kick && userLevel > powerLevelOf(targetUser),
userLevel >= content.kick &&
userLevel > targetLevel,
MembershipAction.ban => MembershipAction.ban =>
targetLevel != null && userLevel >= content.ban && userLevel > powerLevelOf(targetUser),
userLevel >= content.ban &&
userLevel > targetLevel,
MembershipAction.unban => userLevel >= content.ban, MembershipAction.unban => userLevel >= content.ban,
}; },
}
if (config.eventType == "m.room.redaction") { StatePowerLevelConfig(:final eventType) =>
return userLevel >= content.redact; userLevel > (content.events[eventType.type] ?? content.stateDefault),
} RedactPowerLevelConfig(:final targetUser) =>
userLevel >=
final requiredLevel = (targetUser == user
content.events[config.eventType] ?? ? (content.events[EventType.redaction.type] ??
(config.isStateEvent ? content.stateDefault : content.eventsDefault); content.eventsDefault)
: content.redact),
return userLevel >= requiredLevel; };
} }
static final provider = NotifierProvider.autoDispose static final provider = NotifierProvider.autoDispose

View file

@ -1,28 +0,0 @@
import "package:freezed_annotation/freezed_annotation.dart";
import "package:nexus/models/event.dart";
import "package:nexus/models/room.dart";
part "message_config.freezed.dart";
part "message_config.g.dart";
@freezed
abstract class MessageConfig with _$MessageConfig {
const MessageConfig._();
const factory MessageConfig({
@Default(false) bool alwaysReturn,
@Default(false) bool includeEdits,
required Room room,
required Event event,
}) = _MessageConfig;
@override
bool operator ==(Object other) =>
other.runtimeType == runtimeType &&
other is MessageConfig &&
other.event == event;
@override
int get hashCode => Object.hash(runtimeType, event);
factory MessageConfig.fromJson(Map<String, Object?> json) =>
_$MessageConfigFromJson(json);
}

View file

@ -1,17 +0,0 @@
import "package:fast_immutable_collections/fast_immutable_collections.dart";
import "package:freezed_annotation/freezed_annotation.dart";
import "package:nexus/models/event.dart";
import "package:nexus/models/room.dart";
part "messages_config.freezed.dart";
part "messages_config.g.dart";
@freezed
abstract class MessagesConfig with _$MessagesConfig {
const factory MessagesConfig({
required Room room,
required IList<Event> events,
}) = _MessagesConfig;
factory MessagesConfig.fromJson(Map<String, Object?> json) =>
_$MessagesConfigFromJson(json);
}

View file

@ -1,17 +1,21 @@
import "package:freezed_annotation/freezed_annotation.dart"; import "package:freezed_annotation/freezed_annotation.dart";
import "package:nexus/models/content/content.dart";
import "package:nexus/models/requests/membership_action.dart"; import "package:nexus/models/requests/membership_action.dart";
part "power_level_config.freezed.dart"; part "power_level_config.freezed.dart";
part "power_level_config.g.dart";
@freezed @freezed
abstract class PowerLevelConfig with _$PowerLevelConfig { sealed class PowerLevelConfig with _$PowerLevelConfig {
const factory PowerLevelConfig({ const factory PowerLevelConfig({required EventType eventType}) =
@Default(false) bool isStateEvent, EventPowerLevelConfig;
required String eventType,
MembershipAction? action,
String? targetUser,
}) = _PowerLevelConfig;
factory PowerLevelConfig.fromJson(Map<String, Object?> json) => const factory PowerLevelConfig.membershipAction({
_$PowerLevelConfigFromJson(json); required MembershipAction action,
required String targetUser,
}) = MembershipActionPowerLevelConfig;
const factory PowerLevelConfig.state({required EventType eventType}) =
StatePowerLevelConfig;
const factory PowerLevelConfig.redact({required String targetUser}) =
RedactPowerLevelConfig;
} }

View file

@ -11,6 +11,7 @@ import "package:nexus/models/content/name.dart";
import "package:nexus/models/content/pinned_events.dart"; import "package:nexus/models/content/pinned_events.dart";
import "package:nexus/models/content/power_levels.dart"; import "package:nexus/models/content/power_levels.dart";
import "package:nexus/models/content/reaction.dart"; import "package:nexus/models/content/reaction.dart";
import "package:nexus/models/content/redaction.dart";
import "package:nexus/models/content/server_acl.dart"; import "package:nexus/models/content/server_acl.dart";
import "package:nexus/models/content/topic.dart"; import "package:nexus/models/content/topic.dart";
@ -30,6 +31,7 @@ class Content {
@JsonEnum(valueField: "type") @JsonEnum(valueField: "type")
enum EventType { enum EventType {
encrypted("m.room.encrypted", Content.fromJson), encrypted("m.room.encrypted", Content.fromJson),
redaction("m.room.redaction", RedactionContent.fromJson),
encryption("m.room.encryption", EncryptionContent.fromJson), encryption("m.room.encryption", EncryptionContent.fromJson),
membership("m.room.member", MembershipContent.fromJson), membership("m.room.member", MembershipContent.fromJson),
create("m.room.create", CreateContent.fromJson), create("m.room.create", CreateContent.fromJson),

View file

@ -14,7 +14,7 @@ abstract class MessageContent extends Content with _$MessageContent {
required String body, required String body,
String? format, String? format,
String? formattedBody, String? formattedBody,
}) = _TextMessageContent; }) = TextMessageContent;
@FreezedUnionValue("m.image") @FreezedUnionValue("m.image")
const factory MessageContent.image({ const factory MessageContent.image({
@ -25,7 +25,7 @@ abstract class MessageContent extends Content with _$MessageContent {
String? filename, String? filename,
ImageInfo? info, ImageInfo? info,
String? url, String? url,
}) = _ImageMessageContent; }) = ImageMessageContent;
@FreezedUnionValue("m.file") @FreezedUnionValue("m.file")
const factory MessageContent.file({ const factory MessageContent.file({
@ -36,7 +36,7 @@ abstract class MessageContent extends Content with _$MessageContent {
String? filename, String? filename,
FileInfo? info, FileInfo? info,
String? url, String? url,
}) = _FileMessageContent; }) = FileMessageContent;
@FreezedUnionValue("m.audio") @FreezedUnionValue("m.audio")
const factory MessageContent.audio({ const factory MessageContent.audio({
@ -47,7 +47,7 @@ abstract class MessageContent extends Content with _$MessageContent {
String? filename, String? filename,
AudioInfo? info, AudioInfo? info,
String? url, String? url,
}) = _AudioMessageContent; }) = AudioMessageContent;
@FreezedUnionValue("m.video") @FreezedUnionValue("m.video")
const factory MessageContent.video({ const factory MessageContent.video({
@ -58,13 +58,13 @@ abstract class MessageContent extends Content with _$MessageContent {
String? filename, String? filename,
AudioInfo? info, AudioInfo? info,
String? url, String? url,
}) = _AudioMessageContent; }) = AudioMessageContent;
@FreezedUnionValue("m.location") @FreezedUnionValue("m.location")
const factory MessageContent.location({ const factory MessageContent.location({
required String body, required String body,
required Uri geoUri, required Uri geoUri,
}) = _LocationMessageContent; }) = LocationMessageContent;
factory MessageContent.fromJson(Map<String, Object?> json) => factory MessageContent.fromJson(Map<String, Object?> json) =>
_$MessageContentFromJson(json); _$MessageContentFromJson(json);

View file

@ -0,0 +1,14 @@
import "package:freezed_annotation/freezed_annotation.dart";
import "package:nexus/models/content/content.dart";
part "redaction.freezed.dart";
part "redaction.g.dart";
@freezed
abstract class RedactionContent extends Content with _$RedactionContent {
RedactionContent._();
const factory RedactionContent({String? reason, String? redacts}) =
_RedactionContent;
factory RedactionContent.fromJson(Map<String, Object?> json) =>
_$RedactionContentFromJson(json);
}

View file

@ -5,6 +5,7 @@ import "package:fluttertagger/fluttertagger.dart";
import "package:hooks_riverpod/hooks_riverpod.dart"; import "package:hooks_riverpod/hooks_riverpod.dart";
import "package:nexus/controllers/power_level_controller.dart"; import "package:nexus/controllers/power_level_controller.dart";
import "package:nexus/models/configs/power_level_config.dart"; import "package:nexus/models/configs/power_level_config.dart";
import "package:nexus/models/content/content.dart";
import "package:nexus/models/event.dart"; import "package:nexus/models/event.dart";
import "package:nexus/models/relation_type.dart"; import "package:nexus/models/relation_type.dart";
import "package:nexus/widgets/chat_page/composer/mention_overlay.dart"; import "package:nexus/widgets/chat_page/composer/mention_overlay.dart";
@ -87,7 +88,7 @@ class ChatBox extends HookConsumerWidget {
children: children:
ref.watch( ref.watch(
PowerLevelController.provider( PowerLevelController.provider(
PowerLevelConfig(eventType: "m.room.message"), PowerLevelConfig(eventType: EventType.message),
), ),
) )
? [ ? [

View file

@ -13,6 +13,7 @@ import "package:nexus/controllers/via_controller.dart";
import "package:nexus/helpers/extensions/better_when.dart"; import "package:nexus/helpers/extensions/better_when.dart";
import "package:nexus/helpers/extensions/show_context_menu.dart"; import "package:nexus/helpers/extensions/show_context_menu.dart";
import "package:nexus/models/configs/power_level_config.dart"; import "package:nexus/models/configs/power_level_config.dart";
import "package:nexus/models/content/content.dart";
import "package:nexus/models/relation_type.dart"; 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/composer/chat_box.dart"; import "package:nexus/widgets/chat_page/composer/chat_box.dart";
@ -85,7 +86,7 @@ class RoomChat extends HookConsumerWidget {
return [ return [
if (ref.watch( if (ref.watch(
PowerLevelController.provider( PowerLevelController.provider(
PowerLevelConfig(eventType: "m.reaction"), PowerLevelConfig(eventType: EventType.reaction),
), ),
)) ))
PopupMenuItem( PopupMenuItem(
@ -129,7 +130,7 @@ class RoomChat extends HookConsumerWidget {
), ),
if (ref.watch( if (ref.watch(
PowerLevelController.provider( PowerLevelController.provider(
PowerLevelConfig(eventType: "m.room.message"), PowerLevelConfig(eventType: EventType.message),
), ),
)) ))
PopupMenuItem( PopupMenuItem(
@ -167,7 +168,7 @@ class RoomChat extends HookConsumerWidget {
), ),
if (ref.watch( if (ref.watch(
PowerLevelController.provider( PowerLevelController.provider(
PowerLevelConfig(eventType: "m.room.redaction"), PowerLevelConfig.redact(targetUser: message.authorId),
), ),
)) ))
PopupMenuItem( PopupMenuItem(

View file

@ -152,10 +152,8 @@ class UserPopover extends ConsumerWidget {
if (ref.watch( if (ref.watch(
PowerLevelController.provider( PowerLevelController.provider(
PowerLevelConfig( PowerLevelConfig.membershipAction(
eventType: "m.room.member",
action: MembershipAction.kick, action: MembershipAction.kick,
isStateEvent: true,
targetUser: userId, targetUser: userId,
), ),
), ),
@ -176,10 +174,8 @@ class UserPopover extends ConsumerWidget {
), ),
if (ref.watch( if (ref.watch(
PowerLevelController.provider( PowerLevelController.provider(
PowerLevelConfig( PowerLevelConfig.membershipAction(
eventType: "m.room.member",
action: MembershipAction.ban, action: MembershipAction.ban,
isStateEvent: true,
targetUser: userId, targetUser: userId,
), ),
), ),