This commit is contained in:
Christien Rioux 2023-07-24 09:31:51 -04:00
parent 8907ce04ac
commit b7236befd1
8 changed files with 164 additions and 100 deletions

View File

@ -6,13 +6,10 @@
"settings_tooltip": "Settings"
},
"new_account_page": {
"title": "Create a new account",
"titlebar": "Create a new account",
"header": "Account Profile",
"import": "Import an existing account"
},
"new_account_form": {
"name": "Name",
"title": "Title (optional)",
"form_name": "Name",
"form_title": "Title (optional)",
"create": "Create",
"instructions": "This information will be shared with the people you invite to connect with you on VeilidChat."
},

View File

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:animated_theme_switcher/animated_theme_switcher.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
import 'router/router.dart';
import 'package:flutter_translate/flutter_translate.dart';
@ -32,6 +33,7 @@ class VeilidChatApp extends ConsumerWidget {
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
FormBuilderLocalizations.delegate,
localizationDelegate
],
supportedLocales: localizationDelegate.supportedLocales,

View File

@ -1,71 +0,0 @@
import 'package:awesome_extensions/awesome_extensions.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_translate/flutter_translate.dart';
import '../components/default_app_bar.dart';
import '../tools/desktop_control.dart';
class NewAccountForm extends ConsumerStatefulWidget {
const NewAccountForm({super.key});
@override
NewAccountFormState createState() {
return NewAccountFormState();
}
}
class NewAccountFormState extends ConsumerState<NewAccountForm> {
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
children: [
TextFormField(
key: const ValueKey("name"),
autofocus: true,
decoration:
InputDecoration(hintText: translate("new_account_form.name")),
maxLength: 64,
// The validator receives the text that the user has entered.
validator: (value) {
if (value == null || value.isEmpty) {
return 'Name is required';
}
return null;
},
),
TextFormField(
key: const ValueKey("title"),
maxLength: 64,
decoration:
InputDecoration(hintText: translate("new_account_form.title")),
),
Row(children: [
const Spacer(),
Text(translate("new_account_form.instructions"))
.toCenter()
.flexible(flex: 4),
const Spacer(),
]).paddingSymmetric(vertical: 24),
ElevatedButton(
onPressed: () {
// Validate returns true if the form is valid, or false otherwise.
if (_formKey.currentState!.validate()) {
// If the form is valid, display a snackbar. In the real world,
// you'd often call a server or save the information in a database.
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Processing Data')),
);
}
},
child: Text(translate('new_account_form.create')),
).paddingSymmetric(vertical: 16).toCenter(),
],
),
);
}
}

View File

@ -1,37 +1,104 @@
import 'dart:io';
import 'package:awesome_extensions/awesome_extensions.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_translate/flutter_translate.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
import '../components/default_app_bar.dart';
import '../components/new_account_form.dart';
import '../providers/local_accounts.dart';
import '../tools/tools.dart';
class NewAccountPage extends ConsumerWidget {
class NewAccountPage extends ConsumerStatefulWidget {
const NewAccountPage({super.key});
static const path = '/new_account';
@override
Widget build(BuildContext context, WidgetRef ref) {
enableTitleBar(true);
return Scaffold(
resizeToAvoidBottomInset: false,
appBar: DefaultAppBar(context,
title: Text(translate("new_account_page.title"))),
body: Container(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(translate("new_account_page.header"))
.textStyle(context.headlineSmall)
.paddingSymmetric(vertical: 16),
const NewAccountForm().flexible(),
Text(translate("new_account_page.import"))
],
),
));
NewAccountPageState createState() {
return NewAccountPageState();
}
}
class NewAccountPageState extends ConsumerState<NewAccountPage> {
final _formKey = GlobalKey<FormBuilderState>();
late bool isInAsyncCall = false;
Widget _newAccountForm(BuildContext context,
{required Future<void> Function(GlobalKey<FormBuilderState>) onSubmit}) {
return FormBuilder(
key: _formKey,
child: ListView(
children: [
Text(translate("new_account_page.header"))
.textStyle(context.headlineSmall)
.paddingSymmetric(vertical: 16),
FormBuilderTextField(
autofocus: true,
name: 'name',
decoration: InputDecoration(
hintText: translate("new_account_page.form_name")),
maxLength: 64,
// The validator receives the text that the user has entered.
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(),
]),
),
FormBuilderTextField(
name: 'title',
maxLength: 64,
decoration: InputDecoration(
hintText: translate("new_account_page.form_title")),
),
Row(children: [
const Spacer(),
Text(translate("new_account_page.instructions"))
.toCenter()
.flexible(flex: 6),
const Spacer(),
]).paddingSymmetric(vertical: 4),
ElevatedButton(
onPressed: () async {
if (_formKey.currentState?.saveAndValidate() ?? false) {
setState(() {
isInAsyncCall = true;
});
try {
await onSubmit(_formKey);
} finally {
setState(() {
isInAsyncCall = false;
});
}
}
},
child: Text(translate('new_account_page.create')),
).paddingSymmetric(vertical: 4).alignAtCenterRight(),
],
),
);
}
@override
Widget build(BuildContext context) {
enableTitleBar(true);
portraitOnly();
final localAccounts = ref.watch(localAccountsProvider);
return Scaffold(
// resizeToAvoidBottomInset: false,
appBar: DefaultAppBar(context,
title: Text(translate("new_account_page.titlebar"))),
body: _newAccountForm(
context,
onSubmit: (formKey) async {
debugPrint(_formKey.currentState?.value.toString());
FocusScope.of(context).unfocus();
await Future.delayed(Duration(seconds: 5));
},
).paddingSymmetric(horizontal: 24, vertical: 8),
).withModalHUD(context, isInAsyncCall);
}
}

View File

@ -1,6 +1,7 @@
import 'dart:io';
import 'package:window_manager/window_manager.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
Future<void> setupDesktopWindow() async {
if (Platform.isWindows || Platform.isLinux || Platform.isMacOS) {
@ -30,3 +31,17 @@ void enableTitleBar(bool enabled) {
}
}
}
void portraitOnly() {
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
}
void landscapeOnly() {
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeLeft,
DeviceOrientation.landscapeRight,
]);
}

View File

@ -1,4 +1,6 @@
import 'package:flutter/material.dart';
import 'package:blurry_modal_progress_hud/blurry_modal_progress_hud.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
extension BorderExt on Widget {
Container debugBorder() {
@ -7,3 +9,19 @@ extension BorderExt on Widget {
child: this);
}
}
extension ModalProgressExt on Widget {
BlurryModalProgressHUD withModalHUD(BuildContext context, bool isLoading) {
return BlurryModalProgressHUD(
inAsyncCall: isLoading,
blurEffectIntensity: 4,
progressIndicator: SpinKitFoldingCube(
color: Theme.of(context).highlightColor,
size: 90.0,
),
dismissible: false,
opacity: 0.3,
color: Theme.of(context).shadowColor,
child: this);
}
}

View File

@ -81,6 +81,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.1.1"
blurry_modal_progress_hud:
dependency: "direct main"
description:
name: blurry_modal_progress_hud
sha256: "01027921b499fc65c97682b4b9d1c4dd2fe7cfb30d5be5fb3f6518d729dfd1e3"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
boolean_selector:
dependency: transitive
description:
@ -382,6 +390,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.3.1"
flutter_form_builder:
dependency: "direct main"
description:
name: flutter_form_builder
sha256: e828c11156d75fc668da1d8e7ddc2311ea8368f023fd28a7c7c126c8b903c5d6
url: "https://pub.dev"
source: hosted
version: "9.1.0"
flutter_hooks:
dependency: "direct main"
description:
@ -419,6 +435,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.3.6"
flutter_spinkit:
dependency: "direct main"
description:
name: flutter_spinkit
sha256: b39c753e909d4796906c5696a14daf33639a76e017136c8d82bf3e620ce5bb8e
url: "https://pub.dev"
source: hosted
version: "5.2.0"
flutter_svg:
dependency: "direct main"
description:
@ -445,6 +469,14 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
form_builder_validators:
dependency: "direct main"
description:
name: form_builder_validators
sha256: e04998b1597d76a51da7f009ed3b2f12d4173f13e146e8744fd2453e8595a2c9
url: "https://pub.dev"
source: hosted
version: "9.0.0"
freezed:
dependency: "direct dev"
description:

View File

@ -45,6 +45,10 @@ dependencies:
circular_profile_avatar: ^2.0.5
badges: ^3.1.1
awesome_extensions: ^2.0.9
flutter_form_builder: ^9.1.0
form_builder_validators: ^9.0.0
blurry_modal_progress_hud: ^1.1.0
flutter_spinkit: ^5.2.0
dev_dependencies:
flutter_test: