Compare commits
9 Commits
056b2d72c9
...
85f79e4e5a
Author | SHA1 | Date |
---|---|---|
Benimautner | 85f79e4e5a | |
Benimautner | d30a3cf5f2 | |
Benimautner | 4e78b5615e | |
Benimautner | 9961447788 | |
Benimautner | 828a57a642 | |
Denys Vitali | d83114e9aa | |
Denys Vitali | 0e29b6620d | |
Denys Vitali | 1d538d6816 | |
Denys Vitali | 5ab6a59b05 |
26
.metadata
26
.metadata
|
@ -4,5 +4,27 @@
|
|||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: 3b309bda072a6b326e8aa4591a5836af600923ce
|
||||
channel: beta
|
||||
revision: "300451adae589accbece3490f4396f10bdf15e6e"
|
||||
channel: "stable"
|
||||
|
||||
project_type: app
|
||||
|
||||
# Tracks metadata for the flutter migrate command
|
||||
migration:
|
||||
platforms:
|
||||
- platform: root
|
||||
create_revision: 300451adae589accbece3490f4396f10bdf15e6e
|
||||
base_revision: 300451adae589accbece3490f4396f10bdf15e6e
|
||||
- platform: web
|
||||
create_revision: 300451adae589accbece3490f4396f10bdf15e6e
|
||||
base_revision: 300451adae589accbece3490f4396f10bdf15e6e
|
||||
|
||||
# User provided section
|
||||
|
||||
# List of Local paths (relative to this file) that should be
|
||||
# ignored by the migrate tool.
|
||||
#
|
||||
# Files that are not part of the templates will be ignored by default.
|
||||
unmanaged_files:
|
||||
- 'lib/main.dart'
|
||||
- 'ios/Runner.xcodeproj/project.pbxproj'
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Flutter",
|
||||
"request": "launch",
|
||||
"type": "dart",
|
||||
"flutterMode": "debug",
|
||||
"args": [
|
||||
"--flavor",
|
||||
"main"
|
||||
],
|
||||
}
|
||||
]
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Flutter (Chromium)",
|
||||
"type": "dart",
|
||||
"request": "launch",
|
||||
"program": "lib/main.dart",
|
||||
"args": ["-d", "chrome", "--flavor", "main"],
|
||||
"deviceId": "chrome",
|
||||
},
|
||||
{
|
||||
"name": "Flutter",
|
||||
"request": "launch",
|
||||
"type": "dart",
|
||||
"flutterMode": "debug",
|
||||
"args": ["--flavor", "main"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ if (keystorePropertiesFile.exists()) {
|
|||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 33
|
||||
compileSdkVersion 34
|
||||
|
||||
sourceSets {
|
||||
main.java.srcDirs += 'src/main/kotlin'
|
||||
|
@ -42,7 +42,7 @@ android {
|
|||
defaultConfig {
|
||||
applicationId "io.vikunja.app"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 33
|
||||
targetSdkVersion 34
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
versionName flutterVersionName
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
android:label="Vikunja"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:usesCleartextTraffic="true">
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
>
|
||||
<meta-data android:name="io.flutter.network-policy" android:resource="@xml/network_security_config"/>
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
|
@ -106,4 +108,4 @@
|
|||
</provider>
|
||||
</application>
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
</manifest>
|
||||
</manifest>
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<base-config cleartextTrafficPermitted="true">
|
||||
<trust-anchors>
|
||||
<certificates src="system" />
|
||||
<certificates src="user" />
|
||||
</trust-anchors>
|
||||
</base-config>
|
||||
</network-security-config>
|
|
@ -1,5 +1,5 @@
|
|||
buildscript {
|
||||
ext.kotlin_version = '1.7.20'
|
||||
ext.kotlin_version = '1.9.23'
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:core';
|
||||
import 'dart:io';
|
||||
import 'package:cronet_http/cronet_http.dart' as cronet_http;
|
||||
import 'package:cupertino_http/cupertino_http.dart' as cupertino_http;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:http/io_client.dart' as io_client;
|
||||
import 'package:vikunja_app/api/response.dart';
|
||||
import 'package:vikunja_app/components/string_extension.dart';
|
||||
import 'package:vikunja_app/global.dart';
|
||||
|
@ -25,16 +27,42 @@ class Client {
|
|||
|
||||
String? post_body;
|
||||
|
||||
bool operator ==(dynamic otherClient) {
|
||||
@override
|
||||
bool operator ==(Object otherClient) {
|
||||
if (otherClient is! Client) return false;
|
||||
return otherClient._token == _token;
|
||||
}
|
||||
|
||||
Client(this.global_scaffold_key,
|
||||
{String? token, String? base, bool authenticated = false}) {
|
||||
configure(token: token, base: base, authenticated: authenticated);
|
||||
Client(
|
||||
this.global_scaffold_key, {
|
||||
String? token,
|
||||
String? base,
|
||||
bool authenticated = false,
|
||||
}) {
|
||||
configure(
|
||||
token: token,
|
||||
base: base,
|
||||
authenticated: authenticated,
|
||||
);
|
||||
}
|
||||
|
||||
void reload_ignore_certs(bool? val) {
|
||||
http.Client get httpClient {
|
||||
if (Platform.isAndroid) {
|
||||
final engine = cronet_http.CronetEngine.build(
|
||||
cacheMode: cronet_http.CacheMode.memory, cacheMaxSize: 1000000);
|
||||
return cronet_http.CronetClient.fromCronetEngine(engine);
|
||||
}
|
||||
if (Platform.isIOS || Platform.isMacOS) {
|
||||
final config =
|
||||
cupertino_http.URLSessionConfiguration.ephemeralSessionConfiguration()
|
||||
..cache =
|
||||
cupertino_http.URLCache.withCapacity(memoryCapacity: 1000000);
|
||||
return cupertino_http.CupertinoClient.fromSessionConfiguration(config);
|
||||
}
|
||||
return io_client.IOClient();
|
||||
}
|
||||
|
||||
void reloadIgnoreCerts(bool? val) {
|
||||
ignoreCertificates = val ?? false;
|
||||
HttpOverrides.global = new IgnoreCertHttpOverrides(ignoreCertificates);
|
||||
if (global_scaffold_key == null ||
|
||||
|
@ -47,7 +75,7 @@ class Client {
|
|||
get _headers => {
|
||||
'Authorization': _token != '' ? 'Bearer $_token' : '',
|
||||
'Content-Type': 'application/json',
|
||||
'User-Agent': 'Vikunja Mobile App'
|
||||
'User-Agent': 'Vikunja Mobile App',
|
||||
};
|
||||
|
||||
get headers => _headers;
|
||||
|
@ -55,7 +83,11 @@ class Client {
|
|||
@override
|
||||
int get hashCode => _token.hashCode;
|
||||
|
||||
void configure({String? token, String? base, bool? authenticated}) {
|
||||
void configure({
|
||||
String? token,
|
||||
String? base,
|
||||
bool? authenticated,
|
||||
}) {
|
||||
if (token != null) _token = token;
|
||||
if (base != null) {
|
||||
base = base.replaceAll(" ", "");
|
||||
|
@ -66,7 +98,6 @@ class Client {
|
|||
}
|
||||
|
||||
void reset() {
|
||||
_token = _base = '';
|
||||
authenticated = false;
|
||||
}
|
||||
|
||||
|
@ -85,14 +116,14 @@ class Client {
|
|||
queryParameters: queryParameters,
|
||||
fragment: uri.fragment);
|
||||
|
||||
return http
|
||||
return httpClient
|
||||
.get(uri, headers: _headers)
|
||||
.then(_handleResponse)
|
||||
.onError((error, stackTrace) => _handleError(error, stackTrace));
|
||||
}
|
||||
|
||||
Future<Response?> delete(String url) {
|
||||
return http
|
||||
return httpClient
|
||||
.delete(
|
||||
'${this.base}$url'.toUri()!,
|
||||
headers: _headers,
|
||||
|
@ -102,7 +133,7 @@ class Client {
|
|||
}
|
||||
|
||||
Future<Response?> post(String url, {dynamic body}) {
|
||||
return http
|
||||
return httpClient
|
||||
.post(
|
||||
'${this.base}$url'.toUri()!,
|
||||
headers: _headers,
|
||||
|
@ -113,7 +144,7 @@ class Client {
|
|||
}
|
||||
|
||||
Future<Response?> put(String url, {dynamic body}) {
|
||||
return http
|
||||
return httpClient
|
||||
.put(
|
||||
'${this.base}$url'.toUri()!,
|
||||
headers: _headers,
|
||||
|
@ -183,7 +214,7 @@ class Client {
|
|||
}
|
||||
|
||||
Response? _handleResponse(http.Response response) {
|
||||
Error? error = _handleResponseErrors(response);
|
||||
_handleResponseErrors(response);
|
||||
return Response(
|
||||
_decoder.convert(response.body), response.statusCode, response.headers);
|
||||
}
|
||||
|
|
|
@ -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<TaskList?> 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<TaskList?> 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<List<TaskList>?> 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<List<TaskList>?> 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<TaskList?> 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<String> 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<String?> getDefaultList() {
|
||||
return _storage.read(key: "default_list_id");
|
||||
}
|
||||
|
||||
@override
|
||||
void setDefaultList(int? listId) {
|
||||
_storage.write(key: "default_list_id", value: listId.toString());
|
||||
}
|
||||
}
|
|
@ -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<Namespace?> 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<Namespace?> get(int namespaceId) {
|
||||
return client.get('/namespaces/$namespaceId').then((response) {
|
||||
if (response == null) return null;
|
||||
return Namespace.fromJson(response.body);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<Namespace>?> getAll() {
|
||||
return client.get('/namespaces').then((response) {
|
||||
if (response == null) return null;
|
||||
return convertList(response.body, (result) => Namespace.fromJson(result));
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Namespace?> update(Namespace ns) {
|
||||
return client
|
||||
.post('/namespaces/${ns.id}', body: ns.toJSON())
|
||||
.then((response) {
|
||||
if (response == null) return null;
|
||||
return Namespace.fromJson(response.body);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'dart:developer' as dev;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:vikunja_app/api/bucket_implementation.dart';
|
||||
|
@ -7,8 +8,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 +64,12 @@ class VikunjaGlobalState extends State<VikunjaGlobal> {
|
|||
|
||||
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;
|
||||
|
@ -89,6 +84,9 @@ class VikunjaGlobalState extends State<VikunjaGlobal> {
|
|||
late String currentTimeZone;
|
||||
|
||||
void updateWorkmanagerDuration() {
|
||||
if (kIsWeb) {
|
||||
return;
|
||||
}
|
||||
Workmanager().cancelAll().then((value) {
|
||||
settingsManager.getWorkmanagerDuration().then((duration) {
|
||||
if (duration.inMinutes > 0) {
|
||||
|
@ -116,7 +114,7 @@ class VikunjaGlobalState extends State<VikunjaGlobal> {
|
|||
_client = Client(snackbarKey);
|
||||
settingsManager
|
||||
.getIgnoreCertificates()
|
||||
.then((value) => client.reload_ignore_certs(value == "1"));
|
||||
.then((value) => client.reloadIgnoreCerts(value == "1"));
|
||||
_newUserService = UserAPIService(client);
|
||||
_loadCurrentUser();
|
||||
tz.initializeTimeZones();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:dynamic_color/dynamic_color.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
@ -34,6 +35,9 @@ class IgnoreCertHttpOverrides extends HttpOverrides {
|
|||
|
||||
@pragma('vm:entry-point')
|
||||
void callbackDispatcher() {
|
||||
if (kIsWeb) {
|
||||
return;
|
||||
}
|
||||
Workmanager().executeTask((task, inputData) async {
|
||||
print(
|
||||
"Native called background task: $task"); //simpleTask will be emitted here.
|
||||
|
@ -48,7 +52,7 @@ void callbackDispatcher() {
|
|||
.getIgnoreCertificates()
|
||||
.then((value) async {
|
||||
print("ignoring: $value");
|
||||
client.reload_ignore_certs(value == "1");
|
||||
client.reloadIgnoreCerts(value == "1");
|
||||
|
||||
TaskAPIService taskService = TaskAPIService(client);
|
||||
NotificationClass nc = NotificationClass();
|
||||
|
@ -95,18 +99,31 @@ void main() async {
|
|||
Permission.notification.request();
|
||||
}
|
||||
});
|
||||
await FlutterDownloader.initialize();
|
||||
Workmanager().initialize(callbackDispatcher, isInDebugMode: false);
|
||||
try {
|
||||
if (!kIsWeb) {
|
||||
await FlutterDownloader.initialize();
|
||||
}
|
||||
} catch (e) {
|
||||
print("Failed to initialize downloader: $e");
|
||||
}
|
||||
try {
|
||||
if (!kIsWeb) {
|
||||
Workmanager().initialize(callbackDispatcher, isInDebugMode: false);
|
||||
}
|
||||
} catch (e) {
|
||||
print("Failed to initialize workmanager: $e");
|
||||
}
|
||||
runApp(VikunjaGlobal(
|
||||
child: new VikunjaApp(
|
||||
home: HomePage(),
|
||||
key: UniqueKey(),
|
||||
navkey: globalNavigatorKey,
|
||||
),
|
||||
login: new VikunjaApp(
|
||||
home: LoginPage(),
|
||||
key: UniqueKey(),
|
||||
)));
|
||||
child: new VikunjaApp(
|
||||
home: HomePage(),
|
||||
key: UniqueKey(),
|
||||
navkey: globalNavigatorKey,
|
||||
),
|
||||
login: new VikunjaApp(
|
||||
home: LoginPage(),
|
||||
key: UniqueKey(),
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
final ValueNotifier<bool> updateTheme = ValueNotifier(false);
|
||||
|
@ -118,38 +135,41 @@ class VikunjaApp extends StatelessWidget {
|
|||
const VikunjaApp({Key? key, required this.home, this.navkey})
|
||||
: super(key: key);
|
||||
|
||||
Future<ThemeData> getThemedata() async {
|
||||
FlutterThemeMode themeMode = FlutterThemeMode.light;
|
||||
try {
|
||||
SettingsManager manager = SettingsManager(new FlutterSecureStorage());
|
||||
themeMode = await manager.getThemeMode();
|
||||
} catch (e) {
|
||||
print("Failed to get theme mode: $e");
|
||||
}
|
||||
switch (themeMode) {
|
||||
case FlutterThemeMode.dark:
|
||||
return buildVikunjaDarkTheme();
|
||||
case FlutterThemeMode.materialYouLight:
|
||||
return buildVikunjaMaterialLightTheme();
|
||||
case FlutterThemeMode.materialYouDark:
|
||||
return buildVikunjaMaterialDarkTheme();
|
||||
default:
|
||||
return buildVikunjaTheme();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
SettingsManager manager = SettingsManager(new FlutterSecureStorage());
|
||||
|
||||
return new ValueListenableBuilder(
|
||||
valueListenable: updateTheme,
|
||||
builder: (_, mode, __) {
|
||||
updateTheme.value = false;
|
||||
FlutterThemeMode themeMode = FlutterThemeMode.system;
|
||||
Future<ThemeData> theme = manager.getThemeMode().then((value) {
|
||||
themeMode = value;
|
||||
switch (value) {
|
||||
case FlutterThemeMode.dark:
|
||||
return buildVikunjaDarkTheme();
|
||||
case FlutterThemeMode.materialYouLight:
|
||||
return buildVikunjaMaterialLightTheme();
|
||||
case FlutterThemeMode.materialYouDark:
|
||||
return buildVikunjaMaterialDarkTheme();
|
||||
default:
|
||||
return buildVikunjaTheme();
|
||||
}
|
||||
});
|
||||
return FutureBuilder<ThemeData>(
|
||||
future: theme,
|
||||
future: getThemedata(),
|
||||
builder: (BuildContext context, AsyncSnapshot<ThemeData> data) {
|
||||
if (data.hasData) {
|
||||
return new DynamicColorBuilder(
|
||||
builder: (lightTheme, darkTheme) {
|
||||
ThemeData? themeData = data.data;
|
||||
if (themeMode == FlutterThemeMode.materialYouLight)
|
||||
if (data.data == FlutterThemeMode.materialYouLight)
|
||||
themeData = themeData?.copyWith(colorScheme: lightTheme);
|
||||
else if (themeMode == FlutterThemeMode.materialYouDark)
|
||||
else if (data.data == FlutterThemeMode.materialYouDark)
|
||||
themeData = themeData?.copyWith(colorScheme: darkTheme);
|
||||
return MaterialApp(
|
||||
title: 'Vikunja',
|
||||
|
|
|
@ -33,7 +33,7 @@ class NotificationClass {
|
|||
channelDescription: "description",
|
||||
icon: 'vikunja_notification_logo',
|
||||
importance: notifs.Importance.high);
|
||||
late notifs.IOSNotificationDetails iOSSpecifics;
|
||||
late notifs.DarwinNotificationDetails iOSSpecifics;
|
||||
late notifs.NotificationDetails platformChannelSpecificsDueDate;
|
||||
late notifs.NotificationDetails platformChannelSpecificsReminders;
|
||||
|
||||
|
@ -48,7 +48,7 @@ class NotificationClass {
|
|||
Future<void> _initNotifications() async {
|
||||
var initializationSettingsAndroid =
|
||||
notifs.AndroidInitializationSettings('vikunja_logo');
|
||||
var initializationSettingsIOS = notifs.IOSInitializationSettings(
|
||||
var initializationSettingsIOS = notifs.DarwinInitializationSettings(
|
||||
requestAlertPermission: false,
|
||||
requestBadgePermission: false,
|
||||
requestSoundPermission: false,
|
||||
|
@ -60,17 +60,18 @@ class NotificationClass {
|
|||
var initializationSettings = notifs.InitializationSettings(
|
||||
android: initializationSettingsAndroid, iOS: initializationSettingsIOS);
|
||||
await notificationsPlugin.initialize(initializationSettings,
|
||||
onSelectNotification: (String? payload) async {
|
||||
onDidReceiveNotificationResponse:
|
||||
(notifs.NotificationResponse resp) async {
|
||||
if (payload != null) {
|
||||
print('notification payload: ' + payload);
|
||||
selectNotificationSubject.add(payload);
|
||||
print('notification payload: ' + resp.payload!);
|
||||
selectNotificationSubject.add(resp.payload!);
|
||||
}
|
||||
});
|
||||
print("Notifications initialised successfully");
|
||||
}
|
||||
|
||||
Future<void> notificationInitializer() async {
|
||||
iOSSpecifics = notifs.IOSNotificationDetails();
|
||||
iOSSpecifics = notifs.DarwinNotificationDetails();
|
||||
platformChannelSpecificsDueDate = notifs.NotificationDetails(
|
||||
android: androidSpecificsDueDate, iOS: iOSSpecifics);
|
||||
platformChannelSpecificsReminders = notifs.NotificationDetails(
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
import 'package:vikunja_app/models/task.dart';
|
||||
import 'package:vikunja_app/models/user.dart';
|
||||
|
||||
class TaskList {
|
||||
final int id;
|
||||
int namespaceId;
|
||||
String title, description;
|
||||
final User owner;
|
||||
final DateTime created, updated;
|
||||
final List<Task> tasks;
|
||||
final bool isFavorite;
|
||||
|
||||
TaskList({
|
||||
this.id = 0,
|
||||
required this.title,
|
||||
required this.namespaceId,
|
||||
this.description = '',
|
||||
required this.owner,
|
||||
DateTime? created,
|
||||
DateTime? updated,
|
||||
List<Task>? tasks,
|
||||
this.isFavorite = false,
|
||||
}) : this.created = created ?? DateTime.now(),
|
||||
this.updated = updated ?? DateTime.now(),
|
||||
this.tasks = tasks ?? [];
|
||||
|
||||
TaskList.fromJson(Map<String, dynamic> json)
|
||||
: id = json['id'],
|
||||
owner = User.fromJson(json['owner']),
|
||||
description = json['description'],
|
||||
title = json['title'],
|
||||
updated = DateTime.parse(json['updated']),
|
||||
created = DateTime.parse(json['created']),
|
||||
isFavorite = json['is_favorite'],
|
||||
namespaceId = json['namespace_id'],
|
||||
tasks = json['tasks'] == null
|
||||
? []
|
||||
: (json['tasks'] as List<dynamic>)
|
||||
.map((taskJson) => Task.fromJson(taskJson))
|
||||
.toList();
|
||||
|
||||
toJSON() {
|
||||
return {
|
||||
'id': id,
|
||||
'title': title,
|
||||
'description': description,
|
||||
'owner': owner.toJSON(),
|
||||
'created': created.toUtc().toIso8601String(),
|
||||
'updated': updated.toUtc().toIso8601String(),
|
||||
'namespace_id': namespaceId
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
import 'package:vikunja_app/models/user.dart';
|
||||
|
||||
class Namespace {
|
||||
final int id;
|
||||
final DateTime created, updated;
|
||||
final String title, description;
|
||||
final User? owner;
|
||||
|
||||
Namespace({
|
||||
this.id = 0,
|
||||
DateTime? created,
|
||||
DateTime? updated,
|
||||
required this.title,
|
||||
this.description = '',
|
||||
required this.owner,
|
||||
}) : this.created = created ?? DateTime.now(),
|
||||
this.updated = updated ?? DateTime.now();
|
||||
|
||||
Namespace.fromJson(Map<String, dynamic> json)
|
||||
: title = json['title'],
|
||||
description = json['description'],
|
||||
id = json['id'],
|
||||
created = DateTime.parse(json['created']),
|
||||
updated = DateTime.parse(json['updated']),
|
||||
owner = json['owner'] != null ? User.fromJson(json['owner']) : null;
|
||||
|
||||
Map<String, dynamic> toJSON() => {
|
||||
'id': id,
|
||||
'created': created.toUtc().toIso8601String(),
|
||||
'updated': updated.toUtc().toIso8601String(),
|
||||
'title': title,
|
||||
'owner': owner?.toJSON(),
|
||||
'description': description
|
||||
};
|
||||
|
||||
Namespace copyWith({
|
||||
int? id,
|
||||
DateTime? created,
|
||||
DateTime? updated,
|
||||
String? title,
|
||||
String? description,
|
||||
User? owner,
|
||||
}) {
|
||||
return Namespace(
|
||||
id: id ?? this.id,
|
||||
created: created ?? this.created,
|
||||
updated: updated ?? this.updated,
|
||||
title: title ?? this.title,
|
||||
description: description ?? this.description,
|
||||
owner: owner ?? this.owner,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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<ListPage> {
|
||||
final _keyboardController = KeyboardVisibilityController();
|
||||
int _viewIndex = 0;
|
||||
late TaskList _list;
|
||||
List<Task> _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<ListProvider>(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: <Widget>[
|
||||
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>[
|
||||
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<ListProvider>(context, listen: false).updateTask(
|
||||
context: context,
|
||||
task: task.copyWith(done: done),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> 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<void> _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<void> _loadTasksForPage(int page) {
|
||||
return Provider.of<ListProvider>(context, listen: false).loadTasks(
|
||||
context: context,
|
||||
listId: _list.id,
|
||||
page: page,
|
||||
displayDoneTasks: displayDoneTasks);
|
||||
}
|
||||
|
||||
Future<void> _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<void> _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<ListProvider>(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);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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<StatefulWidget> createState() => _ListEditPageState();
|
||||
}
|
||||
|
||||
class _ListEditPageState extends State<ListEditPage> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
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: <Widget>[
|
||||
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<String> matches = <String>[];
|
||||
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),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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<NamespacePage> {
|
||||
List<TaskList> _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: <Widget>[
|
||||
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<void> _removeList(TaskList list) {
|
||||
return VikunjaGlobal.of(context)
|
||||
.listService
|
||||
.delete(list.id)
|
||||
.then((_) => _loadLists());
|
||||
}
|
||||
|
||||
Future<void> _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<ListProvider>(
|
||||
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!'),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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<StatefulWidget> createState() => _NamespaceEditPageState();
|
||||
}
|
||||
|
||||
class _NamespaceEditPageState extends State<NamespaceEditPage> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
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: <Widget>[
|
||||
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),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -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<NamespaceOverviewPage>
|
||||
with AfterLayoutMixin<NamespaceOverviewPage> {
|
||||
List<Namespace> _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<Widget> namespacesList = <Widget>[];
|
||||
_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<void> _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)));
|
||||
}
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
import 'dart:ffi';
|
||||
import 'dart:developer';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:vikunja_app/global.dart';
|
||||
|
@ -99,7 +98,7 @@ class _ProjectEditPageState extends State<ProjectEditPage> {
|
|||
onChanged: (value) {
|
||||
value ??= false;
|
||||
VikunjaGlobal.of(context)
|
||||
.listService
|
||||
.projectService
|
||||
.setDisplayDoneTasks(listId, value ? "1" : "0");
|
||||
setState(() => displayDoneTasks = value);
|
||||
},
|
||||
|
|
|
@ -8,12 +8,10 @@ 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/project_edit.dart';
|
||||
import 'package:vikunja_app/pages/project/task_edit.dart';
|
||||
|
||||
import '../../components/pagestatus.dart';
|
||||
import '../../models/project.dart';
|
||||
|
|
|
@ -2,7 +2,6 @@ import 'package:flutter/cupertino.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:vikunja_app/global.dart';
|
||||
import 'package:vikunja_app/models/list.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
|
||||
import '../main.dart';
|
||||
|
@ -173,7 +172,7 @@ class SettingsPageState extends State<SettingsPage> {
|
|||
value: ignoreCertificates,
|
||||
onChanged: (value) {
|
||||
setState(() => ignoreCertificates = value);
|
||||
VikunjaGlobal.of(context).client.reload_ignore_certs(value);
|
||||
VikunjaGlobal.of(context).client.reloadIgnoreCerts(value);
|
||||
})
|
||||
: ListTile(title: Text("...")),
|
||||
Divider(),
|
||||
|
|
|
@ -264,7 +264,7 @@ class _LoginPageState extends State<LoginPage> {
|
|||
value: client.ignoreCertificates,
|
||||
onChanged: (value) {
|
||||
setState(
|
||||
() => client.reload_ignore_certs(value ?? false));
|
||||
() => client.reloadIgnoreCerts(value ?? false));
|
||||
VikunjaGlobal.of(context)
|
||||
.settingsManager
|
||||
.setIgnoreCertificates(value ?? false);
|
||||
|
|
|
@ -1,202 +1,11 @@
|
|||
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';
|
||||
import 'package:vikunja_app/models/user.dart';
|
||||
import 'package:vikunja_app/service/services.dart';
|
||||
|
||||
// Data for mocked services
|
||||
var _users = {1: User(id: 1, username: 'test1')};
|
||||
|
||||
var _namespaces = {
|
||||
1: Namespace(
|
||||
id: 1,
|
||||
title: 'Test 1',
|
||||
created: DateTime.now(),
|
||||
updated: DateTime.now(),
|
||||
description: 'A namespace for testing purposes',
|
||||
owner: _users[1]!,
|
||||
)
|
||||
};
|
||||
|
||||
var _nsLists = {
|
||||
1: [1]
|
||||
};
|
||||
|
||||
var _lists = {
|
||||
1: TaskList(
|
||||
id: 1,
|
||||
title: 'List 1',
|
||||
tasks: _tasks.values.toList(),
|
||||
owner: _users[1]!,
|
||||
description: 'A nice list',
|
||||
created: DateTime.now(),
|
||||
updated: DateTime.now(),
|
||||
namespaceId: 1)
|
||||
};
|
||||
|
||||
var _tasks = {
|
||||
1: Task(
|
||||
id: 1,
|
||||
title: 'Task 1',
|
||||
createdBy: _users[1]!,
|
||||
updated: DateTime.now(),
|
||||
created: DateTime.now(),
|
||||
description: 'A descriptive task',
|
||||
done: false,
|
||||
projectId: 1,
|
||||
)
|
||||
};
|
||||
|
||||
// Mocked services
|
||||
|
||||
class MockedNamespaceService implements NamespaceService {
|
||||
@override
|
||||
Future<Namespace> create(Namespace ns) {
|
||||
_namespaces[ns.id] = ns;
|
||||
return Future.value(ns);
|
||||
}
|
||||
|
||||
@override
|
||||
Future delete(int namespaceId) {
|
||||
_namespaces.remove(namespaceId);
|
||||
return Future.value();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Namespace> get(int namespaceId) {
|
||||
return Future.value(_namespaces[namespaceId]);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<Namespace>> getAll() {
|
||||
return Future.value(_namespaces.values.toList());
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Namespace> update(Namespace ns) {
|
||||
if (!_namespaces.containsKey(ns.id))
|
||||
throw Exception('Namespace ${ns.id} does not exsists');
|
||||
return create(ns);
|
||||
}
|
||||
}
|
||||
|
||||
class MockedListService implements ListService {
|
||||
@override
|
||||
Future<TaskList> create(namespaceId, TaskList tl) {
|
||||
_nsLists[namespaceId]?.add(tl.id);
|
||||
return Future.value(_lists[tl.id] = tl);
|
||||
}
|
||||
|
||||
@override
|
||||
Future delete(int listId) {
|
||||
_lists.remove(listId);
|
||||
return Future.value();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<TaskList> get(int listId) {
|
||||
return Future.value(_lists[listId]);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<TaskList>> getAll() {
|
||||
return Future.value(_lists.values.toList());
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<TaskList>> getByNamespace(int namespaceId) {
|
||||
return Future.value(
|
||||
_nsLists[namespaceId]!.map((listId) => _lists[listId]!).toList());
|
||||
}
|
||||
|
||||
@override
|
||||
Future<TaskList> update(TaskList tl) {
|
||||
if (!_lists.containsKey(tl))
|
||||
throw Exception('TaskList ${tl.id} does not exists');
|
||||
return Future.value(_lists[tl.id] = tl);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> getDisplayDoneTasks(int listId) {
|
||||
// TODO: implement getDisplayDoneTasks
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
void setDisplayDoneTasks(int listId, String value) {
|
||||
// TODO: implement setDisplayDoneTasks
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> getDefaultList() {
|
||||
// TODO: implement getDefaultList
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
void setDefaultList(int? listId) {
|
||||
// TODO: implement setDefaultList
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
return Future.value(_tasks[task.id] = task);
|
||||
}
|
||||
|
||||
@override
|
||||
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
|
||||
int get maxPages => 1;
|
||||
Future<Task> get(int taskId) {
|
||||
// TODO: implement get
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<Task>> getByOptions(TaskServiceOptions options) {
|
||||
// TODO: implement getByOptions
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<Task>> getAll() {
|
||||
// TODO: implement getAll
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Response?> getAllByProject(int projectId,
|
||||
[Map<String, List<String>>? queryParameters]) {
|
||||
// TODO: implement getAllByProject
|
||||
return Future.value(new Response(_tasks.values.toList(), 200, {}));
|
||||
}
|
||||
}
|
||||
|
||||
class MockedUserService implements UserService {
|
||||
@override
|
||||
Future<UserTokenPair> login(String username, password,
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
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';
|
||||
import 'package:vikunja_app/models/bucket.dart';
|
||||
|
@ -152,40 +149,6 @@ abstract class ProjectService {
|
|||
//void setDefaultList(int? listId);
|
||||
}
|
||||
|
||||
abstract class NamespaceService {
|
||||
Future<List<Namespace>?> getAll();
|
||||
|
||||
Future<Namespace?> get(int namespaceId);
|
||||
|
||||
Future<Namespace?> create(Namespace ns);
|
||||
|
||||
Future<Namespace?> update(Namespace ns);
|
||||
|
||||
Future delete(int namespaceId);
|
||||
}
|
||||
|
||||
abstract class ListService {
|
||||
Future<List<TaskList>?> getAll();
|
||||
|
||||
Future<TaskList?> get(int listId);
|
||||
|
||||
Future<List<TaskList>?> getByNamespace(int namespaceId);
|
||||
|
||||
Future<TaskList?> create(int namespaceId, TaskList tl);
|
||||
|
||||
Future<TaskList?> update(TaskList tl);
|
||||
|
||||
Future delete(int listId);
|
||||
|
||||
Future<String?> getDisplayDoneTasks(int listId);
|
||||
|
||||
void setDisplayDoneTasks(int listId, String value);
|
||||
|
||||
Future<String?> getDefaultList();
|
||||
|
||||
//void setDefaultList(int? listId);
|
||||
}
|
||||
|
||||
abstract class TaskService {
|
||||
Future<Task?> get(int taskId);
|
||||
|
||||
|
@ -324,10 +287,10 @@ class SettingsManager {
|
|||
key: "workmanager-duration", value: duration.inMinutes.toString());
|
||||
}
|
||||
|
||||
Future<List<String>?> getPastServers() {
|
||||
return _storage
|
||||
.read(key: "recent-servers")
|
||||
.then((value) => (jsonDecode(value!) as List<dynamic>).cast<String>());
|
||||
Future<List<String>?> getPastServers() async {
|
||||
String jsonString = await _storage.read(key: "recent-servers") ?? "[]";
|
||||
List<dynamic> server = jsonDecode(jsonString);
|
||||
return server.map((e) => e as String).toList();
|
||||
}
|
||||
|
||||
Future<void> setPastServers(List<String>? server) {
|
||||
|
|
366
pubspec.lock
366
pubspec.lock
|
@ -5,10 +5,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: _fe_analyzer_shared
|
||||
sha256: eb376e9acf6938204f90eb3b1f00b578640d3188b4c8a8ec054f9f479af8d051
|
||||
sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "64.0.0"
|
||||
version: "67.0.0"
|
||||
after_layout:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -21,10 +21,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: analyzer
|
||||
sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893"
|
||||
sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.2.0"
|
||||
version: "6.4.1"
|
||||
archive:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -122,21 +122,21 @@ packages:
|
|||
source: hosted
|
||||
version: "2.0.3"
|
||||
chewie:
|
||||
dependency: "direct main"
|
||||
dependency: transitive
|
||||
description:
|
||||
name: chewie
|
||||
sha256: "745e81e84c6d7f3835f89f85bb49771c0a66099e4caf8f8e9e9a372bc66fb2c1"
|
||||
sha256: "8bc4ac4cf3f316e50a25958c0f5eb9bb12cf7e8308bb1d74a43b230da2cfc144"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.0"
|
||||
version: "1.7.5"
|
||||
cli_util:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cli_util
|
||||
sha256: "66f86e916d285c1a93d3b79587d94bd71984a66aac4ff74e524cfa7877f1395c"
|
||||
sha256: c05b7406fdabc7a49a3929d4af76bcaccbbffcbcdcf185b082e1ae07da323d19
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.5"
|
||||
version: "0.4.1"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -146,7 +146,7 @@ packages:
|
|||
source: hosted
|
||||
version: "1.1.1"
|
||||
collection:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: collection
|
||||
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
|
||||
|
@ -169,6 +169,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.7.2"
|
||||
cronet_http:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: cronet_http
|
||||
sha256: "9b9f00ae48971bc8a8cbdd4528bd35511adce00fb79d1ebf9f9907667056640f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -185,6 +193,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
cupertino_http:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: cupertino_http
|
||||
sha256: "20c167fd843c9ff6fc25cc4a0e8efa4180dfe119fb6d18c3c55104113e9cfc6f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
cupertino_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -197,10 +213,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: dart_style
|
||||
sha256: "40ae61a5d43feea6d24bd22c0537a6629db858963b99b4bc1c3db80676f32368"
|
||||
sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.4"
|
||||
version: "2.3.6"
|
||||
datetime_picker_formfield:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -229,10 +245,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: dynamic_color
|
||||
sha256: a866f1f8947bfdaf674d7928e769eac7230388a2e7a2542824fad4bb5b87be3b
|
||||
sha256: eae98052fa6e2826bdac3dd2e921c6ce2903be15c6b7f8b6d8a5d49b5086298d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.6.9"
|
||||
version: "1.7.0"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -245,18 +261,18 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: ffi
|
||||
sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
|
||||
sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
version: "2.1.2"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
|
||||
sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.4"
|
||||
version: "7.0.0"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -298,10 +314,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_keyboard_visibility
|
||||
sha256: "183ef857869a790aaff0219327a31783017fcc54b895fcdda1909645bb6ab965"
|
||||
sha256: "98664be7be0e3ffca00de50f7f6a287ab62c763fc8c762e0a21584584a3ff4f8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.4.2"
|
||||
version: "6.0.0"
|
||||
flutter_keyboard_visibility_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -346,42 +362,42 @@ packages:
|
|||
dependency: "direct dev"
|
||||
description:
|
||||
name: flutter_launcher_icons
|
||||
sha256: a9de6706cd844668beac27c0aed5910fa0534832b3c2cad61a5fd977fce82a5d
|
||||
sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.10.0"
|
||||
version: "0.13.1"
|
||||
flutter_local_notifications:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_local_notifications
|
||||
sha256: "57d0012730780fe137260dd180e072c18a73fbeeb924cdc029c18aaa0f338d64"
|
||||
sha256: f9a05409385b77b06c18f200a41c7c2711ebf7415669350bb0f8474c07bd40d1
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.9.1"
|
||||
version: "17.0.0"
|
||||
flutter_local_notifications_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_local_notifications_linux
|
||||
sha256: b472bfc173791b59ede323661eae20f7fff0b6908fea33dd720a6ef5d576bae8
|
||||
sha256: "33f741ef47b5f63cc7f78fe75eeeac7e19f171ff3c3df054d84c1e38bedb6a03"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.1"
|
||||
version: "4.0.0+1"
|
||||
flutter_local_notifications_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_local_notifications_platform_interface
|
||||
sha256: "21bceee103a66a53b30ea9daf677f990e5b9e89b62f222e60dd241cd08d63d3a"
|
||||
sha256: "7cf643d6d5022f3baed0be777b0662cce5919c0a7b86e700299f22dc4ae660ef"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.0"
|
||||
version: "7.0.0+1"
|
||||
flutter_secure_storage:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_secure_storage
|
||||
sha256: "22dbf16f23a4bcf9d35e51be1c84ad5bb6f627750565edd70dab70f3ff5fff8f"
|
||||
sha256: ffdbb60130e4665d2af814a0267c481bcf522c41ae2e43caf69fa0146876d685
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.1.0"
|
||||
version: "9.0.0"
|
||||
flutter_secure_storage_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -418,18 +434,18 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: flutter_secure_storage_windows
|
||||
sha256: "38f9501c7cb6f38961ef0e1eacacee2b2d4715c63cc83fe56449c4d3d0b47255"
|
||||
sha256: "5809c66f9dd3b4b93b0a6e2e8561539405322ee767ac2f64d084e2ab5429d108"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "3.0.0"
|
||||
flutter_svg:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_svg
|
||||
sha256: d39e7f95621fc84376bc0f7d504f05c3a41488c562f4a8ad410569127507402c
|
||||
sha256: "7b4ca6cf3304575fe9c8ec64813c8d02ee41d2afe60bcfe0678bcb5375d596a2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.9"
|
||||
version: "2.0.10+1"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
|
@ -447,10 +463,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_typeahead
|
||||
sha256: "1f6b248bb4f3ebb4cf1ee0354aa23c77be457fb2d26d6847ecc33a917f65e58e"
|
||||
sha256: d64712c65db240b1057559b952398ebb6e498077baeebf9b0731dade62438a6d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.1"
|
||||
version: "5.2.0"
|
||||
flutter_web_plugins:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
|
@ -548,10 +564,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: http
|
||||
sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2"
|
||||
sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.13.6"
|
||||
version: "1.2.1"
|
||||
http_multi_server:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -572,18 +588,18 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: image
|
||||
sha256: "8e9d133755c3e84c73288363e6343157c383a0c6c56fc51afcc5d4d7180306d6"
|
||||
sha256: "4c68bfd5ae83e700b5204c1e74451e7bf3cf750e6843c6e158289cf56bda018e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.3.0"
|
||||
version: "4.1.7"
|
||||
intl:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: intl
|
||||
sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91"
|
||||
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.17.0"
|
||||
version: "0.19.0"
|
||||
io:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -592,6 +608,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
jni:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: jni
|
||||
sha256: "499558e919997adfc45809a66caf0b95b91393e23289dd2826b152f8f04e6611"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.3"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -601,7 +625,7 @@ packages:
|
|||
source: hosted
|
||||
version: "0.6.7"
|
||||
json_annotation:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: json_annotation
|
||||
sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467
|
||||
|
@ -640,6 +664,30 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.4.9"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker
|
||||
sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.0.0"
|
||||
leak_tracker_flutter_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_flutter_testing
|
||||
sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
leak_tracker_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_testing
|
||||
sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -652,26 +700,26 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
|
||||
sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.16"
|
||||
version: "0.12.16+1"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
|
||||
sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.0"
|
||||
version: "0.8.0"
|
||||
meta:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: meta
|
||||
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
|
||||
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
version: "1.11.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -716,10 +764,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: package_info_plus
|
||||
sha256: "10259b111176fba5c505b102e3a5b022b51dd97e30522e906d6922c745584745"
|
||||
sha256: "7e76fad405b3e4016cd39d08f455a4eb5199723cf594cd1b8916d47140d93017"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
version: "4.2.0"
|
||||
package_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -732,10 +780,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: path
|
||||
sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
|
||||
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.8.3"
|
||||
version: "1.9.0"
|
||||
path_drawing:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -804,50 +852,58 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: permission_handler
|
||||
sha256: bc56bfe9d3f44c3c612d8d393bd9b174eb796d706759f9b495ac254e4294baa5
|
||||
sha256: "74e962b7fad7ff75959161bb2c0ad8fe7f2568ee82621c9c2660b751146bfe44"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.4.5"
|
||||
version: "11.3.0"
|
||||
permission_handler_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_android
|
||||
sha256: "59c6322171c29df93a22d150ad95f3aa19ed86542eaec409ab2691b8f35f9a47"
|
||||
sha256: "1acac6bae58144b442f11e66621c062aead9c99841093c38f5bcdcc24c1c3474"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.3.6"
|
||||
version: "12.0.5"
|
||||
permission_handler_apple:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_apple
|
||||
sha256: "99e220bce3f8877c78e4ace901082fb29fa1b4ebde529ad0932d8d664b34f3f5"
|
||||
sha256: e9ad66020b89ff1b63908f247c2c6f931c6e62699b756ef8b3c4569350cd8662
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.1.4"
|
||||
version: "9.4.4"
|
||||
permission_handler_html:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_html
|
||||
sha256: "54bf176b90f6eddd4ece307e2c06cf977fb3973719c35a93b85cc7093eb6070d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.1"
|
||||
permission_handler_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_platform_interface
|
||||
sha256: "6760eb5ef34589224771010805bea6054ad28453906936f843a8cc4d3a55c4a4"
|
||||
sha256: "23dfba8447c076ab5be3dee9ceb66aad345c4a648f0cac292c77b1eb0e800b78"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.12.0"
|
||||
version: "4.2.0"
|
||||
permission_handler_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_windows
|
||||
sha256: cc074aace208760f1eee6aa4fae766b45d947df85bc831cde77009cdb4720098
|
||||
sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.3"
|
||||
version: "0.2.1"
|
||||
petitparser:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: petitparser
|
||||
sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750
|
||||
sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.4.0"
|
||||
version: "6.0.2"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -868,10 +924,34 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: pointer_interceptor
|
||||
sha256: adf7a637f97c077041d36801b43be08559fd4322d2127b3f20bb7be1b9eebc22
|
||||
sha256: bd18321519718678d5fa98ad3a3359cbc7a31f018554eab80b73d08a7f0c165a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.3+7"
|
||||
version: "0.10.1"
|
||||
pointer_interceptor_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pointer_interceptor_ios
|
||||
sha256: "2e73c39452830adc4695757130676a39412a3b7f3c34e3f752791b5384770877"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.10.0+2"
|
||||
pointer_interceptor_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pointer_interceptor_platform_interface
|
||||
sha256: "0597b0560e14354baeb23f8375cd612e8bd4841bf8306ecb71fcd0bb78552506"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.10.0+1"
|
||||
pointer_interceptor_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pointer_interceptor_web
|
||||
sha256: a6237528b46c411d8d55cdfad8fcb3269fc4cbb26060b14bff94879165887d1e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.10.2"
|
||||
pointycastle:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -888,22 +968,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.1"
|
||||
process:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: process
|
||||
sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.2.4"
|
||||
provider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: provider
|
||||
sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096"
|
||||
sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.1"
|
||||
version: "6.1.2"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1025,10 +1097,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: sqflite_common
|
||||
sha256: "28d8c66baee4968519fb8bd6cdbedad982d6e53359091f0b74544a9f32ec72d5"
|
||||
sha256: "3da423ce7baf868be70e2c0976c28a1bb2f73644268b7ffa7d2e08eab71f16a4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.3"
|
||||
version: "2.5.4"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1094,13 +1166,13 @@ packages:
|
|||
source: hosted
|
||||
version: "0.5.9"
|
||||
timezone:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: timezone
|
||||
sha256: "57b35f6e8ef731f18529695bffc62f92c6189fac2e52c12d478dec1931afb66e"
|
||||
sha256: "1cfd8ddc2d1cfd836bc93e67b9be88c3adaeca6f40a00ca999104c30693cdca0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.8.0"
|
||||
version: "0.9.2"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1113,26 +1185,26 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: url_launcher
|
||||
sha256: c512655380d241a337521703af62d2c122bf7b77a46ff7dd750092aa9433499c
|
||||
sha256: "0ecc004c62fd3ed36a2ffcbe0dd9700aee63bd7532d0b642a488b1ec310f492e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.2.4"
|
||||
version: "6.2.5"
|
||||
url_launcher_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_android
|
||||
sha256: "507dc655b1d9cb5ebc756032eb785f114e415f91557b73bf60b7e201dfedeb2f"
|
||||
sha256: d4ed0711849dd8e33eb2dd69c25db0d0d3fdc37e0a62e629fe32f57a22db2745
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.2.2"
|
||||
version: "6.3.0"
|
||||
url_launcher_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_ios
|
||||
sha256: "75bb6fe3f60070407704282a2d295630cab232991eb52542b18347a8a941df03"
|
||||
sha256: "9149d493b075ed740901f3ee844a38a00b33116c7c5c10d7fb27df8987fb51d5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.2.4"
|
||||
version: "6.2.5"
|
||||
url_launcher_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1153,18 +1225,18 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_platform_interface
|
||||
sha256: a932c3a8082e118f80a475ce692fde89dc20fddb24c57360b96bc56f7035de1f
|
||||
sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.1"
|
||||
version: "2.3.2"
|
||||
url_launcher_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_web
|
||||
sha256: fff0932192afeedf63cdd50ecbb1bc825d31aed259f02bb8dba0f3b729a5e88b
|
||||
sha256: "3692a459204a33e04bc94f5fb91158faf4f2c8903281ddd82915adecdb1a901d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.3"
|
||||
version: "2.3.0"
|
||||
url_launcher_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1185,26 +1257,26 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: vector_graphics
|
||||
sha256: "4ac59808bbfca6da38c99f415ff2d3a5d7ca0a6b4809c71d9cf30fba5daf9752"
|
||||
sha256: "32c3c684e02f9bc0afb0ae0aa653337a2fe022e8ab064bcd7ffda27a74e288e3"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.10+1"
|
||||
version: "1.1.11+1"
|
||||
vector_graphics_codec:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_graphics_codec
|
||||
sha256: f3247e7ab0ec77dc759263e68394990edc608fb2b480b80db8aa86ed09279e33
|
||||
sha256: c86987475f162fadff579e7320c7ddda04cd2fdeffbe1129227a85d9ac9e03da
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.10+1"
|
||||
version: "1.1.11+1"
|
||||
vector_graphics_compiler:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_graphics_compiler
|
||||
sha256: "18489bdd8850de3dd7ca8a34e0c446f719ec63e2bab2e7a8cc66a9028dd76c5a"
|
||||
sha256: "12faff3f73b1741a36ca7e31b292ddeb629af819ca9efe9953b70bd63fc8cd81"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.10+1"
|
||||
version: "1.1.11+1"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1217,18 +1289,18 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: video_player
|
||||
sha256: fbf28ce8bcfe709ad91b5789166c832cb7a684d14f571a81891858fefb5bb1c2
|
||||
sha256: afc65f4b8bcb2c188f64a591f84fb471f4f2e19fc607c65fd8d2f8fedb3dec23
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.8.2"
|
||||
version: "2.8.3"
|
||||
video_player_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: video_player_android
|
||||
sha256: "7f8f25d7ad56819a82b2948357f3c3af071f6a678db33833b26ec36bbc221316"
|
||||
sha256: "4dd9b8b86d70d65eecf3dcabfcdfbb9c9115d244d022654aba49a00336d540c2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.11"
|
||||
version: "2.4.12"
|
||||
video_player_avfoundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1249,10 +1321,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: video_player_web
|
||||
sha256: "34beb3a07d4331a24f7e7b2f75b8e2b103289038e07e65529699a671b6a6e2cb"
|
||||
sha256: "41245cef5ef29c4585dbabcbcbe9b209e34376642c7576cabf11b4ad9289d6e4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
version: "2.3.0"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1261,46 +1333,22 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "13.0.0"
|
||||
wakelock:
|
||||
wakelock_plus:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: wakelock
|
||||
sha256: "769ecf42eb2d07128407b50cb93d7c10bd2ee48f0276ef0119db1d25cc2f87db"
|
||||
name: wakelock_plus
|
||||
sha256: f268ca2116db22e57577fb99d52515a24bdc1d570f12ac18bb762361d43b043d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.2"
|
||||
wakelock_macos:
|
||||
version: "1.1.4"
|
||||
wakelock_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: wakelock_macos
|
||||
sha256: "047c6be2f88cb6b76d02553bca5a3a3b95323b15d30867eca53a19a0a319d4cd"
|
||||
name: wakelock_plus_platform_interface
|
||||
sha256: "40fabed5da06caff0796dc638e1f07ee395fb18801fbff3255a2372db2d80385"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.4.0"
|
||||
wakelock_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: wakelock_platform_interface
|
||||
sha256: "1f4aeb81fb592b863da83d2d0f7b8196067451e4df91046c26b54a403f9de621"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
wakelock_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: wakelock_web
|
||||
sha256: "1b256b811ee3f0834888efddfe03da8d18d0819317f20f6193e2922b41a501b5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.4.0"
|
||||
wakelock_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: wakelock_windows
|
||||
sha256: "857f77b3fe6ae82dd045455baa626bc4b93cb9bb6c86bf3f27c182167c3a5567"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.1"
|
||||
version: "1.1.0"
|
||||
watcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1313,18 +1361,26 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
|
||||
sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
version: "0.5.1"
|
||||
web_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket
|
||||
sha256: "3f81fde6fbc799d03c0fb3f2c3ac84368ee267012a4beb876685c029946da4e0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.0"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket_channel
|
||||
sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b
|
||||
sha256: "1d8e795e2a8b3730c41b8a98a2dff2e0fb57ae6f0764a1c46ec5915387d257b2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
version: "2.4.4"
|
||||
webkit_inspection_protocol:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1337,18 +1393,18 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: webview_flutter
|
||||
sha256: d81b68e88cc353e546afb93fb38958e3717282c5ac6e5d3be4a4aef9fc3c1413
|
||||
sha256: "25e1b6e839e8cbfbd708abc6f85ed09d1727e24e08e08c6b8590d7c65c9a8932"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.5.0"
|
||||
version: "4.7.0"
|
||||
webview_flutter_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webview_flutter_android
|
||||
sha256: "3e5f4e9d818086b0d01a66fb1ff9cc72ab0cc58c71980e3d3661c5685ea0efb0"
|
||||
sha256: f038ee2fae73b509dde1bc9d2c5a50ca92054282de17631a9a3d515883740934
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.15.0"
|
||||
version: "3.16.0"
|
||||
webview_flutter_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1361,18 +1417,18 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: webview_flutter_wkwebview
|
||||
sha256: "4d062ad505390ecef1c4bfb6001cd857a51e00912cc9dfb66edb1886a9ebd80c"
|
||||
sha256: f12f8d8a99784b863e8b85e4a9a5e3cf1839d6803d2c0c3e0533a8f3c5a992a7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.10.2"
|
||||
version: "3.13.0"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: a6f0236dbda0f63aa9a25ad1ff9a9d8a4eaaa5012da0dc59d21afdb1dc361ca4
|
||||
sha256: "8cb58b45c47dcb42ab3651533626161d6b67a2921917d8d429791f76972b3480"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.4"
|
||||
version: "5.3.0"
|
||||
workmanager:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -1385,18 +1441,18 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: xdg_directories
|
||||
sha256: bd512f03919aac5f1313eb8249f223bacf4927031bf60b02601f81f687689e86
|
||||
sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.0+3"
|
||||
version: "1.0.4"
|
||||
xml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xml
|
||||
sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84"
|
||||
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.0"
|
||||
version: "6.5.0"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1406,5 +1462,5 @@ packages:
|
|||
source: hosted
|
||||
version: "3.1.2"
|
||||
sdks:
|
||||
dart: ">=3.2.0 <4.0.0"
|
||||
flutter: ">=3.16.0"
|
||||
dart: ">=3.3.0 <4.0.0"
|
||||
flutter: ">=3.19.0"
|
||||
|
|
54
pubspec.yaml
54
pubspec.yaml
|
@ -9,40 +9,44 @@ environment:
|
|||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
cupertino_icons: ^1.0.5
|
||||
http: ^0.13.5
|
||||
cupertino_icons: ^1.0.6
|
||||
http: ^1.2.1
|
||||
after_layout: ^1.2.0
|
||||
intl: ^0.17.0
|
||||
flutter_local_notifications: ^9.8.0+1
|
||||
rxdart: ^0.27.5
|
||||
flutter_timezone: ^1.0.4
|
||||
flutter_secure_storage: ^8.0.0
|
||||
intl: ^0.19.0
|
||||
flutter_local_notifications: ^17.0.0
|
||||
rxdart: ^0.27.7
|
||||
flutter_timezone: ^1.0.8
|
||||
flutter_secure_storage: ^9.0.0
|
||||
datetime_picker_formfield: ^2.0.1
|
||||
flutter_typeahead: ^5.0.1
|
||||
build: ^2.3.0
|
||||
json_serializable: ^6.3.1
|
||||
petitparser: ^5.0.0
|
||||
provider: ^6.0.3
|
||||
webview_flutter: ^4.4.3
|
||||
flutter_typeahead: ^5.2.0
|
||||
build: ^2.4.1
|
||||
json_serializable: ^6.7.1
|
||||
petitparser: ^6.0.2
|
||||
provider: ^6.1.2
|
||||
webview_flutter: ^4.7.0
|
||||
flutter_colorpicker: ^1.0.3
|
||||
flutter_keyboard_visibility: ^5.4.2
|
||||
dotted_border: ^2.0.0+2
|
||||
package_info_plus: ^3.0.2
|
||||
url_launcher: ^6.1.7
|
||||
workmanager: ^0.5.1
|
||||
permission_handler: ^10.2.0
|
||||
dynamic_color: ^1.6.6
|
||||
chewie: ^1.5.0
|
||||
flutter_widget_from_html: ^0.14.10
|
||||
flutter_keyboard_visibility: ^6.0.0
|
||||
dotted_border: ^2.1.0
|
||||
url_launcher: ^6.2.5
|
||||
workmanager: ^0.5.2
|
||||
permission_handler: ^11.3.0
|
||||
dynamic_color: ^1.7.0
|
||||
flutter_widget_from_html: ^0.14.11
|
||||
flutter_downloader: ^1.11.6
|
||||
|
||||
|
||||
meta: ^1.11.0
|
||||
timezone: ^0.9.2
|
||||
json_annotation: ^4.8.1
|
||||
collection: ^1.18.0
|
||||
cupertino_http: ^1.4.0
|
||||
cronet_http: ^1.2.0
|
||||
package_info_plus: any
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
version: any
|
||||
test: ^1.21.1
|
||||
flutter_launcher_icons: ^0.10.0
|
||||
test: ^1.24.9
|
||||
flutter_launcher_icons: ^0.13.1
|
||||
|
||||
flutter_icons:
|
||||
image_path: "assets/vikunja_logo.png"
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 917 B |
Binary file not shown.
After Width: | Height: | Size: 5.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 8.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 5.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
|
@ -0,0 +1,59 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<!--
|
||||
If you are serving your web app in a path other than the root, change the
|
||||
href value below to reflect the base path you are serving from.
|
||||
|
||||
The path provided below has to start and end with a slash "/" in order for
|
||||
it to work correctly.
|
||||
|
||||
For more details:
|
||||
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
|
||||
|
||||
This is a placeholder for base href that will be replaced by the value of
|
||||
the `--base-href` argument provided to `flutter build`.
|
||||
-->
|
||||
<base href="$FLUTTER_BASE_HREF">
|
||||
|
||||
<meta charset="UTF-8">
|
||||
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
|
||||
<meta name="description" content="A new Flutter project.">
|
||||
|
||||
<!-- iOS meta tags & icons -->
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||
<meta name="apple-mobile-web-app-title" content="vikunja_app">
|
||||
<link rel="apple-touch-icon" href="icons/Icon-192.png">
|
||||
|
||||
<!-- Favicon -->
|
||||
<link rel="icon" type="image/png" href="favicon.png"/>
|
||||
|
||||
<title>vikunja_app</title>
|
||||
<link rel="manifest" href="manifest.json">
|
||||
|
||||
<script>
|
||||
// The value below is injected by flutter build, do not touch.
|
||||
const serviceWorkerVersion = null;
|
||||
</script>
|
||||
<!-- This script adds the flutter initialization JS code -->
|
||||
<script src="flutter.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
window.addEventListener('load', function(ev) {
|
||||
// Download main.dart.js
|
||||
_flutter.loader.loadEntrypoint({
|
||||
serviceWorker: {
|
||||
serviceWorkerVersion: serviceWorkerVersion,
|
||||
},
|
||||
onEntrypointLoaded: function(engineInitializer) {
|
||||
engineInitializer.initializeEngine().then(function(appRunner) {
|
||||
appRunner.runApp();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"name": "vikunja_app",
|
||||
"short_name": "vikunja_app",
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"background_color": "#0175C2",
|
||||
"theme_color": "#0175C2",
|
||||
"description": "A new Flutter project.",
|
||||
"orientation": "portrait-primary",
|
||||
"prefer_related_applications": false,
|
||||
"icons": [
|
||||
{
|
||||
"src": "icons/Icon-192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "icons/Icon-512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "icons/Icon-maskable-192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
},
|
||||
{
|
||||
"src": "icons/Icon-maskable-512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue