diff --git a/lib/controllers/power_level_controller.dart b/lib/controllers/power_level_controller.dart index 7d377a5..b165d9c 100644 --- a/lib/controllers/power_level_controller.dart +++ b/lib/controllers/power_level_controller.dart @@ -26,37 +26,32 @@ class PowerLevelController extends Notifier { content.users[userId] ?? content.usersDefault; final userLevel = powerLevelOf(user); - final targetLevel = config.targetUser != null - ? powerLevelOf(config.targetUser!) - : null; - if (config.action != null) { - return switch (config.action!) { - MembershipAction.invite => userLevel >= content.invite, + return switch (config) { + EventPowerLevelConfig(:final eventType) => + userLevel > (content.events[eventType.type] ?? content.eventsDefault), + MembershipActionPowerLevelConfig(:final action, :final targetUser) => + switch (action) { + MembershipAction.invite => userLevel >= content.invite, - MembershipAction.kick => - targetLevel != null && - userLevel >= content.kick && - userLevel > targetLevel, + MembershipAction.kick => + userLevel >= content.kick && userLevel > powerLevelOf(targetUser), - MembershipAction.ban => - targetLevel != null && - userLevel >= content.ban && - userLevel > targetLevel, + MembershipAction.ban => + userLevel >= content.ban && userLevel > powerLevelOf(targetUser), - MembershipAction.unban => userLevel >= content.ban, - }; - } + MembershipAction.unban => userLevel >= content.ban, + }, - if (config.eventType == "m.room.redaction") { - return userLevel >= content.redact; - } - - final requiredLevel = - content.events[config.eventType] ?? - (config.isStateEvent ? content.stateDefault : content.eventsDefault); - - return userLevel >= requiredLevel; + StatePowerLevelConfig(:final eventType) => + userLevel > (content.events[eventType.type] ?? content.stateDefault), + RedactPowerLevelConfig(:final targetUser) => + userLevel >= + (targetUser == user + ? (content.events[EventType.redaction.type] ?? + content.eventsDefault) + : content.redact), + }; } static final provider = NotifierProvider.autoDispose diff --git a/lib/models/configs/message_config.dart b/lib/models/configs/message_config.dart deleted file mode 100644 index 66a437c..0000000 --- a/lib/models/configs/message_config.dart +++ /dev/null @@ -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 json) => - _$MessageConfigFromJson(json); -} diff --git a/lib/models/configs/messages_config.dart b/lib/models/configs/messages_config.dart deleted file mode 100644 index b33a71c..0000000 --- a/lib/models/configs/messages_config.dart +++ /dev/null @@ -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 events, - }) = _MessagesConfig; - - factory MessagesConfig.fromJson(Map json) => - _$MessagesConfigFromJson(json); -} diff --git a/lib/models/configs/power_level_config.dart b/lib/models/configs/power_level_config.dart index 31cc08c..a4bb9c1 100644 --- a/lib/models/configs/power_level_config.dart +++ b/lib/models/configs/power_level_config.dart @@ -1,17 +1,21 @@ import "package:freezed_annotation/freezed_annotation.dart"; +import "package:nexus/models/content/content.dart"; import "package:nexus/models/requests/membership_action.dart"; part "power_level_config.freezed.dart"; -part "power_level_config.g.dart"; @freezed -abstract class PowerLevelConfig with _$PowerLevelConfig { - const factory PowerLevelConfig({ - @Default(false) bool isStateEvent, - required String eventType, - MembershipAction? action, - String? targetUser, - }) = _PowerLevelConfig; +sealed class PowerLevelConfig with _$PowerLevelConfig { + const factory PowerLevelConfig({required EventType eventType}) = + EventPowerLevelConfig; - factory PowerLevelConfig.fromJson(Map json) => - _$PowerLevelConfigFromJson(json); + const factory PowerLevelConfig.membershipAction({ + required MembershipAction action, + required String targetUser, + }) = MembershipActionPowerLevelConfig; + + const factory PowerLevelConfig.state({required EventType eventType}) = + StatePowerLevelConfig; + + const factory PowerLevelConfig.redact({required String targetUser}) = + RedactPowerLevelConfig; } diff --git a/lib/models/content/content.dart b/lib/models/content/content.dart index ec729f5..760a90c 100644 --- a/lib/models/content/content.dart +++ b/lib/models/content/content.dart @@ -11,6 +11,7 @@ import "package:nexus/models/content/name.dart"; import "package:nexus/models/content/pinned_events.dart"; import "package:nexus/models/content/power_levels.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/topic.dart"; @@ -30,6 +31,7 @@ class Content { @JsonEnum(valueField: "type") enum EventType { encrypted("m.room.encrypted", Content.fromJson), + redaction("m.room.redaction", RedactionContent.fromJson), encryption("m.room.encryption", EncryptionContent.fromJson), membership("m.room.member", MembershipContent.fromJson), create("m.room.create", CreateContent.fromJson), diff --git a/lib/models/content/message.dart b/lib/models/content/message.dart index c61fb25..cca3af4 100644 --- a/lib/models/content/message.dart +++ b/lib/models/content/message.dart @@ -14,7 +14,7 @@ abstract class MessageContent extends Content with _$MessageContent { required String body, String? format, String? formattedBody, - }) = _TextMessageContent; + }) = TextMessageContent; @FreezedUnionValue("m.image") const factory MessageContent.image({ @@ -25,7 +25,7 @@ abstract class MessageContent extends Content with _$MessageContent { String? filename, ImageInfo? info, String? url, - }) = _ImageMessageContent; + }) = ImageMessageContent; @FreezedUnionValue("m.file") const factory MessageContent.file({ @@ -36,7 +36,7 @@ abstract class MessageContent extends Content with _$MessageContent { String? filename, FileInfo? info, String? url, - }) = _FileMessageContent; + }) = FileMessageContent; @FreezedUnionValue("m.audio") const factory MessageContent.audio({ @@ -47,7 +47,7 @@ abstract class MessageContent extends Content with _$MessageContent { String? filename, AudioInfo? info, String? url, - }) = _AudioMessageContent; + }) = AudioMessageContent; @FreezedUnionValue("m.video") const factory MessageContent.video({ @@ -58,13 +58,13 @@ abstract class MessageContent extends Content with _$MessageContent { String? filename, AudioInfo? info, String? url, - }) = _AudioMessageContent; + }) = AudioMessageContent; @FreezedUnionValue("m.location") const factory MessageContent.location({ required String body, required Uri geoUri, - }) = _LocationMessageContent; + }) = LocationMessageContent; factory MessageContent.fromJson(Map json) => _$MessageContentFromJson(json); diff --git a/lib/models/content/redaction.dart b/lib/models/content/redaction.dart new file mode 100644 index 0000000..289d4bf --- /dev/null +++ b/lib/models/content/redaction.dart @@ -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 json) => + _$RedactionContentFromJson(json); +} diff --git a/lib/widgets/chat_page/composer/chat_box.dart b/lib/widgets/chat_page/composer/chat_box.dart index f793fda..e0aaca9 100644 --- a/lib/widgets/chat_page/composer/chat_box.dart +++ b/lib/widgets/chat_page/composer/chat_box.dart @@ -5,6 +5,7 @@ import "package:fluttertagger/fluttertagger.dart"; import "package:hooks_riverpod/hooks_riverpod.dart"; import "package:nexus/controllers/power_level_controller.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/relation_type.dart"; import "package:nexus/widgets/chat_page/composer/mention_overlay.dart"; @@ -87,7 +88,7 @@ class ChatBox extends HookConsumerWidget { children: ref.watch( PowerLevelController.provider( - PowerLevelConfig(eventType: "m.room.message"), + PowerLevelConfig(eventType: EventType.message), ), ) ? [ diff --git a/lib/widgets/chat_page/room_chat.dart b/lib/widgets/chat_page/room_chat.dart index b4639e5..48d1784 100644 --- a/lib/widgets/chat_page/room_chat.dart +++ b/lib/widgets/chat_page/room_chat.dart @@ -13,6 +13,7 @@ import "package:nexus/controllers/via_controller.dart"; import "package:nexus/helpers/extensions/better_when.dart"; import "package:nexus/helpers/extensions/show_context_menu.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/requests/report_request.dart"; import "package:nexus/widgets/chat_page/composer/chat_box.dart"; @@ -85,7 +86,7 @@ class RoomChat extends HookConsumerWidget { return [ if (ref.watch( PowerLevelController.provider( - PowerLevelConfig(eventType: "m.reaction"), + PowerLevelConfig(eventType: EventType.reaction), ), )) PopupMenuItem( @@ -129,7 +130,7 @@ class RoomChat extends HookConsumerWidget { ), if (ref.watch( PowerLevelController.provider( - PowerLevelConfig(eventType: "m.room.message"), + PowerLevelConfig(eventType: EventType.message), ), )) PopupMenuItem( @@ -167,7 +168,7 @@ class RoomChat extends HookConsumerWidget { ), if (ref.watch( PowerLevelController.provider( - PowerLevelConfig(eventType: "m.room.redaction"), + PowerLevelConfig.redact(targetUser: message.authorId), ), )) PopupMenuItem( diff --git a/lib/widgets/chat_page/user_popover.dart b/lib/widgets/chat_page/user_popover.dart index 115bcda..5ff4110 100644 --- a/lib/widgets/chat_page/user_popover.dart +++ b/lib/widgets/chat_page/user_popover.dart @@ -152,10 +152,8 @@ class UserPopover extends ConsumerWidget { if (ref.watch( PowerLevelController.provider( - PowerLevelConfig( - eventType: "m.room.member", + PowerLevelConfig.membershipAction( action: MembershipAction.kick, - isStateEvent: true, targetUser: userId, ), ), @@ -176,10 +174,8 @@ class UserPopover extends ConsumerWidget { ), if (ref.watch( PowerLevelController.provider( - PowerLevelConfig( - eventType: "m.room.member", + PowerLevelConfig.membershipAction( action: MembershipAction.ban, - isStateEvent: true, targetUser: userId, ), ),