feat: Implement switching between accounts (multi user support), still WIP

This commit is contained in:
Anton Stubenbord
2023-04-21 01:32:43 +02:00
parent 1334f546ee
commit 95dd0a2405
50 changed files with 1055 additions and 721 deletions

View File

@@ -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(

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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),