Signup login updates (#1324)
* fix: stop signup/login loading on dispose * fix: if user signs up with SSO, make them agree to TOS on language/avatar settings page
This commit is contained in:
parent
6b24b68239
commit
0368ce3ea7
9 changed files with 110 additions and 18 deletions
|
|
@ -72,6 +72,16 @@ class LoginController extends State<Login> {
|
|||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
usernameController.dispose();
|
||||
passwordController.dispose();
|
||||
loading = false;
|
||||
usernameError = null;
|
||||
passwordError = null;
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _setStateOnTextChange(String? oldText, String newText) {
|
||||
if ((oldText == null || oldText.isEmpty) && (newText.isNotEmpty)) {
|
||||
setState(() {});
|
||||
|
|
|
|||
|
|
@ -55,6 +55,30 @@ class PangeaSsoButton extends StatefulWidget {
|
|||
class PangeaSsoButtonState extends State<PangeaSsoButton> {
|
||||
bool _loading = false;
|
||||
String? _error;
|
||||
AppLifecycleListener? _listener;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_listener = AppLifecycleListener(
|
||||
onStateChange: _onAppLifecycleChange,
|
||||
);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
// when the SSO login launches, stop the loading indicator
|
||||
void _onAppLifecycleChange(AppLifecycleState state) {
|
||||
if ((state == AppLifecycleState.inactive ||
|
||||
state == AppLifecycleState.hidden) &&
|
||||
_loading) {
|
||||
setState(() => _loading = false);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_listener?.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _runSSOLogin() async {
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ class FullWidthButtonState extends State<FullWidthButton> {
|
|||
onPressed: widget.onPressed,
|
||||
borderRadius: BorderRadius.circular(36),
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
isShadow: true,
|
||||
child: Container(
|
||||
// internal padding
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
|
|
|
|||
|
|
@ -55,6 +55,16 @@ class SignupPageController extends State<SignupPage> {
|
|||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
usernameController.dispose();
|
||||
passwordController.dispose();
|
||||
emailController.dispose();
|
||||
loading = false;
|
||||
error = null;
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
bool get enableSignUp =>
|
||||
!loading &&
|
||||
isTnCChecked &&
|
||||
|
|
|
|||
|
|
@ -44,7 +44,11 @@ class SignupWithEmailView extends StatelessWidget {
|
|||
validator: controller.password1TextFieldValidator,
|
||||
controller: controller.passwordController,
|
||||
),
|
||||
TosCheckbox(controller),
|
||||
TosCheckbox(
|
||||
controller.isTnCChecked,
|
||||
controller.onTncChange,
|
||||
error: controller.signupError,
|
||||
),
|
||||
FullWidthButton(
|
||||
title: L10n.of(context).signUp,
|
||||
icon: PangeaLogoSvg(
|
||||
|
|
|
|||
|
|
@ -29,12 +29,15 @@ class UserSettingsState extends State<UserSettingsPage> {
|
|||
|
||||
String? selectedLanguageError;
|
||||
String? profileCreationError;
|
||||
String? tncError;
|
||||
|
||||
bool loading = false;
|
||||
|
||||
Uint8List? avatar;
|
||||
String? _selectedFilePath;
|
||||
|
||||
bool isTncChecked = false;
|
||||
|
||||
List<String> avatarPaths = const [
|
||||
"assets/pangea/Avatar_1.png",
|
||||
"assets/pangea/Avatar_2.png",
|
||||
|
|
@ -52,7 +55,6 @@ class UserSettingsState extends State<UserSettingsPage> {
|
|||
: PangeaLanguage.byLangCode(systemLangCode);
|
||||
}
|
||||
|
||||
bool canSetDisplayName = false;
|
||||
TextEditingController displayNameController = TextEditingController();
|
||||
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
|
||||
|
||||
|
|
@ -61,19 +63,31 @@ class UserSettingsState extends State<UserSettingsPage> {
|
|||
super.initState();
|
||||
selectedTargetLanguage = _pangeaController.languageController.userL2;
|
||||
selectedAvatarPath = avatarPaths.first;
|
||||
final loginTypeEntry =
|
||||
_pangeaController.pStoreService.read(PLocalKey.loginType);
|
||||
if (loginTypeEntry is String && loginTypeEntry == 'sso') {
|
||||
canSetDisplayName = true;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
displayNameController.dispose();
|
||||
loading = false;
|
||||
selectedLanguageError = null;
|
||||
profileCreationError = null;
|
||||
tncError = null;
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
bool get isSSOSignup {
|
||||
final loginTypeEntry =
|
||||
_pangeaController.pStoreService.read(PLocalKey.loginType);
|
||||
return loginTypeEntry is String && loginTypeEntry == 'sso';
|
||||
}
|
||||
|
||||
void setTncChecked(bool? value) {
|
||||
setState(() {
|
||||
isTncChecked = value ?? false;
|
||||
tncError = null;
|
||||
});
|
||||
}
|
||||
|
||||
void setSelectedTargetLanguage(LanguageModel? language) {
|
||||
setState(() {
|
||||
selectedTargetLanguage = language;
|
||||
|
|
@ -150,7 +164,11 @@ class UserSettingsState extends State<UserSettingsPage> {
|
|||
}
|
||||
|
||||
Future<void> createUserInPangea() async {
|
||||
setState(() => profileCreationError = null);
|
||||
setState(() {
|
||||
profileCreationError = null;
|
||||
selectedLanguageError = null;
|
||||
tncError = null;
|
||||
});
|
||||
|
||||
if (selectedTargetLanguage == null) {
|
||||
setState(() {
|
||||
|
|
@ -159,6 +177,13 @@ class UserSettingsState extends State<UserSettingsPage> {
|
|||
return;
|
||||
}
|
||||
|
||||
if (isSSOSignup && !isTncChecked) {
|
||||
setState(() {
|
||||
tncError = L10n.of(context).pleaseAgreeToTOS;
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!formKey.currentState!.validate()) return;
|
||||
setState(() => loading = true);
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import 'package:fluffychat/config/app_config.dart';
|
|||
import 'package:fluffychat/pangea/pages/sign_up/full_width_button.dart';
|
||||
import 'package:fluffychat/pangea/pages/sign_up/pangea_login_scaffold.dart';
|
||||
import 'package:fluffychat/pangea/pages/sign_up/user_settings.dart';
|
||||
import 'package:fluffychat/pangea/widgets/signup/tos_checkbox.dart';
|
||||
import 'package:fluffychat/pangea/widgets/user_settings/p_language_dropdown.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
|
|
@ -93,7 +94,7 @@ class UserSettingsView extends StatelessWidget {
|
|||
error: controller.selectedLanguageError,
|
||||
),
|
||||
),
|
||||
if (controller.canSetDisplayName)
|
||||
if (controller.isSSOSignup)
|
||||
FullWidthTextField(
|
||||
hintText: L10n.of(context).username,
|
||||
validator: (username) {
|
||||
|
|
@ -104,6 +105,12 @@ class UserSettingsView extends StatelessWidget {
|
|||
},
|
||||
controller: controller.displayNameController,
|
||||
),
|
||||
if (controller.isSSOSignup)
|
||||
TosCheckbox(
|
||||
controller.isTncChecked,
|
||||
controller.setTncChecked,
|
||||
error: controller.tncError,
|
||||
),
|
||||
FullWidthButton(
|
||||
title: L10n.of(context).letsStart,
|
||||
onPressed: controller.selectedTargetLanguage != null
|
||||
|
|
@ -111,7 +118,8 @@ class UserSettingsView extends StatelessWidget {
|
|||
: null,
|
||||
error: controller.profileCreationError,
|
||||
loading: controller.loading,
|
||||
enabled: controller.selectedTargetLanguage != null,
|
||||
enabled: controller.selectedTargetLanguage != null &&
|
||||
(!controller.isSSOSignup || controller.isTncChecked),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ class PressableButton extends StatefulWidget {
|
|||
final Stream? triggerAnimation;
|
||||
final ClickPlayer? clickPlayer;
|
||||
|
||||
final bool? isShadow;
|
||||
|
||||
const PressableButton({
|
||||
required this.borderRadius,
|
||||
required this.child,
|
||||
|
|
@ -25,6 +27,7 @@ class PressableButton extends StatefulWidget {
|
|||
this.depressed = false,
|
||||
this.triggerAnimation,
|
||||
this.clickPlayer,
|
||||
this.isShadow,
|
||||
super.key,
|
||||
});
|
||||
|
||||
|
|
@ -53,6 +56,7 @@ class PressableButtonState extends State<PressableButton>
|
|||
);
|
||||
_tweenAnimation =
|
||||
Tween<double>(begin: 0, end: widget.buttonHeight).animate(_controller);
|
||||
|
||||
if (!_depressed) {
|
||||
_triggerAnimationSubscription = widget.triggerAnimation?.listen((_) {
|
||||
_animationCompleter = Completer<void>();
|
||||
|
|
@ -77,6 +81,9 @@ class PressableButtonState extends State<PressableButton>
|
|||
}
|
||||
}
|
||||
|
||||
bool get _isShadow =>
|
||||
widget.isShadow ?? Theme.of(context).brightness == Brightness.light;
|
||||
|
||||
void _onTapDown(TapDownDetails? details) {
|
||||
if (_depressed) return;
|
||||
_animationCompleter = Completer<void>();
|
||||
|
|
@ -138,7 +145,7 @@ class PressableButtonState extends State<PressableButton>
|
|||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Color.alphaBlend(
|
||||
Theme.of(context).brightness == Brightness.light
|
||||
_isShadow
|
||||
? Colors.black.withOpacity(0.25)
|
||||
: Colors.white.withOpacity(0.25),
|
||||
widget.color,
|
||||
|
|
|
|||
|
|
@ -2,16 +2,19 @@
|
|||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'package:fluffychat/pangea/pages/sign_up/signup.dart';
|
||||
import 'package:fluffychat/utils/url_launcher.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
|
||||
class TosCheckbox extends StatefulWidget {
|
||||
final SignupPageController controller;
|
||||
final bool value;
|
||||
final Function(bool?) onChange;
|
||||
final String? error;
|
||||
|
||||
const TosCheckbox(
|
||||
this.controller, {
|
||||
this.value,
|
||||
this.onChange, {
|
||||
this.error,
|
||||
super.key,
|
||||
});
|
||||
|
||||
|
|
@ -57,12 +60,12 @@ class TosCheckboxState extends State<TosCheckbox>
|
|||
),
|
||||
AnimatedSize(
|
||||
duration: FluffyThemes.animationDuration,
|
||||
child: widget.controller.signupError == null
|
||||
child: widget.error == null
|
||||
? const SizedBox.shrink()
|
||||
: Padding(
|
||||
padding: const EdgeInsets.only(top: 4, left: 30),
|
||||
child: Text(
|
||||
widget.controller.signupError!,
|
||||
widget.error!,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
fontSize: 12,
|
||||
|
|
@ -74,9 +77,9 @@ class TosCheckboxState extends State<TosCheckbox>
|
|||
),
|
||||
),
|
||||
Checkbox(
|
||||
value: widget.controller.isTnCChecked,
|
||||
value: widget.value,
|
||||
activeColor: Theme.of(context).colorScheme.primary,
|
||||
onChanged: widget.controller.onTncChange,
|
||||
onChanged: widget.onChange,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue