mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2024-09-06 03:56:56 +00:00
305 lines
12 KiB
Dart
305 lines
12 KiB
Dart
import 'package:easy_localization/easy_localization.dart';
|
|
import 'package:flutter/material.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({
|
|
required this.serverInstallationCubit,
|
|
super.key,
|
|
});
|
|
|
|
final ServerInstallationCubit serverInstallationCubit;
|
|
|
|
@override
|
|
State<ServerTypePicker> createState() => _ServerTypePickerState();
|
|
}
|
|
|
|
class _ServerTypePickerState extends State<ServerTypePicker> {
|
|
ServerProviderLocation? serverProviderLocation;
|
|
ServerType? serverType;
|
|
|
|
void setServerProviderLocation(final ServerProviderLocation? location) {
|
|
setState(() {
|
|
serverProviderLocation = location;
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(final BuildContext context) {
|
|
if (serverProviderLocation == null) {
|
|
return SelectLocationPage(
|
|
serverInstallationCubit: widget.serverInstallationCubit,
|
|
callback: setServerProviderLocation,
|
|
);
|
|
}
|
|
|
|
return SelectTypePage(
|
|
location: serverProviderLocation!,
|
|
serverInstallationCubit: widget.serverInstallationCubit,
|
|
backToLocationPickingCallback: () {
|
|
setServerProviderLocation(null);
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
class SelectLocationPage extends StatelessWidget {
|
|
const SelectLocationPage({
|
|
required this.serverInstallationCubit,
|
|
required this.callback,
|
|
super.key,
|
|
});
|
|
|
|
final Function callback;
|
|
final ServerInstallationCubit serverInstallationCubit;
|
|
|
|
@override
|
|
Widget build(final BuildContext context) => FutureBuilder(
|
|
future: serverInstallationCubit.fetchAvailableLocations(),
|
|
builder: (
|
|
final BuildContext context,
|
|
final AsyncSnapshot<Object?> snapshot,
|
|
) {
|
|
if (snapshot.hasData) {
|
|
if ((snapshot.data as List<ServerProviderLocation>).isEmpty) {
|
|
return Text('initializing.no_locations_found'.tr());
|
|
}
|
|
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) => 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,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
const SizedBox(height: 24),
|
|
],
|
|
);
|
|
} else {
|
|
return const Center(child: CircularProgressIndicator());
|
|
}
|
|
},
|
|
);
|
|
}
|
|
|
|
class SelectTypePage extends StatelessWidget {
|
|
const SelectTypePage({
|
|
required this.backToLocationPickingCallback,
|
|
required this.location,
|
|
required this.serverInstallationCubit,
|
|
super.key,
|
|
});
|
|
|
|
final ServerProviderLocation location;
|
|
final ServerInstallationCubit serverInstallationCubit;
|
|
final Function backToLocationPickingCallback;
|
|
|
|
@override
|
|
Widget build(final BuildContext context) => FutureBuilder(
|
|
future: serverInstallationCubit.fetchAvailableTypesByLocation(location),
|
|
builder: (
|
|
final BuildContext context,
|
|
final AsyncSnapshot<Object?> snapshot,
|
|
) {
|
|
if (snapshot.hasData) {
|
|
if ((snapshot.data as List<ServerType>).isEmpty) {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
'initializing.locations_not_found'.tr(),
|
|
style: Theme.of(context).textTheme.headlineSmall,
|
|
),
|
|
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();
|
|
},
|
|
text: 'initializing.back_to_locations'.tr(),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
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) => 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: 16),
|
|
InfoBox(text: 'initializing.choose_server_type_notice'.tr()),
|
|
],
|
|
);
|
|
} else {
|
|
return const Center(child: CircularProgressIndicator());
|
|
}
|
|
},
|
|
);
|
|
}
|