mirror of
https://github.com/go-vikunja/app
synced 2024-06-14 08:24:18 +00:00
edit task color, update edited task, some cleanup
This commit is contained in:
parent
5d6120a7ac
commit
c3a7962679
|
@ -174,12 +174,14 @@ class _BucketTaskCardState extends State<BucketTaskCard> {
|
|||
),
|
||||
),
|
||||
),
|
||||
onTap: () => Navigator.push(
|
||||
onTap: () => Navigator.push<Task>(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => TaskEditPage(
|
||||
task: _currentTask,
|
||||
)),
|
||||
),
|
||||
).then((task) => setState(() {
|
||||
if (task != null) _currentTask = task;
|
||||
})),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -81,14 +81,16 @@ class TaskTileState extends State<TaskTile> {
|
|||
: Text(_currentTask.description),
|
||||
secondary:
|
||||
IconButton(icon: Icon(Icons.settings), onPressed: () {
|
||||
Navigator.push(
|
||||
Navigator.push<Task>(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => TaskEditPage(
|
||||
task: _currentTask,
|
||||
))).whenComplete(() {
|
||||
widget.onEdit();
|
||||
});
|
||||
),
|
||||
),
|
||||
).then((task) => setState(() {
|
||||
if (task != null) _currentTask = task;
|
||||
})).whenComplete(() => widget.onEdit());
|
||||
}),
|
||||
onChanged: _change,
|
||||
);
|
||||
|
@ -107,14 +109,8 @@ class TaskTileState extends State<TaskTile> {
|
|||
}
|
||||
|
||||
Future<Task> _updateTask(Task task, bool checked) {
|
||||
// TODO use copyFrom
|
||||
return VikunjaGlobal.of(context).taskService.update(Task(
|
||||
id: task.id,
|
||||
return VikunjaGlobal.of(context).taskService.update(task.copyWith(
|
||||
done: checked,
|
||||
title: task.title,
|
||||
description: task.description,
|
||||
createdBy: task.createdBy,
|
||||
dueDate: task.dueDate
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -107,4 +107,42 @@ class Task {
|
|||
Color get textColor => color != null
|
||||
? color.computeLuminance() > 0.5 ? Colors.black : Colors.white
|
||||
: null;
|
||||
|
||||
Task copyWith({
|
||||
int id, int parentTaskId, int priority, int listId, int bucketId,
|
||||
DateTime created, DateTime updated, DateTime dueDate, DateTime startDate, DateTime endDate,
|
||||
List<DateTime> reminderDates,
|
||||
String title, String description,
|
||||
bool done,
|
||||
Color color,
|
||||
bool resetColor,
|
||||
User createdBy,
|
||||
Duration repeatAfter,
|
||||
List<Task> subtasks,
|
||||
List<Label> labels,
|
||||
List<TaskAttachment> attachments,
|
||||
}) {
|
||||
return Task(
|
||||
id: id ?? this.id,
|
||||
parentTaskId: parentTaskId ?? this.parentTaskId,
|
||||
priority: priority ?? this.priority,
|
||||
listId: listId ?? this.listId,
|
||||
bucketId: bucketId ?? this.bucketId,
|
||||
created: created ?? this.created,
|
||||
updated: updated ?? this.updated,
|
||||
dueDate: dueDate ?? this.dueDate,
|
||||
startDate: startDate ?? this.startDate,
|
||||
endDate: endDate ?? this.endDate,
|
||||
reminderDates: reminderDates ?? this.reminderDates,
|
||||
title: title ?? this.title,
|
||||
description: description ?? this.description,
|
||||
done: done ?? this.done,
|
||||
color: (resetColor ?? false) ? null : color ?? this.color,
|
||||
createdBy: createdBy ?? this.createdBy,
|
||||
repeatAfter: repeatAfter ?? this.repeatAfter,
|
||||
subtasks: subtasks ?? this.subtasks,
|
||||
labels: labels ?? this.labels,
|
||||
attachments: attachments ?? this.attachments,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -224,14 +224,16 @@ class _ListPageState extends State<ListPage> {
|
|||
onReorderStart: (oldIndex) => setState(() => _draggedBucketIndex = oldIndex),
|
||||
onReorder: (oldIndex, newIndex) {},
|
||||
onReorderEnd: (newIndex) => setState(() {
|
||||
if (newIndex > _draggedBucketIndex) newIndex -= 1;
|
||||
taskState.buckets.insert(newIndex, taskState.buckets.removeAt(_draggedBucketIndex));
|
||||
bool indexUpdated = false;
|
||||
if (newIndex > _draggedBucketIndex) {
|
||||
newIndex -= 1;
|
||||
indexUpdated = true;
|
||||
}
|
||||
taskState.buckets.insert(newIndex, taskState.buckets.removeAt(_draggedBucketIndex));
|
||||
if (newIndex == 0) {
|
||||
taskState.buckets[0].position = 0;
|
||||
_updateBucket(context, taskState.buckets[0]);
|
||||
newIndex = 1;
|
||||
indexUpdated = true;
|
||||
}
|
||||
taskState.buckets[newIndex].position = newIndex == taskState.buckets.length - 1
|
||||
? taskState.buckets[newIndex - 1].position + 1
|
||||
|
@ -239,7 +241,9 @@ class _ListPageState extends State<ListPage> {
|
|||
+ taskState.buckets[newIndex + 1].position) / 2.0;
|
||||
_updateBucket(context, taskState.buckets[newIndex]);
|
||||
_draggedBucketIndex = null;
|
||||
_pageController.jumpToPage(indexUpdated ? 0 : newIndex);
|
||||
if (indexUpdated)
|
||||
_pageController.jumpToPage((newIndex
|
||||
/ (deviceData.orientation == Orientation.portrait ? 1 : 2)).floor());
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -2,13 +2,12 @@ import 'dart:developer';
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_typeahead/flutter_typeahead.dart';
|
||||
import 'package:flutter_colorpicker/flutter_colorpicker.dart';
|
||||
import 'package:vikunja_app/components/datetimePicker.dart';
|
||||
import 'package:vikunja_app/components/label.dart';
|
||||
import 'package:vikunja_app/global.dart';
|
||||
import 'package:vikunja_app/models/label.dart';
|
||||
import 'package:vikunja_app/models/task.dart';
|
||||
import 'package:vikunja_app/theme/button.dart';
|
||||
import 'package:vikunja_app/theme/buttonText.dart';
|
||||
import 'package:vikunja_app/utils/repeat_after_parse.dart';
|
||||
|
||||
class TaskEditPage extends StatefulWidget {
|
||||
|
@ -22,6 +21,7 @@ class TaskEditPage extends StatefulWidget {
|
|||
|
||||
class _TaskEditPageState extends State<TaskEditPage> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final _listKey = GlobalKey();
|
||||
bool _loading = false;
|
||||
bool _changed = false;
|
||||
|
||||
|
@ -35,6 +35,9 @@ class _TaskEditPageState extends State<TaskEditPage> {
|
|||
List<Label> _suggestedLabels;
|
||||
var _reminderInputs = <Widget>[];
|
||||
final _labelTypeAheadController = TextEditingController();
|
||||
Color _color;
|
||||
Color _pickerColor;
|
||||
bool _resetColor = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext ctx) {
|
||||
|
@ -47,14 +50,16 @@ class _TaskEditPageState extends State<TaskEditPage> {
|
|||
initialValue: time,
|
||||
label: 'Reminder',
|
||||
onSaved: (reminder) => _reminderDates[i] = reminder,
|
||||
))));
|
||||
)))
|
||||
);
|
||||
}
|
||||
|
||||
if (_labels == null) {
|
||||
_labels = widget.task.labels ?? [];
|
||||
}
|
||||
|
||||
return WillPopScope(onWillPop: () {
|
||||
return WillPopScope(
|
||||
onWillPop: () {
|
||||
if(_changed) {
|
||||
return _showConfirmationDialog();
|
||||
}
|
||||
|
@ -68,8 +73,10 @@ class _TaskEditPageState extends State<TaskEditPage> {
|
|||
builder: (BuildContext context) => SafeArea(
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: ListView(padding: const EdgeInsets.all(16.0), children: <
|
||||
Widget>[
|
||||
child: ListView(
|
||||
key: _listKey,
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 10.0),
|
||||
child: TextFormField(
|
||||
|
@ -136,8 +143,7 @@ class _TaskEditPageState extends State<TaskEditPage> {
|
|||
child: TextFormField(
|
||||
keyboardType: TextInputType.number,
|
||||
initialValue: getRepeatAfterValueFromDuration(
|
||||
widget.task.repeatAfter)
|
||||
?.toString(),
|
||||
widget.task.repeatAfter)?.toString(),
|
||||
onSaved: (repeatAfter) => _repeatAfter =
|
||||
getDurationFromType(repeatAfter, _repeatAfterType),
|
||||
onChanged: (_) => _changed = true,
|
||||
|
@ -279,27 +285,65 @@ class _TaskEditPageState extends State<TaskEditPage> {
|
|||
)
|
||||
],
|
||||
),
|
||||
Builder(
|
||||
builder: (context) => Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 10.0),
|
||||
child: FancyButton(
|
||||
onPressed: !_loading
|
||||
? () {
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 15),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 15, left: 2),
|
||||
child: Icon(
|
||||
Icons.palette,
|
||||
color: Colors.grey,
|
||||
),
|
||||
),
|
||||
ElevatedButton(
|
||||
child: Text(
|
||||
'Color',
|
||||
style: _resetColor || (_color ?? widget.task.color) == null ? null : TextStyle(
|
||||
color: (_color ?? widget.task.color)
|
||||
.computeLuminance() > 0.5 ? Colors.black : Colors.white,
|
||||
),
|
||||
),
|
||||
style: _resetColor ? null : ButtonStyle(
|
||||
backgroundColor: MaterialStateProperty
|
||||
.resolveWith((_) => _color ?? widget.task.color),
|
||||
),
|
||||
onPressed: _onColorEdit,
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 15),
|
||||
child: () {
|
||||
String colorString = (_resetColor ? null : (_color ?? widget.task.color))?.toString();
|
||||
colorString = colorString?.substring(10, colorString.length - 1)?.toUpperCase();
|
||||
colorString = colorString != null ? '#$colorString' : 'None';
|
||||
return Text(
|
||||
'$colorString',
|
||||
style: TextStyle(
|
||||
color: Colors.grey,
|
||||
fontStyle: FontStyle.italic,
|
||||
),
|
||||
);
|
||||
}(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: !_loading ? () {
|
||||
if (_formKey.currentState.validate()) {
|
||||
Form.of(context).save();
|
||||
_saveTask(context);
|
||||
Form.of(_listKey.currentContext).save();
|
||||
_saveTask(_listKey.currentContext);
|
||||
}
|
||||
}
|
||||
: null,
|
||||
child: _loading
|
||||
? CircularProgressIndicator()
|
||||
: VikunjaButtonText('Save'),
|
||||
))),
|
||||
]),
|
||||
} : null,
|
||||
child: Icon(Icons.save),
|
||||
),
|
||||
),
|
||||
),
|
||||
));
|
||||
);
|
||||
}
|
||||
|
||||
_saveTask(BuildContext context) async {
|
||||
|
@ -308,18 +352,17 @@ class _TaskEditPageState extends State<TaskEditPage> {
|
|||
// Removes all reminders with no value set.
|
||||
_reminderDates.removeWhere((d) => d == null);
|
||||
|
||||
Task updatedTask = Task(
|
||||
id: widget.task.id,
|
||||
Task updatedTask = widget.task.copyWith(
|
||||
title: _title,
|
||||
description: _description,
|
||||
done: widget.task.done,
|
||||
reminderDates: _reminderDates,
|
||||
createdBy: widget.task.createdBy,
|
||||
dueDate: _dueDate,
|
||||
startDate: _startDate,
|
||||
endDate: _endDate,
|
||||
priority: _priority,
|
||||
repeatAfter: _repeatAfter,
|
||||
color: _resetColor ? null : (_color ?? widget.task.color),
|
||||
resetColor: _resetColor,
|
||||
);
|
||||
|
||||
// update the labels
|
||||
|
@ -335,11 +378,12 @@ class _TaskEditPageState extends State<TaskEditPage> {
|
|||
);
|
||||
});
|
||||
|
||||
VikunjaGlobal.of(context).taskService.update(updatedTask).then((_) {
|
||||
VikunjaGlobal.of(context).taskService.update(updatedTask).then((result) {
|
||||
setState(() { _loading = false; _changed = false;});
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
||||
content: Text('The task was updated successfully!'),
|
||||
));
|
||||
Navigator.of(context).pop(result);
|
||||
}).catchError((err) {
|
||||
setState(() => _loading = false);
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
|
@ -361,9 +405,7 @@ class _TaskEditPageState extends State<TaskEditPage> {
|
|||
|
||||
_searchLabel(String query) {
|
||||
return VikunjaGlobal.of(context)
|
||||
.labelService
|
||||
.getAll(query: query)
|
||||
.then((labels) {
|
||||
.labelService.getAll(query: query).then((labels) {
|
||||
log("searched");
|
||||
// Only show those labels which aren't already added to the task
|
||||
labels.removeWhere((labelToRemove) => _labels.contains(labelToRemove));
|
||||
|
@ -444,6 +486,61 @@ class _TaskEditPageState extends State<TaskEditPage> {
|
|||
}
|
||||
}
|
||||
|
||||
_onColorEdit() {
|
||||
_pickerColor = _resetColor || (_color ?? widget.task.color) == null
|
||||
? Colors.black
|
||||
: _color ?? widget.task.color;
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: const Text('Task Color'),
|
||||
content: SingleChildScrollView(
|
||||
child: ColorPicker(
|
||||
pickerColor: _pickerColor,
|
||||
enableAlpha: false,
|
||||
labelTypes: const [ColorLabelType.hsl, ColorLabelType.rgb],
|
||||
paletteType: PaletteType.hslWithLightness,
|
||||
hexInputBar: true,
|
||||
onColorChanged: (color) => setState(() => _pickerColor = color),
|
||||
),
|
||||
),
|
||||
actions: <TextButton>[
|
||||
TextButton(
|
||||
child: Text('Cancel'),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
TextButton(
|
||||
child: Text('Reset'),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_color = null;
|
||||
_resetColor = true;
|
||||
_changed = _color != widget.task.color;
|
||||
});
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
TextButton(
|
||||
child: Text('Ok'),
|
||||
onPressed: () {
|
||||
if (_pickerColor != Colors.black) setState(() {
|
||||
_color = _pickerColor;
|
||||
_resetColor = false;
|
||||
_changed = _color != widget.task.color;
|
||||
});
|
||||
else setState(() {
|
||||
_color = null;
|
||||
_resetColor = true;
|
||||
_changed = _color != widget.task.color;
|
||||
});
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<bool> _showConfirmationDialog() async {
|
||||
return showDialog<bool>(
|
||||
context: context,
|
||||
|
|
|
@ -174,6 +174,13 @@ packages:
|
|||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_colorpicker:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_colorpicker
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
flutter_keyboard_visibility:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -24,6 +24,7 @@ dependencies:
|
|||
petitparser: ^5.0.0
|
||||
provider: ^6.0.3
|
||||
webview_flutter: ^3.0.4
|
||||
flutter_colorpicker: ^1.0.3
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
Loading…
Reference in New Issue
Block a user