Re-implemented getting tasks with the new seperate endpoint #39
|
@ -1,6 +1,7 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:vikunja_app/api/response.dart';
|
||||
|
||||
class Client {
|
||||
final JsonDecoder _decoder = new JsonDecoder();
|
||||
|
@ -25,33 +26,45 @@ class Client {
|
|||
'Content-Type': 'application/json'
|
||||
};
|
||||
|
||||
Future<dynamic> get(String url) {
|
||||
return http
|
||||
.get('${this.base}$url', headers: _headers)
|
||||
.then(_handleResponse);
|
||||
Future<Response> get(String url,
|
||||
[Map<String, List<String>> queryParameters]) {
|
||||
// TODO: This could be moved to a seperate function
|
||||
var uri = Uri.parse('${this.base}$url');
|
||||
// Because these are all final values, we can't just add the queryParameters and must instead build a new Uri Object every time this method is called.
|
||||
var newUri = Uri(
|
||||
scheme: uri.scheme,
|
||||
userInfo: uri.userInfo,
|
||||
host: uri.host,
|
||||
port: uri.port,
|
||||
path: uri.path,
|
||||
query: uri.query,
|
||||
queryParameters: queryParameters,
|
||||
// Because dart takes a Map<String, String> here, it is only possible to sort by one parameter while the api supports n parameters.
|
||||
fragment: uri.fragment);
|
||||
return http.get(newUri, headers: _headers).then(_handleResponse);
|
||||
}
|
||||
|
||||
Future<dynamic> delete(String url) {
|
||||
Future<Response> delete(String url) {
|
||||
return http
|
||||
.delete('${this.base}$url', headers: _headers)
|
||||
.then(_handleResponse);
|
||||
}
|
||||
|
||||
Future<dynamic> post(String url, {dynamic body}) {
|
||||
Future<Response> post(String url, {dynamic body}) {
|
||||
return http
|
||||
.post('${this.base}$url',
|
||||
headers: _headers, body: _encoder.convert(body))
|
||||
.then(_handleResponse);
|
||||
}
|
||||
|
||||
Future<dynamic> put(String url, {dynamic body}) {
|
||||
Future<Response> put(String url, {dynamic body}) {
|
||||
return http
|
||||
.put('${this.base}$url',
|
||||
headers: _headers, body: _encoder.convert(body))
|
||||
.then(_handleResponse);
|
||||
}
|
||||
|
||||
dynamic _handleResponse(http.Response response) {
|
||||
Response _handleResponse(http.Response response) {
|
||||
if (response.statusCode < 200 ||
|
||||
response.statusCode >= 400 ||
|
||||
json == null) {
|
||||
|
@ -65,12 +78,14 @@ class Client {
|
|||
throw new ApiException(
|
||||
response.statusCode, response.request.url.toString());
|
||||
}
|
||||
return _decoder.convert(response.body);
|
||||
return new Response(
|
||||
_decoder.convert(response.body), response.statusCode, response.headers);
|
||||
}
|
||||
}
|
||||
|
||||
class InvalidRequestApiException extends ApiException {
|
||||
final String message;
|
||||
|
||||
InvalidRequestApiException(int errorCode, String path, this.message)
|
||||
: super(errorCode, path);
|
||||
|
||||
|
||||
|
@ -83,6 +98,7 @@ class InvalidRequestApiException extends ApiException {
|
|||
class ApiException implements Exception {
|
||||
final int errorCode;
|
||||
final String path;
|
||||
|
||||
ApiException(this.errorCode, this.path);
|
||||
|
||||
@override
|
||||
|
|
|
@ -12,7 +12,7 @@ class ListAPIService extends APIService implements ListService {
|
|||
Future<TaskList> create(namespaceId, TaskList tl) {
|
||||
return client
|
||||
.put('/namespaces/$namespaceId/lists', body: tl.toJSON())
|
||||
.then((map) => TaskList.fromJson(map));
|
||||
.then((response) => TaskList.fromJson(response.body));
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -22,25 +22,27 @@ class ListAPIService extends APIService implements ListService {
|
|||
|
||||
@override
|
||||
Future<TaskList> get(int listId) {
|
||||
return client.get('/lists/$listId').then((map) => TaskList.fromJson(map));
|
||||
return client
|
||||
.get('/lists/$listId')
|
||||
.then((response) => TaskList.fromJson(response.body));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<TaskList>> getAll() {
|
||||
return client.get('/lists').then(
|
||||
(list) => convertList(list, (result) => TaskList.fromJson(result)));
|
||||
return client.get('/lists').then((response) =>
|
||||
convertList(response.body, (result) => TaskList.fromJson(result)));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<TaskList>> getByNamespace(int namespaceId) {
|
||||
return client.get('/namespaces/$namespaceId/lists').then(
|
||||
(list) => convertList(list, (result) => TaskList.fromJson(result)));
|
||||
return client.get('/namespaces/$namespaceId/lists').then((response) =>
|
||||
convertList(response.body, (result) => TaskList.fromJson(result)));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<TaskList> update(TaskList tl) {
|
||||
return client
|
||||
.post('/lists/${tl.id}', body: tl.toJSON())
|
||||
.then((map) => TaskList.fromJson(map));
|
||||
.then((response) => TaskList.fromJson(response.body));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ class NamespaceAPIService extends APIService implements NamespaceService {
|
|||
Future<Namespace> create(Namespace ns) {
|
||||
return client
|
||||
.put('/namespaces', body: ns.toJSON())
|
||||
.then((map) => Namespace.fromJson(map));
|
||||
.then((response) => Namespace.fromJson(response.body));
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -24,19 +24,19 @@ class NamespaceAPIService extends APIService implements NamespaceService {
|
|||
Future<Namespace> get(int namespaceId) {
|
||||
return client
|
||||
.get('/namespaces/$namespaceId')
|
||||
.then((map) => Namespace.fromJson(map));
|
||||
.then((response) => Namespace.fromJson(response.body));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<Namespace>> getAll() {
|
||||
return client.get('/namespaces').then(
|
||||
(list) => convertList(list, (result) => Namespace.fromJson(result)));
|
||||
return client.get('/namespaces').then((response) =>
|
||||
convertList(response.body, (result) => Namespace.fromJson(result)));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Namespace> update(Namespace ns) {
|
||||
return client
|
||||
.post('/namespaces/${ns.id}', body: ns.toJSON())
|
||||
.then((map) => Namespace.fromJson(map));
|
||||
.then((response) => Namespace.fromJson(response.body));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
// This is a wrapper class to be able to return the headers up to the provider
|
||||
// to properly handle things like pagination with it.
|
||||
class Response {
|
||||
Response(this.body, this.statusCode, this.headers);
|
||||
|
||||
final dynamic body;
|
||||
final int statusCode;
|
||||
final Map<String, String> headers;
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:vikunja_app/api/client.dart';
|
||||
import 'package:vikunja_app/api/response.dart';
|
||||
import 'package:vikunja_app/api/service.dart';
|
||||
import 'package:vikunja_app/models/task.dart';
|
||||
import 'package:vikunja_app/service/services.dart';
|
||||
|
@ -12,7 +13,7 @@ class TaskAPIService extends APIService implements TaskService {
|
|||
Future<Task> add(int listId, Task task) {
|
||||
return client
|
||||
.put('/lists/$listId', body: task.toJSON())
|
||||
.then((map) => Task.fromJson(map));
|
||||
.then((response) => Task.fromJson(response.body));
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -24,6 +25,16 @@ class TaskAPIService extends APIService implements TaskService {
|
|||
Future<Task> update(Task task) {
|
||||
return client
|
||||
.post('/tasks/${task.id}', body: task.toJSON())
|
||||
.then((map) => Task.fromJson(map));
|
||||
.then((response) => Task.fromJson(response.body));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Response> getAll(int listId,
|
||||
[Map<String, List<String>> queryParameters]) {
|
||||
return client.get('/lists/$listId/tasks', queryParameters).then(
|
||||
(response) => new Response(
|
||||
convertList(response.body, (result) => Task.fromJson(result)),
|
||||
response.statusCode,
|
||||
response.headers));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ class UserAPIService extends APIService implements UserService {
|
|||
var token = await client.post('/login', body: {
|
||||
'username': username,
|
||||
'password': password
|
||||
}).then((map) => map['token']);
|
||||
}).then((response) => response.body['token']);
|
||||
return UserAPIService(Client(token, client.base))
|
||||
.getCurrentUser()
|
||||
.then((user) => UserTokenPair(user, token));
|
||||
|
@ -25,12 +25,12 @@ class UserAPIService extends APIService implements UserService {
|
|||
'username': username,
|
||||
'email': email,
|
||||
'password': password
|
||||
}).then((resp) => resp['username']);
|
||||
}).then((response) => response.body['username']);
|
||||
return login(newUser, password);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<User> getCurrentUser() {
|
||||
return client.get('/user').then((map) => User.fromJson(map));
|
||||
return client.get('/user').then((response) => User.fromJson(response.body));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import 'package:meta/meta.dart';
|
||||
import 'package:vikunja_app/models/task.dart';
|
||||
import 'package:vikunja_app/models/user.dart';
|
||||
|
||||
class TaskList {
|
||||
|
@ -7,7 +6,6 @@ class TaskList {
|
|||
final String title, description;
|
||||
final User owner;
|
||||
final DateTime created, updated;
|
||||
final List<Task> tasks;
|
||||
|
||||
TaskList(
|
||||
{@required this.id,
|
||||
|
@ -15,8 +13,7 @@ class TaskList {
|
|||
this.description,
|
||||
this.owner,
|
||||
this.created,
|
||||
this.updated,
|
||||
this.tasks});
|
||||
this.updated});
|
||||
|
||||
TaskList.fromJson(Map<String, dynamic> json)
|
||||
: id = json['id'],
|
||||
|
@ -24,10 +21,7 @@ class TaskList {
|
|||
description = json['description'],
|
||||
title = json['title'],
|
||||
updated = DateTime.parse(json['updated']),
|
||||
created = DateTime.parse(json['created']),
|
||||
tasks = (json['tasks'] == null ? [] : json['tasks'] as List<dynamic>)
|
||||
?.map((taskJson) => Task.fromJson(taskJson))
|
||||
?.toList();
|
||||
created = DateTime.parse(json['created']);
|
||||
|
||||
toJSON() {
|
||||
return {
|
||||
|
|
|
@ -27,12 +27,16 @@ class Task {
|
|||
reminders = (json['reminder_dates'] as List<dynamic>)
|
||||
?.map((r) => DateTime.parse(r))
|
||||
?.toList(),
|
||||
due =
|
||||
json['due_date'] != null ? DateTime.parse(json['due_date']) : null,
|
||||
due = json['due_date'].toString() == 'null'
|
||||
? null
|
||||
: DateTime.parse(json['due_date']),
|
||||
description = json['description'],
|
||||
title = json['title'],
|
||||
done = json['done'],
|
||||
owner = User.fromJson(json['created_by']);
|
||||
owner = json['created_by'].toString() == "null"
|
||||
? null
|
||||
: User.fromJson(json[
|
||||
'created_by']); // There has to be a better way of doing this...
|
||||
|
||||
toJSON() => {
|
||||
'id': id,
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:vikunja_app/components/AddDialog.dart';
|
||||
import 'package:vikunja_app/components/TaskTile.dart';
|
||||
import 'package:vikunja_app/global.dart';
|
||||
import 'package:vikunja_app/models/list.dart';
|
||||
import 'package:vikunja_app/models/task.dart';
|
||||
import 'package:vikunja_app/pages/list/list_edit.dart';
|
||||
import 'package:vikunja_app/stores/list_store.dart';
|
||||
|
||||
class ListPage extends StatefulWidget {
|
||||
final TaskList taskList;
|
||||
|
@ -19,24 +19,18 @@ class ListPage extends StatefulWidget {
|
|||
|
||||
class _ListPageState extends State<ListPage> {
|
||||
TaskList _list;
|
||||
List<Task> _loadingTasks = [];
|
||||
bool _loading = true;
|
||||
int _currentPage = 1;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_list = TaskList(
|
||||
id: widget.taskList.id, title: widget.taskList.title, tasks: []);
|
||||
_list = TaskList(id: widget.taskList.id, title: widget.taskList.title);
|
||||
Future.microtask(() => _loadList());
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
_loadList();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final taskState = Provider.of<ListProvider>(context);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: new Text(_list.title),
|
||||
|
@ -51,15 +45,31 @@ class _ListPageState extends State<ListPage> {
|
|||
))))
|
||||
],
|
||||
),
|
||||
body: !this._loading
|
||||
body: !taskState.isLoading
|
||||
? RefreshIndicator(
|
||||
child: _list.tasks.length > 0
|
||||
? ListView(
|
||||
child: taskState.tasks.length > 0
|
||||
? ListView.builder(
|
||||
padding: EdgeInsets.symmetric(vertical: 8.0),
|
||||
children: ListTile.divideTiles(
|
||||
context: context, tiles: _listTasks())
|
||||
.toList(),
|
||||
)
|
||||
itemBuilder: (context, i) {
|
||||
if (i.isOdd) return Divider();
|
||||
|
||||
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 - 1) return null;
|
||||
|
||||
if (index >= taskState.tasks.length &&
|
||||
_currentPage < taskState.maxPages) {
|
||||
_currentPage++;
|
||||
_loadTasksForPage(_currentPage);
|
||||
}
|
||||
return index < taskState.tasks.length
|
||||
? TaskTile(
|
||||
task: taskState.tasks[index],
|
||||
)
|
||||
: null;
|
||||
})
|
||||
: Center(child: Text('This list is empty.')),
|
||||
onRefresh: _loadList,
|
||||
)
|
||||
|
@ -70,56 +80,31 @@ class _ListPageState extends State<ListPage> {
|
|||
));
|
||||
JonasFranz
commented
Please create a custom widget which handles auto loading new tasks and inserting dividers. Please create a custom widget which handles auto loading new tasks and inserting dividers.
|
||||
}
|
||||
|
||||
List<Widget> _listTasks() {
|
||||
var tasks = (_list?.tasks?.map(_buildTile) ?? []).toList();
|
||||
tasks.addAll(_loadingTasks.map(_buildLoadingTile));
|
||||
return tasks;
|
||||
Future<void> _loadList() async {
|
||||
_loadTasksForPage(1);
|
||||
}
|
||||
|
||||
TaskTile _buildTile(Task task) {
|
||||
return TaskTile(task: task, loading: false);
|
||||
}
|
||||
|
||||
TaskTile _buildLoadingTile(Task task) {
|
||||
return TaskTile(
|
||||
task: task,
|
||||
loading: true,
|
||||
void _loadTasksForPage(int page) {
|
||||
Provider.of<ListProvider>(context, listen: false).loadTasks(
|
||||
context: context,
|
||||
listId: _list.id,
|
||||
page: page,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _loadList() {
|
||||
return VikunjaGlobal.of(context)
|
||||
.listService
|
||||
.get(widget.taskList.id)
|
||||
.then((list) {
|
||||
setState(() {
|
||||
_loading = false;
|
||||
_list = list;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
_addItemDialog(BuildContext context) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (_) => AddDialog(
|
||||
onAdd: (name) => _addItem(name, context),
|
||||
onAdd: (title) => _addItem(title, context),
|
||||
decoration: new InputDecoration(
|
||||
labelText: 'Task Name', hintText: 'eg. Milk')));
|
||||
}
|
||||
|
||||
_addItem(String name, BuildContext context) {
|
||||
var globalState = VikunjaGlobal.of(context);
|
||||
var newTask = Task(
|
||||
id: null, title: name, owner: globalState.currentUser, done: false);
|
||||
setState(() => _loadingTasks.add(newTask));
|
||||
globalState.taskService.add(_list.id, newTask).then((task) {
|
||||
setState(() {
|
||||
_list.tasks.add(task);
|
||||
});
|
||||
}).then((_) {
|
||||
_loadList();
|
||||
setState(() => _loadingTasks.remove(newTask));
|
||||
_addItem(String title, BuildContext context) {
|
||||
Provider.of<ListProvider>(context, listen: false)
|
||||
.addTask(context: context, title: title, listId: _list.id)
|
||||
.then((_) {
|
||||
Scaffold.of(context).showSnackBar(SnackBar(
|
||||
content: Text('The task was added successfully!'),
|
||||
));
|
||||
|
|
|
@ -3,12 +3,14 @@ import 'dart:async';
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:after_layout/after_layout.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:vikunja_app/components/AddDialog.dart';
|
||||
import 'package:vikunja_app/global.dart';
|
||||
import 'package:vikunja_app/models/list.dart';
|
||||
import 'package:vikunja_app/models/namespace.dart';
|
||||
import 'package:vikunja_app/pages/list/list.dart';
|
||||
import 'package:vikunja_app/stores/list_store.dart';
|
||||
|
||||
class NamespacePage extends StatefulWidget {
|
||||
final Namespace namespace;
|
||||
|
@ -89,6 +91,7 @@ class _NamespacePageState extends State<NamespacePage>
|
|||
}
|
||||
|
||||
Future<void> _loadLists() {
|
||||
// FIXME: This is called even when the tasks on a list are loaded - which is not needed at all
|
||||
return VikunjaGlobal.of(context)
|
||||
.listService
|
||||
.getByNamespace(widget.namespace.id)
|
||||
|
@ -99,8 +102,14 @@ class _NamespacePageState extends State<NamespacePage>
|
|||
}
|
||||
|
||||
_openList(BuildContext context, TaskList list) {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(builder: (context) => ListPage(taskList: list)));
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (context) => ChangeNotifierProvider<ListProvider>(
|
||||
create: (_) => new ListProvider(),
|
||||
child: ListPage(
|
||||
taskList: list,
|
||||
),
|
||||
),
|
||||
JonasFranz
commented
Maybe init the provider in the ListPage? Make sure to use Builder as child when doing it. Maybe init the provider in the ListPage? Make sure to use Builder as child when doing it.
konrad
commented
You mean in the You mean in the `build` method of it?
|
||||
));
|
||||
}
|
||||
|
||||
_addListDialog(BuildContext context) {
|
||||
|
@ -116,7 +125,7 @@ class _NamespacePageState extends State<NamespacePage>
|
|||
_addList(String name, BuildContext context) {
|
||||
VikunjaGlobal.of(context)
|
||||
.listService
|
||||
.create(widget.namespace.id, TaskList(id: null, title: name, tasks: []))
|
||||
.create(widget.namespace.id, TaskList(id: null, title: name))
|
||||
.then((_) {
|
||||
setState(() {});
|
||||
_loadLists();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:vikunja_app/api/response.dart';
|
||||
import 'package:vikunja_app/models/list.dart';
|
||||
import 'package:vikunja_app/models/namespace.dart';
|
||||
import 'package:vikunja_app/models/task.dart';
|
||||
|
@ -28,7 +29,6 @@ var _lists = {
|
|||
1: TaskList(
|
||||
id: 1,
|
||||
title: 'List 1',
|
||||
tasks: _tasks.values.toList(),
|
||||
owner: _users[1],
|
||||
description: 'A nice list',
|
||||
created: DateTime.now(),
|
||||
|
@ -120,20 +120,13 @@ class MockedListService implements ListService {
|
|||
class MockedTaskService implements TaskService {
|
||||
@override
|
||||
Future delete(int taskId) {
|
||||
_lists.forEach(
|
||||
(_, list) => list.tasks.removeWhere((task) => task.id == taskId));
|
||||
_tasks.remove(taskId);
|
||||
return Future.value();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Task> update(Task task) {
|
||||
_lists.forEach((_, list) {
|
||||
if (list.tasks.where((t) => t.id == task.id).length > 0) {
|
||||
list.tasks.removeWhere((t) => t.id == task.id);
|
||||
list.tasks.add(task);
|
||||
}
|
||||
});
|
||||
_tasks[task.id] = task;
|
||||
return Future.value(_tasks[task.id] = task);
|
||||
}
|
||||
|
||||
|
@ -141,9 +134,17 @@ class MockedTaskService implements TaskService {
|
|||
Future<Task> add(int listId, Task task) {
|
||||
var id = _tasks.keys.last + 1;
|
||||
_tasks[id] = task;
|
||||
_lists[listId].tasks.add(task);
|
||||
return Future.value(task);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Response> getAll(int listId,
|
||||
[Map<String, List<String>> queryParameters]) {
|
||||
return Future.value(new Response(_tasks.values.toList(), 200, {}));
|
||||
}
|
||||
|
||||
@override
|
||||
int get maxPages => 1;
|
||||
}
|
||||
|
||||
class MockedUserService implements UserService {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:vikunja_app/api/response.dart';
|
||||
import 'package:vikunja_app/models/list.dart';
|
||||
import 'package:vikunja_app/models/namespace.dart';
|
||||
import 'package:vikunja_app/models/task.dart';
|
||||
|
@ -26,6 +27,8 @@ abstract class TaskService {
|
|||
Future<Task> update(Task task);
|
||||
Future delete(int taskId);
|
||||
Future<Task> add(int listId, Task task);
|
||||
Future<Response> getAll(int listId,
|
||||
[Map<String, List<String>> queryParameters]);
|
||||
}
|
||||
|
||||
abstract class UserService {
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:vikunja_app/models/task.dart';
|
||||
import 'package:vikunja_app/global.dart';
|
||||
|
||||
class ListProvider with ChangeNotifier {
|
||||
bool _isLoading = false;
|
||||
int _maxPages = 0;
|
||||
|
||||
// TODO: Streams
|
||||
List<Task> _tasks = [];
|
||||
|
||||
bool get isLoading => _isLoading;
|
||||
|
||||
int get maxPages => _maxPages;
|
||||
|
||||
set tasks(List<Task> tasks) {
|
||||
_tasks = tasks;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
List<Task> get tasks => _tasks;
|
||||
|
||||
void loadTasks({BuildContext context, int listId, int page = 1}) {
|
||||
_isLoading = true;
|
||||
notifyListeners();
|
||||
|
||||
VikunjaGlobal.of(context).taskService.getAll(listId, {
|
||||
"sort_by": ["done", "id"],
|
||||
"order_by": ["asc", "desc"],
|
||||
"page": [page.toString()]
|
||||
}).then((response) {
|
||||
if (response.headers["x-pagination-total-pages"] != null) {
|
||||
_maxPages = int.parse(response.headers["x-pagination-total-pages"]);
|
||||
}
|
||||
_tasks.addAll(response.body);
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> addTask({BuildContext context, String title, int listId}) {
|
||||
var globalState = VikunjaGlobal.of(context);
|
||||
var newTask = Task(
|
||||
id: null, title: title, owner: globalState.currentUser, done: false);
|
||||
_isLoading = true;
|
||||
notifyListeners();
|
||||
|
||||
return globalState.taskService.add(listId, newTask).then((task) {
|
||||
_tasks.insert(0, task);
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
});
|
||||
}
|
||||
}
|
15
pubspec.lock
15
pubspec.lock
|
@ -139,6 +139,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.8"
|
||||
nested:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: nested
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.0.4"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -160,6 +167,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
provider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: provider
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.0.5+1"
|
||||
quiver:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -258,3 +272,4 @@ packages:
|
|||
version: "2.2.0"
|
||||
sdks:
|
||||
dart: ">=2.6.0 <3.0.0"
|
||||
flutter: ">=1.12.1"
|
||||
|
|
|
@ -14,6 +14,7 @@ dependencies:
|
|||
http: ^0.12.1
|
||||
after_layout: ^1.0.7
|
||||
sentry: ^3.0.1
|
||||
provider: ^4.0.5
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
Reference in New Issue
Please save this in stores. This shouldn't be handled by the client.
Done!