Files
Client/lib/state/app/modules/app_modules.dart
T

187 lines
6.6 KiB
Dart

import 'package:badges/badges.dart' as badges;
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:persistent_bottom_nav_bar_v2/persistent_bottom_nav_bar_v2.dart';
import '../../../api/mhsl/breaker/get_breakers/get_breakers_response.dart';
import '../../../routing/app_routes.dart';
import '../../../view/pages/files/files.dart';
import '../../../view/pages/grade_averages/grade_averages_view.dart';
import '../../../view/pages/holidays/holidays_view.dart';
import '../../../view/pages/marianum_dates/marianum_dates_view.dart';
import '../../../view/pages/marianum_message/marianum_message_list_view.dart';
import '../../../view/pages/more/roomplan/roomplan.dart';
import '../../../view/pages/talk/chat_list.dart';
import '../../../view/pages/timetable/timetable.dart';
import '../../../widget/breaker/breaker.dart';
import '../../../widget/centered_leading.dart';
import '../infrastructure/loadable_state/loadable_state.dart';
import 'chat_list/bloc/chat_list_bloc.dart';
import 'chat_list/bloc/chat_list_state.dart';
import 'settings/bloc/settings_cubit.dart';
class AppModule {
Modules module;
String name;
Widget Function() icon;
BreakerArea breakerArea;
Widget Function() create;
AppModule(this.module, {required this.name, required this.icon, this.breakerArea = BreakerArea.global, required this.create});
static Map<Modules, AppModule> modules(BuildContext context, {bool showFiltered = false}) {
final settings = context.read<SettingsCubit>();
var available = {
Modules.timetable: AppModule(
Modules.timetable,
name: 'Stundenplan',
icon: () => Icon(Icons.calendar_month),
breakerArea: BreakerArea.timetable,
create: Timetable.new,
),
Modules.talk: AppModule(
Modules.talk,
name: 'Talk',
icon: () => BlocBuilder<ChatListBloc, LoadableState<ChatListState>>(
builder: (context, state) {
final rooms = state.data?.rooms;
if (rooms == null || rooms.data.isEmpty) return const Icon(Icons.chat);
final messages = rooms.data.map((e) => e.unreadMessages).reduce((a, b) => a + b);
return badges.Badge(
showBadge: messages > 0,
position: badges.BadgePosition.topEnd(top: -3, end: -3),
stackFit: StackFit.loose,
badgeStyle: badges.BadgeStyle(
padding: const EdgeInsets.all(3),
badgeColor: Theme.of(context).primaryColor,
elevation: 1,
),
badgeContent: Text('$messages', style: const TextStyle(color: Colors.white, fontSize: 10, fontWeight: FontWeight.bold)),
child: const Icon(Icons.chat),
);
},
),
breakerArea: BreakerArea.talk,
create: ChatList.new,
),
Modules.files: AppModule(
Modules.files,
name: 'Dateien',
icon: () => Icon(Icons.folder),
breakerArea: BreakerArea.files,
create: Files.new,
),
Modules.marianumMessage: AppModule(
Modules.marianumMessage,
name: 'Marianum Message',
icon: () => Icon(Icons.newspaper),
breakerArea: BreakerArea.more,
create: MarianumMessageListView.new,
),
Modules.roomPlan: AppModule(
Modules.roomPlan,
name: 'Raumplan',
icon: () => Icon(Icons.location_pin),
breakerArea: BreakerArea.more,
create: Roomplan.new,
),
Modules.gradeAveragesCalculator: AppModule(
Modules.gradeAveragesCalculator,
name: 'Notendurschnittsrechner',
icon: () => Icon(Icons.calculate),
breakerArea: BreakerArea.more,
create: GradeAveragesView.new,
),
Modules.holidays: AppModule(
Modules.holidays,
name: 'Schulferien',
icon: () => Icon(Icons.flight),
breakerArea: BreakerArea.more,
create: HolidaysView.new,
),
Modules.marianumDates: AppModule(
Modules.marianumDates,
name: 'Marianum Termine',
icon: () => Icon(Icons.event_note),
breakerArea: BreakerArea.more,
create: MarianumDatesView.new,
),
};
if (!showFiltered) available.removeWhere((key, value) => settings.val().modulesSettings.hiddenModules.contains(key));
return { for (var element in settings.val().modulesSettings.moduleOrder.where((element) => available.containsKey(element))) element : available[element]! };
}
static const int minBottomBarSlots = 3;
static const int maxBottomBarSlots = 5;
static int resolveBottomBarSlotCount(BuildContext context) {
final settings = context.read<SettingsCubit>().val().modulesSettings;
final available = modules(context).length;
int desired;
if (settings.autoFillBottomBar) {
final width = MediaQuery.of(context).size.width;
if (width >= 840) {
desired = 5;
} else if (width >= 600) {
desired = 4;
} else {
desired = 3;
}
} else {
desired = settings.fixedBottomBarSlots;
}
desired = desired.clamp(minBottomBarSlots, maxBottomBarSlots);
return desired.clamp(0, available);
}
static List<AppModule> getBottomBarModules(BuildContext context) {
final all = modules(context).values.toList();
final slots = resolveBottomBarSlotCount(context);
return all.take(slots).toList();
}
static List<AppModule> getOverhangModules(BuildContext context) {
final all = modules(context).values.toList();
final slots = resolveBottomBarSlotCount(context);
return all.skip(slots).toList();
}
Widget toListTile(BuildContext context, {Key? key, bool isReorder = false, Function()? onVisibleChange, bool isVisible = true}) => ListTile(
key: key,
leading: CenteredLeading(icon()),
title: Text(name),
onTap: isReorder ? null : () => AppRoutes.openModule(context, this),
trailing: isReorder
? Row(mainAxisSize: MainAxisSize.min, children: [
IconButton(onPressed: onVisibleChange, icon: Icon(isVisible ? Icons.visibility_outlined : Icons.visibility_off_outlined)),
Icon(Icons.drag_handle_outlined)
])
: const Icon(Icons.arrow_right),
);
PersistentTabConfig toBottomTab(BuildContext context, {Widget Function(IconData icon)? iconBuilder}) => PersistentTabConfig(
screen: Breaker(breaker: breakerArea, child: create()),
item: ItemConfig(
activeForegroundColor: Theme.of(context).primaryColor,
inactiveForegroundColor: Theme.of(context).colorScheme.secondary,
icon: icon(),
title: name
),
);
}
enum Modules {
timetable,
talk,
files,
marianumMessage,
roomPlan,
gradeAveragesCalculator,
holidays,
marianumDates,
}