Refactor cards, move server details screen from modal to screen, move storage card to server screen.

pull/116/head
Inex Code 2022-09-15 19:57:26 +03:00
parent bb0da1ac14
commit 0c31e7697c
20 changed files with 208 additions and 357 deletions

View File

@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:selfprivacy/logic/cubit/devices/devices_cubit.dart'; import 'package:selfprivacy/logic/cubit/devices/devices_cubit.dart';
import 'package:selfprivacy/logic/cubit/recovery_key/recovery_key_cubit.dart'; import 'package:selfprivacy/logic/cubit/recovery_key/recovery_key_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/cubit/server_installation/server_installation_cubit.dart';
import 'package:selfprivacy/logic/cubit/app_settings/app_settings_cubit.dart'; import 'package:selfprivacy/logic/cubit/app_settings/app_settings_cubit.dart';
import 'package:selfprivacy/logic/cubit/backups/backups_cubit.dart'; import 'package:selfprivacy/logic/cubit/backups/backups_cubit.dart';

View File

@ -19,23 +19,6 @@ class BrandCards {
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
child: child, child: child,
); );
static Widget outlined({required final Widget child}) => _OutlinedCard(
child: child,
);
static Widget filled({
required final Widget child,
final bool tertiary = false,
final bool secondary = false,
final bool error = false,
final bool clipped = true,
}) =>
_FilledCard(
tertiary: tertiary,
secondary: secondary,
error: error,
clipped: clipped,
child: child,
);
} }
class _BrandCard extends StatelessWidget { class _BrandCard extends StatelessWidget {
@ -63,58 +46,6 @@ class _BrandCard extends StatelessWidget {
); );
} }
class _OutlinedCard extends StatelessWidget {
const _OutlinedCard({
required this.child,
});
final Widget child;
@override
Widget build(final BuildContext context) => Card(
elevation: 0.0,
shape: RoundedRectangleBorder(
borderRadius: const BorderRadius.all(Radius.circular(12)),
side: BorderSide(
color: Theme.of(context).colorScheme.outline,
),
),
clipBehavior: Clip.antiAlias,
child: child,
);
}
class _FilledCard extends StatelessWidget {
const _FilledCard({
required this.child,
required this.secondary,
required this.tertiary,
required this.error,
required this.clipped,
});
final Widget child;
final bool tertiary;
final bool error;
final bool clipped;
final bool secondary;
@override
Widget build(final BuildContext context) => Card(
elevation: 0.0,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
),
clipBehavior: clipped ? Clip.antiAlias : Clip.none,
color: error
? Theme.of(context).colorScheme.errorContainer
: secondary
? Theme.of(context).colorScheme.secondaryContainer
: tertiary
? Theme.of(context).colorScheme.tertiaryContainer
: Theme.of(context).colorScheme.surfaceVariant,
child: child,
);
}
final List<BoxShadow> bigShadow = [ final List<BoxShadow> bigShadow = [
BoxShadow( BoxShadow(
offset: const Offset(0, 4), offset: const Offset(0, 4),

View File

@ -0,0 +1,34 @@
import 'package:flutter/material.dart';
class FilledCard extends StatelessWidget {
const FilledCard({
required this.child,
this.secondary = false,
this.tertiary = false,
this.error = false,
this.clipped = true,
final super.key,
});
final Widget child;
final bool tertiary;
final bool error;
final bool clipped;
final bool secondary;
@override
Widget build(final BuildContext context) => Card(
elevation: 0.0,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
),
clipBehavior: clipped ? Clip.antiAlias : Clip.none,
color: error
? Theme.of(context).colorScheme.errorContainer
: secondary
? Theme.of(context).colorScheme.secondaryContainer
: tertiary
? Theme.of(context).colorScheme.tertiaryContainer
: Theme.of(context).colorScheme.surfaceVariant,
child: child,
);
}

View File

@ -0,0 +1,22 @@
import 'package:flutter/material.dart';
class OutlinedCard extends StatelessWidget {
const OutlinedCard({
required this.child,
final super.key,
});
final Widget child;
@override
Widget build(final BuildContext context) => Card(
elevation: 0.0,
shape: RoundedRectangleBorder(
borderRadius: const BorderRadius.all(Radius.circular(12)),
side: BorderSide(
color: Theme.of(context).colorScheme.outline,
),
),
clipBehavior: Clip.antiAlias,
child: child,
);
}

View File

@ -8,11 +8,11 @@ import 'package:selfprivacy/logic/models/state_types.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';
import 'package:selfprivacy/ui/components/brand_cards/outlined_card.dart';
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart'; import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.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_text/brand_text.dart'; import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
import 'package:selfprivacy/ui/components/brand_cards/brand_cards.dart';
GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>(); GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
@ -63,7 +63,7 @@ class _BackupDetailsState extends State<BackupDetails>
BrandText.body1('providers.backup.waitingForRebuild'.tr()), BrandText.body1('providers.backup.waitingForRebuild'.tr()),
if (backupStatus != BackupStatusEnum.initializing && if (backupStatus != BackupStatusEnum.initializing &&
backupStatus != BackupStatusEnum.noKey) backupStatus != BackupStatusEnum.noKey)
BrandCards.outlined( OutlinedCard(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -127,7 +127,7 @@ class _BackupDetailsState extends State<BackupDetails>
// When clicked, starts the restore action // When clicked, starts the restore action
if (backupStatus != BackupStatusEnum.initializing && if (backupStatus != BackupStatusEnum.initializing &&
backupStatus != BackupStatusEnum.noKey) backupStatus != BackupStatusEnum.noKey)
BrandCards.outlined( OutlinedCard(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -195,7 +195,7 @@ class _BackupDetailsState extends State<BackupDetails>
), ),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
BrandCards.outlined( OutlinedCard(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [

View File

@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
import 'package:selfprivacy/config/get_it_config.dart'; import 'package:selfprivacy/config/get_it_config.dart';
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart'; import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
import 'package:selfprivacy/logic/cubit/dns_records/dns_records_cubit.dart'; import 'package:selfprivacy/logic/cubit/dns_records/dns_records_cubit.dart';
import 'package:selfprivacy/ui/components/brand_cards/brand_cards.dart'; import 'package:selfprivacy/ui/components/brand_cards/filled_card.dart';
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart'; import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart'; import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart';
@ -61,7 +61,8 @@ class _DnsDetailsPageState extends State<DnsDetailsPage> {
isError = true; isError = true;
break; break;
} }
return BrandCards.filled( return FilledCard(
error: isError,
child: ListTile( child: ListTile(
onTap: dnsState == DnsRecordsStatus.error ? () => fixCallback() : null, onTap: dnsState == DnsRecordsStatus.error ? () => fixCallback() : null,
leading: icon, leading: icon,
@ -74,7 +75,6 @@ class _DnsDetailsPageState extends State<DnsDetailsPage> {
? Theme.of(context).colorScheme.error ? Theme.of(context).colorScheme.error
: Theme.of(context).colorScheme.onSurfaceVariant, : Theme.of(context).colorScheme.onSurfaceVariant,
), ),
error: isError,
); );
} }
@ -95,7 +95,7 @@ class _DnsDetailsPageState extends State<DnsDetailsPage> {
heroIcon: BrandIcons.globe, heroIcon: BrandIcons.globe,
heroTitle: 'providers.domain.screen_title'.tr(), heroTitle: 'providers.domain.screen_title'.tr(),
children: <Widget>[ children: <Widget>[
BrandCards.outlined( FilledCard(
child: ListTile( child: ListTile(
title: Text( title: Text(
'not_ready_card.in_menu'.tr(), 'not_ready_card.in_menu'.tr(),

View File

@ -116,7 +116,7 @@ class _AppSettingsPageState extends State<AppSettingsPage> {
), ),
), ),
const Divider(height: 0), const Divider(height: 0),
_DeleteServer(context) _deleteServer(context)
], ],
), ),
), ),
@ -124,7 +124,7 @@ class _AppSettingsPageState extends State<AppSettingsPage> {
); );
} }
Widget _DeleteServer(final BuildContext context) { Widget _deleteServer(final BuildContext context) {
final bool isDisabled = final bool isDisabled =
context.watch<ServerInstallationCubit>().state.serverDetails == null; context.watch<ServerInstallationCubit>().state.serverDetails == null;
return Container( return Container(

View File

@ -6,7 +6,7 @@ import 'package:selfprivacy/logic/cubit/provider_volumes/provider_volume_cubit.d
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart'; import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
import 'package:selfprivacy/logic/cubit/server_volumes/server_volume_cubit.dart'; import 'package:selfprivacy/logic/cubit/server_volumes/server_volume_cubit.dart';
import 'package:selfprivacy/logic/cubit/services/services_cubit.dart'; import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
import 'package:selfprivacy/ui/components/brand_cards/brand_cards.dart'; import 'package:selfprivacy/ui/components/brand_cards/filled_card.dart';
import 'package:selfprivacy/ui/components/brand_header/brand_header.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/pages/devices/devices.dart'; import 'package:selfprivacy/ui/pages/devices/devices.dart';
@ -157,7 +157,7 @@ class _MoreMenuItem extends StatelessWidget {
final Color color = accent final Color color = accent
? Theme.of(context).colorScheme.onTertiaryContainer ? Theme.of(context).colorScheme.onTertiaryContainer
: Theme.of(context).colorScheme.onSurface; : Theme.of(context).colorScheme.onSurface;
return BrandCards.filled( return FilledCard(
tertiary: accent, tertiary: accent,
child: ListTile( child: ListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),

View File

@ -8,13 +8,11 @@ import 'package:selfprivacy/logic/cubit/server_installation/server_installation_
import 'package:selfprivacy/logic/cubit/provider_volumes/provider_volume_cubit.dart'; import 'package:selfprivacy/logic/cubit/provider_volumes/provider_volume_cubit.dart';
import 'package:selfprivacy/logic/cubit/server_volumes/server_volume_cubit.dart'; import 'package:selfprivacy/logic/cubit/server_volumes/server_volume_cubit.dart';
import 'package:selfprivacy/logic/models/provider.dart'; import 'package:selfprivacy/logic/models/provider.dart';
import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart';
import 'package:selfprivacy/ui/components/brand_cards/brand_cards.dart'; import 'package:selfprivacy/ui/components/brand_cards/brand_cards.dart';
import 'package:selfprivacy/ui/components/brand_header/brand_header.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/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:selfprivacy/ui/components/not_ready_card/not_ready_card.dart'; import 'package:selfprivacy/ui/components/not_ready_card/not_ready_card.dart';
import 'package:selfprivacy/ui/helpers/modals.dart';
import 'package:selfprivacy/ui/pages/backup_details/backup_details.dart'; import 'package:selfprivacy/ui/pages/backup_details/backup_details.dart';
import 'package:selfprivacy/ui/pages/dns_details/dns_details.dart'; import 'package:selfprivacy/ui/pages/dns_details/dns_details.dart';
import 'package:selfprivacy/ui/pages/providers/storage_card.dart'; import 'package:selfprivacy/ui/pages/providers/storage_card.dart';
@ -122,14 +120,7 @@ class _Card extends StatelessWidget {
case ProviderType.server: case ProviderType.server:
title = 'providers.server.card_title'.tr(); title = 'providers.server.card_title'.tr();
stableText = 'providers.server.status'.tr(); stableText = 'providers.server.status'.tr();
onTap = () => showBrandBottomSheet( onTap = () => Navigator.of(context).push(materialRoute(const ServerDetailsScreen()));
context: context,
builder: (final BuildContext context) => const BrandBottomSheet(
isExpended: true,
child: ServerDetailsScreen(),
),
);
break; break;
case ProviderType.domain: case ProviderType.domain:
title = 'providers.domain.screen_title'.tr(); title = 'providers.domain.screen_title'.tr();

View File

@ -2,7 +2,6 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.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/cubit/providers/providers_cubit.dart'; import 'package:selfprivacy/logic/cubit/providers/providers_cubit.dart';
import 'package:selfprivacy/ui/components/brand_cards/brand_cards.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:selfprivacy/ui/pages/server_storage/disk_status.dart'; import 'package:selfprivacy/ui/pages/server_storage/disk_status.dart';
import 'package:selfprivacy/ui/pages/server_storage/server_storage.dart'; import 'package:selfprivacy/ui/pages/server_storage/server_storage.dart';
@ -42,7 +41,9 @@ class StorageCard extends StatelessWidget {
state = StateType.error; state = StateType.error;
} }
return GestureDetector( return Card(
child: InkResponse(
highlightShape: BoxShape.rectangle,
onTap: () => Navigator.of(context).push( onTap: () => Navigator.of(context).push(
materialRoute( materialRoute(
ServerStoragePage( ServerStoragePage(
@ -50,49 +51,49 @@ class StorageCard extends StatelessWidget {
), ),
), ),
), ),
child: BrandCards.big(
child: Column( child: Padding(
crossAxisAlignment: CrossAxisAlignment.start, padding: const EdgeInsets.all(16.0),
children: [ child: Column(
Row( crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
children: [ Row(
IconStatusMask( mainAxisAlignment: MainAxisAlignment.spaceBetween,
status: state, crossAxisAlignment: CrossAxisAlignment.start,
child: const Icon( children: [
Icons.storage_outlined, Column(
size: 30, crossAxisAlignment: CrossAxisAlignment.start,
color: Colors.white, children: [
Text(
'providers.storage.card_title'.tr(),
style: Theme.of(context).textTheme.titleLarge,
),
if (state != StateType.uninitialized)
Text(
diskStatus.isDiskOkay
? 'providers.storage.status_ok'.tr()
: 'providers.storage.status_error'.tr(),
style: Theme.of(context).textTheme.bodyLarge,
),
],
), ),
), if (state != StateType.uninitialized)
if (state != StateType.uninitialized) IconStatusMask(
IconStatusMask( status: state,
status: state, child: Icon(
child: Icon( diskStatus.isDiskOkay
diskStatus.isDiskOkay ? Icons.check_circle_outline
? Icons.check_circle_outline : Icons.error_outline,
: Icons.error_outline, size: 24,
size: 24, color: Colors.white,
color: Colors.white, ),
), ),
), ],
],
),
const SizedBox(height: 16),
Text(
'providers.storage.card_title'.tr(),
style: Theme.of(context).textTheme.titleLarge,
),
if (state != StateType.uninitialized)
Text(
diskStatus.isDiskOkay
? 'providers.storage.status_ok'.tr()
: 'providers.storage.status_error'.tr(),
style: Theme.of(context).textTheme.bodyLarge,
), ),
...sections, ...sections,
const SizedBox(height: 8), const SizedBox(height: 8),
], ],
),
), ),
), ),
); );

View File

@ -8,7 +8,7 @@ import 'package:selfprivacy/logic/cubit/recovery_key/recovery_key_cubit.dart';
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart'; import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart'; import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
import 'package:selfprivacy/ui/components/brand_button/filled_button.dart'; import 'package:selfprivacy/ui/components/brand_button/filled_button.dart';
import 'package:selfprivacy/ui/components/brand_cards/brand_cards.dart'; import 'package:selfprivacy/ui/components/brand_cards/filled_card.dart';
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart'; import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
import 'package:selfprivacy/ui/pages/recovery_key/recovery_key_receiving.dart'; import 'package:selfprivacy/ui/pages/recovery_key/recovery_key_receiving.dart';
import 'package:selfprivacy/utils/route_transitions/basic.dart'; import 'package:selfprivacy/utils/route_transitions/basic.dart';
@ -112,7 +112,7 @@ class RecoveryKeyStatusCard extends StatelessWidget {
final bool isValid; final bool isValid;
@override @override
Widget build(final BuildContext context) => BrandCards.filled( Widget build(final BuildContext context) => FilledCard(
child: ListTile( child: ListTile(
title: isValid title: isValid
? Text( ? Text(

View File

@ -17,7 +17,7 @@ class _Chart extends StatelessWidget {
]; ];
} else if (state is HetznerMetricsLoaded) { } else if (state is HetznerMetricsLoaded) {
charts = [ charts = [
BrandCards.filled( FilledCard(
clipped: false, clipped: false,
child: Padding( child: Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
@ -36,18 +36,6 @@ class _Chart extends StatelessWidget {
), ),
), ),
), ),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
BrandText.small('Public Network interface packets per sec'),
const SizedBox(width: 10),
const Legend(color: Colors.red, text: 'IN'),
const SizedBox(width: 5),
const Legend(color: Colors.green, text: 'OUT'),
],
),
const SizedBox(height: 20),
getPpsChart(state),
const SizedBox(height: 1), const SizedBox(height: 1),
Row( Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
@ -66,36 +54,33 @@ class _Chart extends StatelessWidget {
throw 'wrong state'; throw 'wrong state';
} }
return Container( return Column(
padding: const EdgeInsets.symmetric(horizontal: 5), children: [
child: Column( Padding(
children: [ padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10),
Padding( child: Row(
padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10), mainAxisAlignment: MainAxisAlignment.spaceBetween,
child: Row( children: [
mainAxisAlignment: MainAxisAlignment.spaceBetween, BrandRadioTile(
children: [ isChecked: period == Period.month,
BrandRadioTile( text: 'providers.server.chart.month'.tr(),
isChecked: period == Period.month, onPress: () => cubit.changePeriod(Period.month),
text: 'providers.server.chart.month'.tr(), ),
onPress: () => cubit.changePeriod(Period.month), BrandRadioTile(
), isChecked: period == Period.day,
BrandRadioTile( text: 'providers.server.chart.day'.tr(),
isChecked: period == Period.day, onPress: () => cubit.changePeriod(Period.day),
text: 'providers.server.chart.day'.tr(), ),
onPress: () => cubit.changePeriod(Period.day), BrandRadioTile(
), isChecked: period == Period.hour,
BrandRadioTile( text: 'providers.server.chart.hour'.tr(),
isChecked: period == Period.hour, onPress: () => cubit.changePeriod(Period.hour),
text: 'providers.server.chart.hour'.tr(), ),
onPress: () => cubit.changePeriod(Period.hour), ],
),
],
),
), ),
...charts, ),
], ...charts,
), ],
); );
} }
@ -112,20 +97,6 @@ class _Chart extends StatelessWidget {
); );
} }
Widget getPpsChart(final HetznerMetricsLoaded state) {
final ppsIn = state.ppsIn;
final ppsOut = state.ppsOut;
return SizedBox(
height: 200,
child: NetworkChart(
listData: [ppsIn, ppsOut],
period: state.period,
start: state.start,
),
);
}
Widget getBandwidthChart(final HetznerMetricsLoaded state) { Widget getBandwidthChart(final HetznerMetricsLoaded state) {
final ppsIn = state.bandwidthIn; final ppsIn = state.bandwidthIn;
final ppsOut = state.bandwidthOut; final ppsOut = state.bandwidthOut;

View File

@ -1,58 +0,0 @@
part of 'server_details_screen.dart';
class _Header extends StatelessWidget {
const _Header({
required this.providerState,
required this.tabController,
});
final StateType providerState;
final TabController tabController;
@override
Widget build(final BuildContext context) => Row(
children: [
IconStatusMask(
status: providerState,
child: const Icon(
BrandIcons.server,
size: 40,
color: Colors.white,
),
),
const SizedBox(width: 10),
BrandText.h2('providers.server.card_title'.tr()),
const Spacer(),
Padding(
padding: const EdgeInsets.symmetric(
vertical: 4,
horizontal: 2,
),
child: PopupMenuButton<_PopupMenuItemType>(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
onSelected: (final _PopupMenuItemType result) {
switch (result) {
case _PopupMenuItemType.setting:
tabController.animateTo(1);
break;
}
},
icon: const Icon(Icons.more_vert),
itemBuilder: (final BuildContext context) => [
PopupMenuItem<_PopupMenuItemType>(
value: _PopupMenuItemType.setting,
child: Container(
padding: const EdgeInsets.only(left: 5),
child: Text('basis.settings'.tr()),
),
),
],
),
),
],
);
}
enum _PopupMenuItemType { setting }

View File

@ -2,22 +2,24 @@ 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:selfprivacy/config/brand_colors.dart'; import 'package:selfprivacy/config/brand_colors.dart';
import 'package:selfprivacy/config/brand_theme.dart';
import 'package:selfprivacy/logic/common_enum/common_enum.dart'; import 'package:selfprivacy/logic/common_enum/common_enum.dart';
import 'package:selfprivacy/logic/cubit/hetzner_metrics/hetzner_metrics_cubit.dart'; import 'package:selfprivacy/logic/cubit/hetzner_metrics/hetzner_metrics_cubit.dart';
import 'package:selfprivacy/logic/cubit/provider_volumes/provider_volume_cubit.dart';
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/cubit/server_installation/server_installation_cubit.dart'; import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
import 'package:selfprivacy/logic/cubit/server_volumes/server_volume_cubit.dart';
import 'package:selfprivacy/logic/models/auto_upgrade_settings.dart'; import 'package:selfprivacy/logic/models/auto_upgrade_settings.dart';
import 'package:selfprivacy/logic/models/state_types.dart'; import 'package:selfprivacy/ui/components/brand_cards/filled_card.dart';
import 'package:selfprivacy/ui/components/brand_cards/brand_cards.dart';
import 'package:selfprivacy/ui/components/brand_header/brand_header.dart'; import 'package:selfprivacy/ui/components/brand_header/brand_header.dart';
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.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_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/switch_block/switch_bloc.dart'; import 'package:selfprivacy/ui/components/switch_block/switch_bloc.dart';
import 'package:selfprivacy/ui/pages/providers/storage_card.dart';
import 'package:selfprivacy/ui/pages/server_details/time_zone/lang.dart'; import 'package:selfprivacy/ui/pages/server_details/time_zone/lang.dart';
import 'package:selfprivacy/ui/pages/server_storage/disk_status.dart';
import 'package:selfprivacy/utils/extensions/duration.dart'; import 'package:selfprivacy/utils/extensions/duration.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';
@ -27,7 +29,6 @@ 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_details/charts/network_charts.dart';
part 'charts/chart.dart'; part 'charts/chart.dart';
part 'header.dart';
part 'server_settings.dart'; part 'server_settings.dart';
part 'text_details.dart'; part 'text_details.dart';
part 'time_zone/time_zone.dart'; part 'time_zone/time_zone.dart';
@ -64,59 +65,37 @@ class _ServerDetailsScreenState extends State<ServerDetailsScreen>
Widget build(final BuildContext context) { Widget build(final BuildContext context) {
final bool isReady = context.watch<ServerInstallationCubit>().state final bool isReady = context.watch<ServerInstallationCubit>().state
is ServerInstallationFinished; is ServerInstallationFinished;
final providerState = isReady ? StateType.stable : StateType.uninitialized;
if (!isReady) {
return BrandHeroScreen(
heroIcon: BrandIcons.server,
heroTitle: 'providers.server.card_title'.tr(),
heroSubtitle: 'not_ready_card.in_menu'.tr(),
children: const [],
);
}
return BlocProvider( return BlocProvider(
create: (final context) => ServerDetailsCubit()..check(), create: (final context) => ServerDetailsCubit()..check(),
child: Scaffold( child: BrandHeroScreen(
appBar: PreferredSize( heroIcon: BrandIcons.server,
preferredSize: const Size.fromHeight(52), heroTitle: 'providers.server.card_title'.tr(),
child: Column( heroSubtitle: 'providers.server.bottom_sheet.1'.tr(),
children: [ children: [
Container( StorageCard(
height: 51, diskStatus: DiskStatus.fromVolumes(
alignment: Alignment.center, context.read<ApiServerVolumeCubit>().state.volumes,
padding: const EdgeInsets.symmetric(horizontal: 15), context.read<ApiProviderVolumeCubit>().state.volumes,
child: BrandText.h4('basis.details'.tr()),
),
],
),
),
body: TabBarView(
physics: const NeverScrollableScrollPhysics(),
controller: tabController,
children: [
SingleChildScrollView(
physics: const 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()),
],
),
),
const SizedBox(height: 10),
BlocProvider(
create: (final context) => HetznerMetricsCubit()..restart(),
child: _Chart(),
),
const SizedBox(height: 20),
_TextDetails(),
],
),
), ),
_ServerSettings(tabController: tabController), ),
], BlocProvider(
), create: (final context) => HetznerMetricsCubit()..restart(),
child: _Chart(),
),
const SizedBox(height: 20),
_TextDetails(),
const _ServerSettings(),
],
), ),
); );
} }

View File

@ -1,9 +1,7 @@
part of 'server_details_screen.dart'; part of 'server_details_screen.dart';
class _ServerSettings extends StatefulWidget { class _ServerSettings extends StatefulWidget {
const _ServerSettings({required this.tabController}); const _ServerSettings();
final TabController tabController;
@override @override
State<_ServerSettings> createState() => _ServerSettingsState(); State<_ServerSettings> createState() => _ServerSettingsState();
@ -26,25 +24,8 @@ class _ServerSettingsState extends State<_ServerSettings> {
rebootAfterUpgrade = serverDetailsState.autoUpgradeSettings.allowReboot; rebootAfterUpgrade = serverDetailsState.autoUpgradeSettings.allowReboot;
} }
return ListView( return Column(
padding: paddingH15V0,
children: [ children: [
const SizedBox(height: 10),
Container(
height: 52,
alignment: Alignment.centerLeft,
padding: const EdgeInsets.only(left: 1),
child: Row(
children: [
IconButton(
icon: const Icon(BrandIcons.arrowLeft),
onPressed: () => widget.tabController.animateTo(0),
),
const SizedBox(width: 10),
BrandText.h4('basis.settings'.tr()),
],
),
),
SwitcherBlock( SwitcherBlock(
onChange: (final switched) { onChange: (final switched) {
context context

View File

@ -6,7 +6,7 @@ import 'package:selfprivacy/logic/cubit/client_jobs/client_jobs_cubit.dart';
import 'package:selfprivacy/logic/cubit/services/services_cubit.dart'; import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
import 'package:selfprivacy/logic/models/job.dart'; import 'package:selfprivacy/logic/models/job.dart';
import 'package:selfprivacy/logic/models/service.dart'; import 'package:selfprivacy/logic/models/service.dart';
import 'package:selfprivacy/ui/components/brand_cards/brand_cards.dart'; import 'package:selfprivacy/ui/components/brand_cards/filled_card.dart';
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart'; import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
@ -156,8 +156,8 @@ class ServiceStatusCard extends StatelessWidget {
Widget build(final BuildContext context) { Widget build(final BuildContext context) {
switch (status) { switch (status) {
case ServiceStatus.active: case ServiceStatus.active:
return BrandCards.filled( return const FilledCard(
child: const ListTile( child: ListTile(
leading: Icon( leading: Icon(
Icons.check_circle_outline, Icons.check_circle_outline,
size: 24, size: 24,
@ -166,70 +166,70 @@ class ServiceStatusCard extends StatelessWidget {
), ),
); );
case ServiceStatus.inactive: case ServiceStatus.inactive:
return BrandCards.filled( return const FilledCard(
child: const ListTile( tertiary: true,
child: ListTile(
leading: Icon( leading: Icon(
Icons.stop_circle_outlined, Icons.stop_circle_outlined,
size: 24, size: 24,
), ),
title: Text('Stopped'), title: Text('Stopped'),
), ),
tertiary: true,
); );
case ServiceStatus.failed: case ServiceStatus.failed:
return BrandCards.filled( return const FilledCard(
child: const ListTile( error: true,
child: ListTile(
leading: Icon( leading: Icon(
Icons.error_outline, Icons.error_outline,
size: 24, size: 24,
), ),
title: Text('Failed to start'), title: Text('Failed to start'),
), ),
error: true,
); );
case ServiceStatus.off: case ServiceStatus.off:
return BrandCards.filled( return const FilledCard(
child: const ListTile( tertiary: true,
child: ListTile(
leading: Icon( leading: Icon(
Icons.power_settings_new, Icons.power_settings_new,
size: 24, size: 24,
), ),
title: Text('Disabled'), title: Text('Disabled'),
), ),
tertiary: true,
); );
case ServiceStatus.activating: case ServiceStatus.activating:
return BrandCards.filled( return const FilledCard(
child: const ListTile( tertiary: true,
child: ListTile(
leading: Icon( leading: Icon(
Icons.restart_alt_outlined, Icons.restart_alt_outlined,
size: 24, size: 24,
), ),
title: Text('Activating'), title: Text('Activating'),
), ),
tertiary: true,
); );
case ServiceStatus.deactivating: case ServiceStatus.deactivating:
return BrandCards.filled( return const FilledCard(
child: const ListTile( tertiary: true,
child: ListTile(
leading: Icon( leading: Icon(
Icons.restart_alt_outlined, Icons.restart_alt_outlined,
size: 24, size: 24,
), ),
title: Text('Deactivating'), title: Text('Deactivating'),
), ),
tertiary: true,
); );
case ServiceStatus.reloading: case ServiceStatus.reloading:
return BrandCards.filled( return const FilledCard(
child: const ListTile( tertiary: true,
child: ListTile(
leading: Icon( leading: Icon(
Icons.restart_alt_outlined, Icons.restart_alt_outlined,
size: 24, size: 24,
), ),
title: Text('Restarting'), title: Text('Restarting'),
), ),
tertiary: true,
); );
} }
} }

View File

@ -4,7 +4,7 @@ import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_depe
import 'package:selfprivacy/logic/models/server_basic_info.dart'; import 'package:selfprivacy/logic/models/server_basic_info.dart';
import 'package:selfprivacy/ui/components/brand_button/filled_button.dart'; import 'package:selfprivacy/ui/components/brand_button/filled_button.dart';
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart'; import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
import 'package:selfprivacy/ui/components/brand_cards/brand_cards.dart'; import 'package:selfprivacy/ui/components/brand_cards/filled_card.dart';
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart'; import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
class RecoveryConfirmServer extends StatefulWidget { class RecoveryConfirmServer extends StatefulWidget {
@ -135,7 +135,7 @@ class _RecoveryConfirmServerState extends State<RecoveryConfirmServer> {
required final ServerBasicInfoWithValidators server, required final ServerBasicInfoWithValidators server,
final VoidCallback? onTap, final VoidCallback? onTap,
}) => }) =>
BrandCards.filled( FilledCard(
child: ListTile( child: ListTile(
contentPadding: contentPadding:
const EdgeInsets.symmetric(horizontal: 16, vertical: 16), const EdgeInsets.symmetric(horizontal: 16, vertical: 16),

View File

@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart'; import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart'; import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
import 'package:selfprivacy/ui/components/brand_cards/brand_cards.dart'; import 'package:selfprivacy/ui/components/brand_cards/outlined_card.dart';
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart'; import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
import 'package:selfprivacy/ui/pages/setup/recovering/recover_by_old_token.dart'; import 'package:selfprivacy/ui/pages/setup/recovering/recover_by_old_token.dart';
import 'package:selfprivacy/utils/route_transitions/basic.dart'; import 'package:selfprivacy/utils/route_transitions/basic.dart';
@ -20,7 +20,7 @@ class RecoveryMethodSelect extends StatelessWidget {
onBackButtonPressed: onBackButtonPressed:
context.read<ServerInstallationCubit>().revertRecoveryStep, context.read<ServerInstallationCubit>().revertRecoveryStep,
children: [ children: [
BrandCards.outlined( OutlinedCard(
child: ListTile( child: ListTile(
title: Text( title: Text(
'recovering.method_select_other_device'.tr(), 'recovering.method_select_other_device'.tr(),
@ -33,7 +33,7 @@ class RecoveryMethodSelect extends StatelessWidget {
), ),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
BrandCards.outlined( OutlinedCard(
child: ListTile( child: ListTile(
title: Text( title: Text(
'recovering.method_select_recovery_key'.tr(), 'recovering.method_select_recovery_key'.tr(),
@ -75,7 +75,7 @@ class RecoveryFallbackMethodSelect extends StatelessWidget {
hasBackButton: true, hasBackButton: true,
hasFlashButton: false, hasFlashButton: false,
children: [ children: [
BrandCards.outlined( OutlinedCard(
child: ListTile( child: ListTile(
title: Text( title: Text(
'recovering.fallback_select_token_copy'.tr(), 'recovering.fallback_select_token_copy'.tr(),
@ -92,7 +92,7 @@ class RecoveryFallbackMethodSelect extends StatelessWidget {
), ),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
BrandCards.outlined( OutlinedCard(
child: ListTile( child: ListTile(
title: Text( title: Text(
'recovering.fallback_select_root_ssh'.tr(), 'recovering.fallback_select_root_ssh'.tr(),
@ -109,7 +109,7 @@ class RecoveryFallbackMethodSelect extends StatelessWidget {
), ),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
BrandCards.outlined( OutlinedCard(
child: ListTile( child: ListTile(
title: Text( title: Text(
'recovering.fallback_select_provider_console'.tr(), 'recovering.fallback_select_provider_console'.tr(),

View File

@ -130,7 +130,7 @@ class _UserLogins extends StatelessWidget {
final String domainName; final String domainName;
@override @override
Widget build(final BuildContext context) => BrandCards.filled( Widget build(final BuildContext context) => FilledCard(
child: Column( child: Column(
children: [ children: [
ListTile( ListTile(
@ -153,7 +153,7 @@ class _SshKeysCard extends StatelessWidget {
final User user; final User user;
@override @override
Widget build(final BuildContext context) => BrandCards.filled( Widget build(final BuildContext context) => FilledCard(
child: Column( child: Column(
children: [ children: [
ListTile( ListTile(

View File

@ -14,7 +14,7 @@ import 'package:selfprivacy/logic/models/hive/user.dart';
import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart'; import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart';
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart'; import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
import 'package:selfprivacy/ui/components/brand_button/outlined_button.dart'; import 'package:selfprivacy/ui/components/brand_button/outlined_button.dart';
import 'package:selfprivacy/ui/components/brand_cards/brand_cards.dart'; import 'package:selfprivacy/ui/components/brand_cards/filled_card.dart';
import 'package:selfprivacy/ui/components/brand_header/brand_header.dart'; import 'package:selfprivacy/ui/components/brand_header/brand_header.dart';
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart'; import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart'; import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart';