diff --git a/lib/api/marianumcloud/talk/talkApi.dart b/lib/api/marianumcloud/talk/talkApi.dart index cc0ef16..ec01893 100644 --- a/lib/api/marianumcloud/talk/talkApi.dart +++ b/lib/api/marianumcloud/talk/talkApi.dart @@ -47,7 +47,7 @@ abstract class TalkApi extends ApiRequest { if(data.statusCode >= 400 || data.statusCode < 200) throw Exception("Response status code '${data.statusCode}' might indicate an error"); } catch(e) { log(e.toString()); - throw ApiError("Request could not be dispatched: ${e.toString()}"); + throw ApiError("Request $endpoint could not be dispatched: ${e.toString()}"); } //dynamic jsonData = jsonDecode(data.body); diff --git a/lib/api/mhsl/mhslApi.dart b/lib/api/mhsl/mhslApi.dart index 64f6270..422ea1e 100644 --- a/lib/api/mhsl/mhslApi.dart +++ b/lib/api/mhsl/mhslApi.dart @@ -1,5 +1,4 @@ import 'dart:convert'; -import 'dart:developer'; import 'package:http/http.dart' as http; import '../apiError.dart'; @@ -23,7 +22,7 @@ abstract class MhslApi extends ApiRequest { } if(data.statusCode > 299) { - log("Non 200 Status code from mhsl services: $subpath: ${data.statusCode}"); + throw ApiError("Non 200 Status code from mhsl services: $subpath: ${data.statusCode}"); } return assemble(utf8.decode(data.bodyBytes)); diff --git a/lib/api/mhsl/server/feedback/addFeedback.dart b/lib/api/mhsl/server/feedback/addFeedback.dart new file mode 100644 index 0000000..679627a --- /dev/null +++ b/lib/api/mhsl/server/feedback/addFeedback.dart @@ -0,0 +1,21 @@ +import 'dart:convert'; + +import 'package:http/http.dart'; +import 'package:marianum_mobile/api/mhsl/mhslApi.dart'; +import 'package:http/http.dart' as http; + +import 'addFeedbackParams.dart'; + + +class AddFeedback extends MhslApi { + AddFeedbackParams params; + AddFeedback(this.params) : super('server/feedback'); + + @override + void assemble(String raw) {} + + @override + Future? request(Uri uri) { + return http.post(uri, body: jsonEncode(params.toJson())); + } +} \ No newline at end of file diff --git a/lib/api/mhsl/server/feedback/addFeedbackParams.dart b/lib/api/mhsl/server/feedback/addFeedbackParams.dart new file mode 100644 index 0000000..4f3e8b0 --- /dev/null +++ b/lib/api/mhsl/server/feedback/addFeedbackParams.dart @@ -0,0 +1,20 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'addFeedbackParams.g.dart'; + +@JsonSerializable() +class AddFeedbackParams { + String user; + String feedback; + int appVersion; + + + AddFeedbackParams({ + required this.user, + required this.feedback, + required this.appVersion, + }); + + factory AddFeedbackParams.fromJson(Map json) => _$AddFeedbackParamsFromJson(json); + Map toJson() => _$AddFeedbackParamsToJson(this); +} \ No newline at end of file diff --git a/lib/api/mhsl/server/feedback/addFeedbackParams.g.dart b/lib/api/mhsl/server/feedback/addFeedbackParams.g.dart new file mode 100644 index 0000000..47f2105 --- /dev/null +++ b/lib/api/mhsl/server/feedback/addFeedbackParams.g.dart @@ -0,0 +1,21 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'addFeedbackParams.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +AddFeedbackParams _$AddFeedbackParamsFromJson(Map json) => + AddFeedbackParams( + user: json['user'] as String, + feedback: json['feedback'] as String, + appVersion: json['appVersion'] as int, + ); + +Map _$AddFeedbackParamsToJson(AddFeedbackParams instance) => + { + 'user': instance.user, + 'feedback': instance.feedback, + 'appVersion': instance.appVersion, + }; diff --git a/lib/api/mhsl/server/userIndex/update/updateUserindex.dart b/lib/api/mhsl/server/userIndex/update/updateUserindex.dart index 4500904..b41f4c9 100644 --- a/lib/api/mhsl/server/userIndex/update/updateUserindex.dart +++ b/lib/api/mhsl/server/userIndex/update/updateUserindex.dart @@ -2,9 +2,7 @@ import 'dart:convert'; import 'dart:developer'; -import 'package:crypto/crypto.dart'; import 'package:device_info_plus/device_info_plus.dart'; -import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:http/http.dart' as http; import 'package:package_info/package_info.dart'; @@ -21,18 +19,17 @@ class UpdateUserIndex extends MhslApi { @override Future request(Uri uri) { - return http.post(uri, body: jsonEncode(params.toJson())); + String data = jsonEncode(params.toJson()); + log("Updating userindex:\n $data"); + return http.post(uri, body: data); } static void index() async { - String userId = sha512.convert(utf8.encode("${AccountData().getUsername()}:${AccountData().getPassword()}")).toString(); - String deviceId = sha512.convert(utf8.encode("$userId@${await FirebaseMessaging.instance.getToken()}")).toString(); - log("Userindex:\n userid:$userId\n deviceid:$deviceId"); UpdateUserIndex( UpdateUserIndexParams( username: AccountData().getUsername(), - user: userId, - device: deviceId, + user: AccountData().getUserId(), + device: await AccountData().getDeviceId(), appVersion: int.parse((await PackageInfo.fromPlatform()).buildNumber), deviceInfo: jsonEncode((await DeviceInfoPlugin().deviceInfo).data).toString(), ), diff --git a/lib/app.dart b/lib/app.dart index fabc1e6..58dcedd 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -5,7 +5,7 @@ import 'dart:developer'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/material.dart'; import 'package:marianum_mobile/notification/notificationTasks.dart'; -import 'package:persistent_bottom_nav_bar/persistent_tab_view.dart'; +import 'package:persistent_bottom_nav_bar_v2/persistent-tab-view.dart'; import 'package:provider/provider.dart'; import 'package:badges/badges.dart' as badges; diff --git a/lib/model/accountData.dart b/lib/model/accountData.dart index 9d6cf87..0f6ea35 100644 --- a/lib/model/accountData.dart +++ b/lib/model/accountData.dart @@ -1,5 +1,8 @@ import 'dart:async'; +import 'dart:convert'; +import 'package:crypto/crypto.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/cupertino.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -35,6 +38,14 @@ class AccountData { return _password!; } + String getUserId() { + return sha512.convert(utf8.encode("${AccountData().getUsername()}:${AccountData().getPassword()}")).toString(); + } + + Future getDeviceId() async { + return sha512.convert(utf8.encode("${getUserId()}@${await FirebaseMessaging.instance.getToken()}")).toString(); + } + Future setData(String username, String password) async { SharedPreferences storage = await _storage; diff --git a/lib/model/chatList/chatProps.dart b/lib/model/chatList/chatProps.dart index 87502a4..06442be 100644 --- a/lib/model/chatList/chatProps.dart +++ b/lib/model/chatList/chatProps.dart @@ -18,6 +18,7 @@ class ChatProps extends DataHolder { @override void run() { notifyListeners(); + if(_queryToken.isEmpty) return; DateTime requestStart = DateTime.now(); GetChatCache( @@ -27,7 +28,6 @@ class ChatProps extends DataHolder { _getChatResponse = data; notifyListeners(); - } ); } diff --git a/lib/theming/darkAppTheme.dart b/lib/theming/darkAppTheme.dart index 156b234..a8d33e5 100644 --- a/lib/theming/darkAppTheme.dart +++ b/lib/theming/darkAppTheme.dart @@ -4,51 +4,10 @@ class DarkAppTheme { static const Color marianumRed = Color.fromARGB(255, 153, 51, 51); static final theme = ThemeData( - useMaterial3: false, - brightness: Brightness.dark, - primaryColor: marianumRed, - hintColor: marianumRed, - colorScheme: const ColorScheme( + colorScheme: ColorScheme.fromSeed( + seedColor: marianumRed, brightness: Brightness.dark, - - surface: Colors.black54, - onSurface: Colors.white, - - primary: marianumRed, - onPrimary: Colors.white, - - secondary: Colors.grey, - onSecondary: Colors.white, - - background: Colors.black26, - onBackground: Colors.white, - - error: marianumRed, - onError: marianumRed, - ), - inputDecorationTheme: const InputDecorationTheme( - border: UnderlineInputBorder(borderSide: BorderSide(color: marianumRed)), - ), - appBarTheme: const AppBarTheme( - backgroundColor: marianumRed, - ), - progressIndicatorTheme: const ProgressIndicatorThemeData( - color: marianumRed, - ), - iconButtonTheme: IconButtonThemeData( - style: ButtonStyle( - textStyle: MaterialStateProperty.all(const TextStyle(color: Colors.white)), - backgroundColor: MaterialStateProperty.all(Colors.white), - ) - ), - checkboxTheme: CheckboxThemeData( - fillColor: MaterialStateProperty.resolveWith((states) => states.contains(MaterialState.selected) ? marianumRed : Colors.transparent), - ), - textButtonTheme: TextButtonThemeData( - style: TextButton.styleFrom( - foregroundColor: Colors.white, - backgroundColor: marianumRed.withOpacity(0.5), - ), ), + primaryColor: marianumRed, ); } \ No newline at end of file diff --git a/lib/theming/lightAppTheme.dart b/lib/theming/lightAppTheme.dart index 9ce27ee..09a707a 100644 --- a/lib/theming/lightAppTheme.dart +++ b/lib/theming/lightAppTheme.dart @@ -4,39 +4,10 @@ class LightAppTheme { static const Color marianumRed = Color.fromARGB(255, 153, 51, 51); static final theme = ThemeData( - useMaterial3: false, brightness: Brightness.light, - primaryColor: marianumRed, - - colorScheme: const ColorScheme( - brightness: Brightness.light, - - surface: Colors.white, - onSurface: Colors.black, - - secondary: Colors.grey, - onSecondary: Colors.white, - - primary: marianumRed, - onPrimary: Colors.white, - - background: Colors.white, - onBackground: Colors.black, - - error: marianumRed, - onError: marianumRed, - ), - inputDecorationTheme: const InputDecorationTheme( - border: UnderlineInputBorder(borderSide: BorderSide(color: marianumRed)), - ), - appBarTheme: const AppBarTheme( - backgroundColor: marianumRed, - ), - progressIndicatorTheme: const ProgressIndicatorThemeData( - color: marianumRed, - ), - checkboxTheme: CheckboxThemeData( - fillColor: MaterialStateProperty.resolveWith((states) => states.contains(MaterialState.selected) ? marianumRed : Colors.transparent), - ), + colorScheme: ColorScheme.fromSeed(seedColor: marianumRed), + floatingActionButtonTheme: const FloatingActionButtonThemeData( + foregroundColor: Colors.white + ) ); } \ No newline at end of file diff --git a/lib/view/pages/more/feedback/feedbackDialog.dart b/lib/view/pages/more/feedback/feedbackDialog.dart new file mode 100644 index 0000000..d6d4ceb --- /dev/null +++ b/lib/view/pages/more/feedback/feedbackDialog.dart @@ -0,0 +1,73 @@ + +import 'package:flutter/material.dart'; +import 'package:marianum_mobile/api/mhsl/server/feedback/addFeedback.dart'; +import 'package:marianum_mobile/api/mhsl/server/feedback/addFeedbackParams.dart'; +import 'package:marianum_mobile/model/accountData.dart'; +import 'package:package_info/package_info.dart'; + +class FeedbackDialog extends StatefulWidget { + const FeedbackDialog({super.key}); + + @override + State createState() => _FeedbackDialogState(); +} + +class _FeedbackDialogState extends State { + final TextEditingController _feedbackInput = TextEditingController(); + String? _error; + + @override + Widget build(BuildContext context) { + return AlertDialog( + + title: const Text("Feedback"), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const Text("Feedback, Anregungen, Ideen, Fehler und Verbesserungen"), + const SizedBox(height: 10), + const Text("Bitte gib keine geheimen Daten wie z.B. Passwörter weiter.", style: TextStyle(fontSize: 10)), + const SizedBox(height: 10), + TextField( + controller: _feedbackInput, + autofocus: true, + decoration: const InputDecoration( + border: OutlineInputBorder(), + label: Text("Feedback und Verbesserungen") + ), + // style: TextStyle(), + // expands: true, + minLines: 3, + maxLines: 5, + ), + Visibility( + visible: _error != null, + child: Text("Senden fehlgeschlagen: $_error", style: const TextStyle(color: Colors.red)) + ) + ], + ), + actions: [ + TextButton(onPressed: () => Navigator.of(context).pop(), child: const Text("Abbrechen")), + TextButton( + onPressed: () async { + AddFeedback( + AddFeedbackParams( + user: AccountData().getUserId(), + feedback: _feedbackInput.text, + appVersion: int.parse((await PackageInfo.fromPlatform()).buildNumber) + ) + ) + .run() + .then((value) => Navigator.of(context).pop()) + .catchError((error, trace) { + setState(() { + _error = error.toString(); + }); + }); + }, + child: const Text("Senden"), + ) + ], + ); + } +} diff --git a/lib/view/pages/more/overhang.dart b/lib/view/pages/more/overhang.dart index e5cb068..2922144 100644 --- a/lib/view/pages/more/overhang.dart +++ b/lib/view/pages/more/overhang.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:persistent_bottom_nav_bar/persistent_tab_view.dart'; +import 'package:marianum_mobile/view/pages/more/feedback/feedbackDialog.dart'; +import 'package:marianum_mobile/widget/centeredLeading.dart'; +import 'package:persistent_bottom_nav_bar_v2/persistent-tab-view.dart'; import '../../../widget/ListItem.dart'; import '../../settings/settings.dart'; @@ -20,7 +22,7 @@ class Overhang extends StatelessWidget { appBar: AppBar( title: const Text("Mehr"), actions: [ - IconButton(onPressed: () => PersistentNavBarNavigator.pushNewScreen(context, screen: const Settings(), withNavBar: false), icon: const Icon(Icons.settings)) + IconButton(onPressed: () => pushNewScreen(context, screen: const Settings(), withNavBar: false), icon: const Icon(Icons.settings)) ], ), body: ListView( @@ -36,6 +38,13 @@ class Overhang extends StatelessWidget { trailing: const Icon(Icons.arrow_right), onTap: () => showDialog(context: context, builder: (context) => const SelectShareTypeDialog()) ), + ListTile( + leading: const CenteredLeading(Icon(Icons.feedback_outlined)), + title: const Text("Du hast eine Idee?"), + subtitle: const Text("Fehler und Verbessungsvorschläge"), + trailing: const Icon(Icons.arrow_right), + onTap: () => showDialog(context: context, barrierDismissible: false, builder: (context) => const FeedbackDialog()), + ) ], ), ); diff --git a/lib/view/pages/more/share/selectShareTypeDialog.dart b/lib/view/pages/more/share/selectShareTypeDialog.dart index 7ef5c2b..e8f62e9 100644 --- a/lib/view/pages/more/share/selectShareTypeDialog.dart +++ b/lib/view/pages/more/share/selectShareTypeDialog.dart @@ -22,12 +22,11 @@ class SelectShareTypeDialog extends StatelessWidget { ), ListTile( leading: const Icon(Icons.link_outlined), - title: const Text("Per Link"), + title: const Text("Per Link teilen"), trailing: const Icon(Icons.arrow_right), onTap: () { - final box = context.findRenderObject() as RenderBox?; Share.share( - sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size, + sharePositionOrigin: Rect.fromLTWH(0, 0, MediaQuery.of(context).size.width, MediaQuery.of(context).size.height / 2), subject: "App Teilen", "Hol dir die für das Marianum maßgeschneiderte App:" "\n\nAndroid: https://play.google.com/store/apps/details?id=eu.mhsl.marianum.mobile.client " diff --git a/lib/view/pages/talk/components/chatTextfield.dart b/lib/view/pages/talk/components/chatTextfield.dart index d79aab3..35fe84f 100644 --- a/lib/view/pages/talk/components/chatTextfield.dart +++ b/lib/view/pages/talk/components/chatTextfield.dart @@ -84,9 +84,8 @@ class _ChatTextfieldState extends State { Align( alignment: Alignment.bottomLeft, child: Container( - padding: const EdgeInsets.only(left: 10, bottom: 1, top: 1, right: 10), + padding: const EdgeInsets.only(left: 10, bottom: 3, top: 3, right: 10), width: double.infinity, - color: Theme.of(context).primaryColor, child: Row( children: [ GestureDetector( @@ -135,7 +134,7 @@ class _ChatTextfieldState extends State { color: Theme.of(context).primaryColor, borderRadius: BorderRadius.circular(30), ), - child: const Icon(Icons.add, color: Colors.white, size: 20, ), + child: const Icon(Icons.attach_file_outlined, color: Colors.white, size: 20, ), ), ) ), @@ -144,18 +143,13 @@ class _ChatTextfieldState extends State { child: TextField( autocorrect: true, textCapitalization: TextCapitalization.sentences, - style: const TextStyle( - color: Colors.white, - ), controller: _textBoxController, maxLines: 7, minLines: 1, - decoration: InputDecoration( + decoration: const InputDecoration( hintText: "Nachricht schreiben...", - hintStyle: TextStyle(color: Theme.of(context).colorScheme.onSecondary), border: InputBorder.none, ), - cursorColor: Colors.white, onChanged: (String text) { if(text.trim().toLowerCase() == "marbot marbot marbot") { var newText = "Roboter sind cool und so, aber marbots sind besser!"; diff --git a/lib/view/pages/talk/talkNavigator.dart b/lib/view/pages/talk/talkNavigator.dart index 433ace3..b52661a 100644 --- a/lib/view/pages/talk/talkNavigator.dart +++ b/lib/view/pages/talk/talkNavigator.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_split_view/flutter_split_view.dart'; -import 'package:persistent_bottom_nav_bar/persistent_tab_view.dart'; +import 'package:persistent_bottom_nav_bar_v2/persistent-tab-view.dart'; class TalkNavigator { static bool hasSplitViewState(BuildContext context) => context.findAncestorStateOfType() != null; @@ -12,7 +12,7 @@ class TalkNavigator { SplitViewState splitView = SplitView.of(context); overrideToSingleSubScreen ? splitView.setSecondary(view) : splitView.push(view); } else { - PersistentNavBarNavigator.pushNewScreen(context, screen: view, withNavBar: false); + pushNewScreen(context, screen: view, withNavBar: false); } } } \ No newline at end of file diff --git a/lib/view/pages/timetable/appointmenetComponent.dart b/lib/view/pages/timetable/appointmenetComponent.dart index ba11f3d..5f10906 100644 --- a/lib/view/pages/timetable/appointmenetComponent.dart +++ b/lib/view/pages/timetable/appointmenetComponent.dart @@ -18,10 +18,6 @@ class _AppointmentComponentState extends State { Widget build(BuildContext context) { final Appointment meeting = widget.details.appointments.first; final appointmentHeight = widget.details.bounds.height; - double headerHeight = 50; - const double footerHeight = 5; - final double infoHeight = appointmentHeight - (headerHeight + footerHeight); - if (infoHeight < 0) headerHeight += infoHeight; return Stack( children: [ @@ -29,14 +25,11 @@ class _AppointmentComponentState extends State { children: [ Container( padding: const EdgeInsets.all(3), - height: headerHeight, + height: appointmentHeight, alignment: Alignment.topLeft, decoration: BoxDecoration( shape: BoxShape.rectangle, - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(5), - topRight: Radius.circular(5), - ), + borderRadius: const BorderRadius.all(Radius.circular(5)), color: meeting.color, ), child: SingleChildScrollView( @@ -60,7 +53,7 @@ class _AppointmentComponentState extends State { FittedBox( fit: BoxFit.fitWidth, child: Text( - meeting.location ?? "?", + meeting.location ?? "-", maxLines: 3, overflow: TextOverflow.ellipsis, softWrap: true, @@ -74,45 +67,6 @@ class _AppointmentComponentState extends State { ), ), ), - Visibility( - visible: meeting.notes != null && infoHeight > 10, - replacement: Container( - color: meeting.color, - height: infoHeight, - ), - child: Container( - height: infoHeight, - padding: const EdgeInsets.fromLTRB(3, 5, 3, 2), - color: meeting.color.withOpacity(0.8), - alignment: Alignment.topLeft, - child: SingleChildScrollView( - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - meeting.notes ?? "", - style: const TextStyle( - color: Colors.white, - fontSize: 10, - ), - ) - ], - ), - ), - ), - ), - Container( - height: footerHeight, - decoration: BoxDecoration( - shape: BoxShape.rectangle, - borderRadius: const BorderRadius.only( - bottomLeft: Radius.circular(5), - bottomRight: Radius.circular(5), - ), - color: meeting.color, - ), - ), ], ), Visibility( diff --git a/lib/view/pages/timetable/appointmentDetails.dart b/lib/view/pages/timetable/appointmentDetails.dart index dd3265d..dbfa099 100644 --- a/lib/view/pages/timetable/appointmentDetails.dart +++ b/lib/view/pages/timetable/appointmentDetails.dart @@ -3,7 +3,7 @@ import 'package:bottom_sheet/bottom_sheet.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:jiffy/jiffy.dart'; -import 'package:persistent_bottom_nav_bar/persistent_tab_view.dart'; +import 'package:persistent_bottom_nav_bar_v2/persistent-tab-view.dart'; import 'package:syncfusion_flutter_calendar/calendar.dart'; import '../../../api/webuntis/queries/getRooms/getRoomsResponse.dart'; @@ -49,20 +49,18 @@ class AppointmentDetails { maxHeaderHeight: 150, context: context, - headerBuilder: (context, bottomSheetOffset) => Padding( - padding: const EdgeInsets.symmetric(vertical: 30), - child: Center( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text("${_getEventPrefix(timetableData.code)}${subject.alternateName} - (${subject.longName})", style: const TextStyle(fontSize: 30)), - Text("${Jiffy.parseFromDateTime(appointment.startTime).format(pattern: "HH:mm")} - ${Jiffy.parseFromDateTime(appointment.endTime).format(pattern: "HH:mm")}", style: const TextStyle(fontSize: 15)), - ], - ), + headerBuilder: (context, bottomSheetOffset) => Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text("${_getEventPrefix(timetableData.code)}${subject.alternateName} - (${subject.longName})", style: const TextStyle(fontSize: 25), overflow: TextOverflow.ellipsis), + Text("${Jiffy.parseFromDateTime(appointment.startTime).format(pattern: "HH:mm")} - ${Jiffy.parseFromDateTime(appointment.endTime).format(pattern: "HH:mm")}", style: const TextStyle(fontSize: 15)), + ], ), ), bodyBuilder: (context, bottomSheetOffset) => SliverChildListDelegate( [ + const Divider(), ListTile( leading: const Icon(Icons.notifications_active), title: Text("Status: ${timetableData.code != null ? "Geändert" : "Regulär"}"), @@ -73,13 +71,15 @@ class AppointmentDetails { trailing: IconButton( icon: const Icon(Icons.house_outlined), onPressed: () { - PersistentNavBarNavigator.pushNewScreen(context, withNavBar: false, screen: const Roomplan()); + pushNewScreen(context, withNavBar: false, screen: const Roomplan()); }, ), ), ListTile( leading: const Icon(Icons.person), - title: Text("Lehrkraft: ${timetableData.te[0].name} ${timetableData.te[0].longname.isNotEmpty ? "(${timetableData.te[0].longname})" : ""}"), + title: timetableData.te.isNotEmpty + ? Text("Lehrkraft: ${timetableData.te[0].name} ${timetableData.te[0].longname.isNotEmpty ? "(${timetableData.te[0].longname})" : ""}") + : const Text("?"), trailing: Visibility( visible: !kReleaseMode, child: IconButton( diff --git a/lib/view/pages/timetable/timetable.dart b/lib/view/pages/timetable/timetable.dart index 7cfdbaf..75fe943 100644 --- a/lib/view/pages/timetable/timetable.dart +++ b/lib/view/pages/timetable/timetable.dart @@ -163,10 +163,9 @@ class _TimetableState extends State { } List _buildSpecialTimeRegions(GetHolidaysResponse holidays) { - DateTime lastMonday = DateTime.now().subtract(Duration(days: DateTime.now().weekday - 1)); + DateTime lastMonday = DateTime.now().subtract(const Duration(days: 14)).nextWeekday(DateTime.monday); DateTime firstBreak = lastMonday.copyWith(hour: 10, minute: 15); DateTime secondBreak = lastMonday.copyWith(hour: 13, minute: 50); - DateTime beforeSchool = lastMonday.copyWith(hour: 7, minute: 30); Iterable holidayList = holidays.result.map((holiday) { DateTime startDay = _parseWebuntisTimestamp(holiday.startDate, 0); @@ -200,7 +199,7 @@ class _TimetableState extends State { TimeRegion( startTime: firstBreak, endTime: firstBreak.add(const Duration(minutes: 20)), - recurrenceRule: 'FREQ=DAILY;INTERVAL=1;COUNT=5', + recurrenceRule: 'FREQ=DAILY;INTERVAL=1', text: 'centerIcon', color: Theme.of(context).primaryColor.withAlpha(50), iconData: Icons.restaurant @@ -210,20 +209,11 @@ class _TimetableState extends State { TimeRegion( startTime: secondBreak, endTime: secondBreak.add(const Duration(minutes: 15)), - recurrenceRule: 'FREQ=DAILY;INTERVAL=1;COUNT=5', + recurrenceRule: 'FREQ=DAILY;INTERVAL=1', text: 'centerIcon', color: Theme.of(context).primaryColor.withAlpha(50), iconData: Icons.restaurant ), - - if(!isInHoliday(beforeSchool)) - TimeRegion( - startTime: beforeSchool, - endTime: beforeSchool.add(const Duration(minutes: 25)), - recurrenceRule: 'FREQ=DAILY;INTERVAL=1;COUNT=5', - color: Theme.of(context).disabledColor.withAlpha(50), - text: "centerIcon", - ), ]; } diff --git a/lib/view/settings/settings.dart b/lib/view/settings/settings.dart index cfe0374..4d1630a 100644 --- a/lib/view/settings/settings.dart +++ b/lib/view/settings/settings.dart @@ -1,7 +1,9 @@ import 'package:filesize/filesize.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:jiffy/jiffy.dart'; import 'package:package_info/package_info.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -186,11 +188,11 @@ class _SettingsState extends State { context: context, applicationIcon: const Icon(Icons.apps), applicationName: "MarianumMobile", - applicationVersion: "${appInfo.appName}\n\nPackage: ${appInfo.packageName}\n\nVersion: ${appInfo.version}\nBuild: ${appInfo.buildNumber}", + applicationVersion: "${appInfo.appName}\n\nPackage: ${appInfo.packageName}\nVersion: ${appInfo.version}\nBuild: ${appInfo.buildNumber}", applicationLegalese: "Dies ist ein Inoffizieller Nextcloud & Webuntis Client und wird nicht vom Marianum selbst betrieben.\n" "Keinerlei Gewähr für Vollständigkeit, Richtigkeit und Aktualität!\n\n" - "Development build\n" - "Marianum Fulda 2023 Elias Müller", + "${kReleaseMode ? "Production" : "Development"} build\n" + "Marianum Fulda 2023-${Jiffy.now().year}\nElias Müller", ); }); }, @@ -236,8 +238,8 @@ class _SettingsState extends State { ListTile( leading: const CenteredLeading(Icon(Icons.code)), - title: const Text("Quellcode der App"), - subtitle: const Text("Open Source GNU GPL v3"), + title: const Text("Quellcode MarianumMobile/Client"), + subtitle: const Text("open source GNU GPL v3"), onTap: () => ConfirmDialog.openBrowser(context, "https://mhsl.eu/gitea/MarianumMobile/Client"), ), diff --git a/pubspec.yaml b/pubspec.yaml index d0bd123..dd5135f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 0.0.5+29 +version: 0.0.6+30 environment: sdk: '>3.0.0' @@ -68,7 +68,7 @@ dependencies: flowder: git: url: https://github.com/Harsh223/flowder.git - persistent_bottom_nav_bar: ^5.0.2 + persistent_bottom_nav_bar_v2: ^4.2.8 badges: ^3.0.2 image_picker: ^1.0.0 file_picker: ^6.1.1