implemented foreign timetable support for students, teachers, rooms, and classes, including a searchable element picker with favorites support, introduced a capabilities system for feature gating, refactored the timetable UI into a reusable TimetableCalendarView component, and redesigned the chat input field with a unified emoji picker and integrated attachment actions.

This commit is contained in:
2026-05-31 21:29:16 +02:00
parent 6e12da08c0
commit b6d06dd3b4
41 changed files with 2325 additions and 290 deletions
+20
View File
@@ -4,6 +4,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:persistent_bottom_nav_bar_v2/persistent_bottom_nav_bar_v2.dart';
import '../api/marianumcloud/talk/room/get_room_response.dart';
import '../api/marianumconnect/queries/timetable_get_element_week/timetable_element_type.dart';
import '../main.dart';
import '../model/account_data.dart';
import '../notification/notification_tasks.dart';
@@ -14,6 +15,7 @@ import '../state/app/modules/chat/bloc/chat_bloc.dart';
import '../state/app/modules/chat_list/bloc/chat_list_bloc.dart';
import '../state/app/modules/marianum_message/bloc/marianum_message_state.dart';
import '../view/pages/files/files.dart';
import '../view/pages/foreign_timetable/element_picker_page.dart';
import '../view/pages/marianum_message/marianum_message_view.dart';
import '../view/pages/more/feedback/feedback_dialog.dart';
import '../view/pages/more/roomplan/roomplan.dart';
@@ -71,6 +73,24 @@ class AppRoutes {
pushScreen(context, withNavBar: false, screen: const CustomEventsView());
}
/// Opens the picker for choosing a foreign timetable element and resolves to
/// the selected element (or null if dismissed). The timetable view renders
/// the chosen plan inline. Gated behind the `viewForeignTimetables`
/// capability at the call site.
static Future<TimetableElementRef?> openElementPicker(
BuildContext context,
) async {
// pushScreen casts its internal MaterialPageRoute to `Route<T>`, which
// blows up for a concrete (record) T — so push untyped (T = dynamic, like
// every other caller) and cast the popped result ourselves.
final result = await pushScreen(
context,
withNavBar: false,
screen: const ElementPickerPage(),
);
return result as TimetableElementRef?;
}
static void openMarianumMessage(
BuildContext context,
String basePath,