1
0
mirror of https://github.com/go-vikunja/app synced 2024-11-14 08:40:45 +00:00

Make it build again (#38)

Fix parsing of user model if email is not present

Use user avatar hash instead of calculating it from the email

Format

Replace GravatarImageProvider

Set min sdk version to 19

Change target api version to 28

Limit drone pipeline execution to master or pr

Remove drone debug

Use username instead of id

Format

"Fix" clone permissions

Drone debug

Fix drone permissions with different flutter build docker image

Switch CI build image

Bump Gradle sdk version

Fix formatting

Update packages for support for androidX

Update gitignore

AndroidX

Make GravatarImageProvider work again

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/app#38
This commit is contained in:
konrad 2020-01-12 12:59:28 +00:00
parent d1eb3fbc37
commit edbadd9913
18 changed files with 387 additions and 371 deletions

@ -2,16 +2,27 @@ kind: pipeline
name: testing
workspace:
base: /app
base: /home/cirrus/app
clone:
depth: 50
# Only run on prs or pushes to master
trigger:
branch:
include:
- master
event:
include:
- push
- pull_request
steps:
- name: build
image: vikunja/flutter-build
image: cirrusci/flutter:stable
pull: true
commands:
- sudo chown cirrus . -R # The clone step clones everything as root, this is our "fix" until we find a better solution
- flutter packages get
- make format-check
- make build-debug
@ -32,12 +43,12 @@ depends_on:
trigger:
branch:
- master
- master
event:
- push
- push
workspace:
base: /app
base: /home/cirrus/app
clone:
depth: 50
@ -45,13 +56,14 @@ clone:
steps:
# Because drone separates the pipelines, we have to add the build step to this pipeline. This is double code, we should change it at some point if possible.
- name: build
image: vikunja/flutter-build
image: cirrusci/flutter:stable
pull: true
commands:
- flutter packages get
- make build-all
- mkdir apks
- mv build/app/outputs/apk/*/*/*.apk apks
- sudo chown cirrus . -R # The clone step clones everything as root, this is our "fix" until we find a better solution
- flutter packages get
- make build-all
- mkdir apks
- mv build/app/outputs/apk/*/*/*.apk apks
# Push the releases to our pseudo-s3-bucket
- name: release
@ -78,10 +90,10 @@ depends_on:
trigger:
event:
- tag
- tag
workspace:
base: /app
base: /home/cirrus/app
clone:
depth: 50
@ -89,13 +101,14 @@ clone:
steps:
# Because drone separates the pipelines, we have to add the build step to this pipeline. This is double code, we should change it at some point if possible.
- name: build
image: vikunja/flutter-build
image: cirrusci/flutter:stable
pull: true
commands:
- flutter packages get
- make build-all
- mkdir apks
- mv build/app/outputs/apk/*/*/*.apk apks
- sudo chown cirrus . -R # The clone step clones everything as root, this is our "fix" until we find a better solution
- flutter packages get
- make build-all
- mkdir apks
- mv build/app/outputs/apk/*/*/*.apk apks
# Push the releases to our pseudo-s3-bucket
- name: release
image: plugins/s3:1

1
.gitignore vendored

@ -28,6 +28,7 @@
.pub/
build/
!pubspec.lock
.flutter-plugins-dependencies
# Android related
**/android/**/gradle-wrapper.jar

@ -26,7 +26,7 @@ apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 27
compileSdkVersion 28
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
@ -37,14 +37,12 @@ android {
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "io.vikunja.app"
minSdkVersion 18
targetSdkVersion 27
minSdkVersion 19
targetSdkVersion 28
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
flavorDimensions "deploy"

@ -21,8 +21,6 @@ allprojects {
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}

@ -1 +1,4 @@
org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
android.useAndroidX=true
android.enableJetifier=true

@ -0,0 +1 @@
include ':app'

@ -0,0 +1,10 @@
#!/bin/sh
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=/nix/store/nyvp7jf7sfxsbc6jsm1y4fc18631ap26-flutter-stable-1.12.13+hotfix.5-unwrapped"
export "FLUTTER_APPLICATION_PATH=/home/konrad/www/vikunja/app2"
export "FLUTTER_TARGET=lib/main.dart"
export "FLUTTER_BUILD_DIR=build"
export "SYMROOT=${SOURCE_ROOT}/../build/ios"
export "FLUTTER_FRAMEWORK_DIR=/home/konrad/.cache/flutter/artifacts/engine/ios"
export "FLUTTER_BUILD_NAME=0.1.0"
export "FLUTTER_BUILD_NUMBER=0.1.0"

@ -1,9 +0,0 @@
import 'package:flutter/material.dart';
import 'package:crypto/crypto.dart';
class GravatarImageProvider extends NetworkImage {
GravatarImageProvider(String email)
: super("https://secure.gravatar.com/avatar/" +
md5.convert(email.trim().toLowerCase().codeUnits).toString());
}

@ -120,9 +120,9 @@ class VikunjaGlobalState extends State<VikunjaGlobal> {
});
return;
}
loadedCurrentUser = User(int.tryParse(currentUser), "", "");
loadedCurrentUser = User(int.tryParse(currentUser), "", "", "");
} catch (otherExceptions) {
loadedCurrentUser = User(int.tryParse(currentUser), "", "");
loadedCurrentUser = User(int.tryParse(currentUser), "", "", "");
}
setState(() {
_client = client;

@ -1,14 +1,19 @@
class User {
final int id;
final String email, username;
final String email, username, avatarHash;
User(this.id, this.email, this.username);
User(this.id, this.email, this.username, this.avatarHash);
User.fromJson(Map<String, dynamic> json)
: id = json['id'],
email = json['email'],
username = json['username'];
email = json.containsKey('email') ? json['email'] : '',
username = json['username'],
avatarHash = json['avatarUrl'];
toJSON() => {"id": this.id, "email": this.email, "username": this.username};
String avatarUrl() {
return "https://secure.gravatar.com/avatar/" + this.avatarHash;
}
}
class UserTokenPair {

@ -4,7 +4,6 @@ import 'package:flutter/material.dart';
import 'package:after_layout/after_layout.dart';
import 'package:vikunja_app/components/AddDialog.dart';
import 'package:vikunja_app/components/GravatarImage.dart';
import 'package:vikunja_app/pages/namespace/namespace.dart';
import 'package:vikunja_app/pages/namespace/namespace_edit.dart';
import 'package:vikunja_app/pages/placeholder.dart';
@ -90,8 +89,10 @@ class HomePageState extends State<HomePage> with AfterLayoutMixin<HomePage> {
drawer: new Drawer(
child: new Column(children: <Widget>[
new UserAccountsDrawerHeader(
accountEmail: currentUser == null ? null : Text(currentUser.email),
accountName: currentUser == null ? null : Text(currentUser.username),
accountEmail:
currentUser?.email == null ? null : Text(currentUser.email),
accountName:
currentUser?.username == null ? null : Text(currentUser.username),
onDetailsPressed: () {
setState(() {
_showUserDetails = !_showUserDetails;
@ -100,7 +101,8 @@ class HomePageState extends State<HomePage> with AfterLayoutMixin<HomePage> {
currentAccountPicture: currentUser == null
? null
: CircleAvatar(
backgroundImage: GravatarImageProvider(currentUser.username)),
backgroundImage: NetworkImage(currentUser.avatarUrl()),
),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/graphics/hypnotize.png"),
@ -118,10 +120,10 @@ class HomePageState extends State<HomePage> with AfterLayoutMixin<HomePage> {
alignment: FractionalOffset.bottomCenter,
child: Builder(
builder: (context) => ListTile(
leading: const Icon(Icons.add),
title: const Text('Add namespace...'),
onTap: () => _addNamespaceDialog(context),
),
leading: const Icon(Icons.add),
title: const Text('Add namespace...'),
onTap: () => _addNamespaceDialog(context),
),
),
),
])),

@ -26,68 +26,68 @@ class _ListEditPageState extends State<ListEditPage> {
),
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.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(),
),
),
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.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.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: TextFormField(
maxLines: null,
keyboardType: TextInputType.multiline,
initialValue: widget.list.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();
_saveList(context);
}
}
: null,
child: _loading
? CircularProgressIndicator()
: VikunjaButtonText('Save'),
))),
]),
),
),
),
),
Builder(
builder: (context) => Padding(
padding: EdgeInsets.symmetric(vertical: 10.0),
child: FancyButton(
onPressed: !_loading
? () {
if (_formKey.currentState.validate()) {
Form.of(context).save();
_saveList(context);
}
}
: null,
child: _loading
? CircularProgressIndicator()
: VikunjaButtonText('Save'),
))),
]),
),
),
),
);
}

@ -26,68 +26,68 @@ class _NamespaceEditPageState extends State<NamespaceEditPage> {
),
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.name,
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(),
),
),
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.name,
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(),
),
),
),
),
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'),
))),
]),
),
),
),
),
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'),
))),
]),
),
),
),
);
}

@ -24,83 +24,81 @@ class _LoginPageState extends State<LoginPage> {
padding: const EdgeInsets.all(16.0),
child: Builder(
builder: (BuildContext context) => Form(
autovalidate: true,
key: _formKey,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(vertical: 30),
child: Image(
image: AssetImage('assets/vikunja_logo_full.png'),
height: 85.0,
semanticLabel: 'Vikunja Logo',
),
),
Padding(
padding: vStandardVerticalPadding,
child: TextFormField(
enabled: !_loading,
onSaved: (serverAddress) => _server = serverAddress,
validator: (address) {
return isUrl(address) ? null : 'Invalid URL';
},
decoration: new InputDecoration(
border: OutlineInputBorder(),
labelText: 'Server Address'),
),
),
Padding(
padding: vStandardVerticalPadding,
child: TextFormField(
enabled: !_loading,
onSaved: (username) => _username = username,
decoration: new InputDecoration(
border: OutlineInputBorder(),
labelText: 'Username'),
),
),
Padding(
padding: vStandardVerticalPadding,
child: TextFormField(
enabled: !_loading,
onSaved: (password) => _password = password,
decoration: new InputDecoration(
border: OutlineInputBorder(),
labelText: 'Password'),
obscureText: true,
),
),
Builder(
builder: (context) => FancyButton(
onPressed: !_loading
? () {
if (_formKey.currentState
.validate()) {
Form.of(context).save();
_loginUser(context);
}
}
: null,
child: _loading
? CircularProgressIndicator()
: VikunjaButtonText('Login'),
)),
Builder(
builder: (context) => FancyButton(
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
RegisterPage())),
child: VikunjaButtonText('Register'),
)),
],
autovalidate: true,
key: _formKey,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(vertical: 30),
child: Image(
image: AssetImage('assets/vikunja_logo_full.png'),
height: 85.0,
semanticLabel: 'Vikunja Logo',
),
),
),
Padding(
padding: vStandardVerticalPadding,
child: TextFormField(
enabled: !_loading,
onSaved: (serverAddress) => _server = serverAddress,
validator: (address) {
return isUrl(address) ? null : 'Invalid URL';
},
decoration: new InputDecoration(
border: OutlineInputBorder(),
labelText: 'Server Address'),
),
),
Padding(
padding: vStandardVerticalPadding,
child: TextFormField(
enabled: !_loading,
onSaved: (username) => _username = username,
decoration: new InputDecoration(
border: OutlineInputBorder(),
labelText: 'Username'),
),
),
Padding(
padding: vStandardVerticalPadding,
child: TextFormField(
enabled: !_loading,
onSaved: (password) => _password = password,
decoration: new InputDecoration(
border: OutlineInputBorder(),
labelText: 'Password'),
obscureText: true,
),
),
Builder(
builder: (context) => FancyButton(
onPressed: !_loading
? () {
if (_formKey.currentState.validate()) {
Form.of(context).save();
_loginUser(context);
}
}
: null,
child: _loading
? CircularProgressIndicator()
: VikunjaButtonText('Login'),
)),
Builder(
builder: (context) => FancyButton(
onPressed: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => RegisterPage())),
child: VikunjaButtonText('Register'),
)),
],
),
),
),
),
),
),

@ -24,103 +24,102 @@ class _RegisterPageState extends State<RegisterPage> {
),
body: Builder(
builder: (BuildContext context) => SafeArea(
top: false,
bottom: false,
child: Form(
key: _formKey,
child: ListView(
padding: const EdgeInsets.all(16),
children: <Widget>[
Padding(
padding: vStandardVerticalPadding,
child: TextFormField(
onSaved: (serverAddress) => _server = serverAddress,
validator: (address) {
return isUrl(address) ? null : 'Invalid URL';
},
decoration: new InputDecoration(
border: OutlineInputBorder(),
labelText: 'Server Address'),
),
),
Padding(
padding: vStandardVerticalPadding,
child: TextFormField(
onSaved: (username) => _username = username.trim(),
validator: (username) {
return username.trim().isNotEmpty
? null
: 'Please specify a username';
},
decoration: new InputDecoration(
border: OutlineInputBorder(),
labelText: 'Username'),
),
),
Padding(
padding: vStandardVerticalPadding,
child: TextFormField(
onSaved: (email) => _email = email,
validator: (email) {
return isEmail(email)
? null
: 'Email adress is invalid';
},
decoration: new InputDecoration(
border: OutlineInputBorder(),
labelText: 'Email Address'),
),
),
Padding(
padding: vStandardVerticalPadding,
child: TextFormField(
controller: passwordController,
onSaved: (password) => _password = password,
validator: (password) {
return password.length >= 8
? null
: 'Please use at least 8 characters';
},
decoration: new InputDecoration(
border: OutlineInputBorder(),
labelText: 'Password'),
obscureText: true,
),
),
Padding(
padding: vStandardVerticalPadding,
child: TextFormField(
validator: (password) {
return passwordController.text == password
? null
: 'Passwords don\'t match.';
},
decoration: new InputDecoration(
border: OutlineInputBorder(),
labelText: 'Repeat Password'),
obscureText: true,
),
),
Builder(
builder: (context) => FancyButton(
onPressed: !_loading
? () {
if (_formKey.currentState
.validate()) {
Form.of(context).save();
_registerUser(context);
} else {
print("awhat");
}
}
: null,
child: _loading
? CircularProgressIndicator()
: VikunjaButtonText('Register'),
)),
],
)),
),
top: false,
bottom: false,
child: Form(
key: _formKey,
child: ListView(
padding: const EdgeInsets.all(16),
children: <Widget>[
Padding(
padding: vStandardVerticalPadding,
child: TextFormField(
onSaved: (serverAddress) => _server = serverAddress,
validator: (address) {
return isUrl(address) ? null : 'Invalid URL';
},
decoration: new InputDecoration(
border: OutlineInputBorder(),
labelText: 'Server Address'),
),
),
Padding(
padding: vStandardVerticalPadding,
child: TextFormField(
onSaved: (username) => _username = username.trim(),
validator: (username) {
return username.trim().isNotEmpty
? null
: 'Please specify a username';
},
decoration: new InputDecoration(
border: OutlineInputBorder(),
labelText: 'Username'),
),
),
Padding(
padding: vStandardVerticalPadding,
child: TextFormField(
onSaved: (email) => _email = email,
validator: (email) {
return isEmail(email)
? null
: 'Email adress is invalid';
},
decoration: new InputDecoration(
border: OutlineInputBorder(),
labelText: 'Email Address'),
),
),
Padding(
padding: vStandardVerticalPadding,
child: TextFormField(
controller: passwordController,
onSaved: (password) => _password = password,
validator: (password) {
return password.length >= 8
? null
: 'Please use at least 8 characters';
},
decoration: new InputDecoration(
border: OutlineInputBorder(),
labelText: 'Password'),
obscureText: true,
),
),
Padding(
padding: vStandardVerticalPadding,
child: TextFormField(
validator: (password) {
return passwordController.text == password
? null
: 'Passwords don\'t match.';
},
decoration: new InputDecoration(
border: OutlineInputBorder(),
labelText: 'Repeat Password'),
obscureText: true,
),
),
Builder(
builder: (context) => FancyButton(
onPressed: !_loading
? () {
if (_formKey.currentState.validate()) {
Form.of(context).save();
_registerUser(context);
} else {
print("awhat");
}
}
: null,
child: _loading
? CircularProgressIndicator()
: VikunjaButtonText('Register'),
)),
],
)),
),
));
}

@ -7,7 +7,7 @@ import 'package:vikunja_app/models/user.dart';
import 'package:vikunja_app/service/services.dart';
// Data for mocked services
var _users = {1: User(1, 'test@testuser.org', 'test1')};
var _users = {1: User(1, 'test@testuser.org', 'test1', '')};
var _namespaces = {
1: Namespace(

@ -1,5 +1,5 @@
# Generated by pub
# See https://www.dartlang.org/tools/pub/glossary#lockfile
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
after_layout:
dependency: "direct main"
@ -7,35 +7,35 @@ packages:
name: after_layout
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.7"
version: "1.0.7+2"
archive:
dependency: transitive
description:
name: archive
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.8"
version: "2.0.11"
args:
dependency: transitive
description:
name: args
url: "https://pub.dartlang.org"
source: hosted
version: "1.5.1"
version: "1.5.2"
async:
dependency: transitive
description:
name: async
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.8"
version: "2.4.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
version: "1.0.5"
charcode:
dependency: transitive
description:
@ -63,14 +63,14 @@ packages:
name: crypto
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.6"
version: "2.1.3"
cupertino_icons:
dependency: "direct main"
description:
name: cupertino_icons
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.2"
version: "0.1.3"
dart_config:
dependency: transitive
description:
@ -98,7 +98,7 @@ packages:
name: flutter_secure_storage
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.1"
version: "3.3.1+1"
flutter_test:
dependency: "direct dev"
description: flutter
@ -110,7 +110,7 @@ packages:
name: http
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.0"
version: "0.12.0+3"
http_parser:
dependency: transitive
description:
@ -124,49 +124,49 @@ packages:
name: image
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.7"
version: "2.1.4"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.3+1"
version: "0.12.6"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.6"
version: "1.1.8"
path:
dependency: transitive
description:
name: path
url: "https://pub.dartlang.org"
source: hosted
version: "1.6.2"
version: "1.6.4"
pedantic:
dependency: transitive
description:
name: pedantic
url: "https://pub.dartlang.org"
source: hosted
version: "1.4.0"
version: "1.8.0+1"
petitparser:
dependency: transitive
description:
name: petitparser
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.1"
version: "2.4.0"
quiver:
dependency: transitive
description:
name: quiver
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
version: "2.0.5"
sky_engine:
dependency: transitive
description: flutter
@ -178,7 +178,7 @@ packages:
name: source_span
url: "https://pub.dartlang.org"
source: hosted
version: "1.5.4"
version: "1.5.5"
stack_trace:
dependency: transitive
description:
@ -192,14 +192,14 @@ packages:
name: stream_channel
url: "https://pub.dartlang.org"
source: hosted
version: "1.6.8"
version: "2.0.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
version: "1.0.5"
term_glyph:
dependency: transitive
description:
@ -213,7 +213,7 @@ packages:
name: test_api
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.2"
version: "0.2.11"
typed_data:
dependency: transitive
description:
@ -234,13 +234,13 @@ packages:
name: xml
url: "https://pub.dartlang.org"
source: hosted
version: "3.3.1"
version: "3.5.0"
yaml:
dependency: transitive
description:
name: yaml
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.15"
version: "2.2.0"
sdks:
dart: ">=2.1.0 <3.0.0"
dart: ">=2.4.0 <3.0.0"

@ -4,17 +4,14 @@ description: Vikunja as Flutter cross platform app
version: 0.1.0
environment:
sdk: ">=2.0.0-dev.63.0 <3.0.0"
sdk: ">=2.1.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
flutter_secure_storage: 3.1.1
http: 0.12.0
cupertino_icons: ^0.1.3
flutter_secure_storage: 3.3.1+1
http: 0.12.0+3
after_layout: ^1.0.7
dev_dependencies: