chore: Merge master into digital-ocean

routes-refactor
NaiJi ✨ 2022-10-25 12:22:34 +04:00
commit 5ddbfcb342
8 changed files with 129 additions and 83 deletions

View File

@ -101,6 +101,7 @@
"reboot_after_upgrade_hint": "Reboot without prompt after applying changes on server", "reboot_after_upgrade_hint": "Reboot without prompt after applying changes on server",
"server_timezone": "Server timezone", "server_timezone": "Server timezone",
"select_timezone": "Select timezone", "select_timezone": "Select timezone",
"timezone_search_bar": "Timezone name or time shift value",
"server_id": "Server ID", "server_id": "Server ID",
"status": "Status", "status": "Status",
"cpu": "CPU", "cpu": "CPU",
@ -171,6 +172,7 @@
"gb": "{} GB", "gb": "{} GB",
"mb": "{} MB", "mb": "{} MB",
"kb": "{} KB", "kb": "{} KB",
"bytes": "Bytes",
"extend_volume_button": "Extend volume", "extend_volume_button": "Extend volume",
"extending_volume_title": "Extending volume", "extending_volume_title": "Extending volume",
"extending_volume_description": "Resizing volume will allow you to store more data on your server without extending the server itself. Volume can only be extended: shrinking is not possible.", "extending_volume_description": "Resizing volume will allow you to store more data on your server without extending the server itself. Volume can only be extended: shrinking is not possible.",

View File

@ -101,6 +101,7 @@
"reboot_after_upgrade_hint": "Автоматически перезагружать сервер после применения обновлений", "reboot_after_upgrade_hint": "Автоматически перезагружать сервер после применения обновлений",
"server_timezone": "Часовой пояс сервера", "server_timezone": "Часовой пояс сервера",
"select_timezone": "Выберите часовой пояс", "select_timezone": "Выберите часовой пояс",
"timezone_search_bar": "Имя часового пояса или значение временного сдвига",
"server_id": "ID сервера", "server_id": "ID сервера",
"status": "Статус", "status": "Статус",
"cpu": "Процессор", "cpu": "Процессор",
@ -171,6 +172,7 @@
"gb": "{} GB", "gb": "{} GB",
"mb": "{} MB", "mb": "{} MB",
"kb": "{} KB", "kb": "{} KB",
"bytes": "Байт",
"extend_volume_button": "Расширить хранилище", "extend_volume_button": "Расширить хранилище",
"extending_volume_title": "Расширение хранилища", "extending_volume_title": "Расширение хранилища",
"extending_volume_description": "Изменение размера хранилища позволит вам держать больше данных на вашем сервере без расширения самого сервера. Объем можно только увеличить: уменьшить нельзя.", "extending_volume_description": "Изменение размера хранилища позволит вам держать больше данных на вашем сервере без расширения самого сервера. Объем можно только увеличить: уменьшить нельзя.",

View File

@ -369,7 +369,7 @@ class ServerInstallationRepository {
BrandAlert( BrandAlert(
title: e.response!.data['errors'][0]['code'] == 1038 title: e.response!.data['errors'][0]['code'] == 1038
? 'modals.you_cant_use_this_api'.tr() ? 'modals.you_cant_use_this_api'.tr()
: 'domain.states.error'.tr(), : 'domain.error'.tr(),
contentText: 'modals.delete_server_volume'.tr(), contentText: 'modals.delete_server_volume'.tr(),
actions: [ actions: [
ActionButton( ActionButton(

View File

@ -26,7 +26,7 @@ class DiskSize {
@override @override
String toString() { String toString() {
if (byte < 1024) { if (byte < 1024) {
return '${byte.toStringAsFixed(0)} ${tr('bytes')}'; return '${byte.toStringAsFixed(0)} ${tr('storage.bytes')}';
} else if (byte < 1024 * 1024) { } else if (byte < 1024 * 1024) {
return 'storage.kb'.tr(args: [kibibyte.toStringAsFixed(1)]); return 'storage.kb'.tr(args: [kibibyte.toStringAsFixed(1)]);
} else if (byte < 1024 * 1024 * 1024) { } else if (byte < 1024 * 1024 * 1024) {

View File

@ -28,7 +28,7 @@ class _DnsDetailsPageState extends State<DnsDetailsPage> {
bool isError = false; bool isError = false;
switch (dnsState) { switch (dnsState) {
case DnsRecordsStatus.uninitialized: case DnsRecordsStatus.uninitialized:
description = 'domain.states.uninitialized'.tr(); description = 'domain.uninitialized'.tr();
icon = const Icon( icon = const Icon(
Icons.refresh, Icons.refresh,
size: 24.0, size: 24.0,
@ -36,7 +36,7 @@ class _DnsDetailsPageState extends State<DnsDetailsPage> {
isError = false; isError = false;
break; break;
case DnsRecordsStatus.refreshing: case DnsRecordsStatus.refreshing:
description = 'domain.states.refreshing'.tr(); description = 'domain.refreshing'.tr();
icon = const Icon( icon = const Icon(
Icons.refresh, Icons.refresh,
size: 24.0, size: 24.0,
@ -44,7 +44,7 @@ class _DnsDetailsPageState extends State<DnsDetailsPage> {
isError = false; isError = false;
break; break;
case DnsRecordsStatus.good: case DnsRecordsStatus.good:
description = 'domain.states.ok'.tr(); description = 'domain.ok'.tr();
icon = const Icon( icon = const Icon(
Icons.check_circle_outline, Icons.check_circle_outline,
size: 24.0, size: 24.0,
@ -52,8 +52,8 @@ class _DnsDetailsPageState extends State<DnsDetailsPage> {
isError = false; isError = false;
break; break;
case DnsRecordsStatus.error: case DnsRecordsStatus.error:
description = 'domain.states.error'.tr(); description = 'domain.error'.tr();
subtitle = 'domain.states.error_subtitle'.tr(); subtitle = 'domain.error_subtitle'.tr();
icon = const Icon( icon = const Icon(
Icons.error_outline, Icons.error_outline,
size: 24.0, size: 24.0,

View File

@ -17,17 +17,15 @@ 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_loader/brand_loader.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/list_tiles/list_tile_on_surface_variant.dart'; import 'package:selfprivacy/ui/components/list_tiles/list_tile_on_surface_variant.dart';
import 'package:selfprivacy/ui/pages/server_details/charts/cpu_chart.dart';
import 'package:selfprivacy/ui/pages/server_details/charts/network_charts.dart';
import 'package:selfprivacy/ui/pages/server_storage/storage_card.dart'; import 'package:selfprivacy/ui/pages/server_storage/storage_card.dart';
import 'package:selfprivacy/ui/pages/server_details/time_zone/lang.dart';
import 'package:selfprivacy/utils/extensions/duration.dart'; import 'package:selfprivacy/utils/extensions/duration.dart';
import 'package:selfprivacy/utils/extensions/string_extensions.dart'; import 'package:selfprivacy/utils/extensions/string_extensions.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:selfprivacy/utils/route_transitions/basic.dart';
import 'package:timezone/timezone.dart'; import 'package:timezone/timezone.dart';
import 'package:selfprivacy/ui/pages/server_details/charts/cpu_chart.dart';
import 'package:selfprivacy/ui/pages/server_details/charts/network_charts.dart';
part 'charts/chart.dart'; part 'charts/chart.dart';
part 'server_settings.dart'; part 'server_settings.dart';
part 'text_details.dart'; part 'text_details.dart';

View File

@ -14,11 +14,21 @@ class SelectTimezone extends StatefulWidget {
} }
class _SelectTimezoneState extends State<SelectTimezone> { class _SelectTimezoneState extends State<SelectTimezone> {
final ScrollController controller = ScrollController(); final ScrollController scrollController = ScrollController();
final TextEditingController searchController = TextEditingController();
String? timezoneFilterValue;
bool isSearching = false;
@override @override
void initState() { void initState() {
WidgetsBinding.instance.addPostFrameCallback(_afterLayout); WidgetsBinding.instance.addPostFrameCallback(_afterLayout);
searchController.addListener(() {
setState(() {
timezoneFilterValue =
searchController.text.isNotEmpty ? searchController.text : null;
});
});
super.initState(); super.initState();
} }
@ -31,7 +41,7 @@ class _SelectTimezoneState extends State<SelectTimezone> {
print(t); print(t);
if (index >= 0) { if (index >= 0) {
controller.animateTo( scrollController.animateTo(
60.0 * index, 60.0 * index,
duration: const Duration(milliseconds: 300), duration: const Duration(milliseconds: 300),
curve: Curves.easeIn, curve: Curves.easeIn,
@ -41,93 +51,120 @@ class _SelectTimezoneState extends State<SelectTimezone> {
@override @override
void dispose() { void dispose() {
controller.dispose(); scrollController.dispose();
searchController.dispose();
super.dispose(); super.dispose();
} }
@override @override
Widget build(final BuildContext context) => Scaffold( Widget build(final BuildContext context) => Scaffold(
appBar: AppBar( appBar: AppBar(
title: Padding( title: isSearching
padding: const EdgeInsets.only(top: 4.0), ? TextField(
child: Text('server.select_timezone'.tr()), readOnly: false,
), textAlign: TextAlign.start,
textInputAction: TextInputAction.next,
enabled: true,
controller: searchController,
decoration: InputDecoration(
errorText: null,
hintText: 'server.timezone_search_bar'.tr(),
),
)
: Padding(
padding: const EdgeInsets.only(top: 4.0),
child: Text('server.select_timezone'.tr()),
),
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.arrow_back), icon: const Icon(Icons.arrow_back),
onPressed: () => Navigator.of(context).pop(), onPressed: isSearching
? () => setState(() => isSearching = false)
: () => Navigator.of(context).pop(),
), ),
actions: [
if (!isSearching)
IconButton(
icon: const Icon(Icons.search),
onPressed: () => setState(() => isSearching = true),
),
],
), ),
body: SafeArea( body: SafeArea(
child: ListView( child: ListView(
controller: controller, controller: scrollController,
children: locations children: locations
.where(
(final Location location) => timezoneFilterValue == null
? true
: location.name
.toLowerCase()
.contains(timezoneFilterValue!) ||
Duration(
milliseconds: location.currentTimeZone.offset,
)
.toDayHourMinuteFormat()
.contains(timezoneFilterValue!),
)
.toList()
.asMap() .asMap()
.map((final key, final value) { .map(
final duration = (final key, final value) => locationToListTile(key, value),
Duration(milliseconds: value.currentTimeZone.offset); )
final area = value.currentTimeZone.abbreviation
.replaceAll(RegExp(r'[\d+()-]'), '');
String timezoneName = value.name;
if (context.locale.toString() == 'ru') {
timezoneName = russian[value.name] ??
() {
final arr = value.name.split('/')..removeAt(0);
return arr.join('/');
}();
}
return MapEntry(
key,
Container(
height: 75,
padding: const EdgeInsets.symmetric(horizontal: 20),
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(
color: BrandColors.dividerColor,
),
),
),
child: InkWell(
onTap: () {
context
.read<ServerDetailsCubit>()
.repository
.setTimezone(
timezoneName,
);
Navigator.of(context).pop();
},
child: Container(
padding: const EdgeInsets.symmetric(vertical: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
BrandText.body1(
timezoneName,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
BrandText.small(
'GMT ${duration.toDayHourMinuteFormat()} ${area.isNotEmpty ? '($area)' : ''}',
style: const TextStyle(
fontSize: 13,
),
),
],
),
),
),
),
);
})
.values .values
.toList(), .toList(),
), ),
), ),
); );
MapEntry<int, Container> locationToListTile(
final int key, final Location location) {
final duration = Duration(milliseconds: location.currentTimeZone.offset);
final area = location.currentTimeZone.abbreviation
.replaceAll(RegExp(r'[\d+()-]'), '');
return MapEntry(
key,
Container(
height: 75,
padding: const EdgeInsets.symmetric(horizontal: 20),
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(
color: BrandColors.dividerColor,
),
),
),
child: InkWell(
onTap: () {
context.read<ServerDetailsCubit>().repository.setTimezone(
location.name,
);
Navigator.of(context).pop();
},
child: Container(
padding: const EdgeInsets.symmetric(vertical: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
BrandText.body1(
location.name,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
BrandText.small(
'GMT ${duration.toDayHourMinuteFormat()} ${area.isNotEmpty ? '($area)' : ''}',
style: const TextStyle(
fontSize: 13,
),
),
],
),
),
),
),
);
}
} }

View File

@ -33,6 +33,13 @@ class _ExtendingVolumePageState extends State<ExtendingVolumePage> {
super.initState(); super.initState();
} }
@override
void dispose() {
_sizeController.dispose();
_priceController.dispose();
super.dispose();
}
bool _isError = false; bool _isError = false;
late double _currentSliderGbValue; late double _currentSliderGbValue;