diff --git a/lib/pages/add_account.dart b/lib/pages/add_account.dart new file mode 100644 index 0000000..4ccde0f --- /dev/null +++ b/lib/pages/add_account.dart @@ -0,0 +1,167 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:lemmur/hooks/stores.dart'; +import 'package:lemmur/pages/add_instance.dart'; + +import '../widgets/bottom_modal.dart'; + +class AddAccountPage extends HookWidget { + final String instanceUrl; + + const AddAccountPage({@required this.instanceUrl}) + : assert(instanceUrl != null); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + + final usernameController = useTextEditingController(); + final passwordController = useTextEditingController(); + useValueListenable(usernameController); + useValueListenable(passwordController); + final accountsStore = useAccountsStore(); + + final loading = useState(false); + final selectedInstance = useState(instanceUrl); + + selectInstance() async { + final val = await showModalBottomSheet( + backgroundColor: Colors.transparent, + isScrollControlled: true, + context: context, + builder: (context) => BottomModal( + title: 'select instance', + child: Column(children: [ + for (final i in accountsStore.users.keys) + RadioListTile( + value: i, + groupValue: selectedInstance.value, + onChanged: (val) { + Navigator.of(context).pop(val); + }, + title: Text(i), + ), + ListTile( + leading: Padding( + padding: const EdgeInsets.all(8), + child: Icon(Icons.add), + ), + title: Text('Add instance'), + onTap: () async { + final val = await showCupertinoModalPopup( + context: context, + builder: (context) => AddInstancePage(), + ); + Navigator.of(context).pop(val); + }, + ), + ]), + ), + ); + if (val != null) { + selectedInstance.value = val; + } + } + + handleOnAdd() async { + try { + loading.value = true; + await accountsStore.addAccount( + instanceUrl, + usernameController.text, + passwordController.text, + ); + } on Exception catch (err) { + Scaffold.of(context).showSnackBar(SnackBar( + content: Text(err.toString()), + )); + } + loading.value = false; + Navigator.of(context).pop(); + } + + return Scaffold( + appBar: AppBar( + leading: CloseButton(), + actionsIconTheme: theme.iconTheme, + iconTheme: theme.iconTheme, + textTheme: theme.textTheme, + title: Text('Add account'), + backgroundColor: theme.canvasColor, + shadowColor: Colors.transparent, + ), + body: Padding( + padding: const EdgeInsets.all(15), + child: ListView( + children: [ + SizedBox(height: 150), + FlatButton( + onPressed: selectInstance, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text(selectedInstance.value), + Icon(Icons.arrow_drop_down), + ], + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + ), + TextField( + autofocus: true, + controller: usernameController, + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(13), + ), + labelText: 'Username or email', + ), + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(10), + // ), + ), + const SizedBox(height: 5), + TextField( + controller: passwordController, + obscureText: true, + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(13), + ), + labelText: 'Password', + ), + ), + Row( + // mainAxisAlignment: MainAxisAlignment.end, + children: [ + FlatButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + child: Text('Cancel'), + onPressed: () => Navigator.of(context).pop(), + ), + Spacer(), + RaisedButton( + color: theme.accentColor, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + child: !loading.value + ? Text('Add') + : CircularProgressIndicator(), + onPressed: usernameController.text.isEmpty || + passwordController.text.isEmpty + ? null + : handleOnAdd, + ), + ], + ) + ], + ), + ), + ); + } +} diff --git a/lib/pages/add_instance.dart b/lib/pages/add_instance.dart new file mode 100644 index 0000000..acf9db1 --- /dev/null +++ b/lib/pages/add_instance.dart @@ -0,0 +1,78 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; + +import '../hooks/stores.dart'; + +class AddInstancePage extends HookWidget { + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + final instanceController = useTextEditingController(); + useValueListenable(instanceController); + final accountsStore = useAccountsStore(); + + final loading = useState(false); + + handleOnAdd() async { + try { + loading.value = true; + await accountsStore.addInstance(instanceController.text); + Navigator.of(context).pop(instanceController.text); + } on Exception catch (err) { + Scaffold.of(context).showSnackBar(SnackBar( + content: Text(err.toString()), + )); + } + loading.value = false; + Navigator.of(context).pop(); + } + + return Scaffold( + appBar: AppBar( + backgroundColor: theme.scaffoldBackgroundColor, + shadowColor: Colors.transparent, + iconTheme: theme.iconTheme, + leading: CloseButton(), + actionsIconTheme: theme.iconTheme, + textTheme: theme.textTheme, + title: Text('Add instance'), + ), + body: Padding( + padding: const EdgeInsets.all(15), + child: ListView( + children: [ + if (false) + CachedNetworkImage(height: 150, width: 150) + else + SizedBox(height: 150), + TextField( + autofocus: true, + controller: instanceController, + decoration: InputDecoration( + border: OutlineInputBorder(), + labelText: 'instance url', + ), + ), + Row( + children: [ + FlatButton( + child: Text('Cancel'), + onPressed: () => Navigator.of(context).pop(), + ), + Spacer(), + RaisedButton( + child: !loading.value + ? Text('Add') + : CircularProgressIndicator(), + onPressed: + instanceController.text.isEmpty ? null : handleOnAdd, + ), + ], + ) + ], + ), + ), + ); + } +} diff --git a/lib/pages/settings.dart b/lib/pages/settings.dart index b5c9181..5cc7461 100644 --- a/lib/pages/settings.dart +++ b/lib/pages/settings.dart @@ -5,6 +5,8 @@ import 'package:flutter_mobx/flutter_mobx.dart'; import '../hooks/stores.dart'; import '../util/goto.dart'; +import 'add_account.dart'; +import 'add_instance.dart'; class SettingsPage extends StatelessWidget { @override @@ -102,11 +104,8 @@ class AccountsConfigPage extends HookWidget { ), floatingActionButton: FloatingActionButton( onPressed: () { - showDialog( - context: context, - builder: (_) => - _AccountsConfigAddInstanceDialog(scaffoldKey: _scaffoldKey), - ); + showCupertinoModalPopup( + context: context, builder: (_) => AddInstancePage()); }, child: Icon(Icons.add), ), @@ -139,13 +138,9 @@ class AccountsConfigPage extends HookWidget { leading: Icon(Icons.add), title: Text('Add account'), onTap: () { - showDialog( - context: context, - builder: (_) => _AccountsConfigAddAccountDialog( - scaffoldKey: _scaffoldKey, - instanceUrl: entry.key, - ), - ); + showCupertinoModalPopup( + context: context, + builder: (_) => AddAccountPage(instanceUrl: entry.key)); }, ), ] @@ -157,135 +152,6 @@ class AccountsConfigPage extends HookWidget { } } -class _AccountsConfigAddInstanceDialog extends HookWidget { - final GlobalKey scaffoldKey; - - const _AccountsConfigAddInstanceDialog({@required this.scaffoldKey}) - : assert(scaffoldKey != null); - - @override - Widget build(BuildContext context) { - final instanceController = useTextEditingController(); - useValueListenable(instanceController); - final accountsStore = useAccountsStore(); - - final loading = useState(false); - - handleOnAdd() async { - try { - loading.value = true; - await accountsStore.addInstance(instanceController.text); - scaffoldKey.currentState.hideCurrentSnackBar(); - } on Exception catch (err) { - scaffoldKey.currentState.showSnackBar(SnackBar( - content: Text(err.toString()), - )); - } - loading.value = false; - Navigator.of(context).pop(); - } - - return AlertDialog( - title: Text('Add instance'), - content: TextField( - autofocus: true, - controller: instanceController, - decoration: InputDecoration( - border: OutlineInputBorder(), - labelText: 'Instance url', - ), - ), - actions: [ - FlatButton( - child: Text('Cancel'), - onPressed: () => Navigator.of(context).pop(), - ), - FlatButton( - child: !loading.value ? Text('Add') : CircularProgressIndicator(), - onPressed: instanceController.text.isEmpty ? null : handleOnAdd, - ), - ], - ); - } -} - -class _AccountsConfigAddAccountDialog extends HookWidget { - final GlobalKey scaffoldKey; - final String instanceUrl; - - const _AccountsConfigAddAccountDialog( - {@required this.scaffoldKey, @required this.instanceUrl}) - : assert(scaffoldKey != null), - assert(instanceUrl != null); - - @override - Widget build(BuildContext context) { - final usernameController = useTextEditingController(); - final passwordController = useTextEditingController(); - useValueListenable(usernameController); - useValueListenable(passwordController); - final accountsStore = useAccountsStore(); - - final loading = useState(false); - - handleOnAdd() async { - try { - loading.value = true; - await accountsStore.addAccount( - instanceUrl, - usernameController.text, - passwordController.text, - ); - } on Exception catch (err) { - scaffoldKey.currentState.showSnackBar(SnackBar( - content: Text(err.toString()), - )); - } - loading.value = false; - Navigator.of(context).pop(); - } - - return AlertDialog( - title: Text('Add account'), - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - TextField( - autofocus: true, - controller: usernameController, - decoration: InputDecoration( - border: OutlineInputBorder(), - labelText: 'Username or email', - ), - ), - const SizedBox(height: 5), - TextField( - controller: passwordController, - obscureText: true, - decoration: InputDecoration( - border: OutlineInputBorder(), - labelText: 'Password', - ), - ), - ], - ), - actions: [ - FlatButton( - child: Text('Cancel'), - onPressed: () => Navigator.of(context).pop(), - ), - FlatButton( - child: !loading.value ? Text('Add') : CircularProgressIndicator(), - onPressed: - usernameController.text.isEmpty || passwordController.text.isEmpty - ? null - : handleOnAdd, - ), - ], - ); - } -} - class _SectionHeading extends StatelessWidget { final String text;