Implement local HTTP Api usage

This commit is contained in:
2023-02-14 18:06:18 +01:00
parent 83ad7d59d2
commit 7432972b3c
27 changed files with 1300 additions and 59 deletions

5
lib/api/apiError.dart Normal file
View File

@ -0,0 +1,5 @@
class ApiError {
String message;
ApiError(this.message);
}

39
lib/api/apiRequest.dart Normal file
View File

@ -0,0 +1,39 @@
import 'dart:developer';
import 'package:http/http.dart' as http;
import 'package:marianum_mobile/api/apiError.dart';
class ApiRequest {
Uri endpoint;
ApiRequest(this.endpoint);
Future<http.Response> get(Map<String, String>? headers) async {
return await http.get(endpoint, headers: headers);
}
Future<http.Response> post(String data, Map<String, String>? headers) async {
log("Fetching: ${data}");
try {
http.Response response = await http
.post(endpoint, body: data, headers: headers)
.timeout(
const Duration(seconds: 10),
onTimeout: () {
log("timeout!");
throw ApiError("Network timeout");
}
);
if(response.statusCode != 200) {
log("Got ${response.statusCode}");
throw ApiError("Service response invalid, got status ${response.statusCode}");
}
return response;
} on Exception catch(e) {
throw ApiError("Http: ${e.toString()}");
}
}
}

View File

@ -0,0 +1,6 @@
import 'package:marianum_mobile/api/apiRequest.dart';
class RequestLoginTest extends ApiRequest {
RequestLoginTest(super.endpoint);
}

View File

@ -0,0 +1,3 @@
class ApiParams {
}

View File

@ -0,0 +1,6 @@
import 'package:http/http.dart' as http;
import 'package:json_annotation/json_annotation.dart';
abstract class ApiResponse {
@JsonKey(includeFromJson: false, includeToJson: false)
late http.Response rawResponse;
}

View File

@ -0,0 +1,55 @@
import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'package:marianum_mobile/api/webuntis/webuntisApi.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'authenticateParams.dart';
import 'authenticateResponse.dart';
class Authenticate extends WebuntisApi {
AuthenticateParams param;
Authenticate(this.param) : super("authenticate", param, authenticatedResponse: false);
@override
Future<AuthenticateResponse> run() async {
awaitingResponse = true;
String rawAnswer = await query(this);
AuthenticateResponse response = finalize(AuthenticateResponse.fromJson(jsonDecode(rawAnswer)['result']));
_lastResponse = response;
awaitedResponse.complete();
return response;
}
static bool awaitingResponse = false;
static Completer awaitedResponse = Completer();
static AuthenticateResponse? _lastResponse;
static Future<void> createSession() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
_lastResponse = await Authenticate(
AuthenticateParams(
user: preferences.getString("username")!,
password: preferences.getString("password")!,
)
).run();
}
static Future<AuthenticateResponse> getSession() async {
if(awaitingResponse) {
log("Other query in progress... waiting");
await awaitedResponse.future;
}
if(_lastResponse == null) {
log("Not authenticated... requesting");
awaitingResponse = true;
await createSession();
}
return _lastResponse!;
}
}

View File

@ -0,0 +1,16 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:marianum_mobile/api/webuntis/apiParams.dart';
part 'authenticateParams.g.dart';
@JsonSerializable()
class AuthenticateParams extends ApiParams {
String user;
String password;
AuthenticateParams({required this.user, required this.password});
factory AuthenticateParams.fromJson(Map<String, dynamic> json) => _$AuthenticateParamsFromJson(json);
Map<String, dynamic> toJson() => _$AuthenticateParamsToJson(this);
}

View File

@ -0,0 +1,19 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'authenticateParams.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
AuthenticateParams _$AuthenticateParamsFromJson(Map<String, dynamic> json) =>
AuthenticateParams(
user: json['user'] as String,
password: json['password'] as String,
);
Map<String, dynamic> _$AuthenticateParamsToJson(AuthenticateParams instance) =>
<String, dynamic>{
'user': instance.user,
'password': instance.password,
};

View File

@ -0,0 +1,18 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:marianum_mobile/api/webuntis/apiResponse.dart';
part 'authenticateResponse.g.dart';
@JsonSerializable()
class AuthenticateResponse extends ApiResponse {
String sessionId;
int personType;
int personId;
int klasseId;
AuthenticateResponse(this.sessionId, this.personType, this.personId, this.klasseId);
factory AuthenticateResponse.fromJson(Map<String, dynamic> json) => _$AuthenticateResponseFromJson(json);
Map<String, dynamic> toJson() => _$AuthenticateResponseToJson(this);
}

View File

@ -0,0 +1,25 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'authenticateResponse.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
AuthenticateResponse _$AuthenticateResponseFromJson(
Map<String, dynamic> json) =>
AuthenticateResponse(
json['sessionId'] as String,
json['personType'] as int,
json['personId'] as int,
json['klasseId'] as int,
);
Map<String, dynamic> _$AuthenticateResponseToJson(
AuthenticateResponse instance) =>
<String, dynamic>{
'sessionId': instance.sessionId,
'personType': instance.personType,
'personId': instance.personId,
'klasseId': instance.klasseId,
};

View File

@ -0,0 +1,17 @@
import 'dart:convert';
import 'package:marianum_mobile/api/webuntis/apiResponse.dart';
import 'package:marianum_mobile/api/webuntis/webuntisApi.dart';
import 'getRoomsResponse.dart';
class GetRooms extends WebuntisApi {
GetRooms() : super("getRooms", null);
@override
Future<GetRoomsResponse> run() async {
String rawAnswer = await query(this);
return finalize(GetRoomsResponse.fromJson(jsonDecode(rawAnswer)));
}
}

View File

@ -0,0 +1,29 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:marianum_mobile/api/webuntis/apiResponse.dart';
part 'getRoomsResponse.g.dart';
@JsonSerializable()
class GetRoomsResponse extends ApiResponse {
Set<GetRoomsResponseObject> result;
GetRoomsResponse(this.result);
factory GetRoomsResponse.fromJson(Map<String, dynamic> json) => _$GetRoomsResponseFromJson(json);
Map<String, dynamic> toJson() => _$GetRoomsResponseToJson(this);
}
@JsonSerializable(explicitToJson: true)
class GetRoomsResponseObject {
int id;
String name;
String longName;
bool active;
String building;
GetRoomsResponseObject(this.id, this.name, this.longName, this.active, this.building);
factory GetRoomsResponseObject.fromJson(Map<String, dynamic> json) => _$GetRoomsResponseObjectFromJson(json);
Map<String, dynamic> toJson() => _$GetRoomsResponseObjectToJson(this);
}

View File

@ -0,0 +1,40 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'getRoomsResponse.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
GetRoomsResponse _$GetRoomsResponseFromJson(Map<String, dynamic> json) =>
GetRoomsResponse(
(json['result'] as List<dynamic>)
.map(
(e) => GetRoomsResponseObject.fromJson(e as Map<String, dynamic>))
.toSet(),
);
Map<String, dynamic> _$GetRoomsResponseToJson(GetRoomsResponse instance) =>
<String, dynamic>{
'result': instance.result.toList(),
};
GetRoomsResponseObject _$GetRoomsResponseObjectFromJson(
Map<String, dynamic> json) =>
GetRoomsResponseObject(
json['id'] as int,
json['name'] as String,
json['longName'] as String,
json['active'] as bool,
json['building'] as String,
);
Map<String, dynamic> _$GetRoomsResponseObjectToJson(
GetRoomsResponseObject instance) =>
<String, dynamic>{
'id': instance.id,
'name': instance.name,
'longName': instance.longName,
'active': instance.active,
'building': instance.building,
};

View File

@ -0,0 +1,22 @@
import 'dart:convert';
import 'dart:developer';
import 'package:marianum_mobile/api/webuntis/apiResponse.dart';
import 'package:marianum_mobile/api/webuntis/webuntisApi.dart';
import 'getTimetableParams.dart';
import 'getTimetableResponse.dart';
class GetTimetable extends WebuntisApi {
GetTimetableParams params;
GetTimetable(this.params) : super("getTimetable", params);
@override
Future<GetTimetableResponse> run() async {
String rawAnswer = await query(this);
log(rawAnswer);
return finalize(GetTimetableResponse.fromJson(jsonDecode(rawAnswer)));
}
}

View File

@ -0,0 +1,91 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:marianum_mobile/api/webuntis/apiParams.dart';
part 'getTimetableParams.g.dart';
@JsonSerializable(explicitToJson: true)
class GetTimetableParams extends ApiParams {
GetTimetableParamsOptions options;
GetTimetableParams({required this.options});
factory GetTimetableParams.fromJson(Map<String, dynamic> json) => _$GetTimetableParamsFromJson(json);
Map<String, dynamic> toJson() => _$GetTimetableParamsToJson(this);
}
@JsonSerializable(explicitToJson: true)
class GetTimetableParamsOptions {
GetTimetableParamsOptionsElement element;
@JsonKey(includeIfNull: false)
int? startDate;
@JsonKey(includeIfNull: false)
int? endDate;
@JsonKey(includeIfNull: false)
bool? onlyBaseTimetable;
@JsonKey(includeIfNull: false)
bool? showBooking;
@JsonKey(includeIfNull: false)
bool? showInfo;
@JsonKey(includeIfNull: false)
bool? showSubstText;
@JsonKey(includeIfNull: false)
bool? showLsText;
@JsonKey(includeIfNull: false)
bool? showLsNumber;
@JsonKey(includeIfNull: false)
bool? showStudentgroup;
@JsonKey(includeIfNull: false)
GetTimetableParamsOptionsFields? klasseFields;
@JsonKey(includeIfNull: false)
GetTimetableParamsOptionsFields? roomFields;
@JsonKey(includeIfNull: false)
GetTimetableParamsOptionsFields? subjectFields;
@JsonKey(includeIfNull: false)
GetTimetableParamsOptionsFields? teacherFields;
GetTimetableParamsOptions({
required this.element,
this.startDate,
this.endDate,
this.onlyBaseTimetable,
this.showBooking,
this.showInfo,
this.showSubstText,
this.showLsText,
this.showLsNumber,
this.showStudentgroup,
this.klasseFields,
this.roomFields,
this.subjectFields,
this.teacherFields
});
factory GetTimetableParamsOptions.fromJson(Map<String, dynamic> json) => _$GetTimetableParamsOptionsFromJson(json);
Map<String, dynamic> toJson() => _$GetTimetableParamsOptionsToJson(this);
}
enum GetTimetableParamsOptionsFields {
@JsonValue("id") id,
@JsonValue("name") name,
@JsonValue("longname") longname,
@JsonValue("externalkey") externalkey,
}
@JsonSerializable()
class GetTimetableParamsOptionsElement {
int id;
int type;
@JsonKey(includeIfNull: false)
GetTimetableParamsOptionsElementKeyType? keyType;
GetTimetableParamsOptionsElement({required this.id, required this.type, this.keyType});
factory GetTimetableParamsOptionsElement.fromJson(Map<String, dynamic> json) => _$GetTimetableParamsOptionsElementFromJson(json);
Map<String, dynamic> toJson() => _$GetTimetableParamsOptionsElementToJson(this);
}
enum GetTimetableParamsOptionsElementKeyType {
@JsonValue("id") id,
@JsonValue("name") name,
@JsonValue("externalkey") externalkey
}

View File

@ -0,0 +1,114 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'getTimetableParams.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
GetTimetableParams _$GetTimetableParamsFromJson(Map<String, dynamic> json) =>
GetTimetableParams(
options: GetTimetableParamsOptions.fromJson(
json['options'] as Map<String, dynamic>),
);
Map<String, dynamic> _$GetTimetableParamsToJson(GetTimetableParams instance) =>
<String, dynamic>{
'options': instance.options.toJson(),
};
GetTimetableParamsOptions _$GetTimetableParamsOptionsFromJson(
Map<String, dynamic> json) =>
GetTimetableParamsOptions(
element: GetTimetableParamsOptionsElement.fromJson(
json['element'] as Map<String, dynamic>),
startDate: json['startDate'] as int?,
endDate: json['endDate'] as int?,
onlyBaseTimetable: json['onlyBaseTimetable'] as bool?,
showBooking: json['showBooking'] as bool?,
showInfo: json['showInfo'] as bool?,
showSubstText: json['showSubstText'] as bool?,
showLsText: json['showLsText'] as bool?,
showLsNumber: json['showLsNumber'] as bool?,
showStudentgroup: json['showStudentgroup'] as bool?,
klasseFields: $enumDecodeNullable(
_$GetTimetableParamsOptionsFieldsEnumMap, json['klasseFields']),
roomFields: $enumDecodeNullable(
_$GetTimetableParamsOptionsFieldsEnumMap, json['roomFields']),
subjectFields: $enumDecodeNullable(
_$GetTimetableParamsOptionsFieldsEnumMap, json['subjectFields']),
teacherFields: $enumDecodeNullable(
_$GetTimetableParamsOptionsFieldsEnumMap, json['teacherFields']),
);
Map<String, dynamic> _$GetTimetableParamsOptionsToJson(
GetTimetableParamsOptions instance) {
final val = <String, dynamic>{
'element': instance.element.toJson(),
};
void writeNotNull(String key, dynamic value) {
if (value != null) {
val[key] = value;
}
}
writeNotNull('startDate', instance.startDate);
writeNotNull('endDate', instance.endDate);
writeNotNull('onlyBaseTimetable', instance.onlyBaseTimetable);
writeNotNull('showBooking', instance.showBooking);
writeNotNull('showInfo', instance.showInfo);
writeNotNull('showSubstText', instance.showSubstText);
writeNotNull('showLsText', instance.showLsText);
writeNotNull('showLsNumber', instance.showLsNumber);
writeNotNull('showStudentgroup', instance.showStudentgroup);
writeNotNull('klasseFields',
_$GetTimetableParamsOptionsFieldsEnumMap[instance.klasseFields]);
writeNotNull('roomFields',
_$GetTimetableParamsOptionsFieldsEnumMap[instance.roomFields]);
writeNotNull('subjectFields',
_$GetTimetableParamsOptionsFieldsEnumMap[instance.subjectFields]);
writeNotNull('teacherFields',
_$GetTimetableParamsOptionsFieldsEnumMap[instance.teacherFields]);
return val;
}
const _$GetTimetableParamsOptionsFieldsEnumMap = {
GetTimetableParamsOptionsFields.id: 'id',
GetTimetableParamsOptionsFields.name: 'name',
GetTimetableParamsOptionsFields.longname: 'longname',
GetTimetableParamsOptionsFields.externalkey: 'externalkey',
};
GetTimetableParamsOptionsElement _$GetTimetableParamsOptionsElementFromJson(
Map<String, dynamic> json) =>
GetTimetableParamsOptionsElement(
id: json['id'] as int,
type: json['type'] as int,
keyType: $enumDecodeNullable(
_$GetTimetableParamsOptionsElementKeyTypeEnumMap, json['keyType']),
);
Map<String, dynamic> _$GetTimetableParamsOptionsElementToJson(
GetTimetableParamsOptionsElement instance) {
final val = <String, dynamic>{
'id': instance.id,
'type': instance.type,
};
void writeNotNull(String key, dynamic value) {
if (value != null) {
val[key] = value;
}
}
writeNotNull('keyType',
_$GetTimetableParamsOptionsElementKeyTypeEnumMap[instance.keyType]);
return val;
}
const _$GetTimetableParamsOptionsElementKeyTypeEnumMap = {
GetTimetableParamsOptionsElementKeyType.id: 'id',
GetTimetableParamsOptionsElementKeyType.name: 'name',
GetTimetableParamsOptionsElementKeyType.externalkey: 'externalkey',
};

View File

@ -0,0 +1,85 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:marianum_mobile/api/webuntis/apiResponse.dart';
part 'getTimetableResponse.g.dart';
@JsonSerializable(explicitToJson: true)
class GetTimetableResponse extends ApiResponse {
Set<GetTimetableResponseObject> result;
GetTimetableResponse(this.result);
factory GetTimetableResponse.fromJson(Map<String, dynamic> json) => _$GetTimetableResponseFromJson(json);
Map<String, dynamic> toJson() => _$GetTimetableResponseToJson(this);
}
@JsonSerializable(explicitToJson: true)
class GetTimetableResponseObject {
int id;
int date;
int startTime;
int endTime;
String? lstype;
String? code;
String? info;
String? substText;
String? lstext;
int? lsnumber;
String? statflags;
String? activityType;
String? sg;
String? bkRemark;
String? bkText;
List<dynamic> kl;
List<dynamic> te;
List<dynamic> su;
List<dynamic> ro;
GetTimetableResponseObject({
required this.id,
required this.date,
required this.startTime,
required this.endTime,
this.lstype,
this.code,
this.info,
this.substText,
this.lstext,
this.lsnumber,
this.statflags,
this.activityType,
this.sg,
this.bkRemark,
required this.kl,
required this.te,
required this.su,
required this.ro
});
factory GetTimetableResponseObject.fromJson(Map<String, dynamic> json) => _$GetTimetableResponseObjectFromJson(json);
Map<String, dynamic> toJson() => _$GetTimetableResponseObjectToJson(this);
}
@JsonSerializable(explicitToJson: true)
class GetTimetableResponseObjectFields {
List<GetTimetableResponseObjectFieldsObject>? te;
GetTimetableResponseObjectFields(this.te);
factory GetTimetableResponseObjectFields.fromJson(Map<String, dynamic> json) => _$GetTimetableResponseObjectFieldsFromJson(json);
Map<String, dynamic> toJson() => _$GetTimetableResponseObjectFieldsToJson(this);
}
@JsonSerializable()
class GetTimetableResponseObjectFieldsObject {
int? id;
String? name;
String? longname;
String? externalkey;
GetTimetableResponseObjectFieldsObject({this.id, this.name, this.longname, this.externalkey});
factory GetTimetableResponseObjectFieldsObject.fromJson(Map<String, dynamic> json) => _$GetTimetableResponseObjectFieldsObjectFromJson(json);
Map<String, dynamic> toJson() => _$GetTimetableResponseObjectFieldsObjectToJson(this);
}

View File

@ -0,0 +1,103 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'getTimetableResponse.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
GetTimetableResponse _$GetTimetableResponseFromJson(
Map<String, dynamic> json) =>
GetTimetableResponse(
(json['result'] as List<dynamic>)
.map((e) =>
GetTimetableResponseObject.fromJson(e as Map<String, dynamic>))
.toSet(),
);
Map<String, dynamic> _$GetTimetableResponseToJson(
GetTimetableResponse instance) =>
<String, dynamic>{
'result': instance.result.map((e) => e.toJson()).toList(),
};
GetTimetableResponseObject _$GetTimetableResponseObjectFromJson(
Map<String, dynamic> json) =>
GetTimetableResponseObject(
id: json['id'] as int,
date: json['date'] as int,
startTime: json['startTime'] as int,
endTime: json['endTime'] as int,
lstype: json['lstype'] as String?,
code: json['code'] as String?,
info: json['info'] as String?,
substText: json['substText'] as String?,
lstext: json['lstext'] as String?,
lsnumber: json['lsnumber'] as int?,
statflags: json['statflags'] as String?,
activityType: json['activityType'] as String?,
sg: json['sg'] as String?,
bkRemark: json['bkRemark'] as String?,
kl: json['kl'] as List<dynamic>,
te: json['te'] as List<dynamic>,
su: json['su'] as List<dynamic>,
ro: json['ro'] as List<dynamic>,
)..bkText = json['bkText'] as String?;
Map<String, dynamic> _$GetTimetableResponseObjectToJson(
GetTimetableResponseObject instance) =>
<String, dynamic>{
'id': instance.id,
'date': instance.date,
'startTime': instance.startTime,
'endTime': instance.endTime,
'lstype': instance.lstype,
'code': instance.code,
'info': instance.info,
'substText': instance.substText,
'lstext': instance.lstext,
'lsnumber': instance.lsnumber,
'statflags': instance.statflags,
'activityType': instance.activityType,
'sg': instance.sg,
'bkRemark': instance.bkRemark,
'bkText': instance.bkText,
'kl': instance.kl,
'te': instance.te,
'su': instance.su,
'ro': instance.ro,
};
GetTimetableResponseObjectFields _$GetTimetableResponseObjectFieldsFromJson(
Map<String, dynamic> json) =>
GetTimetableResponseObjectFields(
(json['te'] as List<dynamic>?)
?.map((e) => GetTimetableResponseObjectFieldsObject.fromJson(
e as Map<String, dynamic>))
.toList(),
);
Map<String, dynamic> _$GetTimetableResponseObjectFieldsToJson(
GetTimetableResponseObjectFields instance) =>
<String, dynamic>{
'te': instance.te?.map((e) => e.toJson()).toList(),
};
GetTimetableResponseObjectFieldsObject
_$GetTimetableResponseObjectFieldsObjectFromJson(
Map<String, dynamic> json) =>
GetTimetableResponseObjectFieldsObject(
id: json['id'] as int?,
name: json['name'] as String?,
longname: json['longname'] as String?,
externalkey: json['externalkey'] as String?,
);
Map<String, dynamic> _$GetTimetableResponseObjectFieldsObjectToJson(
GetTimetableResponseObjectFieldsObject instance) =>
<String, dynamic>{
'id': instance.id,
'name': instance.name,
'longname': instance.longname,
'externalkey': instance.externalkey,
};

View File

@ -0,0 +1,54 @@
import 'dart:convert';
import 'dart:developer';
import 'package:marianum_mobile/api/apiRequest.dart';
import 'package:http/http.dart' as http;
import 'package:marianum_mobile/api/webuntis/webuntisError.dart';
import 'package:marianum_mobile/api/webuntis/apiResponse.dart';
import 'apiParams.dart';
import 'queries/authenticate/authenticate.dart';
abstract class WebuntisApi extends ApiRequest {
String method;
ApiParams? genericParam;
http.Response? response;
bool authenticatedResponse;
WebuntisApi(this.method, this.genericParam, {this.authenticatedResponse = true}) : super(Uri.parse("https://peleus.webuntis.com/WebUntis/jsonrpc.do?school=marianum-fulda"));
Future<String> query(WebuntisApi untis) async {
String query = '{"id":"ID","method":"$method","params":${untis._body()},"jsonrpc":"2.0"}';
log(query);
String sessionId = "0";
if(authenticatedResponse) {
sessionId = (await Authenticate.getSession()).sessionId;
}
http.Response data = await post(query, {"Cookie": "JSESSIONID=$sessionId"});
response = data;
dynamic jsonData = jsonDecode(data.body);
if(jsonData['error'] != null) {
if(jsonData['error']['code'] == -8520) {
await Authenticate.createSession();
this.query(untis);
} else {
throw WebuntisError(jsonData['error']['message'], jsonData['error']['code']);
}
}
return data.body;
}
dynamic finalize(dynamic response) {
response.rawResponse = this.response!;
return response;
}
Future<ApiResponse> run();
String _body() {
return genericParam == null ? "{}" : jsonEncode(genericParam);
}
}

View File

@ -0,0 +1,10 @@
class WebuntisError {
String message;
int code;
WebuntisError(this.message, this.code);
String toString() {
return "WebUntis ($code): $message";
}
}

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:marianum_mobile/data/incommingPackets/talkNotificationsPacket.dart';
import 'package:marianum_mobile/screen/pages/timetable/testTimetable.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
@ -42,7 +43,7 @@ class _AppState extends State<App> {
PageView(
controller: pageController,
children: const [
Timetable(),
TestTimeTable(),
Talk(),
Files(),
Overhang(),

View File

@ -1,12 +1,19 @@
import 'dart:io';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:flutter_login/flutter_login.dart';
import 'package:marianum_mobile/api/apiError.dart';
import 'package:marianum_mobile/api/webuntis/webuntisError.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../api/webuntis/queries/authenticate/authenticateParams.dart';
import '../../api/webuntis/queries/authenticate/authenticate.dart';
import '../../data/accountModel.dart';
class Login extends StatefulWidget {
const Login({Key? key}) : super(key: key);
@ -15,32 +22,75 @@ class Login extends StatefulWidget {
}
class _LoginState extends State<Login> {
Duration get loginTime => const Duration(milliseconds: 2250);
bool displayDisclaimerText = true;
final Future<SharedPreferences> _storage = SharedPreferences.getInstance();
String? checkInput(value){
return (value ?? "").length < 5 ? "Eingabe zu kurz" : null;
String? _checkInput(value){
return (value ?? "").length == 0 ? "Eingabe erforderlich" : null;
}
Future<String?> _login(LoginData data) async {
SharedPreferences preferences = await SharedPreferences.getInstance();
preferences.setBool("loggedIn", false);
try {
await Authenticate(
AuthenticateParams(
user: data.name,
password: data.password,
)
).run().then((value) => {
log(value.sessionId)
});
} on WebuntisError catch(e) {
return e.toString();
} on ApiError catch(e) {
return e.toString();
}
setState(() {
displayDisclaimerText = false;
});
preferences.setBool("loggedIn", true);
preferences.setString("username", data.name);
preferences.setString("password", data.password);
return null;
}
Future<String> _resetPassword(String name) {
return Future.delayed(Duration.zero).then((_) {
return "Diese Funktion steht nicht zur Verfügung!";
});
}
@override
Widget build(BuildContext context) {
return FlutterLogin(
logo: Image.file(File("assets/logo/icon.png")).image,
userValidator: checkInput,
passwordValidator: checkInput,
userValidator: _checkInput,
passwordValidator: _checkInput,
onSubmitAnimationCompleted: () => Provider.of<AccountModel>(context, listen: false).login(),
onLogin: _authUser,
savedEmail: "test",
onLogin: _login,
onSignup: null,
onRecoverPassword: _recoverPassword,
onRecoverPassword: _resetPassword,
hideForgotPasswordButton: true,
theme: LoginTheme(
primaryColor: Theme.of(context).primaryColor,
accentColor: Colors.white,
errorColor: Theme.of(context).primaryColor,
footerBottomPadding: 10,
textFieldStyle: const TextStyle(
fontWeight: FontWeight.w500
),
cardTheme: const CardTheme(
elevation: 10,
shape: InputBorder.none,
),
),
@ -52,42 +102,23 @@ class _LoginState extends State<Login> {
disableCustomPageTransformer: true,
headerWidget: const Padding(
padding: EdgeInsets.only(bottom: 10),
headerWidget: Padding(
padding: const EdgeInsets.only(bottom: 30),
child: Center(
child: Text(
"Dies ist ein Inoffizieller Nextclient & Webuntis Client und wird nicht vom Marianum selbst betrieben.\nBitte bedenke, dass deine persönlichen Anmelde & Infodaten durch dritte, nicht vom Marianum betriebene, Systeme geleitet werden!",
child: Visibility(
visible: displayDisclaimerText,
child: const Text(
"Dies ist ein Inoffizieller Nextclient & Webuntis Client und wird nicht vom Marianum selbst betrieben.\nKeinerlei Gewähr für Vollständigkeit, Richtigkeit und Aktualität!",
textAlign: TextAlign.center,
),
),
),
),
footer: "Marianum Fulda - Die persönliche Schule!",
title: "Marianum",
footer: "Marianum Fulda - Die persönliche Schule",
title: "Marianum Fulda",
hideForgotPasswordButton: true,
userType: LoginUserType.name,
);
}
Future<String?> _authUser(LoginData data) async {
final SharedPreferences preferences = await _storage;
preferences.setBool("loggedIn", true);
preferences.setString("username", data.name);
preferences.setString("password", data.password);
debugPrint('Name: ${data.name}, Password: ${data.password}');
return Future.delayed(loginTime).then((_) {
Provider.of<AccountModel>(context, listen: false).login();
return null;
});
}
Future<String> _recoverPassword(String name) {
return Future.delayed(loginTime).then((_) {
return "Diese Funktion steht nicht zur Verfügung!";
});
}
}

View File

@ -0,0 +1,145 @@
import 'dart:developer';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:jiffy/jiffy.dart';
import 'package:marianum_mobile/api/webuntis/queries/getRooms/getRooms.dart';
import 'package:marianum_mobile/data/incommingPackets/timetablePacket.dart';
import 'package:marianum_mobile/widget/loadingSpinner.dart';
import 'package:marianum_mobile/widget/offlineError.dart';
import 'package:timetable_view/timetable_view.dart';
import '../../../api/webuntis/queries/getTimetable/getTimetableParams.dart';
import '../../../api/webuntis/queries/getTimetable/getTimetableResponse.dart';
import '../../../api/webuntis/queries/getTimetable/getTimetable.dart';
class TestTimeTable extends StatefulWidget {
const TestTimeTable({Key? key}) : super(key: key);
@override
State<TestTimeTable> createState() => _TestTimeTableState();
}
class _TestTimeTableState extends State<TestTimeTable> {
late Future<GetTimetableResponse> data;
@override
void initState() {
data = GetTimetable(
GetTimetableParams(
options: GetTimetableParamsOptions(
element: GetTimetableParamsOptionsElement(
id: 92,
type: 5,
keyType: GetTimetableParamsOptionsElementKeyType.id,
),
startDate: 20230206,
endDate: 20230212,
)
)
).run();
GetRooms().run().then((value) => {
log(value.rawResponse.body)
});
super.initState();
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
builder: (BuildContext context, AsyncSnapshot<GetTimetableResponse> snapshot) {
if(snapshot.hasData) {
return Center(
child: TimetableView(
laneEventsList: _buildLaneEvents(snapshot.data!),
onEventTap: (TableEvent event) {},
timetableStyle: CustomTableStyle(context),
onEmptySlotTap: (int laneIndex, TableEventTime start, TableEventTime end) => {},
),
);
} else if(snapshot.hasError) {
return const OfflineBanner(text: "Der Stundenplan konnte nicht geladen werden!");
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
},
future: data,
);
}
List<LaneEvents> _buildLaneEvents(GetTimetableResponse data) {
List<LaneEvents> laneEvents = List<LaneEvents>.empty(growable: true);
Jiffy.locale("de");
List<int> dayList = data.result.map((e) => e.date).toSet().toList();
dayList.sort((a, b) => a-b);
dayList.forEach((day) {
//Every Day
laneEvents.add(
LaneEvents(
lane: Lane(
laneIndex: day,
name: "${Jiffy(day.toString()).format("dd.MM.yy")}\n${Jiffy(day.toString()).format("EEEE")}",
textStyle: TextStyle(
color: Theme.of(context).primaryColor,
fontWeight: FontWeight.bold,
fontSize: 14
)
),
events: List<TableEvent>.generate(
data.result.where((element) => element.date == day).length,
(index) {
GetTimetableResponseObject tableEvent = data.result.where((element) => element.date == day).elementAt(index);
return TableEvent(
title: "${tableEvent.substText}",
eventId: tableEvent.id,
laneIndex: day,
startTime: parseTime(tableEvent.startTime),
endTime: parseTime(tableEvent.endTime),
padding: const EdgeInsets.all(5),
backgroundColor: Theme.of(context).primaryColor,
location: "\n${tableEvent.statflags}",
);
}
)
)
);
});
return laneEvents;
}
TableEventTime parseTime(int input) {
String time = input.toString().length < 4 ? "0$input" : input.toString();
return TableEventTime(hour: int.parse(time.substring(0, 2)), minute: int.parse(time.substring(2, 4)));
}
}
class CustomTableStyle extends TimetableStyle {
dynamic context;
CustomTableStyle(this.context);
@override
int get startHour => 07;
@override
int get endHour => 17;
@override
double get laneWidth => 100;
@override
Color get cornerColor => Theme.of(context).primaryColor;
@override
Color get timeItemTextColor => Theme.of(context).primaryColor;
@override
double get timeItemHeight => 60;
@override
double get timeItemWidth => 40;
}

View File

@ -0,0 +1,32 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class OfflineBanner extends StatelessWidget {
final IconData icon;
final String text;
const OfflineBanner({Key? key, this.icon = Icons.report_gmailerrorred, this.text = "Es ist ein Fehler aufgetreten!"}) : super(key: key);
@override
Widget build(BuildContext context) {
return Center(
child: Container(
margin: const EdgeInsets.only(top: 100, left: 20, right: 20),
child: Column(
children: [
Container(
margin: const EdgeInsets.all(30),
child: Icon(icon, color: Colors.grey, size: 60),
),
Text(text,
style: const TextStyle(
fontSize: 20,
color: Colors.grey,
),
textAlign: TextAlign.center,
),
],
),
),
);
}
}