added talk notification levels for chats

This commit is contained in:
2026-09-25 17:04:10 +02:00
parent e21560ed3d
commit ef7d17033d
9 changed files with 281 additions and 0 deletions
@@ -0,0 +1,95 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../../api/marianumcloud/talk/room/get_room_response.dart';
import '../../../../api/marianumcloud/talk/room/notification_level.dart';
import '../../../../state/app/modules/chat_list/bloc/chat_list_bloc.dart';
import '../../../../widget/async_action_button.dart';
import '../../../../widget/details_bottom_sheet.dart';
extension NotificationLevelPresentation on NotificationLevel {
// defaultLevel never reaches the UI (see effectiveNotificationLevel), but
// the switch has to stay exhaustive.
({String label, String description, IconData icon}) get _presentation =>
switch (this) {
NotificationLevel.alwaysNotify || NotificationLevel.defaultLevel => (
label: 'Alle Nachrichten',
description: 'Bei jeder neuen Nachricht',
icon: Icons.notifications_outlined,
),
NotificationLevel.notifyOnMention => (
label: 'Nur Erwähnungen',
description: 'Nur wenn du erwähnt wirst',
icon: Icons.alternate_email,
),
NotificationLevel.neverNotify => (
label: 'Aus',
description: 'Keine Benachrichtigungen',
icon: Icons.notifications_off_outlined,
),
};
String get label => _presentation.label;
String get description => _presentation.description;
IconData get icon => _presentation.icon;
}
/// Lets the user pick the room's Talk notification level. Nextcloud applies
/// it server-side, so no push for the room is sent at all when muted.
/// Returns the new level, or null when nothing changed.
Future<NotificationLevel?> showNotificationLevelSheet(
BuildContext context,
GetRoomResponseObject room, {
required NotificationLevel current,
}) async {
final bloc = context.read<ChatListBloc>();
NotificationLevel? selected;
await showDetailsBottomSheet(
context,
header: ListTile(
leading: const Icon(Icons.notifications_outlined),
title: const Text('Benachrichtigungen'),
subtitle: Text(room.displayName, overflow: TextOverflow.ellipsis),
),
children: (_) => [
for (final level in selectableNotificationLevels)
AsyncListTile(
leading: Icon(
level == current
? Icons.radio_button_checked
: Icons.radio_button_unchecked,
),
title: Text(level.label),
subtitle: Text(level.description),
onPressed: () async {
if (level == current) return;
await bloc.setNotificationLevel(room.token, level);
selected = level;
},
),
],
);
return selected;
}
class NotificationLevelTile extends StatelessWidget {
final NotificationLevel level;
final VoidCallback onTap;
final Widget? trailing;
const NotificationLevelTile({
required this.level,
required this.onTap,
this.trailing,
super.key,
});
@override
Widget build(BuildContext context) => ListTile(
leading: Icon(level.icon),
title: const Text('Benachrichtigungen'),
subtitle: Text(level.label),
trailing: trailing,
onTap: onTap,
);
}