Added Marianum Message pdf reader and backend
This commit is contained in:
18
lib/api/mhsl/message/getMessages/getMessages.dart
Normal file
18
lib/api/mhsl/message/getMessages/getMessages.dart
Normal file
@ -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<GetMessagesResponse> {
|
||||
|
||||
@override
|
||||
GetMessagesResponse assemble(String raw) {
|
||||
return GetMessagesResponse.fromJson(jsonDecode(raw));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<http.Response> request(Uri uri) {
|
||||
return http.get(uri);
|
||||
}
|
||||
}
|
22
lib/api/mhsl/message/getMessages/getMessagesCache.dart
Normal file
22
lib/api/mhsl/message/getMessages/getMessagesCache.dart
Normal file
@ -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<GetMessagesResponse> {
|
||||
GetMessagesCache({onUpdate, renew}) : super(RequestCache.cacheMinute, onUpdate, renew: renew) {
|
||||
start("MarianumMobile", "message");
|
||||
}
|
||||
|
||||
@override
|
||||
GetMessagesResponse onLocalData(String json) {
|
||||
return GetMessagesResponse.fromJson(jsonDecode(json));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<GetMessagesResponse> onLoad() {
|
||||
return GetMessages().run();
|
||||
}
|
||||
}
|
27
lib/api/mhsl/message/getMessages/getMessagesResponse.dart
Normal file
27
lib/api/mhsl/message/getMessages/getMessagesResponse.dart
Normal file
@ -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<GetMessagesResponseObject> messages;
|
||||
|
||||
GetMessagesResponse(this.base, this.messages);
|
||||
|
||||
factory GetMessagesResponse.fromJson(Map<String, dynamic> json) => _$GetMessagesResponseFromJson(json);
|
||||
Map<String, dynamic> 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<String, dynamic> json) => _$GetMessagesResponseObjectFromJson(json);
|
||||
Map<String, dynamic> toJson() => _$GetMessagesResponseObjectToJson(this);
|
||||
}
|
39
lib/api/mhsl/message/getMessages/getMessagesResponse.g.dart
Normal file
39
lib/api/mhsl/message/getMessages/getMessagesResponse.g.dart
Normal file
@ -0,0 +1,39 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'getMessagesResponse.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
GetMessagesResponse _$GetMessagesResponseFromJson(Map<String, dynamic> json) =>
|
||||
GetMessagesResponse(
|
||||
json['base'] as String,
|
||||
(json['messages'] as List<dynamic>)
|
||||
.map((e) =>
|
||||
GetMessagesResponseObject.fromJson(e as Map<String, dynamic>))
|
||||
.toSet(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$GetMessagesResponseToJson(
|
||||
GetMessagesResponse instance) =>
|
||||
<String, dynamic>{
|
||||
'base': instance.base,
|
||||
'messages': instance.messages.map((e) => e.toJson()).toList(),
|
||||
};
|
||||
|
||||
GetMessagesResponseObject _$GetMessagesResponseObjectFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
GetMessagesResponseObject(
|
||||
json['name'] as String,
|
||||
json['date'] as String,
|
||||
json['url'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$GetMessagesResponseObjectToJson(
|
||||
GetMessagesResponseObject instance) =>
|
||||
<String, dynamic>{
|
||||
'name': instance.name,
|
||||
'date': instance.date,
|
||||
'url': instance.url,
|
||||
};
|
22
lib/api/mhsl/message/messageApi.dart
Normal file
22
lib/api/mhsl/message/messageApi.dart
Normal file
@ -0,0 +1,22 @@
|
||||
import 'package:http/http.dart' as http;
|
||||
import '../../apiError.dart';
|
||||
import '../../apiRequest.dart';
|
||||
|
||||
abstract class MessageApi<T> extends ApiRequest {
|
||||
String path = "https://mhsl.eu/marianum/marianummobile/message/messages.json";
|
||||
http.Response? response;
|
||||
|
||||
Future<http.Response>? request(Uri uri);
|
||||
T assemble(String raw);
|
||||
|
||||
Future<T> 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);
|
||||
}
|
||||
}
|
10
lib/app.dart
10
lib/app.dart
@ -49,11 +49,11 @@ class _AppState extends State<App> {
|
||||
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(
|
||||
|
28
lib/data/message/messageProps.dart
Normal file
28
lib/data/message/messageProps.dart
Normal file
@ -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<ApiResponse?> properties() {
|
||||
return [_getMessagesResponse];
|
||||
}
|
||||
|
||||
@override
|
||||
void run({renew}) {
|
||||
GetMessagesCache(
|
||||
renew: renew,
|
||||
onUpdate: (GetMessagesResponse data) => {
|
||||
_getMessagesResponse = data,
|
||||
notifyListeners(),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -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<void> main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
@ -38,6 +39,8 @@ Future<void> main() async {
|
||||
ChangeNotifierProvider(create: (context) => ChatListProps()),
|
||||
ChangeNotifierProvider(create: (context) => ChatProps()),
|
||||
ChangeNotifierProvider(create: (context) => FilesProps()),
|
||||
|
||||
ChangeNotifierProvider(create: (context) => MessageProps()),
|
||||
],
|
||||
child: const Main(),
|
||||
)
|
||||
|
@ -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<Message> {
|
||||
@override
|
||||
void initState() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
Provider.of<MessageProps>(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<MessageProps>(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<MessageProps>(context, listen: false).run(renew: true);
|
||||
return Future.delayed(const Duration(seconds: 3));
|
||||
},
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
62
lib/screen/pages/more/message/messageView.dart
Normal file
62
lib/screen/pages/more/message/messageView.dart
Normal file
@ -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<MessageView> createState() => _MessageViewState();
|
||||
}
|
||||
|
||||
class _MessageViewState extends State<MessageView> {
|
||||
|
||||
@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")),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user