mirror of
https://github.com/mitchell/selfpass.git
synced 2025-12-15 13:47:21 +00:00
Added new config screen and buttons for navigation
This commit is contained in:
parent
d0505a4a58
commit
af8834f7bd
8 changed files with 267 additions and 84 deletions
|
|
@ -3,7 +3,7 @@ import 'package:provider/provider.dart';
|
|||
|
||||
import '../types/abstracts.dart';
|
||||
|
||||
import '../widgets/obfuscated_text_field.dart';
|
||||
import '../widgets/text_field.dart';
|
||||
|
||||
class Authentication extends StatefulWidget {
|
||||
@override
|
||||
|
|
@ -11,9 +11,10 @@ class Authentication extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _AuthenticationState extends State<Authentication> {
|
||||
final TextEditingController _passwordController = TextEditingController();
|
||||
final TextEditingController _confirmController = TextEditingController();
|
||||
bool _invalid = false;
|
||||
bool _passesDontMatch = false;
|
||||
String _masterpass;
|
||||
ConfigRepo _config;
|
||||
Future<bool> _passwordIsSet;
|
||||
|
||||
|
|
@ -21,14 +22,11 @@ class _AuthenticationState extends State<Authentication> {
|
|||
didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
_config = Provider.of<ConfigRepo>(context);
|
||||
_passwordIsSet = _config.passwordSet;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_passwordIsSet == null) {
|
||||
_passwordIsSet = _config.passwordSet;
|
||||
}
|
||||
|
||||
return CupertinoPageScaffold(
|
||||
child: Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 50.0),
|
||||
|
|
@ -36,30 +34,34 @@ class _AuthenticationState extends State<Authentication> {
|
|||
future: _passwordIsSet,
|
||||
builder: (BuildContext context, AsyncSnapshot<bool> snapshot) =>
|
||||
snapshot.connectionState == ConnectionState.done
|
||||
? Column(children: _buildColumnChildren(snapshot.data))
|
||||
: Container(),
|
||||
? Column(
|
||||
children: _buildColumnChildren(context, snapshot.data))
|
||||
: Center(child: CupertinoActivityIndicator()),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> _buildColumnChildren(bool passwordIsSet) {
|
||||
List<Widget> _buildColumnChildren(BuildContext context, bool passwordIsSet) {
|
||||
List<Widget> children = [
|
||||
const Spacer(flex: 4),
|
||||
const Flexible(child: Text('Master password:')),
|
||||
Flexible(
|
||||
child: ObfuscatedTextField(
|
||||
onSubmittedBuilder:
|
||||
_buildMasterpassSubmittedBuilder(passwordIsSet)),
|
||||
child: TextField(
|
||||
obscure: true,
|
||||
autofocus: true,
|
||||
controller: _passwordController,
|
||||
),
|
||||
),
|
||||
];
|
||||
|
||||
if (!passwordIsSet) {
|
||||
children.add(const Flexible(child: Text('Re-enter password:')));
|
||||
children.add(Flexible(
|
||||
child: ObfuscatedTextField(
|
||||
onSubmittedBuilder:
|
||||
_buildConfirmPassSubmittedBuilder(passwordIsSet)),
|
||||
child: TextField(
|
||||
obscure: true,
|
||||
controller: _confirmController,
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
|
|
@ -81,6 +83,11 @@ class _AuthenticationState extends State<Authentication> {
|
|||
));
|
||||
}
|
||||
|
||||
children.add(CupertinoButton(
|
||||
child: Text('Enter'),
|
||||
onPressed: _buildSubmitPressedBuilder(context),
|
||||
));
|
||||
|
||||
if (_passesDontMatch) {
|
||||
children.add(const Spacer(flex: 1));
|
||||
} else if (_invalid || !passwordIsSet) {
|
||||
|
|
@ -92,40 +99,31 @@ class _AuthenticationState extends State<Authentication> {
|
|||
return children;
|
||||
}
|
||||
|
||||
OnSubmittedBuilder _buildMasterpassSubmittedBuilder(bool passwordIsSet) {
|
||||
return (BuildContext context) {
|
||||
return (String pass) async {
|
||||
if (passwordIsSet) {
|
||||
if (await _config.matchesPasswordHash(pass)) {
|
||||
Navigator.of(context).pushReplacementNamed('/home',
|
||||
arguments: await _config.connectionConfig);
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState(() => _invalid = true);
|
||||
VoidCallback _buildSubmitPressedBuilder(BuildContext context) {
|
||||
return () async {
|
||||
if (await _passwordIsSet) {
|
||||
if (await _config.matchesPasswordHash(_passwordController.text)) {
|
||||
Navigator.of(context).pushReplacementNamed(
|
||||
'/home',
|
||||
arguments: await _config.connectionConfig,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
_masterpass = pass;
|
||||
};
|
||||
};
|
||||
}
|
||||
this.setState(() => _invalid = true);
|
||||
return;
|
||||
}
|
||||
|
||||
OnSubmittedBuilder _buildConfirmPassSubmittedBuilder(bool passwordIsSet) {
|
||||
return (BuildContext context) {
|
||||
return (String pass) async {
|
||||
if (pass != _masterpass) {
|
||||
this.setState(() {
|
||||
_passesDontMatch = true;
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (_passwordController.text != _confirmController.text) {
|
||||
this.setState(() {
|
||||
_passesDontMatch = true;
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
_config.setPassword(_masterpass);
|
||||
_passwordIsSet = Future<bool>.value(true);
|
||||
Navigator.of(context).pushReplacementNamed('/home',
|
||||
arguments: await _config.connectionConfig);
|
||||
};
|
||||
_config.setPassword(_passwordController.text);
|
||||
_passwordIsSet = Future<bool>.value(true);
|
||||
Navigator.of(context).pushReplacementNamed('/config');
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
124
lib/screens/config.dart
Normal file
124
lib/screens/config.dart
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../types/abstracts.dart';
|
||||
import '../types/connection_config.dart';
|
||||
|
||||
import '../widgets/text_field.dart';
|
||||
|
||||
class Config extends StatefulWidget {
|
||||
final ConnectionConfig connectionConfig;
|
||||
|
||||
const Config(this.connectionConfig, {Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State createState() => _ConfigState(this.connectionConfig);
|
||||
}
|
||||
|
||||
class _ConfigState extends State<Config> {
|
||||
TextEditingController _hostController;
|
||||
TextEditingController _caCertController;
|
||||
TextEditingController _certController;
|
||||
TextEditingController _privateCertController;
|
||||
ConnectionConfig _connectionConfig;
|
||||
ConfigRepo _config;
|
||||
|
||||
_ConfigState(this._connectionConfig) {
|
||||
if (_connectionConfig == null) {
|
||||
_connectionConfig = ConnectionConfig();
|
||||
}
|
||||
|
||||
_hostController = TextEditingController(text: _connectionConfig.host);
|
||||
_certController =
|
||||
TextEditingController(text: _connectionConfig.certificate);
|
||||
_caCertController =
|
||||
TextEditingController(text: _connectionConfig.caCertificate);
|
||||
_privateCertController =
|
||||
TextEditingController(text: _connectionConfig.privateCertificate);
|
||||
}
|
||||
|
||||
@override
|
||||
didChangeDependencies() async {
|
||||
super.didChangeDependencies();
|
||||
|
||||
_config = Provider.of<ConfigRepo>(context);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CupertinoPageScaffold(
|
||||
navigationBar: _connectionConfig.host == null
|
||||
? null
|
||||
: CupertinoNavigationBar(
|
||||
trailing: GestureDetector(
|
||||
onTap: _buildResetAllHandler(context),
|
||||
child: Text('Reset App',
|
||||
style: TextStyle(color: CupertinoColors.destructiveRed)),
|
||||
),
|
||||
),
|
||||
child: Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 50.0),
|
||||
child: Column(children: [
|
||||
Spacer(flex: 3),
|
||||
Flexible(child: Text('Host:')),
|
||||
Flexible(child: TextField(maxLines: 1, controller: _hostController)),
|
||||
Flexible(child: Text('CA certificate:')),
|
||||
Flexible(
|
||||
child: TextField(maxLines: 3, controller: _caCertController)),
|
||||
Flexible(child: Text('Client certificate:')),
|
||||
Flexible(child: TextField(maxLines: 3, controller: _certController)),
|
||||
Flexible(child: Text('Private certificate:')),
|
||||
Flexible(
|
||||
child:
|
||||
TextField(maxLines: 3, controller: _privateCertController)),
|
||||
CupertinoButton(
|
||||
child: Text('Save'), onPressed: _makeSaveOnPressed(context))
|
||||
]),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
GestureTapCallback _buildResetAllHandler(BuildContext context) {
|
||||
return () {
|
||||
showCupertinoDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) => CupertinoAlertDialog(
|
||||
content: Text('Are you sure?'),
|
||||
actions: [
|
||||
CupertinoDialogAction(
|
||||
isDefaultAction: true,
|
||||
child: Text('Cancel'),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
CupertinoDialogAction(
|
||||
isDestructiveAction: true,
|
||||
child: Text('Confirm'),
|
||||
onPressed: () async {
|
||||
_connectionConfig = null;
|
||||
await _config.deleteAll();
|
||||
Navigator.of(context)
|
||||
.pushNamedAndRemoveUntil('/', ModalRoute.withName('/'));
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
VoidCallback _makeSaveOnPressed(BuildContext context) {
|
||||
return () async {
|
||||
final connConfig = ConnectionConfig(
|
||||
host: _hostController.text,
|
||||
certificate: _certController.text,
|
||||
caCertificate: _caCertController.text,
|
||||
privateCertificate: _privateCertController.text,
|
||||
);
|
||||
|
||||
await _config.setConnectionConfig(connConfig);
|
||||
|
||||
Navigator.of(context)
|
||||
.pushReplacementNamed('/home', arguments: connConfig);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -13,20 +13,21 @@ class Home extends StatefulWidget {
|
|||
|
||||
class _HomeState extends State<Home> {
|
||||
CredentialsRepo _client;
|
||||
ConfigRepo _config;
|
||||
Future<List<Metadata>> _metadatas;
|
||||
|
||||
@override
|
||||
didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
|
||||
_config = Provider.of<ConfigRepo>(context);
|
||||
|
||||
_client = Provider.of<CredentialsRepo>(context);
|
||||
_metadatas = _client.getAllMetadata('').toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_metadatas == null) {
|
||||
_metadatas = _client.getAllMetadata('').toList();
|
||||
}
|
||||
|
||||
return CupertinoPageScaffold(
|
||||
child: FutureBuilder<List<Metadata>>(
|
||||
future: _metadatas,
|
||||
|
|
@ -35,9 +36,21 @@ class _HomeState extends State<Home> {
|
|||
(snapshot.connectionState == ConnectionState.done)
|
||||
? TappableTextList(
|
||||
tappableText: _buildTappableText(context, snapshot.data))
|
||||
: Container(),
|
||||
: Center(child: CupertinoActivityIndicator()),
|
||||
),
|
||||
navigationBar: CupertinoNavigationBar(
|
||||
leading: GestureDetector(
|
||||
child: Align(
|
||||
child: Text('Lock',
|
||||
style: TextStyle(color: CupertinoColors.destructiveRed)),
|
||||
alignment: Alignment(-0.9, 0)),
|
||||
onTap: _makeLockOnTapHandler(context),
|
||||
),
|
||||
trailing: GestureDetector(
|
||||
child: Icon(CupertinoIcons.gear),
|
||||
onTap: _makeConfigOnTapHandler(context),
|
||||
),
|
||||
),
|
||||
navigationBar: CupertinoNavigationBar(),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -69,4 +82,13 @@ class _HomeState extends State<Home> {
|
|||
|
||||
return tappableText;
|
||||
}
|
||||
|
||||
GestureTapCallback _makeLockOnTapHandler(BuildContext context) {
|
||||
return () => Navigator.of(context).pushReplacementNamed('/');
|
||||
}
|
||||
|
||||
GestureTapCallback _makeConfigOnTapHandler(BuildContext context) {
|
||||
return () async => Navigator.of(context)
|
||||
.pushNamed('/config', arguments: await _config.connectionConfig);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue