Merge branch 'master' into backblaze-refactor

This commit is contained in:
NaiJi 2023-09-19 11:13:33 -03:00
commit 49896a8e9f
11 changed files with 81 additions and 45 deletions

View file

@ -304,6 +304,7 @@
"extending_volume_price_info": "Price includes VAT and is estimated from pricing data provided by your server provider. Server will be rebooted after resizing.", "extending_volume_price_info": "Price includes VAT and is estimated from pricing data provided by your server provider. Server will be rebooted after resizing.",
"extending_volume_error": "Couldn't initialize volume extending.", "extending_volume_error": "Couldn't initialize volume extending.",
"size": "Size", "size": "Size",
"price": "Price",
"data_migration_title": "Data migration", "data_migration_title": "Data migration",
"data_migration_notice": "During migration all services will be turned off.", "data_migration_notice": "During migration all services will be turned off.",
"start_migration_button": "Start migration", "start_migration_button": "Start migration",

View file

@ -18,6 +18,32 @@ class UsersState extends ServerInstallationDependendState {
@override @override
List<Object> get props => [users, isLoading]; List<Object> get props => [users, isLoading];
/// Makes a copy of existing users list, but places 'primary'
/// to the beginning and sorts the rest alphabetically
///
/// If found a 'root' user, it doesn't get copied into the result
List<User> get orderedUsers {
User? primaryUser;
final List<User> normalUsers = [];
for (final User user in users) {
if (user.type == UserType.primary) {
primaryUser = user;
continue;
}
if (user.type == UserType.root) {
continue;
}
normalUsers.add(user);
}
normalUsers.sort(
(final User a, final User b) =>
a.login.toLowerCase().compareTo(b.login.toLowerCase()),
);
return primaryUser == null ? normalUsers : [primaryUser] + normalUsers;
}
UsersState copyWith({ UsersState copyWith({
final List<User>? users, final List<User>? users,
final bool? isLoading, final bool? isLoading,

View file

@ -1,7 +1,7 @@
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:selfprivacy/logic/models/message.dart'; import 'package:selfprivacy/logic/models/message.dart';
import 'package:selfprivacy/utils/platform_adapter.dart';
class LogListItem extends StatelessWidget { class LogListItem extends StatelessWidget {
const LogListItem({ const LogListItem({
@ -71,7 +71,7 @@ class _RestApiRequestMessageItem extends StatelessWidget {
if (message.text != null) if (message.text != null)
TextButton( TextButton(
onPressed: () { onPressed: () {
Clipboard.setData(ClipboardData(text: message.text ?? '')); PlatformAdapter.setClipboard(message.text ?? '');
}, },
child: Text('console_page.copy'.tr()), child: Text('console_page.copy'.tr()),
), ),
@ -121,7 +121,7 @@ class _RestApiResponseMessageItem extends StatelessWidget {
if (message.text != null) if (message.text != null)
TextButton( TextButton(
onPressed: () { onPressed: () {
Clipboard.setData(ClipboardData(text: message.text ?? '')); PlatformAdapter.setClipboard(message.text ?? '');
}, },
child: Text('console_page.copy'.tr()), child: Text('console_page.copy'.tr()),
), ),
@ -195,7 +195,7 @@ class _GraphQlResponseMessageItem extends StatelessWidget {
if (message.text != null) if (message.text != null)
TextButton( TextButton(
onPressed: () { onPressed: () {
Clipboard.setData(ClipboardData(text: message.text ?? '')); PlatformAdapter.setClipboard(message.text ?? '');
}, },
child: Text('console_page.copy'.tr()), child: Text('console_page.copy'.tr()),
), ),
@ -264,7 +264,7 @@ class _GraphQlRequestMessageItem extends StatelessWidget {
if (message.text != null) if (message.text != null)
TextButton( TextButton(
onPressed: () { onPressed: () {
Clipboard.setData(ClipboardData(text: message.text ?? '')); PlatformAdapter.setClipboard(message.text ?? '');
}, },
child: Text('console_page.copy'.tr()), child: Text('console_page.copy'.tr()),
), ),

View file

@ -2,11 +2,11 @@ import 'dart:async';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart'; import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
import 'package:selfprivacy/logic/cubit/backups/backups_cubit.dart'; import 'package:selfprivacy/logic/cubit/backups/backups_cubit.dart';
import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_cubit.dart'; import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_cubit.dart';
import 'package:selfprivacy/ui/components/info_box/info_box.dart'; import 'package:selfprivacy/ui/components/info_box/info_box.dart';
import 'package:selfprivacy/utils/platform_adapter.dart';
class CopyEncryptionKeyModal extends StatefulWidget { class CopyEncryptionKeyModal extends StatefulWidget {
const CopyEncryptionKeyModal({ const CopyEncryptionKeyModal({
@ -144,11 +144,7 @@ class _CopyEncryptionKeyModalState extends State<CopyEncryptionKeyModal> {
}, },
); );
}); });
Clipboard.setData( PlatformAdapter.setClipboard(encryptionKey);
ClipboardData(
text: encryptionKey,
),
);
}, },
icon: const Icon(Icons.copy_all_outlined), icon: const Icon(Icons.copy_all_outlined),
label: Text( label: Text(

View file

@ -1,7 +1,7 @@
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:selfprivacy/config/get_it_config.dart'; import 'package:selfprivacy/config/get_it_config.dart';
import 'package:selfprivacy/utils/platform_adapter.dart';
class SnapshotIdListTile extends StatelessWidget { class SnapshotIdListTile extends StatelessWidget {
const SnapshotIdListTile({ const SnapshotIdListTile({
@ -14,7 +14,7 @@ class SnapshotIdListTile extends StatelessWidget {
@override @override
Widget build(final BuildContext context) => ListTile( Widget build(final BuildContext context) => ListTile(
onLongPress: () { onLongPress: () {
Clipboard.setData(ClipboardData(text: snapshotId)); PlatformAdapter.setClipboard(snapshotId);
getIt<NavigationService>().showSnackBar( getIt<NavigationService>().showSnackBar(
'basis.copied_to_clipboard'.tr(), 'basis.copied_to_clipboard'.tr(),
behavior: SnackBarBehavior.floating, behavior: SnackBarBehavior.floating,

View file

@ -79,10 +79,12 @@ class _ExtendingVolumePageState extends State<ExtendingVolumePage> {
} }
final price = snapshot.data as Price; final price = snapshot.data as Price;
_pricePerGb = price.value; _pricePerGb = price.value;
_sizeController.text = _currentSliderGbValue.truncate().toString(); final currentSizeValue = _currentSliderGbValue.truncate().toString();
_sizeController.text = 'storage.gb'.tr(args: [currentSizeValue]);
_priceController.text = _priceController.text =
(_pricePerGb * double.parse(_sizeController.text)) '${(_pricePerGb * double.parse(currentSizeValue)).toStringAsFixed(2)}'
.toStringAsFixed(2); ' '
'${price.currency.shortcode}';
minSize = minSize =
widget.diskVolumeToResize.sizeTotal + DiskSize.fromGibibyte(3); widget.diskVolumeToResize.sizeTotal + DiskSize.fromGibibyte(3);
if (_currentSliderGbValue < 0) { if (_currentSliderGbValue < 0) {
@ -130,7 +132,7 @@ class _ExtendingVolumePageState extends State<ExtendingVolumePage> {
decoration: InputDecoration( decoration: InputDecoration(
border: const OutlineInputBorder(), border: const OutlineInputBorder(),
errorText: _isError ? ' ' : null, errorText: _isError ? ' ' : null,
labelText: price.currency.shortcode, labelText: 'storage.price'.tr(),
), ),
), ),
), ),

View file

@ -160,13 +160,15 @@ class _Card extends StatelessWidget {
], ],
), ),
Text( Text(
service.loginInfo, service.description,
style: Theme.of(context).textTheme.bodyMedium, style: Theme.of(context).textTheme.bodyMedium,
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
Text( Text(
service.description, service.loginInfo,
style: Theme.of(context).textTheme.bodyMedium, style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: Theme.of(context).colorScheme.secondary,
),
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
], ],

View file

@ -3,11 +3,11 @@ part of 'users.dart';
class _User extends StatelessWidget { class _User extends StatelessWidget {
const _User({ const _User({
required this.user, required this.user,
required this.isRootUser, required this.isPrimaryUser,
}); });
final User user; final User user;
final bool isRootUser; final bool isPrimaryUser;
@override @override
Widget build(final BuildContext context) => InkWell( Widget build(final BuildContext context) => InkWell(
onTap: () { onTap: () {
@ -32,7 +32,7 @@ class _User extends StatelessWidget {
user.login, user.login,
style: Theme.of(context).textTheme.titleMedium?.copyWith( style: Theme.of(context).textTheme.titleMedium?.copyWith(
color: Theme.of(context).colorScheme.onBackground, color: Theme.of(context).colorScheme.onBackground,
decoration: isRootUser decoration: isPrimaryUser
? TextDecoration.underline ? TextDecoration.underline
: user.isFoundOnServer : user.isFoundOnServer
? TextDecoration.none ? TextDecoration.none

View file

@ -143,17 +143,27 @@ class _UserLogins extends StatelessWidget {
final String domainName; final String domainName;
@override @override
Widget build(final BuildContext context) => FilledCard( Widget build(final BuildContext context) {
child: Column( final email = '${user.login}@$domainName';
children: [ return FilledCard(
ListTileOnSurfaceVariant( child: Column(
title: '${user.login}@$domainName', children: [
subtitle: 'users.email_login'.tr(), ListTileOnSurfaceVariant(
leadingIcon: Icons.alternate_email_outlined, onTap: () {
), PlatformAdapter.setClipboard(email);
], getIt<NavigationService>().showSnackBar(
), 'basis.copied_to_clipboard'.tr(),
); behavior: SnackBarBehavior.floating,
);
},
title: email,
subtitle: 'users.email_login'.tr(),
leadingIcon: Icons.alternate_email_outlined,
),
],
),
);
}
} }
class _SshKeysCard extends StatelessWidget { class _SshKeysCard extends StatelessWidget {

View file

@ -3,6 +3,7 @@ import 'package:cubit_form/cubit_form.dart';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:selfprivacy/config/brand_theme.dart'; import 'package:selfprivacy/config/brand_theme.dart';
import 'package:selfprivacy/config/get_it_config.dart';
import 'package:selfprivacy/logic/cubit/forms/user/ssh_form_cubit.dart'; import 'package:selfprivacy/logic/cubit/forms/user/ssh_form_cubit.dart';
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart'; import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
import 'package:selfprivacy/logic/cubit/forms/factories/field_cubit_factory.dart'; import 'package:selfprivacy/logic/cubit/forms/factories/field_cubit_factory.dart';
@ -22,6 +23,7 @@ import 'package:selfprivacy/ui/components/list_tiles/list_tile_on_surface_varian
import 'package:selfprivacy/ui/components/not_ready_card/not_ready_card.dart'; import 'package:selfprivacy/ui/components/not_ready_card/not_ready_card.dart';
import 'package:selfprivacy/ui/router/router.dart'; import 'package:selfprivacy/ui/router/router.dart';
import 'package:selfprivacy/utils/breakpoints.dart'; import 'package:selfprivacy/utils/breakpoints.dart';
import 'package:selfprivacy/utils/platform_adapter.dart';
import 'package:selfprivacy/utils/ui_helpers.dart'; import 'package:selfprivacy/utils/ui_helpers.dart';
part 'empty.dart'; part 'empty.dart';
@ -45,15 +47,7 @@ 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) {
final List<User> users = state.users final users = state.orderedUsers;
.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 (users.isEmpty) {
if (state.isLoading) { if (state.isLoading) {
return const Center( return const Center(
@ -115,7 +109,7 @@ class UsersPage extends StatelessWidget {
itemBuilder: itemBuilder:
(final BuildContext context, final int index) => _User( (final BuildContext context, final int index) => _User(
user: users[index], user: users[index],
isRootUser: users[index].type == UserType.primary, isPrimaryUser: users[index].type == UserType.primary,
), ),
), ),
), ),

View file

@ -2,6 +2,7 @@ import 'dart:io';
import 'package:device_info_plus/device_info_plus.dart'; import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
/// SelfPrivacy wrapper for Platform information provider. /// SelfPrivacy wrapper for Platform information provider.
class PlatformAdapter { class PlatformAdapter {
@ -56,4 +57,8 @@ class PlatformAdapter {
return 'Unidentified'; return 'Unidentified';
} }
static void setClipboard(final String clipboardData) {
Clipboard.setData(ClipboardData(text: clipboardData));
}
} }