From 4e78b5615eeae21060e7b0684bbf0d68b9bc7362 Mon Sep 17 00:00:00 2001 From: Benimautner Date: Mon, 29 Apr 2024 16:45:42 +0200 Subject: [PATCH] chore: removed all references to namespaces and lists (old names for what projects are now) --- lib/api/list_implementation.dart | 108 ------- lib/api/namespace_implementation.dart | 49 ---- lib/components/BucketTaskCard.dart | 2 +- lib/components/KanbanWidget.dart | 3 +- lib/components/TaskBottomSheet.dart | 2 +- lib/components/TaskTile.dart | 2 +- lib/global.dart | 6 - lib/pages/home.dart | 8 - lib/pages/list/list.dart | 324 --------------------- lib/pages/list/list_edit.dart | 174 ----------- lib/pages/namespace/namespace.dart | 192 ------------ lib/pages/namespace/namespace_edit.dart | 131 --------- lib/pages/namespace/overview.dart | 124 -------- lib/pages/project/project_edit.dart | 2 +- lib/pages/project/project_task_list.dart | 4 +- lib/pages/{list => project}/task_edit.dart | 0 lib/service/mocked_services.dart | 4 +- lib/service/services.dart | 5 +- 18 files changed, 10 insertions(+), 1130 deletions(-) delete mode 100644 lib/api/list_implementation.dart delete mode 100644 lib/api/namespace_implementation.dart delete mode 100644 lib/pages/list/list.dart delete mode 100644 lib/pages/list/list_edit.dart delete mode 100644 lib/pages/namespace/namespace.dart delete mode 100644 lib/pages/namespace/namespace_edit.dart delete mode 100644 lib/pages/namespace/overview.dart rename lib/pages/{list => project}/task_edit.dart (100%) diff --git a/lib/api/list_implementation.dart b/lib/api/list_implementation.dart deleted file mode 100644 index e1c6f6d..0000000 --- a/lib/api/list_implementation.dart +++ /dev/null @@ -1,108 +0,0 @@ -import 'dart:async'; - -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; -import 'package:vikunja_app/api/client.dart'; -import 'package:vikunja_app/api/service.dart'; -import 'package:vikunja_app/models/list.dart'; -import 'package:vikunja_app/service/services.dart'; - -class ListAPIService extends APIService implements ListService { - FlutterSecureStorage _storage; - ListAPIService(Client client, FlutterSecureStorage storage) - : _storage = storage, - super(client); - - @override - Future create(namespaceId, TaskList tl) { - tl.namespaceId = namespaceId; - return client - .put('/namespaces/$namespaceId/lists', body: tl.toJSON()) - .then((response) { - if (response == null) return null; - return TaskList.fromJson(response.body); - }); - } - - @override - Future delete(int listId) { - return client.delete('/lists/$listId').then((_) {}); - } - - @override - Future get(int listId) { - return client.get('/lists/$listId').then((response) { - if (response == null) return null; - final map = response.body; - if (map.containsKey('id')) { - return client.get("/lists/$listId/tasks").then((tasks) { - map['tasks'] = tasks?.body; - return TaskList.fromJson(map); - }); - } - return TaskList.fromJson(map); - }); - } - - @override - Future?> getAll() { - return client.get('/lists').then((list) { - if (list == null || list.statusCode != 200) return null; - if (list.body.toString().isEmpty) return Future.value([]); - print(list.statusCode); - return convertList(list.body, (result) => TaskList.fromJson(result)); - }); - } - - @override - Future?> getByNamespace(int namespaceId) { - // TODO there needs to be a better way for this. /namespaces/-2/lists should - // return favorite lists - if (namespaceId == -2) { - // Favourites. - return getAll().then((value) { - if (value == null) return null; - value.removeWhere((element) => !element.isFavorite); - return value; - }); - } - return client.get('/namespaces/$namespaceId/lists').then((list) { - if (list == null || list.statusCode != 200) return null; - return convertList(list.body, (result) => TaskList.fromJson(result)); - }); - } - - @override - Future update(TaskList tl) { - return client.post('/lists/${tl.id}', body: tl.toJSON()).then((response) { - if (response == null) return null; - return TaskList.fromJson(response.body); - }); - } - - @override - Future getDisplayDoneTasks(int listId) { - return _storage.read(key: "display_done_tasks_list_$listId").then((value) { - if (value == null) { - // TODO: implement default value - setDisplayDoneTasks(listId, "1"); - return Future.value("1"); - } - return value; - }); - } - - @override - void setDisplayDoneTasks(int listId, String value) { - _storage.write(key: "display_done_tasks_list_$listId", value: value); - } - - @override - Future getDefaultList() { - return _storage.read(key: "default_list_id"); - } - - @override - void setDefaultList(int? listId) { - _storage.write(key: "default_list_id", value: listId.toString()); - } -} diff --git a/lib/api/namespace_implementation.dart b/lib/api/namespace_implementation.dart deleted file mode 100644 index 5bb7349..0000000 --- a/lib/api/namespace_implementation.dart +++ /dev/null @@ -1,49 +0,0 @@ -import 'dart:async'; -import 'dart:developer'; -import 'package:vikunja_app/api/client.dart'; -import 'package:vikunja_app/api/service.dart'; -import 'package:vikunja_app/models/namespace.dart'; -import 'package:vikunja_app/service/services.dart'; - -class NamespaceAPIService extends APIService implements NamespaceService { - NamespaceAPIService(Client client) : super(client); - - @override - Future create(Namespace ns) { - return client.put('/namespaces', body: ns.toJSON()).then((response) { - if (response == null) return null; - return Namespace.fromJson(response.body); - }); - } - - @override - Future delete(int namespaceId) { - return client.delete('/namespaces/$namespaceId'); - } - - @override - Future get(int namespaceId) { - return client.get('/namespaces/$namespaceId').then((response) { - if (response == null) return null; - return Namespace.fromJson(response.body); - }); - } - - @override - Future?> getAll() { - return client.get('/namespaces').then((response) { - if (response == null) return null; - return convertList(response.body, (result) => Namespace.fromJson(result)); - }); - } - - @override - Future update(Namespace ns) { - return client - .post('/namespaces/${ns.id}', body: ns.toJSON()) - .then((response) { - if (response == null) return null; - return Namespace.fromJson(response.body); - }); - } -} diff --git a/lib/components/BucketTaskCard.dart b/lib/components/BucketTaskCard.dart index 3eec689..5218a27 100644 --- a/lib/components/BucketTaskCard.dart +++ b/lib/components/BucketTaskCard.dart @@ -5,7 +5,7 @@ import 'package:flutter/scheduler.dart'; import 'package:dotted_border/dotted_border.dart'; import 'package:provider/provider.dart'; import 'package:vikunja_app/models/task.dart'; -import 'package:vikunja_app/pages/list/task_edit.dart'; +import 'package:vikunja_app/pages/project/task_edit.dart'; import 'package:vikunja_app/utils/misc.dart'; import 'package:vikunja_app/theme/constants.dart'; diff --git a/lib/components/KanbanWidget.dart b/lib/components/KanbanWidget.dart index c36e98a..b7b573c 100644 --- a/lib/components/KanbanWidget.dart +++ b/lib/components/KanbanWidget.dart @@ -7,9 +7,8 @@ import 'package:provider/provider.dart'; import '../global.dart'; import '../models/bucket.dart'; -import '../models/list.dart'; import '../models/project.dart'; -import '../pages/list/list.dart'; +import '../pages/project/project_task_list.dart'; import '../stores/project_store.dart'; import '../utils/calculate_item_position.dart'; import 'AddDialog.dart'; diff --git a/lib/components/TaskBottomSheet.dart b/lib/components/TaskBottomSheet.dart index ac21772..27382d1 100644 --- a/lib/components/TaskBottomSheet.dart +++ b/lib/components/TaskBottomSheet.dart @@ -7,7 +7,7 @@ import 'package:vikunja_app/utils/priority.dart'; import '../models/label.dart'; import '../models/task.dart'; -import '../pages/list/task_edit.dart'; +import '../pages/project/task_edit.dart'; import '../stores/project_store.dart'; import '../theme/constants.dart'; import 'label.dart'; diff --git a/lib/components/TaskTile.dart b/lib/components/TaskTile.dart index 7d3bae4..15d5df2 100644 --- a/lib/components/TaskTile.dart +++ b/lib/components/TaskTile.dart @@ -6,7 +6,7 @@ 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'; +import 'package:vikunja_app/pages/project/task_edit.dart'; import 'package:vikunja_app/utils/priority.dart'; import '../stores/project_store.dart'; diff --git a/lib/global.dart b/lib/global.dart index 006b4fc..78c063d 100644 --- a/lib/global.dart +++ b/lib/global.dart @@ -7,8 +7,6 @@ import 'package:vikunja_app/api/client.dart'; import 'package:vikunja_app/api/label_task.dart'; import 'package:vikunja_app/api/label_task_bulk.dart'; import 'package:vikunja_app/api/labels.dart'; -import 'package:vikunja_app/api/list_implementation.dart'; -import 'package:vikunja_app/api/namespace_implementation.dart'; import 'package:vikunja_app/api/server_implementation.dart'; import 'package:vikunja_app/api/task_implementation.dart'; import 'package:vikunja_app/api/user_implementation.dart'; @@ -65,16 +63,12 @@ class VikunjaGlobalState extends State { VersionChecker get versionChecker => new VersionChecker(snackbarKey); - NamespaceService get namespaceService => new NamespaceAPIService(client); - ProjectService get projectService => new ProjectAPIService(client, _storage); TaskService get taskService => new TaskAPIService(client); BucketService get bucketService => new BucketAPIService(client); - ListService get listService => new ListAPIService(client, _storage); - TaskServiceOptions get taskServiceOptions => new TaskServiceOptions(); NotificationClass get notifications => _notificationClass; diff --git a/lib/pages/home.dart b/lib/pages/home.dart index 5600c5c..1c263fa 100644 --- a/lib/pages/home.dart +++ b/lib/pages/home.dart @@ -2,18 +2,10 @@ 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/components/ErrorDialog.dart'; -import 'package:vikunja_app/models/project.dart'; -import 'package:vikunja_app/pages/namespace/namespace.dart'; -import 'package:vikunja_app/pages/namespace/namespace_edit.dart'; import 'package:vikunja_app/pages/landing_page.dart'; import 'package:vikunja_app/global.dart'; -import 'package:vikunja_app/models/namespace.dart'; -import 'package:vikunja_app/pages/namespace/overview.dart'; import 'package:vikunja_app/pages/project/overview.dart'; import 'package:vikunja_app/pages/settings.dart'; diff --git a/lib/pages/list/list.dart b/lib/pages/list/list.dart deleted file mode 100644 index b74faef..0000000 --- a/lib/pages/list/list.dart +++ /dev/null @@ -1,324 +0,0 @@ -import 'dart:async'; -import 'dart:math'; - -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart'; -import 'package:vikunja_app/components/AddDialog.dart'; -import 'package:vikunja_app/components/KanbanWidget.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/models/bucket.dart'; -import 'package:vikunja_app/pages/list/list_edit.dart'; -import 'package:vikunja_app/pages/list/task_edit.dart'; -import 'package:vikunja_app/stores/list_store.dart'; - -import '../../components/pagestatus.dart'; - -enum BucketMenu { limit, done, delete } - -class BucketProps { - final ScrollController controller = ScrollController(); - final TextEditingController titleController = TextEditingController(); - bool scrollable = false; - bool portrait = true; - int bucketLength = 0; - Size? taskDropSize; -} - -class ListPage extends StatefulWidget { - final TaskList taskList; - - //ListPage({this.taskList}) : super(key: Key(taskList.id.toString())); - ListPage({required this.taskList}) - : super(key: Key(Random().nextInt(100000).toString())); - - @override - _ListPageState createState() => _ListPageState(); -} - -class _ListPageState extends State { - final _keyboardController = KeyboardVisibilityController(); - int _viewIndex = 0; - late TaskList _list; - List _loadingTasks = []; - int _currentPage = 1; - bool displayDoneTasks = false; - late ListProvider taskState; - late KanbanClass _kanban; - - @override - void initState() { - _list = widget.taskList; - _keyboardController.onChange.listen((visible) { - if (!visible && mounted) FocusScope.of(context).unfocus(); - }); - super.initState(); - } - - void nullSetState() { - setState(() {}); - } - - @override - Widget build(BuildContext context) { - taskState = Provider.of(context); - //_kanban = KanbanClass( - // context, nullSetState, _onViewTapped, _addItemDialog, _list); - - Widget body; - - switch (taskState.pageStatus) { - case PageStatus.built: - Future.delayed(Duration.zero, _loadList); - body = new Stack(children: [ - ListView(), - Center( - child: CircularProgressIndicator(), - ) - ]); - break; - case PageStatus.loading: - body = new Stack(children: [ - ListView(), - Center( - child: CircularProgressIndicator(), - ) - ]); - break; - case PageStatus.error: - body = new Stack(children: [ - ListView(), - Center(child: Text("There was an error loading this view")) - ]); - break; - case PageStatus.success: - body = taskState.tasks.length > 0 || taskState.buckets.length > 0 - ? ListenableProvider.value( - value: taskState, - 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 _kanban.kanbanView(); - default: - return _listView(context); - } - }(), - ), - ) - : Stack(children: [ - ListView(), - Center(child: Text('This list is empty.')) - ]); - break; - case PageStatus.empty: - body = new Stack( - children: [ListView(), Center(child: Text("This view is empty"))]); - break; - } - - return new Scaffold( - appBar: AppBar( - title: Text(_list.title), - actions: [ - IconButton( - icon: Icon(Icons.edit), - onPressed: () => Navigator.push( - context, - MaterialPageRoute( - builder: (context) => ListEditPage( - list: _list, - ), - )).whenComplete(() => _loadList()), - ), - ], - ), - body: RefreshIndicator(onRefresh: () => _loadList(), child: body), - floatingActionButton: _viewIndex == 1 - ? null - : Builder( - builder: (context) => FloatingActionButton( - onPressed: () => _addItemDialog(context), - child: Icon(Icons.add)), - ), - bottomNavigationBar: BottomNavigationBar( - items: const [ - BottomNavigationBarItem( - icon: Icon(Icons.view_list), - label: 'List', - tooltip: 'List', - ), - BottomNavigationBarItem( - icon: Icon(Icons.view_kanban), - label: 'Kanban', - tooltip: 'Kanban', - ), - ], - currentIndex: _viewIndex, - onTap: _onViewTapped, - ), - ); - } - - void _onViewTapped(int index) { - _loadList().then((_) { - _currentPage = 1; - setState(() { - _viewIndex = index; - }); - }); - } - - ListView _listView(BuildContext context) { - return ListView.builder( - padding: EdgeInsets.symmetric(vertical: 8.0), - itemCount: taskState.tasks.length * 2, - itemBuilder: (context, i) { - if (i.isOdd) return Divider(); - - if (_loadingTasks.isNotEmpty) { - final loadingTask = _loadingTasks.removeLast(); - return _buildLoadingTile(loadingTask); - } - - final index = i ~/ 2; - - if (taskState.maxPages == _currentPage && - index == taskState.tasks.length) - throw Exception("Check itemCount attribute"); - - if (index >= taskState.tasks.length && - _currentPage < taskState.maxPages) { - _currentPage++; - _loadTasksForPage(_currentPage); - } - return _buildTile(taskState.tasks[index]); - }); - } - - Widget _buildTile(Task task) { - return ListenableProvider.value( - value: taskState, - child: TaskTile( - task: task, - loading: false, - onEdit: () {}, - onMarkedAsDone: (done) { - Provider.of(context, listen: false).updateTask( - context: context, - task: task.copyWith(done: done), - ); - }, - ), - ); - } - - Future updateDisplayDoneTasks() { - return VikunjaGlobal.of(context) - .listService - .getDisplayDoneTasks(_list.id) - .then((value) { - displayDoneTasks = value == "1"; - }); - } - - TaskTile _buildLoadingTile(Task task) { - return TaskTile( - task: task, - loading: true, - onEdit: () {}, - ); - } - - Future _loadList() async { - taskState.pageStatus = (PageStatus.loading); - - updateDisplayDoneTasks().then((value) async { - switch (_viewIndex) { - case 0: - _loadTasksForPage(1); - break; - case 1: - await _kanban.loadBucketsForPage(1); - // load all buckets to get length for RecordableListView - while (_currentPage < taskState.maxPages) { - _currentPage++; - await _kanban.loadBucketsForPage(_currentPage); - } - break; - default: - _loadTasksForPage(1); - } - }); - } - - Future _loadTasksForPage(int page) { - return Provider.of(context, listen: false).loadTasks( - context: context, - listId: _list.id, - page: page, - displayDoneTasks: displayDoneTasks); - } - - Future _addItemDialog(BuildContext context, [Bucket? bucket]) { - return showDialog( - context: context, - builder: (_) => AddDialog( - onAdd: (title) => _addItem(title, context, bucket), - decoration: InputDecoration( - labelText: - (bucket != null ? '\'${bucket.title}\': ' : '') + 'New Task Name', - hintText: 'eg. Milk', - ), - ), - ); - } - - Future _addItem(String title, BuildContext context, - [Bucket? bucket]) async { - final currentUser = VikunjaGlobal.of(context).currentUser; - if (currentUser == null) { - return; - } - - final newTask = Task( - title: title, - createdBy: currentUser, - done: false, - bucketId: bucket?.id, - projectId: _list.id, - ); - setState(() => _loadingTasks.add(newTask)); - return Provider.of(context, listen: false) - .addTask( - context: context, - newTask: newTask, - listId: _list.id, - ) - .then((_) { - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text('The task was added successfully' + - (bucket != null ? ' to \'${bucket.title}\'' : '') + - '!'), - )); - setState(() { - _loadingTasks.remove(newTask); - }); - }); - } -} diff --git a/lib/pages/list/list_edit.dart b/lib/pages/list/list_edit.dart deleted file mode 100644 index 9d49eb1..0000000 --- a/lib/pages/list/list_edit.dart +++ /dev/null @@ -1,174 +0,0 @@ -import 'dart:ffi'; -import 'dart:developer'; -import 'package:flutter/material.dart'; -import 'package:flutter_typeahead/flutter_typeahead.dart'; -import 'package:vikunja_app/global.dart'; -import 'package:vikunja_app/models/list.dart'; -import 'package:vikunja_app/theme/button.dart'; -import 'package:vikunja_app/theme/buttonText.dart'; - -class ListEditPage extends StatefulWidget { - final TaskList list; - - ListEditPage({required this.list}) : super(key: Key(list.toString())); - - @override - State createState() => _ListEditPageState(); -} - -class _ListEditPageState extends State { - final _formKey = GlobalKey(); - bool _loading = false; - String _title = '', _description = ''; - bool? displayDoneTasks; - late int listId; - - @override - void initState() { - listId = widget.list.id; - super.initState(); - } - - @override - Widget build(BuildContext ctx) { - if (displayDoneTasks == null) - VikunjaGlobal.of(context) - .listService - .getDisplayDoneTasks(listId) - .then((value) => setState(() => displayDoneTasks = value == "1")); - else - log("Display done tasks: " + displayDoneTasks.toString()); - return Scaffold( - appBar: AppBar( - title: Text('Edit List'), - ), - body: Builder( - builder: (BuildContext context) => SafeArea( - child: Form( - key: _formKey, - child: ListView( - //reverse: true, - padding: const EdgeInsets.all(16.0), - children: [ - Padding( - padding: EdgeInsets.symmetric(vertical: 10.0), - child: TextFormField( - maxLines: null, - keyboardType: TextInputType.multiline, - initialValue: widget.list.title, - onSaved: (title) => _title = title ?? '', - validator: (title) { - //if (title?.length < 3 || title.length > 250) { - // return 'The title needs to have between 3 and 250 characters.'; - //} - return null; - }, - decoration: new InputDecoration( - labelText: 'Title', - border: OutlineInputBorder(), - ), - ), - ), - Padding( - padding: EdgeInsets.symmetric(vertical: 10.0), - child: TextFormField( - maxLines: null, - keyboardType: TextInputType.multiline, - initialValue: widget.list.description, - onSaved: (description) => - _description = description ?? '', - validator: (description) { - if (description == null) return null; - if (description.length > 1000) { - return 'The description can have a maximum of 1000 characters.'; - } - return null; - }, - decoration: new InputDecoration( - labelText: 'Description', - border: OutlineInputBorder(), - ), - ), - ), - Padding( - padding: EdgeInsets.symmetric(vertical: 10.0), - child: CheckboxListTile( - value: displayDoneTasks ?? false, - title: Text("Show done tasks"), - onChanged: (value) { - value ??= false; - VikunjaGlobal.of(context) - .listService - .setDisplayDoneTasks(listId, value ? "1" : "0"); - setState(() => displayDoneTasks = value); - }, - ), - ), - Builder( - builder: (context) => Padding( - padding: EdgeInsets.symmetric(vertical: 10.0), - child: FancyButton( - onPressed: !_loading - ? () { - if (_formKey.currentState!.validate()) { - Form.of(context)?.save(); - _saveList(context); - } - } - : () {}, - child: _loading - ? CircularProgressIndicator() - : VikunjaButtonText('Save'), - ))), - /*ExpansionTile( - title: Text("Sharing"), - children: [ - TypeAheadFormField( - onSuggestionSelected: (suggestion) {}, - itemBuilder: (BuildContext context, Object? itemData) { - return Card( - child: Container( - padding: EdgeInsets.all(10), - child: Text(itemData.toString())), - );}, - suggestionsCallback: (String pattern) { - List matches = []; - matches.addAll(["test", "test2", "test3"]); - matches.retainWhere((s){ - return s.toLowerCase().contains(pattern.toLowerCase()); - }); - return matches; - },) - ], - )*/ - ]), - ), - ), - ), - ); - } - - _saveList(BuildContext context) async { - setState(() => _loading = true); - // FIXME: is there a way we can update the list without creating a new list object? - // aka updating the existing list we got from context (setters?) - widget.list.title = _title; - widget.list.description = _description; - VikunjaGlobal.of(context).listService.update(widget.list).then((_) { - setState(() => _loading = false); - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text('The list was updated successfully!'), - )); - }).catchError((err) { - setState(() => _loading = false); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Something went wrong: ' + err.toString()), - action: SnackBarAction( - label: 'CLOSE', - onPressed: ScaffoldMessenger.of(context).hideCurrentSnackBar), - ), - ); - }); - } -} diff --git a/lib/pages/namespace/namespace.dart b/lib/pages/namespace/namespace.dart deleted file mode 100644 index 0901d9b..0000000 --- a/lib/pages/namespace/namespace.dart +++ /dev/null @@ -1,192 +0,0 @@ -import 'dart:async'; - -import 'package:flutter/material.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/pages/namespace/namespace_edit.dart'; -import 'package:vikunja_app/stores/list_store.dart'; - -import '../../components/pagestatus.dart'; - -class NamespacePage extends StatefulWidget { - final Namespace namespace; - - NamespacePage({required this.namespace}) - : super(key: Key(namespace.id.toString())); - - @override - _NamespacePageState createState() => new _NamespacePageState(); -} - -class _NamespacePageState extends State { - List _lists = []; - PageStatus namespacestatus = PageStatus.loading; - - ///// - // This essentially shows the lists. - @override - Widget build(BuildContext context) { - Widget body; - switch (namespacestatus) { - case PageStatus.built: - _loadLists(); - body = new Stack(children: [ - ListView(), - Center( - child: CircularProgressIndicator(), - ) - ]); - break; - case PageStatus.loading: - body = new Stack(children: [ - ListView(), - Center( - child: CircularProgressIndicator(), - ) - ]); - break; - case PageStatus.error: - body = new Stack(children: [ - ListView(), - Center(child: Text("There was an error loading this view")) - ]); - break; - case PageStatus.success: - body = new ListView( - padding: EdgeInsets.symmetric(vertical: 8.0), - children: ListTile.divideTiles( - context: context, - tiles: _lists.map((ls) => Dismissible( - key: Key(ls.id.toString()), - direction: DismissDirection.startToEnd, - child: ListTile( - title: new Text(ls.title), - onTap: () => _openList(context, ls), - trailing: Icon(Icons.arrow_right), - ), - background: Container( - color: Colors.red, - child: const ListTile( - leading: Icon(Icons.delete, - color: Colors.white, size: 36.0)), - ), - onDismissed: (direction) { - _removeList(ls).then((_) => ScaffoldMessenger.of(context) - .showSnackBar( - SnackBar(content: Text("${ls.title} removed")))); - }, - ))).toList(), - ); - break; - case PageStatus.empty: - body = new Stack( - children: [ListView(), Center(child: Text("This view is empty"))]); - break; - } - return new Scaffold( - appBar: AppBar( - title: Text(widget.namespace.title), - actions: [ - IconButton( - icon: Icon(Icons.edit), - onPressed: () => Navigator.push( - context, - MaterialPageRoute( - builder: (context) => NamespaceEditPage( - namespace: widget.namespace, - ), - )).whenComplete(() => _loadLists()), - ), - ], - ), - body: RefreshIndicator(onRefresh: () => _loadLists(), child: body), - floatingActionButton: Builder( - builder: (context) => FloatingActionButton( - onPressed: () => _addListDialog(context), - child: const Icon(Icons.add))), - ); - } - - @override - void didChangeDependencies() { - super.didChangeDependencies(); - _loadLists(); - } - - Future _removeList(TaskList list) { - return VikunjaGlobal.of(context) - .listService - .delete(list.id) - .then((_) => _loadLists()); - } - - Future _loadLists() { - // FIXME: This is called even when the tasks on a list are loaded - which is not needed at all - namespacestatus = PageStatus.loading; - return VikunjaGlobal.of(context) - .listService - .getByNamespace(widget.namespace.id) - .then((lists) => setState(() { - if (lists != null) { - this._lists = lists; - namespacestatus = PageStatus.success; - } else { - namespacestatus = PageStatus.error; - } - })); - } - - _openList(BuildContext context, TaskList list) { - Navigator.of(context).push(MaterialPageRoute( - builder: (context) => ChangeNotifierProvider( - create: (_) => new ListProvider(), - child: ListPage( - taskList: list, - ), - ), - // ListPage(taskList: list) - )); - } - - _addListDialog(BuildContext context) { - showDialog( - context: context, - builder: (_) => AddDialog( - onAdd: (name) => _addList(name, context), - decoration: new InputDecoration( - labelText: 'List Name', hintText: 'eg. Shopping List')), - ); - } - - void _addList(String name, BuildContext context) { - final curentUser = VikunjaGlobal.of(context).currentUser; - if (curentUser == null) { - return; - } - - VikunjaGlobal.of(context) - .listService - .create( - widget.namespace.id, - TaskList( - title: name, - tasks: [], - namespaceId: widget.namespace.id, - owner: curentUser, - )) - .then((_) { - setState(() {}); - _loadLists(); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('The list was successfully created!'), - ), - ); - }); - } -} diff --git a/lib/pages/namespace/namespace_edit.dart b/lib/pages/namespace/namespace_edit.dart deleted file mode 100644 index f3c51a3..0000000 --- a/lib/pages/namespace/namespace_edit.dart +++ /dev/null @@ -1,131 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:vikunja_app/global.dart'; -import 'package:vikunja_app/models/namespace.dart'; -import 'package:vikunja_app/theme/button.dart'; -import 'package:vikunja_app/theme/buttonText.dart'; - -class NamespaceEditPage extends StatefulWidget { - final Namespace namespace; - - NamespaceEditPage({required this.namespace}) - : super(key: Key(namespace.toString())); - - @override - State createState() => _NamespaceEditPageState(); -} - -class _NamespaceEditPageState extends State { - final _formKey = GlobalKey(); - bool _loading = false; - late String _name, _description; - - @override - void initState() { - _name = widget.namespace.title; - _description = widget.namespace.description; - super.initState(); - } - - @override - Widget build(BuildContext ctx) { - return Scaffold( - appBar: AppBar( - title: Text('Edit Namespace'), - ), - body: Builder( - builder: (BuildContext context) => SafeArea( - child: Form( - key: _formKey, - child: ListView( - padding: const EdgeInsets.all(16.0), - children: [ - Padding( - padding: EdgeInsets.symmetric(vertical: 10.0), - child: TextFormField( - maxLines: null, - keyboardType: TextInputType.multiline, - initialValue: widget.namespace.title, - onSaved: (name) => _name = name ?? '', - validator: (name) { - //if (name.length < 3 || name.length > 250) { - // return 'The name needs to have between 3 and 250 characters.'; - //} - return null; - }, - decoration: new InputDecoration( - labelText: 'Name', - border: OutlineInputBorder(), - ), - ), - ), - Padding( - padding: EdgeInsets.symmetric(vertical: 10.0), - child: TextFormField( - maxLines: null, - keyboardType: TextInputType.multiline, - initialValue: widget.namespace.description, - onSaved: (description) => - _description = description ?? '', - validator: (description) { - //if (description.length > 1000) { - // return 'The description can have a maximum of 1000 characters.'; - //} - return null; - }, - decoration: new InputDecoration( - labelText: 'Description', - border: OutlineInputBorder(), - ), - ), - ), - Builder( - builder: (context) => Padding( - padding: EdgeInsets.symmetric(vertical: 10.0), - child: FancyButton( - onPressed: !_loading - ? () { - if (_formKey.currentState!.validate()) { - Form.of(context)?.save(); - _saveNamespace(context); - } - } - : null, - child: _loading - ? CircularProgressIndicator() - : VikunjaButtonText('Save'), - ))), - ]), - ), - ), - ), - ); - } - - _saveNamespace(BuildContext context) async { - setState(() => _loading = true); - final updatedNamespace = widget.namespace.copyWith( - title: _name, - description: _description, - ); - - VikunjaGlobal.of(context) - .namespaceService - .update(updatedNamespace) - .then((_) { - setState(() => _loading = false); - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text('The namespace was updated successfully!'), - )); - }).catchError((err) { - setState(() => _loading = false); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text('Something went wrong: ' + err.toString()), - action: SnackBarAction( - label: 'CLOSE', - onPressed: ScaffoldMessenger.of(context).hideCurrentSnackBar), - ), - ); - }); - } -} diff --git a/lib/pages/namespace/overview.dart b/lib/pages/namespace/overview.dart deleted file mode 100644 index 1cf9086..0000000 --- a/lib/pages/namespace/overview.dart +++ /dev/null @@ -1,124 +0,0 @@ -import 'package:after_layout/after_layout.dart'; -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; - -import '../../components/AddDialog.dart'; -import '../../components/ErrorDialog.dart'; -import '../../global.dart'; -import '../../models/namespace.dart'; -import 'namespace.dart'; - -class NamespaceOverviewPage extends StatefulWidget { - @override - _NamespaceOverviewPageState createState() => - new _NamespaceOverviewPageState(); -} - -class _NamespaceOverviewPageState extends State - with AfterLayoutMixin { - List _namespaces = []; - int _selectedDrawerIndex = -2, _previousDrawerIndex = -2; - bool _loading = true; - - Namespace? get _currentNamespace => - _selectedDrawerIndex >= -1 && _selectedDrawerIndex < _namespaces.length - ? _namespaces[_selectedDrawerIndex] - : null; - - @override - void afterFirstLayout(BuildContext context) { - _loadNamespaces(); - } - - @override - Widget build(BuildContext context) { - List namespacesList = []; - _namespaces - .asMap() - .forEach((i, namespace) => namespacesList.add(new ListTile( - leading: const Icon(Icons.folder), - title: new Text(namespace.title), - selected: i == _selectedDrawerIndex, - onTap: () => _onSelectItem(i), - ))); - - if (_selectedDrawerIndex > -1) { - return new WillPopScope( - child: NamespacePage(namespace: _namespaces[_selectedDrawerIndex]), - onWillPop: () async { - setState(() { - _selectedDrawerIndex = -2; - }); - return false; - }); - } - - return Scaffold( - body: this._loading - ? Center(child: CircularProgressIndicator()) - : RefreshIndicator( - child: ListView( - padding: EdgeInsets.zero, - children: ListTile.divideTiles( - context: context, tiles: namespacesList) - .toList()), - onRefresh: _loadNamespaces, - ), - floatingActionButton: Builder( - builder: (context) => FloatingActionButton( - onPressed: () => _addNamespaceDialog(context), - child: const Icon(Icons.add))), - appBar: AppBar( - title: Text("Namespaces"), - ), - ); - } - - Future _loadNamespaces() { - return VikunjaGlobal.of(context).namespaceService.getAll().then((result) { - setState(() { - _loading = false; - if (result != null) _namespaces = result; - }); - }); - } - - _onSelectItem(int index) { - Navigator.push( - context, - MaterialPageRoute( - builder: (buildContext) => NamespacePage( - namespace: _namespaces[index], - ), - )); - //setState(() => _selectedDrawerIndex = index); - } - - _addNamespaceDialog(BuildContext context) { - showDialog( - context: context, - builder: (_) => AddDialog( - onAdd: (name) => _addNamespace(name, context), - decoration: new InputDecoration( - labelText: 'Namespace', hintText: 'eg. Personal Namespace'), - )); - } - - _addNamespace(String name, BuildContext context) { - final currentUser = VikunjaGlobal.of(context).currentUser; - if (currentUser == null) { - return; - } - - VikunjaGlobal.of(context) - .namespaceService - .create(Namespace(title: name, owner: currentUser)) - .then((_) { - _loadNamespaces(); - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text('The namespace was created successfully!'), - )); - }).catchError((error) => showDialog( - context: context, builder: (context) => ErrorDialog(error: error))); - } -} diff --git a/lib/pages/project/project_edit.dart b/lib/pages/project/project_edit.dart index 9341475..b7b8f2e 100644 --- a/lib/pages/project/project_edit.dart +++ b/lib/pages/project/project_edit.dart @@ -99,7 +99,7 @@ class _ProjectEditPageState extends State { onChanged: (value) { value ??= false; VikunjaGlobal.of(context) - .listService + .projectService .setDisplayDoneTasks(listId, value ? "1" : "0"); setState(() => displayDoneTasks = value); }, diff --git a/lib/pages/project/project_task_list.dart b/lib/pages/project/project_task_list.dart index ce27ebd..3b02b62 100644 --- a/lib/pages/project/project_task_list.dart +++ b/lib/pages/project/project_task_list.dart @@ -8,11 +8,9 @@ import 'package:vikunja_app/components/AddDialog.dart'; import 'package:vikunja_app/components/KanbanWidget.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/models/bucket.dart'; -import 'package:vikunja_app/pages/list/list_edit.dart'; -import 'package:vikunja_app/pages/list/task_edit.dart'; +import 'package:vikunja_app/pages/project/task_edit.dart'; import 'package:vikunja_app/pages/project/project_edit.dart'; import '../../components/pagestatus.dart'; diff --git a/lib/pages/list/task_edit.dart b/lib/pages/project/task_edit.dart similarity index 100% rename from lib/pages/list/task_edit.dart rename to lib/pages/project/task_edit.dart diff --git a/lib/service/mocked_services.dart b/lib/service/mocked_services.dart index f5d92a3..18f7f1d 100644 --- a/lib/service/mocked_services.dart +++ b/lib/service/mocked_services.dart @@ -82,7 +82,7 @@ class MockedNamespaceService implements NamespaceService { return create(ns); } } - +/* class MockedListService implements ListService { @override Future create(namespaceId, TaskList tl) { @@ -140,7 +140,7 @@ class MockedListService implements ListService { void setDefaultList(int? listId) { // TODO: implement setDefaultList } -} +}*/ class MockedTaskService implements TaskService { @override diff --git a/lib/service/services.dart b/lib/service/services.dart index 79e961e..fbf7e0f 100644 --- a/lib/service/services.dart +++ b/lib/service/services.dart @@ -6,7 +6,6 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:vikunja_app/api/response.dart'; import 'package:vikunja_app/models/label.dart'; import 'package:vikunja_app/models/labelTask.dart'; -import 'package:vikunja_app/models/list.dart'; import 'package:vikunja_app/models/namespace.dart'; import 'package:vikunja_app/models/task.dart'; import 'package:vikunja_app/models/user.dart'; @@ -163,7 +162,7 @@ abstract class NamespaceService { Future delete(int namespaceId); } - +/* abstract class ListService { Future?> getAll(); @@ -185,7 +184,7 @@ abstract class ListService { //void setDefaultList(int? listId); } - +*/ abstract class TaskService { Future get(int taskId);