Compare commits

..

5 Commits

Author SHA1 Message Date
Inex Code 11d0e58334 fix: Flatpak builds didn't work 2024-04-26 18:08:04 +03:00
NaiJi ✨ a6b846cc78 feat(backups): Show how much space a service uses on backup (#500)
continuous-integration/drone/push Build is passing Details
Fixes #434

![image](/attachments/351cc025-8dae-44f2-9bca-18f8950e0780)

Co-authored-by: Inex Code <inex.code@selfprivacy.org>
Reviewed-on: #500
Reviewed-by: Inex Code <inex.code@selfprivacy.org>
Co-authored-by: NaiJi  <naiji@noreply.git.selfprivacy.org>
Co-committed-by: NaiJi  <naiji@noreply.git.selfprivacy.org>
2024-04-24 13:18:02 +03:00
NaiJi ✨ 6819192219 feat: Add country names to installation process (#501)
continuous-integration/drone/push Build is passing Details
Fixes #494

Reviewed-on: #501
Reviewed-by: Inex Code <inex.code@selfprivacy.org>
Co-authored-by: NaiJi  <naiji@noreply.git.selfprivacy.org>
Co-committed-by: NaiJi  <naiji@noreply.git.selfprivacy.org>
2024-04-24 12:54:32 +03:00
NaiJi ✨ ffdb9d92fb Merge pull request 'fix(backups): Implement filtering for enabled services for backups' (#499) from filter-enabled-backup-services into master
continuous-integration/drone/push Build is passing Details
Reviewed-on: #499
Reviewed-by: Inex Code <inex.code@selfprivacy.org>
2024-04-17 18:48:56 +03:00
NaiJi ✨ 1c42598787 fix(backups): Implement filtering for enabled services for backups
- Resolve: #433
2024-04-16 23:03:11 +04:00
14 changed files with 153 additions and 14 deletions

View File

@ -606,5 +606,16 @@
"reset_onboarding": "Reset onboarding switch", "reset_onboarding": "Reset onboarding switch",
"reset_onboarding_description": "Reset onboarding switch to show onboarding screen again", "reset_onboarding_description": "Reset onboarding switch to show onboarding screen again",
"cubit_statuses": "Cubit loading statuses" "cubit_statuses": "Cubit loading statuses"
},
"countries": {
"germany": "Germany",
"netherlands": "Netherlands",
"singapore": "Singapore",
"united_kingdom": "United Kingdom",
"canada": "Canada",
"india": "India",
"australia": "Australia",
"united_states": "United States",
"finland": "Finland"
} }
} }

View File

@ -32,6 +32,16 @@ class HiveConfig {
await getEncryptedKey(BNames.serverInstallationEncryptionKey), await getEncryptedKey(BNames.serverInstallationEncryptionKey),
); );
await Hive.openBox<User>(BNames.usersDeprecated);
await Hive.openBox<User>(BNames.usersBox, encryptionCipher: cipher);
final Box<User> deprecatedUsers = Hive.box<User>(BNames.usersDeprecated);
if (deprecatedUsers.isNotEmpty) {
final Box<User> users = Hive.box<User>(BNames.usersBox);
await users.addAll(deprecatedUsers.values.toList());
await deprecatedUsers.clear();
}
await Hive.openBox(BNames.serverInstallationBox, encryptionCipher: cipher); await Hive.openBox(BNames.serverInstallationBox, encryptionCipher: cipher);
} }
@ -62,7 +72,7 @@ class BNames {
/// A boolean field of [appSettingsBox] box. /// A boolean field of [appSettingsBox] box.
static String isOnboardingShowing = 'isOnboardingShowing'; static String isOnboardingShowing = 'isOnboardingShowing';
/// Encryption key to decrypt [serverInstallationBox] box. /// Encryption key to decrypt [serverInstallationBox] and [usersBox] box.
static String serverInstallationEncryptionKey = 'key'; static String serverInstallationEncryptionKey = 'key';
/// Server installation box. Contains server details and provider tokens. /// Server installation box. Contains server details and provider tokens.
@ -121,4 +131,10 @@ class BNames {
/// A boolean field of [serverInstallationBox] box. /// A boolean field of [serverInstallationBox] box.
static String isRecoveringServer = 'isRecoveringServer'; static String isRecoveringServer = 'isRecoveringServer';
/// Deprecated users box as it is unencrypted
static String usersDeprecated = 'users';
/// Box with users
static String usersBox = 'usersEncrypted';
} }

View File

@ -34,6 +34,7 @@ class ServerAuthorizationException implements Exception {
class ServerInstallationRepository { class ServerInstallationRepository {
Box box = Hive.box(BNames.serverInstallationBox); Box box = Hive.box(BNames.serverInstallationBox);
Box<User> usersBox = Hive.box(BNames.usersBox);
Future<ServerInstallationState> load() async { Future<ServerInstallationState> load() async {
final String? providerApiToken = getIt<ApiConfigModel>().serverProviderKey; final String? providerApiToken = getIt<ApiConfigModel>().serverProviderKey;
@ -176,6 +177,7 @@ class ServerInstallationRepository {
void clearAppConfig() { void clearAppConfig() {
box.clear(); box.clear();
usersBox.clear();
} }
Future<ServerHostingDetails> startServer( Future<ServerHostingDetails> startServer(

View File

@ -49,11 +49,11 @@ abstract class ServerInstallationState extends Equatable {
bool get isPrimaryUserFilled => rootUser != null; bool get isPrimaryUserFilled => rootUser != null;
bool get isServerCreated => serverDetails != null; bool get isServerCreated => serverDetails != null;
bool get isFullyInitialized => _fulfillmentList.every((final el) => el!); bool get isFullyInitilized => _fulfilementList.every((final el) => el!);
ServerSetupProgress get progress => ServerSetupProgress ServerSetupProgress get progress => ServerSetupProgress
.values[_fulfillmentList.where((final el) => el!).length]; .values[_fulfilementList.where((final el) => el!).length];
int get progressBar { int get porgressBar {
if (progress.index < 6) { if (progress.index < 6) {
return progress.index; return progress.index;
} else if (progress.index < 10) { } else if (progress.index < 10) {
@ -63,7 +63,7 @@ abstract class ServerInstallationState extends Equatable {
} }
} }
List<bool?> get _fulfillmentList { List<bool?> get _fulfilementList {
final List<bool> res = [ final List<bool> res = [
isServerProviderApiKeyFilled, isServerProviderApiKeyFilled,
isServerTypeFilled, isServerTypeFilled,
@ -118,7 +118,7 @@ class TimerState extends ServerInstallationNotFinished {
enum ServerSetupProgress { enum ServerSetupProgress {
nothingYet, nothingYet,
serverProviderFilled, serverProviderFilled,
serverTypeFilled, servertTypeFilled,
dnsProviderFilled, dnsProviderFilled,
backblazeFilled, backblazeFilled,
domainFilled, domainFilled,

View File

@ -65,14 +65,59 @@ class DigitalOceanLocation {
emoji = '🇮🇳'; emoji = '🇮🇳';
break; break;
case 'syd':
emoji = '🇦🇺';
break;
case 'nyc': case 'nyc':
case 'sfo': case 'sfo':
emoji = '🇺🇸'; emoji = '🇺🇸';
break; break;
} }
return emoji; return emoji;
} }
String get countryDisplayKey {
String displayKey = 'countries.';
switch (slug.substring(0, 3)) {
case 'fra':
displayKey += 'germany';
break;
case 'ams':
displayKey += 'netherlands';
break;
case 'sgp':
displayKey += 'singapore';
break;
case 'lon':
displayKey += 'united_kingdom';
break;
case 'tor':
displayKey += 'canada';
break;
case 'blr':
displayKey += 'india';
break;
case 'syd':
displayKey += 'australia';
break;
case 'nyc':
case 'sfo':
displayKey += 'united_states';
break;
default:
displayKey = slug;
}
return displayKey;
}
} }
@JsonSerializable() @JsonSerializable()

View File

@ -155,6 +155,27 @@ class HetznerLocation {
} }
return emoji; return emoji;
} }
String get countryDisplayKey {
String displayKey = 'countries.';
switch (country.substring(0, 2)) {
case 'DE':
displayKey += 'germany';
break;
case 'FI':
displayKey += 'finland';
break;
case 'US':
displayKey += 'united_states';
break;
default:
displayKey = country;
}
return displayKey;
}
} }
/// A Volume is a highly-available, scalable, and SSD-based block storage for Servers. /// A Volume is a highly-available, scalable, and SSD-based block storage for Servers.

View File

@ -11,7 +11,7 @@ class Price {
enum CurrencyType { enum CurrencyType {
eur, eur,
usd, usd,
unknown, unkown,
} }
class Currency { class Currency {

View File

@ -2,12 +2,14 @@ class ServerProviderLocation {
ServerProviderLocation({ ServerProviderLocation({
required this.title, required this.title,
required this.identifier, required this.identifier,
required this.countryDisplayKey,
this.description, this.description,
this.flag = '', this.flag = '',
}); });
final String title; final String title;
final String identifier; final String identifier;
final String countryDisplayKey;
final String? description; final String? description;
final String flag; final String flag;
} }

View File

@ -438,6 +438,7 @@ class DigitalOceanServerProvider extends ServerProvider {
description: rawLocation.name, description: rawLocation.name,
flag: rawLocation.flag, flag: rawLocation.flag,
identifier: rawLocation.slug, identifier: rawLocation.slug,
countryDisplayKey: rawLocation.countryDisplayKey,
); );
} catch (e) { } catch (e) {
continue; continue;

View File

@ -156,6 +156,7 @@ class HetznerServerProvider extends ServerProvider {
description: server.location.description, description: server.location.description,
flag: server.location.flag, flag: server.location.flag,
identifier: server.location.name, identifier: server.location.name,
countryDisplayKey: server.location.countryDisplayKey,
), ),
), ),
); );
@ -456,6 +457,7 @@ class HetznerServerProvider extends ServerProvider {
description: rawLocation.description, description: rawLocation.description,
flag: rawLocation.flag, flag: rawLocation.flag,
identifier: rawLocation.name, identifier: rawLocation.name,
countryDisplayKey: rawLocation.countryDisplayKey,
); );
} catch (e) { } catch (e) {
continue; continue;

View File

@ -38,8 +38,14 @@ class BackupDetailsPage extends StatelessWidget {
: StateType.uninitialized; : StateType.uninitialized;
final bool preventActions = backupsState.preventActions; final bool preventActions = backupsState.preventActions;
final List<Backup> backups = backupsState.backups; final List<Backup> backups = backupsState.backups;
final List<Service> services = final List<Service> services = context
context.watch<ServicesBloc>().state.servicesThatCanBeBackedUp; .watch<ServicesBloc>()
.state
.servicesThatCanBeBackedUp
.where(
(final service) => service.isEnabled,
)
.toList();
final Duration? autobackupPeriod = backupsState.autobackupPeriod; final Duration? autobackupPeriod = backupsState.autobackupPeriod;
final List<ServerJob> backupJobs = context final List<ServerJob> backupJobs = context
.watch<ServerJobsBloc>() .watch<ServerJobsBloc>()

View File

@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:selfprivacy/logic/bloc/backups/backups_bloc.dart'; import 'package:selfprivacy/logic/bloc/backups/backups_bloc.dart';
import 'package:selfprivacy/logic/bloc/server_jobs/server_jobs_bloc.dart'; import 'package:selfprivacy/logic/bloc/server_jobs/server_jobs_bloc.dart';
import 'package:selfprivacy/logic/bloc/volumes/volumes_bloc.dart';
import 'package:selfprivacy/logic/models/json/server_job.dart'; import 'package:selfprivacy/logic/models/json/server_job.dart';
import 'package:selfprivacy/logic/models/service.dart'; import 'package:selfprivacy/logic/models/service.dart';
@ -103,6 +104,29 @@ class _CreateBackupsModalState extends State<CreateBackupsModal> {
...widget.services.map( ...widget.services.map(
(final Service service) { (final Service service) {
final bool busy = busyServices.contains(service.id); final bool busy = busyServices.contains(service.id);
final List<Widget> descriptionWidgets = [];
if (busy) {
descriptionWidgets.add(Text('backup.service_busy'.tr()));
} else {
descriptionWidgets.add(
Text(
'service_page.uses'.tr(
namedArgs: {
'usage': service.storageUsage.used.toString(),
'volume': context
.read<VolumesBloc>()
.state
.getVolume(service.storageUsage.volume ?? '')
.displayName,
},
),
style: Theme.of(context).textTheme.labelMedium,
),
);
descriptionWidgets.add(
Text(service.backupDescription),
);
}
return CheckboxListTile.adaptive( return CheckboxListTile.adaptive(
onChanged: !busy onChanged: !busy
? (final bool? value) { ? (final bool? value) {
@ -122,8 +146,9 @@ class _CreateBackupsModalState extends State<CreateBackupsModal> {
title: Text( title: Text(
service.displayName, service.displayName,
), ),
subtitle: Text( subtitle: Column(
busy ? 'backup.service_busy'.tr() : service.backupDescription, crossAxisAlignment: CrossAxisAlignment.start,
children: descriptionWidgets,
), ),
secondary: SvgPicture.string( secondary: SvgPicture.string(
service.svgIcon, service.svgIcon,

View File

@ -112,7 +112,7 @@ class InitializingPage extends StatelessWidget {
'Server', 'Server',
'Installation', 'Installation',
], ],
activeIndex: cubit.state.progressBar, activeIndex: cubit.state.porgressBar,
), ),
), ),
), ),

View File

@ -120,6 +120,14 @@ class SelectLocationPage extends StatelessWidget {
.titleMedium, .titleMedium,
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
Text(
location.countryDisplayKey.tr(),
style: Theme.of(context)
.textTheme
.bodyMedium,
),
if (location.description != null)
const SizedBox(height: 4),
if (location.description != null) if (location.description != null)
Text( Text(
location.description!, location.description!,