Make it build again (#38)
continuous-integration/drone/push Build is passing Details

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: #38
This commit is contained in:
konrad 2020-01-12 12:59:28 +00:00
parent 144f55af6d
commit 0f23c4d0f3
18 changed files with 387 additions and 371 deletions

View File

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

1
.gitignore vendored
View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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"

View File

@ -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());
}

View File

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

View File

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

View File

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

View File

@ -26,68 +26,68 @@ class _ListEditPageState extends State<ListEditPage> {
), ),
body: Builder( body: Builder(
builder: (BuildContext context) => SafeArea( builder: (BuildContext context) => SafeArea(
child: Form( child: Form(
key: _formKey, key: _formKey,
child: ListView( child: ListView(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
children: <Widget>[ children: <Widget>[
Padding( Padding(
padding: EdgeInsets.symmetric(vertical: 10.0), padding: EdgeInsets.symmetric(vertical: 10.0),
child: TextFormField( child: TextFormField(
maxLines: null, maxLines: null,
keyboardType: TextInputType.multiline, keyboardType: TextInputType.multiline,
initialValue: widget.list.title, initialValue: widget.list.title,
onSaved: (title) => _title = title, onSaved: (title) => _title = title,
validator: (title) { validator: (title) {
if (title.length < 3 || title.length > 250) { if (title.length < 3 || title.length > 250) {
return 'The title needs to have between 3 and 250 characters.'; return 'The title needs to have between 3 and 250 characters.';
} }
return null; return null;
}, },
decoration: new InputDecoration( decoration: new InputDecoration(
labelText: 'Title', labelText: 'Title',
border: OutlineInputBorder(), border: OutlineInputBorder(),
),
),
), ),
Padding( ),
padding: EdgeInsets.symmetric(vertical: 10.0), ),
child: TextFormField( Padding(
maxLines: null, padding: EdgeInsets.symmetric(vertical: 10.0),
keyboardType: TextInputType.multiline, child: TextFormField(
initialValue: widget.list.description, maxLines: null,
onSaved: (description) => _description = description, keyboardType: TextInputType.multiline,
validator: (description) { initialValue: widget.list.description,
if (description.length > 1000) { onSaved: (description) => _description = description,
return 'The description can have a maximum of 1000 characters.'; validator: (description) {
} if (description.length > 1000) {
return null; return 'The description can have a maximum of 1000 characters.';
}, }
decoration: new InputDecoration( return null;
labelText: 'Description', },
border: OutlineInputBorder(), decoration: new InputDecoration(
), labelText: 'Description',
), border: OutlineInputBorder(),
), ),
Builder( ),
builder: (context) => Padding( ),
padding: EdgeInsets.symmetric(vertical: 10.0), Builder(
child: FancyButton( builder: (context) => Padding(
onPressed: !_loading padding: EdgeInsets.symmetric(vertical: 10.0),
? () { child: FancyButton(
if (_formKey.currentState.validate()) { onPressed: !_loading
Form.of(context).save(); ? () {
_saveList(context); if (_formKey.currentState.validate()) {
} Form.of(context).save();
} _saveList(context);
: null, }
child: _loading }
? CircularProgressIndicator() : null,
: VikunjaButtonText('Save'), child: _loading
))), ? CircularProgressIndicator()
]), : VikunjaButtonText('Save'),
), ))),
), ]),
),
),
), ),
); );
} }

View File

@ -26,68 +26,68 @@ class _NamespaceEditPageState extends State<NamespaceEditPage> {
), ),
body: Builder( body: Builder(
builder: (BuildContext context) => SafeArea( builder: (BuildContext context) => SafeArea(
child: Form( child: Form(
key: _formKey, key: _formKey,
child: ListView( child: ListView(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
children: <Widget>[ children: <Widget>[
Padding( Padding(
padding: EdgeInsets.symmetric(vertical: 10.0), padding: EdgeInsets.symmetric(vertical: 10.0),
child: TextFormField( child: TextFormField(
maxLines: null, maxLines: null,
keyboardType: TextInputType.multiline, keyboardType: TextInputType.multiline,
initialValue: widget.namespace.name, initialValue: widget.namespace.name,
onSaved: (name) => _name = name, onSaved: (name) => _name = name,
validator: (name) { validator: (name) {
if (name.length < 3 || name.length > 250) { if (name.length < 3 || name.length > 250) {
return 'The name needs to have between 3 and 250 characters.'; return 'The name needs to have between 3 and 250 characters.';
} }
return null; return null;
}, },
decoration: new InputDecoration( decoration: new InputDecoration(
labelText: 'Name', labelText: 'Name',
border: OutlineInputBorder(), border: OutlineInputBorder(),
),
),
), ),
Padding( ),
padding: EdgeInsets.symmetric(vertical: 10.0), ),
child: TextFormField( Padding(
maxLines: null, padding: EdgeInsets.symmetric(vertical: 10.0),
keyboardType: TextInputType.multiline, child: TextFormField(
initialValue: widget.namespace.description, maxLines: null,
onSaved: (description) => _description = description, keyboardType: TextInputType.multiline,
validator: (description) { initialValue: widget.namespace.description,
if (description.length > 1000) { onSaved: (description) => _description = description,
return 'The description can have a maximum of 1000 characters.'; validator: (description) {
} if (description.length > 1000) {
return null; return 'The description can have a maximum of 1000 characters.';
}, }
decoration: new InputDecoration( return null;
labelText: 'Description', },
border: OutlineInputBorder(), decoration: new InputDecoration(
), labelText: 'Description',
), border: OutlineInputBorder(),
), ),
Builder( ),
builder: (context) => Padding( ),
padding: EdgeInsets.symmetric(vertical: 10.0), Builder(
child: FancyButton( builder: (context) => Padding(
onPressed: !_loading padding: EdgeInsets.symmetric(vertical: 10.0),
? () { child: FancyButton(
if (_formKey.currentState.validate()) { onPressed: !_loading
Form.of(context).save(); ? () {
_saveNamespace(context); if (_formKey.currentState.validate()) {
} Form.of(context).save();
} _saveNamespace(context);
: null, }
child: _loading }
? CircularProgressIndicator() : null,
: VikunjaButtonText('Save'), child: _loading
))), ? CircularProgressIndicator()
]), : VikunjaButtonText('Save'),
), ))),
), ]),
),
),
), ),
); );
} }

View File

@ -24,83 +24,81 @@ class _LoginPageState extends State<LoginPage> {
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: Builder( child: Builder(
builder: (BuildContext context) => Form( builder: (BuildContext context) => Form(
autovalidate: true, autovalidate: true,
key: _formKey, key: _formKey,
child: Center( child: Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[ children: <Widget>[
Padding( Padding(
padding: EdgeInsets.symmetric(vertical: 30), padding: EdgeInsets.symmetric(vertical: 30),
child: Image( child: Image(
image: AssetImage('assets/vikunja_logo_full.png'), image: AssetImage('assets/vikunja_logo_full.png'),
height: 85.0, height: 85.0,
semanticLabel: 'Vikunja Logo', 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'),
)),
],
), ),
), 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'),
)),
],
), ),
),
),
), ),
), ),
), ),

View File

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

View File

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

View File

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

View File

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