mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2024-10-31 22:17:29 +00:00
Merge branch 'feature/service-configurations' into dkim
# Conflicts: # lib/logic/api_maps/hetzner.dart # lib/logic/api_maps/server.dart # lib/logic/cubit/backups/backups_cubit.dart # lib/logic/cubit/forms/initializing/cloudflare_form_cubit.dart # lib/logic/models/job.dart # lib/ui/pages/initializing/initializing.dart # lib/ui/pages/providers/providers.dart # pubspec.lock # pubspec.yaml
This commit is contained in:
commit
e4bdd47848
|
@ -61,4 +61,4 @@ SPEC CHECKSUMS:
|
||||||
|
|
||||||
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
|
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
|
||||||
|
|
||||||
COCOAPODS: 1.10.1
|
COCOAPODS: 1.11.2
|
||||||
|
|
|
@ -157,7 +157,7 @@
|
||||||
97C146E61CF9000F007C117D /* Project object */ = {
|
97C146E61CF9000F007C117D /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastUpgradeCheck = 1020;
|
LastUpgradeCheck = 1300;
|
||||||
ORGANIZATIONNAME = "";
|
ORGANIZATIONNAME = "";
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
97C146ED1CF9000F007C117D = {
|
97C146ED1CF9000F007C117D = {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "1020"
|
LastUpgradeVersion = "1300"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
|
|
|
@ -2,7 +2,6 @@ import 'dart:convert';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
import 'package:hive/hive.dart';
|
|
||||||
import 'package:hive_flutter/hive_flutter.dart';
|
import 'package:hive_flutter/hive_flutter.dart';
|
||||||
import 'package:selfprivacy/logic/models/backblaze_bucket.dart';
|
import 'package:selfprivacy/logic/models/backblaze_bucket.dart';
|
||||||
import 'package:selfprivacy/logic/models/backblaze_credential.dart';
|
import 'package:selfprivacy/logic/models/backblaze_credential.dart';
|
||||||
|
|
|
@ -6,7 +6,6 @@ import 'package:dio/adapter.dart';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
|
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
|
||||||
import 'package:selfprivacy/config/get_it_config.dart';
|
import 'package:selfprivacy/config/get_it_config.dart';
|
||||||
import 'package:selfprivacy/logic/get_it/console.dart';
|
|
||||||
import 'package:selfprivacy/logic/models/message.dart';
|
import 'package:selfprivacy/logic/models/message.dart';
|
||||||
|
|
||||||
abstract class ApiMap {
|
abstract class ApiMap {
|
||||||
|
|
|
@ -5,8 +5,10 @@ import 'dart:io';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:selfprivacy/config/get_it_config.dart';
|
import 'package:selfprivacy/config/get_it_config.dart';
|
||||||
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
|
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
|
||||||
|
import 'package:selfprivacy/logic/models/auto_upgrade_settings.dart';
|
||||||
import 'package:selfprivacy/logic/models/backblaze_bucket.dart';
|
import 'package:selfprivacy/logic/models/backblaze_bucket.dart';
|
||||||
import 'package:selfprivacy/logic/models/backup.dart';
|
import 'package:selfprivacy/logic/models/backup.dart';
|
||||||
|
import 'package:selfprivacy/logic/models/timezone_settings.dart';
|
||||||
import 'package:selfprivacy/logic/models/user.dart';
|
import 'package:selfprivacy/logic/models/user.dart';
|
||||||
|
|
||||||
import 'api_map.dart';
|
import 'api_map.dart';
|
||||||
|
@ -238,6 +240,39 @@ class ServerApi extends ApiMap {
|
||||||
return response.statusCode == HttpStatus.ok;
|
return response.statusCode == HttpStatus.ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<AutoUpgradeSettings> getAutoUpgradeSettings() async {
|
||||||
|
var client = await getClient();
|
||||||
|
Response response = await client.get('/system/configuration/autoUpgrade');
|
||||||
|
client.close();
|
||||||
|
return AutoUpgradeSettings.fromJson(response.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> updateAutoUpgradeSettings(AutoUpgradeSettings settings) async {
|
||||||
|
var client = await getClient();
|
||||||
|
await client.put(
|
||||||
|
'/system/configuration/autoUpgrade',
|
||||||
|
data: settings.toJson(),
|
||||||
|
);
|
||||||
|
client.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<TimeZoneSettings> getServerTimezone() async {
|
||||||
|
var client = await getClient();
|
||||||
|
Response response = await client.get('/system/configuration/timezone');
|
||||||
|
client.close();
|
||||||
|
|
||||||
|
return TimeZoneSettings.fromString(response.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> updateServerTimezone(TimeZoneSettings settings) async {
|
||||||
|
var client = await getClient();
|
||||||
|
await client.put(
|
||||||
|
'/system/configuration/timezone',
|
||||||
|
data: settings.toJson(),
|
||||||
|
);
|
||||||
|
client.close();
|
||||||
|
}
|
||||||
|
|
||||||
Future<String> getDkim() async {
|
Future<String> getDkim() async {
|
||||||
var client = await getClient();
|
var client = await getClient();
|
||||||
Response response = await client.get('/services/mailserver/dkim');
|
Response response = await client.get('/services/mailserver/dkim');
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:selfprivacy/config/get_it_config.dart';
|
import 'package:selfprivacy/config/get_it_config.dart';
|
||||||
|
import 'package:selfprivacy/logic/api_maps/backblaze.dart';
|
||||||
|
import 'package:selfprivacy/logic/api_maps/server.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/models/backblaze_bucket.dart';
|
import 'package:selfprivacy/logic/models/backblaze_bucket.dart';
|
||||||
import 'package:selfprivacy/logic/models/backup.dart';
|
import 'package:selfprivacy/logic/models/backup.dart';
|
||||||
import 'package:selfprivacy/logic/api_maps/server.dart';
|
|
||||||
import 'package:selfprivacy/logic/api_maps/backblaze.dart';
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
|
||||||
|
|
||||||
part 'backups_state.dart';
|
part 'backups_state.dart';
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,11 @@ class CloudFlareFormCubit extends FormCubit {
|
||||||
ValidationModel<String>(
|
ValidationModel<String>(
|
||||||
(s) => regExp.hasMatch(s), 'validations.key_format'.tr()),
|
(s) => regExp.hasMatch(s), 'validations.key_format'.tr()),
|
||||||
LengthStringValidationWithLengthShowing(
|
LengthStringValidationWithLengthShowing(
|
||||||
40, 'validations.length'.tr(args: ["40"]))
|
40,
|
||||||
|
'validations.length'.tr(
|
||||||
|
args: ["40"],
|
||||||
|
),
|
||||||
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ class JobsCubit extends Cubit<JobsState> {
|
||||||
emit(newState);
|
emit(newState);
|
||||||
}
|
}
|
||||||
|
|
||||||
void createOrRemoveServiceToggleJob(ServiceToggleJob job) {
|
void createOrRemoveServiceToggleJob(ToggleJob job) {
|
||||||
var newJobsList = <Job>[];
|
var newJobsList = <Job>[];
|
||||||
if (state is JobsStateWithJobs) {
|
if (state is JobsStateWithJobs) {
|
||||||
newJobsList.addAll((state as JobsStateWithJobs).jobList);
|
newJobsList.addAll((state as JobsStateWithJobs).jobList);
|
||||||
|
|
|
@ -2,7 +2,9 @@ import 'package:bloc/bloc.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:selfprivacy/config/get_it_config.dart';
|
import 'package:selfprivacy/config/get_it_config.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/server_detailed_info/server_detailed_info_repository.dart';
|
import 'package:selfprivacy/logic/cubit/server_detailed_info/server_detailed_info_repository.dart';
|
||||||
|
import 'package:selfprivacy/logic/models/auto_upgrade_settings.dart';
|
||||||
import 'package:selfprivacy/logic/models/hetzner_server_info.dart';
|
import 'package:selfprivacy/logic/models/hetzner_server_info.dart';
|
||||||
|
import 'package:selfprivacy/logic/models/timezone_settings.dart';
|
||||||
|
|
||||||
part 'server_detailed_info_state.dart';
|
part 'server_detailed_info_state.dart';
|
||||||
|
|
||||||
|
@ -16,7 +18,12 @@ class ServerDetailsCubit extends Cubit<ServerDetailsState> {
|
||||||
if (isReadyToCheck) {
|
if (isReadyToCheck) {
|
||||||
emit(ServerDetailsLoading());
|
emit(ServerDetailsLoading());
|
||||||
var data = await repository.load();
|
var data = await repository.load();
|
||||||
emit(Loaded(serverInfo: data, checkTime: DateTime.now()));
|
emit(Loaded(
|
||||||
|
serverInfo: data.hetznerServerInfo,
|
||||||
|
autoUpgradeSettings: data.autoUpgradeSettings,
|
||||||
|
serverTimezone: data.serverTimezone,
|
||||||
|
checkTime: DateTime.now(),
|
||||||
|
));
|
||||||
} else {
|
} else {
|
||||||
emit(ServerDetailsNotReady());
|
emit(ServerDetailsNotReady());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,33 @@
|
||||||
import 'package:selfprivacy/logic/api_maps/hetzner.dart';
|
import 'package:selfprivacy/logic/api_maps/hetzner.dart';
|
||||||
|
import 'package:selfprivacy/logic/api_maps/server.dart';
|
||||||
|
import 'package:selfprivacy/logic/models/auto_upgrade_settings.dart';
|
||||||
import 'package:selfprivacy/logic/models/hetzner_server_info.dart';
|
import 'package:selfprivacy/logic/models/hetzner_server_info.dart';
|
||||||
|
import 'package:selfprivacy/logic/models/timezone_settings.dart';
|
||||||
|
|
||||||
class ServerDetailsRepository {
|
class ServerDetailsRepository {
|
||||||
Future<HetznerServerInfo> load() async {
|
var hetznerAPi = HetznerApi();
|
||||||
var client = HetznerApi();
|
var selfprivacyServer = ServerApi();
|
||||||
return await client.getInfo();
|
|
||||||
|
Future<_ServerDetailsRepositoryDto> load() async {
|
||||||
|
print('load');
|
||||||
|
return _ServerDetailsRepositoryDto(
|
||||||
|
autoUpgradeSettings: await selfprivacyServer.getAutoUpgradeSettings(),
|
||||||
|
hetznerServerInfo: await hetznerAPi.getInfo(),
|
||||||
|
serverTimezone: await selfprivacyServer.getServerTimezone(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _ServerDetailsRepositoryDto {
|
||||||
|
final HetznerServerInfo hetznerServerInfo;
|
||||||
|
|
||||||
|
final TimeZoneSettings serverTimezone;
|
||||||
|
|
||||||
|
final AutoUpgradeSettings autoUpgradeSettings;
|
||||||
|
|
||||||
|
_ServerDetailsRepositoryDto({
|
||||||
|
required this.hetznerServerInfo,
|
||||||
|
required this.serverTimezone,
|
||||||
|
required this.autoUpgradeSettings,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -17,13 +17,24 @@ class Loading extends ServerDetailsState {}
|
||||||
|
|
||||||
class Loaded extends ServerDetailsState {
|
class Loaded extends ServerDetailsState {
|
||||||
final HetznerServerInfo serverInfo;
|
final HetznerServerInfo serverInfo;
|
||||||
|
|
||||||
|
final TimeZoneSettings serverTimezone;
|
||||||
|
|
||||||
|
final AutoUpgradeSettings autoUpgradeSettings;
|
||||||
final DateTime checkTime;
|
final DateTime checkTime;
|
||||||
|
|
||||||
Loaded({
|
Loaded({
|
||||||
required this.serverInfo,
|
required this.serverInfo,
|
||||||
|
required this.serverTimezone,
|
||||||
|
required this.autoUpgradeSettings,
|
||||||
required this.checkTime,
|
required this.checkTime,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [serverInfo, checkTime];
|
List<Object> get props => [
|
||||||
|
serverInfo,
|
||||||
|
serverTimezone,
|
||||||
|
autoUpgradeSettings,
|
||||||
|
checkTime,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ import 'package:hive/hive.dart';
|
||||||
import 'package:selfprivacy/config/hive_config.dart';
|
import 'package:selfprivacy/config/hive_config.dart';
|
||||||
import 'package:selfprivacy/logic/api_maps/server.dart';
|
import 'package:selfprivacy/logic/api_maps/server.dart';
|
||||||
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
|
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart';
|
|
||||||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||||
|
|
||||||
part 'services_state.dart';
|
part 'services_state.dart';
|
||||||
|
|
22
lib/logic/models/auto_upgrade_settings.dart
Normal file
22
lib/logic/models/auto_upgrade_settings.dart
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
|
||||||
|
part 'auto_upgrade_settings.g.dart';
|
||||||
|
|
||||||
|
@JsonSerializable(createToJson: true)
|
||||||
|
class AutoUpgradeSettings extends Equatable {
|
||||||
|
final bool enable;
|
||||||
|
final bool allowReboot;
|
||||||
|
|
||||||
|
AutoUpgradeSettings({
|
||||||
|
required this.enable,
|
||||||
|
required this.allowReboot,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [enable, allowReboot];
|
||||||
|
factory AutoUpgradeSettings.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$AutoUpgradeSettingsFromJson(json);
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() => _$AutoUpgradeSettingsToJson(this);
|
||||||
|
}
|
20
lib/logic/models/auto_upgrade_settings.g.dart
Normal file
20
lib/logic/models/auto_upgrade_settings.g.dart
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'auto_upgrade_settings.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
AutoUpgradeSettings _$AutoUpgradeSettingsFromJson(Map<String, dynamic> json) =>
|
||||||
|
AutoUpgradeSettings(
|
||||||
|
enable: json['enable'] as bool,
|
||||||
|
allowReboot: json['allowReboot'] as bool,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$AutoUpgradeSettingsToJson(
|
||||||
|
AutoUpgradeSettings instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'enable': instance.enable,
|
||||||
|
'allowReboot': instance.allowReboot,
|
||||||
|
};
|
|
@ -6,46 +6,16 @@ part of 'backup.dart';
|
||||||
// JsonSerializableGenerator
|
// JsonSerializableGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
Backup _$BackupFromJson(Map<String, dynamic> json) {
|
Backup _$BackupFromJson(Map<String, dynamic> json) => Backup(
|
||||||
return Backup(
|
time: DateTime.parse(json['time'] as String),
|
||||||
time: DateTime.parse(json['time'] as String),
|
id: json['short_id'] as String,
|
||||||
id: json['short_id'] as String,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
BackupStatus _$BackupStatusFromJson(Map<String, dynamic> json) {
|
|
||||||
return BackupStatus(
|
|
||||||
status: _$enumDecode(_$BackupStatusEnumEnumMap, json['status']),
|
|
||||||
progress: (json['progress'] as num).toDouble(),
|
|
||||||
errorMessage: json['error_message'] as String?,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
K _$enumDecode<K, V>(
|
|
||||||
Map<K, V> enumValues,
|
|
||||||
Object? source, {
|
|
||||||
K? unknownValue,
|
|
||||||
}) {
|
|
||||||
if (source == null) {
|
|
||||||
throw ArgumentError(
|
|
||||||
'A value must be provided. Supported values: '
|
|
||||||
'${enumValues.values.join(', ')}',
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
return enumValues.entries.singleWhere(
|
BackupStatus _$BackupStatusFromJson(Map<String, dynamic> json) => BackupStatus(
|
||||||
(e) => e.value == source,
|
status: $enumDecode(_$BackupStatusEnumEnumMap, json['status']),
|
||||||
orElse: () {
|
progress: (json['progress'] as num).toDouble(),
|
||||||
if (unknownValue == null) {
|
errorMessage: json['error_message'] as String?,
|
||||||
throw ArgumentError(
|
);
|
||||||
'`$source` is not one of the supported values: '
|
|
||||||
'${enumValues.values.join(', ')}',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return MapEntry(unknownValue, enumValues.values.first);
|
|
||||||
},
|
|
||||||
).key;
|
|
||||||
}
|
|
||||||
|
|
||||||
const _$BackupStatusEnumEnumMap = {
|
const _$BackupStatusEnumEnumMap = {
|
||||||
BackupStatusEnum.noKey: 'NO_KEY',
|
BackupStatusEnum.noKey: 'NO_KEY',
|
||||||
|
|
|
@ -6,42 +6,16 @@ part of 'hetzner_server_info.dart';
|
||||||
// JsonSerializableGenerator
|
// JsonSerializableGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
HetznerServerInfo _$HetznerServerInfoFromJson(Map<String, dynamic> json) {
|
HetznerServerInfo _$HetznerServerInfoFromJson(Map<String, dynamic> json) =>
|
||||||
return HetznerServerInfo(
|
HetznerServerInfo(
|
||||||
json['id'] as int,
|
json['id'] as int,
|
||||||
json['name'] as String,
|
json['name'] as String,
|
||||||
_$enumDecode(_$ServerStatusEnumMap, json['status']),
|
$enumDecode(_$ServerStatusEnumMap, json['status']),
|
||||||
DateTime.parse(json['created'] as String),
|
DateTime.parse(json['created'] as String),
|
||||||
HetznerServerTypeInfo.fromJson(json['server_type'] as Map<String, dynamic>),
|
HetznerServerTypeInfo.fromJson(
|
||||||
HetznerServerInfo.locationFromJson(json['datacenter'] as Map),
|
json['server_type'] as Map<String, dynamic>),
|
||||||
);
|
HetznerServerInfo.locationFromJson(json['datacenter'] as Map),
|
||||||
}
|
|
||||||
|
|
||||||
K _$enumDecode<K, V>(
|
|
||||||
Map<K, V> enumValues,
|
|
||||||
Object? source, {
|
|
||||||
K? unknownValue,
|
|
||||||
}) {
|
|
||||||
if (source == null) {
|
|
||||||
throw ArgumentError(
|
|
||||||
'A value must be provided. Supported values: '
|
|
||||||
'${enumValues.values.join(', ')}',
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
return enumValues.entries.singleWhere(
|
|
||||||
(e) => e.value == source,
|
|
||||||
orElse: () {
|
|
||||||
if (unknownValue == null) {
|
|
||||||
throw ArgumentError(
|
|
||||||
'`$source` is not one of the supported values: '
|
|
||||||
'${enumValues.values.join(', ')}',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return MapEntry(unknownValue, enumValues.values.first);
|
|
||||||
},
|
|
||||||
).key;
|
|
||||||
}
|
|
||||||
|
|
||||||
const _$ServerStatusEnumMap = {
|
const _$ServerStatusEnumMap = {
|
||||||
ServerStatus.running: 'running',
|
ServerStatus.running: 'running',
|
||||||
|
@ -56,29 +30,26 @@ const _$ServerStatusEnumMap = {
|
||||||
};
|
};
|
||||||
|
|
||||||
HetznerServerTypeInfo _$HetznerServerTypeInfoFromJson(
|
HetznerServerTypeInfo _$HetznerServerTypeInfoFromJson(
|
||||||
Map<String, dynamic> json) {
|
Map<String, dynamic> json) =>
|
||||||
return HetznerServerTypeInfo(
|
HetznerServerTypeInfo(
|
||||||
json['cores'] as int,
|
json['cores'] as int,
|
||||||
json['memory'] as num,
|
json['memory'] as num,
|
||||||
json['disk'] as int,
|
json['disk'] as int,
|
||||||
(json['prices'] as List<dynamic>)
|
(json['prices'] as List<dynamic>)
|
||||||
.map((e) => HetznerPriceInfo.fromJson(e as Map<String, dynamic>))
|
.map((e) => HetznerPriceInfo.fromJson(e as Map<String, dynamic>))
|
||||||
.toList(),
|
.toList(),
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
HetznerPriceInfo _$HetznerPriceInfoFromJson(Map<String, dynamic> json) {
|
HetznerPriceInfo _$HetznerPriceInfoFromJson(Map<String, dynamic> json) =>
|
||||||
return HetznerPriceInfo(
|
HetznerPriceInfo(
|
||||||
HetznerPriceInfo.getPrice(json['price_hourly'] as Map),
|
HetznerPriceInfo.getPrice(json['price_hourly'] as Map),
|
||||||
HetznerPriceInfo.getPrice(json['price_monthly'] as Map),
|
HetznerPriceInfo.getPrice(json['price_monthly'] as Map),
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
HetznerLocation _$HetznerLocationFromJson(Map<String, dynamic> json) {
|
HetznerLocation _$HetznerLocationFromJson(Map<String, dynamic> json) =>
|
||||||
return HetznerLocation(
|
HetznerLocation(
|
||||||
json['country'] as String,
|
json['country'] as String,
|
||||||
json['city'] as String,
|
json['city'] as String,
|
||||||
json['description'] as String,
|
json['description'] as String,
|
||||||
json['network_zone'] as String,
|
json['network_zone'] as String,
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
|
@ -42,19 +42,29 @@ class DeleteUserJob extends Job {
|
||||||
List<Object> get props => [id, title, user];
|
List<Object> get props => [id, title, user];
|
||||||
}
|
}
|
||||||
|
|
||||||
class ServiceToggleJob extends Job {
|
class ToggleJob extends Job {
|
||||||
ServiceToggleJob({
|
ToggleJob({
|
||||||
required this.type,
|
required this.type,
|
||||||
required this.needToTurnOn,
|
required String title,
|
||||||
}) : super(
|
}) : super(title: title);
|
||||||
title:
|
|
||||||
'${needToTurnOn ? "jobs.serviceTurnOn".tr() : "jobs.serviceTurnOff".tr()} ${type.title}');
|
|
||||||
|
|
||||||
final ServiceTypes type;
|
final dynamic type;
|
||||||
final bool needToTurnOn;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [id, title, type, needToTurnOn];
|
List<Object> get props => [...super.props, type];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ServiceToggleJob extends ToggleJob {
|
||||||
|
ServiceToggleJob({
|
||||||
|
required ServiceTypes type,
|
||||||
|
required this.needToTurnOn,
|
||||||
|
}) : super(
|
||||||
|
title:
|
||||||
|
'${needToTurnOn ? "jobs.serviceTurnOn".tr() : "jobs.serviceTurnOff".tr()} ${type.title}',
|
||||||
|
type: type,
|
||||||
|
);
|
||||||
|
|
||||||
|
final bool needToTurnOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
class CreateSSHKeyJob extends Job {
|
class CreateSSHKeyJob extends Job {
|
||||||
|
|
22
lib/logic/models/server_configurations.dart
Normal file
22
lib/logic/models/server_configurations.dart
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
|
|
||||||
|
part 'server_configurations.g.dart';
|
||||||
|
|
||||||
|
@JsonSerializable(createToJson: true)
|
||||||
|
class AutoUpgradeConfigurations extends Equatable {
|
||||||
|
const AutoUpgradeConfigurations({
|
||||||
|
required this.enable,
|
||||||
|
required this.allowReboot,
|
||||||
|
});
|
||||||
|
|
||||||
|
final bool enable;
|
||||||
|
final bool allowReboot;
|
||||||
|
|
||||||
|
factory AutoUpgradeConfigurations.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$AutoUpgradeConfigurationsFromJson(json);
|
||||||
|
Map<String, dynamic> toJson() => _$AutoUpgradeConfigurationsToJson(this);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [enable, allowReboot];
|
||||||
|
}
|
21
lib/logic/models/server_configurations.g.dart
Normal file
21
lib/logic/models/server_configurations.g.dart
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'server_configurations.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
AutoUpgradeConfigurations _$AutoUpgradeConfigurationsFromJson(
|
||||||
|
Map<String, dynamic> json) =>
|
||||||
|
AutoUpgradeConfigurations(
|
||||||
|
enable: json['enable'] as bool,
|
||||||
|
allowReboot: json['allowReboot'] as bool,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$AutoUpgradeConfigurationsToJson(
|
||||||
|
AutoUpgradeConfigurations instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'enable': instance.enable,
|
||||||
|
'allowReboot': instance.allowReboot,
|
||||||
|
};
|
18
lib/logic/models/timezone_settings.dart
Normal file
18
lib/logic/models/timezone_settings.dart
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import 'package:timezone/timezone.dart';
|
||||||
|
|
||||||
|
class TimeZoneSettings {
|
||||||
|
final Location timezone;
|
||||||
|
|
||||||
|
TimeZoneSettings(this.timezone);
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return {
|
||||||
|
'timezone': timezone.name,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
factory TimeZoneSettings.fromString(String string) {
|
||||||
|
var location = timeZoneDatabase.locations[string]!;
|
||||||
|
return TimeZoneSettings(location);
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ import 'package:selfprivacy/ui/pages/initializing/initializing.dart';
|
||||||
import 'package:selfprivacy/ui/pages/onboarding/onboarding.dart';
|
import 'package:selfprivacy/ui/pages/onboarding/onboarding.dart';
|
||||||
import 'package:selfprivacy/ui/pages/rootRoute.dart';
|
import 'package:selfprivacy/ui/pages/rootRoute.dart';
|
||||||
import 'package:wakelock/wakelock.dart';
|
import 'package:wakelock/wakelock.dart';
|
||||||
|
import 'package:timezone/data/latest.dart' as tz;
|
||||||
|
|
||||||
import 'config/bloc_config.dart';
|
import 'config/bloc_config.dart';
|
||||||
import 'config/bloc_observer.dart';
|
import 'config/bloc_observer.dart';
|
||||||
|
@ -19,12 +20,15 @@ void main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
await HiveConfig.init();
|
await HiveConfig.init();
|
||||||
await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||||
Bloc.observer = SimpleBlocObserver();
|
|
||||||
Wakelock.enable();
|
Wakelock.enable();
|
||||||
await getItSetup();
|
await getItSetup();
|
||||||
await EasyLocalization.ensureInitialized();
|
await EasyLocalization.ensureInitialized();
|
||||||
|
tz.initializeTimeZones();
|
||||||
|
|
||||||
runApp(MyApp());
|
BlocOverrides.runZoned(
|
||||||
|
() => runApp(Localization(child: MyApp())),
|
||||||
|
blocObserver: SimpleBlocObserver(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
class MyApp extends StatelessWidget {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ import 'package:selfprivacy/config/brand_colors.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/config/get_it_config.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/jobs/jobs_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/jobs/jobs_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/users/users_cubit.dart';
|
|
||||||
import 'package:selfprivacy/ui/components/action_button/action_button.dart';
|
import 'package:selfprivacy/ui/components/action_button/action_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_alert/brand_alert.dart';
|
import 'package:selfprivacy/ui/components/brand_alert/brand_alert.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import 'package:cubit_form/cubit_form.dart';
|
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:flutter/rendering.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
import 'package:selfprivacy/config/brand_theme.dart';
|
import 'package:selfprivacy/config/brand_theme.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/forms/initializing/backblaze_form_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/forms/initializing/backblaze_form_cubit.dart';
|
||||||
|
|
|
@ -3,7 +3,6 @@ import 'dart:collection';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:selfprivacy/config/brand_colors.dart';
|
import 'package:selfprivacy/config/brand_colors.dart';
|
||||||
import 'package:selfprivacy/config/get_it_config.dart';
|
import 'package:selfprivacy/config/get_it_config.dart';
|
||||||
import 'package:selfprivacy/logic/get_it/console.dart';
|
|
||||||
import 'package:selfprivacy/logic/models/message.dart';
|
import 'package:selfprivacy/logic/models/message.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';
|
||||||
|
|
|
@ -1,122 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:selfprivacy/config/brand_colors.dart';
|
|
||||||
import 'package:selfprivacy/config/brand_theme.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_text/brand_text.dart';
|
|
||||||
import 'package:selfprivacy/ui/components/switch_block/switch_bloc.dart';
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
|
||||||
|
|
||||||
class SettingsPage extends StatelessWidget {
|
|
||||||
const SettingsPage({Key? key}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return ListView(
|
|
||||||
padding: paddingH15V0,
|
|
||||||
children: [
|
|
||||||
SizedBox(height: 10),
|
|
||||||
BrandHeader(title: 'basis.settings'.tr(), hasBackButton: true),
|
|
||||||
BrandDivider(),
|
|
||||||
SwitcherBlock(
|
|
||||||
onChange: (_) {},
|
|
||||||
child: _TextColumn(
|
|
||||||
title: 'Allow Auto-upgrade',
|
|
||||||
value: 'Wether to allow automatic packages upgrades',
|
|
||||||
),
|
|
||||||
isActive: true,
|
|
||||||
),
|
|
||||||
SwitcherBlock(
|
|
||||||
onChange: (_) {},
|
|
||||||
child: _TextColumn(
|
|
||||||
title: 'Reboot after upgrade',
|
|
||||||
value: 'Reboot without prompt after applying updates',
|
|
||||||
),
|
|
||||||
isActive: false,
|
|
||||||
),
|
|
||||||
_Button(
|
|
||||||
onTap: () {},
|
|
||||||
child: _TextColumn(
|
|
||||||
title: 'Server Timezone',
|
|
||||||
value: 'Europe/Kyiv',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
_Button(
|
|
||||||
onTap: () {},
|
|
||||||
child: _TextColumn(
|
|
||||||
title: 'Server Locale',
|
|
||||||
value: 'Default',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
_Button(
|
|
||||||
onTap: () {},
|
|
||||||
child: _TextColumn(
|
|
||||||
hasWarning: true,
|
|
||||||
title: 'Factory Reset',
|
|
||||||
value: 'Restore default settings on your server',
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _Button extends StatelessWidget {
|
|
||||||
const _Button({
|
|
||||||
Key? key,
|
|
||||||
required this.onTap,
|
|
||||||
required this.child,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
final Widget child;
|
|
||||||
final VoidCallback onTap;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return InkWell(
|
|
||||||
onTap: onTap,
|
|
||||||
child: Container(
|
|
||||||
padding: EdgeInsets.only(top: 20, bottom: 5),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
border: Border(
|
|
||||||
bottom: BorderSide(width: 1, color: BrandColors.dividerColor),
|
|
||||||
)),
|
|
||||||
child: child,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _TextColumn extends StatelessWidget {
|
|
||||||
const _TextColumn({
|
|
||||||
Key? key,
|
|
||||||
required this.title,
|
|
||||||
required this.value,
|
|
||||||
this.hasWarning = false,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
final String title;
|
|
||||||
final String value;
|
|
||||||
final bool hasWarning;
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
BrandText.body1(
|
|
||||||
title,
|
|
||||||
style: TextStyle(color: hasWarning ? BrandColors.warning : null),
|
|
||||||
),
|
|
||||||
SizedBox(height: 5),
|
|
||||||
BrandText.body1(
|
|
||||||
value,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 13,
|
|
||||||
height: 1.53,
|
|
||||||
color: hasWarning ? BrandColors.warning : BrandColors.gray1,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,6 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:selfprivacy/logic/api_maps/server.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_tab_bar/brand_tab_bar.dart';
|
import 'package:selfprivacy/ui/components/brand_tab_bar/brand_tab_bar.dart';
|
||||||
import 'package:selfprivacy/ui/pages/more/more.dart';
|
import 'package:selfprivacy/ui/pages/more/more.dart';
|
||||||
import 'package:selfprivacy/ui/pages/providers/providers.dart';
|
import 'package:selfprivacy/ui/pages/providers/providers.dart';
|
||||||
|
@ -30,6 +30,8 @@ class _RootPageState extends State<RootPage>
|
||||||
tabController.dispose();
|
tabController.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var selfprivacyServer = ServerApi();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SafeArea(
|
return SafeArea(
|
||||||
|
|
|
@ -8,20 +8,27 @@ import 'package:selfprivacy/logic/cubit/hetzner_metrics/hetzner_metrics_cubit.da
|
||||||
import 'package:selfprivacy/logic/cubit/server_detailed_info/server_detailed_info_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/server_detailed_info/server_detailed_info_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/models/state_types.dart';
|
import 'package:selfprivacy/logic/models/state_types.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_icons/brand_icons.dart';
|
import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart';
|
||||||
|
import 'package:selfprivacy/ui/components/brand_loader/brand_loader.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_radio_tile/brand_radio_tile.dart';
|
import 'package:selfprivacy/ui/components/brand_radio_tile/brand_radio_tile.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
|
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
|
||||||
import 'package:selfprivacy/ui/components/icon_status_mask/icon_status_mask.dart';
|
import 'package:selfprivacy/ui/components/icon_status_mask/icon_status_mask.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:selfprivacy/ui/components/switch_block/switch_bloc.dart';
|
import 'package:selfprivacy/ui/components/switch_block/switch_bloc.dart';
|
||||||
|
import 'package:selfprivacy/ui/pages/server_details/time_zone/lang.dart';
|
||||||
import 'package:selfprivacy/utils/named_font_weight.dart';
|
import 'package:selfprivacy/utils/named_font_weight.dart';
|
||||||
|
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
||||||
|
import 'package:timezone/timezone.dart';
|
||||||
import 'cpu_chart.dart';
|
import 'cpu_chart.dart';
|
||||||
import 'network_charts.dart';
|
import 'network_charts.dart';
|
||||||
|
import 'package:selfprivacy/utils/extensions/duration.dart';
|
||||||
|
|
||||||
part 'server_settings.dart';
|
part 'server_settings.dart';
|
||||||
part 'text_details.dart';
|
part 'text_details.dart';
|
||||||
part 'chart.dart';
|
part 'chart.dart';
|
||||||
part 'header.dart';
|
part 'header.dart';
|
||||||
|
part 'time_zone/time_zone.dart';
|
||||||
|
|
||||||
var navigatorKey = GlobalKey<NavigatorState>();
|
var navigatorKey = GlobalKey<NavigatorState>();
|
||||||
|
|
||||||
|
@ -56,57 +63,57 @@ class _ServerDetailsState extends State<ServerDetails>
|
||||||
var isReady = context.watch<AppConfigCubit>().state is AppConfigFinished;
|
var isReady = context.watch<AppConfigCubit>().state is AppConfigFinished;
|
||||||
var providerState = isReady ? StateType.stable : StateType.uninitialized;
|
var providerState = isReady ? StateType.stable : StateType.uninitialized;
|
||||||
|
|
||||||
return Scaffold(
|
return BlocProvider(
|
||||||
appBar: PreferredSize(
|
create: (context) => ServerDetailsCubit()..check(),
|
||||||
child: Column(
|
child: Scaffold(
|
||||||
|
appBar: PreferredSize(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
height: 51,
|
||||||
|
alignment: Alignment.center,
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 15),
|
||||||
|
child: BrandText.h4('basis.details'.tr()),
|
||||||
|
),
|
||||||
|
BrandDivider(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
preferredSize: Size.fromHeight(52),
|
||||||
|
),
|
||||||
|
body: TabBarView(
|
||||||
|
physics: NeverScrollableScrollPhysics(),
|
||||||
|
controller: tabController,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
SingleChildScrollView(
|
||||||
height: 51,
|
physics: ClampingScrollPhysics(),
|
||||||
alignment: Alignment.center,
|
child: Column(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 15),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
child: BrandText.h4('basis.details'.tr()),
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: paddingH15V0,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
_Header(
|
||||||
|
providerState: providerState,
|
||||||
|
tabController: tabController),
|
||||||
|
BrandText.body1('providers.server.bottom_sheet.1'.tr()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 10),
|
||||||
|
BlocProvider(
|
||||||
|
create: (context) => HetznerMetricsCubit()..restart(),
|
||||||
|
child: _Chart(),
|
||||||
|
),
|
||||||
|
SizedBox(height: 20),
|
||||||
|
_TextDetails(),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
BrandDivider(),
|
_ServerSettings(tabController: tabController),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
preferredSize: Size.fromHeight(52),
|
|
||||||
),
|
|
||||||
body: TabBarView(
|
|
||||||
physics: NeverScrollableScrollPhysics(),
|
|
||||||
controller: tabController,
|
|
||||||
children: [
|
|
||||||
SingleChildScrollView(
|
|
||||||
physics: ClampingScrollPhysics(),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding: paddingH15V0,
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
_Header(
|
|
||||||
providerState: providerState,
|
|
||||||
tabController: tabController),
|
|
||||||
BrandText.body1('providers.server.bottom_sheet.1'.tr()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: 10),
|
|
||||||
BlocProvider(
|
|
||||||
create: (context) => HetznerMetricsCubit()..restart(),
|
|
||||||
child: _Chart(),
|
|
||||||
),
|
|
||||||
SizedBox(height: 20),
|
|
||||||
BlocProvider(
|
|
||||||
create: (context) => ServerDetailsCubit()..check(),
|
|
||||||
child: _TextDetails(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
_ServerSettings(tabController: tabController),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,12 @@ class _ServerSettings extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
var serverDetailsState = context.watch<ServerDetailsCubit>().state;
|
||||||
|
if (serverDetailsState is ServerDetailsNotReady) {
|
||||||
|
return Text('not ready');
|
||||||
|
} else if (serverDetailsState is! Loaded) {
|
||||||
|
return BrandLoader.horizontal();
|
||||||
|
}
|
||||||
return ListView(
|
return ListView(
|
||||||
padding: paddingH15V0,
|
padding: paddingH15V0,
|
||||||
children: [
|
children: [
|
||||||
|
@ -38,7 +44,7 @@ class _ServerSettings extends StatelessWidget {
|
||||||
title: 'Allow Auto-upgrade',
|
title: 'Allow Auto-upgrade',
|
||||||
value: 'Wether to allow automatic packages upgrades',
|
value: 'Wether to allow automatic packages upgrades',
|
||||||
),
|
),
|
||||||
isActive: true,
|
isActive: serverDetailsState.autoUpgradeSettings.enable,
|
||||||
),
|
),
|
||||||
SwitcherBlock(
|
SwitcherBlock(
|
||||||
onChange: (_) {},
|
onChange: (_) {},
|
||||||
|
@ -46,30 +52,17 @@ class _ServerSettings extends StatelessWidget {
|
||||||
title: 'Reboot after upgrade',
|
title: 'Reboot after upgrade',
|
||||||
value: 'Reboot without prompt after applying updates',
|
value: 'Reboot without prompt after applying updates',
|
||||||
),
|
),
|
||||||
isActive: false,
|
isActive: serverDetailsState.autoUpgradeSettings.allowReboot,
|
||||||
),
|
),
|
||||||
_Button(
|
_Button(
|
||||||
onTap: () {},
|
onTap: () {
|
||||||
|
Navigator.of(context).push(materialRoute(SelectTimezone()));
|
||||||
|
},
|
||||||
child: _TextColumn(
|
child: _TextColumn(
|
||||||
title: 'Server Timezone',
|
title: 'Server Timezone',
|
||||||
value: 'Europe/Kyiv',
|
value: serverDetailsState.serverTimezone.timezone.name,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
_Button(
|
|
||||||
onTap: () {},
|
|
||||||
child: _TextColumn(
|
|
||||||
title: 'Server Locale',
|
|
||||||
value: 'Default',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
_Button(
|
|
||||||
onTap: () {},
|
|
||||||
child: _TextColumn(
|
|
||||||
hasWarning: true,
|
|
||||||
title: 'Factory Reset',
|
|
||||||
value: 'Restore default settings on your server',
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
431
lib/ui/pages/server_details/time_zone/lang.dart
Normal file
431
lib/ui/pages/server_details/time_zone/lang.dart
Normal file
|
@ -0,0 +1,431 @@
|
||||||
|
final russian = {
|
||||||
|
"Pacific/Midway": "Мидуэй",
|
||||||
|
"Pacific/Niue": "Ниуэ",
|
||||||
|
"Pacific/Pago_Pago": "Паго-Паго",
|
||||||
|
"America/Adak": "Адак",
|
||||||
|
"Pacific/Honolulu": "Гонолулу",
|
||||||
|
"Pacific/Johnston": "Джонстон",
|
||||||
|
"Pacific/Rarotonga": "Раротонга",
|
||||||
|
"Pacific/Tahiti": "Таити",
|
||||||
|
"US/Hawaii": "Гавайи",
|
||||||
|
"Pacific/Marquesas": "Маркизские острова",
|
||||||
|
"America/Sitka": "Ситка",
|
||||||
|
"America/Anchorage": "Анкоридж",
|
||||||
|
"America/Metlakatla": "Метлакатла",
|
||||||
|
"America/Juneau": "Джуно",
|
||||||
|
"US/Alaska": "Аляска",
|
||||||
|
"America/Nome": "Ном",
|
||||||
|
"America/Yakutat": "Якутат",
|
||||||
|
"Pacific/Gambier": "Гамбье",
|
||||||
|
"America/Tijuana": "Тихуана",
|
||||||
|
"Pacific/Pitcairn": "Питкэрн",
|
||||||
|
"US/Pacific": "США/Тихий океан",
|
||||||
|
"Canada/Pacific": "США/Тихий океан",
|
||||||
|
"America/Los_Angeles": "Лос-Анджелес",
|
||||||
|
"America/Vancouver": "Ванкувер",
|
||||||
|
"America/Santa_Isabel": "Санта-Изабель",
|
||||||
|
"America/Chihuahua": "Чихуахуа",
|
||||||
|
"America/Cambridge_Bay": "Кембридж-Бэй",
|
||||||
|
"America/Inuvik": "Инувик",
|
||||||
|
"America/Boise": "Бойсе",
|
||||||
|
"America/Dawson": "Доусон",
|
||||||
|
"America/Mazatlan": "Масатлан",
|
||||||
|
"America/Dawson_Creek": "Доусон-Крик",
|
||||||
|
"US/Arizona": "Аризона",
|
||||||
|
"America/Denver": "Денвер",
|
||||||
|
"US/Mountain": "гора",
|
||||||
|
"America/Edmonton": "Эдмонтон",
|
||||||
|
"America/Yellowknife": "Йеллоунайф",
|
||||||
|
"America/Ojinaga": "Охинага",
|
||||||
|
"America/Phoenix": "Феникс",
|
||||||
|
"America/Whitehorse": "Белая лошадь",
|
||||||
|
"Canada/Mountain": "гора",
|
||||||
|
"America/Hermosillo": "Эрмосильо",
|
||||||
|
"America/Creston": "Крестон",
|
||||||
|
"America/Swift_Current": "Свифт Керрент",
|
||||||
|
"America/Tegucigalpa": "Тегусигальпа",
|
||||||
|
"America/Regina": "Регина",
|
||||||
|
"America/Rankin_Inlet": "Ранкин-Инлет",
|
||||||
|
"America/Rainy_River": "Райни-Ривер",
|
||||||
|
"America/Winnipeg": "Виннипег",
|
||||||
|
"America/North_Dakota/Center": "Северная Дакота/Центр",
|
||||||
|
"America/North_Dakota/Beulah": "Северная Дакота/Беула",
|
||||||
|
"America/Monterrey": "Монтеррей",
|
||||||
|
"America/Mexico_City": "Мехико",
|
||||||
|
"US/Central": "Центральный",
|
||||||
|
"America/Merida": "Мерида",
|
||||||
|
"America/Menominee": "Меномини",
|
||||||
|
"America/Matamoros": "Матаморос",
|
||||||
|
"America/Managua": "Манагуа",
|
||||||
|
"America/North_Dakota/New_Salem": "Северная Дакота/Нью-Салем",
|
||||||
|
"Pacific/Galapagos": "Галапагосские острова",
|
||||||
|
"America/Indiana/Tell_City": "Индиана/Телл-Сити",
|
||||||
|
"America/Indiana/Knox": "Индиана/Нокс",
|
||||||
|
"Canada/Central": "Центральный",
|
||||||
|
"America/Guatemala": "Гватемала",
|
||||||
|
"America/El_Salvador": "Сальвадор",
|
||||||
|
"America/Costa_Rica": "Коста-Рика",
|
||||||
|
"America/Chicago": "Чикаго",
|
||||||
|
"America/Belize": "Белиз",
|
||||||
|
"America/Bahia_Banderas": "Баия де Бандерас",
|
||||||
|
"America/Resolute": "Резольют",
|
||||||
|
"America/Atikokan": "Атикокан",
|
||||||
|
"America/Lima": "Лима",
|
||||||
|
"America/Bogota": "Богота",
|
||||||
|
"America/Cancun": "Канкун",
|
||||||
|
"America/Cayman": "Кайман",
|
||||||
|
"America/Detroit": "Детройт",
|
||||||
|
"America/Indiana/Indianapolis": "Индиана/Индианаполис",
|
||||||
|
"America/Eirunepe": "Эйрунепе",
|
||||||
|
"America/Grand_Turk": "Гранд-Терк",
|
||||||
|
"America/Guayaquil": "Гуаякиль",
|
||||||
|
"America/Havana": "Гавана",
|
||||||
|
"America/Indiana/Marengo": "Индиана/Маренго",
|
||||||
|
"America/Indiana/Petersburg": "Индиана/Петербург",
|
||||||
|
"America/Indiana/Vevay": "Индиана/Вева",
|
||||||
|
"America/Indiana/Vincennes": "Индиана/Винсеннес",
|
||||||
|
"America/Indiana/Winamac": "Индиана/Винамак",
|
||||||
|
"America/Iqaluit": "Икалуит",
|
||||||
|
"America/Jamaica": "Ямайка",
|
||||||
|
"America/Kentucky/Louisville": "Кентукки/Луисвилл",
|
||||||
|
"America/Nassau": "Нассау",
|
||||||
|
"America/Toronto": "Торонто",
|
||||||
|
"America/Montreal": "Монреаль",
|
||||||
|
"America/Pangnirtung": "Пангниртунг",
|
||||||
|
"America/Port-au-Prince": "Порт-о-Пренс",
|
||||||
|
"America/Kentucky/Monticello": "Кентукки/Монтичелло",
|
||||||
|
"Canada/Eastern": "Канада/Восточное",
|
||||||
|
"US/Eastern": "США/Восточное",
|
||||||
|
"America/Thunder_Bay": "Тандер-Бей",
|
||||||
|
"Pacific/Easter": "Пасха",
|
||||||
|
"America/Panama": "Панама",
|
||||||
|
"America/Nipigon": "Нипигон",
|
||||||
|
"America/Rio_Branco": "Рио-Бранко",
|
||||||
|
"America/New_York": "Нью-Йорк",
|
||||||
|
"Canada/Atlantic": "Атлантика",
|
||||||
|
"America/Kralendijk": "Кралендейк",
|
||||||
|
"America/La_Paz": "Ла-Пас",
|
||||||
|
"America/Halifax": "Галифакс",
|
||||||
|
"America/Lower_Princes": "Лоуэр-Принс-Куотер",
|
||||||
|
"America/Manaus": "Манаус",
|
||||||
|
"America/Marigot": "Мариго",
|
||||||
|
"America/Martinique": "Мартиника",
|
||||||
|
"America/Moncton": "Монктон",
|
||||||
|
"America/Guyana": "Гайана",
|
||||||
|
"America/Montserrat": "Монтсеррат",
|
||||||
|
"America/Guadeloupe": "Гваделупа",
|
||||||
|
"America/Grenada": "Гренада",
|
||||||
|
"America/Goose_Bay": "Гуз-Бей",
|
||||||
|
"America/Glace_Bay": "Глас Бэй",
|
||||||
|
"America/Curacao": "Кюрасао",
|
||||||
|
"America/Cuiaba": "Куяба",
|
||||||
|
"America/Port_of_Spain": "Порт-оф-Спейн",
|
||||||
|
"America/Porto_Velho": "Порту-Велью",
|
||||||
|
"America/Puerto_Rico": "Пуэрто-Рико",
|
||||||
|
"America/Caracas": "Каракас",
|
||||||
|
"America/Santo_Domingo": "Санто-Доминго",
|
||||||
|
"America/St_Barthelemy": "Святой Бартелеми",
|
||||||
|
"Atlantic/Bermuda": "Бермуды",
|
||||||
|
"America/St_Kitts": "Сент-Китс",
|
||||||
|
"America/St_Lucia": "Святая Люсия",
|
||||||
|
"America/St_Thomas": "Сент-Томас",
|
||||||
|
"America/St_Vincent": "Сент-Винсент",
|
||||||
|
"America/Thule": "Туле",
|
||||||
|
"America/Campo_Grande": "Кампу-Гранди",
|
||||||
|
"America/Boa_Vista": "Боа-Виста",
|
||||||
|
"America/Tortola": "Тортола",
|
||||||
|
"America/Aruba": "Аруба",
|
||||||
|
"America/Blanc-Sablon": "Блан-Саблон",
|
||||||
|
"America/Barbados": "Барбадос",
|
||||||
|
"America/Anguilla": "Ангилья",
|
||||||
|
"America/Antigua": "Антигуа",
|
||||||
|
"America/Dominica": "Доминика",
|
||||||
|
"Canada/Newfoundland": "Ньюфаундленд",
|
||||||
|
"America/St_Johns": "Сент-Джонс",
|
||||||
|
"America/Sao_Paulo": "Сан-Паулу",
|
||||||
|
"Atlantic/Stanley": "Стэнли",
|
||||||
|
"America/Miquelon": "Микелон",
|
||||||
|
"America/Argentina/Salta": "Аргентина/Сальта",
|
||||||
|
"America/Montevideo": "Монтевидео",
|
||||||
|
"America/Argentina/Rio_Gallegos": "Аргентина/Рио-Гальегос",
|
||||||
|
"America/Argentina/Mendoza": "Аргентина/Мендоса",
|
||||||
|
"America/Argentina/La_Rioja": "Аргентина/Ла-Риоха",
|
||||||
|
"America/Argentina/Jujuy": "Аргентина/Жужуй",
|
||||||
|
"Antarctica/Rothera": "Ротера",
|
||||||
|
"America/Argentina/Cordoba": "Аргентина/Кордова",
|
||||||
|
"America/Argentina/Catamarca": "Аргентина/Катамарка",
|
||||||
|
"America/Argentina/Ushuaia": "Аргентина/Ушуая",
|
||||||
|
"America/Argentina/Tucuman": "Аргентина/Тукуман",
|
||||||
|
"America/Paramaribo": "Парамарибо",
|
||||||
|
"America/Argentina/San_Luis": "Аргентина/Сан-Луис",
|
||||||
|
"America/Recife": "Ресифи",
|
||||||
|
"America/Argentina/Buenos_Aires": "Аргентина/Буэнос-Айрес",
|
||||||
|
"America/Asuncion": "Асунсьон",
|
||||||
|
"America/Maceio": "Масейо",
|
||||||
|
"America/Santarem": "Сантарен",
|
||||||
|
"America/Santiago": "Сантьяго",
|
||||||
|
"Antarctica/Palmer": "Палмер",
|
||||||
|
"America/Argentina/San_Juan": "Аргентина/Сан-Хуан",
|
||||||
|
"America/Fortaleza": "Форталеза",
|
||||||
|
"America/Cayenne": "Кайенна",
|
||||||
|
"America/Godthab": "Годтаб",
|
||||||
|
"America/Belem": "Белен",
|
||||||
|
"America/Araguaina": "Арагуайна",
|
||||||
|
"America/Bahia": "Баия",
|
||||||
|
"Atlantic/South_Georgia": "Южная_Грузия",
|
||||||
|
"America/Noronha": "Норонья",
|
||||||
|
"Atlantic/Azores": "Азорские острова",
|
||||||
|
"Atlantic/Cape_Verde": "Кабо-Верде",
|
||||||
|
"America/Scoresbysund": "Скорсбисунд",
|
||||||
|
"Africa/Accra": "Аккра",
|
||||||
|
"Atlantic/Faroe": "Фарерские острова",
|
||||||
|
"Europe/Guernsey": "Гернси",
|
||||||
|
"Africa/Dakar": "Дакар",
|
||||||
|
"Europe/Isle_of_Man": "Остров Мэн",
|
||||||
|
"Africa/Conakry": "Конакри",
|
||||||
|
"Africa/Abidjan": "Абиджан",
|
||||||
|
"Atlantic/Canary": "канарейка",
|
||||||
|
"Africa/Banjul": "Банжул",
|
||||||
|
"Europe/Jersey": "Джерси",
|
||||||
|
"Atlantic/St_Helena": "Остров Святой Елены",
|
||||||
|
"Africa/Bissau": "Бисау",
|
||||||
|
"Europe/London": "Лондон",
|
||||||
|
"Africa/Nouakchott": "Нуакшот",
|
||||||
|
"Africa/Lome": "Ломе",
|
||||||
|
"America/Danmarkshavn": "Данмарксхавн",
|
||||||
|
"Africa/Ouagadougou": "Уагадугу",
|
||||||
|
"Europe/Lisbon": "Лиссабон",
|
||||||
|
"Africa/Sao_Tome": "Сан-Томе",
|
||||||
|
"Africa/Monrovia": "Монровия",
|
||||||
|
"Atlantic/Reykjavik": "Рейкьявик",
|
||||||
|
"Antarctica/Troll": "Тролль",
|
||||||
|
"Atlantic/Madeira": "Мадейра",
|
||||||
|
"Africa/Bamako": "Бамако",
|
||||||
|
"Europe/Dublin": "Дублин",
|
||||||
|
"Africa/Freetown": "Фритаун",
|
||||||
|
"Europe/Monaco": "Монако",
|
||||||
|
"Europe/Skopje": "Скопье",
|
||||||
|
"Europe/Amsterdam": "Амстердам",
|
||||||
|
"Africa/Tunis": "Тунис",
|
||||||
|
"Arctic/Longyearbyen": "Лонгйир",
|
||||||
|
"Africa/Bangui": "Банги",
|
||||||
|
"Africa/Lagos": "Лагос",
|
||||||
|
"Africa/Douala": "Дуала",
|
||||||
|
"Africa/Libreville": "Либревиль",
|
||||||
|
"Europe/Belgrade": "Белград",
|
||||||
|
"Europe/Stockholm": "Стокгольм",
|
||||||
|
"Europe/Berlin": "Берлин",
|
||||||
|
"Europe/Zurich": "Цюрих",
|
||||||
|
"Europe/Zagreb": "Загреб",
|
||||||
|
"Europe/Warsaw": "Варшава",
|
||||||
|
"Africa/Luanda": "Луанда",
|
||||||
|
"Africa/Porto-Novo": "Порто-Ново",
|
||||||
|
"Africa/Brazzaville": "Браззавиль",
|
||||||
|
"Europe/Vienna": "Вена",
|
||||||
|
"Europe/Vatican": "Ватикан",
|
||||||
|
"Europe/Vaduz": "Вадуц",
|
||||||
|
"Europe/Tirane": "Тиран",
|
||||||
|
"Europe/Bratislava": "Братислава",
|
||||||
|
"Europe/Brussels": "Брюссель",
|
||||||
|
"Europe/Paris": "Париж",
|
||||||
|
"Europe/Sarajevo": "Сараево",
|
||||||
|
"Europe/San_Marino": "Сан-Марино",
|
||||||
|
"Europe/Rome": "Рим",
|
||||||
|
"Africa/El_Aaiun": "Эль-Аайун",
|
||||||
|
"Africa/Casablanca": "Касабланка",
|
||||||
|
"Europe/Malta": "Мальта",
|
||||||
|
"Africa/Ceuta": "Сеута",
|
||||||
|
"Europe/Gibraltar": "Гибралтар",
|
||||||
|
"Africa/Malabo": "Малабо",
|
||||||
|
"Europe/Busingen": "Бузинген",
|
||||||
|
"Africa/Ndjamena": "Нджамена",
|
||||||
|
"Europe/Andorra": "Андорра",
|
||||||
|
"Europe/Oslo": "Осло",
|
||||||
|
"Europe/Luxembourg": "Люксембург",
|
||||||
|
"Africa/Niamey": "Ниамей",
|
||||||
|
"Europe/Copenhagen": "Копенгаген",
|
||||||
|
"Europe/Madrid": "Мадрид",
|
||||||
|
"Europe/Budapest": "Будапешт",
|
||||||
|
"Africa/Algiers": "Алжир",
|
||||||
|
"Europe/Ljubljana": "Любляна",
|
||||||
|
"Europe/Podgorica": "Подгорица",
|
||||||
|
"Africa/Kinshasa": "Киншаса",
|
||||||
|
"Europe/Prague": "Прага",
|
||||||
|
"Europe/Riga": "Рига",
|
||||||
|
"Africa/Bujumbura": "Бужумбура",
|
||||||
|
"Africa/Lubumbashi": "Лубумбаши",
|
||||||
|
"Europe/Bucharest": "Бухарест",
|
||||||
|
"Africa/Blantyre": "Блантайр",
|
||||||
|
"Asia/Nicosia": "Никосия",
|
||||||
|
"Europe/Sofia": "София",
|
||||||
|
"Asia/Jerusalem": "Иерусалим",
|
||||||
|
"Europe/Tallinn": "Таллинн",
|
||||||
|
"Europe/Uzhgorod": "Ужгород",
|
||||||
|
"Africa/Lusaka": "Лусака",
|
||||||
|
"Europe/Mariehamn": "Мариехамн",
|
||||||
|
"Asia/Hebron": "Хеврон",
|
||||||
|
"Asia/Gaza": "Газа",
|
||||||
|
"Asia/Damascus": "Дамаск",
|
||||||
|
"Europe/Zaporozhye": "Запорожье",
|
||||||
|
"Asia/Beirut": "Бейрут",
|
||||||
|
"Africa/Juba": "Джуба",
|
||||||
|
"Africa/Harare": "Хараре",
|
||||||
|
"Europe/Athens": "Афины",
|
||||||
|
"Europe/Kiev": "Киев",
|
||||||
|
"Europe/Kaliningrad": "Калининград",
|
||||||
|
"Africa/Khartoum": "Хартум",
|
||||||
|
"Africa/Cairo": "Каир",
|
||||||
|
"Africa/Kigali": "Кигали",
|
||||||
|
"Asia/Amman": "Амман",
|
||||||
|
"Africa/Maputo": "Мапуту",
|
||||||
|
"Africa/Gaborone": "Габороне",
|
||||||
|
"Africa/Tripoli": "Триполи",
|
||||||
|
"Africa/Maseru": "Масеру",
|
||||||
|
"Africa/Windhoek": "Виндхук",
|
||||||
|
"Africa/Johannesburg": "Йоханнесбург",
|
||||||
|
"Europe/Chisinau": "Кишинев",
|
||||||
|
"Africa/Mbabane": "Мбабане",
|
||||||
|
"Europe/Vilnius": "Вильнюс",
|
||||||
|
"Europe/Helsinki": "Хельсинки",
|
||||||
|
"Europe/Moscow": "Москва",
|
||||||
|
"Africa/Kampala": "Кампала",
|
||||||
|
"Africa/Nairobi": "Найроби",
|
||||||
|
"Africa/Asmara": "Асмэра",
|
||||||
|
"Europe/Istanbul": "Стамбул",
|
||||||
|
"Asia/Riyadh": "Эр-Рияд",
|
||||||
|
"Asia/Qatar": "Катар",
|
||||||
|
"Europe/Minsk": "Минск",
|
||||||
|
"Indian/Comoro": "Коморо",
|
||||||
|
"Asia/Kuwait": "Кувейт",
|
||||||
|
"Africa/Addis_Ababa": "Аддис-Абеба",
|
||||||
|
"Africa/Dar_es_Salaam": "Дар-эс-Салам",
|
||||||
|
"Europe/Volgograd": "Волгоград",
|
||||||
|
"Indian/Antananarivo": "Антананариву",
|
||||||
|
"Asia/Bahrain": "Бахрейн",
|
||||||
|
"Asia/Baghdad": "Багдад",
|
||||||
|
"Indian/Mayotte": "Майотта",
|
||||||
|
"Africa/Djibouti": "Джибути",
|
||||||
|
"Europe/Simferopol": "Симферополь",
|
||||||
|
"Asia/Aden": "Аден",
|
||||||
|
"Antarctica/Syowa": "Сёва",
|
||||||
|
"Africa/Mogadishu": "Могадишо",
|
||||||
|
"Asia/Tehran": "Тегеран",
|
||||||
|
"Asia/Yerevan": "Ереван",
|
||||||
|
"Asia/Tbilisi": "Тбилиси",
|
||||||
|
"Asia/Muscat": "Мускат",
|
||||||
|
"Europe/Samara": "Самара",
|
||||||
|
"Indian/Mahe": "Маэ",
|
||||||
|
"Asia/Baku": "Баку",
|
||||||
|
"Indian/Mauritius": "Маврикий",
|
||||||
|
"Indian/Reunion": "Воссоединение",
|
||||||
|
"Asia/Dubai": "Дубай",
|
||||||
|
"Asia/Kabul": "Кабул",
|
||||||
|
"Asia/Ashgabat": "Ашхабад",
|
||||||
|
"Antarctica/Mawson": "Моусон",
|
||||||
|
"Asia/Aqtau": "Актау",
|
||||||
|
"Asia/Yekaterinburg": "Екатеринбург",
|
||||||
|
"Asia/Aqtobe": "Актобе",
|
||||||
|
"Asia/Dushanbe": "Душанбе",
|
||||||
|
"Asia/Tashkent": "Ташкент",
|
||||||
|
"Asia/Samarkand": "Самарканд",
|
||||||
|
"Asia/Qyzylorda": "Кызылорда",
|
||||||
|
"Asia/Oral": "Оральный",
|
||||||
|
"Asia/Karachi": "Карачи",
|
||||||
|
"Indian/Kerguelen": "Кергелен",
|
||||||
|
"Indian/Maldives": "Мальдивы",
|
||||||
|
"Asia/Kolkata": "Калькутта",
|
||||||
|
"Asia/Colombo": "Коломбо",
|
||||||
|
"Asia/Kathmandu": "Катманду",
|
||||||
|
"Antarctica/Vostok": "Восток",
|
||||||
|
"Asia/Almaty": "Алматы",
|
||||||
|
"Asia/Urumqi": "Урумчи",
|
||||||
|
"Asia/Thimphu": "Тхимпху",
|
||||||
|
"Asia/Omsk": "Омск",
|
||||||
|
"Asia/Dhaka": "Дакка",
|
||||||
|
"Indian/Chagos": "Чагос",
|
||||||
|
"Asia/Bishkek": "Бишкек",
|
||||||
|
"Asia/Rangoon": "Рангун",
|
||||||
|
"Indian/Cocos": "кокосы",
|
||||||
|
"Asia/Bangkok": "Бангкок",
|
||||||
|
"Asia/Hovd": "Ховд",
|
||||||
|
"Asia/Novokuznetsk": "Новокузнецк",
|
||||||
|
"Asia/Vientiane": "Вьентьян",
|
||||||
|
"Asia/Krasnoyarsk": "Красноярск",
|
||||||
|
"Antarctica/Davis": "Дэвис",
|
||||||
|
"Asia/Novosibirsk": "Новосибирск",
|
||||||
|
"Asia/Phnom_Penh": "Пномпень",
|
||||||
|
"Asia/Pontianak": "Понтианак",
|
||||||
|
"Asia/Jakarta": "Джакарта",
|
||||||
|
"Asia/Ho_Chi_Minh": "Хо Ши Мин",
|
||||||
|
"Indian/Christmas": "Рождество",
|
||||||
|
"Asia/Manila": "Манила",
|
||||||
|
"Asia/Makassar": "Макассар",
|
||||||
|
"Asia/Macau": "Макао",
|
||||||
|
"Asia/Kuala_Lumpur": "Куала-Лумпур",
|
||||||
|
"Asia/Singapore": "Сингапур",
|
||||||
|
"Asia/Shanghai": "Шанхай",
|
||||||
|
"Asia/Irkutsk": "Иркутск",
|
||||||
|
"Asia/Kuching": "Кучинг",
|
||||||
|
"Asia/Hong_Kong": "Гонконг",
|
||||||
|
"Australia/Perth": "Перт",
|
||||||
|
"Asia/Taipei": "Тайбэй",
|
||||||
|
"Asia/Brunei": "Бруней",
|
||||||
|
"Asia/Choibalsan": "Чойбалсан",
|
||||||
|
"Asia/Ulaanbaatar": "Улан-Батор",
|
||||||
|
"Australia/Eucla": "Евкла",
|
||||||
|
"Asia/Yakutsk": "Якутск",
|
||||||
|
"Asia/Dili": "Дили",
|
||||||
|
"Pacific/Palau": "Палау",
|
||||||
|
"Asia/Jayapura": "Джаяпура",
|
||||||
|
"Asia/Seoul": "Сеул",
|
||||||
|
"Asia/Pyongyang": "Пхеньян",
|
||||||
|
"Asia/Khandyga": "Хандыга",
|
||||||
|
"Asia/Chita": "Чита",
|
||||||
|
"Asia/Tokyo": "Токио",
|
||||||
|
"Australia/Darwin": "Дарвин",
|
||||||
|
"Pacific/Saipan": "Сайпан",
|
||||||
|
"Australia/Brisbane": "Брисбен",
|
||||||
|
"Pacific/Port_Moresby": "Порт-Морсби",
|
||||||
|
"Pacific/Chuuk": "Чуук",
|
||||||
|
"Antarctica/DumontDUrville": "Дюмон-д'Юрвиль",
|
||||||
|
"Pacific/Guam": "Гуам",
|
||||||
|
"Australia/Lindeman": "Линдеман",
|
||||||
|
"Asia/Ust-Nera": "Усть-Нера",
|
||||||
|
"Asia/Vladivostok": "Владивосток",
|
||||||
|
"Australia/Broken_Hill": "Брокен-Хилл",
|
||||||
|
"Australia/Adelaide": "Аделаида",
|
||||||
|
"Asia/Sakhalin": "Сахалин",
|
||||||
|
"Pacific/Guadalcanal": "Гуадалканал",
|
||||||
|
"Pacific/Efate": "Эфате",
|
||||||
|
"Antarctica/Casey": "Кейси",
|
||||||
|
"Antarctica/Macquarie": "Маккуори",
|
||||||
|
"Pacific/Kosrae": "Косрае",
|
||||||
|
"Australia/Sydney": "Сидней",
|
||||||
|
"Pacific/Noumea": "Нумеа",
|
||||||
|
"Australia/Melbourne": "Мельбурн",
|
||||||
|
"Australia/Lord_Howe": "Остров Лорд-Хау",
|
||||||
|
"Australia/Hobart": "Хобарт",
|
||||||
|
"Pacific/Pohnpei": "Понпеи",
|
||||||
|
"Australia/Currie": "Карри",
|
||||||
|
"Asia/Srednekolymsk": "Среднеколымск",
|
||||||
|
"Asia/Magadan": "Магадан",
|
||||||
|
"Pacific/Kwajalein": "Кваджалейн",
|
||||||
|
"Pacific/Majuro": "Маджуро",
|
||||||
|
"Pacific/Funafuti": "Фунафути",
|
||||||
|
"Asia/Anadyr": "Анадырь",
|
||||||
|
"Pacific/Nauru": "Науру",
|
||||||
|
"Asia/Kamchatka": "Камчатка",
|
||||||
|
"Pacific/Fiji": "Фиджи",
|
||||||
|
"Pacific/Norfolk": "Норфолк",
|
||||||
|
"Pacific/Tarawa": "Тарава",
|
||||||
|
"Pacific/Wallis": "Уоллис",
|
||||||
|
"Pacific/Wake": "Будить",
|
||||||
|
"Pacific/Tongatapu": "Тонгатапу",
|
||||||
|
"Antarctica/McMurdo": "МакМердо",
|
||||||
|
"Pacific/Enderbury": "Эндербери",
|
||||||
|
"Pacific/Fakaofo": "Факаофо",
|
||||||
|
"Pacific/Auckland": "Окленд",
|
||||||
|
"Pacific/Chatham": "Чатем",
|
||||||
|
"Pacific/Kiritimati": "Киритимати",
|
||||||
|
"Pacific/Apia": "Апиа",
|
||||||
|
};
|
107
lib/ui/pages/server_details/time_zone/time_zone.dart
Normal file
107
lib/ui/pages/server_details/time_zone/time_zone.dart
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
part of '../server_details.dart';
|
||||||
|
|
||||||
|
final List<Location> locations = timeZoneDatabase.locations.values.toList()
|
||||||
|
..sort((l1, l2) =>
|
||||||
|
l1.currentTimeZone.offset.compareTo(l2.currentTimeZone.offset));
|
||||||
|
|
||||||
|
class SelectTimezone extends StatefulWidget {
|
||||||
|
SelectTimezone({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_SelectTimezoneState createState() => _SelectTimezoneState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _SelectTimezoneState extends State<SelectTimezone> {
|
||||||
|
final ScrollController controller = ScrollController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
WidgetsBinding.instance!.addPostFrameCallback(_afterLayout);
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _afterLayout(_) {
|
||||||
|
var t = DateTime.now().timeZoneOffset;
|
||||||
|
var index = locations.indexWhere((element) =>
|
||||||
|
Duration(milliseconds: element.currentTimeZone.offset) == t);
|
||||||
|
print(t);
|
||||||
|
|
||||||
|
if (index >= 0) {
|
||||||
|
controller.animateTo(60.0 * index,
|
||||||
|
duration: Duration(milliseconds: 300), curve: Curves.easeIn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
controller.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: PreferredSize(
|
||||||
|
child: BrandHeader(
|
||||||
|
title: 'select timezone',
|
||||||
|
hasBackButton: true,
|
||||||
|
),
|
||||||
|
preferredSize: Size.fromHeight(52),
|
||||||
|
),
|
||||||
|
body: ListView(
|
||||||
|
controller: controller,
|
||||||
|
children: locations
|
||||||
|
.asMap()
|
||||||
|
.map((key, value) {
|
||||||
|
var duration =
|
||||||
|
Duration(milliseconds: value.currentTimeZone.offset);
|
||||||
|
var area = value.currentTimeZone.abbreviation
|
||||||
|
.replaceAll(RegExp(r'[\d+()-]'), '');
|
||||||
|
|
||||||
|
String timezoneName = value.name;
|
||||||
|
if (context.locale.toString() == 'ru') {
|
||||||
|
timezoneName = russian[value.name] ??
|
||||||
|
() {
|
||||||
|
var arr = value.name.split('/')..removeAt(0);
|
||||||
|
return arr.join('/');
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
|
||||||
|
return MapEntry(
|
||||||
|
key,
|
||||||
|
Container(
|
||||||
|
height: 60,
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 20),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
BrandText.body1(
|
||||||
|
timezoneName,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
BrandText.small(
|
||||||
|
'GMT ${duration.toDayHourMinuteFormat()} ${area.isNotEmpty ? '($area)' : ''}',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 13,
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border(
|
||||||
|
bottom: BorderSide(
|
||||||
|
color: BrandColors.dividerColor,
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.values
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
41
lib/utils/extensions/duration.dart
Normal file
41
lib/utils/extensions/duration.dart
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
// ignore_for_file: unnecessary_this
|
||||||
|
|
||||||
|
extension DurationFormatter on Duration {
|
||||||
|
String toDayHourMinuteSecondFormat() {
|
||||||
|
return [
|
||||||
|
this.inHours.remainder(24),
|
||||||
|
this.inMinutes.remainder(60),
|
||||||
|
this.inSeconds.remainder(60)
|
||||||
|
].map((seg) {
|
||||||
|
return seg.toString().padLeft(2, '0');
|
||||||
|
}).join(':');
|
||||||
|
}
|
||||||
|
|
||||||
|
String toDayHourMinuteFormat() {
|
||||||
|
var designator = this >= Duration.zero ? '+' : '-';
|
||||||
|
|
||||||
|
var segments = [
|
||||||
|
this.inHours.remainder(24).abs(),
|
||||||
|
this.inMinutes.remainder(60).abs(),
|
||||||
|
].map((seg) {
|
||||||
|
return seg.toString().padLeft(2, '0');
|
||||||
|
});
|
||||||
|
|
||||||
|
return '$designator${segments.first}:${segments.last}';
|
||||||
|
}
|
||||||
|
|
||||||
|
String toHoursMinutesSecondsFormat() {
|
||||||
|
// WAT: https://flutterigniter.com/how-to-format-duration/
|
||||||
|
return this.toString().split('.').first.padLeft(8, "0");
|
||||||
|
}
|
||||||
|
|
||||||
|
String toDayHourMinuteFormat2() {
|
||||||
|
var segments = [
|
||||||
|
this.inHours.remainder(24),
|
||||||
|
this.inMinutes.remainder(60),
|
||||||
|
].map((seg) {
|
||||||
|
return seg.toString().padLeft(2, '0');
|
||||||
|
});
|
||||||
|
return segments.first + " h" + " " + segments.last + " min";
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,3 @@
|
||||||
import 'dart:ui';
|
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
|
|
||||||
extension TextExtension on Text {
|
extension TextExtension on Text {
|
||||||
|
|
29
pubspec.lock
29
pubspec.lock
|
@ -63,7 +63,7 @@ packages:
|
||||||
name: bloc
|
name: bloc
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.2.1"
|
version: "8.0.2"
|
||||||
boolean_selector:
|
boolean_selector:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -210,7 +210,7 @@ packages:
|
||||||
name: cubit_form
|
name: cubit_form
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.18"
|
version: "2.0.1"
|
||||||
cupertino_icons:
|
cupertino_icons:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -267,13 +267,6 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.3"
|
version: "2.0.3"
|
||||||
extended_masked_text:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: extended_masked_text
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "2.3.1"
|
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -320,14 +313,14 @@ packages:
|
||||||
name: flutter_bloc
|
name: flutter_bloc
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.3.3"
|
version: "8.0.1"
|
||||||
flutter_launcher_icons:
|
flutter_launcher_icons:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: flutter_launcher_icons
|
name: flutter_launcher_icons
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.9.2"
|
version: "0.9.0"
|
||||||
flutter_localizations:
|
flutter_localizations:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
|
@ -504,6 +497,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.1"
|
version: "4.0.1"
|
||||||
|
mask_text_input_formatter:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: mask_text_input_formatter
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.0"
|
||||||
matcher:
|
matcher:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -943,6 +943,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.4.9"
|
version: "0.4.9"
|
||||||
|
timezone:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: timezone
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.8.0"
|
||||||
timing:
|
timing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
61
pubspec.yaml
61
pubspec.yaml
|
@ -8,38 +8,39 @@ environment:
|
||||||
flutter: ">=2.10.0"
|
flutter: ">=2.10.0"
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
|
auto_size_text: 3.0.0-nullsafety.0
|
||||||
|
basic_utils: 3.4.0
|
||||||
|
crypt: 4.0.1
|
||||||
|
cubit_form: 2.0.1
|
||||||
|
cupertino_icons: 1.0.2
|
||||||
|
dio: 4.0.1
|
||||||
|
easy_localization: 3.0.0
|
||||||
|
either_option: 2.0.1-dev.1
|
||||||
|
equatable: 2.0.3
|
||||||
|
fl_chart: 0.40.0
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
crypt: ^4.0.1
|
flutter_bloc: 8.0.1
|
||||||
cubit_form: ^1.0.0-nullsafety.0
|
flutter_markdown: 0.6.9
|
||||||
cupertino_icons: ^1.0.2
|
flutter_secure_storage: 4.2.1
|
||||||
dio: ^4.0.0-beta7
|
get_it: 7.2.0
|
||||||
easy_localization: ^3.0.0
|
hive: 2.0.5
|
||||||
either_option: ^2.0.1-dev.1
|
hive_flutter: 1.1.0
|
||||||
equatable: ^2.0.3
|
ionicons: 0.1.2
|
||||||
fl_chart: ^0.40.0
|
json_annotation: 4.3.0
|
||||||
flutter_bloc: ^7.3.3
|
local_auth: 1.1.7
|
||||||
flutter_markdown: ^0.6.0
|
modal_bottom_sheet: 2.0.0
|
||||||
flutter_secure_storage: ^4.1.0
|
nanoid: 1.0.0
|
||||||
get_it: ^7.2.0
|
package_info: 2.0.0
|
||||||
hive: ^2.0.0
|
pointycastle: 3.3.2
|
||||||
hive_flutter: ^1.0.0
|
pretty_dio_logger: 1.2.0-beta-1
|
||||||
json_annotation: ^4.0.0
|
provider: 6.0.0
|
||||||
modal_bottom_sheet: ^2.0.0
|
rsa_encrypt: 2.0.0
|
||||||
nanoid: ^1.0.0
|
share_plus: 2.1.4
|
||||||
package_info: ^2.0.0
|
ssh_key: 0.7.0
|
||||||
pretty_dio_logger: ^1.1.1
|
timezone: ^0.8.0
|
||||||
provider: ^6.0.0
|
url_launcher: 6.0.2
|
||||||
share_plus: ^2.1.4
|
wakelock: 0.5.0+2
|
||||||
url_launcher: ^6.0.2
|
|
||||||
wakelock: ^0.5.0+2
|
|
||||||
basic_utils: ^3.4.0
|
|
||||||
ionicons: ^0.1.2
|
|
||||||
pointycastle: ^3.3.2
|
|
||||||
rsa_encrypt: ^2.0.0
|
|
||||||
ssh_key: ^0.7.0
|
|
||||||
local_auth: ^1.1.7
|
|
||||||
auto_size_text: ^3.0.0-nullsafety.0
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|
Loading…
Reference in a new issue