1
0
Fork 0
mirror of https://github.com/immich-app/immich.git synced 2025-01-01 08:31:59 +00:00

improve login ux (#2004)

removed animated switchers to resolve issue with flutter/issues/120874
This commit is contained in:
martyfuhry 2023-03-15 15:38:26 -04:00 committed by GitHub
parent 3a1d5de742
commit 08ed71e51e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 134 additions and 132 deletions

View file

@ -242,5 +242,6 @@
"permission_onboarding_go_to_settings": "Go to settings", "permission_onboarding_go_to_settings": "Go to settings",
"permission_onboarding_permission_limited": "Permission limited. To let Immich backup and manage your entire gallery collection, grant photo and video permissions in Settings.", "permission_onboarding_permission_limited": "Permission limited. To let Immich backup and manage your entire gallery collection, grant photo and video permissions in Settings.",
"permission_onboarding_continue_anyway": "Continue anyway", "permission_onboarding_continue_anyway": "Continue anyway",
"permission_onboarding_log_out": "Log out" "permission_onboarding_log_out": "Log out",
"login_form_next_button": "Next"
} }

View file

@ -57,13 +57,13 @@ class LoginForm extends HookConsumerWidget {
msg: "login_form_server_empty".tr(), msg: "login_form_server_empty".tr(),
toastType: ToastType.error, toastType: ToastType.error,
); );
return false; return false;
} }
try { try {
isLoadingServer.value = true; isLoadingServer.value = true;
final endpoint = final endpoint =
await apiService.resolveAndSetEndpoint(serverUrl); await apiService.resolveAndSetEndpoint(serverUrl);
final loginConfig = await apiService.oAuthApi.generateConfig( final loginConfig = await apiService.oAuthApi.generateConfig(
@ -96,7 +96,7 @@ class LoginForm extends HookConsumerWidget {
isOauthEnable.value = false; isOauthEnable.value = false;
isLoadingServer.value = false; isLoadingServer.value = false;
return false; return false;
} }
isLoadingServer.value = false; isLoadingServer.value = false;
return true; return true;
@ -166,7 +166,6 @@ class LoginForm extends HookConsumerWidget {
} }
} }
oAuthLogin() async { oAuthLogin() async {
var oAuthService = ref.watch(oAuthServiceProvider); var oAuthService = ref.watch(oAuthServiceProvider);
ref.watch(assetProvider.notifier).clearAllAsset(); ref.watch(assetProvider.notifier).clearAllAsset();
@ -230,151 +229,153 @@ class LoginForm extends HookConsumerWidget {
} }
buildSelectServer() { buildSelectServer() {
return ConstrainedBox( return Column(
key: const ValueKey('server'), crossAxisAlignment: CrossAxisAlignment.stretch,
constraints: const BoxConstraints(maxWidth: 300), children: [
ServerEndpointInput(
controller: serverEndpointController,
focusNode: serverEndpointFocusNode,
onSubmit: getServerLoginCredential,
),
const SizedBox(height: 18),
ElevatedButton.icon(
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 12),
),
onPressed: isLoadingServer.value ? null : getServerLoginCredential,
icon: const Icon(Icons.arrow_forward_rounded),
label: const Text(
'login_form_next_button',
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
).tr(),
),
if (isLoadingServer.value)
const Padding(
padding: EdgeInsets.only(top: 18.0),
child: Center(
child: CircularProgressIndicator(),
),
),
],
);
}
buildLogin() {
return AutofillGroup(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
ServerEndpointInput( Text(
controller: serverEndpointController, serverEndpointController.text,
focusNode: serverEndpointFocusNode, style: Theme.of(context).textTheme.displaySmall,
onSubmit: getServerLoginCredential, textAlign: TextAlign.center,
), ),
const SizedBox(height: 18), const SizedBox(height: 18),
ElevatedButton.icon( EmailInput(
style: ElevatedButton.styleFrom( controller: usernameController,
padding: const EdgeInsets.symmetric(vertical: 12), focusNode: emailFocusNode,
), onSubmit: passwordFocusNode.requestFocus,
onPressed: isLoadingServer.value ? null : getServerLoginCredential,
icon: const Icon(Icons.arrow_forward_rounded),
label: const Text(
'Next',
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
).tr(),
), ),
if (isLoadingServer.value) const SizedBox(height: 8),
const Padding( PasswordInput(
padding: EdgeInsets.only(top: 18.0), controller: passwordController,
child: Center( focusNode: passwordFocusNode,
child: CircularProgressIndicator(), onSubmit: login,
),
// Note: This used to have an AnimatedSwitcher, but was removed
// because of https://github.com/flutter/flutter/issues/120874
isLoading.value
? const Padding(
padding: EdgeInsets.only(top: 18.0),
child: SizedBox(
width: 24,
height: 24,
child: FittedBox(
child: CircularProgressIndicator(
strokeWidth: 2,
),
),
),
)
: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(height: 18),
LoginButton(onPressed: login),
if (isOauthEnable.value) ...[
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
),
child: Divider(
color:
Brightness.dark == Theme.of(context).brightness
? Colors.white
: Colors.black,
),
),
OAuthLoginButton(
serverEndpointController: serverEndpointController,
buttonLabel: oAuthButtonLabel.value,
isLoading: isLoading,
onPressed: oAuthLogin,
),
],
],
), ),
const SizedBox(height: 12),
TextButton.icon(
icon: const Icon(Icons.arrow_back),
onPressed: () => serverEndpoint.value = null,
label: const Text('Back'),
), ),
], ],
), ),
); );
} }
final serverSelectionOrLogin = serverEndpoint.value == null
buildLogin() {
return ConstrainedBox(
key: const ValueKey('login'),
constraints: const BoxConstraints(maxWidth: 300),
child: AutofillGroup(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
serverEndpointController.text,
style: Theme.of(context).textTheme.displaySmall,
textAlign: TextAlign.center,
),
const SizedBox(height: 18),
EmailInput(
controller: usernameController,
focusNode: emailFocusNode,
onSubmit: passwordFocusNode.requestFocus,
),
const SizedBox(height: 8),
PasswordInput(
controller: passwordController,
focusNode: passwordFocusNode,
onSubmit: login,
),
AnimatedSwitcher(
duration: const Duration(milliseconds: 500),
child: isLoading.value
? const SizedBox(
width: 24,
height: 24,
child: CircularProgressIndicator(
strokeWidth: 2,
),
)
: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(height: 18),
LoginButton(onPressed: login),
if (isOauthEnable.value) ...[
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
),
child: Divider(
color:
Brightness.dark == Theme.of(context).brightness
? Colors.white
: Colors.black,
),
),
OAuthLoginButton(
serverEndpointController: serverEndpointController,
buttonLabel: oAuthButtonLabel.value,
isLoading: isLoading,
onPressed: oAuthLogin,
),
],
],
),
),
const SizedBox(height: 12),
TextButton.icon(
icon: const Icon(Icons.arrow_back),
onPressed: () => serverEndpoint.value = null,
label: const Text('Back'),
),
],
),
),
);
}
final child = serverEndpoint.value == null
? buildSelectServer() ? buildSelectServer()
: buildLogin(); : buildLogin();
return LayoutBuilder( return LayoutBuilder(
builder: (context, constraints) { builder: (context, constraints) {
return SingleChildScrollView( return SingleChildScrollView(
child: Column( child: Center(
crossAxisAlignment: CrossAxisAlignment.stretch, child: Container(
mainAxisAlignment: MainAxisAlignment.center, constraints: const BoxConstraints(maxWidth: 300),
children: [ child: Column(
SizedBox( crossAxisAlignment: CrossAxisAlignment.stretch,
height: constraints.maxHeight / 5, mainAxisAlignment: MainAxisAlignment.center,
),
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
GestureDetector( SizedBox(
onDoubleTap: () => populateTestLoginInfo(), height: constraints.maxHeight / 5,
child: RotationTransition(
turns: logoAnimationController,
child: const ImmichLogo(
heroTag: 'logo',
),
),
), ),
const ImmichTitleText(), Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.end,
children: [
GestureDetector(
onDoubleTap: () => populateTestLoginInfo(),
child: RotationTransition(
turns: logoAnimationController,
child: const ImmichLogo(
heroTag: 'logo',
),
),
),
const ImmichTitleText(),
],
),
const SizedBox(height: 18),
// Note: This used to have an AnimatedSwitcher, but was removed
// because of https://github.com/flutter/flutter/issues/120874
serverSelectionOrLogin,
], ],
), ),
const SizedBox(height: 18), ),
AnimatedSwitcher(
duration: const Duration(milliseconds: 500),
child: child,
),
],
), ),
); );
}, },
@ -386,7 +387,7 @@ class ServerEndpointInput extends StatelessWidget {
final TextEditingController controller; final TextEditingController controller;
final FocusNode focusNode; final FocusNode focusNode;
final Function()? onSubmit; final Function()? onSubmit;
const ServerEndpointInput({ const ServerEndpointInput({
Key? key, Key? key,
required this.controller, required this.controller,
@ -436,7 +437,7 @@ class EmailInput extends StatelessWidget {
final Function()? onSubmit; final Function()? onSubmit;
const EmailInput({ const EmailInput({
Key? key, Key? key,
required this.controller, required this.controller,
this.focusNode, this.focusNode,
this.onSubmit, this.onSubmit,
@ -480,8 +481,8 @@ class PasswordInput extends StatelessWidget {
const PasswordInput({ const PasswordInput({
Key? key, Key? key,
required this.controller, required this.controller,
this.focusNode, this.focusNode,
this.onSubmit, this.onSubmit,
}) : super(key: key); }) : super(key: key);