mirror of
https://github.com/Xevion/paperless-mobile.git
synced 2025-12-09 20:07:51 -06:00
feat: Implement switching between accounts (multi user support), still WIP
This commit is contained in:
@@ -1,64 +0,0 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hydrated_bloc/hydrated_bloc.dart';
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:paperless_mobile/features/login/services/authentication_service.dart';
|
||||
import 'package:paperless_mobile/features/settings/model/color_scheme_option.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
|
||||
part 'application_settings_cubit.g.dart';
|
||||
part 'application_settings_state.dart';
|
||||
|
||||
class ApplicationSettingsCubit extends HydratedCubit<ApplicationSettingsState> {
|
||||
final LocalAuthenticationService _localAuthenticationService;
|
||||
ApplicationSettingsCubit(this._localAuthenticationService)
|
||||
: super(ApplicationSettingsState.defaultSettings);
|
||||
|
||||
Future<void> setLocale(String? localeSubtag) async {
|
||||
final updatedSettings = state.copyWith(preferredLocaleSubtag: localeSubtag);
|
||||
_updateSettings(updatedSettings);
|
||||
}
|
||||
|
||||
Future<void> setIsBiometricAuthenticationEnabled(
|
||||
bool isEnabled, {
|
||||
required String localizedReason,
|
||||
}) async {
|
||||
final isActionAuthorized = await _localAuthenticationService
|
||||
.authenticateLocalUser(localizedReason);
|
||||
if (isActionAuthorized) {
|
||||
final updatedSettings =
|
||||
state.copyWith(isLocalAuthenticationEnabled: isEnabled);
|
||||
_updateSettings(updatedSettings);
|
||||
}
|
||||
}
|
||||
|
||||
void setThemeMode(ThemeMode? selectedMode) {
|
||||
final updatedSettings = state.copyWith(preferredThemeMode: selectedMode);
|
||||
_updateSettings(updatedSettings);
|
||||
}
|
||||
|
||||
void setColorSchemeOption(ColorSchemeOption schemeOption) {
|
||||
final updatedSettings =
|
||||
state.copyWith(preferredColorSchemeOption: schemeOption);
|
||||
_updateSettings(updatedSettings);
|
||||
}
|
||||
|
||||
void _updateSettings(ApplicationSettingsState settings) async {
|
||||
emit(settings);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> clear() async {
|
||||
await super.clear();
|
||||
emit(ApplicationSettingsState.defaultSettings);
|
||||
}
|
||||
|
||||
@override
|
||||
ApplicationSettingsState? fromJson(Map<String, dynamic> json) =>
|
||||
ApplicationSettingsState.fromJson(json);
|
||||
|
||||
@override
|
||||
Map<String, dynamic>? toJson(ApplicationSettingsState state) =>
|
||||
state.toJson();
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
part of 'application_settings_cubit.dart';
|
||||
|
||||
///
|
||||
/// State holding the current application settings such as selected language, theme mode and more.
|
||||
///
|
||||
@JsonSerializable()
|
||||
class ApplicationSettingsState {
|
||||
static final defaultSettings = ApplicationSettingsState(
|
||||
preferredLocaleSubtag: _defaultPreferredLocaleSubtag,
|
||||
);
|
||||
|
||||
final bool isLocalAuthenticationEnabled;
|
||||
final String preferredLocaleSubtag;
|
||||
final ThemeMode preferredThemeMode;
|
||||
final ColorSchemeOption preferredColorSchemeOption;
|
||||
|
||||
ApplicationSettingsState({
|
||||
required this.preferredLocaleSubtag,
|
||||
this.preferredThemeMode = ThemeMode.system,
|
||||
this.isLocalAuthenticationEnabled = false,
|
||||
this.preferredColorSchemeOption = ColorSchemeOption.classic,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() => _$ApplicationSettingsStateToJson(this);
|
||||
factory ApplicationSettingsState.fromJson(Map<String, dynamic> json) =>
|
||||
_$ApplicationSettingsStateFromJson(json);
|
||||
|
||||
ApplicationSettingsState copyWith({
|
||||
bool? isLocalAuthenticationEnabled,
|
||||
String? preferredLocaleSubtag,
|
||||
ThemeMode? preferredThemeMode,
|
||||
ColorSchemeOption? preferredColorSchemeOption,
|
||||
}) {
|
||||
return ApplicationSettingsState(
|
||||
isLocalAuthenticationEnabled:
|
||||
isLocalAuthenticationEnabled ?? this.isLocalAuthenticationEnabled,
|
||||
preferredLocaleSubtag:
|
||||
preferredLocaleSubtag ?? this.preferredLocaleSubtag,
|
||||
preferredThemeMode: preferredThemeMode ?? this.preferredThemeMode,
|
||||
preferredColorSchemeOption:
|
||||
preferredColorSchemeOption ?? this.preferredColorSchemeOption,
|
||||
);
|
||||
}
|
||||
|
||||
static String get _defaultPreferredLocaleSubtag {
|
||||
String preferredLocale = Platform.localeName.split("_").first;
|
||||
if (!S.supportedLocales
|
||||
.any((locale) => locale.languageCode == preferredLocale)) {
|
||||
preferredLocale = 'en';
|
||||
}
|
||||
return preferredLocale;
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,10 @@ import 'package:hive/hive.dart';
|
||||
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
||||
import 'package:paperless_mobile/features/settings/model/color_scheme_option.dart';
|
||||
|
||||
part 'global_app_settings.g.dart';
|
||||
part 'global_settings.g.dart';
|
||||
|
||||
@HiveType(typeId: HiveTypeIds.globalSettings)
|
||||
class GlobalAppSettings with ChangeNotifier, HiveObjectMixin {
|
||||
class GlobalSettings with HiveObjectMixin {
|
||||
@HiveField(0)
|
||||
String preferredLocaleSubtag;
|
||||
|
||||
@@ -22,7 +22,7 @@ class GlobalAppSettings with ChangeNotifier, HiveObjectMixin {
|
||||
@HiveField(4)
|
||||
String? currentLoggedInUser;
|
||||
|
||||
GlobalAppSettings({
|
||||
GlobalSettings({
|
||||
required this.preferredLocaleSubtag,
|
||||
this.preferredThemeMode = ThemeMode.system,
|
||||
this.preferredColorSchemeOption = ColorSchemeOption.classic,
|
||||
@@ -30,7 +30,6 @@ class GlobalAppSettings with ChangeNotifier, HiveObjectMixin {
|
||||
this.currentLoggedInUser,
|
||||
});
|
||||
|
||||
static GlobalAppSettings get boxedValue =>
|
||||
Hive.box<GlobalAppSettings>(HiveBoxes.globalSettings)
|
||||
.get(HiveBoxSingleValueKey.value)!;
|
||||
static GlobalSettings get boxedValue =>
|
||||
Hive.box<GlobalSettings>(HiveBoxes.globalSettings).getValue()!;
|
||||
}
|
||||
@@ -1,16 +1,14 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
||||
import 'package:paperless_mobile/features/settings/model/color_scheme_option.dart';
|
||||
|
||||
part 'user_app_settings.g.dart';
|
||||
part 'user_settings.g.dart';
|
||||
|
||||
@HiveType(typeId: HiveTypeIds.userSettings)
|
||||
class UserAppSettings with HiveObjectMixin {
|
||||
class UserSettings with HiveObjectMixin {
|
||||
@HiveField(0)
|
||||
bool isBiometricAuthenticationEnabled;
|
||||
|
||||
UserAppSettings({
|
||||
UserSettings({
|
||||
this.isBiometricAuthenticationEnabled = false,
|
||||
});
|
||||
}
|
||||
@@ -1,18 +1,18 @@
|
||||
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/repository/label_repository.dart';
|
||||
import 'package:paperless_mobile/core/repository/saved_view_repository.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/features/settings/global_app_settings.dart';
|
||||
import 'package:paperless_mobile/features/settings/cubit/application_settings_cubit.dart';
|
||||
import 'package:paperless_mobile/features/login/model/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 {
|
||||
@@ -20,74 +20,95 @@ class AccountSettingsDialog extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
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: [
|
||||
ExpansionTile(
|
||||
leading: CircleAvatar(
|
||||
child: Text(state.information?.userInitials ?? ''),
|
||||
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(),
|
||||
);
|
||||
},
|
||||
),
|
||||
title: Text(state.information?.username ?? ''),
|
||||
subtitle: Text(state.information?.host ?? ''),
|
||||
children: const [
|
||||
HintCard(
|
||||
hintText: "WIP: Coming soon with multi user support!",
|
||||
),
|
||||
],
|
||||
),
|
||||
const Divider(),
|
||||
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,
|
||||
),
|
||||
ListTile(
|
||||
dense: true,
|
||||
leading: const Icon(Icons.person_add_rounded),
|
||||
title: Text(S.of(context)!.addAnotherAccount),
|
||||
onTap: () {},
|
||||
),
|
||||
child: Text(
|
||||
S.of(context)!.disconnect,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.onError,
|
||||
const Divider(),
|
||||
FilledButton(
|
||||
style: ButtonStyle(
|
||||
backgroundColor: MaterialStatePropertyAll(
|
||||
Theme.of(context).colorScheme.error,
|
||||
),
|
||||
),
|
||||
),
|
||||
onPressed: () async {
|
||||
await _onLogout(context);
|
||||
Navigator.of(context).maybePop();
|
||||
},
|
||||
).padded(16),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
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 context.read<GlobalAppSettings>();
|
||||
await context.read<LabelRepository>().clear();
|
||||
await context.read<SavedViewRepository>().clear();
|
||||
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(" ")),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:paperless_mobile/core/widgets/dialog_utils/dialog_cancel_button.dart';
|
||||
import 'package:paperless_mobile/core/widgets/dialog_utils/dialog_confirm_button.dart';
|
||||
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,
|
||||
});
|
||||
|
||||
@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?"),
|
||||
actions: [
|
||||
DialogConfirmButton(
|
||||
style: DialogConfirmButtonStyle.danger,
|
||||
label: S.of(context)!.continueLabel, //TODO: INTL change labels
|
||||
),
|
||||
DialogCancelButton(),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
136
lib/features/settings/view/manage_accounts_page.dart
Normal file
136
lib/features/settings/view/manage_accounts_page.dart
Normal file
@@ -0,0 +1,136 @@
|
||||
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/cubit/authentication_cubit.dart';
|
||||
import 'package:paperless_mobile/features/login/model/login_form_credentials.dart';
|
||||
import 'package:paperless_mobile/features/login/model/user_account.dart';
|
||||
import 'package:paperless_mobile/features/login/view/login_page.dart';
|
||||
import 'package:paperless_mobile/features/settings/model/global_settings.dart';
|
||||
import 'package:paperless_mobile/features/settings/view/dialogs/switch_account_dialog.dart';
|
||||
import 'package:paperless_mobile/features/settings/view/pages/switching_accounts_page.dart';
|
||||
import 'package:paperless_mobile/features/settings/view/widgets/global_settings_builder.dart';
|
||||
|
||||
class ManageAccountsPage extends StatelessWidget {
|
||||
const ManageAccountsPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Dialog.fullscreen(
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: CloseButton(),
|
||||
title: Text("Manage Accounts"), //TODO: INTL
|
||||
),
|
||||
floatingActionButton: FloatingActionButton.extended(
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => LoginPage(
|
||||
onSubmit: (context, username, password, serverUrl, clientCertificate) async {
|
||||
final userId = await context.read<AuthenticationCubit>().addAccount(
|
||||
credentials: LoginFormCredentials(
|
||||
username: username,
|
||||
password: password,
|
||||
),
|
||||
clientCertificate: clientCertificate,
|
||||
serverUrl: serverUrl,
|
||||
//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);
|
||||
}
|
||||
},
|
||||
submitText: "Add account",
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
label: Text("Add account"),
|
||||
icon: Icon(Icons.person_add),
|
||||
),
|
||||
body: GlobalSettingsBuilder(
|
||||
builder: (context, globalSettings) {
|
||||
return ValueListenableBuilder(
|
||||
valueListenable: Hive.box<UserAccount>(HiveBoxes.userAccount).listenable(),
|
||||
builder: (context, box, _) {
|
||||
final userIds = box.keys.toList().cast<String>();
|
||||
return ListView.builder(
|
||||
itemBuilder: (context, index) {
|
||||
return _buildAccountTile(
|
||||
context,
|
||||
userIds[index],
|
||||
box.get(userIds[index])!,
|
||||
globalSettings,
|
||||
);
|
||||
},
|
||||
itemCount: userIds.length,
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildAccountTile(
|
||||
BuildContext context, String userId, UserAccount account, GlobalSettings settings) {
|
||||
final theme = Theme.of(context);
|
||||
return ListTile(
|
||||
selected: userId == settings.currentLoggedInUser,
|
||||
title: Text(account.username),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (account.fullName != null) Text(account.fullName!),
|
||||
Text(account.serverUrl),
|
||||
],
|
||||
),
|
||||
isThreeLine: true,
|
||||
leading: CircleAvatar(
|
||||
child: Text((account.fullName ?? account.username)
|
||||
.split(" ")
|
||||
.take(2)
|
||||
.map((e) => e.substring(0, 1))
|
||||
.map((e) => e.toUpperCase())
|
||||
.join(" ")),
|
||||
),
|
||||
onTap: () async {
|
||||
final navigator = Navigator.of(context);
|
||||
if (settings.currentLoggedInUser == userId) return;
|
||||
Navigator.pushReplacement(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => SwitchingAccountsPage(),
|
||||
),
|
||||
);
|
||||
await context.read<AuthenticationCubit>().switchAccount(userId);
|
||||
navigator.popUntil((route) => route.isFirst);
|
||||
},
|
||||
trailing: TextButton(
|
||||
child: Text(
|
||||
"Remove",
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.error,
|
||||
),
|
||||
),
|
||||
onPressed: () async {
|
||||
final shouldPop = userId == settings.currentLoggedInUser;
|
||||
await context.read<AuthenticationCubit>().removeAccount(userId);
|
||||
if (shouldPop) {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/src/widgets/framework.dart';
|
||||
import 'package:flutter/src/widgets/placeholder.dart';
|
||||
|
||||
class SwitchingAccountsPage extends StatelessWidget {
|
||||
const SwitchingAccountsPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return WillPopScope(
|
||||
onWillPop: () async {
|
||||
return false;
|
||||
},
|
||||
child: Material(
|
||||
child: Center(
|
||||
child: Text("Switching accounts. Please wait..."),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,9 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.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/features/settings/global_app_settings.dart';
|
||||
import 'package:paperless_mobile/features/settings/cubit/application_settings_cubit.dart';
|
||||
import 'package:paperless_mobile/features/settings/view/pages/application_settings_page.dart';
|
||||
import 'package:paperless_mobile/features/settings/view/pages/security_settings_page.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class SettingsPage extends StatelessWidget {
|
||||
const SettingsPage({super.key});
|
||||
@@ -18,14 +15,13 @@ class SettingsPage extends StatelessWidget {
|
||||
appBar: AppBar(
|
||||
title: Text(S.of(context)!.settings),
|
||||
),
|
||||
bottomNavigationBar: BlocBuilder<PaperlessServerInformationCubit,
|
||||
PaperlessServerInformationState>(
|
||||
bottomNavigationBar:
|
||||
BlocBuilder<PaperlessServerInformationCubit, PaperlessServerInformationState>(
|
||||
builder: (context, state) {
|
||||
final info = state.information!;
|
||||
return ListTile(
|
||||
title: Text(
|
||||
S.of(context)!.loggedInAs(info.username ?? 'unknown') +
|
||||
"@${info.host}",
|
||||
S.of(context)!.loggedInAs(info.username ?? 'unknown') + "@${info.host}",
|
||||
style: Theme.of(context).textTheme.labelSmall,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
|
||||
@@ -3,9 +3,8 @@ 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/features/settings/cubit/application_settings_cubit.dart';
|
||||
import 'package:paperless_mobile/features/settings/global_app_settings.dart';
|
||||
import 'package:paperless_mobile/features/settings/user_app_settings.dart';
|
||||
import 'package:paperless_mobile/features/settings/model/global_settings.dart';
|
||||
import 'package:paperless_mobile/features/settings/model/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';
|
||||
|
||||
@@ -7,8 +7,7 @@ import 'package:paperless_mobile/constants.dart';
|
||||
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
||||
import 'package:paperless_mobile/core/translation/color_scheme_option_localization_mapper.dart';
|
||||
import 'package:paperless_mobile/core/widgets/hint_card.dart';
|
||||
import 'package:paperless_mobile/features/settings/cubit/application_settings_cubit.dart';
|
||||
import 'package:paperless_mobile/features/settings/global_app_settings.dart';
|
||||
import 'package:paperless_mobile/features/settings/model/global_settings.dart';
|
||||
import 'package:paperless_mobile/features/settings/model/color_scheme_option.dart';
|
||||
import 'package:paperless_mobile/features/settings/view/widgets/global_settings_builder.dart';
|
||||
import 'package:paperless_mobile/features/settings/view/widgets/radio_settings_dialog.dart';
|
||||
@@ -37,8 +36,7 @@ class ColorSchemeOptionSetting extends StatelessWidget {
|
||||
options: [
|
||||
RadioOption(
|
||||
value: ColorSchemeOption.classic,
|
||||
label: translateColorSchemeOption(
|
||||
context, ColorSchemeOption.classic),
|
||||
label: translateColorSchemeOption(context, ColorSchemeOption.classic),
|
||||
),
|
||||
RadioOption(
|
||||
value: ColorSchemeOption.dynamic,
|
||||
@@ -71,8 +69,7 @@ class ColorSchemeOptionSetting extends StatelessWidget {
|
||||
|
||||
bool _isBelowAndroid12() {
|
||||
if (Platform.isAndroid) {
|
||||
final int version =
|
||||
int.tryParse(androidInfo!.version.release ?? '0') ?? 0;
|
||||
final int version = int.tryParse(androidInfo!.version.release ?? '0') ?? 0;
|
||||
return version < 12;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -3,21 +3,18 @@ import 'package:flutter/src/widgets/framework.dart';
|
||||
import 'package:flutter/src/widgets/placeholder.dart';
|
||||
import 'package:hive_flutter/adapters.dart';
|
||||
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
||||
import 'package:paperless_mobile/features/settings/global_app_settings.dart';
|
||||
import 'package:paperless_mobile/features/settings/model/global_settings.dart';
|
||||
|
||||
class GlobalSettingsBuilder extends StatelessWidget {
|
||||
|
||||
final Widget Function(BuildContext context, GlobalAppSettings settings)
|
||||
builder;
|
||||
final Widget Function(BuildContext context, GlobalSettings settings) builder;
|
||||
const GlobalSettingsBuilder({super.key, required this.builder});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ValueListenableBuilder(
|
||||
valueListenable:
|
||||
Hive.box<GlobalAppSettings>(HiveBoxes.globalSettings).listenable(),
|
||||
valueListenable: Hive.box<GlobalSettings>(HiveBoxes.globalSettings).listenable(),
|
||||
builder: (context, value, _) {
|
||||
final settings = value.get(HiveBoxSingleValueKey.value)!;
|
||||
final settings = value.getValue()!;
|
||||
return builder(context, settings);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:hive_flutter/adapters.dart';
|
||||
import 'package:paperless_mobile/features/settings/cubit/application_settings_cubit.dart';
|
||||
import 'package:paperless_mobile/features/settings/global_app_settings.dart';
|
||||
import 'package:paperless_mobile/features/settings/model/global_settings.dart';
|
||||
import 'package:paperless_mobile/features/settings/view/widgets/radio_settings_dialog.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
import 'package:paperless_mobile/features/settings/view/widgets/global_settings_builder.dart';
|
||||
@@ -11,8 +10,7 @@ class LanguageSelectionSetting extends StatefulWidget {
|
||||
const LanguageSelectionSetting({super.key});
|
||||
|
||||
@override
|
||||
State<LanguageSelectionSetting> createState() =>
|
||||
_LanguageSelectionSettingState();
|
||||
State<LanguageSelectionSetting> createState() => _LanguageSelectionSettingState();
|
||||
}
|
||||
|
||||
class _LanguageSelectionSettingState extends State<LanguageSelectionSetting> {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:paperless_mobile/features/settings/cubit/application_settings_cubit.dart';
|
||||
import 'package:paperless_mobile/features/settings/view/widgets/global_settings_builder.dart';
|
||||
import 'package:paperless_mobile/features/settings/view/widgets/radio_settings_dialog.dart';
|
||||
import 'package:paperless_mobile/generated/l10n/app_localizations.dart';
|
||||
@@ -14,8 +13,7 @@ class ThemeModeSetting extends StatelessWidget {
|
||||
builder: (context, settings) {
|
||||
return ListTile(
|
||||
title: Text(S.of(context)!.appearance),
|
||||
subtitle: Text(_mapThemeModeToLocalizedString(
|
||||
settings.preferredThemeMode, context)),
|
||||
subtitle: Text(_mapThemeModeToLocalizedString(settings.preferredThemeMode, context)),
|
||||
onTap: () => showDialog<ThemeMode>(
|
||||
context: context,
|
||||
builder: (_) => RadioSettingsDialog<ThemeMode>(
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hive_flutter/adapters.dart';
|
||||
import 'package:paperless_mobile/core/config/hive/hive_config.dart';
|
||||
import 'package:paperless_mobile/features/settings/global_app_settings.dart';
|
||||
import 'package:paperless_mobile/features/settings/user_app_settings.dart';
|
||||
import 'package:paperless_mobile/features/settings/model/global_settings.dart';
|
||||
import 'package:paperless_mobile/features/settings/model/user_settings.dart';
|
||||
|
||||
class UserSettingsBuilder extends StatelessWidget {
|
||||
final Widget Function(
|
||||
BuildContext context,
|
||||
UserAppSettings? settings,
|
||||
UserSettings? settings,
|
||||
) builder;
|
||||
|
||||
const UserSettingsBuilder({
|
||||
@@ -17,14 +17,11 @@ class UserSettingsBuilder extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ValueListenableBuilder<Box<UserAppSettings>>(
|
||||
valueListenable:
|
||||
Hive.box<UserAppSettings>(HiveBoxes.userSettings).listenable(),
|
||||
return ValueListenableBuilder<Box<UserSettings>>(
|
||||
valueListenable: Hive.box<UserSettings>(HiveBoxes.userSettings).listenable(),
|
||||
builder: (context, value, _) {
|
||||
final currentUser =
|
||||
Hive.box<GlobalAppSettings>(HiveBoxes.globalSettings)
|
||||
.get(HiveBoxSingleValueKey.value)
|
||||
?.currentLoggedInUser;
|
||||
Hive.box<GlobalSettings>(HiveBoxes.globalSettings).getValue()!.currentLoggedInUser;
|
||||
if (currentUser != null) {
|
||||
final settings = value.get(currentUser);
|
||||
return builder(context, settings);
|
||||
|
||||
Reference in New Issue
Block a user