diff --git a/.idea/libraries/Dart_Packages.xml b/.idea/libraries/Dart_Packages.xml index 005afa6..7cb7313 100644 --- a/.idea/libraries/Dart_Packages.xml +++ b/.idea/libraries/Dart_Packages.xml @@ -16,6 +16,13 @@ + + + + + + @@ -1151,6 +1158,7 @@ + diff --git a/lib/screen/pages/more/countdown/addTimerDialog.dart b/lib/screen/pages/more/countdown/addTimerDialog.dart new file mode 100644 index 0000000..8db64cb --- /dev/null +++ b/lib/screen/pages/more/countdown/addTimerDialog.dart @@ -0,0 +1,59 @@ + +import 'package:flutter/material.dart'; + +class AddTimerDialog extends StatefulWidget { + const AddTimerDialog({Key? key}) : super(key: key); + + @override + State createState() => _AddTimerDialogState(); +} + +class _AddTimerDialogState extends State { + DateTime selected = DateTime.now().add(const Duration(days: 1)); + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Text("Timer hinzufügen"), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextField( + decoration: InputDecoration( + labelText: "Timer Name" + ), + ), + + TextButton(onPressed: () async { + DateTime? selectedDate = await showDatePicker(context: context, initialDate: DateTime.now(), firstDate: DateTime.now(), lastDate: DateTime.now().add(const Duration(days: 365 * 10))); + if(selectedDate == null) return; + + setState(() { + selected = selectedDate; + }); + + }, child: Text("Datum auswählen")), + + TextButton(onPressed: () async { + TimeOfDay? selectedTime = await showTimePicker(context: context, initialTime: TimeOfDay.fromDateTime(DateTime.now())); + if(selectedTime == null) return; + + setState(() { + selected = selected.copyWith(hour: selectedTime.hour, minute: selectedTime.minute); + }); + }, child: Text("Zeit auswählen")), + + Text(selected.toString()) + ], + ), + actions: [ + TextButton(onPressed: () { + Navigator.of(context).pop(); + }, child: Text("Abbrechen")), + TextButton(onPressed: () { + // TODO add timer + }, child: Text("Hinzufügen")), + ], + ); + } +} diff --git a/lib/screen/pages/more/countdown/animatedTime.dart b/lib/screen/pages/more/countdown/animatedTime.dart new file mode 100644 index 0000000..0be7851 --- /dev/null +++ b/lib/screen/pages/more/countdown/animatedTime.dart @@ -0,0 +1,53 @@ +import 'dart:async'; + +import 'package:animated_digit/animated_digit.dart'; +import 'package:flutter/cupertino.dart'; + +class AnimatedTime extends StatefulWidget { + final Duration Function() callback; + const AnimatedTime({Key? key, required this.callback}) : super(key: key); + + @override + State createState() => _AnimatedTimeState(); +} + +class _AnimatedTimeState extends State { + Duration current = Duration.zero; + + @override + void initState() { + super.initState(); + Timer.periodic(const Duration(seconds: 1), (Timer t) => update()); + } + + void update() { + setState(() { + current = widget.callback(); + }); + } + + @override + Widget build(BuildContext context) { + return Row( + children: [ + const Text("Noch "), + buildWidget(current.inDays), + const Text(" Tage, "), + buildWidget(current.inHours > 24 ? current.inHours - current.inDays * 24 : current.inHours), + const Text(":"), + buildWidget(current.inMinutes > 60 ? current.inMinutes - current.inHours * 60 : current.inMinutes), + const Text(":"), + buildWidget(current.inSeconds > 60 ? current.inSeconds - current.inMinutes * 60 : current.inSeconds), + const Text(""), + ], + ); + } + + AnimatedDigitWidget buildWidget(int value) { + return AnimatedDigitWidget( + value: value, + duration: Duration(milliseconds: 100), + textStyle: const TextStyle(fontSize: 15), + ); + } +} diff --git a/lib/screen/pages/more/countdown/countdown.dart b/lib/screen/pages/more/countdown/countdown.dart new file mode 100644 index 0000000..3565bd0 --- /dev/null +++ b/lib/screen/pages/more/countdown/countdown.dart @@ -0,0 +1,56 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:marianum_mobile/screen/pages/more/countdown/addTimerDialog.dart'; +import 'package:marianum_mobile/screen/pages/more/countdown/timer.dart'; + +class Countdown extends StatefulWidget { + const Countdown({Key? key}) : super(key: key); + + @override + State createState() => _CountdownState(); +} + +class _CountdownState extends State { + List timers = List.empty(growable: true); + + @override + void initState() { + super.initState(); + timers.add(Timer(key: const Key("1"), target: DateTime.now().add(const Duration(seconds: 20)), label: "Countdown 1")); + timers.add(Timer(key: const Key("2"), author: "goldbaja", target: DateTime.now().add(const Duration(days: 20)), label: "Sommerferien")); + timers.add(Timer(key: const Key("3"), target: DateTime.now().add(const Duration(hours: 20)), label: "Joa")); + + timers.sort((a, b) => a.target.compareTo(b.target)); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text("Countdown"), + actions: [ + IconButton(onPressed: () { + showDialog(context: context, builder: (context) => AddTimerDialog()); + }, icon: const Icon(Icons.add)), + ], + ), + body: ReorderableListView( + shrinkWrap: true, + footer: Container( + padding: EdgeInsets.only(top: 30), + child: Center( + child: Text("Halte und Ziehe ein Element um es umzusortieren.", style: TextStyle(color: Theme.of(context).disabledColor)), + ), + ), + onReorder: (int oldIndex, int newIndex) { }, + children: timers, + + ), + // body: ListView.separated( + // itemBuilder: (context, index) => timers[index], + // separatorBuilder: (context, index) => const Divider(), + // itemCount: timers.length + // ) + ); + } +} diff --git a/lib/screen/pages/more/countdown/timer.dart b/lib/screen/pages/more/countdown/timer.dart new file mode 100644 index 0000000..1239d48 --- /dev/null +++ b/lib/screen/pages/more/countdown/timer.dart @@ -0,0 +1,53 @@ + +import 'package:flutter/material.dart'; +import 'package:marianum_mobile/screen/pages/more/countdown/animatedTime.dart'; + +class Timer extends StatefulWidget { + final DateTime target; + final String? author; + final String label; + const Timer({Key? key, required this.target, this.author, required this.label}) : super(key: key); + + @override + State createState() => _TimerState(); +} + +class _TimerState extends State { + late bool isLocal; + + @override + void initState() { + super.initState(); + isLocal = widget.author == null; + } + + @override + Widget build(BuildContext context) { + return ListTile( + leading: const Icon(Icons.timer), + title: AnimatedTime( + callback: () { + if(widget.target.isBefore(DateTime.now())) return Duration.zero; + return widget.target.difference(DateTime.now()); + }, + ), + trailing: Row( + mainAxisSize: MainAxisSize.min, + children: [ + if(!isLocal) Row( + children: [ + Text("5"), + IconButton(onPressed: () { + + }, icon: const Icon(Icons.thumb_up_outlined)), + ], + ), + IconButton(onPressed: () { + + }, icon: const Icon(Icons.star_outline)) + ], + ), + subtitle: Text("${widget.label}${!isLocal ? "\ngeteilt von ${widget.author}" : ""}"), + ); + } +} diff --git a/lib/screen/pages/more/debug/ThemeColors.dart b/lib/screen/pages/more/debug/ThemeColors.dart deleted file mode 100644 index 9dd56be..0000000 --- a/lib/screen/pages/more/debug/ThemeColors.dart +++ /dev/null @@ -1,128 +0,0 @@ -import 'package:flutter/material.dart'; - -class ColorPreviewWidget extends StatelessWidget { - @override - Widget build(BuildContext context) { - final themeData = Theme.of(context); - - return ListView( - children: [ - ListTile( - leading: Icon(Icons.color_lens_outlined), - title: Text('Farbtest'), - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => ColorPreviewPage(), - ), - ); - }, - ), - ], - ); - } -} - -class ColorPreviewPage extends StatelessWidget { - @override - Widget build(BuildContext context) { - final themeData = Theme.of(context); - final colorScheme = themeData.colorScheme; - - return Scaffold( - appBar: AppBar( - title: Text('Farbtest'), - ), - body: ListView( - children: [ - for (var entry in [ - 'Primary', - 'Primary Variant', - 'Secondary', - 'Secondary Variant', - 'Background', - 'Surface', - 'Error', - 'On Primary', - 'On Secondary', - 'On Background', - 'On Surface', - 'On Error', - ]) - ColorItem(name: entry, color: _getColor(colorScheme, entry)), - ], - ), - ); - } - - Color _getColor(ColorScheme colorScheme, String name) { - switch (name) { - case 'Primary': - return colorScheme.primary; - case 'Primary Variant': - return colorScheme.primaryVariant; - case 'Secondary': - return colorScheme.secondary; - case 'Secondary Variant': - return colorScheme.secondaryVariant; - case 'Background': - return colorScheme.background; - case 'Surface': - return colorScheme.surface; - case 'Error': - return colorScheme.error; - case 'On Primary': - return colorScheme.onPrimary; - case 'On Secondary': - return colorScheme.onSecondary; - case 'On Background': - return colorScheme.onBackground; - case 'On Surface': - return colorScheme.onSurface; - case 'On Error': - return colorScheme.onError; - default: - return Colors.transparent; - } - } -} - -class ColorItem extends StatelessWidget { - final String name; - final Color color; - - const ColorItem({Key? key, required this.name, required this.color}) - : super(key: key); - - @override - Widget build(BuildContext context) { - final themeData = Theme.of(context); - - return Container( - padding: EdgeInsets.all(16.0), - color: color, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - name, - style: TextStyle( - color: themeData.brightness == Brightness.light - ? Colors.black - : Colors.white, - ), - ), - Text( - '#${color.value.toRadixString(16).padLeft(8, '0').toUpperCase()}', - style: TextStyle( - color: themeData.brightness == Brightness.light - ? Colors.black - : Colors.white, - ), - ), - ], - ), - ); - } -} diff --git a/pubspec.yaml b/pubspec.yaml index 1c420b2..1ad6191 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -78,6 +78,7 @@ dependencies: package_info: ^2.0.2 syncfusion_flutter_calendar: ^21.2.4 async: ^2.11.0 + animated_digit: ^3.2.1 dev_dependencies: flutter_test: