diff --git a/.idea/libraries/Dart_Packages.xml b/.idea/libraries/Dart_Packages.xml
index 7cb7313..5e60838 100644
--- a/.idea/libraries/Dart_Packages.xml
+++ b/.idea/libraries/Dart_Packages.xml
@@ -275,6 +275,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -957,7 +971,7 @@
-
+
@@ -968,6 +982,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1195,6 +1251,8 @@
+
+
@@ -1284,8 +1342,14 @@
-
+
+
+
+
+
+
+
diff --git a/.idea/libraries/Flutter_Plugins.xml b/.idea/libraries/Flutter_Plugins.xml
index 5480177..c288cf5 100644
--- a/.idea/libraries/Flutter_Plugins.xml
+++ b/.idea/libraries/Flutter_Plugins.xml
@@ -28,6 +28,9 @@
+
+
+
diff --git a/lib/api/mhsl/message/getMessages/getMessages.dart b/lib/api/mhsl/message/getMessages/getMessages.dart
new file mode 100644
index 0000000..db5a813
--- /dev/null
+++ b/lib/api/mhsl/message/getMessages/getMessages.dart
@@ -0,0 +1,18 @@
+import 'dart:convert';
+
+import 'package:http/http.dart' as http;
+import 'package:marianum_mobile/api/mhsl/message/getMessages/getMessagesResponse.dart';
+import 'package:marianum_mobile/api/mhsl/message/messageApi.dart';
+
+class GetMessages extends MessageApi {
+
+ @override
+ GetMessagesResponse assemble(String raw) {
+ return GetMessagesResponse.fromJson(jsonDecode(raw));
+ }
+
+ @override
+ Future request(Uri uri) {
+ return http.get(uri);
+ }
+}
\ No newline at end of file
diff --git a/lib/api/mhsl/message/getMessages/getMessagesCache.dart b/lib/api/mhsl/message/getMessages/getMessagesCache.dart
new file mode 100644
index 0000000..d009e9f
--- /dev/null
+++ b/lib/api/mhsl/message/getMessages/getMessagesCache.dart
@@ -0,0 +1,22 @@
+import 'dart:convert';
+
+import 'package:marianum_mobile/api/mhsl/message/getMessages/getMessagesResponse.dart';
+import 'package:marianum_mobile/api/requestCache.dart';
+
+import 'getMessages.dart';
+
+class GetMessagesCache extends RequestCache {
+ GetMessagesCache({onUpdate, renew}) : super(RequestCache.cacheMinute, onUpdate, renew: renew) {
+ start("MarianumMobile", "message");
+ }
+
+ @override
+ GetMessagesResponse onLocalData(String json) {
+ return GetMessagesResponse.fromJson(jsonDecode(json));
+ }
+
+ @override
+ Future onLoad() {
+ return GetMessages().run();
+ }
+}
\ No newline at end of file
diff --git a/lib/api/mhsl/message/getMessages/getMessagesResponse.dart b/lib/api/mhsl/message/getMessages/getMessagesResponse.dart
new file mode 100644
index 0000000..314928a
--- /dev/null
+++ b/lib/api/mhsl/message/getMessages/getMessagesResponse.dart
@@ -0,0 +1,27 @@
+import 'package:json_annotation/json_annotation.dart';
+import 'package:marianum_mobile/api/apiResponse.dart';
+
+part 'getMessagesResponse.g.dart';
+
+@JsonSerializable(explicitToJson: true)
+class GetMessagesResponse extends ApiResponse {
+ String base;
+ Set messages;
+
+ GetMessagesResponse(this.base, this.messages);
+
+ factory GetMessagesResponse.fromJson(Map json) => _$GetMessagesResponseFromJson(json);
+ Map toJson() => _$GetMessagesResponseToJson(this);
+}
+
+@JsonSerializable(explicitToJson: true)
+class GetMessagesResponseObject {
+ String name;
+ String date;
+ String url;
+
+ GetMessagesResponseObject(this.name, this.date, this.url);
+
+ factory GetMessagesResponseObject.fromJson(Map json) => _$GetMessagesResponseObjectFromJson(json);
+ Map toJson() => _$GetMessagesResponseObjectToJson(this);
+}
diff --git a/lib/api/mhsl/message/getMessages/getMessagesResponse.g.dart b/lib/api/mhsl/message/getMessages/getMessagesResponse.g.dart
new file mode 100644
index 0000000..50498ba
--- /dev/null
+++ b/lib/api/mhsl/message/getMessages/getMessagesResponse.g.dart
@@ -0,0 +1,39 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'getMessagesResponse.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+GetMessagesResponse _$GetMessagesResponseFromJson(Map json) =>
+ GetMessagesResponse(
+ json['base'] as String,
+ (json['messages'] as List)
+ .map((e) =>
+ GetMessagesResponseObject.fromJson(e as Map))
+ .toSet(),
+ );
+
+Map _$GetMessagesResponseToJson(
+ GetMessagesResponse instance) =>
+ {
+ 'base': instance.base,
+ 'messages': instance.messages.map((e) => e.toJson()).toList(),
+ };
+
+GetMessagesResponseObject _$GetMessagesResponseObjectFromJson(
+ Map json) =>
+ GetMessagesResponseObject(
+ json['name'] as String,
+ json['date'] as String,
+ json['url'] as String,
+ );
+
+Map _$GetMessagesResponseObjectToJson(
+ GetMessagesResponseObject instance) =>
+ {
+ 'name': instance.name,
+ 'date': instance.date,
+ 'url': instance.url,
+ };
diff --git a/lib/api/mhsl/message/messageApi.dart b/lib/api/mhsl/message/messageApi.dart
new file mode 100644
index 0000000..e85100d
--- /dev/null
+++ b/lib/api/mhsl/message/messageApi.dart
@@ -0,0 +1,22 @@
+import 'package:http/http.dart' as http;
+import '../../apiError.dart';
+import '../../apiRequest.dart';
+
+abstract class MessageApi extends ApiRequest {
+ String path = "https://mhsl.eu/marianum/marianummobile/message/messages.json";
+ http.Response? response;
+
+ Future? request(Uri uri);
+ T assemble(String raw);
+
+ Future run() async {
+ Uri endpoint = Uri.parse(path);
+
+ http.Response? data = await request(endpoint);
+ if(data == null) {
+ throw ApiError("Request could not be dispatched!");
+ }
+
+ return assemble(data.body);
+ }
+}
\ No newline at end of file
diff --git a/lib/app.dart b/lib/app.dart
index d2e9dd9..8973470 100644
--- a/lib/app.dart
+++ b/lib/app.dart
@@ -49,11 +49,11 @@ class _AppState extends State {
border: Border.symmetric(vertical: BorderSide.none, horizontal: BorderSide(color: Colors.grey, width: 1))
),
screenTransitionAnimation: const ScreenTransitionAnimation(animateTabTransition: true, curve: Curves.ease, duration: Duration(milliseconds: 200)),
- screens: [
- const Timetable(),
- const ChatList(),
- Files(const []),
- const Overhang(),
+ screens: const [
+ Timetable(),
+ ChatList(),
+ Files([]),
+ Overhang(),
],
items: [
PersistentBottomNavBarItem(
diff --git a/lib/data/message/messageProps.dart b/lib/data/message/messageProps.dart
new file mode 100644
index 0000000..2776e31
--- /dev/null
+++ b/lib/data/message/messageProps.dart
@@ -0,0 +1,28 @@
+
+import 'package:marianum_mobile/api/mhsl/message/getMessages/getMessagesCache.dart';
+import 'package:marianum_mobile/api/mhsl/message/getMessages/getMessagesResponse.dart';
+import 'package:marianum_mobile/data/dataHolder.dart';
+
+import '../../api/apiResponse.dart';
+
+class MessageProps extends DataHolder {
+ GetMessagesResponse? _getMessagesResponse;
+ GetMessagesResponse get getMessagesResponse => _getMessagesResponse!;
+
+ @override
+ List properties() {
+ return [_getMessagesResponse];
+ }
+
+ @override
+ void run({renew}) {
+ GetMessagesCache(
+ renew: renew,
+ onUpdate: (GetMessagesResponse data) => {
+ _getMessagesResponse = data,
+ notifyListeners(),
+ }
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/lib/main.dart b/lib/main.dart
index d3472f2..05147bc 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -18,6 +18,7 @@ import 'data/chatList/chatListProps.dart';
import 'data/chatList/chatProps.dart';
import 'data/accountModel.dart';
import 'data/files/filesProps.dart';
+import 'data/message/messageProps.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
@@ -38,6 +39,8 @@ Future main() async {
ChangeNotifierProvider(create: (context) => ChatListProps()),
ChangeNotifierProvider(create: (context) => ChatProps()),
ChangeNotifierProvider(create: (context) => FilesProps()),
+
+ ChangeNotifierProvider(create: (context) => MessageProps()),
],
child: const Main(),
)
diff --git a/lib/screen/pages/more/message/message.dart b/lib/screen/pages/more/message/message.dart
index 5d28eb2..e000ff3 100644
--- a/lib/screen/pages/more/message/message.dart
+++ b/lib/screen/pages/more/message/message.dart
@@ -1,5 +1,10 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
+import 'package:marianum_mobile/api/mhsl/message/getMessages/getMessagesResponse.dart';
+import 'package:marianum_mobile/screen/pages/more/message/messageView.dart';
+import 'package:provider/provider.dart';
+
+import '../../../../data/message/messageProps.dart';
class Message extends StatefulWidget {
const Message({Key? key}) : super(key: key);
@@ -9,17 +14,46 @@ class Message extends StatefulWidget {
}
class _MessageState extends State {
+ @override
+ void initState() {
+ WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
+ Provider.of(context, listen: false).run();
+ });
+ super.initState();
+ }
+
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Marianum Message"),
),
- body: ListView.builder(itemBuilder: (context, index) {
- return ListTile(
- leading: const Icon(Icons.newspaper),
- title: Text(index.toString()),
- trailing: const Icon(Icons.arrow_right),
+ body: Consumer(builder: (context, value, child) {
+ if(value.primaryLoading()) return const Center(child: CircularProgressIndicator());
+
+ return RefreshIndicator(
+ child: ListView.builder(
+ itemCount: value.getMessagesResponse.messages.length,
+ itemBuilder: (context, index) {
+ GetMessagesResponseObject message = value.getMessagesResponse.messages.toList()[index];
+ return ListTile(
+ leading: const Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [Icon(Icons.newspaper)],
+ ),
+ title: Text(message.name, overflow: TextOverflow.ellipsis),
+ subtitle: Text("vom ${message.date}"),
+ trailing: const Icon(Icons.arrow_right),
+ onTap: () {
+ Navigator.push(context, MaterialPageRoute(builder: (context) => MessageView(basePath: value.getMessagesResponse.base, message: message)));
+ },
+ );
+ }
+ ),
+ onRefresh: () {
+ Provider.of(context, listen: false).run(renew: true);
+ return Future.delayed(const Duration(seconds: 3));
+ },
);
}),
);
diff --git a/lib/screen/pages/more/message/messageView.dart b/lib/screen/pages/more/message/messageView.dart
new file mode 100644
index 0000000..da42385
--- /dev/null
+++ b/lib/screen/pages/more/message/messageView.dart
@@ -0,0 +1,62 @@
+import 'package:flutter/material.dart';
+import 'package:marianum_mobile/api/mhsl/message/getMessages/getMessagesResponse.dart';
+import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';
+import 'package:url_launcher/url_launcher.dart';
+
+class MessageView extends StatefulWidget {
+ final String basePath;
+ final GetMessagesResponseObject message;
+ const MessageView({Key? key, required this.basePath, required this.message}) : super(key: key);
+
+ @override
+ State createState() => _MessageViewState();
+}
+
+class _MessageViewState extends State {
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: Text(widget.message.name),
+ ),
+ body: SfPdfViewer.network(
+ widget.basePath + widget.message.url,
+ enableHyperlinkNavigation: true,
+ onDocumentLoadFailed: (PdfDocumentLoadFailedDetails e) {
+ Navigator.of(context).pop();
+ showDialog(context: context, builder: (context) {
+ return AlertDialog(
+ title: const Text("Fehler beim öffnen"),
+ content: Text("Dokument '${widget.message.name}' konnte nicht geladen werden:\n${e.description}"),
+ actions: [
+ TextButton(onPressed: () {
+ Navigator.of(context).pop();
+ }, child: const Text("Ok"))
+ ],
+ );
+ });
+ },
+ onHyperlinkClicked: (PdfHyperlinkClickedDetails e) {
+ showDialog(
+ context: context,
+ builder: (context) {
+ return AlertDialog(
+ title: const Text("Link öffnen"),
+ content: Text("Möchtest du den folgenden Link öffnen?\n${e.uri}"),
+ actions: [
+ TextButton(onPressed: () {
+ Navigator.of(context).pop();
+ }, child: const Text("Abbrechen")),
+ TextButton(onPressed: () {
+ launchUrl(Uri.parse(e.uri), mode: LaunchMode.externalApplication);
+ }, child: const Text("Öffnen")),
+ ],
+ );
+ },
+ );
+ },
+ ),
+ );
+ }
+}
diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift
index 33cba8b..7026e66 100644
--- a/macos/Flutter/GeneratedPluginRegistrant.swift
+++ b/macos/Flutter/GeneratedPluginRegistrant.swift
@@ -5,16 +5,20 @@
import FlutterMacOS
import Foundation
+import device_info_plus
import package_info
import path_provider_foundation
import shared_preferences_foundation
import sqflite
+import syncfusion_pdfviewer_macos
import url_launcher_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
+ DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
FLTPackageInfoPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlugin"))
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
+ SyncfusionFlutterPdfViewerPlugin.register(with: registry.registrar(forPlugin: "SyncfusionFlutterPdfViewerPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
}
diff --git a/pubspec.yaml b/pubspec.yaml
index 1ad6191..bb78d51 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -79,6 +79,7 @@ dependencies:
syncfusion_flutter_calendar: ^21.2.4
async: ^2.11.0
animated_digit: ^3.2.1
+ syncfusion_flutter_pdfviewer: ^21.2.8
dev_dependencies:
flutter_test:
diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc
index 4f78848..9871f6b 100644
--- a/windows/flutter/generated_plugin_registrant.cc
+++ b/windows/flutter/generated_plugin_registrant.cc
@@ -6,9 +6,12 @@
#include "generated_plugin_registrant.h"
+#include
#include
void RegisterPlugins(flutter::PluginRegistry* registry) {
+ SyncfusionPdfviewerWindowsPluginRegisterWithRegistrar(
+ registry->GetRegistrarForPlugin("SyncfusionPdfviewerWindowsPlugin"));
UrlLauncherWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
}
diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake
index 88b22e5..2487723 100644
--- a/windows/flutter/generated_plugins.cmake
+++ b/windows/flutter/generated_plugins.cmake
@@ -3,6 +3,7 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
+ syncfusion_pdfviewer_windows
url_launcher_windows
)