2018-09-27 15:55:56 +00:00
|
|
|
import 'dart:async';
|
2022-05-08 08:16:06 +00:00
|
|
|
import 'dart:math';
|
2022-07-27 00:15:17 +00:00
|
|
|
import 'dart:ui';
|
2018-09-27 15:55:56 +00:00
|
|
|
|
2018-09-15 16:21:48 +00:00
|
|
|
import 'package:flutter/material.dart';
|
2022-07-27 00:15:17 +00:00
|
|
|
import 'package:flutter/scheduler.dart';
|
2021-06-10 07:58:25 +00:00
|
|
|
import 'package:provider/provider.dart';
|
2018-09-27 15:55:56 +00:00
|
|
|
import 'package:vikunja_app/components/AddDialog.dart';
|
|
|
|
import 'package:vikunja_app/components/TaskTile.dart';
|
2022-07-27 00:15:17 +00:00
|
|
|
import 'package:vikunja_app/components/SliverBucketList.dart';
|
|
|
|
import 'package:vikunja_app/components/SliverBucketPersistentHeader.dart';
|
2018-09-22 20:56:16 +00:00
|
|
|
import 'package:vikunja_app/global.dart';
|
2019-03-11 20:29:15 +00:00
|
|
|
import 'package:vikunja_app/models/list.dart';
|
2018-09-22 20:56:16 +00:00
|
|
|
import 'package:vikunja_app/models/task.dart';
|
2022-07-15 14:25:16 +00:00
|
|
|
import 'package:vikunja_app/models/bucket.dart';
|
2019-03-16 13:29:00 +00:00
|
|
|
import 'package:vikunja_app/pages/list/list_edit.dart';
|
2021-06-04 09:34:25 +00:00
|
|
|
import 'package:vikunja_app/pages/list/task_edit.dart';
|
2021-06-10 07:58:25 +00:00
|
|
|
import 'package:vikunja_app/stores/list_store.dart';
|
2018-09-15 16:21:48 +00:00
|
|
|
|
|
|
|
class ListPage extends StatefulWidget {
|
2018-09-17 16:16:50 +00:00
|
|
|
final TaskList taskList;
|
2018-09-15 16:21:48 +00:00
|
|
|
|
2022-05-08 08:16:06 +00:00
|
|
|
//ListPage({this.taskList}) : super(key: Key(taskList.id.toString()));
|
|
|
|
ListPage({this.taskList}) : super(key: Key(Random().nextInt(100000).toString()));
|
2018-09-15 16:21:48 +00:00
|
|
|
|
|
|
|
@override
|
|
|
|
_ListPageState createState() => _ListPageState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class _ListPageState extends State<ListPage> {
|
2022-07-10 10:21:48 +00:00
|
|
|
int _viewIndex = 0;
|
2019-03-11 20:29:15 +00:00
|
|
|
TaskList _list;
|
2018-09-27 15:55:56 +00:00
|
|
|
List<Task> _loadingTasks = [];
|
2021-06-10 07:58:25 +00:00
|
|
|
int _currentPage = 1;
|
2018-09-27 15:55:56 +00:00
|
|
|
bool _loading = true;
|
2022-04-12 19:03:16 +00:00
|
|
|
bool displayDoneTasks;
|
2022-05-08 08:16:06 +00:00
|
|
|
ListProvider taskState;
|
2022-07-27 00:15:17 +00:00
|
|
|
PageController _pageController;
|
|
|
|
Map<int, ValueKey<int>> _bucketKeys = {};
|
|
|
|
Map<int, bool> _bucketScrollable = {};
|
|
|
|
Map<int, ScrollController> _controllers = {};
|
|
|
|
int _draggedBucketIndex;
|
2018-09-17 16:16:50 +00:00
|
|
|
|
|
|
|
@override
|
|
|
|
void initState() {
|
2019-03-11 20:29:15 +00:00
|
|
|
_list = TaskList(
|
2021-06-04 09:34:25 +00:00
|
|
|
id: widget.taskList.id,
|
|
|
|
title: widget.taskList.title,
|
|
|
|
tasks: [],
|
|
|
|
);
|
2022-05-08 08:16:06 +00:00
|
|
|
super.initState();
|
2022-04-12 16:46:30 +00:00
|
|
|
Future.delayed(Duration.zero, (){
|
2022-05-08 08:16:06 +00:00
|
|
|
_loadList();
|
2022-04-12 16:46:30 +00:00
|
|
|
});
|
2018-09-17 16:16:50 +00:00
|
|
|
}
|
2018-09-15 17:40:59 +00:00
|
|
|
|
2018-09-15 16:21:48 +00:00
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
2022-05-08 08:16:06 +00:00
|
|
|
taskState = Provider.of<ListProvider>(context);
|
2018-09-15 16:21:48 +00:00
|
|
|
return Scaffold(
|
2021-12-21 11:22:17 +00:00
|
|
|
appBar: AppBar(
|
|
|
|
title: Text(_list.title),
|
|
|
|
actions: <Widget>[
|
|
|
|
IconButton(
|
|
|
|
icon: Icon(Icons.edit),
|
|
|
|
onPressed: () => Navigator.push(
|
|
|
|
context,
|
|
|
|
MaterialPageRoute(
|
|
|
|
builder: (context) => ListEditPage(
|
|
|
|
list: _list,
|
|
|
|
),
|
2022-05-08 08:16:06 +00:00
|
|
|
)).whenComplete(() => _loadList()),
|
2021-12-21 11:22:17 +00:00
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
// TODO: it brakes the flow with _loadingTasks and conflicts with the provider
|
|
|
|
body: !taskState.isLoading
|
|
|
|
? RefreshIndicator(
|
2022-07-15 14:25:16 +00:00
|
|
|
child: taskState.tasks.length > 0 || taskState.buckets.length > 0
|
2021-06-10 07:58:25 +00:00
|
|
|
? ListenableProvider.value(
|
|
|
|
value: taskState,
|
2022-07-23 23:08:59 +00:00
|
|
|
child: Theme(
|
|
|
|
data: (ThemeData base) {
|
|
|
|
return base.copyWith(
|
|
|
|
chipTheme: base.chipTheme.copyWith(
|
|
|
|
labelPadding: EdgeInsets.symmetric(horizontal: 2),
|
|
|
|
shape: RoundedRectangleBorder(
|
|
|
|
borderRadius: BorderRadius.all(Radius.circular(5)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}(Theme.of(context)),
|
|
|
|
child: () {
|
|
|
|
switch (_viewIndex) {
|
|
|
|
case 0:
|
|
|
|
return _listView(context);
|
|
|
|
case 1:
|
|
|
|
return _kanbanView(context);
|
|
|
|
default:
|
|
|
|
return _listView(context);
|
|
|
|
}
|
|
|
|
}(),
|
|
|
|
),
|
2021-12-21 11:22:17 +00:00
|
|
|
)
|
2021-06-10 07:58:25 +00:00
|
|
|
: Center(child: Text('This list is empty.')),
|
2021-12-21 11:22:17 +00:00
|
|
|
onRefresh: _loadList,
|
2021-06-10 07:58:25 +00:00
|
|
|
)
|
2021-12-21 11:22:17 +00:00
|
|
|
: Center(child: CircularProgressIndicator()),
|
|
|
|
floatingActionButton: Builder(
|
|
|
|
builder: (context) => FloatingActionButton(
|
|
|
|
onPressed: () => _addItemDialog(context), child: Icon(Icons.add)),
|
|
|
|
),
|
2022-07-10 10:21:48 +00:00
|
|
|
bottomNavigationBar: BottomNavigationBar(
|
|
|
|
items: const <BottomNavigationBarItem>[
|
|
|
|
BottomNavigationBarItem(
|
|
|
|
icon: Icon(Icons.view_list),
|
|
|
|
label: 'List',
|
|
|
|
tooltip: 'List',
|
|
|
|
),
|
|
|
|
BottomNavigationBarItem(
|
|
|
|
icon: Icon(Icons.view_kanban),
|
|
|
|
label: 'Kanban',
|
|
|
|
tooltip: 'Kanban',
|
|
|
|
),
|
|
|
|
],
|
|
|
|
currentIndex: _viewIndex,
|
|
|
|
onTap: _onViewTapped,
|
|
|
|
),
|
2021-06-08 05:50:05 +00:00
|
|
|
);
|
2018-09-17 16:16:50 +00:00
|
|
|
}
|
|
|
|
|
2022-07-10 10:21:48 +00:00
|
|
|
void _onViewTapped(int index) {
|
2022-07-15 14:25:16 +00:00
|
|
|
_loadList().then((_) {
|
|
|
|
_currentPage = 1;
|
|
|
|
setState(() {
|
|
|
|
_viewIndex = index;
|
|
|
|
});
|
2022-07-10 10:21:48 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-07-15 14:25:16 +00:00
|
|
|
ListView _listView(BuildContext context) {
|
|
|
|
return ListView.builder(
|
|
|
|
padding: EdgeInsets.symmetric(vertical: 8.0),
|
|
|
|
itemBuilder: (context, i) {
|
|
|
|
if (i.isOdd) return Divider();
|
|
|
|
|
|
|
|
if (_loadingTasks.isNotEmpty) {
|
|
|
|
final loadingTask = _loadingTasks.removeLast();
|
|
|
|
return _buildLoadingTile(loadingTask);
|
|
|
|
}
|
|
|
|
|
|
|
|
final index = i ~/ 2;
|
|
|
|
|
|
|
|
// This handles the case if there are no more elements in the list left which can be provided by the api
|
|
|
|
if (taskState.maxPages == _currentPage &&
|
|
|
|
index == taskState.tasks.length)
|
|
|
|
return null;
|
|
|
|
|
|
|
|
if (index >= taskState.tasks.length &&
|
|
|
|
_currentPage < taskState.maxPages) {
|
|
|
|
_currentPage++;
|
|
|
|
_loadTasksForPage(_currentPage);
|
|
|
|
}
|
|
|
|
return index < taskState.tasks.length
|
|
|
|
? _buildTile(taskState.tasks[index])
|
|
|
|
: null;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-07-27 00:15:17 +00:00
|
|
|
Widget _kanbanView(BuildContext context) {
|
|
|
|
final deviceData = MediaQuery.of(context);
|
|
|
|
final bucketWidth = deviceData.size.width
|
|
|
|
* (deviceData.orientation == Orientation.portrait ? 0.8 : 0.4);
|
|
|
|
if (_pageController == null) _pageController = PageController(viewportFraction: 0.8);
|
|
|
|
return ReorderableListView.builder(
|
2022-07-15 14:25:16 +00:00
|
|
|
scrollDirection: Axis.horizontal,
|
2022-07-27 00:15:17 +00:00
|
|
|
scrollController: _pageController,
|
|
|
|
physics: PageScrollPhysics(),
|
|
|
|
itemCount: taskState.buckets.length,
|
|
|
|
itemExtent: bucketWidth,
|
|
|
|
cacheExtent: bucketWidth,
|
|
|
|
buildDefaultDragHandles: false,
|
|
|
|
itemBuilder: (context, index) {
|
|
|
|
if (index > taskState.buckets.length) return null;
|
|
|
|
return ReorderableDelayedDragStartListener(
|
|
|
|
key: ValueKey<int>(index),
|
|
|
|
index: index,
|
|
|
|
enabled: taskState.buckets.length > 1,
|
|
|
|
child: _buildBucketTile(taskState.buckets[index]),
|
|
|
|
);
|
2022-07-15 14:25:16 +00:00
|
|
|
},
|
2022-07-27 00:15:17 +00:00
|
|
|
proxyDecorator: (child, index, animation) {
|
|
|
|
return AnimatedBuilder(
|
|
|
|
animation: animation,
|
|
|
|
child: child,
|
|
|
|
builder: (context, child) {
|
|
|
|
return Transform.scale(
|
|
|
|
scale: lerpDouble(1.0, 0.75, Curves.easeInOut.transform(animation.value)),
|
|
|
|
child: child,
|
|
|
|
);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
},
|
|
|
|
footer: _draggedBucketIndex != null ? null : SizedBox(
|
|
|
|
width: bucketWidth,
|
|
|
|
child: Column(
|
|
|
|
children: [
|
|
|
|
ListTile(
|
|
|
|
title: Align(
|
|
|
|
alignment: Alignment.centerLeft,
|
|
|
|
child: ElevatedButton.icon(
|
|
|
|
onPressed: () => _addBucketDialog(context),
|
|
|
|
label: Text('Create Bucket'),
|
|
|
|
//style: ButtonStyle(alignment: Alignment.centerLeft),
|
|
|
|
icon: Icon(Icons.add),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
Spacer(),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
onReorderStart: (oldIndex) => setState(() => _draggedBucketIndex = oldIndex),
|
|
|
|
onReorder: (oldIndex, newIndex) {},
|
|
|
|
onReorderEnd: (newIndex) => setState(() {
|
|
|
|
bool indexUpdated = false;
|
2022-07-27 18:10:01 +00:00
|
|
|
if (newIndex > _draggedBucketIndex) {
|
|
|
|
newIndex -= 1;
|
|
|
|
indexUpdated = true;
|
|
|
|
}
|
|
|
|
taskState.buckets.insert(newIndex, taskState.buckets.removeAt(_draggedBucketIndex));
|
2022-07-27 00:15:17 +00:00
|
|
|
if (newIndex == 0) {
|
|
|
|
taskState.buckets[0].position = 0;
|
|
|
|
_updateBucket(context, taskState.buckets[0]);
|
|
|
|
newIndex = 1;
|
|
|
|
}
|
|
|
|
taskState.buckets[newIndex].position = newIndex == taskState.buckets.length - 1
|
|
|
|
? taskState.buckets[newIndex - 1].position + 1
|
|
|
|
: (taskState.buckets[newIndex - 1].position
|
|
|
|
+ taskState.buckets[newIndex + 1].position) / 2.0;
|
|
|
|
_updateBucket(context, taskState.buckets[newIndex]);
|
|
|
|
_draggedBucketIndex = null;
|
2022-07-27 18:10:01 +00:00
|
|
|
if (indexUpdated)
|
|
|
|
_pageController.jumpToPage((newIndex
|
|
|
|
/ (deviceData.orientation == Orientation.portrait ? 1 : 2)).floor());
|
2022-07-27 00:15:17 +00:00
|
|
|
}),
|
2022-07-15 14:25:16 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2018-09-27 15:55:56 +00:00
|
|
|
TaskTile _buildTile(Task task) {
|
2021-06-04 09:34:25 +00:00
|
|
|
return TaskTile(
|
|
|
|
task: task,
|
|
|
|
loading: false,
|
2022-04-20 20:57:21 +00:00
|
|
|
onEdit: () {
|
|
|
|
/*Navigator.push(
|
|
|
|
context,
|
|
|
|
MaterialPageRoute(
|
|
|
|
builder: (context) =>
|
|
|
|
TaskEditPage(
|
|
|
|
task: task,
|
|
|
|
),
|
2021-06-04 09:34:25 +00:00
|
|
|
),
|
2022-04-20 20:57:21 +00:00
|
|
|
);*/
|
|
|
|
},
|
2021-06-04 09:34:25 +00:00
|
|
|
onMarkedAsDone: (done) {
|
2021-06-10 07:58:25 +00:00
|
|
|
Provider.of<ListProvider>(context, listen: false).updateTask(
|
|
|
|
context: context,
|
|
|
|
id: task.id,
|
|
|
|
done: done,
|
2021-06-08 05:50:05 +00:00
|
|
|
);
|
2021-06-04 09:34:25 +00:00
|
|
|
},
|
|
|
|
);
|
2018-09-17 16:16:50 +00:00
|
|
|
}
|
|
|
|
|
2022-07-27 00:15:17 +00:00
|
|
|
Widget _buildBucketTile(Bucket bucket) {
|
|
|
|
final theme = Theme.of(context);
|
|
|
|
final addTaskButton = ElevatedButton.icon(
|
|
|
|
icon: Icon(Icons.add),
|
|
|
|
label: Text('Add Task'),
|
|
|
|
onPressed: () => _addItemDialog(context, bucket),
|
|
|
|
);
|
|
|
|
|
|
|
|
if (_controllers[bucket.id] == null) {
|
|
|
|
_controllers[bucket.id] = ScrollController();
|
|
|
|
}
|
|
|
|
if (_bucketKeys[bucket.id] == null) {
|
|
|
|
if (_bucketKeys[bucket.id] == null)
|
|
|
|
_bucketKeys[bucket.id] = ValueKey<int>(bucket.id);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Stack(
|
|
|
|
key: _bucketKeys[bucket.id],
|
|
|
|
children: <Widget>[
|
|
|
|
CustomScrollView(
|
|
|
|
controller: _controllers[bucket.id],
|
|
|
|
slivers: <Widget>[
|
|
|
|
SliverBucketPersistentHeader(
|
|
|
|
minExtent: 56,
|
|
|
|
maxExtent: 56,
|
|
|
|
child: Material(
|
|
|
|
color: theme.scaffoldBackgroundColor,
|
|
|
|
child: ListTile(
|
|
|
|
title: Text(
|
|
|
|
bucket.title,
|
|
|
|
style: theme.textTheme.titleLarge,
|
2022-07-23 23:08:59 +00:00
|
|
|
),
|
2022-07-27 00:15:17 +00:00
|
|
|
trailing: Icon(Icons.more_vert),
|
2022-07-23 23:08:59 +00:00
|
|
|
),
|
2022-07-22 21:46:22 +00:00
|
|
|
),
|
2022-07-27 00:15:17 +00:00
|
|
|
),
|
|
|
|
SliverPadding(
|
|
|
|
padding: const EdgeInsets.symmetric(horizontal: 8),
|
|
|
|
sliver: SliverBucketList(
|
|
|
|
bucket: bucket,
|
|
|
|
onLast: () {
|
|
|
|
if (_bucketScrollable[bucket.id] == null) {
|
|
|
|
SchedulerBinding.instance.addPostFrameCallback((_) {
|
|
|
|
setState(() {
|
|
|
|
_bucketScrollable[bucket.id] = _controllers[bucket.id].position.maxScrollExtent > 0;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
},
|
2022-07-22 21:46:22 +00:00
|
|
|
),
|
2022-07-27 00:15:17 +00:00
|
|
|
),
|
|
|
|
SliverVisibility(
|
|
|
|
visible: !(_bucketScrollable[bucket.id] ?? false),
|
|
|
|
maintainState: true,
|
|
|
|
maintainAnimation: true,
|
|
|
|
maintainSize: true,
|
|
|
|
sliver: SliverFillRemaining(
|
|
|
|
hasScrollBody: false,
|
|
|
|
child: Align(
|
|
|
|
alignment: Alignment.topCenter,
|
|
|
|
child: addTaskButton,
|
2022-07-22 21:46:22 +00:00
|
|
|
),
|
|
|
|
),
|
2022-07-27 00:15:17 +00:00
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
if (_bucketScrollable[bucket.id] ?? false) Align(
|
|
|
|
alignment: Alignment.bottomCenter,
|
|
|
|
child: addTaskButton,
|
|
|
|
),
|
|
|
|
],
|
2022-07-15 14:25:16 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-05-08 08:16:06 +00:00
|
|
|
Future<void> updateDisplayDoneTasks() {
|
|
|
|
return VikunjaGlobal.of(context).listService.getDisplayDoneTasks(_list.id)
|
|
|
|
.then((value) {displayDoneTasks = value == "1";});
|
2018-09-17 16:16:50 +00:00
|
|
|
}
|
|
|
|
|
2018-09-27 15:55:56 +00:00
|
|
|
TaskTile _buildLoadingTile(Task task) {
|
|
|
|
return TaskTile(
|
|
|
|
task: task,
|
|
|
|
loading: true,
|
2021-06-08 05:50:05 +00:00
|
|
|
onEdit: () => Navigator.push(
|
|
|
|
context,
|
|
|
|
MaterialPageRoute(
|
|
|
|
builder: (context) => TaskEditPage(
|
|
|
|
task: task,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
2018-09-27 15:55:56 +00:00
|
|
|
);
|
2018-09-17 16:16:50 +00:00
|
|
|
}
|
|
|
|
|
2021-06-10 07:58:25 +00:00
|
|
|
Future<void> _loadList() async {
|
2022-07-27 00:15:17 +00:00
|
|
|
updateDisplayDoneTasks().then((value) async {
|
2022-07-15 14:25:16 +00:00
|
|
|
switch (_viewIndex) {
|
|
|
|
case 0:
|
|
|
|
_loadTasksForPage(1);
|
|
|
|
break;
|
|
|
|
case 1:
|
2022-07-27 00:15:17 +00:00
|
|
|
await _loadBucketsForPage(1);
|
|
|
|
// load all buckets to get length for RecordableListView
|
|
|
|
while (_currentPage < taskState.maxPages) {
|
|
|
|
_currentPage++;
|
|
|
|
await _loadBucketsForPage(_currentPage);
|
|
|
|
}
|
2022-07-15 14:25:16 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
_loadTasksForPage(1);
|
|
|
|
}
|
|
|
|
});
|
2021-06-10 07:58:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void _loadTasksForPage(int page) {
|
|
|
|
Provider.of<ListProvider>(context, listen: false).loadTasks(
|
|
|
|
context: context,
|
|
|
|
listId: _list.id,
|
|
|
|
page: page,
|
2022-04-20 20:57:21 +00:00
|
|
|
displayDoneTasks: displayDoneTasks ?? false
|
2021-06-10 07:58:25 +00:00
|
|
|
);
|
2018-09-17 16:16:50 +00:00
|
|
|
}
|
|
|
|
|
2022-07-27 00:15:17 +00:00
|
|
|
Future<void> _loadBucketsForPage(int page) {
|
|
|
|
return Provider.of<ListProvider>(context, listen: false).loadBuckets(
|
2022-07-15 14:25:16 +00:00
|
|
|
context: context,
|
|
|
|
listId: _list.id,
|
|
|
|
page: page
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-07-19 09:47:37 +00:00
|
|
|
_addItemDialog(BuildContext context, [Bucket bucket]) {
|
2018-09-15 17:40:59 +00:00
|
|
|
showDialog(
|
2021-06-10 07:58:25 +00:00
|
|
|
context: context,
|
|
|
|
builder: (_) => AddDialog(
|
2022-07-19 09:47:37 +00:00
|
|
|
onAdd: (title) => _addItem(title, context, bucket),
|
2021-06-10 07:58:25 +00:00
|
|
|
decoration: InputDecoration(
|
2022-07-23 23:08:59 +00:00
|
|
|
labelText: (bucket != null ? '${bucket.title}: ' : '') + 'New Task Name',
|
2021-12-21 11:22:17 +00:00
|
|
|
hintText: 'eg. Milk',
|
2021-06-10 07:58:25 +00:00
|
|
|
),
|
|
|
|
),
|
2021-03-15 07:31:38 +00:00
|
|
|
);
|
2018-09-15 17:40:59 +00:00
|
|
|
}
|
2018-09-17 16:16:50 +00:00
|
|
|
|
2022-07-19 09:47:37 +00:00
|
|
|
_addItem(String title, BuildContext context, [Bucket bucket]) {
|
2018-09-17 16:16:50 +00:00
|
|
|
var globalState = VikunjaGlobal.of(context);
|
2020-06-15 21:48:15 +00:00
|
|
|
var newTask = Task(
|
2021-06-04 09:34:25 +00:00
|
|
|
id: null,
|
|
|
|
title: title,
|
|
|
|
createdBy: globalState.currentUser,
|
|
|
|
done: false,
|
2022-07-19 09:47:37 +00:00
|
|
|
bucketId: bucket?.id,
|
2021-06-04 09:34:25 +00:00
|
|
|
);
|
2018-09-27 15:55:56 +00:00
|
|
|
setState(() => _loadingTasks.add(newTask));
|
2021-06-10 07:58:25 +00:00
|
|
|
Provider.of<ListProvider>(context, listen: false)
|
|
|
|
.addTask(
|
2021-12-21 11:22:17 +00:00
|
|
|
context: context,
|
|
|
|
newTask: newTask,
|
|
|
|
listId: _list.id,
|
|
|
|
)
|
|
|
|
.then((_) {
|
2021-03-15 07:31:38 +00:00
|
|
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
2022-07-19 09:47:37 +00:00
|
|
|
content: Text('The task was added successfully' + (bucket != null ? ' to ${bucket.title}' : '') + '!'),
|
2019-03-15 06:52:50 +00:00
|
|
|
));
|
2021-12-21 11:22:17 +00:00
|
|
|
setState(() {
|
|
|
|
_loadingTasks.remove(newTask);
|
2018-09-17 16:16:50 +00:00
|
|
|
});
|
2019-03-14 21:27:13 +00:00
|
|
|
});
|
2018-09-17 16:16:50 +00:00
|
|
|
}
|
2022-07-19 09:47:37 +00:00
|
|
|
|
|
|
|
_addBucketDialog(BuildContext context) {
|
|
|
|
showDialog(
|
|
|
|
context: context,
|
|
|
|
builder: (_) => AddDialog(
|
|
|
|
onAdd: (title) => _addBucket(title, context),
|
|
|
|
decoration: InputDecoration(
|
|
|
|
labelText: 'New Bucket Name',
|
|
|
|
hintText: 'eg. To Do',
|
|
|
|
),
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
_addBucket(String title, BuildContext context) {
|
|
|
|
Provider.of<ListProvider>(context, listen: false).addBucket(
|
|
|
|
context: context,
|
|
|
|
newBucket: Bucket(
|
|
|
|
id: null,
|
|
|
|
title: title,
|
|
|
|
createdBy: VikunjaGlobal.of(context).currentUser,
|
|
|
|
listId: _list.id,
|
|
|
|
),
|
|
|
|
listId: _list.id,
|
|
|
|
).then((_) {
|
|
|
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
|
|
|
content: Text('The bucket was added successfully!'),
|
|
|
|
));
|
|
|
|
setState(() {});
|
|
|
|
});
|
|
|
|
}
|
2022-07-27 00:15:17 +00:00
|
|
|
|
|
|
|
_updateBucket(BuildContext context, Bucket bucket) async {
|
|
|
|
await Provider.of<ListProvider>(context, listen: false).updateBucket(
|
|
|
|
context: context,
|
|
|
|
bucket: bucket,
|
|
|
|
);
|
|
|
|
}
|
2018-09-15 16:21:48 +00:00
|
|
|
}
|