Merge branch 'master' into 'dynamic-dns'

pull/392/head
NaiJi ✨ 2023-11-22 09:34:31 +04:00
commit cd9b47b924
30 changed files with 1847 additions and 390 deletions

View File

@ -137,7 +137,7 @@ class BackblazeApi extends RestApiMap {
{
'daysFromHidingToDeleting': 30,
'daysFromUploadingToHiding': null,
'fileNamePrefix': ''
'fileNamePrefix': '',
}
],
},

View File

@ -360,21 +360,14 @@ class HetznerApi extends RestApiMap {
return GenericResult(success: true, data: pricing);
}
Future<GenericResult<List<HetznerVolume>>> getVolumes({
final String? status,
}) async {
Future<GenericResult<List<HetznerVolume>>> getVolumes() async {
final List<HetznerVolume> volumes = [];
Response? getVolumesResonse;
Response? getVolumesResponse;
final Dio client = await getClient();
try {
getVolumesResonse = await client.get(
'/volumes',
queryParameters: {
'status': status,
},
);
for (final volume in getVolumesResonse.data['volumes']) {
getVolumesResponse = await client.get('/volumes');
for (final volume in getVolumesResponse.data['volumes']) {
volumes.add(HetznerVolume.fromJson(volume));
}
} catch (e) {
@ -391,8 +384,8 @@ class HetznerApi extends RestApiMap {
return GenericResult(
data: volumes,
success: true,
code: getVolumesResonse.statusCode,
message: getVolumesResonse.statusMessage,
code: getVolumesResponse.statusCode,
message: getVolumesResponse.statusMessage,
);
}
@ -409,7 +402,7 @@ class HetznerApi extends RestApiMap {
'labels': {'labelkey': 'value'},
'location': region,
'automount': false,
'format': 'ext4'
'format': 'ext4',
},
);
volume = HetznerVolume.fromJson(createVolumeResponse.data['volume']);
@ -586,7 +579,7 @@ class HetznerApi extends RestApiMap {
final Map<String, dynamic> queryParameters = {
'start': start.toUtc().toIso8601String(),
'end': end.toUtc().toIso8601String(),
'type': type
'type': type,
};
final Response res = await client.get(
'/servers/$serverId/metrics',

View File

@ -26,7 +26,7 @@ abstract class ServerInstallationState extends Equatable {
serverDetails,
isServerStarted,
isServerResetedFirstTime,
installationDialoguePopUp
installationDialoguePopUp,
];
final String? providerApiToken;
@ -317,7 +317,7 @@ class ServerInstallationRecovery extends ServerInstallationState {
isServerStarted,
isServerResetedFirstTime,
currentStep,
installationDialoguePopUp
installationDialoguePopUp,
];
ServerInstallationRecovery copyWith({

View File

@ -90,7 +90,7 @@ class ServerJobsCubit
ServerJobsState(
serverJobList: [
for (final ServerJob job in state.serverJobList)
if (job.uid != uid) job
if (job.uid != uid) job,
],
),
);

View File

@ -78,7 +78,7 @@ class _ProgressBarState extends State<ProgressBar> {
end: Alignment.bottomRight,
colors: [
Theme.of(context).colorScheme.primary,
Theme.of(context).colorScheme.secondary
Theme.of(context).colorScheme.secondary,
],
),
),
@ -110,7 +110,7 @@ class _ProgressBarState extends State<ProgressBar> {
style: progressTextStyleLight,
children: [
TextSpan(text: '${index + 1}.', style: style),
TextSpan(text: step, style: style)
TextSpan(text: step, style: style),
],
),
),

View File

@ -32,7 +32,7 @@ class EmptyPagePlaceholder extends StatelessWidget {
child: _expandedContent(context),
),
),
)
),
],
);

View File

@ -163,7 +163,7 @@ class BackupDetailsPage extends StatelessWidget {
autobackupPeriod != null
? 'backup.autobackup_period_subtitle'.tr(
namedArgs: {
'period': autobackupPeriod.toPrettyString(context.locale)
'period': autobackupPeriod.toPrettyString(context.locale),
},
)
: 'backup.autobackup_period_never'.tr(),
@ -337,7 +337,7 @@ class BackupDetailsPage extends StatelessWidget {
actionButtonOnPressed: () => {
context.read<BackupsCubit>().forgetSnapshot(
backup.id,
)
),
},
);
},
@ -385,7 +385,7 @@ class BackupDetailsPage extends StatelessWidget {
),
onTap: () =>
context.pushRoute(BackupsListRoute(service: null)),
)
),
],
),
const SizedBox(height: 8),

View File

@ -39,68 +39,70 @@ class BackupsListPage extends StatelessWidget {
),
)
else
...backups.map((final Backup backup) {
final service = context
.read<ServicesCubit>()
.state
.getServiceById(backup.serviceId);
return ListTile(
onTap: preventActions
? null
: () {
showModalBottomSheet(
useRootNavigator: true,
context: context,
isScrollControlled: true,
builder: (final BuildContext context) =>
DraggableScrollableSheet(
expand: false,
maxChildSize: 0.9,
minChildSize: 0.5,
initialChildSize: 0.7,
builder: (final context, final scrollController) =>
SnapshotModal(
snapshot: backup,
scrollController: scrollController,
...backups.map(
(final Backup backup) {
final service = context
.read<ServicesCubit>()
.state
.getServiceById(backup.serviceId);
return ListTile(
onTap: preventActions
? null
: () {
showModalBottomSheet(
useRootNavigator: true,
context: context,
isScrollControlled: true,
builder: (final BuildContext context) =>
DraggableScrollableSheet(
expand: false,
maxChildSize: 0.9,
minChildSize: 0.5,
initialChildSize: 0.7,
builder: (final context, final scrollController) =>
SnapshotModal(
snapshot: backup,
scrollController: scrollController,
),
),
);
},
onLongPress: preventActions
? null
: () {
showPopUpAlert(
alertTitle: 'backup.forget_snapshot'.tr(),
description: 'backup.forget_snapshot_alert'.tr(),
actionButtonTitle: 'backup.forget_snapshot'.tr(),
actionButtonOnPressed: () => {
context.read<BackupsCubit>().forgetSnapshot(
backup.id,
),
},
);
},
title: Text(
'${MaterialLocalizations.of(context).formatShortDate(backup.time)} ${TimeOfDay.fromDateTime(backup.time).format(context)}',
),
subtitle: Text(
service?.displayName ?? backup.fallbackServiceName,
),
leading: service != null
? SvgPicture.string(
service.svgIcon,
height: 24,
width: 24,
colorFilter: ColorFilter.mode(
Theme.of(context).colorScheme.onBackground,
BlendMode.srcIn,
),
);
},
onLongPress: preventActions
? null
: () {
showPopUpAlert(
alertTitle: 'backup.forget_snapshot'.tr(),
description: 'backup.forget_snapshot_alert'.tr(),
actionButtonTitle: 'backup.forget_snapshot'.tr(),
actionButtonOnPressed: () => {
context.read<BackupsCubit>().forgetSnapshot(
backup.id,
)
},
);
},
title: Text(
'${MaterialLocalizations.of(context).formatShortDate(backup.time)} ${TimeOfDay.fromDateTime(backup.time).format(context)}',
),
subtitle: Text(
service?.displayName ?? backup.fallbackServiceName,
),
leading: service != null
? SvgPicture.string(
service.svgIcon,
height: 24,
width: 24,
colorFilter: ColorFilter.mode(
Theme.of(context).colorScheme.onBackground,
BlendMode.srcIn,
)
: const Icon(
Icons.question_mark_outlined,
),
)
: const Icon(
Icons.question_mark_outlined,
),
);
})
);
},
),
],
);
}

View File

@ -172,7 +172,7 @@ class _SnapshotModalState extends State<SnapshotModal> {
isWarning: true,
text: 'backup.snapshot_modal_service_not_found'.tr(),
),
)
),
],
),
);

View File

@ -62,7 +62,7 @@ class _AppSettingsPageState extends State<AppSettingsPage> {
),
const _ResetAppTile(),
// const Divider(height: 0),
_deleteServer(context)
_deleteServer(context),
],
);
}

View File

@ -118,7 +118,7 @@ class MorePage extends StatelessWidget {
),
],
),
)
),
],
),
);

View File

@ -113,7 +113,7 @@ class _Chart extends StatelessWidget {
titles: [
'resource_chart.month'.tr(),
'resource_chart.day'.tr(),
'resource_chart.hour'.tr()
'resource_chart.hour'.tr(),
],
),
const SizedBox(height: 8),

View File

@ -86,7 +86,9 @@ class CpuChart extends StatelessWidget {
maxY: 100,
minX: 0,
titlesData: FlTitlesData(
topTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)),
topTitles: AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
interval: 40,

View File

@ -113,12 +113,14 @@ class NetworkChart extends StatelessWidget {
minY: 0,
maxY: [
...listData[0].map((final e) => e.value),
...listData[1].map((final e) => e.value)
...listData[1].map((final e) => e.value),
].reduce(max) *
1.2,
minX: 0,
titlesData: FlTitlesData(
topTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)),
topTitles: AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
interval: 40,
@ -139,7 +141,9 @@ class NetworkChart extends StatelessWidget {
showTitles: true,
),
),
leftTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)),
leftTitles: AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
rightTitles: AxisTitles(
sideTitles: SideTitles(
reservedSize: 50,
@ -154,7 +158,7 @@ class NetworkChart extends StatelessWidget {
),
interval: [
...listData[0].map((final e) => e.value),
...listData[1].map((final e) => e.value)
...listData[1].map((final e) => e.value),
].reduce(max) *
2 /
6.5,
@ -168,7 +172,7 @@ class NetworkChart extends StatelessWidget {
verticalInterval: 40,
horizontalInterval: [
...listData[0].map((final e) => e.value),
...listData[1].map((final e) => e.value)
...listData[1].map((final e) => e.value),
].reduce(max) *
2 /
6.5,

View File

@ -134,7 +134,7 @@ class _ServicePageState extends State<ServicePage> {
.read<ApiServerVolumeCubit>()
.state
.getVolume(service.storageUsage.volume ?? '')
.displayName
.displayName,
},
),
style: Theme.of(context).textTheme.bodyMedium,

View File

@ -69,7 +69,7 @@ class _ServicesPageState extends State<ServicesPage> {
),
child: _Card(service: service),
),
)
),
],
),
),
@ -179,7 +179,7 @@ class _Card extends StatelessWidget {
),
const SizedBox(height: 8),
],
)
),
],
),
),

View File

@ -49,7 +49,7 @@ class InitializingPage extends StatelessWidget {
() => _stepCheck(cubit),
() => _stepCheck(cubit),
() => _stepCheck(cubit),
() => _stepCheck(cubit)
() => _stepCheck(cubit),
][cubit.state.progress.index]();
}
@ -193,7 +193,7 @@ class InitializingPage extends StatelessWidget {
.replace(const RecoveryRoute());
},
),
)
),
],
),
],
@ -517,7 +517,7 @@ class InitializingPage extends StatelessWidget {
BrandTimer(
startDateTime: state.timerStart!,
duration: state.duration!,
)
),
],
),
if (state.isLoading)

View File

@ -9,6 +9,7 @@ import 'package:selfprivacy/logic/models/server_type.dart';
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
import 'package:selfprivacy/ui/components/info_box/info_box.dart';
import 'package:selfprivacy/ui/layouts/responsive_layout_with_infobox.dart';
import 'package:selfprivacy/utils/ui_helpers.dart';
class ServerTypePicker extends StatefulWidget {
const ServerTypePicker({
@ -329,7 +330,7 @@ class SelectTypePage extends StatelessWidget {
'initializing.choose_server_type_payment_per_month'
.tr(
args: [
'${(type.price.value + storagePrice + publicIpPrice).toStringAsFixed(4)} ${type.price.currency.shortcode}'
'${UiHelpers.formatWithPrecision(type.price.value + storagePrice + publicIpPrice)} ${type.price.currency.shortcode}',
],
),
style: Theme.of(context)
@ -370,8 +371,10 @@ class SelectTypePage extends StatelessWidget {
'initializing.choose_server_type_payment_server'
.tr(
args: [
type.price.value
.toString()
UiHelpers
.formatWithPrecision(
type.price.value,
),
],
),
style: Theme.of(context)
@ -401,7 +404,10 @@ class SelectTypePage extends StatelessWidget {
'initializing.choose_server_type_payment_storage'
.tr(
args: [
storagePrice.toString()
UiHelpers
.formatWithPrecision(
storagePrice,
),
],
),
style: Theme.of(context)
@ -432,7 +438,10 @@ class SelectTypePage extends StatelessWidget {
'initializing.choose_server_type_payment_ip'
.tr(
args: [
publicIpPrice.toString()
UiHelpers
.formatWithPrecision(
publicIpPrice,
),
],
),
style: Theme.of(context)

View File

@ -25,7 +25,7 @@ class RecoverByNewDeviceKeyInstruction extends StatelessWidget {
child: Text('recovering.method_device_button'.tr()),
onPressed: () => Navigator.of(context)
.push(materialRoute(const RecoverByNewDeviceKeyInput())),
)
),
],
);
}
@ -81,7 +81,7 @@ class RecoverByNewDeviceKeyInput extends StatelessWidget {
: () =>
context.read<RecoveryDeviceFormCubit>().trySubmit(),
child: Text('basis.continue'.tr()),
)
),
],
);
},

View File

@ -41,7 +41,7 @@ class RecoverByOldTokenInstruction extends StatelessWidget {
onPressed: () => context
.read<ServerInstallationCubit>()
.selectRecoveryMethod(ServerRecoveryMethods.oldToken),
)
),
],
),
);
@ -90,7 +90,7 @@ class RecoverByOldToken extends StatelessWidget {
? null
: () => context.read<RecoveryDeviceFormCubit>().trySubmit(),
child: Text('basis.continue'.tr()),
)
),
],
);
},

View File

@ -50,7 +50,7 @@ class RecoverByRecoveryKey extends StatelessWidget {
? null
: () => context.read<RecoveryDeviceFormCubit>().trySubmit(),
child: Text('basis.continue'.tr()),
)
),
],
);
},

View File

@ -81,7 +81,7 @@ class _RecoveryConfirmServerState extends State<RecoveryConfirmServer> {
);
}
},
)
),
],
);

View File

@ -51,7 +51,7 @@ class RecoveryMethodSelect extends StatelessWidget {
title: 'recovering.method_select_nothing'.tr(),
onPressed: () => Navigator.of(context)
.push(materialRoute(const RecoveryFallbackMethodSelect())),
)
),
],
);
}

View File

@ -136,7 +136,7 @@ class SelectDomainToRecover extends StatelessWidget {
: () =>
context.read<RecoveryDomainFormCubit>().trySubmit(),
child: Text('basis.continue'.tr()),
)
),
],
),
);

View File

@ -23,7 +23,7 @@ class RecoveryServerProviderConnected extends StatelessWidget {
heroTitle: 'recovering.provider_connected'.tr(
args: [
appConfig.state.serverDetails?.provider.displayName ??
'Server Provider'
'Server Provider',
],
),
heroSubtitle: 'recovering.provider_connected_description'.tr(
@ -45,7 +45,7 @@ class RecoveryServerProviderConnected extends StatelessWidget {
labelText: 'recovering.provider_connected_placeholder'.tr(
args: [
appConfig.state.serverDetails?.provider.displayName ??
'Server Provider'
'Server Provider',
],
),
),

View File

@ -124,7 +124,7 @@ class _DeleteUserTile extends StatelessWidget {
),
],
),
)
),
},
leading: const Icon(Icons.person_remove_outlined),
title: Text(

View File

@ -7,7 +7,7 @@ import 'package:flutter/material.dart';
const Set<TargetPlatform> _desktop = <TargetPlatform>{
TargetPlatform.linux,
TargetPlatform.macOS,
TargetPlatform.windows
TargetPlatform.windows,
};
const Set<TargetPlatform> _mobile = <TargetPlatform>{

View File

@ -1,51 +0,0 @@
import 'package:flutter/material.dart';
extension TextExtension on Text {
Text withColor(final Color color) => Text(
data!,
key: key,
strutStyle: strutStyle,
textAlign: textAlign,
textDirection: textDirection,
locale: locale,
softWrap: softWrap,
overflow: overflow,
textScaleFactor: textScaleFactor,
maxLines: maxLines,
semanticsLabel: semanticsLabel,
textWidthBasis: textWidthBasis ?? textWidthBasis,
style: style != null
? style!.copyWith(color: color)
: TextStyle(color: color),
);
Text copyWith({
final Key? key,
final StrutStyle? strutStyle,
final TextAlign? textAlign,
final TextDirection? textDirection,
final Locale? locale,
final bool? softWrap,
final TextOverflow? overflow,
final double? textScaleFactor,
final int? maxLines,
final String? semanticsLabel,
final TextWidthBasis? textWidthBasis,
final TextStyle? style,
}) =>
Text(
data!,
key: key ?? this.key,
strutStyle: strutStyle ?? this.strutStyle,
textAlign: textAlign ?? this.textAlign,
textDirection: textDirection ?? this.textDirection,
locale: locale ?? this.locale,
softWrap: softWrap ?? this.softWrap,
overflow: overflow ?? this.overflow,
textScaleFactor: textScaleFactor ?? this.textScaleFactor,
maxLines: maxLines ?? this.maxLines,
semanticsLabel: semanticsLabel ?? this.semanticsLabel,
textWidthBasis: textWidthBasis ?? this.textWidthBasis,
style: style != null ? this.style?.merge(style) ?? style : this.style,
);
}

View File

@ -1,3 +1,4 @@
import 'package:intl/intl.dart';
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
/// it's ui helpers use only for ui components, don't use for logic components.
@ -5,4 +6,14 @@ import 'package:selfprivacy/logic/cubit/server_installation/server_installation_
class UiHelpers {
static String getDomainName(final ServerInstallationState config) =>
config.isDomainSelected ? config.serverDomain!.domainName : 'example.com';
static String formatWithPrecision(
final double value, {
final int fraction = 2,
}) {
final NumberFormat formatter = NumberFormat();
formatter.minimumFractionDigits = 0;
formatter.maximumFractionDigits = fraction;
return formatter.format(value);
}
}

File diff suppressed because it is too large Load Diff