refactor(initializing): Refresh the server istallation UI
parent
040de69268
commit
b007fec75b
|
@ -0,0 +1,6 @@
|
|||
<svg width="24" height="25" viewBox="0 0 24 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12.0013 24.0128V19.3592C16.927 19.3592 20.7505 14.4743 18.8591 9.2901C18.1652 7.37152 16.6276 5.83395 14.709 5.14C9.52482 3.26224 4.63995 7.07217 4.63995 11.9979H0C0 4.14669 7.59264 -1.97641 15.8248 0.595295C19.417 1.72467 22.2881 4.58211 23.4038 8.17433C25.9755 16.4201 19.8661 24.0128 12.0013 24.0128Z" fill="white"/>
|
||||
<path d="M12.0149 19.3729H7.38855V14.7466H12.0149V19.3729Z" fill="white"/>
|
||||
<path d="M7.38861 22.9376H3.82361V19.3726H7.38861V22.9376Z" fill="white"/>
|
||||
<path d="M3.82354 19.373H0.843628V16.3931H3.82354V19.373Z" fill="white"/>
|
||||
</svg>
|
After Width: | Height: | Size: 657 B |
|
@ -0,0 +1,10 @@
|
|||
<svg width="24" height="23" viewBox="0 0 24 23" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_51804_9018)">
|
||||
<path d="M22.5704 0H19.3252C18.5948 0 18.2817 0.302609 18.2817 1.04348V9.25565H5.35304V1.04348C5.35304 0.313043 5.05044 0 4.30957 0H1.04348C0.302609 0 0 0.302609 0 1.04348V22.1739C0 22.9148 0.302609 23.2174 1.04348 23.2174H4.30957C5.04 23.2174 5.35304 22.9252 5.35304 22.1739V13.8261H18.2922V22.1739C18.2922 22.9043 18.5948 23.2174 19.3357 23.2174H22.5809C23.3113 23.2174 23.6243 22.9148 23.6243 22.1739V1.04348C23.6035 0.333913 23.3009 0 22.5704 0Z" fill="white"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_51804_9018">
|
||||
<rect width="24" height="22.9565" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 722 B |
File diff suppressed because it is too large
Load Diff
|
@ -90,7 +90,8 @@ class BackblazeApi extends ApiMap {
|
|||
),
|
||||
);
|
||||
if (response.statusCode == HttpStatus.ok) {
|
||||
isTokenValid = response.data['allowed']['capabilities'].contains('listBuckets');
|
||||
isTokenValid =
|
||||
response.data['allowed']['capabilities'].contains('listBuckets');
|
||||
} else if (response.statusCode == HttpStatus.unauthorized) {
|
||||
isTokenValid = false;
|
||||
} else {
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:material_color_utilities/material_color_utilities.dart'
|
||||
as color_utils;
|
||||
import 'package:selfprivacy/config/brand_colors.dart';
|
||||
import 'package:selfprivacy/config/hive_config.dart';
|
||||
import 'package:selfprivacy/theming/factory/app_theme_factory.dart';
|
||||
|
||||
export 'package:provider/provider.dart';
|
||||
|
||||
|
@ -20,7 +25,7 @@ class AppSettingsCubit extends Cubit<AppSettingsState> {
|
|||
|
||||
Box box = Hive.box(BNames.appSettingsBox);
|
||||
|
||||
void load() {
|
||||
void load() async {
|
||||
final bool? isDarkModeOn = box.get(BNames.isDarkModeOn);
|
||||
final bool? isOnboardingShowing = box.get(BNames.isOnboardingShowing);
|
||||
emit(
|
||||
|
@ -29,6 +34,14 @@ class AppSettingsCubit extends Cubit<AppSettingsState> {
|
|||
isOnboardingShowing: isOnboardingShowing,
|
||||
),
|
||||
);
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
final color_utils.CorePalette? colorPalette =
|
||||
await AppThemeFactory.getCorePalette();
|
||||
emit(
|
||||
state.copyWith(
|
||||
corePalette: colorPalette,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void updateDarkMode({required final bool isDarkModeOn}) {
|
||||
|
|
|
@ -4,20 +4,27 @@ class AppSettingsState extends Equatable {
|
|||
const AppSettingsState({
|
||||
required this.isDarkModeOn,
|
||||
required this.isOnboardingShowing,
|
||||
this.corePalette,
|
||||
});
|
||||
|
||||
final bool isDarkModeOn;
|
||||
final bool isOnboardingShowing;
|
||||
final color_utils.CorePalette? corePalette;
|
||||
|
||||
AppSettingsState copyWith({
|
||||
final bool? isDarkModeOn,
|
||||
final bool? isOnboardingShowing,
|
||||
final color_utils.CorePalette? corePalette,
|
||||
}) =>
|
||||
AppSettingsState(
|
||||
isDarkModeOn: isDarkModeOn ?? this.isDarkModeOn,
|
||||
isOnboardingShowing: isOnboardingShowing ?? this.isOnboardingShowing,
|
||||
corePalette: corePalette ?? this.corePalette,
|
||||
);
|
||||
|
||||
color_utils.CorePalette get corePaletteOrDefault =>
|
||||
corePalette ?? color_utils.CorePalette.of(BrandColors.primary.value);
|
||||
|
||||
@override
|
||||
List<Object> get props => [isDarkModeOn, isOnboardingShowing];
|
||||
List<dynamic> get props => [isDarkModeOn, isOnboardingShowing, corePalette];
|
||||
}
|
||||
|
|
|
@ -95,4 +95,15 @@ enum ServerProvider {
|
|||
return unknown;
|
||||
}
|
||||
}
|
||||
|
||||
String get displayName {
|
||||
switch (this) {
|
||||
case ServerProvider.hetzner:
|
||||
return 'Hetzner Cloud';
|
||||
case ServerProvider.digitalOcean:
|
||||
return 'Digital Ocean';
|
||||
default:
|
||||
return 'Unknown';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,8 +29,7 @@ abstract class AppThemeFactory {
|
|||
brightness: brightness,
|
||||
);
|
||||
|
||||
final ColorScheme colorScheme =
|
||||
dynamicColorsScheme ?? fallbackColorScheme;
|
||||
final ColorScheme colorScheme = dynamicColorsScheme ?? fallbackColorScheme;
|
||||
|
||||
final Typography appTypography = Typography.material2021();
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
|
|||
import 'package:selfprivacy/config/brand_colors.dart';
|
||||
import 'package:selfprivacy/config/text_themes.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_settings/app_settings_cubit.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
|
||||
|
||||
class ProgressBar extends StatefulWidget {
|
||||
const ProgressBar({
|
||||
|
@ -63,13 +62,6 @@ class _ProgressBarState extends State<ProgressBar> {
|
|||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
BrandText.h2('Progress'),
|
||||
const SizedBox(height: 10),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: even,
|
||||
),
|
||||
const SizedBox(height: 7),
|
||||
Container(
|
||||
alignment: Alignment.centerLeft,
|
||||
decoration: BoxDecoration(
|
||||
|
@ -98,11 +90,6 @@ class _ProgressBarState extends State<ProgressBar> {
|
|||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: odd,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_settings/app_settings_cubit.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
|
||||
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
|
||||
|
@ -49,11 +48,16 @@ class _OnboardingPageState extends State<OnboardingPage> {
|
|||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 30),
|
||||
BrandText.h2(
|
||||
Text(
|
||||
'onboarding.page1_title'.tr(),
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
BrandText.body2('onboarding.page1_text'.tr()),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'onboarding.page1_text'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Flexible(
|
||||
child: Center(
|
||||
child: Image.asset(
|
||||
|
@ -86,34 +90,49 @@ class _OnboardingPageState extends State<OnboardingPage> {
|
|||
maxHeight: MediaQuery.of(context).size.height,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 30),
|
||||
BrandText.h2('onboarding.page2_title'.tr()),
|
||||
const SizedBox(height: 20),
|
||||
BrandText.body2('onboarding.page2_text'.tr()),
|
||||
const SizedBox(height: 20),
|
||||
Center(
|
||||
child: Image.asset(
|
||||
_fileName(
|
||||
context: context,
|
||||
path: 'assets/images/onboarding',
|
||||
fileExtention: 'png',
|
||||
fileName: 'logos_line',
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'onboarding.page2_title'.tr(),
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
Flexible(
|
||||
child: Center(
|
||||
child: Image.asset(
|
||||
_fileName(
|
||||
context: context,
|
||||
path: 'assets/images/onboarding',
|
||||
fileExtention: 'png',
|
||||
fileName: 'onboarding2',
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'onboarding.page2_text'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'onboarding.page2_server_provider_title'.tr(),
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'onboarding.page2_server_provider_text'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'onboarding.page2_dns_provider_title'.tr(),
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'onboarding.page2_dns_provider_text'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'onboarding.page2_backup_provider_title'.tr(),
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'onboarding.page2_backup_provider_text'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
BrandButton.rised(
|
||||
onPressed: () {
|
||||
context.read<AppSettingsCubit>().turnOffOnboarding();
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import 'dart:ui';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:selfprivacy/config/brand_theme.dart';
|
||||
|
|
|
@ -11,7 +11,6 @@ import 'package:selfprivacy/logic/cubit/forms/setup/initializing/domain_setup_cu
|
|||
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/root_user_form_cubit.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_cards/brand_cards.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_md/brand_md.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_timer/brand_timer.dart';
|
||||
|
@ -56,88 +55,91 @@ class InitializingPage extends StatelessWidget {
|
|||
.pushReplacement(materialRoute(const RootPage()));
|
||||
}
|
||||
},
|
||||
child: SafeArea(
|
||||
child: Scaffold(
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Padding(
|
||||
padding: paddingH15V0.copyWith(top: 10, bottom: 10),
|
||||
child: cubit.state is ServerInstallationFinished
|
||||
? const SizedBox(
|
||||
height: 80,
|
||||
)
|
||||
: ProgressBar(
|
||||
steps: const [
|
||||
'Hosting',
|
||||
'Server Type',
|
||||
'CloudFlare',
|
||||
'Backblaze',
|
||||
'Domain',
|
||||
'User',
|
||||
'Server',
|
||||
'Installation',
|
||||
],
|
||||
activeIndex: cubit.state.porgressBar,
|
||||
),
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
actions: [
|
||||
if (cubit.state is ServerInstallationFinished)
|
||||
IconButton(
|
||||
icon: const Icon(Icons.check),
|
||||
onPressed: () {
|
||||
Navigator.of(context)
|
||||
.pushReplacement(materialRoute(const RootPage()));
|
||||
},
|
||||
)
|
||||
],
|
||||
bottom: PreferredSize(
|
||||
preferredSize: const Size.fromHeight(28),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
|
||||
child: ProgressBar(
|
||||
steps: const [
|
||||
'Hosting',
|
||||
'Server Type',
|
||||
'CloudFlare',
|
||||
'Backblaze',
|
||||
'Domain',
|
||||
'User',
|
||||
'Server',
|
||||
'Installation',
|
||||
],
|
||||
activeIndex: cubit.state.porgressBar,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16.0, 0, 16.0, 0.0),
|
||||
child: AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
child: actualInitializingPage,
|
||||
),
|
||||
if (cubit.state.porgressBar ==
|
||||
ServerSetupProgress.serverProviderFilled.index)
|
||||
BrandText.h2(
|
||||
'initializing.choose_location_type'.tr(),
|
||||
),
|
||||
_addCard(
|
||||
AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
child: actualInitializingPage,
|
||||
),
|
||||
),
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minHeight: MediaQuery.of(context).size.height -
|
||||
MediaQuery.of(context).padding.top -
|
||||
MediaQuery.of(context).padding.bottom -
|
||||
566,
|
||||
),
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
minHeight: MediaQuery.of(context).size.height -
|
||||
MediaQuery.of(context).padding.top -
|
||||
MediaQuery.of(context).padding.bottom -
|
||||
566,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
alignment: Alignment.center,
|
||||
child: BrandButton.text(
|
||||
title: cubit.state is ServerInstallationFinished
|
||||
? 'basis.close'.tr()
|
||||
: 'basis.later'.tr(),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pushAndRemoveUntil(
|
||||
materialRoute(const RootPage()),
|
||||
(final predicate) => false,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
if (cubit.state is ServerInstallationEmpty)
|
||||
Container(
|
||||
alignment: Alignment.center,
|
||||
child: BrandButton.text(
|
||||
title: cubit.state is ServerInstallationFinished
|
||||
? 'basis.close'.tr()
|
||||
: 'basis.later'.tr(),
|
||||
title: 'basis.connect_to_existing'.tr(),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pushAndRemoveUntil(
|
||||
materialRoute(const RootPage()),
|
||||
(final predicate) => false,
|
||||
Navigator.of(context).push(
|
||||
materialRoute(
|
||||
const RecoveryRouting(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
if (cubit.state is ServerInstallationFinished)
|
||||
Container()
|
||||
else
|
||||
Container(
|
||||
alignment: Alignment.center,
|
||||
child: BrandButton.text(
|
||||
title: 'basis.connect_to_existing'.tr(),
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(
|
||||
materialRoute(
|
||||
const RecoveryRouting(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -189,15 +191,16 @@ class InitializingPage extends StatelessWidget {
|
|||
builder: (final context) => Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/images/logos/cloudflare.png',
|
||||
width: 150,
|
||||
Text(
|
||||
'${'initializing.connect_to_server_provider'.tr()}Cloudflare',
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
BrandText.h2('initializing.connect_cloudflare'.tr()),
|
||||
const SizedBox(height: 10),
|
||||
BrandText.body2('initializing.manage_domain_dns'.tr()),
|
||||
const Spacer(),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'initializing.manage_domain_dns'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
CubitFormTextField(
|
||||
formFieldCubit: context.read<DnsProviderFormCubit>().apiKey,
|
||||
textAlign: TextAlign.center,
|
||||
|
@ -206,7 +209,7 @@ class InitializingPage extends StatelessWidget {
|
|||
hintText: 'initializing.cloudflare_api_token'.tr(),
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
const SizedBox(height: 32),
|
||||
BrandButton.rised(
|
||||
onPressed: () =>
|
||||
context.read<DnsProviderFormCubit>().trySubmit(),
|
||||
|
@ -236,14 +239,11 @@ class InitializingPage extends StatelessWidget {
|
|||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/images/logos/backblaze.png',
|
||||
height: 50,
|
||||
Text(
|
||||
'${'initializing.connect_to_server_provider'.tr()}Backblaze',
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
BrandText.h2('initializing.connect_backblaze_storage'.tr()),
|
||||
const SizedBox(height: 10),
|
||||
const Spacer(),
|
||||
const SizedBox(height: 32),
|
||||
CubitFormTextField(
|
||||
formFieldCubit: context.read<BackblazeFormCubit>().keyId,
|
||||
textAlign: TextAlign.center,
|
||||
|
@ -252,7 +252,7 @@ class InitializingPage extends StatelessWidget {
|
|||
hintText: 'KeyID',
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
const SizedBox(height: 16),
|
||||
CubitFormTextField(
|
||||
formFieldCubit:
|
||||
context.read<BackblazeFormCubit>().applicationKey,
|
||||
|
@ -262,7 +262,7 @@ class InitializingPage extends StatelessWidget {
|
|||
hintText: 'Master Application Key',
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
const SizedBox(height: 32),
|
||||
BrandButton.rised(
|
||||
onPressed: formCubitState.isSubmitting
|
||||
? null
|
||||
|
@ -292,91 +292,85 @@ class InitializingPage extends StatelessWidget {
|
|||
builder: (final context) {
|
||||
final DomainSetupState state =
|
||||
context.watch<DomainSetupCubit>().state;
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/images/logos/cloudflare.png',
|
||||
width: 150,
|
||||
),
|
||||
const SizedBox(height: 30),
|
||||
BrandText.h2('basis.domain'.tr()),
|
||||
const SizedBox(height: 10),
|
||||
if (state is Empty)
|
||||
BrandText.body2('initializing.no_connected_domains'.tr()),
|
||||
if (state is Loading)
|
||||
BrandText.body2(
|
||||
state.type == LoadingTypes.loadingDomain
|
||||
? 'initializing.loading_domain_list'.tr()
|
||||
: 'basis.saving'.tr(),
|
||||
return SizedBox(
|
||||
width: double.infinity,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'initializing.use_this_domain'.tr(),
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
if (state is MoreThenOne)
|
||||
BrandText.body2(
|
||||
'initializing.found_more_domains'.tr(),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'initializing.use_this_domain_text'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
if (state is Loaded) ...[
|
||||
const SizedBox(height: 10),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Expanded(
|
||||
child: BrandText.h3(
|
||||
const SizedBox(height: 32),
|
||||
if (state is Empty)
|
||||
Text(
|
||||
'initializing.no_connected_domains'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
if (state is Loading)
|
||||
Text(
|
||||
state.type == LoadingTypes.loadingDomain
|
||||
? 'initializing.loading_domain_list'.tr()
|
||||
: 'basis.saving'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
if (state is MoreThenOne)
|
||||
Text(
|
||||
'initializing.found_more_domains'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
if (state is Loaded) ...[
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
state.domain,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.headlineMedium
|
||||
?.copyWith(
|
||||
color:
|
||||
Theme.of(context).colorScheme.onBackground,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 56,
|
||||
child: BrandButton.rised(
|
||||
onPressed: () =>
|
||||
context.read<DomainSetupCubit>().load(),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: const [
|
||||
Icon(
|
||||
Icons.refresh,
|
||||
color: Colors.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
if (state is Empty) ...[
|
||||
const SizedBox(height: 30),
|
||||
BrandButton.rised(
|
||||
onPressed: () => context.read<DomainSetupCubit>().load(),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.refresh,
|
||||
color: Colors.white,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
BrandText.buttonTitleText('domain.update_list'.tr()),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
if (state is Empty) ...[
|
||||
const SizedBox(height: 30),
|
||||
BrandButton.rised(
|
||||
onPressed: () => context.read<DomainSetupCubit>().load(),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.refresh,
|
||||
color: Colors.white,
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
BrandText.buttonTitleText('domain.update_list'.tr()),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
if (state is Loaded) ...[
|
||||
const SizedBox(height: 32),
|
||||
BrandButton.rised(
|
||||
onPressed: () =>
|
||||
context.read<DomainSetupCubit>().saveDomain(),
|
||||
text: 'initializing.save_domain'.tr(),
|
||||
),
|
||||
],
|
||||
],
|
||||
if (state is Loaded) ...[
|
||||
const SizedBox(height: 30),
|
||||
BrandButton.rised(
|
||||
onPressed: () =>
|
||||
context.read<DomainSetupCubit>().saveDomain(),
|
||||
text: 'initializing.save_domain'.tr(),
|
||||
),
|
||||
],
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
width: double.infinity,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
@ -393,12 +387,16 @@ class InitializingPage extends StatelessWidget {
|
|||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
BrandText.h2('initializing.create_master_account'.tr()),
|
||||
const SizedBox(height: 10),
|
||||
BrandText.body2(
|
||||
'initializing.enter_username_and_password'.tr(),
|
||||
Text(
|
||||
'initializing.create_master_account'.tr(),
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
const Spacer(),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'initializing.enter_username_and_password'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
if (formCubitState.isErrorShown) const SizedBox(height: 16),
|
||||
if (formCubitState.isErrorShown)
|
||||
Text(
|
||||
'users.username_rule'.tr(),
|
||||
|
@ -406,7 +404,7 @@ class InitializingPage extends StatelessWidget {
|
|||
color: Theme.of(context).colorScheme.error,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
const SizedBox(height: 32),
|
||||
CubitFormTextField(
|
||||
formFieldCubit: context.read<RootUserFormCubit>().userName,
|
||||
textAlign: TextAlign.center,
|
||||
|
@ -415,7 +413,7 @@ class InitializingPage extends StatelessWidget {
|
|||
hintText: 'basis.username'.tr(),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
const SizedBox(height: 16),
|
||||
BlocBuilder<FieldCubit<bool>, FieldCubitState<bool>>(
|
||||
bloc: context.read<RootUserFormCubit>().isVisible,
|
||||
builder: (final context, final state) {
|
||||
|
@ -446,7 +444,7 @@ class InitializingPage extends StatelessWidget {
|
|||
);
|
||||
},
|
||||
),
|
||||
const Spacer(),
|
||||
const SizedBox(height: 32),
|
||||
BrandButton.rised(
|
||||
onPressed: formCubitState.isSubmitting
|
||||
? null
|
||||
|
@ -466,11 +464,16 @@ class InitializingPage extends StatelessWidget {
|
|||
builder: (final context) => Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Spacer(flex: 2),
|
||||
BrandText.h2('initializing.final'.tr()),
|
||||
const SizedBox(height: 10),
|
||||
BrandText.body2('initializing.create_server'.tr()),
|
||||
const Spacer(),
|
||||
Text(
|
||||
'initializing.final'.tr(),
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'initializing.create_server'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
const SizedBox(height: 128),
|
||||
BrandButton.rised(
|
||||
onPressed:
|
||||
isLoading ? null : appConfigCubit.createServerAndSetDnsRecords,
|
||||
|
@ -505,55 +508,64 @@ class InitializingPage extends StatelessWidget {
|
|||
doneCount = 0;
|
||||
}
|
||||
return Builder(
|
||||
builder: (final context) => Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 15),
|
||||
BrandText.h4(
|
||||
'initializing.checks'.tr(args: [doneCount.toString(), '4']),
|
||||
),
|
||||
const Spacer(flex: 2),
|
||||
const SizedBox(height: 10),
|
||||
BrandText.body2(text),
|
||||
const SizedBox(height: 10),
|
||||
if (doneCount == 0 && state.dnsMatches != null)
|
||||
Column(
|
||||
children: state.dnsMatches!.entries.map((final entry) {
|
||||
final String domain = entry.key;
|
||||
final bool isCorrect = entry.value;
|
||||
return Row(
|
||||
children: [
|
||||
if (isCorrect) const Icon(Icons.check, color: Colors.green),
|
||||
if (!isCorrect)
|
||||
const Icon(Icons.schedule, color: Colors.amber),
|
||||
const SizedBox(width: 10),
|
||||
Text(domain),
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
builder: (final context) => SizedBox(
|
||||
width: double.infinity,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'initializing.checks'.tr(args: [doneCount.toString(), '4']),
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
if (!state.isLoading)
|
||||
Row(
|
||||
children: [
|
||||
BrandText.body2('initializing.until_the_next_check'.tr()),
|
||||
BrandTimer(
|
||||
startDateTime: state.timerStart!,
|
||||
duration: state.duration!,
|
||||
)
|
||||
],
|
||||
),
|
||||
if (state.isLoading) BrandText.body2('initializing.check'.tr()),
|
||||
],
|
||||
const SizedBox(height: 16),
|
||||
if (text != null)
|
||||
Text(
|
||||
text,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
const SizedBox(height: 128),
|
||||
const SizedBox(height: 10),
|
||||
if (doneCount == 0 && state.dnsMatches != null)
|
||||
Column(
|
||||
children: state.dnsMatches!.entries.map((final entry) {
|
||||
final String domain = entry.key;
|
||||
final bool isCorrect = entry.value;
|
||||
return Row(
|
||||
children: [
|
||||
if (isCorrect)
|
||||
const Icon(Icons.check, color: Colors.green),
|
||||
if (!isCorrect)
|
||||
const Icon(Icons.schedule, color: Colors.amber),
|
||||
const SizedBox(width: 10),
|
||||
Text(domain),
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
if (!state.isLoading)
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'initializing.until_the_next_check'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
BrandTimer(
|
||||
startDateTime: state.timerStart!,
|
||||
duration: state.duration!,
|
||||
)
|
||||
],
|
||||
),
|
||||
if (state.isLoading)
|
||||
Text(
|
||||
'initializing.check'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _addCard(final Widget child) => Container(
|
||||
height: 450,
|
||||
padding: paddingH15V0,
|
||||
child: BrandCards.big(child: child),
|
||||
);
|
||||
}
|
||||
|
||||
class _HowTo extends StatelessWidget {
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
import 'package:cubit_form/cubit_form.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:selfprivacy/config/brand_theme.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/provider_form_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/hive/server_details.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_button/filled_button.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_button/outlined_button.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_cards/outlined_card.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_md/brand_md.dart';
|
||||
import 'package:selfprivacy/ui/components/info_box/info_box.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class ServerProviderPicker extends StatefulWidget {
|
||||
const ServerProviderPicker({
|
||||
|
@ -96,13 +101,16 @@ class ProviderInputDataPage extends StatelessWidget {
|
|||
Widget build(final BuildContext context) => Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
providerInfo.image,
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
'initializing.connect_to_server'.tr(),
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
"${'initializing.connect_to_server_provider'.tr()}${providerInfo.providerType.displayName}",
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
const Spacer(),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'initializing.connect_to_server_provider_text'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
CubitFormTextField(
|
||||
formFieldCubit: providerCubit.apiKey,
|
||||
textAlign: TextAlign.center,
|
||||
|
@ -111,13 +119,13 @@ class ProviderInputDataPage extends StatelessWidget {
|
|||
hintText: 'Provider API Token',
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
const SizedBox(height: 32),
|
||||
FilledButton(
|
||||
title: 'basis.connect'.tr(),
|
||||
onPressed: () => providerCubit.trySubmit(),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
OutlinedButton(
|
||||
BrandOutlinedButton(
|
||||
child: Text('initializing.how'.tr()),
|
||||
onPressed: () => showModalBottomSheet<void>(
|
||||
context: context,
|
||||
|
@ -154,51 +162,189 @@ class ProviderSelectionPage extends StatelessWidget {
|
|||
final ServerInstallationCubit serverInstallationCubit;
|
||||
|
||||
@override
|
||||
Widget build(final BuildContext context) => Column(
|
||||
children: [
|
||||
Text(
|
||||
'initializing.select_provider'.tr(),
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
'initializing.place_where_data'.tr(),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 320,
|
||||
Widget build(final BuildContext context) => SizedBox(
|
||||
width: double.infinity,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'initializing.connect_to_server'.tr(),
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
InkWell(
|
||||
onTap: () {
|
||||
serverInstallationCubit
|
||||
.setServerProviderType(ServerProvider.hetzner);
|
||||
callback(ServerProvider.hetzner);
|
||||
},
|
||||
child: Image.asset(
|
||||
'assets/images/logos/hetzner.png',
|
||||
width: 150,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 20,
|
||||
),
|
||||
InkWell(
|
||||
onTap: () {
|
||||
serverInstallationCubit
|
||||
.setServerProviderType(ServerProvider.digitalOcean);
|
||||
callback(ServerProvider.digitalOcean);
|
||||
},
|
||||
child: Image.asset(
|
||||
'assets/images/logos/digital_ocean.png',
|
||||
width: 150,
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
'initializing.select_provider'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 10),
|
||||
OutlinedCard(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
padding: const EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(40),
|
||||
color: const Color(0xFFD50C2D),
|
||||
),
|
||||
child: SvgPicture.asset(
|
||||
'assets/images/logos/hetzner.svg',
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Text(
|
||||
'Hetzner Cloud',
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'initializing.select_provider_countries_title'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
Text(
|
||||
'initializing.select_provider_countries_text_hetzner'
|
||||
.tr(),
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'initializing.select_provider_price_title'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
Text(
|
||||
'initializing.select_provider_price_text_hetzner'.tr(),
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'initializing.select_provider_payment_title'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
Text(
|
||||
'initializing.select_provider_payment_text_hetzner'.tr(),
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'initializing.select_provider_email_notice'.tr(),
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
FilledButton(
|
||||
title: 'basis.select'.tr(),
|
||||
onPressed: () {
|
||||
serverInstallationCubit
|
||||
.setServerProviderType(ServerProvider.hetzner);
|
||||
callback(ServerProvider.hetzner);
|
||||
},
|
||||
),
|
||||
// Outlined button that will open website
|
||||
BrandOutlinedButton(
|
||||
onPressed: () =>
|
||||
_launchURL('https://www.hetzner.com/cloud'),
|
||||
title: 'initializing.select_provider_site_button'.tr(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
OutlinedCard(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
padding: const EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(40),
|
||||
color: const Color(0xFF0080FF),
|
||||
),
|
||||
child: SvgPicture.asset(
|
||||
'assets/images/logos/digital_ocean.svg',
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Text(
|
||||
'Digital Ocean',
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'initializing.select_provider_countries_title'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
Text(
|
||||
'initializing.select_provider_countries_text_do'.tr(),
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'initializing.select_provider_price_title'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
Text(
|
||||
'initializing.select_provider_price_text_do'.tr(),
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'initializing.select_provider_payment_title'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
Text(
|
||||
'initializing.select_provider_payment_text_do'.tr(),
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
FilledButton(
|
||||
title: 'basis.select'.tr(),
|
||||
onPressed: () {
|
||||
serverInstallationCubit
|
||||
.setServerProviderType(ServerProvider.digitalOcean);
|
||||
callback(ServerProvider.digitalOcean);
|
||||
},
|
||||
),
|
||||
// Outlined button that will open website
|
||||
BrandOutlinedButton(
|
||||
onPressed: () =>
|
||||
_launchURL('https://www.digitalocean.com'),
|
||||
title: 'initializing.select_provider_site_button'.tr(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
InfoBox(text: 'initializing.select_provider_notice'.tr()),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _launchURL(final url) async {
|
||||
try {
|
||||
final Uri uri = Uri.parse(url);
|
||||
await launchUrl(
|
||||
uri,
|
||||
mode: LaunchMode.externalApplication,
|
||||
);
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/config/brand_theme.dart';
|
||||
import 'package:selfprivacy/illustrations/stray_deer.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_settings/app_settings_cubit.dart';
|
||||
import 'package:selfprivacy/logic/models/server_provider_location.dart';
|
||||
import 'package:selfprivacy/logic/models/server_type.dart';
|
||||
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
||||
import 'package:selfprivacy/ui/components/info_box/info_box.dart';
|
||||
|
||||
class ServerTypePicker extends StatefulWidget {
|
||||
const ServerTypePicker({
|
||||
|
@ -68,27 +70,43 @@ class SelectLocationPage extends StatelessWidget {
|
|||
if ((snapshot.data as List<ServerProviderLocation>).isEmpty) {
|
||||
return Text('initializing.no_locations_found'.tr());
|
||||
}
|
||||
return ListView(
|
||||
padding: paddingH15V0,
|
||||
return Column(
|
||||
children: [
|
||||
Text(
|
||||
'initializing.choose_location_type'.tr(),
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'initializing.choose_location_type_text'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
...(snapshot.data! as List<ServerProviderLocation>).map(
|
||||
(final location) => InkWell(
|
||||
onTap: () {
|
||||
callback(location);
|
||||
},
|
||||
child: Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (location.flag != null) Text(location.flag!),
|
||||
const SizedBox(height: 8),
|
||||
Text(location.title),
|
||||
const SizedBox(height: 8),
|
||||
if (location.description != null)
|
||||
Text(location.description!),
|
||||
],
|
||||
(final location) => SizedBox(
|
||||
width: double.infinity,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
callback(location);
|
||||
},
|
||||
child: Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'${location.flag ?? ''} ${location.title}',
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
if (location.description != null)
|
||||
Text(
|
||||
location.description!,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -126,11 +144,33 @@ class SelectTypePage extends StatelessWidget {
|
|||
if (snapshot.hasData) {
|
||||
if ((snapshot.data as List<ServerType>).isEmpty) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'initializing.no_server_types_found'.tr(),
|
||||
'initializing.locations_not_found'.tr(),
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'initializing.locations_not_found_text'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
LayoutBuilder(
|
||||
builder: (final context, final constraints) => CustomPaint(
|
||||
size: Size(
|
||||
constraints.maxWidth,
|
||||
(constraints.maxWidth * 1).toDouble(),
|
||||
),
|
||||
painter: StrayDeerPainter(
|
||||
colorScheme: Theme.of(context).colorScheme,
|
||||
colorPalette: context
|
||||
.read<AppSettingsCubit>()
|
||||
.state
|
||||
.corePaletteOrDefault,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
BrandButton.rised(
|
||||
onPressed: () {
|
||||
backToLocationPickingCallback();
|
||||
|
@ -140,51 +180,118 @@ class SelectTypePage extends StatelessWidget {
|
|||
],
|
||||
);
|
||||
}
|
||||
return ListView(
|
||||
padding: paddingH15V0,
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'initializing.choose_server_type'.tr(),
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'initializing.choose_server_type_text'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
...(snapshot.data! as List<ServerType>).map(
|
||||
(final type) => InkWell(
|
||||
onTap: () {
|
||||
serverInstallationCubit.setServerType(type);
|
||||
},
|
||||
child: Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
type.title,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'cores: ${type.cores.toString()}',
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'ram: ${type.ram.toString()}',
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'disk: ${type.disk.gibibyte.toString()}',
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'price: ${type.price.value.toString()} ${type.price.currency}',
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
),
|
||||
],
|
||||
(final type) => SizedBox(
|
||||
width: double.infinity,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
serverInstallationCubit.setServerType(type);
|
||||
},
|
||||
child: Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
type.title,
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.memory_outlined,
|
||||
color:
|
||||
Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
'server.core_count'.plural(type.cores),
|
||||
style:
|
||||
Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.memory_outlined,
|
||||
color:
|
||||
Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
'initializing.choose_server_type_ram'
|
||||
.tr(args: [type.ram.toString()]),
|
||||
style:
|
||||
Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.sd_card_outlined,
|
||||
color:
|
||||
Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
'initializing.choose_server_type_storage'
|
||||
.tr(args: [
|
||||
type.disk.gibibyte.toString()
|
||||
]),
|
||||
style:
|
||||
Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
const Divider(height: 8),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.payments_outlined,
|
||||
color:
|
||||
Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
'initializing.choose_server_type_payment_per_month'
|
||||
.tr(args: [
|
||||
'${type.price.value.toString()} ${type.price.currency}'
|
||||
]),
|
||||
style:
|
||||
Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
const SizedBox(height: 16),
|
||||
InfoBox(text: 'initializing.choose_server_type_notice'.tr()),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue