diff --git a/lib/api/marianumconnect/queries/timetable_get_week/timetable_get_week_response.dart b/lib/api/marianumconnect/queries/timetable_get_week/timetable_get_week_response.dart index 48bcc7e..e5b5011 100644 --- a/lib/api/marianumconnect/queries/timetable_get_week/timetable_get_week_response.dart +++ b/lib/api/marianumconnect/queries/timetable_get_week/timetable_get_week_response.dart @@ -10,12 +10,17 @@ class McTimetableTeacher { final String displayName; final String? originalShortName; final String? originalDisplayName; + // Webuntis element ids; null from servers that predate them. + final int? id; + final int? originalId; McTimetableTeacher({ required this.shortName, required this.displayName, this.originalShortName, this.originalDisplayName, + this.id, + this.originalId, }); factory McTimetableTeacher.fromJson(Map json) => @@ -45,6 +50,8 @@ class McTimetableEntry { final String? substitutionText; final String? lessonText; final String? infoText; + // Index-aligned with [classNames]; null from servers that predate it. + final List? classIds; McTimetableEntry({ required this.id, @@ -60,6 +67,7 @@ class McTimetableEntry { required this.substitutionText, required this.lessonText, required this.infoText, + this.classIds, }); factory McTimetableEntry.fromJson(Map json) => diff --git a/lib/api/marianumconnect/queries/timetable_get_week/timetable_get_week_response.g.dart b/lib/api/marianumconnect/queries/timetable_get_week/timetable_get_week_response.g.dart index 96edde4..d32bd40 100644 --- a/lib/api/marianumconnect/queries/timetable_get_week/timetable_get_week_response.g.dart +++ b/lib/api/marianumconnect/queries/timetable_get_week/timetable_get_week_response.g.dart @@ -12,6 +12,8 @@ McTimetableTeacher _$McTimetableTeacherFromJson(Map json) => displayName: json['displayName'] as String, originalShortName: json['originalShortName'] as String?, originalDisplayName: json['originalDisplayName'] as String?, + id: (json['id'] as num?)?.toInt(), + originalId: (json['originalId'] as num?)?.toInt(), ); Map _$McTimetableTeacherToJson(McTimetableTeacher instance) => @@ -20,6 +22,8 @@ Map _$McTimetableTeacherToJson(McTimetableTeacher instance) => 'displayName': instance.displayName, 'originalShortName': instance.originalShortName, 'originalDisplayName': instance.originalDisplayName, + 'id': instance.id, + 'originalId': instance.originalId, }; McTimetableEntry _$McTimetableEntryFromJson(Map json) => @@ -43,6 +47,9 @@ McTimetableEntry _$McTimetableEntryFromJson(Map json) => substitutionText: json['substitutionText'] as String?, lessonText: json['lessonText'] as String?, infoText: json['infoText'] as String?, + classIds: (json['classIds'] as List?) + ?.map((e) => (e as num).toInt()) + .toList(), ); Map _$McTimetableEntryToJson(McTimetableEntry instance) => @@ -60,6 +67,7 @@ Map _$McTimetableEntryToJson(McTimetableEntry instance) => 'substitutionText': instance.substitutionText, 'lessonText': instance.lessonText, 'infoText': instance.infoText, + 'classIds': instance.classIds, }; TimetableGetWeekResponse _$TimetableGetWeekResponseFromJson( diff --git a/lib/main.dart b/lib/main.dart index 2eafc98..235cb10 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -36,6 +36,7 @@ import 'routing/app_routes.dart'; import 'share_intent/share_intent_listener.dart'; import 'state/app/modules/account/bloc/account_bloc.dart'; import 'state/app/modules/account/bloc/account_state.dart'; +import 'state/app/modules/app_modules.dart'; import 'state/app/modules/breaker/bloc/breaker_bloc.dart'; import 'state/app/modules/capabilities/bloc/capabilities_cubit.dart'; import 'state/app/modules/chat/bloc/chat_bloc.dart'; @@ -295,7 +296,9 @@ class _MainState extends State
{ unawaited( context.read().load().then((_) { if (!mounted) return; - _syncPush(settingsCubit, context.read()); + final capabilities = context.read(); + _syncPush(settingsCubit, capabilities); + _applyRoleDefaults(settingsCubit, capabilities); }), ); unawaited(context.read().load()); @@ -331,6 +334,19 @@ class _MainState extends State
{ ); } + /// userType is only known once capabilities are loaded. + void _applyRoleDefaults( + SettingsCubit settings, + CapabilitiesCubit capabilities, + ) { + if (AppModule.applyTeacherDefaults( + settings.val().modulesSettings, + isTeacher: capabilities.isTeacher, + )) { + settings.val(write: true); + } + } + /// Background credential check: a 401 means the password was rotated /// server-side, so the validator wipes the local session and flips the /// account bloc to `loggedOut` (sending the user to the login screen). @@ -424,6 +440,7 @@ class _MainState extends State
{ capabilitiesCubit.load().then((_) { if (!mounted) return; _syncPush(settingsCubit, capabilitiesCubit); + _applyRoleDefaults(settingsCubit, capabilitiesCubit); }), ); unawaited( diff --git a/lib/state/app/modules/app_modules.dart b/lib/state/app/modules/app_modules.dart index 59c8c67..97e94fa 100644 --- a/lib/state/app/modules/app_modules.dart +++ b/lib/state/app/modules/app_modules.dart @@ -188,6 +188,27 @@ class AppModule { return order; } + /// Modules that are of no use to teachers and start out hidden for them. + static const Set hiddenForTeachersByDefault = { + Modules.absenceReport, + }; + + /// Hides [hiddenForTeachersByDefault] once for teacher accounts; the teacher + /// can re-enable them in the module settings. Returns whether [settings] + /// changed. + static bool applyTeacherDefaults( + ModulesSettings settings, { + required bool isTeacher, + }) { + if (!isTeacher || settings.teacherDefaultsApplied) return false; + settings.hiddenModules = { + ...settings.hiddenModules, + ...hiddenForTeachersByDefault, + }.toList(); + settings.teacherDefaultsApplied = true; + return true; + } + // The settings list displays a capability-filtered subset, so reorder // indices refer to that subset; the move is applied there and merged back // into the full order (non-displayed modules keep their relative slots). diff --git a/lib/storage/modules_settings.dart b/lib/storage/modules_settings.dart index 0706b9c..a3bc941 100644 --- a/lib/storage/modules_settings.dart +++ b/lib/storage/modules_settings.dart @@ -10,12 +10,16 @@ class ModulesSettings { List hiddenModules; bool autoFillBottomBar; int fixedBottomBarSlots; + // Set once the teacher module defaults were applied, so a module the teacher + // re-enables afterwards stays visible. + bool teacherDefaultsApplied; ModulesSettings({ required this.moduleOrder, required this.hiddenModules, this.autoFillBottomBar = true, this.fixedBottomBarSlots = 3, + this.teacherDefaultsApplied = false, }); factory ModulesSettings.fromJson(Map json) => diff --git a/lib/storage/modules_settings.g.dart b/lib/storage/modules_settings.g.dart index 20ea811..fe9b776 100644 --- a/lib/storage/modules_settings.g.dart +++ b/lib/storage/modules_settings.g.dart @@ -16,6 +16,7 @@ ModulesSettings _$ModulesSettingsFromJson(Map json) => .toList(), autoFillBottomBar: json['autoFillBottomBar'] as bool? ?? true, fixedBottomBarSlots: (json['fixedBottomBarSlots'] as num?)?.toInt() ?? 3, + teacherDefaultsApplied: json['teacherDefaultsApplied'] as bool? ?? false, ); Map _$ModulesSettingsToJson( @@ -27,6 +28,7 @@ Map _$ModulesSettingsToJson( .toList(), 'autoFillBottomBar': instance.autoFillBottomBar, 'fixedBottomBarSlots': instance.fixedBottomBarSlots, + 'teacherDefaultsApplied': instance.teacherDefaultsApplied, }; const _$ModulesEnumMap = { diff --git a/lib/view/pages/timetable/data/lesson_merger.dart b/lib/view/pages/timetable/data/lesson_merger.dart index bb5ab06..03f1e28 100644 --- a/lib/view/pages/timetable/data/lesson_merger.dart +++ b/lib/view/pages/timetable/data/lesson_merger.dart @@ -73,5 +73,6 @@ class LessonMerger { substitutionText: source.substitutionText, lessonText: source.lessonText, infoText: source.infoText, + classIds: source.classIds, ); } diff --git a/lib/view/pages/timetable/data/timetable_appointment_factory.dart b/lib/view/pages/timetable/data/timetable_appointment_factory.dart index 307ef28..c7ea181 100644 --- a/lib/view/pages/timetable/data/timetable_appointment_factory.dart +++ b/lib/view/pages/timetable/data/timetable_appointment_factory.dart @@ -240,12 +240,14 @@ class TimetableAppointmentFactory { String _locationLabel(McTimetableEntry lesson) { final roomName = collapseWhitespace(lesson.rooms.firstOrNull) ?? 'Unbekannt'; - // Klassenlose Einträge (Aufsichten etc.) fallen auf den Lehrer zurück. - final secondLine = - (showClassInsteadOfTeacher ? lesson.classLabel : null) ?? - _teacherLabel(lesson.teachers.firstOrNull) ?? - 'Unbekannt'; - return '$roomName\n$secondLine'; + if (showClassInsteadOfTeacher) { + // Klassenlose Einträge (Aufsichten etc.) zeigen nur den Raum — die + // Lehrkraft wäre hier die Plan-Inhaberin selbst. + final classLabel = lesson.classLabel; + return classLabel == null ? roomName : '$roomName\n$classLabel'; + } + final teacher = _teacherLabel(lesson.teachers.firstOrNull) ?? 'Unbekannt'; + return '$roomName\n$teacher'; } /// Backend serves teachers with their full display name ("Stefan Müller"), diff --git a/lib/view/pages/timetable/details/appointment_details_dispatcher.dart b/lib/view/pages/timetable/details/appointment_details_dispatcher.dart index de8edd0..c02cc08 100644 --- a/lib/view/pages/timetable/details/appointment_details_dispatcher.dart +++ b/lib/view/pages/timetable/details/appointment_details_dispatcher.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_calendar/calendar.dart'; +import '../../../../api/marianumconnect/queries/timetable_get_element_week/timetable_element_type.dart'; import '../../../../state/app/modules/timetable/bloc/timetable_state.dart'; import '../data/arbitrary_appointment.dart'; import 'custom_event_sheet.dart'; @@ -12,6 +13,8 @@ class AppointmentDetailsDispatcher { TimetableState? state, Appointment appointment, { bool canEditSubjectColor = false, + bool teacherPlan = false, + void Function(TimetableElementRef element)? onOpenElement, }) { final id = appointment.id; if (id is! ArbitraryAppointment) return; @@ -23,6 +26,8 @@ class AppointmentDetailsDispatcher { appointment, entry, canEditSubjectColor: canEditSubjectColor, + teacherPlan: teacherPlan, + onOpenElement: onOpenElement, ), custom: (event) => CustomEventSheet.show(context, event), ); diff --git a/lib/view/pages/timetable/details/lesson_sheet.dart b/lib/view/pages/timetable/details/lesson_sheet.dart index bcd399c..d402d04 100644 --- a/lib/view/pages/timetable/details/lesson_sheet.dart +++ b/lib/view/pages/timetable/details/lesson_sheet.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncfusion_flutter_calendar/calendar.dart'; +import '../../../../api/marianumconnect/queries/timetable_get_element_week/timetable_element_type.dart'; import '../../../../api/marianumconnect/queries/timetable_get_week/timetable_get_week_response.dart'; import '../../../../extensions/date_time.dart'; import '../../../../extensions/text.dart'; @@ -21,6 +22,8 @@ class LessonSheet { Appointment appointment, McTimetableEntry lesson, { bool canEditSubjectColor = false, + bool teacherPlan = false, + void Function(TimetableElementRef element)? onOpenElement, }) { if (state == null) return; @@ -72,7 +75,7 @@ class LessonSheet { ) : null, ), - children: (_) => [ + children: (sheetContext) => [ ListTile( leading: const Icon(Icons.notifications_active), title: Text('Status: ${_statusLabel(lesson.status)}'), @@ -88,13 +91,14 @@ class LessonSheet { .toList(), ), _roomTile(context, lesson), - _teacherTile(context, lesson), - if (lesson.classNames.isNotEmpty) - _listTile( - icon: Icons.people, - label: lesson.classNames.length == 1 ? 'Klasse' : 'Klassen', - entries: lesson.classNames.map(_line).toList(), - ), + ..._peopleTiles( + context, + lesson, + opener: onOpenElement == null + ? null + : _ElementOpener(sheetContext, onOpenElement), + teacherPlan: teacherPlan, + ), ..._optionalTextTiles(lesson), DebugTile(context).jsonData(lesson.toJson()), ], @@ -128,7 +132,59 @@ class LessonSheet { ); } - static Widget _teacherTile(BuildContext context, McTimetableEntry lesson) { + // Aus Lehrersicht ist die Klasse die relevante Angabe, die Lehrkraft ist + // meist die Plan-Inhaberin selbst — daher dort Klasse zuerst. + static List _peopleTiles( + BuildContext context, + McTimetableEntry lesson, { + required _ElementOpener? opener, + required bool teacherPlan, + }) { + final classTile = _classTile(lesson, opener); + final teacherTile = _teacherTile( + context, + lesson, + opener, + teacherPlan: teacherPlan, + ); + return teacherPlan ? [?classTile, teacherTile] : [teacherTile, ?classTile]; + } + + static Widget? _classTile(McTimetableEntry lesson, _ElementOpener? opener) { + final names = lesson.classNames; + if (names.isEmpty) return null; + const tooltip = 'Stundenplan der Klasse öffnen'; + final ids = lesson.classIds?.length == names.length + ? lesson.classIds + : null; + TimetableElementRef? element(int i) => ids == null + ? null + : (type: TimetableElementType.schoolClass, id: ids[i], label: names[i]); + + return _listTile( + icon: Icons.people, + label: names.length == 1 ? 'Klasse' : 'Klassen', + entries: names.map(_line).toList(), + trailing: names.length == 1 + ? opener?.button(tooltip: tooltip, element: element(0)) + : null, + wrapRow: (i, row) => _openable(opener, row, tooltip, element(i)), + ); + } + + static Widget _openable( + _ElementOpener? opener, + Widget label, + String tooltip, + TimetableElementRef? element, + ) => opener?.row(label: label, tooltip: tooltip, element: element) ?? label; + + static Widget _teacherTile( + BuildContext context, + McTimetableEntry lesson, + _ElementOpener? opener, { + required bool teacherPlan, + }) { if (lesson.teachers.isEmpty) { return const ListTile( leading: Icon(Icons.person), @@ -146,12 +202,17 @@ class LessonSheet { } final label = teachers.length == 1 ? 'Lehrkraft' : 'Lehrkräfte'; + const tooltip = 'Stundenplan der Lehrkraft öffnen'; // Einzelne, reguläre Lehrkraft kompakt in der Titelzeile. if (teachers.length == 1 && teachers.first.isPlain) { return ListTile( leading: const Icon(Icons.person), title: Text('$label: ${teachers.first.after}'), + // Im Lehrerplan ist das die Plan-Inhaberin selbst. + trailing: teacherPlan + ? null + : opener?.button(tooltip: tooltip, element: teachers.first.target), ); } @@ -160,7 +221,10 @@ class LessonSheet { title: Text(label), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [for (final t in teachers) t.buildRow(context)], + children: [ + for (final t in teachers) + _openable(opener, t.buildRow(context), tooltip, t.target), + ], ), ); } @@ -207,6 +271,7 @@ class LessonSheet { required String label, required List entries, Widget? trailing, + Widget Function(int index, Widget row)? wrapRow, }) { if (entries.length == 1) { return ListTile( @@ -220,7 +285,10 @@ class LessonSheet { title: Text(label), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, - children: entries.map(Text.new).toList(), + children: [ + for (final (i, entry) in entries.indexed) + wrapRow?.call(i, Text(entry)) ?? Text(entry), + ], ), trailing: trailing, ); @@ -333,7 +401,15 @@ class _TeacherDisplay { /// Aktuelle Lehrkraft. Leer bei ersatzlosem Entfall. final String after; - const _TeacherDisplay._({this.before = '', this.after = ''}); + /// Lehrkraft, deren Stundenplan sich öffnen lässt: die aktuelle, bei + /// ersatzlosem Entfall die ursprüngliche. Null, wenn beide unbekannt sind. + final TimetableElementRef? target; + + const _TeacherDisplay._({ + this.before = '', + this.after = '', + this.target, + }); bool get isPlain => before.isEmpty; @@ -345,14 +421,32 @@ class _TeacherDisplay { t.originalShortName ?? '', t.originalDisplayName ?? '', ); + final target = _target(t, currentKnown: current.isNotEmpty); // Kein (abweichendes) Original → reguläre Lehrkraft. if (original.isEmpty || original == current) { - return _TeacherDisplay._(after: current.isEmpty ? '?' : current); + return _TeacherDisplay._( + after: current.isEmpty ? '?' : current, + target: target, + ); } // Original vorhanden → ersetzte/entfallende Lehrkraft vorn, aktuelle // Lehrkraft (falls vorhanden) als Ersatz dahinter. - return _TeacherDisplay._(before: original, after: current); + return _TeacherDisplay._( + before: original, + after: current, + target: target, + ); + } + + static TimetableElementRef? _target( + McTimetableTeacher t, { + required bool currentKnown, + }) { + final id = currentKnown ? t.id : t.originalId; + if (id == null) return null; + final label = currentKnown ? t.displayName : t.originalDisplayName; + return (type: TimetableElementType.teacher, id: id, label: label ?? ''); } /// Eine Bullet-Zeile je Lehrkraft: ersetzte Person durchgestrichen, bei @@ -404,3 +498,58 @@ class _TeacherDisplay { return short; } } + +/// Baut die Bedienelemente, die aus dem Sheet heraus einen fremden +/// Stundenplan öffnen. Ohne Element-Id (älterer Server) entfallen sie. +class _ElementOpener { + static const IconData icon = Icons.calendar_view_week_outlined; + + final BuildContext sheetContext; + final void Function(TimetableElementRef element) onOpen; + + const _ElementOpener(this.sheetContext, this.onOpen); + + void _open(TimetableElementRef element) { + Navigator.of(sheetContext).pop(); + onOpen(element); + } + + /// Trailing-Button für einzeilige Tiles, analog zum Raumplan-Button. + Widget? button({ + required String tooltip, + required TimetableElementRef? element, + }) { + if (element == null) return null; + return IconButton( + icon: const Icon(icon), + tooltip: tooltip, + onPressed: () => _open(element), + ); + } + + /// Kompakte, vollständig antippbare Zeile für Aufzählungen — ein + /// 48px-Button pro Eintrag würde die Liste auseinanderziehen. + Widget row({ + required Widget label, + required String tooltip, + required TimetableElementRef? element, + }) { + if (element == null) return label; + final muted = Theme.of(sheetContext).colorScheme.onSurfaceVariant; + return Semantics( + button: true, + label: tooltip, + child: InkWell( + onTap: () => _open(element), + borderRadius: BorderRadius.circular(6), + child: Row( + children: [ + Expanded(child: label), + const SizedBox(width: 8), + Icon(icon, size: 18, color: muted), + ], + ), + ), + ); + } +} diff --git a/lib/view/pages/timetable/timetable.dart b/lib/view/pages/timetable/timetable.dart index 46f4f74..366942a 100644 --- a/lib/view/pages/timetable/timetable.dart +++ b/lib/view/pages/timetable/timetable.dart @@ -46,6 +46,10 @@ class _TimetableState extends State { if (guardDemoAction(context)) return; final ref = await AppRoutes.openElementPicker(context); if (!mounted || ref == null) return; + _openElement(ref); + } + + void _openElement(TimetableElementRef ref) { setState(() => _selected = ref); } @@ -103,6 +107,7 @@ class _TimetableState extends State { final atToday = innerState != null && _isOnInitialWeek(innerState); final capabilities = context.watch(); final canViewForeign = capabilities.canViewForeignTimetables; + final teacherPlan = capabilities.isTeacher; return Scaffold( appBar: AppBar( // Der Kalender scrollt nicht (nur ziehen/reloaden), aber seine internen @@ -162,10 +167,12 @@ class _TimetableState extends State { state, apt, canEditSubjectColor: true, + teacherPlan: teacherPlan, + onOpenElement: canViewForeign ? _openElement : null, ), onCreateEvent: _onCreateEventAt, customEvents: state.customEvents?.events ?? const [], - showClassInsteadOfTeacher: capabilities.isTeacher, + showClassInsteadOfTeacher: teacherPlan, ), ), ); @@ -179,6 +186,7 @@ class _TimetableState extends State { final canViewForeign = context .watch() .canViewForeignTimetables; + final teacherPlan = selected.type == TimetableElementType.teacher; return Scaffold( appBar: AppBar( // Siehe _buildOwnPlan: den scroll-under-Farbwechsel unterdrücken, weil @@ -214,11 +222,15 @@ class _TimetableState extends State { key: _calendarKey, state: state, onWeekChanged: bloc.changeWeek, - onAppointmentTap: (apt) => - AppointmentDetailsDispatcher.show(context, state, apt), + onAppointmentTap: (apt) => AppointmentDetailsDispatcher.show( + context, + state, + apt, + teacherPlan: teacherPlan, + onOpenElement: canViewForeign ? _openElement : null, + ), customEvents: const [], - showClassInsteadOfTeacher: - selected.type == TimetableElementType.teacher, + showClassInsteadOfTeacher: teacherPlan, ), ), ), diff --git a/lib/widget_data/widget_data_mapper.dart b/lib/widget_data/widget_data_mapper.dart index 080a444..eb30bda 100644 --- a/lib/widget_data/widget_data_mapper.dart +++ b/lib/widget_data/widget_data_mapper.dart @@ -350,11 +350,12 @@ class WidgetDataMapper { } final teacher = lesson.teachers.firstOrNull; // Lehrerpläne: Klasse in den Teacher-Slot mappen, damit die nativen - // Renderer unverändert bleiben. Klassenlose Einträge (Aufsichten) behalten - // den Lehrer als Fallback. - final classLabel = showClassInsteadOfTeacher ? lesson.classLabel : null; - final teacherName = classLabel ?? teacher?.shortName; - final originalTeacher = classLabel != null + // Renderer unverändert bleiben. Klassenlose Einträge (Aufsichten) lassen + // den Slot leer — die Lehrkraft wäre die Plan-Inhaberin selbst. + final teacherName = showClassInsteadOfTeacher + ? lesson.classLabel + : teacher?.shortName; + final originalTeacher = showClassInsteadOfTeacher ? null : teacher?.originalShortName; return WidgetLesson( diff --git a/test/state/app_modules_order_test.dart b/test/state/app_modules_order_test.dart index 7732c79..74eb134 100644 --- a/test/state/app_modules_order_test.dart +++ b/test/state/app_modules_order_test.dart @@ -92,4 +92,47 @@ void main() { ); }); }); + + group('applyTeacherDefaults', () { + test('hides the absence report once for teachers', () { + final settings = settingsWith(Modules.values); + + expect(AppModule.applyTeacherDefaults(settings, isTeacher: true), isTrue); + expect(settings.hiddenModules, [Modules.absenceReport]); + expect(settings.teacherDefaultsApplied, isTrue); + }); + + test('keeps a module the teacher re-enabled afterwards', () { + final settings = settingsWith(Modules.values); + AppModule.applyTeacherDefaults(settings, isTeacher: true); + settings.hiddenModules.remove(Modules.absenceReport); + + expect( + AppModule.applyTeacherDefaults(settings, isTeacher: true), + isFalse, + ); + expect(settings.hiddenModules, isEmpty); + }); + + test('leaves non-teachers untouched', () { + final settings = settingsWith(Modules.values); + + expect( + AppModule.applyTeacherDefaults(settings, isTeacher: false), + isFalse, + ); + expect(settings.hiddenModules, isEmpty); + expect(settings.teacherDefaultsApplied, isFalse); + }); + + test('does not duplicate an already hidden module', () { + final settings = ModulesSettings( + moduleOrder: Modules.values, + hiddenModules: [Modules.absenceReport, Modules.files], + ); + AppModule.applyTeacherDefaults(settings, isTeacher: true); + + expect(settings.hiddenModules, [Modules.absenceReport, Modules.files]); + }); + }); } diff --git a/test/view/timetable/teacher_class_label_test.dart b/test/view/timetable/teacher_class_label_test.dart index f6cf531..e56d9fc 100644 --- a/test/view/timetable/teacher_class_label_test.dart +++ b/test/view/timetable/teacher_class_label_test.dart @@ -65,10 +65,10 @@ void main() { ); }); - test('falls back to the teacher when the entry has no class', () { + test('shows only the room when the entry has no class', () { expect( _location(showClassInsteadOfTeacher: true, classNames: const []), - 'A101\nMüller', + 'A101', ); }); });