mirror of
https://github.com/go-vikunja/app
synced 2024-05-29 00:36:49 +00:00
Compare commits
2 Commits
c2eb96c6e1
...
aa0f56231f
Author | SHA1 | Date | |
---|---|---|---|
aa0f56231f | |||
092386db2e |
63
lib/components/TaskBottomSheet.dart
Normal file
63
lib/components/TaskBottomSheet.dart
Normal file
|
@ -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<bool>? 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<TaskBottomSheet> {
|
||||||
|
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: <Widget>[
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(_currentTask.title),
|
||||||
|
BackButton(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
HtmlWidget(_currentTask.description),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ import 'dart:async';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
|
import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:vikunja_app/components/TaskBottomSheet.dart';
|
||||||
import 'package:vikunja_app/models/task.dart';
|
import 'package:vikunja_app/models/task.dart';
|
||||||
import 'package:vikunja_app/utils/misc.dart';
|
import 'package:vikunja_app/utils/misc.dart';
|
||||||
import 'package:vikunja_app/pages/list/task_edit.dart';
|
import 'package:vikunja_app/pages/list/task_edit.dart';
|
||||||
|
@ -32,30 +33,35 @@ class TaskTile extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@override
|
@override
|
||||||
TaskTileState createState() => TaskTileState(this.task);
|
TaskTileState createState() => TaskTileState(this.task);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget? _buildTaskSubtitle(Task? task, bool showInfo) {
|
Widget? _buildTaskSubtitle(Task? task, bool showInfo, BuildContext context) {
|
||||||
Duration? durationUntilDue = task?.dueDate?.difference(DateTime.now());
|
Duration? durationUntilDue = task?.dueDate?.difference(DateTime.now());
|
||||||
|
|
||||||
if(task == null)
|
if (task == null) return null;
|
||||||
return null;
|
|
||||||
|
|
||||||
List<TextSpan> texts = [];
|
List<TextSpan> texts = [];
|
||||||
|
|
||||||
if(showInfo && task.hasDueDate) {
|
if (showInfo && task.hasDueDate) {
|
||||||
texts.add(TextSpan(text: "Due " + durationToHumanReadable(durationUntilDue!), style: durationUntilDue.isNegative ? TextStyle(color: Colors.red) : null));
|
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) {
|
if (task.priority != null && task.priority != 0) {
|
||||||
texts.add(TextSpan(text: " !" + priorityToString(task.priority), style: TextStyle(color: Colors.orange)));
|
texts.add(TextSpan(
|
||||||
|
text: " !" + priorityToString(task.priority),
|
||||||
|
style: TextStyle(color: Colors.orange)));
|
||||||
}
|
}
|
||||||
|
|
||||||
//if(texts.isEmpty && task.description.isNotEmpty) {
|
//if(texts.isEmpty && task.description.isNotEmpty) {
|
||||||
// return HtmlWidget(task.description);
|
// return HtmlWidget(task.description);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if(texts.isNotEmpty) {
|
if (texts.isNotEmpty) {
|
||||||
return RichText(text: TextSpan(children: texts));
|
return RichText(text: TextSpan(children: texts));
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -82,59 +88,73 @@ class TaskTileState extends State<TaskTile> with AutomaticKeepAliveClientMixin {
|
||||||
)),
|
)),
|
||||||
),
|
),
|
||||||
title: Text(_currentTask.title),
|
title: Text(_currentTask.title),
|
||||||
subtitle:
|
subtitle: _currentTask.description.isEmpty
|
||||||
_currentTask.description.isEmpty
|
? null
|
||||||
? null
|
: HtmlWidget(_currentTask.description),
|
||||||
: HtmlWidget(_currentTask.description),
|
|
||||||
trailing: IconButton(
|
trailing: IconButton(
|
||||||
icon: Icon(Icons.settings), onPressed: () { },
|
icon: Icon(Icons.settings),
|
||||||
),
|
onPressed: () {},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return
|
return IntrinsicHeight(
|
||||||
IntrinsicHeight(child:
|
child: Row(crossAxisAlignment: CrossAxisAlignment.stretch, children: [
|
||||||
Row(
|
Container(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
width: 4.0, // Adjust the width of the red line
|
||||||
children: [
|
color: widget.task.color,
|
||||||
Container(
|
//margin: EdgeInsets.only(left: 10.0),
|
||||||
width: 4.0, // Adjust the width of the red line
|
),
|
||||||
color: widget.task.color,
|
Flexible(
|
||||||
//margin: EdgeInsets.only(left: 10.0),
|
child: ListTile(
|
||||||
),
|
onTap: () {
|
||||||
Flexible(child: CheckboxListTile(
|
showModalBottomSheet<void>(
|
||||||
title: widget.showInfo ?
|
context: context,
|
||||||
RichText(
|
builder: (BuildContext context) {
|
||||||
text: TextSpan(
|
return TaskBottomSheet(task: widget.task);
|
||||||
text: null,
|
});
|
||||||
children: <TextSpan> [
|
},
|
||||||
// TODO: get list name of task
|
title: widget.showInfo
|
||||||
//TextSpan(text: widget.task.list.title+" - ", style: TextStyle(color: Colors.grey)),
|
? RichText(
|
||||||
TextSpan(text: widget.task.title),
|
text: TextSpan(
|
||||||
],
|
text: null,
|
||||||
style: TextStyle(
|
children: <TextSpan>[
|
||||||
color: Theme.of(context).brightness == Brightness.dark ? Colors.white : Colors.black,
|
// TODO: get list name of task
|
||||||
),
|
//TextSpan(text: widget.task.list.title+" - ", style: TextStyle(color: Colors.grey)),
|
||||||
)
|
TextSpan(text: widget.task.title),
|
||||||
) : Text(_currentTask.title),
|
],
|
||||||
controlAffinity: ListTileControlAffinity.leading,
|
style: TextStyle(
|
||||||
value: _currentTask.done,
|
color: Theme.of(context).brightness == Brightness.dark
|
||||||
subtitle: _buildTaskSubtitle(widget.task, widget.showInfo),
|
? Colors.white
|
||||||
secondary:
|
: Colors.black,
|
||||||
IconButton(icon: Icon(Icons.settings), onPressed: () {
|
|
||||||
Navigator.push<Task>(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (buildContext) => TaskEditPage(
|
|
||||||
task: _currentTask,
|
|
||||||
taskState: taskState,
|
|
||||||
),
|
),
|
||||||
),
|
))
|
||||||
).then((task) => setState(() {
|
: Text(_currentTask.title),
|
||||||
if (task != null) _currentTask = task;
|
subtitle: _buildTaskSubtitle(widget.task, widget.showInfo, context),
|
||||||
})).whenComplete(() => widget.onEdit());
|
leading: Checkbox(
|
||||||
}),
|
value: _currentTask.done,
|
||||||
onChanged: _change,
|
onChanged: (bool? newValue) {
|
||||||
))]));
|
_change(newValue);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
trailing: IconButton(
|
||||||
|
icon: Icon(Icons.settings),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.push<Task>(
|
||||||
|
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 {
|
void _change(bool? value) async {
|
||||||
|
@ -144,8 +164,7 @@ class TaskTileState extends State<TaskTile> with AutomaticKeepAliveClientMixin {
|
||||||
});
|
});
|
||||||
Task? newTask = await _updateTask(_currentTask, value);
|
Task? newTask = await _updateTask(_currentTask, value);
|
||||||
setState(() {
|
setState(() {
|
||||||
if(newTask != null)
|
if (newTask != null) this._currentTask = newTask;
|
||||||
this._currentTask = newTask;
|
|
||||||
this._currentTask.loading = false;
|
this._currentTask.loading = false;
|
||||||
});
|
});
|
||||||
widget.onEdit();
|
widget.onEdit();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user