diff --git a/lib/components/TaskBottomSheet.dart b/lib/components/TaskBottomSheet.dart new file mode 100644 index 0000000..379b8b5 --- /dev/null +++ b/lib/components/TaskBottomSheet.dart @@ -0,0 +1,63 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_widget_from_html/flutter_widget_from_html.dart'; + +import '../models/task.dart'; + +class TaskBottomSheet extends StatefulWidget { + final Task task; + final bool showInfo; + final bool loading; + final ValueSetter? onMarkedAsDone; + + const TaskBottomSheet({ + Key? key, + required this.task, + this.loading = false, + this.showInfo = false, + this.onMarkedAsDone, + }) : super(key: key); +/* + @override + TaskTileState createState() { + return new TaskTileState(this.task, this.loading); + } + + */ + @override + TaskBottomSheetState createState() => TaskBottomSheetState(this.task); +} + +class TaskBottomSheetState extends State { + Task _currentTask; + + TaskBottomSheetState(this._currentTask); + + @override + Widget build(BuildContext context) { + return Container( + height: MediaQuery.of(context).size.height * 0.9, + child: Center( + child: Padding( + padding: EdgeInsets.fromLTRB(10, 10, 10, 10), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + mainAxisSize: MainAxisSize.max, + + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(_currentTask.title), + BackButton(), + ], + ), + HtmlWidget(_currentTask.description), + ], + ), + ) + ), + ); + } + +} \ No newline at end of file diff --git a/lib/components/TaskTile.dart b/lib/components/TaskTile.dart index fc17d91..36873ae 100644 --- a/lib/components/TaskTile.dart +++ b/lib/components/TaskTile.dart @@ -3,6 +3,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_widget_from_html/flutter_widget_from_html.dart'; import 'package:provider/provider.dart'; +import 'package:vikunja_app/components/TaskBottomSheet.dart'; import 'package:vikunja_app/models/task.dart'; import 'package:vikunja_app/utils/misc.dart'; import 'package:vikunja_app/pages/list/task_edit.dart'; @@ -32,31 +33,35 @@ class TaskTile extends StatefulWidget { } */ -@override + @override TaskTileState createState() => TaskTileState(this.task); } Widget? _buildTaskSubtitle(Task? task, bool showInfo, BuildContext context) { Duration? durationUntilDue = task?.dueDate?.difference(DateTime.now()); - if(task == null) - return null; + if (task == null) return null; List texts = []; - - if(showInfo && task.hasDueDate) { - texts.add(TextSpan(text: "Due " + durationToHumanReadable(durationUntilDue!), style: durationUntilDue.isNegative ? TextStyle(color: Colors.red) : Theme.of(context).textTheme.bodyMedium)); + if (showInfo && task.hasDueDate) { + texts.add(TextSpan( + text: "Due " + durationToHumanReadable(durationUntilDue!), + style: durationUntilDue.isNegative + ? TextStyle(color: Colors.red) + : Theme.of(context).textTheme.bodyMedium)); } - if(task.priority != null && task.priority != 0) { - texts.add(TextSpan(text: " !" + priorityToString(task.priority), style: TextStyle(color: Colors.orange))); + if (task.priority != null && task.priority != 0) { + texts.add(TextSpan( + text: " !" + priorityToString(task.priority), + style: TextStyle(color: Colors.orange))); } //if(texts.isEmpty && task.description.isNotEmpty) { // return HtmlWidget(task.description); - // } + // } - if(texts.isNotEmpty) { + if (texts.isNotEmpty) { return RichText(text: TextSpan(children: texts)); } return null; @@ -83,59 +88,73 @@ class TaskTileState extends State with AutomaticKeepAliveClientMixin { )), ), title: Text(_currentTask.title), - subtitle: - _currentTask.description.isEmpty - ? null - : HtmlWidget(_currentTask.description), + subtitle: _currentTask.description.isEmpty + ? null + : HtmlWidget(_currentTask.description), trailing: IconButton( - icon: Icon(Icons.settings), onPressed: () { }, - ), + icon: Icon(Icons.settings), + onPressed: () {}, + ), ); } - return - IntrinsicHeight(child: - Row( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Container( - width: 4.0, // Adjust the width of the red line - color: widget.task.color, - //margin: EdgeInsets.only(left: 10.0), - ), - Flexible(child: CheckboxListTile( - title: widget.showInfo ? - RichText( - text: TextSpan( - text: null, - children: [ - // TODO: get list name of task - //TextSpan(text: widget.task.list.title+" - ", style: TextStyle(color: Colors.grey)), - TextSpan(text: widget.task.title), - ], - style: TextStyle( - color: Theme.of(context).brightness == Brightness.dark ? Colors.white : Colors.black, - ), - ) - ) : Text(_currentTask.title), - controlAffinity: ListTileControlAffinity.leading, - value: _currentTask.done, - subtitle: _buildTaskSubtitle(widget.task, widget.showInfo, context), - secondary: - IconButton(icon: Icon(Icons.settings), onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (buildContext) => TaskEditPage( - task: _currentTask, - taskState: taskState, + return IntrinsicHeight( + child: Row(crossAxisAlignment: CrossAxisAlignment.stretch, children: [ + Container( + width: 4.0, // Adjust the width of the red line + color: widget.task.color, + //margin: EdgeInsets.only(left: 10.0), + ), + Flexible( + child: ListTile( + onTap: () { + showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return TaskBottomSheet(task: widget.task); + }); + }, + title: widget.showInfo + ? RichText( + text: TextSpan( + text: null, + children: [ + // TODO: get list name of task + //TextSpan(text: widget.task.list.title+" - ", style: TextStyle(color: Colors.grey)), + TextSpan(text: widget.task.title), + ], + style: TextStyle( + color: Theme.of(context).brightness == Brightness.dark + ? Colors.white + : Colors.black, ), - ), - ).then((task) => setState(() { - if (task != null) _currentTask = task; - })).whenComplete(() => widget.onEdit()); - }), - onChanged: _change, - ))])); + )) + : Text(_currentTask.title), + subtitle: _buildTaskSubtitle(widget.task, widget.showInfo, context), + leading: Checkbox( + value: _currentTask.done, + onChanged: (bool? newValue) { + _change(newValue); + }, + ), + trailing: IconButton( + icon: Icon(Icons.settings), + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (buildContext) => TaskEditPage( + task: _currentTask, + taskState: taskState, + ), + ), + ) + .then((task) => setState(() { + if (task != null) _currentTask = task; + })) + .whenComplete(() => widget.onEdit()); + }), + )) + ])); } void _change(bool? value) async { @@ -145,8 +164,7 @@ class TaskTileState extends State with AutomaticKeepAliveClientMixin { }); Task? newTask = await _updateTask(_currentTask, value); setState(() { - if(newTask != null) - this._currentTask = newTask; + if (newTask != null) this._currentTask = newTask; this._currentTask.loading = false; }); widget.onEdit();