merged to origin/devlop

This commit is contained in:
2024-04-07 15:58:51 +02:00
185 changed files with 500 additions and 866 deletions

View File

@ -20,9 +20,7 @@ class Login extends StatefulWidget {
class _LoginState extends State<Login> {
bool displayDisclaimerText = true;
String? _checkInput(value){
return (value ?? '').length == 0 ? 'Eingabe erforderlich' : null;
}
String? _checkInput(value)=> (value ?? '').length == 0 ? 'Eingabe erforderlich' : null;
Future<String?> _login(LoginData data) async {
await AccountData().removeData();
@ -49,15 +47,10 @@ class _LoginState extends State<Login> {
return null;
}
Future<String> _resetPassword(String name) {
return Future.delayed(Duration.zero).then((_) {
return 'Diese Funktion steht nicht zur Verfügung!';
});
}
Future<String> _resetPassword(String name) => Future.delayed(Duration.zero).then((_) => 'Diese Funktion steht nicht zur Verfügung!');
@override
Widget build(BuildContext context) {
return FlutterLogin(
Widget build(BuildContext context) => FlutterLogin(
logo: Image.asset('assets/logo/icon.png').image,
userValidator: _checkInput,
@ -109,5 +102,4 @@ class _LoginState extends State<Login> {
userType: LoginUserType.name,
);
}
}

View File

@ -26,14 +26,14 @@ class FileElement extends StatefulWidget {
const FileElement(this.file, this.path, this.refetch, {super.key});
static Future<DownloaderCore> download(BuildContext context, String remotePath, String name, Function(double) onProgress, Function(OpenResult) onDone) async {
Directory paths = await getTemporaryDirectory();
var paths = await getTemporaryDirectory();
var encodedPath = Uri.encodeComponent(remotePath);
encodedPath = encodedPath.replaceAll('%2F', '/');
String local = paths.path + Platform.pathSeparator + name;
var local = paths.path + Platform.pathSeparator + name;
DownloaderUtils options = DownloaderUtils(
var options = DownloaderUtils(
progressCallback: (current, total) {
final progress = (current / total) * 100;
onProgress(progress);
@ -52,7 +52,7 @@ class FileElement extends StatefulWidget {
);
return await Flowder.download(
"${await WebdavApi.webdavConnectString}$encodedPath",
'${await WebdavApi.webdavConnectString}$encodedPath',
options,
);
}
@ -89,8 +89,7 @@ class _FileElementState extends State<FileElement> {
}
@override
Widget build(BuildContext context) {
return ListTile(
Widget build(BuildContext context) => ListTile(
leading: CenteredLeading(
Icon(widget.file.isDirectory ? Icons.folder : Icons.description_outlined)
),
@ -100,9 +99,7 @@ class _FileElementState extends State<FileElement> {
onTap: () {
if(widget.file.isDirectory) {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) {
return Files(widget.path.toList()..add(widget.file.name));
},
builder: (context) => Files(widget.path.toList()..add(widget.file.name)),
));
} else {
if(EndpointData().getEndpointMode() == EndpointMode.stage) {
@ -141,12 +138,10 @@ class _FileElementState extends State<FileElement> {
setState(() => percent = progress);
}, (result) {
if(result.type != ResultType.done) {
showDialog(context: context, builder: (context) {
return AlertDialog(
showDialog(context: context, builder: (context) => AlertDialog(
title: const Text('Download'),
content: Text(result.message),
);
});
));
}
setState(() {
@ -158,8 +153,7 @@ class _FileElementState extends State<FileElement> {
}
},
onLongPress: () {
showDialog(context: context, builder: (context) {
return SimpleDialog(
showDialog(context: context, builder: (context) => SimpleDialog(
children: [
ListTile(
leading: const Icon(Icons.delete_outline),
@ -189,9 +183,7 @@ class _FileElementState extends State<FileElement> {
),
),
],
);
});
));
},
);
}
}

View File

@ -113,7 +113,7 @@ class _FilesState extends State<Files> {
@override
Widget build(BuildContext context) {
List<CacheableFile> files = data?.sortBy(
var files = data?.sortBy(
sortOption: currentSort,
foldersToTop: Provider.of<SettingsProvider>(context).val().fileSettings.sortFoldersToTop,
reversed: currentSortDirection
@ -131,8 +131,7 @@ class _FilesState extends State<Files> {
// ),
PopupMenuButton<bool>(
icon: Icon(currentSortDirection ? Icons.text_rotate_up : Icons.text_rotation_down),
itemBuilder: (context) {
return [true, false].map((e) => PopupMenuItem<bool>(
itemBuilder: (context) => [true, false].map((e) => PopupMenuItem<bool>(
value: e,
enabled: e != currentSortDirection,
child: Row(
@ -142,8 +141,7 @@ class _FilesState extends State<Files> {
Text(e ? 'Aufsteigend' : 'Absteigend')
],
)
)).toList();
},
)).toList(),
onSelected: (e) {
setState(() {
currentSortDirection = e;
@ -153,8 +151,7 @@ class _FilesState extends State<Files> {
),
PopupMenuButton<SortOption>(
icon: const Icon(Icons.sort),
itemBuilder: (context) {
return SortOptions.options.keys.map((key) => PopupMenuItem<SortOption>(
itemBuilder: (context) => SortOptions.options.keys.map((key) => PopupMenuItem<SortOption>(
value: key,
enabled: key != currentSort,
child: Row(
@ -164,8 +161,7 @@ class _FilesState extends State<Files> {
Text(SortOptions.getOption(key).displayName),
],
)
)).toList();
},
)).toList(),
onSelected: (e) {
setState(() {
currentSort = e;
@ -179,8 +175,7 @@ class _FilesState extends State<Files> {
heroTag: 'uploadFile',
backgroundColor: Theme.of(context).primaryColor,
onPressed: () {
showDialog(context: context, builder: (context) {
return SimpleDialog(
showDialog(context: context, builder: (context) => SimpleDialog(
children: [
ListTile(
leading: const Icon(Icons.create_new_folder_outlined),
@ -234,8 +229,7 @@ class _FilesState extends State<Files> {
),
),
],
);
});
));
},
child: const Icon(Icons.add),
),
@ -249,7 +243,7 @@ class _FilesState extends State<Files> {
padding: EdgeInsets.zero,
itemCount: files.length,
itemBuilder: (context, index) {
CacheableFile file = files.toList()[index];
var file = files.toList()[index];
return FileElement(file, widget.path, _query);
},
),

View File

@ -44,8 +44,7 @@ class _FeedbackDialogState extends State<FeedbackDialog> {
}
@override
Widget build(BuildContext context) {
return Scaffold(
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: const Text('Feedback'),
),
@ -125,7 +124,7 @@ class _FeedbackDialogState extends State<FeedbackDialog> {
onPressed: () async {
context.loaderOverlay.show();
var imageData = await (await FilePick.galleryPick())?.readAsBytes();
context.loaderOverlay.hide();
if(context.mounted) context.loaderOverlay.hide();
setState(() {
_image = imageData;
});
@ -170,6 +169,4 @@ class _FeedbackDialogState extends State<FeedbackDialog> {
],
),
);
}
}

View File

@ -4,7 +4,6 @@ import 'package:flutter/material.dart';
import 'package:jiffy/jiffy.dart';
import 'package:provider/provider.dart';
import '../../../../api/holidays/getHolidaysResponse.dart';
import '../../../../model/holidays/holidaysProps.dart';
import '../../../../storage/base/settingsProvider.dart';
import '../../../../widget/centeredLeading.dart';
@ -22,9 +21,7 @@ class Holidays extends StatefulWidget {
}
extension StringExtension on String {
String capitalize() {
return "${this[0].toUpperCase()}${substring(1).toLowerCase()}";
}
String capitalize() => '${this[0].toUpperCase()}${substring(1).toLowerCase()}';
}
class _HolidaysState extends State<Holidays> {
@ -41,13 +38,10 @@ class _HolidaysState extends State<Holidays> {
super.initState();
}
String parseString(String enDate) {
return Jiffy.parse(enDate).format(pattern: 'dd.MM.yyyy');
}
String parseString(String enDate) => Jiffy.parse(enDate).format(pattern: 'dd.MM.yyyy');
void showDisclaimer() {
showDialog(context: context, builder: (context) {
return AlertDialog(
showDialog(context: context, builder: (context) => AlertDialog(
title: const Text('Richtigkeit und Bereitstellung der Daten'),
content: Column(
mainAxisSize: MainAxisSize.min,
@ -70,13 +64,11 @@ class _HolidaysState extends State<Holidays> {
TextButton(child: const Text('ferien-api.de besuchen'), onPressed: () => ConfirmDialog.openBrowser(context, 'https://ferien-api.de/')),
TextButton(child: const Text('Okay'), onPressed: () => Navigator.of(context).pop()),
],
);
});
));
}
@override
Widget build(BuildContext context) {
return Scaffold(
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: const Text('Schulferien in Hessen'),
actions: [
@ -87,8 +79,7 @@ class _HolidaysState extends State<Holidays> {
PopupMenuButton<bool>(
initialValue: settings.val().holidaysSettings.showPastEvents,
icon: const Icon(Icons.manage_history_outlined),
itemBuilder: (context) {
return [true, false].map((e) => PopupMenuItem<bool>(
itemBuilder: (context) => [true, false].map((e) => PopupMenuItem<bool>(
value: e,
enabled: e != showPastEvents,
child: Row(
@ -98,8 +89,7 @@ class _HolidaysState extends State<Holidays> {
Text(e ? 'Alle anzeigen' : 'Nur zukünftige anzeigen')
],
)
)).toList();
},
)).toList(),
onSelected: (e) {
setState(() {
showPastEvents = e;
@ -112,7 +102,7 @@ class _HolidaysState extends State<Holidays> {
body: Consumer<HolidaysProps>(builder: (context, value, child) {
if(value.primaryLoading()) return const LoadingSpinner();
List<GetHolidaysResponseObject> holidays = value.getHolidaysResponse.data;
var holidays = value.getHolidaysResponse.data;
if(!showPastEvents) holidays = holidays.where((element) => DateTime.parse(element.end).isAfter(DateTime.now())).toList();
if(holidays.isEmpty) return const PlaceholderView(icon: Icons.search_off, text: 'Es wurden keine Ferieneinträge gefunden!');
@ -120,8 +110,8 @@ class _HolidaysState extends State<Holidays> {
return ListView.builder(
itemCount: holidays.length,
itemBuilder: (context, index) {
GetHolidaysResponseObject holiday = holidays[index];
String holidayType = holiday.name.split(' ').first.capitalize();
var holiday = holidays[index];
var holidayType = holiday.name.split(' ').first.capitalize();
return ListTile(
leading: const CenteredLeading(Icon(Icons.calendar_month)),
title: Text('$holidayType ab ${parseString(holiday.start)}'),
@ -164,5 +154,4 @@ class _HolidaysState extends State<Holidays> {
},
)
);
}
}

View File

@ -1,7 +1,6 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../../../../api/mhsl/message/getMessages/getMessagesResponse.dart';
import '../../../../model/message/messageProps.dart';
import '../../../../widget/loadingSpinner.dart';
import 'messageView.dart';
@ -24,8 +23,7 @@ class _MessageState extends State<Message> {
}
@override
Widget build(BuildContext context) {
return Scaffold(
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: const Text('Marianum Message'),
),
@ -36,7 +34,7 @@ class _MessageState extends State<Message> {
child: ListView.builder(
itemCount: value.getMessagesResponse.messages.length,
itemBuilder: (context, index) {
GetMessagesResponseObject message = value.getMessagesResponse.messages.toList()[index];
var message = value.getMessagesResponse.messages.toList()[index];
return ListTile(
leading: const Column(
mainAxisAlignment: MainAxisAlignment.center,
@ -58,5 +56,4 @@ class _MessageState extends State<Message> {
);
}),
);
}
}

View File

@ -17,8 +17,7 @@ class MessageView extends StatefulWidget {
class _MessageViewState extends State<MessageView> {
@override
Widget build(BuildContext context) {
return Scaffold(
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: Text(widget.message.name),
),
@ -27,8 +26,7 @@ class _MessageViewState extends State<MessageView> {
enableHyperlinkNavigation: true,
onDocumentLoadFailed: (PdfDocumentLoadFailedDetails e) {
Navigator.of(context).pop();
showDialog(context: context, builder: (context) {
return AlertDialog(
showDialog(context: context, builder: (context) => AlertDialog(
title: const Text('Fehler beim öffnen'),
content: Text("Dokument '${widget.message.name}' konnte nicht geladen werden:\n${e.description}"),
actions: [
@ -36,8 +34,7 @@ class _MessageViewState extends State<MessageView> {
Navigator.of(context).pop();
}, child: const Text('Ok'))
],
);
});
));
},
onHyperlinkClicked: (PdfHyperlinkClickedDetails e) {
showDialog(
@ -52,5 +49,4 @@ class _MessageViewState extends State<MessageView> {
},
),
);
}
}

View File

@ -5,8 +5,7 @@ class Roomplan extends StatelessWidget {
const Roomplan({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: const Text('Raumplan'),
),
@ -17,5 +16,4 @@ class Roomplan extends StatelessWidget {
backgroundDecoration: BoxDecoration(color: Theme.of(context).colorScheme.background),
),
);
}
}

View File

@ -8,7 +8,7 @@ class AppSharePlatformView extends StatelessWidget {
@override
Widget build(BuildContext context) {
Color foregroundColor = Theme.of(context).colorScheme.onBackground;
var foregroundColor = Theme.of(context).colorScheme.onBackground;
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,

View File

@ -11,8 +11,7 @@ class QrShareView extends StatefulWidget {
class _QrShareViewState extends State<QrShareView> {
@override
Widget build(BuildContext context) {
return DefaultTabController(
Widget build(BuildContext context) => DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
@ -32,5 +31,4 @@ class _QrShareViewState extends State<QrShareView> {
),
),
);
}
}

View File

@ -8,8 +8,7 @@ class SelectShareTypeDialog extends StatelessWidget {
const SelectShareTypeDialog({super.key});
@override
Widget build(BuildContext context) {
return SimpleDialog(
Widget build(BuildContext context) => SimpleDialog(
children: [
ListTile(
leading: const Icon(Icons.qr_code_2_outlined),
@ -36,5 +35,4 @@ class SelectShareTypeDialog extends StatelessWidget {
)
],
);
}
}

View File

@ -21,9 +21,7 @@ class Overhang extends StatelessWidget {
const Overhang({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: const Text('Mehr'),
actions: [
@ -79,5 +77,4 @@ class Overhang extends StatelessWidget {
],
),
);
}
}

View File

@ -35,7 +35,7 @@ class _ChatInfoState extends State<ChatInfo> {
@override
Widget build(BuildContext context) {
bool isGroup = widget.room.type != GetRoomResponseObjectConversationType.oneToOne;
var isGroup = widget.room.type != GetRoomResponseObjectConversationType.oneToOne;
return Scaffold(
appBar: AppBar(
title: Text(widget.room.displayName),

View File

@ -13,20 +13,16 @@ class ParticipantsListView extends StatefulWidget {
class _ParticipantsListViewState extends State<ParticipantsListView> {
@override
Widget build(BuildContext context) {
return Scaffold(
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: const Text('Teilnehmende'),
),
body: ListView(
children: widget.participantsResponse.data.map((participant) {
return ListTile(
children: widget.participantsResponse.data.map((participant) => ListTile(
leading: UserAvatar(id: participant.actorId),
title: Text(participant.displayName),
subtitle: participant.statusMessage != null ? Text(participant.statusMessage!) : null,
);
}).toList(),
)).toList(),
),
);
}
}

View File

@ -119,14 +119,14 @@ class _ChatListState extends State<ChatList> {
if(data.primaryLoading()) return const LoadingSpinner();
latestData = data;
List<ChatTile> chats = [];
var chats = <ChatTile>[];
for (var chatRoom in data.getRoomsResponse.sortBy(
lastActivity: true,
favoritesToTop: Provider.of<SettingsProvider>(context).val().talkSettings.sortFavoritesToTop,
unreadToTop: Provider.of<SettingsProvider>(context).val().talkSettings.sortUnreadToTop,
)
) {
bool hasDraft = settings.val().talkSettings.drafts.containsKey(chatRoom.token);
var hasDraft = settings.val().talkSettings.drafts.containsKey(chatRoom.token);
chats.add(ChatTile(data: chatRoom, query: _query, hasDraft: hasDraft));
}
@ -146,4 +146,4 @@ class _ChatListState extends State<ChatList> {
),
);
}
}
}

View File

@ -40,19 +40,18 @@ class _ChatViewState extends State<ChatView> {
}
@override
Widget build(BuildContext context) {
return Consumer<ChatProps>(
Widget build(BuildContext context) => Consumer<ChatProps>(
builder: (context, data, child) {
List<Widget> messages = List<Widget>.empty(growable: true);
var messages = List<Widget>.empty(growable: true);
if(!data.primaryLoading()) {
DateTime lastDate = DateTime.now();
var lastDate = DateTime.now();
data.getChatResponse.sortByTimestamp().forEach((element) {
DateTime elementDate = DateTime.fromMillisecondsSinceEpoch(element.timestamp * 1000);
var elementDate = DateTime.fromMillisecondsSinceEpoch(element.timestamp * 1000);
if(element.systemMessage.contains('reaction')) return;
int commonRead = int.parse(data.getChatResponse.headers?['x-chat-last-common-read'] ?? '0');
var commonRead = int.parse(data.getChatResponse.headers?['x-chat-last-common-read'] ?? '0');
if(!elementDate.isSameDay(lastDate)) {
lastDate = elementDate;
@ -140,5 +139,4 @@ class _ChatViewState extends State<ChatView> {
);
},
);
}
}

View File

@ -51,15 +51,13 @@ class ChatBubble extends StatefulWidget {
class _ChatBubbleState extends State<ChatBubble> {
BubbleStyle getSystemStyle() {
return BubbleStyle(
BubbleStyle getSystemStyle() => BubbleStyle(
color: AppTheme.isDarkMode(context) ? const Color(0xff182229) : Colors.white,
borderWidth: 1,
elevation: 2,
margin: const BubbleEdges.only(bottom: 20, top: 10),
alignment: Alignment.center,
);
}
BubbleStyle getRemoteStyle(bool seamless) {
var color = AppTheme.isDarkMode(context) ? const Color(0xff202c33) : Colors.white;
@ -105,17 +103,17 @@ class _ChatBubbleState extends State<ChatBubble> {
@override
Widget build(BuildContext context) {
message = ChatMessage(originalMessage: widget.bubbleData.message, originalData: widget.bubbleData.messageParameters);
bool showActorDisplayName = widget.bubbleData.messageType == GetRoomResponseObjectMessageType.comment && widget.chatData.type != GetRoomResponseObjectConversationType.oneToOne;
bool showBubbleTime = widget.bubbleData.messageType != GetRoomResponseObjectMessageType.system;
var showActorDisplayName = widget.bubbleData.messageType == GetRoomResponseObjectMessageType.comment && widget.chatData.type != GetRoomResponseObjectConversationType.oneToOne;
var showBubbleTime = widget.bubbleData.messageType != GetRoomResponseObjectMessageType.system;
Text actorText = Text(
var actorText = Text(
widget.bubbleData.actorDisplayName,
textAlign: TextAlign.start,
overflow: TextOverflow.ellipsis,
style: TextStyle(color: Theme.of(context).primaryColor, fontWeight: FontWeight.bold),
);
Text timeText = Text(
var timeText = Text(
Jiffy.parseFromMillisecondsSinceEpoch(widget.bubbleData.timestamp * 1000).format(pattern: 'HH:mm'),
textAlign: TextAlign.end,
style: TextStyle(color: widget.timeIconColor, fontSize: widget.timeIconSize),
@ -186,8 +184,8 @@ class _ChatBubbleState extends State<ChatBubble> {
),
onLongPress: () {
showDialog(context: context, builder: (context) {
List<String> commonReactions = ['👍', '👎', '😆', '❤️', '👀'];
bool canReact = widget.bubbleData.messageType == GetRoomResponseObjectMessageType.comment;
var commonReactions = <String>['👍', '👎', '😆', '❤️', '👀'];
var canReact = widget.bubbleData.messageType == GetRoomResponseObjectMessageType.comment;
return SimpleDialog(
children: [
Visibility(
@ -217,8 +215,7 @@ class _ChatBubbleState extends State<ChatBubble> {
),
IconButton(
onPressed: () {
showDialog(context: context, builder: (context) {
return AlertDialog(
showDialog(context: context, builder: (context) => AlertDialog(
contentPadding: const EdgeInsets.all(15),
titlePadding: const EdgeInsets.only(left: 6, top: 15),
title: Row(
@ -278,8 +275,7 @@ class _ChatBubbleState extends State<ChatBubble> {
],
),
),
);
});
));
},
style: IconButton.styleFrom(
padding: EdgeInsets.zero,
@ -350,8 +346,7 @@ class _ChatBubbleState extends State<ChatBubble> {
if(message.file == null) return;
if(downloadProgress > 0) {
showDialog(context: context, builder: (context) {
return AlertDialog(
showDialog(context: context, builder: (context) => AlertDialog(
title: const Text('Download abbrechen?'),
content: const Text('Möchtest du den Download abbrechen?'),
actions: [
@ -369,8 +364,7 @@ class _ChatBubbleState extends State<ChatBubble> {
});
}, child: const Text('Ja, Abbrechen'))
],
);
});
));
return;
}
@ -388,11 +382,9 @@ class _ChatBubbleState extends State<ChatBubble> {
});
if(result.type != ResultType.done) {
showDialog(context: context, builder: (context) {
return AlertDialog(
showDialog(context: context, builder: (context) => AlertDialog(
content: Text(result.message),
);
});
));
}
});
},
@ -408,7 +400,7 @@ class _ChatBubbleState extends State<ChatBubble> {
alignment: widget.isSender ? WrapAlignment.end : WrapAlignment.start,
crossAxisAlignment: WrapCrossAlignment.start,
children: widget.bubbleData.reactions?.entries.map<Widget>((e) {
bool hasSelfReacted = widget.bubbleData.reactionsSelf?.contains(e.key) ?? false;
var hasSelfReacted = widget.bubbleData.reactionsSelf?.contains(e.key) ?? false;
return Container(
margin: const EdgeInsets.only(right: 2.5, left: 2.5),
child: ActionChip(

View File

@ -37,8 +37,7 @@ class ChatMessage {
}
return CachedNetworkImage(
errorWidget: (context, url, error) {
return Padding(padding: const EdgeInsets.only(top: 10), child: Row(
errorWidget: (context, url, error) => Padding(padding: const EdgeInsets.only(top: 10), child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
@ -47,12 +46,9 @@ class ChatMessage {
Flexible(child: Text(file!.name, maxLines: 2, overflow: TextOverflow.ellipsis, style: const TextStyle(fontWeight: FontWeight.bold))),
const SizedBox(width: 10),
],
));
},
)),
alignment: Alignment.center,
placeholder: (context, url) {
return const Padding(padding: EdgeInsets.all(10), child: CircularProgressIndicator());
},
placeholder: (context, url) => const Padding(padding: EdgeInsets.all(10), child: CircularProgressIndicator()),
fadeInDuration: Duration.zero,
fadeOutDuration: Duration.zero,
errorListener: (value) {},
@ -60,9 +56,9 @@ class ChatMessage {
);
}
void onOpen(LinkableElement link) async {
Future<void> onOpen(LinkableElement link) async {
if(await canLaunchUrlString(link.url)) {
await launchUrlString(link.url);
}
}
}
}

View File

@ -66,7 +66,6 @@ class _ChatTextfieldState extends State<ChatTextfield> {
);
}
void setDraft(String text) {
if(text.isNotEmpty) {
settings.val(write: true).talkSettings.drafts[widget.sendToToken] = text;
@ -96,8 +95,7 @@ class _ChatTextfieldState extends State<ChatTextfield> {
children: <Widget>[
GestureDetector(
onTap: (){
showDialog(context: context, builder: (context) {
return SimpleDialog(
showDialog(context: context, builder: (context) => SimpleDialog(
children: [
ListTile(
leading: const Icon(Icons.file_open),
@ -121,8 +119,7 @@ class _ChatTextfieldState extends State<ChatTextfield> {
),
),
],
);
});
));
},
child: Material(
elevation: 5,

View File

@ -40,7 +40,7 @@ class _ChatTileState extends State<ChatTile> {
username = value.getString('username')!
});
bool isGroup = widget.data.type != GetRoomResponseObjectConversationType.oneToOne;
var isGroup = widget.data.type != GetRoomResponseObjectConversationType.oneToOne;
circleAvatar = UserAvatar(id: isGroup ? widget.data.token : widget.data.name, isGroup: isGroup);
}
@ -56,10 +56,7 @@ class _ChatTileState extends State<ChatTile> {
@override
Widget build(BuildContext context) {
return Consumer<ChatProps>(builder: (context, chatData, child) {
return ListTile(
Widget build(BuildContext context) => Consumer<ChatProps>(builder: (context, chatData, child) => ListTile(
style: ListTileStyle.list,
tileColor: chatData.currentToken() == widget.data.token && TalkNavigator.isSecondaryVisible(context)
? Theme.of(context).primaryColor.withAlpha(100)
@ -120,7 +117,7 @@ class _ChatTileState extends State<ChatTile> {
),
onTap: () async {
setCurrentAsRead();
ChatView view = ChatView(room: widget.data, selfId: username, avatar: circleAvatar);
var view = ChatView(room: widget.data, selfId: username, avatar: circleAvatar);
TalkNavigator.pushSplitView(context, view, overrideToSingleSubScreen: true);
Provider.of<ChatProps>(context, listen: false).setQueryToken(widget.data.token);
},
@ -185,7 +182,5 @@ class _ChatTileState extends State<ChatTile> {
],
));
},
);
});
}
));
}

View File

@ -6,8 +6,7 @@ class SplitViewPlaceholder extends StatelessWidget {
const SplitViewPlaceholder({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(),
body: Center(
child: Column(
@ -25,5 +24,4 @@ class SplitViewPlaceholder extends StatelessWidget {
),
)
);
}
}

View File

@ -11,8 +11,7 @@ class JoinChat extends SearchDelegate<String> {
CancelableOperation<AutocompleteResponse>? future;
@override
List<Widget>? buildActions(BuildContext context) {
return [
List<Widget>? buildActions(BuildContext context) => [
if(future != null && query.isNotEmpty) FutureBuilder(
future: future!.value,
builder: (context, snapshot) {
@ -35,12 +34,9 @@ class JoinChat extends SearchDelegate<String> {
),
if(query.isNotEmpty) IconButton(onPressed: () => query = '', icon: const Icon(Icons.delete)),
];
}
@override
Widget? buildLeading(BuildContext context) {
return null;
}
Widget? buildLeading(BuildContext context) => null;
@override
Widget buildResults(BuildContext context) {
@ -61,8 +57,8 @@ class JoinChat extends SearchDelegate<String> {
return ListView.builder(
itemCount: snapshot.data!.data.length,
itemBuilder: (context, index) {
AutocompleteResponseObject object = snapshot.data!.data[index];
CircleAvatar circleAvatar = CircleAvatar(
var object = snapshot.data!.data[index];
var circleAvatar = CircleAvatar(
foregroundImage: Image.network('https://${EndpointData().nextcloud().full()}/avatar/${object.id}/128').image,
backgroundColor: Theme.of(context).primaryColor,
foregroundColor: Colors.white,
@ -89,8 +85,6 @@ class JoinChat extends SearchDelegate<String> {
}
@override
Widget buildSuggestions(BuildContext context) {
return buildResults(context);
}
Widget buildSuggestions(BuildContext context) => buildResults(context);
}
}

View File

@ -30,8 +30,7 @@ class _MessageReactionsState extends State<MessageReactions> {
}
@override
Widget build(BuildContext context) {
return Scaffold(
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: const Text('Reaktionen'),
),
@ -42,8 +41,7 @@ class _MessageReactionsState extends State<MessageReactions> {
if(snapshot.data == null) return const PlaceholderView(icon: Icons.search_off_outlined, text: 'Keine Reaktionen gefunden!');
return ListView(
children: [
...snapshot.data!.data.entries.map<Widget>((entry) {
return ExpansionTile(
...snapshot.data!.data.entries.map<Widget>((entry) => ExpansionTile(
textColor: Theme.of(context).colorScheme.onSurface,
collapsedTextColor: Theme.of(context).colorScheme.onSurface,
iconColor: Theme.of(context).colorScheme.onSurface,
@ -53,7 +51,7 @@ class _MessageReactionsState extends State<MessageReactions> {
leading: CenteredLeading(Text(entry.key)),
title: Text('${entry.value.length} mal reagiert'),
children: entry.value.map((e) {
bool isSelf = AccountData().getUsername() == e.actorId;
var isSelf = AccountData().getUsername() == e.actorId;
return ListTile(
leading: UserAvatar(id: e.actorId, isGroup: false),
title: Text(e.actorDisplayName),
@ -71,12 +69,10 @@ class _MessageReactionsState extends State<MessageReactions> {
),
);
}).toList(),
);
})
))
],
);
},
),
);
}
}

View File

@ -9,16 +9,12 @@ class SearchChat extends SearchDelegate {
SearchChat(this.chats);
@override
List<Widget>? buildActions(BuildContext context) {
return [
List<Widget>? buildActions(BuildContext context) => [
if(query.isNotEmpty) IconButton(onPressed: () => query = '', icon: const Icon(Icons.delete)),
];
}
@override
Widget? buildLeading(BuildContext context) {
return null;
}
Widget? buildLeading(BuildContext context) => null;
@override
Widget buildResults(BuildContext context) {
@ -35,7 +31,5 @@ class SearchChat extends SearchDelegate {
}
@override
Widget buildSuggestions(BuildContext context) {
return buildResults(context);
}
}
Widget buildSuggestions(BuildContext context) => buildResults(context);
}

View File

@ -9,10 +9,10 @@ class TalkNavigator {
static void pushSplitView(BuildContext context, Widget view, {bool overrideToSingleSubScreen = false}) {
if(isSecondaryVisible(context)) {
SplitViewState splitView = SplitView.of(context);
var splitView = SplitView.of(context);
overrideToSingleSubScreen ? splitView.setSecondary(view) : splitView.push(view);
} else {
pushScreen(context, screen: view, withNavBar: false);
}
}
}
}

View File

@ -13,4 +13,4 @@ class CrossPainter extends CustomPainter {
@override
bool shouldRepaint(CrossPainter oldDelegate) => false;
}
}

View File

@ -33,7 +33,7 @@ class AppointmentDetails {
}
static void show(BuildContext context, TimetableProps webuntisData, Appointment appointment) {
(appointment.id as ArbitraryAppointment).handlers(
(appointment.id! as ArbitraryAppointment).handlers(
(webuntis) => _webuntis(context, webuntisData, appointment, webuntis),
(customData) => _custom(context, webuntisData, customData)
);
@ -76,21 +76,18 @@ class AppointmentDetails {
_bottomSheet(
context,
(context) {
return Center(
(context) => Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text("${_getEventPrefix(timetableData.code)}${subject.alternateName}", textAlign: TextAlign.center, style: const TextStyle(fontSize: 25), overflow: TextOverflow.ellipsis),
Text('${_getEventPrefix(timetableData.code)}${subject.alternateName}', textAlign: TextAlign.center, style: const TextStyle(fontSize: 25), overflow: TextOverflow.ellipsis),
Text(subject.longName),
Text("${Jiffy.parseFromDateTime(appointment.startTime).format(pattern: "HH:mm")} - ${Jiffy.parseFromDateTime(appointment.endTime).format(pattern: "HH:mm")}", style: const TextStyle(fontSize: 15)),
],
),
);
},
),
(context) {
return SliverChildListDelegate(
(context) => SliverChildListDelegate(
[
const Divider(),
ListTile(
@ -132,13 +129,12 @@ class AppointmentDetails {
),
DebugTile(context).jsonData(timetableData.toJson()),
],
);
}
)
);
}
static Completer deleteCustomEvent(BuildContext context, CustomTimetableEvent appointment) {
Completer future = Completer();
var future = Completer();
ConfirmDialog(
title: 'Termin löschen',
content: "Der ${appointment.rrule.isEmpty ? "Termin" : "Serientermin"} wird unwiederruflich gelöscht.",
@ -160,8 +156,7 @@ class AppointmentDetails {
static void _custom(BuildContext context, TimetableProps webuntisData, CustomTimetableEvent appointment) {
_bottomSheet(
context,
(context) {
return Center(
(context) => Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
@ -169,10 +164,8 @@ class AppointmentDetails {
Text("${Jiffy.parseFromDateTime(appointment.startDate).format(pattern: "HH:mm")} - ${Jiffy.parseFromDateTime(appointment.endDate).format(pattern: "HH:mm")}", style: const TextStyle(fontSize: 15)),
],
),
);
},
(context) {
return SliverChildListDelegate(
),
(context) => SliverChildListDelegate(
[
const Divider(),
Center(
@ -212,7 +205,7 @@ class AppointmentDetails {
builder: (context, snapshot) {
if(appointment.rrule.isEmpty) return const Text('Keine weiteren vorkomnisse');
if(snapshot.data == null) return const Text('...');
RecurrenceRule rrule = RecurrenceRule.fromString(appointment.rrule);
var rrule = RecurrenceRule.fromString(appointment.rrule);
if(!rrule.canFullyConvertToText) return const Text('Keine genauere Angabe möglich.');
return Text(rrule.toText(l10n: snapshot.data!));
},
@ -227,8 +220,7 @@ class AppointmentDetails {
),
DebugTile(context).jsonData(appointment.toJson()),
]
);
}
)
);
}
}
}

View File

@ -8,16 +8,12 @@ class ArbitraryAppointment {
ArbitraryAppointment({this.webuntis, this.custom});
bool hasWebuntis() {
return webuntis != null;
}
bool hasWebuntis() => webuntis != null;
bool hasCustom() {
return custom != null;
}
bool hasCustom() => custom != null;
void handlers(void Function(GetTimetableResponseObject webuntisData) webuntis, void Function(CustomTimetableEvent customData) custom) {
if(hasWebuntis()) webuntis(this.webuntis!);
if(hasCustom()) custom(this.custom!);
}
}
}

View File

@ -29,9 +29,7 @@ class TimetableColors {
}
}
static Color getColorFromString(String color) {
return getDisplayOptions(CustomTimetableColors.values.firstWhere((element) => element.name == color, orElse: () => TimetableColors.defaultColor)).color;
}
static Color getColorFromString(String color) => getDisplayOptions(CustomTimetableColors.values.firstWhere((element) => element.name == color, orElse: () => TimetableColors.defaultColor)).color;
}
class ColorModeDisplay {
@ -39,4 +37,4 @@ class ColorModeDisplay {
final String displayName;
ColorModeDisplay({required this.color, required this.displayName});
}
}

View File

@ -51,8 +51,7 @@ class _AddCustomTimetableEventDialogState extends State<CustomTimetableEventEdit
}
@override
Widget build(BuildContext context) {
return AlertDialog(
Widget build(BuildContext context) => AlertDialog(
insetPadding: const EdgeInsets.all(20),
contentPadding: const EdgeInsets.all(10),
title: const Text('Termin hinzufügen'),
@ -89,7 +88,7 @@ class _AddCustomTimetableEventDialogState extends State<CustomTimetableEventEdit
title: Text(Jiffy.parseFromDateTime(_date).yMMMd),
subtitle: const Text('Datum'),
onTap: () async {
final DateTime? pickedDate = await showDatePicker(
final pickedDate = await showDatePicker(
context: context,
initialDate: _date,
firstDate: DateTime.now().subtract(const Duration(days: 30)),
@ -185,7 +184,7 @@ class _AddCustomTimetableEventDialogState extends State<CustomTimetableEventEdit
onPressed: () {
if(!validate()) return;
CustomTimetableEvent editedEvent = CustomTimetableEvent(
var editedEvent = CustomTimetableEvent(
id: '',
title: _eventName.text,
description: _eventDescription.text,
@ -231,5 +230,4 @@ class _AddCustomTimetableEventDialogState extends State<CustomTimetableEventEdit
),
],
);
}
}

View File

@ -12,8 +12,8 @@ class TimeRegionComponent extends StatefulWidget {
class _TimeRegionComponentState extends State<TimeRegionComponent> {
@override
Widget build(BuildContext context) {
String text = widget.details.region.text!;
Color? color = widget.details.region.color;
var text = widget.details.region.text!;
var color = widget.details.region.color;
if (text == 'centerIcon') {
return Container(

View File

@ -7,8 +7,6 @@ import 'package:provider/provider.dart';
import 'package:syncfusion_flutter_calendar/calendar.dart';
import '../../../api/webuntis/queries/getHolidays/getHolidaysResponse.dart';
import '../../../api/webuntis/queries/getRooms/getRoomsResponse.dart';
import '../../../api/webuntis/queries/getSubjects/getSubjectsResponse.dart';
import '../../../api/webuntis/queries/getTimetable/getTimetableResponse.dart';
import '../../../model/timetable/timetableProps.dart';
import '../../../storage/base/settingsProvider.dart';
@ -53,9 +51,7 @@ class _TimetableState extends State<Timetable> {
}
@override
Widget build(BuildContext context) {
return Scaffold(
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: const Text('Stunden & Vertretungsplan'),
actions: [
@ -67,8 +63,7 @@ class _TimetableState extends State<Timetable> {
),
PopupMenuButton<CalendarActions>(
icon: const Icon(Icons.edit_calendar_outlined),
itemBuilder: (context) {
return CalendarActions.values.map(
itemBuilder: (context) => CalendarActions.values.map(
(e) {
String title;
Icon icon;
@ -89,8 +84,7 @@ class _TimetableState extends State<Timetable> {
)
);
}
).toList();
},
).toList(),
onSelected: (value) {
switch(value) {
case CalendarActions.addEvent:
@ -125,7 +119,7 @@ class _TimetableState extends State<Timetable> {
if(value.primaryLoading()) return const LoadingSpinner();
GetHolidaysResponse holidays = value.getHolidaysResponse;
var holidays = value.getHolidaysResponse;
return RefreshIndicator(
child: SfCalendar(
@ -181,7 +175,6 @@ class _TimetableState extends State<Timetable> {
},
),
);
}
@override
void dispose() {
@ -190,19 +183,18 @@ class _TimetableState extends State<Timetable> {
}
List<TimeRegion> _buildSpecialTimeRegions(GetHolidaysResponse holidays) {
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);
var lastMonday = DateTime.now().subtract(const Duration(days: 14)).nextWeekday(DateTime.monday);
var firstBreak = lastMonday.copyWith(hour: 10, minute: 15);
var secondBreak = lastMonday.copyWith(hour: 13, minute: 50);
Iterable<TimeRegion> holidayList = holidays.result.map((holiday) {
DateTime startDay = _parseWebuntisTimestamp(holiday.startDate, 0);
int dayCount = _parseWebuntisTimestamp(holiday.endDate, 0)
var holidayList = holidays.result.map((holiday) {
var startDay = _parseWebuntisTimestamp(holiday.startDate, 0);
var dayCount = _parseWebuntisTimestamp(holiday.endDate, 0)
.difference(startDay)
.inDays;
List<DateTime> days = List.generate(dayCount, (index) => startDay.add(Duration(days: index)));
var days = List<DateTime>.generate(dayCount, (index) => startDay.add(Duration(days: index)));
return days.map((holidayDay) {
return TimeRegion(
return days.map((holidayDay) => TimeRegion(
startTime: holidayDay.copyWith(hour: 07, minute: 55),
endTime: holidayDay.copyWith(hour: 16, minute: 30),
text: 'holiday:${holiday.name}',
@ -211,13 +203,10 @@ class _TimetableState extends State<Timetable> {
.disabledColor
.withAlpha(50),
iconData: Icons.holiday_village_outlined
);
});
));
}).expand((e) => e);
bool isInHoliday(DateTime time) {
return holidayList.any((element) => element.startTime.isSameDay(time));
}
bool isInHoliday(DateTime time) => holidayList.any((element) => element.startTime.isSameDay(time));
return [
...holidayList,
@ -246,34 +235,34 @@ class _TimetableState extends State<Timetable> {
List<GetTimetableResponseObject> _removeDuplicates(TimetableProps data, Duration maxTimeBetweenDouble) {
List<GetTimetableResponseObject> timetableList = data.getTimetableResponse.result.toList();
var timetableList = data.getTimetableResponse.result.toList();
if(timetableList.isEmpty) return timetableList;
timetableList.sort((a, b) => _parseWebuntisTimestamp(a.date, a.startTime).compareTo(_parseWebuntisTimestamp(b.date, b.startTime)));
GetTimetableResponseObject previousElement = timetableList.first;
var previousElement = timetableList.first;
for(var i = 1; i < timetableList.length; i++) {
GetTimetableResponseObject currentElement = timetableList.elementAt(i);
var currentElement = timetableList.elementAt(i);
bool isSameLesson() {
int? currentSubjectId = currentElement.su.firstOrNull?.id;
int? previousSubjectId = previousElement.su.firstOrNull?.id;
var currentSubjectId = currentElement.su.firstOrNull?.id;
var previousSubjectId = previousElement.su.firstOrNull?.id;
if(currentSubjectId == null || previousSubjectId == null || currentSubjectId != previousSubjectId) return false;
int? currentRoomId = currentElement.ro.firstOrNull?.id;
int? previousRoomId = previousElement.ro.firstOrNull?.id;
var currentRoomId = currentElement.ro.firstOrNull?.id;
var previousRoomId = previousElement.ro.firstOrNull?.id;
if(currentRoomId != previousRoomId) return false;
int? currentTeacherId = currentElement.te.firstOrNull?.id;
int? previousTeacherId = previousElement.te.firstOrNull?.id;
var currentTeacherId = currentElement.te.firstOrNull?.id;
var previousTeacherId = previousElement.te.firstOrNull?.id;
if(currentTeacherId != previousTeacherId) return false;
String? currentStatusCode = currentElement.code;
String? previousStatusCode = previousElement.code;
var currentStatusCode = currentElement.code;
var previousStatusCode = previousElement.code;
if(currentStatusCode != previousStatusCode) return false;
@ -297,20 +286,20 @@ class _TimetableState extends State<Timetable> {
TimetableEvents _buildTableEvents(TimetableProps data) {
List<GetTimetableResponseObject> timetableList = data.getTimetableResponse.result.toList();
var timetableList = data.getTimetableResponse.result.toList();
if(settings.val().timetableSettings.connectDoubleLessons) {
timetableList = _removeDuplicates(data, const Duration(minutes: 5));
}
List<Appointment> appointments = timetableList.map((element) {
var appointments = timetableList.map((element) {
GetRoomsResponse rooms = data.getRoomsResponse;
GetSubjectsResponse subjects = data.getSubjectsResponse;
var rooms = data.getRoomsResponse;
var subjects = data.getSubjectsResponse;
try {
DateTime startTime = _parseWebuntisTimestamp(element.date, element.startTime);
DateTime endTime = _parseWebuntisTimestamp(element.date, element.endTime);
var startTime = _parseWebuntisTimestamp(element.date, element.startTime);
var endTime = _parseWebuntisTimestamp(element.date, element.endTime);
return Appointment(
id: ArbitraryAppointment(webuntis: element),
startTime: startTime,
@ -324,7 +313,7 @@ class _TimetableState extends State<Timetable> {
color: _getEventColor(element, startTime, endTime),
);
} catch(e) {
DateTime endTime = _parseWebuntisTimestamp(element.date, element.endTime);
var endTime = _parseWebuntisTimestamp(element.date, element.endTime);
return Appointment(
id: ArbitraryAppointment(webuntis: element),
startTime: _parseWebuntisTimestamp(element.date, element.startTime),
@ -339,8 +328,7 @@ class _TimetableState extends State<Timetable> {
}
}).toList();
appointments.addAll(data.getCustomTimetableEventResponse.events.map((customEvent) {
return Appointment(
appointments.addAll(data.getCustomTimetableEventResponse.events.map((customEvent) => Appointment(
id: ArbitraryAppointment(custom: customEvent),
startTime: customEvent.startDate,
endTime: customEvent.endDate,
@ -350,20 +338,19 @@ class _TimetableState extends State<Timetable> {
color: TimetableColors.getColorFromString(customEvent.color ?? TimetableColors.defaultColor.name),
startTimeZone: '',
endTimeZone: '',
);
}));
)));
return TimetableEvents(appointments);
}
DateTime _parseWebuntisTimestamp(int date, int time) {
String timeString = time.toString().padLeft(4, '0');
var timeString = time.toString().padLeft(4, '0');
return DateTime.parse('$date ${timeString.substring(0, 2)}:${timeString.substring(2, 4)}');
}
Color _getEventColor(GetTimetableResponseObject webuntisElement, DateTime startTime, DateTime endTime) {
// Make element darker, when it already took place
int alpha = endTime.isBefore(DateTime.now()) ? 100 : 255;
var alpha = endTime.isBefore(DateTime.now()) ? 100 : 255;
// Cancelled
if(webuntisElement.code == 'cancelled') return const Color(0xff000000).withAlpha(alpha);
@ -382,7 +369,7 @@ class _TimetableState extends State<Timetable> {
}
bool _isCrossedOut(CalendarAppointmentDetails calendarEntry) {
ArbitraryAppointment appointment = calendarEntry.appointments.first.id as ArbitraryAppointment;
var appointment = calendarEntry.appointments.first.id as ArbitraryAppointment;
if(appointment.hasWebuntis()) {
return appointment.webuntis!.code == 'cancelled';
}

View File

@ -5,4 +5,4 @@ class TimetableEvents extends CalendarDataSource {
TimetableEvents(List<Appointment> source) {
appointments = source;
}
}
}

View File

@ -34,8 +34,7 @@ class _ViewCustomTimetableEventsState extends State<ViewCustomTimetableEvents> {
}
@override
Widget build(BuildContext context) {
return Scaffold(
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
title: const Text('Eigene Termine'),
actions: [
@ -49,8 +48,7 @@ class _ViewCustomTimetableEventsState extends State<ViewCustomTimetableEvents> {
if(value.primaryLoading()) return const LoadingSpinner();
var listView = ListView(
children: value.getCustomTimetableEventResponse.events.map((e) {
return ListTile(
children: value.getCustomTimetableEventResponse.events.map((e) => ListTile(
title: Text(e.title),
subtitle: Text("${e.rrule.isNotEmpty ? "wiederholdend, " : ""}beginnend ${Jiffy.parseFromDateTime(e.startDate).fromNow()}"),
leading: CenteredLeading(Icon(e.rrule.isEmpty ? Icons.event_outlined : Icons.event_repeat_outlined)),
@ -71,8 +69,7 @@ class _ViewCustomTimetableEventsState extends State<ViewCustomTimetableEvents> {
)
],
),
);
}).toList(),
)).toList(),
);
var placeholder = PlaceholderView(
@ -95,5 +92,4 @@ class _ViewCustomTimetableEventsState extends State<ViewCustomTimetableEvents> {
);
}),
);
}
}

View File

@ -14,8 +14,7 @@ import '../../storage/timetable/timetableSettings.dart';
import '../pages/files/files.dart';
class DefaultSettings {
static Settings get() {
return Settings(
static Settings get() => Settings(
appTheme: ThemeMode.system,
devToolsEnabled: false,
gradeAveragesSettings: GradeAveragesSettings(
@ -53,5 +52,4 @@ class DefaultSettings {
showPerformanceOverlay: false,
),
);
}
}
}

View File

@ -19,8 +19,7 @@ class DevToolsSettingsDialog extends StatefulWidget {
class _DevToolsSettingsDialogState extends State<DevToolsSettingsDialog> {
@override
Widget build(BuildContext context) {
return Column(
Widget build(BuildContext context) => Column(
children: [
ListTile(
leading: const CenteredLeading(Icon(Icons.speed_outlined)),
@ -95,14 +94,10 @@ class _DevToolsSettingsDialogState extends State<DevToolsSettingsDialog> {
title: const Text('Cache-storage JSON dump'),
subtitle: FutureBuilder(
future: const CacheView().totalSize(),
builder: (context, snapshot) {
return Text("etwa ${snapshot.hasError ? "?" : snapshot.hasData ? filesize(snapshot.data) : "..."}\nLange tippen um zu löschen");
},
builder: (context, snapshot) => Text("etwa ${snapshot.hasError ? "?" : snapshot.hasData ? filesize(snapshot.data) : "..."}\nLange tippen um zu löschen"),
),
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return const CacheView();
}));
Navigator.push(context, MaterialPageRoute(builder: (context) => const CacheView()));
},
onLongPress: () {
ConfirmDialog(
@ -116,5 +111,4 @@ class _DevToolsSettingsDialogState extends State<DevToolsSettingsDialog> {
),
],
);
}
}

View File

@ -11,8 +11,7 @@ class PrivacyInfo {
PrivacyInfo({required this.providerText, required this.imprintUrl, required this.privacyUrl});
void showPopup(BuildContext context) {
showDialog(context: context, builder: (context) {
return SimpleDialog(
showDialog(context: context, builder: (context) => SimpleDialog(
title: Text('Betreiberinformation | $providerText'),
children: [
ListTile(
@ -28,7 +27,6 @@ class PrivacyInfo {
onTap: () => ConfirmDialog.openBrowser(context, privacyUrl),
),
],
);
});
));
}
}
}

View File

@ -36,10 +36,7 @@ class _SettingsState extends State<Settings> {
bool developerMode = false;
@override
Widget build(BuildContext context) {
return Consumer<SettingsProvider>(builder: (context, settings, child) {
return Scaffold(
Widget build(BuildContext context) => Consumer<SettingsProvider>(builder: (context, settings, child) => Scaffold(
appBar: AppBar(
title: const Text('Einstellungen'),
),
@ -180,11 +177,11 @@ class _SettingsState extends State<Settings> {
onLongPress: () => showDialog(context: context, builder: (context) => AlertDialog(
title: const Text('Info über Push'),
content: const SingleChildScrollView(child: Text(''
"Aufgrund technischer Limitationen müssen Push-nachrichten über einen externen Server - hier 'mhsl.eu' (Author dieser App) - erfolgen.\n\n"
"Aufgrund technischer Limitationen müssen Push-Nachrichten über einen externen Server - hier 'mhsl.eu' (Author dieser App) - erfolgen.\n\n"
'Wenn Push aktiviert wird, werden deine Zugangsdaten und ein Token verschlüsselt an den Betreiber gesendet und von ihm unverschlüsselt gespeichert.\n\n'
'Der extene Server verwendet die Zugangsdaten um sich maschinell in Nextcloud Talk anzumelden und via Websockets auf neue Nachrichten zu warten.\n\n'
'Wenn eine neue Nachricht eintrifft wird dein Telefon via FBC-Messaging (Google Firebase Push) vom externen Server benachrichtigt.\n\n'
'Behalte im Hinterkopf, dass deine Zugangsdaten auf einem externen Server gespeichert werden und dies trots bester Absichten ein Sicherheitsrisiko sein kann!'
'Behalte im Hinterkopf, dass deine Zugangsdaten auf einem externen Server gespeichert werden und dies trotz bester Absichten ein Sicherheitsrisiko sein kann!'
)),
actions: [
TextButton(onPressed: () => Navigator.of(context).pop(), child: const Text('Zurück'))
@ -218,8 +215,7 @@ class _SettingsState extends State<Settings> {
leading: const Icon(Icons.policy_outlined),
title: const Text('Impressum & Datenschutz'),
onTap: () {
showDialog(context: context, builder: (context) {
return SimpleDialog(
showDialog(context: context, builder: (context) => SimpleDialog(
children: [
ListTile(
leading: const CenteredLeading(Icon(Icons.school_outlined)),
@ -243,8 +239,7 @@ class _SettingsState extends State<Settings> {
onTap: () => PrivacyInfo(providerText: 'mhsl', imprintUrl: 'https://mhsl.eu/id.html', privacyUrl: 'https://mhsl.eu/datenschutz.html').showPopup(context),
),
],
);
});
));
},
trailing: const Icon(Icons.arrow_right),
),
@ -297,7 +292,5 @@ class _SettingsState extends State<Settings> {
),
],
),
);
});
}
));
}