custom login implementation, period-based timetable layout with overlap handling, enhanced error dialogs, and unified bottom sheets

This commit is contained in:
2026-05-06 20:42:09 +02:00
parent 50d2941e52
commit 86d12884fc
32 changed files with 1038 additions and 377 deletions
+46 -5
View File
@@ -1,10 +1,51 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class InfoDialog {
static void show(BuildContext context, String info) {
showDialog(context: context, builder: (context) => AlertDialog(
content: Text(info),
contentPadding: const EdgeInsets.all(20),
));
/// Shows a single-text dialog. When [copyable] is true (default for error
/// details surfaces), the dialog body is selectable and a "Kopieren" action
/// places it on the clipboard with a SnackBar confirmation.
static void show(
BuildContext context,
String info, {
bool copyable = false,
String? title,
}) {
showDialog<void>(
context: context,
builder: (dialogContext) {
final theme = Theme.of(dialogContext);
return AlertDialog(
title: title != null ? Text(title) : null,
content: SingleChildScrollView(
child: copyable
? SelectableText(info, style: theme.textTheme.bodyMedium)
: Text(info, style: theme.textTheme.bodyMedium),
),
contentPadding: const EdgeInsets.fromLTRB(20, 20, 20, 12),
actions: [
if (copyable)
TextButton.icon(
onPressed: () async {
await Clipboard.setData(ClipboardData(text: info));
if (!dialogContext.mounted) return;
ScaffoldMessenger.of(dialogContext).showSnackBar(
const SnackBar(
content: Text('In Zwischenablage kopiert'),
duration: Duration(seconds: 2),
),
);
},
icon: const Icon(Icons.copy_outlined, size: 18),
label: const Text('Kopieren'),
),
TextButton(
onPressed: () => Navigator.of(dialogContext).pop(),
child: const Text('Schließen'),
),
],
);
},
);
}
}