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",
"send_registration_data": "Share login credentials",
"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_delete_user": "Couldn't delete user",
"could_not_add_ssh_key": "Couldn't add SSH key"

View File

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

View File

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

View File

@ -16,6 +16,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
serverInstallationCubit,
const UsersState(
<User>[],
false,
),
);
Box<User> box = Hive.box<User>(BNames.usersBox);
@ -33,6 +34,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
emit(
UsersState(
loadedUsers,
false,
),
);
}
@ -44,11 +46,15 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
if (serverInstallationCubit.state is! ServerInstallationFinished) {
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();
if (usersFromServer.isNotEmpty) {
emit(
UsersState(
usersFromServer,
false,
),
);
// Update the users it the box
@ -57,6 +63,7 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
} else {
getIt<NavigationService>()
.showSnackBar('users.could_not_fetch_users'.tr());
emit(state.copyWith(isLoading: false));
}
}
@ -110,7 +117,9 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
}
Future<void> changeUserPassword(
final User user, final String newPassword) async {
final User user,
final String newPassword,
) async {
if (user.type == UserType.root) {
getIt<NavigationService>()
.showSnackBar('users.could_not_change_password'.tr());
@ -120,7 +129,8 @@ class UsersCubit extends ServerInstallationDependendCubit<UsersState> {
await api.updateUser(user.login, newPassword);
if (!result.success) {
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(
const UsersState(
<User>[],
false,
),
);
}

View File

@ -1,9 +1,10 @@
part of 'users_cubit.dart';
class UsersState extends ServerInstallationDependendState {
const UsersState(this.users);
const UsersState(this.users, this.isLoading);
final List<User> users;
final bool isLoading;
User get rootUser =>
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();
@override
List<Object> get props => [users];
List<Object> get props => [users, isLoading];
UsersState copyWith({
final List<User>? users,
final bool? isLoading,
}) =>
UsersState(
users ?? this.users,
isLoading ?? this.isLoading,
);
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/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/outlined_button.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_icons/brand_icons.dart';
@ -46,10 +47,47 @@ class UsersPage extends StatelessWidget {
} else {
child = BlocBuilder<UsersCubit, UsersState>(
builder: (final BuildContext context, final UsersState state) {
print('Rebuild users page');
final primaryUser = state.primaryUser;
final users = [primaryUser, ...state.users];
final List<User> users = state.users
.where((final user) => user.type != UserType.root)
.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(
onRefresh: () async {
context.read<UsersCubit>().refresh();
@ -59,7 +97,7 @@ class UsersPage extends StatelessWidget {
itemBuilder: (final BuildContext context, final int index) =>
_User(
user: users[index],
isRootUser: index == 0,
isRootUser: users[index].type == UserType.primary,
),
),
);