mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-01-04 23:24:20 +00:00
refactor(ui): Skeletonize servere storage card and text details card. Enable skeleton transition animation.
This commit is contained in:
parent
8eb7c96826
commit
e11e5b1a7b
|
@ -1,4 +1,5 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:skeletonizer/skeletonizer.dart';
|
||||
|
||||
class BrandLinearIndicator extends StatelessWidget {
|
||||
const BrandLinearIndicator({
|
||||
|
@ -16,29 +17,31 @@ class BrandLinearIndicator extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(final BuildContext context) => LayoutBuilder(
|
||||
builder: (final context, final constraints) => Container(
|
||||
height: height,
|
||||
width: constraints.maxWidth,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
decoration: BoxDecoration(
|
||||
color: backgroundColor,
|
||||
borderRadius: BorderRadius.circular(height),
|
||||
),
|
||||
alignment: Alignment.centerLeft,
|
||||
child: AnimatedSlide(
|
||||
duration: const Duration(milliseconds: 400),
|
||||
curve: Curves.easeInOutCubicEmphasized,
|
||||
offset: Offset(
|
||||
-(1 - value),
|
||||
0,
|
||||
builder: (final context, final constraints) => Skeleton.leaf(
|
||||
child: Container(
|
||||
height: height,
|
||||
width: constraints.maxWidth,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
decoration: BoxDecoration(
|
||||
color: backgroundColor,
|
||||
borderRadius: BorderRadius.circular(height),
|
||||
),
|
||||
child: AnimatedContainer(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: AnimatedSlide(
|
||||
duration: const Duration(milliseconds: 400),
|
||||
curve: Curves.easeInOutCubicEmphasized,
|
||||
width: constraints.maxWidth,
|
||||
decoration: BoxDecoration(
|
||||
color: color,
|
||||
borderRadius: BorderRadius.circular(height),
|
||||
offset: Offset(
|
||||
-(1 - value),
|
||||
0,
|
||||
),
|
||||
child: AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 400),
|
||||
curve: Curves.easeInOutCubicEmphasized,
|
||||
width: constraints.maxWidth,
|
||||
decoration: BoxDecoration(
|
||||
color: color,
|
||||
borderRadius: BorderRadius.circular(height),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
95
lib/ui/molecules/cards/server_text_details_card.dart
Normal file
95
lib/ui/molecules/cards/server_text_details_card.dart
Normal file
|
@ -0,0 +1,95 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_detailed_info/server_detailed_info_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/server_metadata.dart';
|
||||
import 'package:selfprivacy/ui/atoms/cards/filled_card.dart';
|
||||
import 'package:selfprivacy/ui/atoms/list_tiles/list_tile_on_surface_variant.dart';
|
||||
import 'package:selfprivacy/utils/fake_data.dart';
|
||||
import 'package:skeletonizer/skeletonizer.dart';
|
||||
|
||||
class ServerTextDetailsCard extends StatelessWidget {
|
||||
const ServerTextDetailsCard({super.key});
|
||||
|
||||
@override
|
||||
Widget build(final BuildContext context) {
|
||||
final details = context.watch<ServerDetailsCubit>().state;
|
||||
|
||||
final isLoading = details is! Loaded;
|
||||
|
||||
if (details is ServerDetailsNotReady) {
|
||||
return _TempMessage(message: 'basis.no_data'.tr());
|
||||
} else {
|
||||
return Skeletonizer(
|
||||
enabled: isLoading || details.metadata.isEmpty,
|
||||
containersColor: Theme.of(context).colorScheme.surfaceContainerLow,
|
||||
enableSwitchAnimation: true,
|
||||
child: FilledCard(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Skeleton.keep(
|
||||
child: Text(
|
||||
'server.general_information'.tr(),
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (!isLoading)
|
||||
...details.metadata.map(
|
||||
(final metadata) => _ServerTextDetailTile(
|
||||
metadata: metadata,
|
||||
),
|
||||
),
|
||||
if (isLoading || details.metadata.isEmpty)
|
||||
...List.generate(
|
||||
8,
|
||||
(final index) => FakeSelfPrivacyData.fakeServerMetadataEntity,
|
||||
).map(
|
||||
(final metadata) => _ServerTextDetailTile(metadata: metadata),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _ServerTextDetailTile extends StatelessWidget {
|
||||
const _ServerTextDetailTile({
|
||||
required this.metadata,
|
||||
});
|
||||
|
||||
final ServerMetadataEntity metadata;
|
||||
|
||||
@override
|
||||
Widget build(final BuildContext context) => ListTileOnSurfaceVariant(
|
||||
leadingIcon: metadata.type.icon,
|
||||
title: metadata.trId.tr(),
|
||||
subtitle: metadata.value,
|
||||
);
|
||||
}
|
||||
|
||||
class _TempMessage extends StatelessWidget {
|
||||
const _TempMessage({
|
||||
required this.message,
|
||||
});
|
||||
|
||||
final String message;
|
||||
@override
|
||||
Widget build(final BuildContext context) => SizedBox(
|
||||
height: 200,
|
||||
child: Center(
|
||||
child: Text(
|
||||
message,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
124
lib/ui/molecules/cards/storage_card.dart
Normal file
124
lib/ui/molecules/cards/storage_card.dart
Normal file
|
@ -0,0 +1,124 @@
|
|||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/disk_status.dart';
|
||||
import 'package:selfprivacy/logic/models/state_types.dart';
|
||||
import 'package:selfprivacy/ui/atoms/masks/icon_status_mask.dart';
|
||||
import 'package:selfprivacy/ui/organisms/storage_list_items/server_storage_list_item.dart';
|
||||
import 'package:selfprivacy/ui/router/router.dart';
|
||||
import 'package:selfprivacy/utils/fake_data.dart';
|
||||
import 'package:skeletonizer/skeletonizer.dart';
|
||||
|
||||
class StorageCard extends StatelessWidget {
|
||||
const StorageCard({
|
||||
required this.diskStatus,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final DiskStatus diskStatus;
|
||||
|
||||
@override
|
||||
Widget build(final BuildContext context) {
|
||||
final List<Widget> sections = [];
|
||||
for (final DiskVolume volume in diskStatus.diskVolumes) {
|
||||
sections.add(
|
||||
const SizedBox(height: 16),
|
||||
);
|
||||
sections.add(
|
||||
ServerStorageListItem(
|
||||
volume: volume,
|
||||
dense: true,
|
||||
showIcon: false,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
final List<Widget> fakeSections = [
|
||||
const SizedBox(height: 16),
|
||||
ServerStorageListItem(
|
||||
volume: FakeSelfPrivacyData.fakeDiskVolume,
|
||||
dense: true,
|
||||
showIcon: false,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
ServerStorageListItem(
|
||||
volume: FakeSelfPrivacyData.fakeDiskVolume,
|
||||
dense: true,
|
||||
showIcon: false,
|
||||
),
|
||||
];
|
||||
|
||||
StateType state = context.watch<ServerInstallationCubit>().state
|
||||
is ServerInstallationFinished
|
||||
? StateType.stable
|
||||
: StateType.uninitialized;
|
||||
|
||||
if (state == StateType.stable && !diskStatus.isDiskOkay) {
|
||||
state = StateType.error;
|
||||
}
|
||||
|
||||
return Skeletonizer(
|
||||
enabled: diskStatus.diskVolumes.isEmpty,
|
||||
enableSwitchAnimation: true,
|
||||
child: Card(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: InkResponse(
|
||||
highlightShape: BoxShape.rectangle,
|
||||
onTap: () => diskStatus.diskVolumes.isEmpty
|
||||
? null
|
||||
: context.pushRoute(ServerStorageRoute(diskStatus: diskStatus)),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Skeleton.shade(
|
||||
child: Text(
|
||||
'storage.card_title'.tr(),
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
),
|
||||
if (state != StateType.uninitialized)
|
||||
Text(
|
||||
diskStatus.isDiskOkay
|
||||
? 'storage.status_ok'.tr()
|
||||
: 'storage.status_error'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (state != StateType.uninitialized)
|
||||
Skeleton.ignore(
|
||||
child: IconStatusMask(
|
||||
status: state,
|
||||
icon: Icon(
|
||||
diskStatus.isDiskOkay
|
||||
? Icons.check_circle_outline
|
||||
: Icons.error_outline,
|
||||
size: 24,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
...sections,
|
||||
if (diskStatus.diskVolumes.isEmpty) ...fakeSections,
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -82,6 +82,7 @@ class _DevicesInfo extends StatelessWidget {
|
|||
Skeletonizer(
|
||||
enabled:
|
||||
devicesStatus.thisDevice == FakeSelfPrivacyData.thisDeviceToken,
|
||||
enableSwitchAnimation: true,
|
||||
child: DeviceItem(
|
||||
device: devicesStatus.thisDevice,
|
||||
),
|
||||
|
@ -103,6 +104,7 @@ class _DevicesInfo extends StatelessWidget {
|
|||
3,
|
||||
(final index) => Skeletonizer(
|
||||
enabled: true,
|
||||
enableSwitchAnimation: true,
|
||||
child: DeviceItem(
|
||||
device: FakeSelfPrivacyData.otherDeviceToken,
|
||||
),
|
||||
|
|
|
@ -68,6 +68,7 @@ class _DnsDetailsPageState extends State<DnsDetailsPage> {
|
|||
.map(
|
||||
(final dnsRecord) => Skeletonizer(
|
||||
enabled: refreshing,
|
||||
enableSwitchAnimation: true,
|
||||
child: DnsRecordItem(
|
||||
dnsRecord: dnsRecord,
|
||||
refreshing: refreshing,
|
||||
|
|
|
@ -103,6 +103,7 @@ class _ProvidersPageState extends State<ProvidersPage> {
|
|||
const SizedBox(height: 16),
|
||||
Skeletonizer(
|
||||
enabled: dnsStatus == DnsRecordsStatus.refreshing,
|
||||
enableSwitchAnimation: true,
|
||||
child: ProvidersPageCard(
|
||||
state: getDnsStatus(),
|
||||
icon: BrandIcons.globe,
|
||||
|
@ -119,6 +120,7 @@ class _ProvidersPageState extends State<ProvidersPage> {
|
|||
Skeletonizer(
|
||||
enabled: backupsState is BackupsLoading ||
|
||||
backupsState is BackupsInitial,
|
||||
enableSwitchAnimation: true,
|
||||
child: ProvidersPageCard(
|
||||
state: backupsState is BackupsInitialized
|
||||
? StateType.stable
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'package:selfprivacy/config/get_it_config.dart';
|
|||
import 'package:selfprivacy/logic/bloc/recovery_key/recovery_key_bloc.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/ui/atoms/buttons/brand_button.dart';
|
||||
import 'package:selfprivacy/ui/atoms/buttons/outlined_button.dart';
|
||||
import 'package:selfprivacy/ui/atoms/cards/filled_card.dart';
|
||||
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
|
||||
import 'package:selfprivacy/ui/pages/recovery_key/recovery_key_receiving.dart';
|
||||
|
@ -58,6 +59,7 @@ class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
|
|||
heroSubtitle: subtitle,
|
||||
hasBackButton: true,
|
||||
hasFlashButton: false,
|
||||
heroIcon: Icons.password_outlined,
|
||||
children: widgets,
|
||||
),
|
||||
);
|
||||
|
@ -92,7 +94,7 @@ class _RecoveryKeyContentState extends State<RecoveryKeyContent> {
|
|||
),
|
||||
const SizedBox(height: 16),
|
||||
if (!_isConfigurationVisible && keyStatus.isValid && keyStatus.exists)
|
||||
BrandButton.text(
|
||||
BrandOutlinedButton(
|
||||
title: 'recovery_key.key_replace_button'.tr(),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
|
@ -157,55 +159,44 @@ class RecoveryKeyInformation extends StatelessWidget {
|
|||
final RecoveryKeyState state;
|
||||
|
||||
@override
|
||||
Widget build(final BuildContext context) {
|
||||
const EdgeInsets padding =
|
||||
EdgeInsets.symmetric(vertical: 8.0, horizontal: 8.0);
|
||||
return SizedBox(
|
||||
width: double.infinity,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (state.expiresAt != null)
|
||||
Padding(
|
||||
padding: padding,
|
||||
child: Text(
|
||||
'recovery_key.key_valid_until'.tr(
|
||||
args: [DateFormat.yMMMMd().format(state.expiresAt!)],
|
||||
Widget build(final BuildContext context) => SizedBox(
|
||||
width: double.infinity,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (state.expiresAt != null)
|
||||
ListTile(
|
||||
title: Text(
|
||||
'recovery_key.key_valid_until'.tr(
|
||||
args: [DateFormat.yMMMMd().format(state.expiresAt!)],
|
||||
),
|
||||
),
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
color: state.isInvalidBecauseExpired
|
||||
? Theme.of(context).colorScheme.error
|
||||
: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
textColor: state.isInvalidBecauseExpired
|
||||
? Theme.of(context).colorScheme.error
|
||||
: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
if (state.usesLeft != null)
|
||||
Padding(
|
||||
padding: padding,
|
||||
child: Text(
|
||||
'recovery_key.key_valid_for'.tr(
|
||||
args: [state.usesLeft!.toString()],
|
||||
if (state.usesLeft != null)
|
||||
ListTile(
|
||||
title: Text(
|
||||
'recovery_key.key_valid_for'.tr(
|
||||
args: [state.usesLeft!.toString()],
|
||||
),
|
||||
),
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
color: state.isInvalidBecauseUsed
|
||||
? Theme.of(context).colorScheme.error
|
||||
: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
textColor: state.isInvalidBecauseUsed
|
||||
? Theme.of(context).colorScheme.error
|
||||
: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
if (state.generatedAt != null)
|
||||
Padding(
|
||||
padding: padding,
|
||||
child: Text(
|
||||
'recovery_key.key_creation_date'.tr(
|
||||
args: [DateFormat.yMMMMd().format(state.generatedAt!)],
|
||||
if (state.generatedAt != null)
|
||||
ListTile(
|
||||
title: Text(
|
||||
'recovery_key.key_creation_date'.tr(
|
||||
args: [DateFormat.yMMMMd().format(state.generatedAt!)],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
class RecoveryKeyConfiguration extends StatefulWidget {
|
||||
|
|
|
@ -5,7 +5,6 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||
import 'package:selfprivacy/logic/bloc/volumes/volumes_bloc.dart';
|
||||
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
|
||||
import 'package:selfprivacy/logic/cubit/metrics/metrics_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_detailed_info/server_detailed_info_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/disk_status.dart';
|
||||
import 'package:selfprivacy/logic/models/metrics.dart';
|
||||
|
@ -13,17 +12,16 @@ import 'package:selfprivacy/theming/harmonized_basic_colors.dart';
|
|||
import 'package:selfprivacy/ui/atoms/buttons/segmented_buttons.dart';
|
||||
import 'package:selfprivacy/ui/atoms/cards/filled_card.dart';
|
||||
import 'package:selfprivacy/ui/atoms/icons/brand_icons.dart';
|
||||
import 'package:selfprivacy/ui/atoms/list_tiles/list_tile_on_surface_variant.dart';
|
||||
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
|
||||
import 'package:selfprivacy/ui/molecules/cards/server_text_details_card.dart';
|
||||
import 'package:selfprivacy/ui/molecules/cards/storage_card.dart';
|
||||
import 'package:selfprivacy/ui/pages/server_details/charts/cpu_chart.dart';
|
||||
import 'package:selfprivacy/ui/pages/server_details/charts/disk_charts.dart';
|
||||
import 'package:selfprivacy/ui/pages/server_details/charts/memory_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/router/router.dart';
|
||||
|
||||
part 'charts/chart.dart';
|
||||
part 'text_details.dart';
|
||||
|
||||
var navigatorKey = GlobalKey<NavigatorState>();
|
||||
|
||||
|
@ -99,7 +97,7 @@ class _ServerDetailsScreenState extends State<ServerDetailsScreen>
|
|||
child: _Chart(),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
_TextDetails(),
|
||||
const ServerTextDetailsCard(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
part of 'server_details_screen.dart';
|
||||
|
||||
class _TextDetails extends StatelessWidget {
|
||||
@override
|
||||
Widget build(final BuildContext context) {
|
||||
final details = context.watch<ServerDetailsCubit>().state;
|
||||
|
||||
if (details is ServerDetailsLoading || details is ServerDetailsInitial) {
|
||||
return _TempMessage(message: 'basis.loading'.tr());
|
||||
} else if (details is ServerDetailsNotReady) {
|
||||
return _TempMessage(message: 'basis.no_data'.tr());
|
||||
} else if (details is Loaded) {
|
||||
return FilledCard(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Text(
|
||||
'server.general_information'.tr(),
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
...details.metadata.map(
|
||||
(final metadata) => ListTileOnSurfaceVariant(
|
||||
leadingIcon: metadata.type.icon,
|
||||
title: metadata.trId.tr(),
|
||||
subtitle: metadata.value,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
} else {
|
||||
throw Exception('wrong state');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _TempMessage extends StatelessWidget {
|
||||
const _TempMessage({
|
||||
required this.message,
|
||||
});
|
||||
|
||||
final String message;
|
||||
@override
|
||||
Widget build(final BuildContext context) => SizedBox(
|
||||
height: 200,
|
||||
child: Center(
|
||||
child: Text(
|
||||
message,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
|
@ -1,431 +0,0 @@
|
|||
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': 'Апиа',
|
||||
};
|
|
@ -1,101 +0,0 @@
|
|||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/disk_status.dart';
|
||||
import 'package:selfprivacy/logic/models/state_types.dart';
|
||||
import 'package:selfprivacy/ui/atoms/masks/icon_status_mask.dart';
|
||||
import 'package:selfprivacy/ui/organisms/storage_list_items/server_storage_list_item.dart';
|
||||
import 'package:selfprivacy/ui/router/router.dart';
|
||||
|
||||
class StorageCard extends StatelessWidget {
|
||||
const StorageCard({
|
||||
required this.diskStatus,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final DiskStatus diskStatus;
|
||||
|
||||
@override
|
||||
Widget build(final BuildContext context) {
|
||||
final List<Widget> sections = [];
|
||||
for (final DiskVolume volume in diskStatus.diskVolumes) {
|
||||
sections.add(
|
||||
const SizedBox(height: 16),
|
||||
);
|
||||
sections.add(
|
||||
ServerStorageListItem(
|
||||
volume: volume,
|
||||
dense: true,
|
||||
showIcon: false,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
StateType state = context.watch<ServerInstallationCubit>().state
|
||||
is ServerInstallationFinished
|
||||
? StateType.stable
|
||||
: StateType.uninitialized;
|
||||
|
||||
if (state == StateType.stable && !diskStatus.isDiskOkay) {
|
||||
state = StateType.error;
|
||||
}
|
||||
|
||||
return Card(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: InkResponse(
|
||||
highlightShape: BoxShape.rectangle,
|
||||
|
||||
/// TODO: when 'isEmpty' replace with a skeleton
|
||||
onTap: () => diskStatus.diskVolumes.isEmpty
|
||||
? null
|
||||
: context.pushRoute(ServerStorageRoute(diskStatus: diskStatus)),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'storage.card_title'.tr(),
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
if (state != StateType.uninitialized)
|
||||
Text(
|
||||
diskStatus.isDiskOkay
|
||||
? 'storage.status_ok'.tr()
|
||||
: 'storage.status_error'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (state != StateType.uninitialized)
|
||||
IconStatusMask(
|
||||
status: state,
|
||||
icon: Icon(
|
||||
diskStatus.isDiskOkay
|
||||
? Icons.check_circle_outline
|
||||
: Icons.error_outline,
|
||||
size: 24,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
...sections,
|
||||
const SizedBox(height: 8),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,8 @@
|
|||
import 'package:selfprivacy/logic/api_maps/rest_maps/dns_providers/desired_dns_record.dart';
|
||||
import 'package:selfprivacy/logic/models/disk_size.dart';
|
||||
import 'package:selfprivacy/logic/models/disk_status.dart';
|
||||
import 'package:selfprivacy/logic/models/json/api_token.dart';
|
||||
import 'package:selfprivacy/logic/models/server_metadata.dart';
|
||||
|
||||
/// Fake data collections to fill skeletons
|
||||
class FakeSelfPrivacyData {
|
||||
|
@ -41,4 +44,18 @@ class FakeSelfPrivacyData {
|
|||
isCaller: false,
|
||||
date: DateTime.now(),
|
||||
);
|
||||
|
||||
static final DiskVolume fakeDiskVolume = DiskVolume(
|
||||
name: 'fake_volume_name',
|
||||
isResizable: false,
|
||||
root: false,
|
||||
sizeTotal: const DiskSize(byte: 350000000),
|
||||
sizeUsed: const DiskSize(byte: 100000000),
|
||||
);
|
||||
|
||||
static final ServerMetadataEntity fakeServerMetadataEntity =
|
||||
ServerMetadataEntity(
|
||||
trId: 'some_long_id',
|
||||
value: 'some_interesting_value',
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue