add power level room settings
This commit is contained in:
parent
fcfe4eed1e
commit
b0dd452926
6 changed files with 944 additions and 179 deletions
|
|
@ -1,44 +1,27 @@
|
|||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/controllers/members_by_status.dart";
|
||||
import "package:nexus/controllers/room_creators.dart";
|
||||
import "package:nexus/controllers/rooms.dart";
|
||||
import "package:nexus/controllers/room_power_levels.dart";
|
||||
import "package:nexus/models/configs/members_by_status.dart";
|
||||
import "package:nexus/models/content/content.dart";
|
||||
import "package:nexus/models/content/power_levels.dart";
|
||||
import "package:nexus/models/event.dart";
|
||||
|
||||
class MembersGroupedController(final MembersByStatusConfig config)
|
||||
extends AsyncNotifier<IList<MapEntry<int?, ISet<Event>>>> {
|
||||
@override
|
||||
Future<IList<MapEntry<int?, ISet<Event>>>> build() async {
|
||||
final room = ref.watch(
|
||||
RoomsController.provider.select((value) => value[config.roomId]),
|
||||
final powerLevels = ref.watch(
|
||||
RoomPowerLevelsController.provider(config.roomId),
|
||||
);
|
||||
|
||||
final roomCreators = room == null
|
||||
? null
|
||||
: ref.watch((RoomCreatorsController.provider(room)));
|
||||
|
||||
final powerLevelsRowId = room?.state[EventType.powerLevels.type]?[""];
|
||||
final powerLevelsEvent = powerLevelsRowId == null
|
||||
? null
|
||||
: room?.events[powerLevelsRowId];
|
||||
|
||||
final content = switch (powerLevelsEvent?.content) {
|
||||
PowerLevelsContent content => content,
|
||||
_ => PowerLevelsContent(),
|
||||
};
|
||||
|
||||
final members = await ref.watch(
|
||||
MembersByStatusController.provider(config).future,
|
||||
);
|
||||
|
||||
return members
|
||||
.fold<IMap<int?, ISet<Event>>>(.new(), (result, event) {
|
||||
final groupKey = roomCreators?.contains(event.stateKey!) == true
|
||||
final groupKey = powerLevels.creators.contains(event.stateKey!)
|
||||
? null
|
||||
: content.users[event.stateKey!] ?? content.usersDefault;
|
||||
: powerLevels.levelOf(event.stateKey!).toInt();
|
||||
|
||||
return result.update(
|
||||
groupKey,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/controllers/client_state.dart";
|
||||
import "package:nexus/controllers/room_creators.dart";
|
||||
import "package:nexus/controllers/rooms.dart";
|
||||
import "package:nexus/controllers/room_power_levels.dart";
|
||||
import "package:nexus/models/configs/power_level.dart";
|
||||
import "package:nexus/models/content/content.dart";
|
||||
import "package:nexus/models/content/power_levels.dart";
|
||||
|
||||
class PowerLevelController(final PowerLevelConfig config)
|
||||
extends Notifier<bool> {
|
||||
|
|
@ -17,31 +15,17 @@ class PowerLevelController(final PowerLevelConfig config)
|
|||
);
|
||||
}
|
||||
|
||||
final room = ref.watch(
|
||||
RoomsController.provider.select((value) => value[config.roomId]),
|
||||
final powerLevels = ref.watch(
|
||||
RoomPowerLevelsController.provider(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 content = powerLevels.content;
|
||||
|
||||
final user = ref.watch(
|
||||
ClientStateController.provider.select((value) => value?.userId),
|
||||
);
|
||||
if (user == null || content is! PowerLevelsContent) return false;
|
||||
if (user == null) return false;
|
||||
|
||||
double powerLevelOf(String userId) => roomCreators?.contains(userId) == true
|
||||
? double.infinity
|
||||
: (content.users[userId] ?? content.usersDefault).toDouble();
|
||||
|
||||
final userLevel = powerLevelOf(user);
|
||||
final userLevel = powerLevels.levelOf(user);
|
||||
|
||||
return switch (config) {
|
||||
EventPowerLevelConfig(:final eventType) =>
|
||||
|
|
@ -52,10 +36,12 @@ class PowerLevelController(final PowerLevelConfig config)
|
|||
.invite => userLevel >= content.invite,
|
||||
|
||||
.kick =>
|
||||
userLevel >= content.kick && userLevel > powerLevelOf(targetUser),
|
||||
userLevel >= content.kick &&
|
||||
userLevel > powerLevels.levelOf(targetUser),
|
||||
|
||||
.ban =>
|
||||
userLevel >= content.ban && userLevel > powerLevelOf(targetUser),
|
||||
userLevel >= content.ban &&
|
||||
userLevel > powerLevels.levelOf(targetUser),
|
||||
|
||||
.unban => userLevel >= content.ban,
|
||||
},
|
||||
|
|
|
|||
20
lib/controllers/power_levels_saving.dart
Normal file
20
lib/controllers/power_levels_saving.dart
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
|
||||
class PowerLevelsSavingController(final String roomId) extends Notifier<bool> {
|
||||
@override
|
||||
bool build() => false;
|
||||
|
||||
Future<void> run(Future<void> Function() action) async {
|
||||
state = true;
|
||||
try {
|
||||
await action();
|
||||
} finally {
|
||||
if (ref.mounted) state = false;
|
||||
}
|
||||
}
|
||||
|
||||
static final provider = NotifierProvider.autoDispose
|
||||
.family<PowerLevelsSavingController, bool, String>(
|
||||
PowerLevelsSavingController.new,
|
||||
);
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/models/content/content.dart";
|
||||
import "package:nexus/models/content/create.dart";
|
||||
import "package:nexus/models/room.dart";
|
||||
|
||||
class RoomCreatorsController(final Room room) extends Notifier<IList<String>> {
|
||||
@override
|
||||
IList<String> build() {
|
||||
final createRowId = room.state[EventType.create.type]?[""];
|
||||
final createEvent = createRowId == null ? null : room.events[createRowId];
|
||||
|
||||
if (createEvent == null) return .new();
|
||||
|
||||
final createEventContent = switch (createEvent.content) {
|
||||
CreateContent content => content,
|
||||
_ => null,
|
||||
};
|
||||
|
||||
return switch (createEventContent?.additionalCreatorIds) {
|
||||
IList<String> creators => creators.add(createEvent.sender),
|
||||
_ => .new([createEvent.sender]),
|
||||
};
|
||||
}
|
||||
|
||||
static final provider =
|
||||
NotifierProvider.family<RoomCreatorsController, IList<String>, Room>(
|
||||
RoomCreatorsController.new,
|
||||
);
|
||||
}
|
||||
59
lib/controllers/room_power_levels.dart
Normal file
59
lib/controllers/room_power_levels.dart
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/controllers/rooms.dart";
|
||||
import "package:nexus/models/content/content.dart";
|
||||
import "package:nexus/models/content/create.dart";
|
||||
import "package:nexus/models/content/power_levels.dart";
|
||||
import "package:nexus/models/event.dart";
|
||||
import "package:nexus/models/room_power_levels.dart";
|
||||
|
||||
class RoomPowerLevelsController(final String roomId)
|
||||
extends Notifier<RoomPowerLevels> {
|
||||
@override
|
||||
RoomPowerLevels build() {
|
||||
final room = ref.watch(
|
||||
RoomsController.provider.select((rooms) => rooms[roomId]),
|
||||
);
|
||||
|
||||
Event? stateEvent(EventType type) => switch (room?.state[type.type]?[""]) {
|
||||
final rowId? => room?.events[rowId],
|
||||
null => null,
|
||||
};
|
||||
|
||||
final createEvent = stateEvent(.create);
|
||||
final create = switch (createEvent?.content) {
|
||||
final CreateContent content => content,
|
||||
_ => null,
|
||||
};
|
||||
// Creators only outrank everyone from room version 12, earlier ones just have a power level
|
||||
final creatorsPrivileged =
|
||||
(int.tryParse(create?.roomVersion ?? "") ?? 0) >= 12;
|
||||
|
||||
return .new(
|
||||
content: switch (stateEvent(.powerLevels)?.content) {
|
||||
final PowerLevelsContent content => content,
|
||||
// Until there are power levels, creators have 100
|
||||
_ => PowerLevelsContent(
|
||||
users: switch (createEvent) {
|
||||
final createEvent? when !creatorsPrivileged => .new({
|
||||
createEvent.sender: 100,
|
||||
}),
|
||||
_ => const .empty(),
|
||||
},
|
||||
),
|
||||
},
|
||||
creators: switch (createEvent) {
|
||||
final createEvent? when creatorsPrivileged =>
|
||||
(create?.additionalCreatorIds ?? const .empty())
|
||||
.add(createEvent.sender)
|
||||
.toISet(),
|
||||
_ => const .empty(),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
static final provider = NotifierProvider.autoDispose
|
||||
.family<RoomPowerLevelsController, RoomPowerLevels, String>(
|
||||
RoomPowerLevelsController.new,
|
||||
);
|
||||
}
|
||||
|
|
@ -3,8 +3,11 @@ import "package:flutter_hooks/flutter_hooks.dart";
|
|||
import "package:hooks_riverpod/hooks_riverpod.dart";
|
||||
import "package:material_ui/material_ui.dart";
|
||||
import "package:nexus/controllers/client.dart";
|
||||
import "package:nexus/controllers/client_state.dart";
|
||||
import "package:nexus/controllers/local_aliases.dart";
|
||||
import "package:nexus/controllers/power_level.dart";
|
||||
import "package:nexus/controllers/power_levels_saving.dart";
|
||||
import "package:nexus/controllers/room_power_levels.dart";
|
||||
import "package:nexus/controllers/rooms.dart";
|
||||
import "package:nexus/controllers/space_edges.dart";
|
||||
import "package:nexus/helpers/extensions/show_adaptive_sheet.dart";
|
||||
|
|
@ -15,18 +18,26 @@ import "package:nexus/models/content/avatar.dart";
|
|||
import "package:nexus/models/content/canonical_alias.dart";
|
||||
import "package:nexus/models/content/content.dart";
|
||||
import "package:nexus/models/content/create.dart";
|
||||
import "package:nexus/models/content/encryption.dart";
|
||||
import "package:nexus/models/content/history_visibility.dart";
|
||||
import "package:nexus/models/content/join_rules.dart";
|
||||
import "package:nexus/models/content/membership.dart";
|
||||
import "package:nexus/models/content/message.dart";
|
||||
import "package:nexus/models/content/name.dart";
|
||||
import "package:nexus/models/content/power_levels.dart";
|
||||
import "package:nexus/models/content/topic.dart";
|
||||
import "package:nexus/models/join_rule.dart";
|
||||
import "package:nexus/models/setting.dart";
|
||||
import "package:nexus/models/settings_category.dart";
|
||||
import "package:nexus/widgets/avatar_or_hash.dart";
|
||||
import "package:nexus/widgets/divider_text.dart";
|
||||
import "package:nexus/widgets/settings/add_users_power_level_sheet.dart";
|
||||
import "package:nexus/widgets/settings/aliases_sheet.dart";
|
||||
import "package:nexus/widgets/settings/allowed_rooms_sheet.dart";
|
||||
import "package:nexus/widgets/settings/dialog_list_tile.dart";
|
||||
import "package:nexus/widgets/settings/local_aliases_sheet.dart";
|
||||
import "package:nexus/widgets/settings/power_level_entry_sheet.dart";
|
||||
import "package:nexus/widgets/settings/power_level_tile.dart";
|
||||
import "package:nexus/widgets/settings/text_setting_tile.dart";
|
||||
|
||||
class RoomSettingsSectionsController(final String roomId)
|
||||
|
|
@ -69,6 +80,9 @@ class RoomSettingsSectionsController(final String roomId)
|
|||
final canSetJoinRules = canSet(.joinRules);
|
||||
final canSetHistoryVisibility = canSet(.historyVisibility);
|
||||
final canSetAliases = canSet(.canonicalAlias);
|
||||
final canSetPowerLevels =
|
||||
canSet(.powerLevels) &&
|
||||
!ref.watch(PowerLevelsSavingController.provider(roomId));
|
||||
|
||||
final joinRules = switch (stateContent(.joinRules)) {
|
||||
final JoinRulesContent content => content,
|
||||
|
|
@ -125,6 +139,19 @@ class RoomSettingsSectionsController(final String roomId)
|
|||
.nonNulls
|
||||
.toISet();
|
||||
|
||||
final roomPowerLevels = ref.watch(
|
||||
RoomPowerLevelsController.provider(roomId),
|
||||
);
|
||||
final powerLevels = roomPowerLevels.content;
|
||||
final userId = ref.watch(
|
||||
ClientStateController.provider.select((state) => state?.userId),
|
||||
);
|
||||
final ownLevel = userId == null ? 0.0 : roomPowerLevels.levelOf(userId);
|
||||
// Encrypted rooms send messages as m.room.encrypted, so that's what limits them
|
||||
final messageType = stateContent(.encryption) is EncryptionContent
|
||||
? EventType.encrypted
|
||||
: EventType.message;
|
||||
|
||||
Future<void> setState(EventType type, Content content) async {
|
||||
final eventId = await client.setState(
|
||||
.new(roomId: roomId, type: type.type, stateKey: "", content: content),
|
||||
|
|
@ -167,6 +194,108 @@ class RoomSettingsSectionsController(final String roomId)
|
|||
),
|
||||
);
|
||||
|
||||
Setting header(String title, String description, IconData icon) => .new(
|
||||
title: title,
|
||||
description: description,
|
||||
icon: icon,
|
||||
builder: (title, _, _) => Padding(
|
||||
padding: .symmetric(horizontal: 16),
|
||||
child: DividerText(title),
|
||||
),
|
||||
);
|
||||
|
||||
Future<void> setPowerLevels(PowerLevelsContent content) => ref
|
||||
.read(PowerLevelsSavingController.provider(roomId).notifier)
|
||||
.run(() => setState(.powerLevels, content).onError(showError));
|
||||
|
||||
// Event types with their own level that don't have a setting of their own
|
||||
final listedEvents = [
|
||||
messageType,
|
||||
EventType.sticker,
|
||||
EventType.reaction,
|
||||
EventType.pinnedEvents,
|
||||
].map((type) => type.type).toISet();
|
||||
final otherEvents = powerLevels.events.entries
|
||||
.where((entry) => !listedEvents.contains(entry.key))
|
||||
.toIList()
|
||||
.sort((a, b) => a.key.compareTo(b.key));
|
||||
|
||||
// Users with their own level, the highest first
|
||||
final users = powerLevels.users.entries.toIList().sort(
|
||||
(a, b) => switch (b.value.compareTo(a.value)) {
|
||||
0 => a.key.compareTo(b.key),
|
||||
final order => order,
|
||||
},
|
||||
);
|
||||
MembershipContent? memberOf(String userId) =>
|
||||
switch (room?.state[EventType.membership.type]?[userId]) {
|
||||
final rowId? => switch (room?.events[rowId]?.content) {
|
||||
final MembershipContent content => content,
|
||||
_ => null,
|
||||
},
|
||||
null => null,
|
||||
};
|
||||
|
||||
/// A tile opening a [sheet] to add entries, like event types or users, with their own power level.
|
||||
Setting addSetting({
|
||||
required String title,
|
||||
required String description,
|
||||
required Widget Function(void Function(PowerLevelsContent content) save)
|
||||
sheet,
|
||||
}) => .new(
|
||||
title: title,
|
||||
description: description,
|
||||
icon: Icons.add,
|
||||
builder: (title, description, icon) => Builder(
|
||||
builder: (context) => ListTile(
|
||||
enabled: canSetPowerLevels,
|
||||
leading: Icon(icon),
|
||||
title: Text(title),
|
||||
subtitle: Text(description),
|
||||
onTap: () => context.showAdaptiveSheet((_) => sheet(setPowerLevels)),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
Setting powerLevelSetting({
|
||||
required String title,
|
||||
required String description,
|
||||
required IconData icon,
|
||||
required int value,
|
||||
required PowerLevelsContent Function(int level) update,
|
||||
}) => .new(
|
||||
title: title,
|
||||
description: description,
|
||||
icon: icon,
|
||||
builder: (title, description, icon) => PowerLevelTile(
|
||||
leading: Icon(icon),
|
||||
title: title,
|
||||
description: description,
|
||||
value: value,
|
||||
ownLevel: ownLevel,
|
||||
onChanged: canSetPowerLevels
|
||||
? (level) => setPowerLevels(update(level))
|
||||
: null,
|
||||
),
|
||||
);
|
||||
|
||||
/// A setting for the level needed to send [type], which otherwise needs [fallback].
|
||||
Setting eventSetting(
|
||||
EventType type, {
|
||||
required String title,
|
||||
required String description,
|
||||
required IconData icon,
|
||||
required int fallback,
|
||||
}) => powerLevelSetting(
|
||||
title: title,
|
||||
description: description,
|
||||
icon: icon,
|
||||
value: powerLevels.events[type.type] ?? fallback,
|
||||
update: (level) => powerLevels.copyWith(
|
||||
events: powerLevels.events.add(type.type, level),
|
||||
),
|
||||
);
|
||||
|
||||
return .new({
|
||||
"Room": .new([
|
||||
.new(
|
||||
|
|
@ -473,6 +602,208 @@ class RoomSettingsSectionsController(final String roomId)
|
|||
),
|
||||
]),
|
||||
),
|
||||
.new(
|
||||
title: "Permissions",
|
||||
icon: Icons.admin_panel_settings,
|
||||
settings: .new([
|
||||
powerLevelSetting(
|
||||
title: "Default Power Level",
|
||||
description: "The power level of users who aren't given one.",
|
||||
icon: Icons.person,
|
||||
value: powerLevels.usersDefault,
|
||||
update: (level) => powerLevels.copyWith(usersDefault: level),
|
||||
),
|
||||
header("Users", "Power levels of specific users.", Icons.group),
|
||||
...users.map((entry) {
|
||||
final member = memberOf(entry.key);
|
||||
// Others can only be changed if they're below you, but your own level can be lowered
|
||||
final canChange =
|
||||
canSetPowerLevels &&
|
||||
(entry.key == userId || entry.value < ownLevel);
|
||||
|
||||
return Setting(
|
||||
title: member?.displayName ?? entry.key,
|
||||
description: entry.key,
|
||||
icon: Icons.person,
|
||||
builder: (title, description, _) => PowerLevelTile(
|
||||
leading: AvatarOrHash(
|
||||
member?.avatarUrl,
|
||||
title,
|
||||
dimension: 40,
|
||||
),
|
||||
title: title,
|
||||
description: description,
|
||||
value: entry.value,
|
||||
ownLevel: ownLevel,
|
||||
onChanged: canChange
|
||||
? (level) => setPowerLevels(
|
||||
powerLevels.copyWith(
|
||||
users: powerLevels.users.add(entry.key, level),
|
||||
),
|
||||
)
|
||||
: null,
|
||||
onRemoved: canChange
|
||||
? () => setPowerLevels(
|
||||
powerLevels.copyWith(
|
||||
users: powerLevels.users.remove(entry.key),
|
||||
),
|
||||
)
|
||||
: null,
|
||||
removeConfirmation: entry.key == userId
|
||||
? "Remove your own power level? You'll have the default of ${powerLevels.usersDefault}, and won't be able to raise it again yourself."
|
||||
: "Remove $title's power level? They'll have the default of ${powerLevels.usersDefault}.",
|
||||
),
|
||||
);
|
||||
}),
|
||||
addSetting(
|
||||
title: "Add Users",
|
||||
description: "Give users their own power level.",
|
||||
sheet: (save) => AddUsersPowerLevelSheet(
|
||||
roomId: roomId,
|
||||
existing: powerLevels.users.keys.toISet().union(
|
||||
roomPowerLevels.creators,
|
||||
),
|
||||
ownLevel: ownLevel,
|
||||
onSave: (users, level) => save(
|
||||
powerLevels.copyWith(
|
||||
users: powerLevels.users.addEntries(
|
||||
users.map((user) => MapEntry(user, level)),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
header(
|
||||
"Regular Events",
|
||||
"Power levels needed to send messages and other timeline events.",
|
||||
Icons.chat,
|
||||
),
|
||||
eventSetting(
|
||||
messageType,
|
||||
title: "Send Messages",
|
||||
description: "The power level needed to send messages.",
|
||||
icon: Icons.message,
|
||||
fallback: powerLevels.eventsDefault,
|
||||
),
|
||||
eventSetting(
|
||||
.sticker,
|
||||
title: "Send Stickers",
|
||||
description: "The power level needed to send stickers.",
|
||||
icon: Icons.sticky_note_2,
|
||||
fallback: powerLevels.eventsDefault,
|
||||
),
|
||||
eventSetting(
|
||||
.reaction,
|
||||
title: "Send Reactions",
|
||||
description: "The power level needed to react to messages.",
|
||||
icon: Icons.add_reaction,
|
||||
fallback: powerLevels.eventsDefault,
|
||||
),
|
||||
powerLevelSetting(
|
||||
title: "Default for Events",
|
||||
description:
|
||||
"The power level needed to send events without their own.",
|
||||
icon: Icons.more_horiz,
|
||||
value: powerLevels.eventsDefault,
|
||||
update: (level) => powerLevels.copyWith(eventsDefault: level),
|
||||
),
|
||||
header(
|
||||
"State Events",
|
||||
"Power levels needed to manage members and change the room's state.",
|
||||
Icons.settings,
|
||||
),
|
||||
eventSetting(
|
||||
.pinnedEvents,
|
||||
title: "Pin Messages",
|
||||
description: "The power level needed to pin messages.",
|
||||
icon: Icons.push_pin,
|
||||
fallback: powerLevels.stateDefault,
|
||||
),
|
||||
powerLevelSetting(
|
||||
title: "Invite Users",
|
||||
description: "The power level needed to invite users.",
|
||||
icon: Icons.person_add,
|
||||
value: powerLevels.invite,
|
||||
update: (level) => powerLevels.copyWith(invite: level),
|
||||
),
|
||||
powerLevelSetting(
|
||||
title: "Kick Users",
|
||||
description: "The power level needed to kick users.",
|
||||
icon: Icons.sports_martial_arts,
|
||||
value: powerLevels.kick,
|
||||
update: (level) => powerLevels.copyWith(kick: level),
|
||||
),
|
||||
powerLevelSetting(
|
||||
title: "Ban Users",
|
||||
description: "The power level needed to ban and unban users.",
|
||||
icon: Icons.gavel,
|
||||
value: powerLevels.ban,
|
||||
update: (level) => powerLevels.copyWith(ban: level),
|
||||
),
|
||||
powerLevelSetting(
|
||||
title: "Delete Others' Messages",
|
||||
description: "The power level needed to remove others' messages.",
|
||||
icon: Icons.delete,
|
||||
value: powerLevels.redact,
|
||||
update: (level) => powerLevels.copyWith(redact: level),
|
||||
),
|
||||
powerLevelSetting(
|
||||
title: "Default for State Events",
|
||||
description: "The power level needed to send state events without their own.",
|
||||
icon: Icons.tune,
|
||||
value: powerLevels.stateDefault,
|
||||
update: (level) => powerLevels.copyWith(stateDefault: level),
|
||||
),
|
||||
header(
|
||||
"Other Events",
|
||||
"Power levels for specific event types.",
|
||||
Icons.code,
|
||||
),
|
||||
...otherEvents.map(
|
||||
(entry) => Setting(
|
||||
title: entry.key,
|
||||
description: "The power level needed to send this event.",
|
||||
icon: Icons.code,
|
||||
builder: (title, _, icon) => PowerLevelTile(
|
||||
leading: Icon(icon),
|
||||
title: title,
|
||||
description: null,
|
||||
value: entry.value,
|
||||
ownLevel: ownLevel,
|
||||
onChanged: canSetPowerLevels
|
||||
? (level) => setPowerLevels(
|
||||
powerLevels.copyWith(
|
||||
events: powerLevels.events.add(entry.key, level),
|
||||
),
|
||||
)
|
||||
: null,
|
||||
onRemoved: canSetPowerLevels
|
||||
? () => setPowerLevels(
|
||||
powerLevels.copyWith(
|
||||
events: powerLevels.events.remove(entry.key),
|
||||
),
|
||||
)
|
||||
: null,
|
||||
),
|
||||
),
|
||||
),
|
||||
addSetting(
|
||||
title: "Add Event",
|
||||
description: "Give an event type its own power level.",
|
||||
sheet: (save) => PowerLevelEntrySheet(
|
||||
title: "Add Event",
|
||||
keyLabel: "Event type",
|
||||
keyHint: "m.room.name",
|
||||
ownLevel: ownLevel,
|
||||
onSave: (type, level) => save(
|
||||
powerLevels.copyWith(
|
||||
events: powerLevels.events.add(type, level),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
]),
|
||||
),
|
||||
]),
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue