mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-15 02:12:25 -06:00
feat: Implement switching between accounts (multi user support), still WIP
This commit is contained in:
@@ -3,18 +3,37 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||
import 'package:paperless_api/paperless_api.dart';
|
||||
import 'package:paperless_mobile/core/type/types.dart';
|
||||
import 'package:paperless_mobile/features/app_intro/application_intro_slideshow.dart';
|
||||
import 'package:paperless_mobile/features/login/cubit/authentication_cubit.dart';
|
||||
import 'package:paperless_mobile/features/login/model/client_certificate.dart';
|
||||
import 'package:paperless_mobile/features/login/model/client_certificate_form_model.dart';
|
||||
import 'package:paperless_mobile/features/login/model/login_form_credentials.dart';
|
||||
import 'package:paperless_mobile/features/login/view/widgets/form_fields/client_certificate_form_field.dart';
|
||||
import 'package:paperless_mobile/features/login/view/widgets/form_fields/server_address_form_field.dart';
|
||||
import 'package:paperless_mobile/features/login/view/widgets/form_fields/user_credentials_form_field.dart';
|
||||
import 'package:paperless_mobile/features/login/view/widgets/login_pages/server_connection_page.dart';
|
||||
import 'package:paperless_mobile/features/settings/model/global_settings.dart';
|
||||
import 'package:paperless_mobile/helpers/message_helpers.dart';
|
||||
|
||||
import 'widgets/login_pages/server_login_page.dart';
|
||||
import 'widgets/never_scrollable_scroll_behavior.dart';
|
||||
|
||||
class LoginPage extends StatefulWidget {
|
||||
const LoginPage({Key? key}) : super(key: key);
|
||||
final void Function(
|
||||
BuildContext context,
|
||||
String username,
|
||||
String password,
|
||||
String serverUrl,
|
||||
ClientCertificate? clientCertificate,
|
||||
) onSubmit;
|
||||
|
||||
final String submitText;
|
||||
|
||||
const LoginPage({
|
||||
Key? key,
|
||||
required this.onSubmit,
|
||||
required this.submitText,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<LoginPage> createState() => _LoginPageState();
|
||||
@@ -46,7 +65,8 @@ class _LoginPageState extends State<LoginPage> {
|
||||
),
|
||||
ServerLoginPage(
|
||||
formBuilderKey: _formKey,
|
||||
onDone: _login,
|
||||
submitText: widget.submitText,
|
||||
onSubmit: _login,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -58,24 +78,23 @@ class _LoginPageState extends State<LoginPage> {
|
||||
FocusScope.of(context).unfocus();
|
||||
if (_formKey.currentState?.saveAndValidate() ?? false) {
|
||||
final form = _formKey.currentState!.value;
|
||||
try {
|
||||
await context.read<AuthenticationCubit>().login(
|
||||
credentials: form[UserCredentialsFormField.fkCredentials],
|
||||
serverUrl: form[ServerAddressFormField.fkServerAddress],
|
||||
clientCertificate:
|
||||
form[ClientCertificateFormField.fkClientCertificate],
|
||||
);
|
||||
} on PaperlessServerException catch (error, stackTrace) {
|
||||
showErrorMessage(context, error, stackTrace);
|
||||
} on PaperlessValidationErrors catch (error, stackTrace) {
|
||||
if (error.hasFieldUnspecificError) {
|
||||
showLocalizedError(context, error.fieldUnspecificError!);
|
||||
} else {
|
||||
showGenericError(context, error.values.first, stackTrace);
|
||||
}
|
||||
} catch (unknownError, stackTrace) {
|
||||
showGenericError(context, unknownError.toString(), stackTrace);
|
||||
ClientCertificate? clientCert;
|
||||
final clientCertFormModel =
|
||||
form[ClientCertificateFormField.fkClientCertificate] as ClientCertificateFormModel?;
|
||||
if (clientCertFormModel != null) {
|
||||
clientCert = ClientCertificate(
|
||||
bytes: clientCertFormModel.bytes,
|
||||
passphrase: clientCertFormModel.passphrase,
|
||||
);
|
||||
}
|
||||
final credentials = form[UserCredentialsFormField.fkCredentials] as LoginFormCredentials;
|
||||
widget.onSubmit(
|
||||
context,
|
||||
credentials.username!,
|
||||
credentials.password!,
|
||||
form[ServerAddressFormField.fkServerAddress],
|
||||
clientCert,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||
import 'package:paperless_mobile/features/login/model/client_certificate.dart';
|
||||
import 'package:paperless_mobile/features/login/model/client_certificate_form_model.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
|
||||
import 'package:paperless_mobile/constants.dart';
|
||||
@@ -15,23 +16,21 @@ import 'obscured_input_text_form_field.dart';
|
||||
class ClientCertificateFormField extends StatefulWidget {
|
||||
static const fkClientCertificate = 'clientCertificate';
|
||||
|
||||
final void Function(ClientCertificate? cert) onChanged;
|
||||
final void Function(ClientCertificateFormModel? cert) onChanged;
|
||||
const ClientCertificateFormField({
|
||||
Key? key,
|
||||
required this.onChanged,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<ClientCertificateFormField> createState() =>
|
||||
_ClientCertificateFormFieldState();
|
||||
State<ClientCertificateFormField> createState() => _ClientCertificateFormFieldState();
|
||||
}
|
||||
|
||||
class _ClientCertificateFormFieldState
|
||||
extends State<ClientCertificateFormField> {
|
||||
class _ClientCertificateFormFieldState extends State<ClientCertificateFormField> {
|
||||
File? _selectedFile;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FormBuilderField<ClientCertificate?>(
|
||||
return FormBuilderField<ClientCertificateFormModel?>(
|
||||
key: const ValueKey('login-client-cert'),
|
||||
onChanged: widget.onChanged,
|
||||
initialValue: null,
|
||||
@@ -46,8 +45,7 @@ class _ClientCertificateFormFieldState
|
||||
return null;
|
||||
},
|
||||
builder: (field) {
|
||||
final theme =
|
||||
Theme.of(context).copyWith(dividerColor: Colors.transparent); //new
|
||||
final theme = Theme.of(context).copyWith(dividerColor: Colors.transparent); //new
|
||||
return Theme(
|
||||
data: theme,
|
||||
child: ExpansionTile(
|
||||
@@ -124,7 +122,7 @@ class _ClientCertificateFormFieldState
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _onSelectFile(FormFieldState<ClientCertificate?> field) async {
|
||||
Future<void> _onSelectFile(FormFieldState<ClientCertificateFormModel?> field) async {
|
||||
FilePickerResult? result = await FilePicker.platform.pickFiles(
|
||||
allowMultiple: false,
|
||||
);
|
||||
@@ -133,14 +131,13 @@ class _ClientCertificateFormFieldState
|
||||
setState(() {
|
||||
_selectedFile = file;
|
||||
});
|
||||
final changedValue =
|
||||
field.value?.copyWith(bytes: file.readAsBytesSync()) ??
|
||||
ClientCertificate(bytes: file.readAsBytesSync());
|
||||
final changedValue = field.value?.copyWith(bytes: file.readAsBytesSync()) ??
|
||||
ClientCertificateFormModel(bytes: file.readAsBytesSync());
|
||||
field.didChange(changedValue);
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildSelectedFileText(FormFieldState<ClientCertificate?> field) {
|
||||
Widget _buildSelectedFileText(FormFieldState<ClientCertificateFormModel?> field) {
|
||||
if (field.value == null) {
|
||||
assert(_selectedFile == null);
|
||||
return Text(
|
||||
|
||||
@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||
|
||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||
import 'package:paperless_mobile/features/login/model/user_credentials.model.dart';
|
||||
import 'package:paperless_mobile/features/login/model/login_form_credentials.dart';
|
||||
import 'package:paperless_mobile/features/login/view/widgets/form_fields/obscured_input_text_form_field.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
|
||||
@@ -14,14 +14,13 @@ class UserCredentialsFormField extends StatefulWidget {
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<UserCredentialsFormField> createState() =>
|
||||
_UserCredentialsFormFieldState();
|
||||
State<UserCredentialsFormField> createState() => _UserCredentialsFormFieldState();
|
||||
}
|
||||
|
||||
class _UserCredentialsFormFieldState extends State<UserCredentialsFormField> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FormBuilderField<UserCredentials?>(
|
||||
return FormBuilderField<LoginFormCredentials?>(
|
||||
name: UserCredentialsFormField.fkCredentials,
|
||||
builder: (field) => AutofillGroup(
|
||||
child: Column(
|
||||
@@ -34,7 +33,7 @@ class _UserCredentialsFormFieldState extends State<UserCredentialsFormField> {
|
||||
autocorrect: false,
|
||||
onChanged: (username) => field.didChange(
|
||||
field.value?.copyWith(username: username) ??
|
||||
UserCredentials(username: username),
|
||||
LoginFormCredentials(username: username),
|
||||
),
|
||||
validator: (value) {
|
||||
if (value?.trim().isEmpty ?? true) {
|
||||
@@ -51,7 +50,7 @@ class _UserCredentialsFormFieldState extends State<UserCredentialsFormField> {
|
||||
label: S.of(context)!.password,
|
||||
onChanged: (password) => field.didChange(
|
||||
field.value?.copyWith(password: password) ??
|
||||
UserCredentials(password: password),
|
||||
LoginFormCredentials(password: password),
|
||||
),
|
||||
validator: (value) {
|
||||
if (value?.trim().isEmpty ?? true) {
|
||||
|
||||
@@ -3,6 +3,8 @@ import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||
import 'package:paperless_mobile/core/service/connectivity_status_service.dart';
|
||||
import 'package:paperless_mobile/core/widgets/paperless_logo.dart';
|
||||
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
|
||||
import 'package:paperless_mobile/features/login/model/client_certificate.dart';
|
||||
import 'package:paperless_mobile/features/login/model/client_certificate_form_model.dart';
|
||||
import 'package:paperless_mobile/features/login/model/reachability_status.dart';
|
||||
import 'package:paperless_mobile/features/login/view/widgets/form_fields/client_certificate_form_field.dart';
|
||||
import 'package:paperless_mobile/features/login/view/widgets/form_fields/server_address_form_field.dart';
|
||||
@@ -35,9 +37,8 @@ class _ServerConnectionPageState extends State<ServerConnectionPage> {
|
||||
toolbarHeight: kToolbarHeight - 4,
|
||||
title: Text(S.of(context)!.connectToPaperless),
|
||||
bottom: PreferredSize(
|
||||
child: _isCheckingConnection
|
||||
? const LinearProgressIndicator()
|
||||
: const SizedBox(height: 4.0),
|
||||
child:
|
||||
_isCheckingConnection ? const LinearProgressIndicator() : const SizedBox(height: 4.0),
|
||||
preferredSize: const Size.fromHeight(4.0),
|
||||
),
|
||||
),
|
||||
@@ -67,9 +68,8 @@ class _ServerConnectionPageState extends State<ServerConnectionPage> {
|
||||
),
|
||||
FilledButton(
|
||||
child: Text(S.of(context)!.continueLabel),
|
||||
onPressed: _reachabilityStatus == ReachabilityStatus.reachable
|
||||
? widget.onContinue
|
||||
: null,
|
||||
onPressed:
|
||||
_reachabilityStatus == ReachabilityStatus.reachable ? widget.onContinue : null,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -81,16 +81,16 @@ class _ServerConnectionPageState extends State<ServerConnectionPage> {
|
||||
setState(() {
|
||||
_isCheckingConnection = true;
|
||||
});
|
||||
|
||||
final status = await context
|
||||
.read<ConnectivityStatusService>()
|
||||
.isPaperlessServerReachable(
|
||||
final certForm = widget.formBuilderKey.currentState
|
||||
?.getRawValue(ClientCertificateFormField.fkClientCertificate)
|
||||
as ClientCertificateFormModel?;
|
||||
final status = await context.read<ConnectivityStatusService>().isPaperlessServerReachable(
|
||||
address ??
|
||||
widget.formBuilderKey.currentState!
|
||||
.getRawValue(ServerAddressFormField.fkServerAddress),
|
||||
widget.formBuilderKey.currentState?.getRawValue(
|
||||
ClientCertificateFormField.fkClientCertificate,
|
||||
),
|
||||
certForm != null
|
||||
? ClientCertificate(bytes: certForm.bytes, passphrase: certForm.passphrase)
|
||||
: null,
|
||||
);
|
||||
setState(() {
|
||||
_isCheckingConnection = false;
|
||||
|
||||
@@ -6,12 +6,14 @@ import 'package:paperless_mobile/features/login/view/widgets/form_fields/user_cr
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
|
||||
class ServerLoginPage extends StatefulWidget {
|
||||
final Future<void> Function() onDone;
|
||||
final String submitText;
|
||||
final Future<void> Function() onSubmit;
|
||||
final GlobalKey<FormBuilderState> formBuilderKey;
|
||||
const ServerLoginPage({
|
||||
super.key,
|
||||
required this.onDone,
|
||||
required this.onSubmit,
|
||||
required this.formBuilderKey,
|
||||
required this.submitText,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -23,8 +25,7 @@ class _ServerLoginPageState extends State<ServerLoginPage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final serverAddress = (widget.formBuilderKey.currentState
|
||||
?.getRawValue(ServerAddressFormField.fkServerAddress)
|
||||
as String?)
|
||||
?.getRawValue(ServerAddressFormField.fkServerAddress) as String?)
|
||||
?.replaceAll(RegExp(r'https?://'), '') ??
|
||||
'';
|
||||
return Scaffold(
|
||||
@@ -50,7 +51,7 @@ class _ServerLoginPageState extends State<ServerLoginPage> {
|
||||
FilledButton(
|
||||
onPressed: () async {
|
||||
setState(() => _isLoginLoading = true);
|
||||
await widget.onDone();
|
||||
await widget.onSubmit();
|
||||
setState(() => _isLoginLoading = false);
|
||||
},
|
||||
child: Text(S.of(context)!.signIn),
|
||||
|
||||
Reference in New Issue
Block a user