nexus/lib/controllers/power_level_controller.dart

81 lines
2.7 KiB
Dart

import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:nexus/controllers/client_state_controller.dart";
import "package:nexus/controllers/room_creators_controller.dart";
import "package:nexus/controllers/rooms_controller.dart";
import "package:nexus/models/configs/power_level_config.dart";
import "package:nexus/models/content/content.dart";
import "package:nexus/models/content/power_levels.dart";
class PowerLevelController extends Notifier<bool> {
final PowerLevelConfig config;
PowerLevelController(this.config);
@override
bool build() {
if (config case EventPowerLevelConfig(:final eventType)) {
assert(
eventType != .redaction,
"Checking power level for a redaction should use [PowerLevelConfig.redaction].",
);
}
final room = ref.watch(
RoomsController.provider.select((value) => value[config.roomId]),
);
final roomCreators = room == null
? null
: ref.watch(RoomCreatorsController.provider(room));
final eventRowId = room?.state[EventType.powerLevels.type]?[""];
final event = eventRowId == null ? null : room?.events[eventRowId];
final content = event?.content is PowerLevelsContent
? event!.content
: PowerLevelsContent();
final user = ref.watch(
ClientStateController.provider.select((value) => value?.userId),
);
if (user == null || content is! PowerLevelsContent) return false;
double powerLevelOf(String userId) => roomCreators?.contains(userId) == true
? double.infinity
: (content.users[userId] ?? content.usersDefault).toDouble();
final userLevel = powerLevelOf(user);
return switch (config) {
EventPowerLevelConfig(:final eventType) =>
userLevel >= (content.events[eventType.type] ?? content.eventsDefault),
MembershipActionPowerLevelConfig(:final action, :final targetUser) =>
switch (action) {
.invite => userLevel >= content.invite,
.kick =>
userLevel >= content.kick && userLevel > powerLevelOf(targetUser),
.ban =>
userLevel >= content.ban && userLevel > powerLevelOf(targetUser),
.unban => userLevel >= content.ban,
},
StatePowerLevelConfig(:final eventType) =>
userLevel >= (content.events[eventType.type] ?? content.stateDefault),
RedactionPowerLevelConfig(:final targetUser) =>
userLevel >=
(targetUser == user
? (content.events[EventType.redaction.type] ??
content.eventsDefault)
: content.redact),
};
}
static final provider = NotifierProvider.autoDispose
.family<PowerLevelController, bool, PowerLevelConfig>(
PowerLevelController.new,
);
}