This commit is contained in:
parent
67e47b03cd
commit
fa05e0e6a3
153
.drone.yml
153
.drone.yml
|
@ -1,58 +1,117 @@
|
||||||
|
kind: pipeline
|
||||||
|
name: testing
|
||||||
|
|
||||||
workspace:
|
workspace:
|
||||||
base: /app
|
base: /app
|
||||||
|
|
||||||
clone:
|
clone:
|
||||||
git:
|
depth: 50
|
||||||
image: plugins/git
|
|
||||||
depth: 50
|
|
||||||
tags: true
|
|
||||||
|
|
||||||
pipeline:
|
steps:
|
||||||
build:
|
- name: build
|
||||||
image: jonasfranz/flutter:master
|
image: adamantium/flutter
|
||||||
pull: true
|
pull: true
|
||||||
commands:
|
commands:
|
||||||
- flutter packages get
|
- apt-get update && apt-get install make # We do this here to not have to deal with updating the image itself
|
||||||
- make format-check
|
- flutter packages get
|
||||||
- make build-all
|
- make format-check
|
||||||
- mkdir apks
|
- make build-debug
|
||||||
- mv build/app/outputs/apk/*/*/*.apk apks
|
|
||||||
when:
|
|
||||||
event: [ push, tag ]
|
|
||||||
|
|
||||||
test:
|
- name: test
|
||||||
image: jonasfranz/flutter:master
|
image: adamantium/flutter
|
||||||
pull: true
|
pull: true
|
||||||
commands:
|
commands:
|
||||||
- make test
|
- apt-get update && apt-get install make # We do this here to not have to deal with updating the image itself
|
||||||
when:
|
- flutter packages get
|
||||||
event: [ push, tag, pull_request ]
|
- make test
|
||||||
|
|
||||||
# Push the releases to our pseudo-s3-bucket
|
---
|
||||||
release:
|
kind: pipeline
|
||||||
|
name: release-latest
|
||||||
|
|
||||||
|
depends_on:
|
||||||
|
- testing
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
branch:
|
||||||
|
- master
|
||||||
|
event:
|
||||||
|
- push
|
||||||
|
|
||||||
|
workspace:
|
||||||
|
base: /app
|
||||||
|
|
||||||
|
clone:
|
||||||
|
depth: 50
|
||||||
|
|
||||||
|
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: adamantium/flutter
|
||||||
|
pull: true
|
||||||
|
commands:
|
||||||
|
- apt-get update && apt-get install make # We do this here to not have to deal with updating the image itself
|
||||||
|
- 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
|
image: plugins/s3:1
|
||||||
pull: true
|
pull: true
|
||||||
secrets: [ aws_access_key_id, aws_secret_access_key ]
|
settings:
|
||||||
bucket: vikunja-app
|
bucket: vikunja-app
|
||||||
endpoint: https://storage.kolaente.de
|
access_key:
|
||||||
path_style: true
|
from_secret: aws_access_key_id
|
||||||
strip_prefix: apks/
|
secret_key:
|
||||||
source: apks/*
|
from_secret: aws_secret_access_key
|
||||||
target: /${DRONE_TAG##v}
|
endpoint: https://storage.kolaente.de
|
||||||
when:
|
path_style: true
|
||||||
event: [ tag ]
|
strip_prefix: apks/
|
||||||
|
source: apks/*
|
||||||
|
target: /master
|
||||||
|
|
||||||
# Push the releases to our pseudo-s3-bucket
|
---
|
||||||
release:
|
kind: pipeline
|
||||||
|
name: release-version
|
||||||
|
|
||||||
|
depends_on:
|
||||||
|
- testing
|
||||||
|
|
||||||
|
trigger:
|
||||||
|
event:
|
||||||
|
- tag
|
||||||
|
|
||||||
|
workspace:
|
||||||
|
base: /app
|
||||||
|
|
||||||
|
clone:
|
||||||
|
depth: 50
|
||||||
|
|
||||||
|
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: adamantium/flutter
|
||||||
|
pull: true
|
||||||
|
commands:
|
||||||
|
- apt-get update && apt-get install make # We do this here to not have to deal with updating the image itself
|
||||||
|
- 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
|
image: plugins/s3:1
|
||||||
pull: true
|
pull: true
|
||||||
secrets: [ aws_access_key_id, aws_secret_access_key ]
|
settings:
|
||||||
bucket: vikunja-app
|
bucket: vikunja-app
|
||||||
endpoint: https://storage.kolaente.de
|
access_key:
|
||||||
path_style: true
|
from_secret: aws_access_key_id
|
||||||
strip_prefix: apks/
|
secret_key:
|
||||||
source: apks/*
|
from_secret: aws_secret_access_key
|
||||||
target: /master
|
endpoint: https://storage.kolaente.de
|
||||||
when:
|
path_style: true
|
||||||
event: [ push ]
|
strip_prefix: apks/
|
||||||
branch: [ master ]
|
source: apks/*
|
||||||
|
target: /${DRONE_TAG##v}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
.pub-cache/
|
.pub-cache/
|
||||||
.pub/
|
.pub/
|
||||||
build/
|
build/
|
||||||
|
!pubspec.lock
|
||||||
|
|
||||||
# Android related
|
# Android related
|
||||||
**/android/**/gradle-wrapper.jar
|
**/android/**/gradle-wrapper.jar
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Vikunja Cross-Plattform app
|
# Vikunja Cross-Plattform app
|
||||||
|
|
||||||
[![Build Status](https://drone.kolaente.de/api/badges/vikunja/app/status.svg)](https://drone.kolaente.de/vikunja/app)
|
[![Build Status](https://drone1.kolaente.de/api/badges/vikunja/app/status.svg)](https://drone1.kolaente.de/vikunja/app)
|
||||||
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
|
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
|
||||||
[![Download](https://img.shields.io/badge/download-v0.1-brightgreen.svg)](https://storage.kolaente.de/minio/vikunja-app/)
|
[![Download](https://img.shields.io/badge/download-v0.1-brightgreen.svg)](https://storage.kolaente.de/minio/vikunja-app/)
|
||||||
|
|
||||||
|
|
|
@ -57,8 +57,8 @@ class _NamespaceFragmentState extends State<NamespaceFragment> {
|
||||||
: Center(child: CircularProgressIndicator()),
|
: Center(child: CircularProgressIndicator()),
|
||||||
floatingActionButton: Builder(
|
floatingActionButton: Builder(
|
||||||
builder: (context) => FloatingActionButton(
|
builder: (context) => FloatingActionButton(
|
||||||
onPressed: () => _addListDialog(context), child: const Icon(Icons.add))
|
onPressed: () => _addListDialog(context),
|
||||||
),
|
child: const Icon(Icons.add))),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,16 +102,16 @@ class _NamespaceFragmentState extends State<NamespaceFragment> {
|
||||||
|
|
||||||
_addList(String name, BuildContext context) {
|
_addList(String name, BuildContext context) {
|
||||||
VikunjaGlobal.of(context)
|
VikunjaGlobal.of(context)
|
||||||
.listService
|
.listService
|
||||||
.create(widget.namespace.id, TaskList(id: null, title: name, tasks: []))
|
.create(widget.namespace.id, TaskList(id: null, title: name, tasks: []))
|
||||||
.then((_) {
|
.then((_) {
|
||||||
setState(() {});
|
setState(() {});
|
||||||
_updateLists();
|
_updateLists();
|
||||||
Scaffold.of(context).showSnackBar(
|
Scaffold.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text('The list was successfully created!'),
|
content: Text('The list was successfully created!'),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,10 +51,10 @@ class HomePageState extends State<HomePage> {
|
||||||
.namespaceService
|
.namespaceService
|
||||||
.create(Namespace(id: null, name: name))
|
.create(Namespace(id: null, name: name))
|
||||||
.then((_) {
|
.then((_) {
|
||||||
_updateNamespaces();
|
_updateNamespaces();
|
||||||
Scaffold.of(context).showSnackBar(SnackBar(
|
Scaffold.of(context).showSnackBar(SnackBar(
|
||||||
content: Text('The namespace was created successfully!'),
|
content: Text('The namespace was created successfully!'),
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,10 +120,10 @@ class HomePageState extends State<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),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
])),
|
])),
|
||||||
|
|
|
@ -26,71 +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:
|
decoration: new InputDecoration(
|
||||||
new InputDecoration(
|
labelText: 'Title',
|
||||||
labelText: 'Title',
|
border: OutlineInputBorder(),
|
||||||
border: OutlineInputBorder(),
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
Padding(
|
||||||
),
|
padding: EdgeInsets.symmetric(vertical: 10.0),
|
||||||
Padding(
|
child: TextFormField(
|
||||||
padding: EdgeInsets.symmetric(vertical: 10.0),
|
maxLines: null,
|
||||||
child: TextFormField(
|
keyboardType: TextInputType.multiline,
|
||||||
maxLines: null,
|
initialValue: widget.list.description,
|
||||||
keyboardType: TextInputType.multiline,
|
onSaved: (description) => _description = description,
|
||||||
initialValue: widget.list.description,
|
validator: (description) {
|
||||||
onSaved: (description) => _description = description,
|
if (description.length > 1000) {
|
||||||
validator: (description) {
|
return 'The description can have a maximum of 1000 characters.';
|
||||||
if (description.length > 1000) {
|
}
|
||||||
return 'The description can have a maximum of 1000 characters.';
|
return null;
|
||||||
}
|
},
|
||||||
return null;
|
decoration: new InputDecoration(
|
||||||
},
|
labelText: 'Description',
|
||||||
decoration: new InputDecoration(
|
border: OutlineInputBorder(),
|
||||||
labelText: 'Description',
|
),
|
||||||
border: OutlineInputBorder(),
|
),
|
||||||
),
|
),
|
||||||
),
|
Builder(
|
||||||
),
|
builder: (context) => Padding(
|
||||||
Builder(
|
padding: EdgeInsets.symmetric(vertical: 10.0),
|
||||||
builder: (context) => Padding(
|
child: FancyButton(
|
||||||
padding: EdgeInsets.symmetric(vertical: 10.0),
|
onPressed: !_loading
|
||||||
child: FancyButton(
|
? () {
|
||||||
onPressed: !_loading ? () {
|
if (_formKey.currentState.validate()) {
|
||||||
if (_formKey.currentState.validate()) {
|
Form.of(context).save();
|
||||||
Form.of(context).save();
|
_saveList(context);
|
||||||
_saveList(context);
|
}
|
||||||
}
|
}
|
||||||
}
|
: null,
|
||||||
: null,
|
child: _loading
|
||||||
child: _loading
|
? CircularProgressIndicator()
|
||||||
? CircularProgressIndicator()
|
: VikunjaButtonText('Save'),
|
||||||
: VikunjaButtonText('Save'),
|
))),
|
||||||
)
|
]),
|
||||||
)
|
),
|
||||||
),
|
|
||||||
]
|
|
||||||
),
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -99,25 +96,24 @@ class _ListEditPageState extends State<ListEditPage> {
|
||||||
setState(() => _loading = true);
|
setState(() => _loading = true);
|
||||||
// FIXME: is there a way we can update the list without creating a new list object?
|
// 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?)
|
// aka updating the existing list we got from context (setters?)
|
||||||
TaskList updatedList = TaskList(
|
TaskList updatedList =
|
||||||
id: widget.list.id, title: _title, description: _description);
|
TaskList(id: widget.list.id, title: _title, description: _description);
|
||||||
|
|
||||||
VikunjaGlobal.of(context).listService.update(updatedList)
|
VikunjaGlobal.of(context).listService.update(updatedList).then((_) {
|
||||||
.then((_) {
|
setState(() => _loading = false);
|
||||||
setState(() => _loading = false);
|
Scaffold.of(context).showSnackBar(SnackBar(
|
||||||
Scaffold.of(context).showSnackBar(SnackBar(
|
content: Text('The list was updated successfully!'),
|
||||||
content: Text('The list was updated successfully!'),
|
));
|
||||||
));
|
}).catchError((err) {
|
||||||
})
|
setState(() => _loading = false);
|
||||||
.catchError((err) {
|
Scaffold.of(context).showSnackBar(
|
||||||
setState(() => _loading = false);
|
SnackBar(
|
||||||
Scaffold.of(context).showSnackBar(
|
content: Text('Something went wrong: ' + err.toString()),
|
||||||
SnackBar(
|
action: SnackBarAction(
|
||||||
content: Text('Something went wrong: ' + err.toString()),
|
label: 'CLOSE',
|
||||||
action: SnackBarAction(
|
onPressed: Scaffold.of(context).hideCurrentSnackBar),
|
||||||
label: 'CLOSE', onPressed: Scaffold.of(context).hideCurrentSnackBar),
|
),
|
||||||
),
|
);
|
||||||
);
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,34 +38,34 @@ class _ListPageState extends State<ListPage> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: new Text(_list.title),
|
title: new Text(_list.title),
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.edit),
|
icon: Icon(Icons.edit),
|
||||||
onPressed: () => Navigator.push(
|
onPressed: () => Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => ListEditPage(
|
builder: (context) => ListEditPage(
|
||||||
list: _list,
|
list: _list,
|
||||||
))))
|
))))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: !this._loading
|
body: !this._loading
|
||||||
? RefreshIndicator(
|
? RefreshIndicator(
|
||||||
child: ListView(
|
child: ListView(
|
||||||
padding: EdgeInsets.symmetric(vertical: 8.0),
|
padding: EdgeInsets.symmetric(vertical: 8.0),
|
||||||
children:
|
children: ListTile.divideTiles(
|
||||||
ListTile.divideTiles(context: context, tiles: _listTasks())
|
context: context, tiles: _listTasks())
|
||||||
.toList(),
|
.toList(),
|
||||||
),
|
),
|
||||||
onRefresh: _loadList,
|
onRefresh: _loadList,
|
||||||
)
|
)
|
||||||
: Center(child: CircularProgressIndicator()),
|
: Center(child: CircularProgressIndicator()),
|
||||||
floatingActionButton: Builder(
|
floatingActionButton: Builder(
|
||||||
builder: (context) => FloatingActionButton(
|
builder: (context) => FloatingActionButton(
|
||||||
onPressed: () => _addItemDialog(context), child: Icon(Icons.add)),
|
onPressed: () => _addItemDialog(context), child: Icon(Icons.add)),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _listTasks() {
|
List<Widget> _listTasks() {
|
||||||
|
|
|
@ -24,86 +24,83 @@ 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'),
|
|
||||||
)),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -137,7 +137,9 @@ class _RegisterPageState extends State<RegisterPage> {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => new AlertDialog(
|
builder: (context) => new AlertDialog(
|
||||||
title: Text('Registration failed! Please check your server url and credentials. ' + ex.toString()),
|
title: Text(
|
||||||
|
'Registration failed! Please check your server url and credentials. ' +
|
||||||
|
ex.toString()),
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
FlatButton(
|
FlatButton(
|
||||||
onPressed: () => Navigator.pop(context),
|
onPressed: () => Navigator.pop(context),
|
||||||
|
|
|
@ -0,0 +1,232 @@
|
||||||
|
# Generated by pub
|
||||||
|
# See https://www.dartlang.org/tools/pub/glossary#lockfile
|
||||||
|
packages:
|
||||||
|
archive:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: archive
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.8"
|
||||||
|
args:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: args
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.5.1"
|
||||||
|
async:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: async
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.8"
|
||||||
|
boolean_selector:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: boolean_selector
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.4"
|
||||||
|
charcode:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: charcode
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.2"
|
||||||
|
collection:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: collection
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.14.11"
|
||||||
|
convert:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: convert
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.1"
|
||||||
|
crypto:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: crypto
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.6"
|
||||||
|
cupertino_icons:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: cupertino_icons
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.2"
|
||||||
|
dart_config:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
path: "."
|
||||||
|
ref: HEAD
|
||||||
|
resolved-ref: a7ed88a4793e094a4d5d5c2d88a89e55510accde
|
||||||
|
url: "https://github.com/MarkOSullivan94/dart_config.git"
|
||||||
|
source: git
|
||||||
|
version: "0.5.0"
|
||||||
|
flutter:
|
||||||
|
dependency: "direct main"
|
||||||
|
description: flutter
|
||||||
|
source: sdk
|
||||||
|
version: "0.0.0"
|
||||||
|
flutter_launcher_icons:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description:
|
||||||
|
name: flutter_launcher_icons
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.6.1"
|
||||||
|
flutter_secure_storage:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_secure_storage
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.1"
|
||||||
|
flutter_test:
|
||||||
|
dependency: "direct dev"
|
||||||
|
description: flutter
|
||||||
|
source: sdk
|
||||||
|
version: "0.0.0"
|
||||||
|
http:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: http
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.12.0"
|
||||||
|
http_parser:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: http_parser
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.1.3"
|
||||||
|
image:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: image
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.7"
|
||||||
|
matcher:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: matcher
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.12.3+1"
|
||||||
|
meta:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: meta
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.6"
|
||||||
|
path:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.6.2"
|
||||||
|
petitparser:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: petitparser
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.1"
|
||||||
|
quiver:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: quiver
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.1"
|
||||||
|
sky_engine:
|
||||||
|
dependency: transitive
|
||||||
|
description: flutter
|
||||||
|
source: sdk
|
||||||
|
version: "0.0.99"
|
||||||
|
source_span:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: source_span
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.4.1"
|
||||||
|
stack_trace:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: stack_trace
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.9.3"
|
||||||
|
stream_channel:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: stream_channel
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.6.8"
|
||||||
|
string_scanner:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: string_scanner
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.4"
|
||||||
|
term_glyph:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: term_glyph
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.0.1"
|
||||||
|
test_api:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: test_api
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.1"
|
||||||
|
typed_data:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: typed_data
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "1.1.6"
|
||||||
|
vector_math:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: vector_math
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.8"
|
||||||
|
xml:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: xml
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "3.3.1"
|
||||||
|
yaml:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: yaml
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.15"
|
||||||
|
sdks:
|
||||||
|
dart: ">=2.0.0 <3.0.0"
|
Reference in New Issue