feat: Fix hive errors, change provider hierarchy for blocs, translate strings

This commit is contained in:
Anton Stubenbord
2023-04-25 01:16:14 +02:00
parent 1f335119b3
commit 8c2a6928b4
34 changed files with 502 additions and 363 deletions

View File

@@ -1,114 +0,0 @@
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hive_flutter/adapters.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:paperless_api/paperless_api.dart';
import 'package:paperless_mobile/core/bloc/paperless_server_information_cubit.dart';
import 'package:paperless_mobile/core/bloc/paperless_server_information_state.dart';
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
import 'package:paperless_mobile/core/widgets/hint_card.dart';
import 'package:paperless_mobile/extensions/flutter_extensions.dart';
import 'package:paperless_mobile/features/login/cubit/authentication_cubit.dart';
import 'package:paperless_mobile/core/database/tables/user_account.dart';
import 'package:paperless_mobile/features/settings/view/widgets/global_settings_builder.dart';
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
import 'package:paperless_mobile/helpers/message_helpers.dart';
class AccountSettingsDialog extends StatelessWidget {
const AccountSettingsDialog({super.key});
@override
Widget build(BuildContext context) {
return GlobalSettingsBuilder(builder: (context, globalSettings) {
return AlertDialog(
insetPadding: EdgeInsets.symmetric(horizontal: 24, vertical: 32),
scrollable: true,
contentPadding: EdgeInsets.zero,
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(S.of(context)!.account),
const CloseButton(),
],
),
content: BlocBuilder<PaperlessServerInformationCubit, PaperlessServerInformationState>(
builder: (context, state) {
return Column(
children: [
ValueListenableBuilder(
valueListenable: Hive.box<UserAccount>(HiveBoxes.userAccount).listenable(),
builder: (context, box, _) {
// final currentUser = globalSettings.currentLoggedInUser;
final currentUser = null;
final accountIds =
box.keys.whereNot((element) => element == currentUser).toList();
final accounts = accountIds.map((id) => box.get(id)!).toList();
return ExpansionTile(
leading: CircleAvatar(
child: Text(state.information?.userInitials ?? ''),
),
title: Text(state.information?.username ?? ''),
subtitle: Text(state.information?.host ?? ''),
children:
accounts.map((account) => _buildAccountTile(account, true)).toList(),
);
},
),
ListTile(
dense: true,
leading: const Icon(Icons.person_add_rounded),
title: Text(S.of(context)!.addAnotherAccount),
onTap: () {},
),
const Divider(),
FilledButton(
style: ButtonStyle(
backgroundColor: MaterialStatePropertyAll(
Theme.of(context).colorScheme.error,
),
),
child: Text(
S.of(context)!.disconnect,
style: TextStyle(
color: Theme.of(context).colorScheme.onError,
),
),
onPressed: () async {
await _onLogout(context);
Navigator.of(context).maybePop();
},
).padded(16),
],
);
},
),
);
});
}
Future<void> _onLogout(BuildContext context) async {
try {
await context.read<AuthenticationCubit>().logout();
await HydratedBloc.storage.clear();
} on PaperlessServerException catch (error, stackTrace) {
showErrorMessage(context, error, stackTrace);
}
}
Widget _buildAccountTile(UserAccount account, bool isActive) {
return ListTile(
selected: isActive,
title: Text(account.username),
subtitle: Text(account.serverUrl),
leading: CircleAvatar(
child: Text((account.fullName ?? account.username)
.split(" ")
.take(2)
.map((e) => e.substring(0, 1))
.map((e) => e.toUpperCase())
.join(" ")),
),
);
}
}

View File

@@ -4,25 +4,19 @@ import 'package:paperless_mobile/core/widgets/dialog_utils/dialog_confirm_button
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
class SwitchAccountDialog extends StatelessWidget {
final String username;
final String serverUrl;
const SwitchAccountDialog({
super.key,
required this.username,
required this.serverUrl,
});
const SwitchAccountDialog({super.key});
@override
Widget build(BuildContext context) {
return AlertDialog(
title: Text("Switch account"),
content: Text("Do you want to switch to $serverUrl and log in as $username?"),
title: Text(S.of(context)!.switchAccountTitle),
content: Text(S.of(context)!.switchToNewAccount),
actions: [
const DialogCancelButton(),
DialogConfirmButton(
style: DialogConfirmButtonStyle.danger,
label: S.of(context)!.continueLabel, //TODO: INTL change labels
style: DialogConfirmButtonStyle.normal,
label: S.of(context)!.switchAccount,
),
DialogCancelButton(),
],
);
}

View File

@@ -42,7 +42,7 @@ class ManageAccountsPage extends StatelessWidget {
alignment: Alignment.centerLeft,
child: CloseButton(),
),
Center(child: Text("Accounts")),
Center(child: Text(S.of(context)!.accounts)),
],
), //TODO: INTL
shape: RoundedRectangleBorder(
@@ -65,7 +65,7 @@ class ManageAccountsPage extends StatelessWidget {
),
const Divider(),
ListTile(
title: const Text("Add account"),
title: Text(S.of(context)!.addAccount),
leading: const Icon(Icons.person_add),
onTap: () {
_onAddAccount(context);
@@ -113,17 +113,17 @@ class ManageAccountsPage extends StatelessWidget {
itemBuilder: (context) {
return [
if (!isLoggedIn)
const PopupMenuItem(
PopupMenuItem(
child: ListTile(
title: Text("Switch"), //TODO: INTL
title: Text(S.of(context)!.switchAccount),
leading: Icon(Icons.switch_account_rounded),
),
value: 0,
),
if (!isLoggedIn)
const PopupMenuItem(
PopupMenuItem(
child: ListTile(
title: Text("Remove"), // TODO: INTL
title: Text(S.of(context)!.remove),
leading: Icon(
Icons.person_remove,
color: Colors.red,
@@ -132,9 +132,9 @@ class ManageAccountsPage extends StatelessWidget {
value: 1,
)
else
const PopupMenuItem(
PopupMenuItem(
child: ListTile(
title: Text("Logout"), // TODO: INTL
title: Text(S.of(context)!.logout),
leading: Icon(
Icons.person_remove,
color: Colors.red,
@@ -177,12 +177,12 @@ class ManageAccountsPage extends StatelessWidget {
return child;
}
Future<void> _onAddAccount(BuildContext context) {
return Navigator.push(
Future<void> _onAddAccount(BuildContext context) async {
final userId = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => LoginPage(
titleString: "Add account", //TODO: INTL
titleString: S.of(context)!.addAccount,
onSubmit: (context, username, password, serverUrl, clientCertificate) async {
final userId = await context.read<AuthenticationCubit>().addAccount(
credentials: LoginFormCredentials(
@@ -194,19 +194,22 @@ class ManageAccountsPage extends StatelessWidget {
//TODO: Ask user whether to enable biometric authentication
enableBiometricAuthentication: false,
);
final shoudSwitch = await showDialog(
context: context,
builder: (context) =>
SwitchAccountDialog(username: username, serverUrl: serverUrl),
) ??
false;
if (shoudSwitch) {
context.read<AuthenticationCubit>().switchAccount(userId);
}
Navigator.of(context).pop<String?>(userId);
},
submitText: "Add account", //TODO: INTL
submitText: S.of(context)!.addAccount,
),
),
);
if (userId != null) {
final shoudSwitch = await showDialog<bool>(
context: context,
builder: (context) => const SwitchAccountDialog(),
) ??
false;
if (shoudSwitch) {
await context.read<AuthenticationCubit>().switchAccount(userId);
Navigator.pop(context);
}
}
}
}

View File

@@ -15,12 +15,8 @@ class ApplicationSettingsPage extends StatelessWidget {
actions: [
Padding(
padding: const EdgeInsets.all(16.0),
child: Tooltip(
triggerMode: TooltipTriggerMode.tap,
message: "These settings apply to all accounts", //TODO: INTL
child: Icon(Icons.info_outline),
),
),
child: const Icon(Icons.public),
)
],
),
body: ListView(

View File

@@ -13,12 +13,8 @@ class SecuritySettingsPage extends StatelessWidget {
actions: [
Padding(
padding: const EdgeInsets.all(16.0),
child: Tooltip(
triggerMode: TooltipTriggerMode.tap,
message: "These settings apply to the current user only", //TODO: INTL
child: Icon(Icons.info_outline),
),
),
child: const Icon(Icons.person_outline),
)
],
),
body: ListView(

View File

@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
class SwitchingAccountsPage extends StatelessWidget {
const SwitchingAccountsPage({super.key});
@@ -6,17 +7,19 @@ class SwitchingAccountsPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
return false;
},
onWillPop: () async => false,
child: Material(
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(),
Text("Switching accounts. Please wait..."),
const CircularProgressIndicator(),
const SizedBox(height: 16),
Text(
S.of(context)!.switchingAccountsPleaseWait,
style: Theme.of(context).textTheme.labelLarge,
),
],
),
),

View File

@@ -1,10 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hive_flutter/adapters.dart';
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
import 'package:paperless_mobile/features/login/services/authentication_service.dart';
import 'package:paperless_mobile/core/database/tables/global_settings.dart';
import 'package:paperless_mobile/core/database/tables/user_settings.dart';
import 'package:paperless_mobile/features/settings/view/widgets/user_settings_builder.dart';
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
import 'package:provider/provider.dart';