Update user list screen to properly support newer cubit logic

pull/111/head
Inex Code 2022-09-05 14:51:01 +04:00
parent 5ee1dec6b5
commit 5f58022d42
7 changed files with 118 additions and 21 deletions

View File

@ -283,6 +283,8 @@
"account": "Account", "account": "Account",
"send_registration_data": "Share login credentials", "send_registration_data": "Share login credentials",
"could_not_fetch_users": "Couldn't fetch users list", "could_not_fetch_users": "Couldn't fetch users list",
"could_not_fetch_description": "Please check your internet connection and try again",
"refresh_users": "Refresh users list",
"could_not_create_user": "Couldn't create user", "could_not_create_user": "Couldn't create user",
"could_not_delete_user": "Couldn't delete user", "could_not_delete_user": "Couldn't delete user",
"could_not_add_ssh_key": "Couldn't add SSH key" "could_not_add_ssh_key": "Couldn't add SSH key"

View File

@ -31,7 +31,6 @@ mixin UsersApi on ApiMap {
} }
} catch (e) { } catch (e) {
print(e); print(e);
print("Could not");
} }
return users; return users;
} }

View File

@ -9,29 +9,41 @@ class ServicesState extends ServerInstallationDependendState {
final List<Service> services; final List<Service> services;
bool get isPasswordManagerEnable => services bool get isPasswordManagerEnable => services
.firstWhere((final service) => service.id == 'bitwarden', .firstWhere(
orElse: () => Service.empty) (final service) => service.id == 'bitwarden',
orElse: () => Service.empty,
)
.isEnabled; .isEnabled;
bool get isCloudEnable => services bool get isCloudEnable => services
.firstWhere((final service) => service.id == 'nextcloud', .firstWhere(
orElse: () => Service.empty) (final service) => service.id == 'nextcloud',
orElse: () => Service.empty,
)
.isEnabled; .isEnabled;
bool get isGitEnable => services bool get isGitEnable => services
.firstWhere((final service) => service.id == 'gitea', .firstWhere(
orElse: () => Service.empty) (final service) => service.id == 'gitea',
orElse: () => Service.empty,
)
.isEnabled; .isEnabled;
bool get isSocialNetworkEnable => services bool get isSocialNetworkEnable => services
.firstWhere((final service) => service.id == 'pleroma', .firstWhere(
orElse: () => Service.empty) (final service) => service.id == 'pleroma',
orElse: () => Service.empty,
)
.isEnabled; .isEnabled;
bool get isVpnEnable => services bool get isVpnEnable => services
.firstWhere((final service) => service.id == 'ocserv', .firstWhere(
orElse: () => Service.empty) (final service) => service.id == 'ocserv',
orElse: () => Service.empty,
)
.isEnabled; .isEnabled;
Service? getServiceById(final String id) { Service? getServiceById(final String id) {
final service = services.firstWhere((final service) => service.id == id, final service = services.firstWhere(
orElse: () => Service.empty); (final service) => service.id == id,
orElse: () => Service.empty,
);
if (service.id == 'empty') { if (service.id == 'empty') {
return null; return null;
} }

View File

@ -16,6 +16,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
serverInstallationCubit, serverInstallationCubit,
const UsersState( const UsersState(
<User>[], <User>[],
false,
), ),
); );
Box<User> box = Hive.box<User>(BNames.usersBox); Box<User> box = Hive.box<User>(BNames.usersBox);
@ -33,6 +34,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
emit( emit(
UsersState( UsersState(
loadedUsers, loadedUsers,
false,
), ),
); );
} }
@ -44,11 +46,15 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
if (serverInstallationCubit.state is! ServerInstallationFinished) { if (serverInstallationCubit.state is! ServerInstallationFinished) {
return; return;
} }
emit(state.copyWith(isLoading: true));
// sleep for 10 seconds to simulate a slow connection
await Future<void>.delayed(const Duration(seconds: 10));
final List<User> usersFromServer = await api.getAllUsers(); final List<User> usersFromServer = await api.getAllUsers();
if (usersFromServer.isNotEmpty) { if (usersFromServer.isNotEmpty) {
emit( emit(
UsersState( UsersState(
usersFromServer, usersFromServer,
false,
), ),
); );
// Update the users it the box // Update the users it the box
@ -57,6 +63,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
} else { } else {
getIt<NavigationService>() getIt<NavigationService>()
.showSnackBar('users.could_not_fetch_users'.tr()); .showSnackBar('users.could_not_fetch_users'.tr());
emit(state.copyWith(isLoading: false));
} }
} }
@ -110,7 +117,9 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
} }
Future<void> changeUserPassword( Future<void> changeUserPassword(
final User user, final String newPassword) async { final User user,
final String newPassword,
) async {
if (user.type == UserType.root) { if (user.type == UserType.root) {
getIt<NavigationService>() getIt<NavigationService>()
.showSnackBar('users.could_not_change_password'.tr()); .showSnackBar('users.could_not_change_password'.tr());
@ -120,7 +129,8 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
await api.updateUser(user.login, newPassword); await api.updateUser(user.login, newPassword);
if (!result.success) { if (!result.success) {
getIt<NavigationService>().showSnackBar( getIt<NavigationService>().showSnackBar(
result.message ?? 'users.could_not_change_password'.tr()); result.message ?? 'users.could_not_change_password'.tr(),
);
} }
} }
@ -160,6 +170,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
emit( emit(
const UsersState( const UsersState(
<User>[], <User>[],
false,
), ),
); );
} }

View File

@ -1,9 +1,10 @@
part of 'users_cubit.dart'; part of 'users_cubit.dart';
class UsersState extends ServerInstallationDependendState { class UsersState extends ServerInstallationDependendState {
const UsersState(this.users); const UsersState(this.users, this.isLoading);
final List<User> users; final List<User> users;
final bool isLoading;
User get rootUser => User get rootUser =>
users.firstWhere((final user) => user.type == UserType.root); users.firstWhere((final user) => user.type == UserType.root);
@ -15,13 +16,15 @@ class UsersState extends ServerInstallationDependendState {
users.where((final user) => user.type == UserType.normal).toList(); users.where((final user) => user.type == UserType.normal).toList();
@override @override
List<Object> get props => [users]; List<Object> get props => [users, isLoading];
UsersState copyWith({ UsersState copyWith({
final List<User>? users, final List<User>? users,
final bool? isLoading,
}) => }) =>
UsersState( UsersState(
users ?? this.users, users ?? this.users,
isLoading ?? this.isLoading,
); );
bool isLoginRegistered(final String login) => bool isLoginRegistered(final String login) =>

View File

@ -31,3 +31,35 @@ class _NoUsers extends StatelessWidget {
), ),
); );
} }
class _CouldNotLoadUsers extends StatelessWidget {
const _CouldNotLoadUsers({required this.text});
final String text;
@override
Widget build(final BuildContext context) => Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(BrandIcons.users, size: 50, color: BrandColors.grey7),
const SizedBox(height: 20),
BrandText.h2(
'users.could_not_fetch_users'.tr(),
style: const TextStyle(
color: BrandColors.grey7,
),
),
const SizedBox(height: 10),
BrandText.medium(
text,
textAlign: TextAlign.center,
style: const TextStyle(
color: BrandColors.grey7,
),
),
],
),
);
}

View File

@ -14,6 +14,7 @@ import 'package:selfprivacy/logic/models/job.dart';
import 'package:selfprivacy/logic/models/hive/user.dart'; import 'package:selfprivacy/logic/models/hive/user.dart';
import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart'; import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart';
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart'; import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
import 'package:selfprivacy/ui/components/brand_button/outlined_button.dart';
import 'package:selfprivacy/ui/components/brand_divider/brand_divider.dart'; import 'package:selfprivacy/ui/components/brand_divider/brand_divider.dart';
import 'package:selfprivacy/ui/components/brand_header/brand_header.dart'; import 'package:selfprivacy/ui/components/brand_header/brand_header.dart';
import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart'; import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart';
@ -46,10 +47,47 @@ class UsersPage extends StatelessWidget {
} else { } else {
child = BlocBuilder<UsersCubit, UsersState>( child = BlocBuilder<UsersCubit, UsersState>(
builder: (final BuildContext context, final UsersState state) { builder: (final BuildContext context, final UsersState state) {
print('Rebuild users page'); final List<User> users = state.users
final primaryUser = state.primaryUser; .where((final user) => user.type != UserType.root)
final users = [primaryUser, ...state.users]; .toList();
// final List<User> users = [];
users.sort(
(final User a, final User b) =>
a.login.toLowerCase().compareTo(b.login.toLowerCase()),
);
if (users.isEmpty) {
if (state.isLoading) {
return const Center(
child: CircularProgressIndicator(),
);
}
return RefreshIndicator(
onRefresh: () async {
context.read<UsersCubit>().refresh();
},
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
_CouldNotLoadUsers(
text: 'users.could_not_fetch_description'.tr(),
),
const SizedBox(height: 18),
BrandOutlinedButton(
onPressed: () {
context.read<UsersCubit>().refresh();
},
title: 'users.refresh_users'.tr(),
),
],
),
),
),
);
}
return RefreshIndicator( return RefreshIndicator(
onRefresh: () async { onRefresh: () async {
context.read<UsersCubit>().refresh(); context.read<UsersCubit>().refresh();
@ -59,7 +97,7 @@ class UsersPage extends StatelessWidget {
itemBuilder: (final BuildContext context, final int index) => itemBuilder: (final BuildContext context, final int index) =>
_User( _User(
user: users[index], user: users[index],
isRootUser: index == 0, isRootUser: users[index].type == UserType.primary,
), ),
), ),
); );