Merge remote-tracking branch 'origin/develop' into develop-customTimetableEvents
This commit is contained in:
commit
64b23c88ae
@ -47,7 +47,7 @@ abstract class TalkApi<T> 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);
|
||||
|
||||
|
@ -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<T> 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));
|
||||
|
21
lib/api/mhsl/server/feedback/addFeedback.dart
Normal file
21
lib/api/mhsl/server/feedback/addFeedback.dart
Normal file
@ -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<void> {
|
||||
AddFeedbackParams params;
|
||||
AddFeedback(this.params) : super('server/feedback');
|
||||
|
||||
@override
|
||||
void assemble(String raw) {}
|
||||
|
||||
@override
|
||||
Future<Response>? request(Uri uri) {
|
||||
return http.post(uri, body: jsonEncode(params.toJson()));
|
||||
}
|
||||
}
|
20
lib/api/mhsl/server/feedback/addFeedbackParams.dart
Normal file
20
lib/api/mhsl/server/feedback/addFeedbackParams.dart
Normal file
@ -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<String, dynamic> json) => _$AddFeedbackParamsFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$AddFeedbackParamsToJson(this);
|
||||
}
|
21
lib/api/mhsl/server/feedback/addFeedbackParams.g.dart
Normal file
21
lib/api/mhsl/server/feedback/addFeedbackParams.g.dart
Normal file
@ -0,0 +1,21 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'addFeedbackParams.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
AddFeedbackParams _$AddFeedbackParamsFromJson(Map<String, dynamic> json) =>
|
||||
AddFeedbackParams(
|
||||
user: json['user'] as String,
|
||||
feedback: json['feedback'] as String,
|
||||
appVersion: json['appVersion'] as int,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$AddFeedbackParamsToJson(AddFeedbackParams instance) =>
|
||||
<String, dynamic>{
|
||||
'user': instance.user,
|
||||
'feedback': instance.feedback,
|
||||
'appVersion': instance.appVersion,
|
||||
};
|
@ -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<void> {
|
||||
|
||||
@override
|
||||
Future<http.Response> 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(),
|
||||
),
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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<String> getDeviceId() async {
|
||||
return sha512.convert(utf8.encode("${getUserId()}@${await FirebaseMessaging.instance.getToken()}")).toString();
|
||||
}
|
||||
|
||||
Future<void> setData(String username, String password) async {
|
||||
SharedPreferences storage = await _storage;
|
||||
|
||||
|
@ -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();
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -4,51 +4,10 @@ class DarkAppTheme {
|
||||
static const Color marianumRed = Color.fromARGB(255, 153, 51, 51);
|
||||
|
||||
static final theme = ThemeData(
|
||||
useMaterial3: false,
|
||||
colorScheme: ColorScheme.fromSeed(
|
||||
seedColor: marianumRed,
|
||||
brightness: Brightness.dark,
|
||||
),
|
||||
primaryColor: marianumRed,
|
||||
hintColor: marianumRed,
|
||||
colorScheme: const ColorScheme(
|
||||
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),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
@ -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
|
||||
)
|
||||
);
|
||||
}
|
73
lib/view/pages/more/feedback/feedbackDialog.dart
Normal file
73
lib/view/pages/more/feedback/feedbackDialog.dart
Normal file
@ -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<FeedbackDialog> createState() => _FeedbackDialogState();
|
||||
}
|
||||
|
||||
class _FeedbackDialogState extends State<FeedbackDialog> {
|
||||
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"),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
@ -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()),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
|
@ -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 "
|
||||
|
@ -84,9 +84,8 @@ class _ChatTextfieldState extends State<ChatTextfield> {
|
||||
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: <Widget>[
|
||||
GestureDetector(
|
||||
@ -135,7 +134,7 @@ class _ChatTextfieldState extends State<ChatTextfield> {
|
||||
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<ChatTextfield> {
|
||||
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!";
|
||||
|
@ -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<SplitViewState>() != 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -18,10 +18,6 @@ class _AppointmentComponentState extends State<AppointmentComponent> {
|
||||
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<AppointmentComponent> {
|
||||
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<AppointmentComponent> {
|
||||
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<AppointmentComponent> {
|
||||
),
|
||||
),
|
||||
),
|
||||
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(
|
||||
|
@ -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(
|
||||
headerBuilder: (context, bottomSheetOffset) => Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text("${_getEventPrefix(timetableData.code)}${subject.alternateName} - (${subject.longName})", style: const TextStyle(fontSize: 30)),
|
||||
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(
|
||||
|
@ -163,10 +163,9 @@ class _TimetableState extends State<Timetable> {
|
||||
}
|
||||
|
||||
List<TimeRegion> _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<TimeRegion> holidayList = holidays.result.map((holiday) {
|
||||
DateTime startDay = _parseWebuntisTimestamp(holiday.startDate, 0);
|
||||
@ -200,7 +199,7 @@ class _TimetableState extends State<Timetable> {
|
||||
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<Timetable> {
|
||||
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",
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -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<Settings> {
|
||||
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<Settings> {
|
||||
|
||||
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"),
|
||||
),
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user