mirror of
https://git.selfprivacy.org/kherel/selfprivacy.org.app.git
synced 2025-01-08 17:11:14 +00:00
Merge pull request 'UI Refactor and move to auto_route' (#203) from ui-refactor into master
Reviewed-on: https://git.selfprivacy.org/kherel/selfprivacy.org.app/pulls/203 Reviewed-by: NaiJi ✨ <naiji@udongein.xyz>
This commit is contained in:
commit
e180c23cb7
|
@ -14,3 +14,6 @@ max_line_length = 150
|
||||||
|
|
||||||
[*.md]
|
[*.md]
|
||||||
trim_trailing_whitespace = false
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
|
[*.json]
|
||||||
|
indent_size = 4
|
||||||
|
|
|
@ -29,16 +29,16 @@ linter:
|
||||||
# producing the lint.
|
# producing the lint.
|
||||||
rules:
|
rules:
|
||||||
avoid_print: false # Uncomment to disable the `avoid_print` rule
|
avoid_print: false # Uncomment to disable the `avoid_print` rule
|
||||||
prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
|
||||||
always_use_package_imports: true
|
|
||||||
no_adjacent_strings_in_list: true
|
|
||||||
unnecessary_statements: true
|
|
||||||
always_declare_return_types: true
|
always_declare_return_types: true
|
||||||
always_put_required_named_parameters_first: true
|
|
||||||
always_put_control_body_on_new_line: true
|
always_put_control_body_on_new_line: true
|
||||||
|
always_put_required_named_parameters_first: true
|
||||||
|
always_use_package_imports: true
|
||||||
avoid_escaping_inner_quotes: true
|
avoid_escaping_inner_quotes: true
|
||||||
avoid_setters_without_getters: true
|
avoid_setters_without_getters: true
|
||||||
|
collection_methods_unrelated_type: true
|
||||||
|
combinators_ordering: true
|
||||||
eol_at_end_of_file: true
|
eol_at_end_of_file: true
|
||||||
|
no_adjacent_strings_in_list: true
|
||||||
prefer_constructors_over_static_methods: true
|
prefer_constructors_over_static_methods: true
|
||||||
prefer_expression_function_bodies: true
|
prefer_expression_function_bodies: true
|
||||||
prefer_final_in_for_each: true
|
prefer_final_in_for_each: true
|
||||||
|
@ -48,12 +48,18 @@ linter:
|
||||||
prefer_if_elements_to_conditional_expressions: true
|
prefer_if_elements_to_conditional_expressions: true
|
||||||
prefer_mixin: true
|
prefer_mixin: true
|
||||||
prefer_null_aware_method_calls: true
|
prefer_null_aware_method_calls: true
|
||||||
|
prefer_single_quotes: true
|
||||||
require_trailing_commas: true
|
require_trailing_commas: true
|
||||||
sized_box_shrink_expand: true
|
sized_box_shrink_expand: true
|
||||||
sort_constructors_first: true
|
sort_constructors_first: true
|
||||||
|
unawaited_futures: true
|
||||||
unnecessary_await_in_return: true
|
unnecessary_await_in_return: true
|
||||||
|
unnecessary_null_aware_operator_on_extension_on_nullable: true
|
||||||
unnecessary_null_checks: true
|
unnecessary_null_checks: true
|
||||||
unnecessary_parenthesis: true
|
unnecessary_parenthesis: true
|
||||||
|
unnecessary_statements: true
|
||||||
|
unnecessary_to_list_in_spreads: true
|
||||||
|
unreachable_from_main: true
|
||||||
use_enums: true
|
use_enums: true
|
||||||
use_if_null_to_convert_nulls_to_bools: true
|
use_if_null_to_convert_nulls_to_bools: true
|
||||||
use_is_even_rather_than_modulo: true
|
use_is_even_rather_than_modulo: true
|
||||||
|
@ -61,6 +67,7 @@ linter:
|
||||||
use_named_constants: true
|
use_named_constants: true
|
||||||
use_setters_to_change_properties: true
|
use_setters_to_change_properties: true
|
||||||
use_string_buffers: true
|
use_string_buffers: true
|
||||||
|
use_string_in_part_of_directives: true
|
||||||
use_super_parameters: true
|
use_super_parameters: true
|
||||||
use_to_and_as_if_applicable: true
|
use_to_and_as_if_applicable: true
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
"test": "en-test",
|
"test": "en-test",
|
||||||
"locale": "en",
|
"locale": "en",
|
||||||
"basis": {
|
"basis": {
|
||||||
|
"app_name": "SelfPrivacy",
|
||||||
"providers": "Providers",
|
"providers": "Providers",
|
||||||
"providers_title": "Your Data Center",
|
"providers_title": "Your Data Center",
|
||||||
"select": "Select",
|
"select": "Select",
|
||||||
|
@ -46,7 +47,8 @@
|
||||||
},
|
},
|
||||||
"console_page": {
|
"console_page": {
|
||||||
"title": "Console",
|
"title": "Console",
|
||||||
"waiting": "Waiting for initialization…"
|
"waiting": "Waiting for initialization…",
|
||||||
|
"copy": "Copy"
|
||||||
},
|
},
|
||||||
"about_us_page": {
|
"about_us_page": {
|
||||||
"title": "About us"
|
"title": "About us"
|
||||||
|
@ -59,8 +61,11 @@
|
||||||
},
|
},
|
||||||
"application_settings": {
|
"application_settings": {
|
||||||
"title": "Application settings",
|
"title": "Application settings",
|
||||||
|
"system_dark_theme_title": "System default theme",
|
||||||
|
"system_dark_theme_description": "Use light or dark theme depending on system settings",
|
||||||
"dark_theme_title": "Dark theme",
|
"dark_theme_title": "Dark theme",
|
||||||
"dark_theme_description": "Switch your application theme",
|
"dark_theme_description": "Switch your application theme",
|
||||||
|
"dangerous_settings": "Dangerous settings",
|
||||||
"reset_config_title": "Reset application config",
|
"reset_config_title": "Reset application config",
|
||||||
"reset_config_description": "Reset api keys and root user",
|
"reset_config_description": "Reset api keys and root user",
|
||||||
"delete_server_title": "Delete server",
|
"delete_server_title": "Delete server",
|
||||||
|
@ -251,6 +256,7 @@
|
||||||
"subtitle": "Private VPN server"
|
"subtitle": "Private VPN server"
|
||||||
},
|
},
|
||||||
"users": {
|
"users": {
|
||||||
|
"details_title": "User details",
|
||||||
"add_new_user": "Add a first user",
|
"add_new_user": "Add a first user",
|
||||||
"new_user": "New user",
|
"new_user": "New user",
|
||||||
"delete_user": "Delete user",
|
"delete_user": "Delete user",
|
||||||
|
@ -329,7 +335,20 @@
|
||||||
"create_master_account": "Create master account",
|
"create_master_account": "Create master account",
|
||||||
"enter_username_and_password": "Enter username and strong password",
|
"enter_username_and_password": "Enter username and strong password",
|
||||||
"finish": "Everything is initialized",
|
"finish": "Everything is initialized",
|
||||||
"checks": "Checks have been completed \n{} out of {}"
|
"checks": "Checks have been completed \n{} out of {}",
|
||||||
|
"steps": {
|
||||||
|
"hosting": "Hosting",
|
||||||
|
"server_type": "Server type",
|
||||||
|
"dns_provider": "DNS provider",
|
||||||
|
"backups_provider": "Backups",
|
||||||
|
"domain": "Domain",
|
||||||
|
"master_account": "Master account",
|
||||||
|
"server": "Server",
|
||||||
|
"dns_setup": "DNS setup",
|
||||||
|
"nixos_installation": "NixOS installation",
|
||||||
|
"server_reboot": "Server reboot",
|
||||||
|
"final_checks": "Final checks"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"recovering": {
|
"recovering": {
|
||||||
"generic_error": "Operation failed, please try again.",
|
"generic_error": "Operation failed, please try again.",
|
||||||
|
@ -472,5 +491,19 @@
|
||||||
"root_name": "Cannot be 'root'",
|
"root_name": "Cannot be 'root'",
|
||||||
"length_not_equal": "Length is [], should be {}",
|
"length_not_equal": "Length is [], should be {}",
|
||||||
"length_longer": "Length is [], should be shorter than or equal to {}"
|
"length_longer": "Length is [], should be shorter than or equal to {}"
|
||||||
|
},
|
||||||
|
"support": {
|
||||||
|
"title": "SelfPrivacy Support"
|
||||||
|
},
|
||||||
|
"developer_settings": {
|
||||||
|
"title": "Developer settings",
|
||||||
|
"subtitle": "These settings are for debugging only. Don't change them unless you know what you're doing.",
|
||||||
|
"server_setup": "Server setup",
|
||||||
|
"use_staging_acme": "Use staging ACME server",
|
||||||
|
"use_staging_acme_description": "Rebuild your app to change this value.",
|
||||||
|
"routing": "App routing",
|
||||||
|
"reset_onboarding": "Reset onboarding switch",
|
||||||
|
"reset_onboarding_description": "Reset onboarding switch to show onboarding screen again",
|
||||||
|
"cubit_statuses": "Cubit loading statuses"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import 'package:selfprivacy/logic/cubit/providers/providers_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_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/logic/cubit/support_system/support_system_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/users/users_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/users/users_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/provider_volumes/provider_volume_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/provider_volumes/provider_volume_cubit.dart';
|
||||||
|
|
||||||
|
@ -23,7 +24,9 @@ class BlocAndProviderConfig extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(final BuildContext context) {
|
Widget build(final BuildContext context) {
|
||||||
const isDark = false;
|
const isDark = false;
|
||||||
|
const isAutoDark = true;
|
||||||
final serverInstallationCubit = ServerInstallationCubit()..load();
|
final serverInstallationCubit = ServerInstallationCubit()..load();
|
||||||
|
final supportSystemCubit = SupportSystemCubit();
|
||||||
final usersCubit = UsersCubit(serverInstallationCubit);
|
final usersCubit = UsersCubit(serverInstallationCubit);
|
||||||
final servicesCubit = ServicesCubit(serverInstallationCubit);
|
final servicesCubit = ServicesCubit(serverInstallationCubit);
|
||||||
final backupsCubit = BackupsCubit(serverInstallationCubit);
|
final backupsCubit = BackupsCubit(serverInstallationCubit);
|
||||||
|
@ -41,9 +44,13 @@ class BlocAndProviderConfig extends StatelessWidget {
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (final _) => AppSettingsCubit(
|
create: (final _) => AppSettingsCubit(
|
||||||
isDarkModeOn: isDark,
|
isDarkModeOn: isDark,
|
||||||
|
isAutoDarkModeOn: isAutoDark,
|
||||||
isOnboardingShowing: true,
|
isOnboardingShowing: true,
|
||||||
)..load(),
|
)..load(),
|
||||||
),
|
),
|
||||||
|
BlocProvider(
|
||||||
|
create: (final _) => supportSystemCubit,
|
||||||
|
),
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (final _) => serverInstallationCubit,
|
create: (final _) => serverInstallationCubit,
|
||||||
lazy: false,
|
lazy: false,
|
||||||
|
|
|
@ -2,53 +2,16 @@ import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class BrandColors {
|
class BrandColors {
|
||||||
static const Color blue = Color(0xFF093CEF);
|
static const Color blue = Color(0xFF093CEF);
|
||||||
static const Color white = Colors.white;
|
|
||||||
static const Color black = Colors.black;
|
|
||||||
|
|
||||||
static const Color gray1 = Color(0xFF555555);
|
|
||||||
static const Color gray2 = Color(0xFF7C7C7C);
|
|
||||||
static const Color gray3 = Color(0xFFFAFAFA);
|
|
||||||
static const Color gray4 = Color(0xFFDDDDDD);
|
|
||||||
static const Color gray5 = Color(0xFFEDEEF1);
|
|
||||||
static Color gray6 = const Color(0xFF181818).withOpacity(0.7);
|
|
||||||
static const Color grey7 = Color(0xFFABABAB);
|
|
||||||
|
|
||||||
static const Color red1 = Color(0xFFFA0E0E);
|
|
||||||
static const Color red2 = Color(0xFFE65527);
|
|
||||||
|
|
||||||
static const Color green1 = Color(0xFF00AF54);
|
|
||||||
|
|
||||||
static const Color green2 = Color(0xFF0F8849);
|
|
||||||
|
|
||||||
static Color get navBackgroundLight => white.withOpacity(0.8);
|
|
||||||
static Color get navBackgroundDark => black.withOpacity(0.8);
|
|
||||||
|
|
||||||
static const List<Color> uninitializedGradientColors = [
|
static const List<Color> uninitializedGradientColors = [
|
||||||
Color(0xFF555555),
|
Color(0xFF555555),
|
||||||
Color(0xFFABABAB),
|
Color(0xFFABABAB),
|
||||||
];
|
];
|
||||||
static const List<Color> stableGradientColors = [
|
|
||||||
Color(0xFF093CEF),
|
|
||||||
Color(0xFF14A1CB),
|
|
||||||
];
|
|
||||||
|
|
||||||
static const List<Color> progressGradientColors = [
|
|
||||||
Color(0xFF093CEF),
|
|
||||||
Color(0xFF14A1CB),
|
|
||||||
];
|
|
||||||
static const List<Color> warningGradientColors = [
|
static const List<Color> warningGradientColors = [
|
||||||
Color(0xFFEF4E09),
|
Color(0xFFEF4E09),
|
||||||
Color(0xFFEFD135),
|
Color(0xFFEFD135),
|
||||||
];
|
];
|
||||||
|
|
||||||
static const Color primary = blue;
|
static const Color primary = blue;
|
||||||
static const Color headlineColor = black;
|
|
||||||
static const Color inactive = gray2;
|
|
||||||
static const Color scaffoldBackground = gray3;
|
|
||||||
static const Color inputInactive = gray4;
|
|
||||||
|
|
||||||
static const Color textColor1 = black;
|
|
||||||
static const Color textColor2 = gray1;
|
|
||||||
static const Color dividerColor = gray5;
|
|
||||||
static const Color warning = red1;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,9 @@ class BNames {
|
||||||
/// A boolean field of [appSettingsBox] box.
|
/// A boolean field of [appSettingsBox] box.
|
||||||
static String isDarkModeOn = 'isDarkModeOn';
|
static String isDarkModeOn = 'isDarkModeOn';
|
||||||
|
|
||||||
|
/// A boolean field of [appSettingsBox] box.
|
||||||
|
static String isAutoDarkModeOn = 'isAutoDarkModeOn';
|
||||||
|
|
||||||
/// A boolean field of [appSettingsBox] box.
|
/// A boolean field of [appSettingsBox] box.
|
||||||
static String isOnboardingShowing = 'isOnboardingShowing';
|
static String isOnboardingShowing = 'isOnboardingShowing';
|
||||||
|
|
||||||
|
|
|
@ -1,80 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:selfprivacy/utils/named_font_weight.dart';
|
|
||||||
|
|
||||||
import 'package:selfprivacy/config/brand_colors.dart';
|
|
||||||
|
|
||||||
const TextStyle defaultTextStyle = TextStyle(
|
|
||||||
fontSize: 15,
|
|
||||||
color: BrandColors.textColor1,
|
|
||||||
);
|
|
||||||
|
|
||||||
final TextStyle headline1Style = defaultTextStyle.copyWith(
|
|
||||||
fontSize: 40,
|
|
||||||
fontWeight: NamedFontWeight.extraBold,
|
|
||||||
color: BrandColors.headlineColor,
|
|
||||||
);
|
|
||||||
|
|
||||||
final TextStyle headline2Style = defaultTextStyle.copyWith(
|
|
||||||
fontSize: 24,
|
|
||||||
fontWeight: NamedFontWeight.extraBold,
|
|
||||||
color: BrandColors.headlineColor,
|
|
||||||
);
|
|
||||||
|
|
||||||
final TextStyle onboardingTitle = defaultTextStyle.copyWith(
|
|
||||||
fontSize: 30,
|
|
||||||
fontWeight: NamedFontWeight.extraBold,
|
|
||||||
color: BrandColors.headlineColor,
|
|
||||||
);
|
|
||||||
|
|
||||||
final TextStyle headline3Style = defaultTextStyle.copyWith(
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: NamedFontWeight.extraBold,
|
|
||||||
color: BrandColors.headlineColor,
|
|
||||||
);
|
|
||||||
|
|
||||||
final TextStyle headline4Style = defaultTextStyle.copyWith(
|
|
||||||
fontSize: 18,
|
|
||||||
fontWeight: NamedFontWeight.medium,
|
|
||||||
color: BrandColors.headlineColor,
|
|
||||||
);
|
|
||||||
|
|
||||||
final TextStyle headline4UnderlinedStyle = defaultTextStyle.copyWith(
|
|
||||||
fontSize: 18,
|
|
||||||
fontWeight: NamedFontWeight.medium,
|
|
||||||
color: BrandColors.headlineColor,
|
|
||||||
decoration: TextDecoration.underline,
|
|
||||||
);
|
|
||||||
|
|
||||||
final TextStyle headline5Style = defaultTextStyle.copyWith(
|
|
||||||
fontSize: 15,
|
|
||||||
fontWeight: NamedFontWeight.medium,
|
|
||||||
color: BrandColors.headlineColor.withOpacity(0.8),
|
|
||||||
);
|
|
||||||
|
|
||||||
const TextStyle body1Style = defaultTextStyle;
|
|
||||||
final TextStyle body2Style = defaultTextStyle.copyWith(
|
|
||||||
color: BrandColors.textColor2,
|
|
||||||
);
|
|
||||||
|
|
||||||
final TextStyle buttonTitleText = defaultTextStyle.copyWith(
|
|
||||||
color: BrandColors.white,
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
height: 1,
|
|
||||||
);
|
|
||||||
|
|
||||||
final TextStyle mediumStyle =
|
|
||||||
defaultTextStyle.copyWith(fontSize: 13, height: 1.53);
|
|
||||||
|
|
||||||
final TextStyle smallStyle =
|
|
||||||
defaultTextStyle.copyWith(fontSize: 11, height: 1.45);
|
|
||||||
|
|
||||||
const TextStyle progressTextStyleLight = TextStyle(
|
|
||||||
fontSize: 11,
|
|
||||||
color: BrandColors.textColor1,
|
|
||||||
height: 1.7,
|
|
||||||
);
|
|
||||||
|
|
||||||
final TextStyle progressTextStyleDark = progressTextStyleLight.copyWith(
|
|
||||||
color: BrandColors.white,
|
|
||||||
);
|
|
|
@ -20,7 +20,13 @@ class RequestLoggingLink extends Link {
|
||||||
final Request request, [
|
final Request request, [
|
||||||
final NextLink? forward,
|
final NextLink? forward,
|
||||||
]) async* {
|
]) async* {
|
||||||
_logToAppConsole(request);
|
getIt.get<ConsoleModel>().addMessage(
|
||||||
|
GraphQlRequestMessage(
|
||||||
|
operation: request.operation,
|
||||||
|
variables: request.variables,
|
||||||
|
context: request.context,
|
||||||
|
),
|
||||||
|
);
|
||||||
yield* forward!(request);
|
yield* forward!(request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +35,13 @@ class ResponseLoggingParser extends ResponseParser {
|
||||||
@override
|
@override
|
||||||
Response parseResponse(final Map<String, dynamic> body) {
|
Response parseResponse(final Map<String, dynamic> body) {
|
||||||
final response = super.parseResponse(body);
|
final response = super.parseResponse(body);
|
||||||
_logToAppConsole(response);
|
getIt.get<ConsoleModel>().addMessage(
|
||||||
|
GraphQlResponseMessage(
|
||||||
|
data: response.data,
|
||||||
|
errors: response.errors,
|
||||||
|
context: response.context,
|
||||||
|
),
|
||||||
|
);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,376 +0,0 @@
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
|
||||||
|
|
||||||
part of 'disk_volumes.graphql.dart';
|
|
||||||
|
|
||||||
// **************************************************************************
|
|
||||||
// JsonSerializableGenerator
|
|
||||||
// **************************************************************************
|
|
||||||
|
|
||||||
Fragment$basicMutationReturnFields _$Fragment$basicMutationReturnFieldsFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Fragment$basicMutationReturnFields(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Fragment$basicMutationReturnFieldsToJson(
|
|
||||||
Fragment$basicMutationReturnFields instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$GetServerDiskVolumes _$Query$GetServerDiskVolumesFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$GetServerDiskVolumes(
|
|
||||||
storage: Query$GetServerDiskVolumes$storage.fromJson(
|
|
||||||
json['storage'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$GetServerDiskVolumesToJson(
|
|
||||||
Query$GetServerDiskVolumes instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'storage': instance.storage.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$GetServerDiskVolumes$storage _$Query$GetServerDiskVolumes$storageFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$GetServerDiskVolumes$storage(
|
|
||||||
volumes: (json['volumes'] as List<dynamic>)
|
|
||||||
.map((e) => Query$GetServerDiskVolumes$storage$volumes.fromJson(
|
|
||||||
e as Map<String, dynamic>))
|
|
||||||
.toList(),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$GetServerDiskVolumes$storageToJson(
|
|
||||||
Query$GetServerDiskVolumes$storage instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'volumes': instance.volumes.map((e) => e.toJson()).toList(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$GetServerDiskVolumes$storage$volumes
|
|
||||||
_$Query$GetServerDiskVolumes$storage$volumesFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$GetServerDiskVolumes$storage$volumes(
|
|
||||||
freeSpace: json['freeSpace'] as String,
|
|
||||||
model: json['model'] as String?,
|
|
||||||
name: json['name'] as String,
|
|
||||||
root: json['root'] as bool,
|
|
||||||
serial: json['serial'] as String?,
|
|
||||||
totalSpace: json['totalSpace'] as String,
|
|
||||||
type: json['type'] as String,
|
|
||||||
usages: (json['usages'] as List<dynamic>)
|
|
||||||
.map((e) =>
|
|
||||||
Query$GetServerDiskVolumes$storage$volumes$usages.fromJson(
|
|
||||||
e as Map<String, dynamic>))
|
|
||||||
.toList(),
|
|
||||||
usedSpace: json['usedSpace'] as String,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$GetServerDiskVolumes$storage$volumesToJson(
|
|
||||||
Query$GetServerDiskVolumes$storage$volumes instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'freeSpace': instance.freeSpace,
|
|
||||||
'model': instance.model,
|
|
||||||
'name': instance.name,
|
|
||||||
'root': instance.root,
|
|
||||||
'serial': instance.serial,
|
|
||||||
'totalSpace': instance.totalSpace,
|
|
||||||
'type': instance.type,
|
|
||||||
'usages': instance.usages.map((e) => e.toJson()).toList(),
|
|
||||||
'usedSpace': instance.usedSpace,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$GetServerDiskVolumes$storage$volumes$usages
|
|
||||||
_$Query$GetServerDiskVolumes$storage$volumes$usagesFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$GetServerDiskVolumes$storage$volumes$usages(
|
|
||||||
title: json['title'] as String,
|
|
||||||
usedSpace: json['usedSpace'] as String,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$GetServerDiskVolumes$storage$volumes$usagesToJson(
|
|
||||||
Query$GetServerDiskVolumes$storage$volumes$usages instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'title': instance.title,
|
|
||||||
'usedSpace': instance.usedSpace,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$GetServerDiskVolumes$storage$volumes$usages$$ServiceStorageUsage
|
|
||||||
_$Query$GetServerDiskVolumes$storage$volumes$usages$$ServiceStorageUsageFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$GetServerDiskVolumes$storage$volumes$usages$$ServiceStorageUsage(
|
|
||||||
title: json['title'] as String,
|
|
||||||
usedSpace: json['usedSpace'] as String,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
service: json['service'] == null
|
|
||||||
? null
|
|
||||||
: Query$GetServerDiskVolumes$storage$volumes$usages$$ServiceStorageUsage$service
|
|
||||||
.fromJson(json['service'] as Map<String, dynamic>),
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic>
|
|
||||||
_$Query$GetServerDiskVolumes$storage$volumes$usages$$ServiceStorageUsageToJson(
|
|
||||||
Query$GetServerDiskVolumes$storage$volumes$usages$$ServiceStorageUsage
|
|
||||||
instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'title': instance.title,
|
|
||||||
'usedSpace': instance.usedSpace,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
'service': instance.service?.toJson(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$GetServerDiskVolumes$storage$volumes$usages$$ServiceStorageUsage$service
|
|
||||||
_$Query$GetServerDiskVolumes$storage$volumes$usages$$ServiceStorageUsage$serviceFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$GetServerDiskVolumes$storage$volumes$usages$$ServiceStorageUsage$service(
|
|
||||||
id: json['id'] as String,
|
|
||||||
isMovable: json['isMovable'] as bool,
|
|
||||||
displayName: json['displayName'] as String,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic>
|
|
||||||
_$Query$GetServerDiskVolumes$storage$volumes$usages$$ServiceStorageUsage$serviceToJson(
|
|
||||||
Query$GetServerDiskVolumes$storage$volumes$usages$$ServiceStorageUsage$service
|
|
||||||
instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'id': instance.id,
|
|
||||||
'isMovable': instance.isMovable,
|
|
||||||
'displayName': instance.displayName,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Variables$Mutation$MountVolume _$Variables$Mutation$MountVolumeFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Variables$Mutation$MountVolume(
|
|
||||||
name: json['name'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Variables$Mutation$MountVolumeToJson(
|
|
||||||
Variables$Mutation$MountVolume instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'name': instance.name,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$MountVolume _$Mutation$MountVolumeFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$MountVolume(
|
|
||||||
mountVolume: Mutation$MountVolume$mountVolume.fromJson(
|
|
||||||
json['mountVolume'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$MountVolumeToJson(
|
|
||||||
Mutation$MountVolume instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'mountVolume': instance.mountVolume.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$MountVolume$mountVolume _$Mutation$MountVolume$mountVolumeFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$MountVolume$mountVolume(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$MountVolume$mountVolumeToJson(
|
|
||||||
Mutation$MountVolume$mountVolume instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Variables$Mutation$ResizeVolume _$Variables$Mutation$ResizeVolumeFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Variables$Mutation$ResizeVolume(
|
|
||||||
name: json['name'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Variables$Mutation$ResizeVolumeToJson(
|
|
||||||
Variables$Mutation$ResizeVolume instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'name': instance.name,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$ResizeVolume _$Mutation$ResizeVolumeFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$ResizeVolume(
|
|
||||||
resizeVolume: Mutation$ResizeVolume$resizeVolume.fromJson(
|
|
||||||
json['resizeVolume'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$ResizeVolumeToJson(
|
|
||||||
Mutation$ResizeVolume instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'resizeVolume': instance.resizeVolume.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$ResizeVolume$resizeVolume _$Mutation$ResizeVolume$resizeVolumeFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$ResizeVolume$resizeVolume(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$ResizeVolume$resizeVolumeToJson(
|
|
||||||
Mutation$ResizeVolume$resizeVolume instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Variables$Mutation$UnmountVolume _$Variables$Mutation$UnmountVolumeFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Variables$Mutation$UnmountVolume(
|
|
||||||
name: json['name'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Variables$Mutation$UnmountVolumeToJson(
|
|
||||||
Variables$Mutation$UnmountVolume instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'name': instance.name,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$UnmountVolume _$Mutation$UnmountVolumeFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$UnmountVolume(
|
|
||||||
unmountVolume: Mutation$UnmountVolume$unmountVolume.fromJson(
|
|
||||||
json['unmountVolume'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$UnmountVolumeToJson(
|
|
||||||
Mutation$UnmountVolume instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'unmountVolume': instance.unmountVolume.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$UnmountVolume$unmountVolume
|
|
||||||
_$Mutation$UnmountVolume$unmountVolumeFromJson(Map<String, dynamic> json) =>
|
|
||||||
Mutation$UnmountVolume$unmountVolume(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$UnmountVolume$unmountVolumeToJson(
|
|
||||||
Mutation$UnmountVolume$unmountVolume instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Variables$Mutation$MigrateToBinds _$Variables$Mutation$MigrateToBindsFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Variables$Mutation$MigrateToBinds(
|
|
||||||
input: Input$MigrateToBindsInput.fromJson(
|
|
||||||
json['input'] as Map<String, dynamic>),
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Variables$Mutation$MigrateToBindsToJson(
|
|
||||||
Variables$Mutation$MigrateToBinds instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'input': instance.input.toJson(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$MigrateToBinds _$Mutation$MigrateToBindsFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$MigrateToBinds(
|
|
||||||
migrateToBinds: Mutation$MigrateToBinds$migrateToBinds.fromJson(
|
|
||||||
json['migrateToBinds'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$MigrateToBindsToJson(
|
|
||||||
Mutation$MigrateToBinds instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'migrateToBinds': instance.migrateToBinds.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$MigrateToBinds$migrateToBinds
|
|
||||||
_$Mutation$MigrateToBinds$migrateToBindsFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$MigrateToBinds$migrateToBinds(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
job: json['job'] == null
|
|
||||||
? null
|
|
||||||
: Mutation$MigrateToBinds$migrateToBinds$job.fromJson(
|
|
||||||
json['job'] as Map<String, dynamic>),
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$MigrateToBinds$migrateToBindsToJson(
|
|
||||||
Mutation$MigrateToBinds$migrateToBinds instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
'job': instance.job?.toJson(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$MigrateToBinds$migrateToBinds$job
|
|
||||||
_$Mutation$MigrateToBinds$migrateToBinds$jobFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$MigrateToBinds$migrateToBinds$job(
|
|
||||||
createdAt: dateTimeFromJson(json['createdAt']),
|
|
||||||
description: json['description'] as String,
|
|
||||||
error: json['error'] as String?,
|
|
||||||
finishedAt: _nullable$dateTimeFromJson(json['finishedAt']),
|
|
||||||
name: json['name'] as String,
|
|
||||||
progress: json['progress'] as int?,
|
|
||||||
result: json['result'] as String?,
|
|
||||||
status: json['status'] as String,
|
|
||||||
statusText: json['statusText'] as String?,
|
|
||||||
uid: json['uid'] as String,
|
|
||||||
updatedAt: dateTimeFromJson(json['updatedAt']),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$MigrateToBinds$migrateToBinds$jobToJson(
|
|
||||||
Mutation$MigrateToBinds$migrateToBinds$job instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'createdAt': dateTimeToJson(instance.createdAt),
|
|
||||||
'description': instance.description,
|
|
||||||
'error': instance.error,
|
|
||||||
'finishedAt': _nullable$dateTimeToJson(instance.finishedAt),
|
|
||||||
'name': instance.name,
|
|
||||||
'progress': instance.progress,
|
|
||||||
'result': instance.result,
|
|
||||||
'status': instance.status,
|
|
||||||
'statusText': instance.statusText,
|
|
||||||
'uid': instance.uid,
|
|
||||||
'updatedAt': dateTimeToJson(instance.updatedAt),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,147 +0,0 @@
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
|
||||||
|
|
||||||
part of 'schema.graphql.dart';
|
|
||||||
|
|
||||||
// **************************************************************************
|
|
||||||
// JsonSerializableGenerator
|
|
||||||
// **************************************************************************
|
|
||||||
|
|
||||||
Input$AutoUpgradeSettingsInput _$Input$AutoUpgradeSettingsInputFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Input$AutoUpgradeSettingsInput(
|
|
||||||
enableAutoUpgrade: json['enableAutoUpgrade'] as bool?,
|
|
||||||
allowReboot: json['allowReboot'] as bool?,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Input$AutoUpgradeSettingsInputToJson(
|
|
||||||
Input$AutoUpgradeSettingsInput instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'enableAutoUpgrade': instance.enableAutoUpgrade,
|
|
||||||
'allowReboot': instance.allowReboot,
|
|
||||||
};
|
|
||||||
|
|
||||||
Input$MigrateToBindsInput _$Input$MigrateToBindsInputFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Input$MigrateToBindsInput(
|
|
||||||
emailBlockDevice: json['emailBlockDevice'] as String,
|
|
||||||
bitwardenBlockDevice: json['bitwardenBlockDevice'] as String,
|
|
||||||
giteaBlockDevice: json['giteaBlockDevice'] as String,
|
|
||||||
nextcloudBlockDevice: json['nextcloudBlockDevice'] as String,
|
|
||||||
pleromaBlockDevice: json['pleromaBlockDevice'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Input$MigrateToBindsInputToJson(
|
|
||||||
Input$MigrateToBindsInput instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'emailBlockDevice': instance.emailBlockDevice,
|
|
||||||
'bitwardenBlockDevice': instance.bitwardenBlockDevice,
|
|
||||||
'giteaBlockDevice': instance.giteaBlockDevice,
|
|
||||||
'nextcloudBlockDevice': instance.nextcloudBlockDevice,
|
|
||||||
'pleromaBlockDevice': instance.pleromaBlockDevice,
|
|
||||||
};
|
|
||||||
|
|
||||||
Input$MoveServiceInput _$Input$MoveServiceInputFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Input$MoveServiceInput(
|
|
||||||
serviceId: json['serviceId'] as String,
|
|
||||||
location: json['location'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Input$MoveServiceInputToJson(
|
|
||||||
Input$MoveServiceInput instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'serviceId': instance.serviceId,
|
|
||||||
'location': instance.location,
|
|
||||||
};
|
|
||||||
|
|
||||||
Input$RecoveryKeyLimitsInput _$Input$RecoveryKeyLimitsInputFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Input$RecoveryKeyLimitsInput(
|
|
||||||
expirationDate: _nullable$dateTimeFromJson(json['expirationDate']),
|
|
||||||
uses: json['uses'] as int?,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Input$RecoveryKeyLimitsInputToJson(
|
|
||||||
Input$RecoveryKeyLimitsInput instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'expirationDate': _nullable$dateTimeToJson(instance.expirationDate),
|
|
||||||
'uses': instance.uses,
|
|
||||||
};
|
|
||||||
|
|
||||||
Input$SshMutationInput _$Input$SshMutationInputFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Input$SshMutationInput(
|
|
||||||
username: json['username'] as String,
|
|
||||||
sshKey: json['sshKey'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Input$SshMutationInputToJson(
|
|
||||||
Input$SshMutationInput instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'username': instance.username,
|
|
||||||
'sshKey': instance.sshKey,
|
|
||||||
};
|
|
||||||
|
|
||||||
Input$UseNewDeviceKeyInput _$Input$UseNewDeviceKeyInputFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Input$UseNewDeviceKeyInput(
|
|
||||||
key: json['key'] as String,
|
|
||||||
deviceName: json['deviceName'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Input$UseNewDeviceKeyInputToJson(
|
|
||||||
Input$UseNewDeviceKeyInput instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'key': instance.key,
|
|
||||||
'deviceName': instance.deviceName,
|
|
||||||
};
|
|
||||||
|
|
||||||
Input$UseRecoveryKeyInput _$Input$UseRecoveryKeyInputFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Input$UseRecoveryKeyInput(
|
|
||||||
key: json['key'] as String,
|
|
||||||
deviceName: json['deviceName'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Input$UseRecoveryKeyInputToJson(
|
|
||||||
Input$UseRecoveryKeyInput instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'key': instance.key,
|
|
||||||
'deviceName': instance.deviceName,
|
|
||||||
};
|
|
||||||
|
|
||||||
Input$UserMutationInput _$Input$UserMutationInputFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Input$UserMutationInput(
|
|
||||||
username: json['username'] as String,
|
|
||||||
password: json['password'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Input$UserMutationInputToJson(
|
|
||||||
Input$UserMutationInput instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'username': instance.username,
|
|
||||||
'password': instance.password,
|
|
||||||
};
|
|
||||||
|
|
||||||
Fragment$dnsRecordFields _$Fragment$dnsRecordFieldsFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Fragment$dnsRecordFields(
|
|
||||||
content: json['content'] as String,
|
|
||||||
name: json['name'] as String,
|
|
||||||
priority: json['priority'] as int?,
|
|
||||||
recordType: json['recordType'] as String,
|
|
||||||
ttl: json['ttl'] as int,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Fragment$dnsRecordFieldsToJson(
|
|
||||||
Fragment$dnsRecordFields instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'content': instance.content,
|
|
||||||
'name': instance.name,
|
|
||||||
'priority': instance.priority,
|
|
||||||
'recordType': instance.recordType,
|
|
||||||
'ttl': instance.ttl,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,797 +0,0 @@
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
|
||||||
|
|
||||||
part of 'server_api.graphql.dart';
|
|
||||||
|
|
||||||
// **************************************************************************
|
|
||||||
// JsonSerializableGenerator
|
|
||||||
// **************************************************************************
|
|
||||||
|
|
||||||
Fragment$basicMutationReturnFields _$Fragment$basicMutationReturnFieldsFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Fragment$basicMutationReturnFields(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Fragment$basicMutationReturnFieldsToJson(
|
|
||||||
Fragment$basicMutationReturnFields instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$GetApiVersion _$Query$GetApiVersionFromJson(Map<String, dynamic> json) =>
|
|
||||||
Query$GetApiVersion(
|
|
||||||
api:
|
|
||||||
Query$GetApiVersion$api.fromJson(json['api'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$GetApiVersionToJson(
|
|
||||||
Query$GetApiVersion instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'api': instance.api.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$GetApiVersion$api _$Query$GetApiVersion$apiFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$GetApiVersion$api(
|
|
||||||
version: json['version'] as String,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$GetApiVersion$apiToJson(
|
|
||||||
Query$GetApiVersion$api instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'version': instance.version,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$GetApiJobs _$Query$GetApiJobsFromJson(Map<String, dynamic> json) =>
|
|
||||||
Query$GetApiJobs(
|
|
||||||
jobs:
|
|
||||||
Query$GetApiJobs$jobs.fromJson(json['jobs'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$GetApiJobsToJson(Query$GetApiJobs instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'jobs': instance.jobs.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$GetApiJobs$jobs _$Query$GetApiJobs$jobsFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$GetApiJobs$jobs(
|
|
||||||
getJobs: (json['getJobs'] as List<dynamic>)
|
|
||||||
.map((e) =>
|
|
||||||
Query$GetApiJobs$jobs$getJobs.fromJson(e as Map<String, dynamic>))
|
|
||||||
.toList(),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$GetApiJobs$jobsToJson(
|
|
||||||
Query$GetApiJobs$jobs instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'getJobs': instance.getJobs.map((e) => e.toJson()).toList(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$GetApiJobs$jobs$getJobs _$Query$GetApiJobs$jobs$getJobsFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$GetApiJobs$jobs$getJobs(
|
|
||||||
createdAt: dateTimeFromJson(json['createdAt']),
|
|
||||||
description: json['description'] as String,
|
|
||||||
error: json['error'] as String?,
|
|
||||||
finishedAt: _nullable$dateTimeFromJson(json['finishedAt']),
|
|
||||||
name: json['name'] as String,
|
|
||||||
progress: json['progress'] as int?,
|
|
||||||
result: json['result'] as String?,
|
|
||||||
status: json['status'] as String,
|
|
||||||
statusText: json['statusText'] as String?,
|
|
||||||
uid: json['uid'] as String,
|
|
||||||
updatedAt: dateTimeFromJson(json['updatedAt']),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$GetApiJobs$jobs$getJobsToJson(
|
|
||||||
Query$GetApiJobs$jobs$getJobs instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'createdAt': dateTimeToJson(instance.createdAt),
|
|
||||||
'description': instance.description,
|
|
||||||
'error': instance.error,
|
|
||||||
'finishedAt': _nullable$dateTimeToJson(instance.finishedAt),
|
|
||||||
'name': instance.name,
|
|
||||||
'progress': instance.progress,
|
|
||||||
'result': instance.result,
|
|
||||||
'status': instance.status,
|
|
||||||
'statusText': instance.statusText,
|
|
||||||
'uid': instance.uid,
|
|
||||||
'updatedAt': dateTimeToJson(instance.updatedAt),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Variables$Mutation$RemoveJob _$Variables$Mutation$RemoveJobFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Variables$Mutation$RemoveJob(
|
|
||||||
jobId: json['jobId'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Variables$Mutation$RemoveJobToJson(
|
|
||||||
Variables$Mutation$RemoveJob instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'jobId': instance.jobId,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$RemoveJob _$Mutation$RemoveJobFromJson(Map<String, dynamic> json) =>
|
|
||||||
Mutation$RemoveJob(
|
|
||||||
removeJob: Mutation$RemoveJob$removeJob.fromJson(
|
|
||||||
json['removeJob'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$RemoveJobToJson(Mutation$RemoveJob instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'removeJob': instance.removeJob.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$RemoveJob$removeJob _$Mutation$RemoveJob$removeJobFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$RemoveJob$removeJob(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$RemoveJob$removeJobToJson(
|
|
||||||
Mutation$RemoveJob$removeJob instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$RunSystemRebuild _$Mutation$RunSystemRebuildFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$RunSystemRebuild(
|
|
||||||
runSystemRebuild: Mutation$RunSystemRebuild$runSystemRebuild.fromJson(
|
|
||||||
json['runSystemRebuild'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$RunSystemRebuildToJson(
|
|
||||||
Mutation$RunSystemRebuild instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'runSystemRebuild': instance.runSystemRebuild.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$RunSystemRebuild$runSystemRebuild
|
|
||||||
_$Mutation$RunSystemRebuild$runSystemRebuildFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$RunSystemRebuild$runSystemRebuild(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$RunSystemRebuild$runSystemRebuildToJson(
|
|
||||||
Mutation$RunSystemRebuild$runSystemRebuild instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$RunSystemRollback _$Mutation$RunSystemRollbackFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$RunSystemRollback(
|
|
||||||
runSystemRollback: Mutation$RunSystemRollback$runSystemRollback.fromJson(
|
|
||||||
json['runSystemRollback'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$RunSystemRollbackToJson(
|
|
||||||
Mutation$RunSystemRollback instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'runSystemRollback': instance.runSystemRollback.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$RunSystemRollback$runSystemRollback
|
|
||||||
_$Mutation$RunSystemRollback$runSystemRollbackFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$RunSystemRollback$runSystemRollback(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$RunSystemRollback$runSystemRollbackToJson(
|
|
||||||
Mutation$RunSystemRollback$runSystemRollback instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$RunSystemUpgrade _$Mutation$RunSystemUpgradeFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$RunSystemUpgrade(
|
|
||||||
runSystemUpgrade: Mutation$RunSystemUpgrade$runSystemUpgrade.fromJson(
|
|
||||||
json['runSystemUpgrade'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$RunSystemUpgradeToJson(
|
|
||||||
Mutation$RunSystemUpgrade instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'runSystemUpgrade': instance.runSystemUpgrade.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$RunSystemUpgrade$runSystemUpgrade
|
|
||||||
_$Mutation$RunSystemUpgrade$runSystemUpgradeFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$RunSystemUpgrade$runSystemUpgrade(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$RunSystemUpgrade$runSystemUpgradeToJson(
|
|
||||||
Mutation$RunSystemUpgrade$runSystemUpgrade instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$PullRepositoryChanges _$Mutation$PullRepositoryChangesFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$PullRepositoryChanges(
|
|
||||||
pullRepositoryChanges:
|
|
||||||
Mutation$PullRepositoryChanges$pullRepositoryChanges.fromJson(
|
|
||||||
json['pullRepositoryChanges'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$PullRepositoryChangesToJson(
|
|
||||||
Mutation$PullRepositoryChanges instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'pullRepositoryChanges': instance.pullRepositoryChanges.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$PullRepositoryChanges$pullRepositoryChanges
|
|
||||||
_$Mutation$PullRepositoryChanges$pullRepositoryChangesFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$PullRepositoryChanges$pullRepositoryChanges(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic>
|
|
||||||
_$Mutation$PullRepositoryChanges$pullRepositoryChangesToJson(
|
|
||||||
Mutation$PullRepositoryChanges$pullRepositoryChanges instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$RebootSystem _$Mutation$RebootSystemFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$RebootSystem(
|
|
||||||
rebootSystem: Mutation$RebootSystem$rebootSystem.fromJson(
|
|
||||||
json['rebootSystem'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$RebootSystemToJson(
|
|
||||||
Mutation$RebootSystem instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'rebootSystem': instance.rebootSystem.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$RebootSystem$rebootSystem _$Mutation$RebootSystem$rebootSystemFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$RebootSystem$rebootSystem(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$RebootSystem$rebootSystemToJson(
|
|
||||||
Mutation$RebootSystem$rebootSystem instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$SystemServerProvider _$Query$SystemServerProviderFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$SystemServerProvider(
|
|
||||||
system: Query$SystemServerProvider$system.fromJson(
|
|
||||||
json['system'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$SystemServerProviderToJson(
|
|
||||||
Query$SystemServerProvider instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'system': instance.system.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$SystemServerProvider$system _$Query$SystemServerProvider$systemFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$SystemServerProvider$system(
|
|
||||||
provider: Query$SystemServerProvider$system$provider.fromJson(
|
|
||||||
json['provider'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$SystemServerProvider$systemToJson(
|
|
||||||
Query$SystemServerProvider$system instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'provider': instance.provider.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$SystemServerProvider$system$provider
|
|
||||||
_$Query$SystemServerProvider$system$providerFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$SystemServerProvider$system$provider(
|
|
||||||
provider: $enumDecode(_$Enum$ServerProviderEnumMap, json['provider'],
|
|
||||||
unknownValue: Enum$ServerProvider.$unknown),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$SystemServerProvider$system$providerToJson(
|
|
||||||
Query$SystemServerProvider$system$provider instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'provider': _$Enum$ServerProviderEnumMap[instance.provider]!,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
const _$Enum$ServerProviderEnumMap = {
|
|
||||||
Enum$ServerProvider.HETZNER: 'HETZNER',
|
|
||||||
Enum$ServerProvider.DIGITALOCEAN: 'DIGITALOCEAN',
|
|
||||||
Enum$ServerProvider.$unknown: r'$unknown',
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$GetApiTokens _$Query$GetApiTokensFromJson(Map<String, dynamic> json) =>
|
|
||||||
Query$GetApiTokens(
|
|
||||||
api: Query$GetApiTokens$api.fromJson(json['api'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$GetApiTokensToJson(Query$GetApiTokens instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'api': instance.api.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$GetApiTokens$api _$Query$GetApiTokens$apiFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$GetApiTokens$api(
|
|
||||||
devices: (json['devices'] as List<dynamic>)
|
|
||||||
.map((e) => Query$GetApiTokens$api$devices.fromJson(
|
|
||||||
e as Map<String, dynamic>))
|
|
||||||
.toList(),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$GetApiTokens$apiToJson(
|
|
||||||
Query$GetApiTokens$api instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'devices': instance.devices.map((e) => e.toJson()).toList(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$GetApiTokens$api$devices _$Query$GetApiTokens$api$devicesFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$GetApiTokens$api$devices(
|
|
||||||
creationDate: dateTimeFromJson(json['creationDate']),
|
|
||||||
isCaller: json['isCaller'] as bool,
|
|
||||||
name: json['name'] as String,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$GetApiTokens$api$devicesToJson(
|
|
||||||
Query$GetApiTokens$api$devices instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'creationDate': dateTimeToJson(instance.creationDate),
|
|
||||||
'isCaller': instance.isCaller,
|
|
||||||
'name': instance.name,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$RecoveryKey _$Query$RecoveryKeyFromJson(Map<String, dynamic> json) =>
|
|
||||||
Query$RecoveryKey(
|
|
||||||
api: Query$RecoveryKey$api.fromJson(json['api'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$RecoveryKeyToJson(Query$RecoveryKey instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'api': instance.api.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$RecoveryKey$api _$Query$RecoveryKey$apiFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$RecoveryKey$api(
|
|
||||||
recoveryKey: Query$RecoveryKey$api$recoveryKey.fromJson(
|
|
||||||
json['recoveryKey'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$RecoveryKey$apiToJson(
|
|
||||||
Query$RecoveryKey$api instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'recoveryKey': instance.recoveryKey.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$RecoveryKey$api$recoveryKey _$Query$RecoveryKey$api$recoveryKeyFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$RecoveryKey$api$recoveryKey(
|
|
||||||
creationDate: _nullable$dateTimeFromJson(json['creationDate']),
|
|
||||||
exists: json['exists'] as bool,
|
|
||||||
expirationDate: _nullable$dateTimeFromJson(json['expirationDate']),
|
|
||||||
usesLeft: json['usesLeft'] as int?,
|
|
||||||
valid: json['valid'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$RecoveryKey$api$recoveryKeyToJson(
|
|
||||||
Query$RecoveryKey$api$recoveryKey instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'creationDate': _nullable$dateTimeToJson(instance.creationDate),
|
|
||||||
'exists': instance.exists,
|
|
||||||
'expirationDate': _nullable$dateTimeToJson(instance.expirationDate),
|
|
||||||
'usesLeft': instance.usesLeft,
|
|
||||||
'valid': instance.valid,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Variables$Mutation$GetNewRecoveryApiKey
|
|
||||||
_$Variables$Mutation$GetNewRecoveryApiKeyFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Variables$Mutation$GetNewRecoveryApiKey(
|
|
||||||
limits: json['limits'] == null
|
|
||||||
? null
|
|
||||||
: Input$RecoveryKeyLimitsInput.fromJson(
|
|
||||||
json['limits'] as Map<String, dynamic>),
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Variables$Mutation$GetNewRecoveryApiKeyToJson(
|
|
||||||
Variables$Mutation$GetNewRecoveryApiKey instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'limits': instance.limits?.toJson(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$GetNewRecoveryApiKey _$Mutation$GetNewRecoveryApiKeyFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$GetNewRecoveryApiKey(
|
|
||||||
getNewRecoveryApiKey:
|
|
||||||
Mutation$GetNewRecoveryApiKey$getNewRecoveryApiKey.fromJson(
|
|
||||||
json['getNewRecoveryApiKey'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$GetNewRecoveryApiKeyToJson(
|
|
||||||
Mutation$GetNewRecoveryApiKey instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'getNewRecoveryApiKey': instance.getNewRecoveryApiKey.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$GetNewRecoveryApiKey$getNewRecoveryApiKey
|
|
||||||
_$Mutation$GetNewRecoveryApiKey$getNewRecoveryApiKeyFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$GetNewRecoveryApiKey$getNewRecoveryApiKey(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
key: json['key'] as String?,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$GetNewRecoveryApiKey$getNewRecoveryApiKeyToJson(
|
|
||||||
Mutation$GetNewRecoveryApiKey$getNewRecoveryApiKey instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
'key': instance.key,
|
|
||||||
};
|
|
||||||
|
|
||||||
Variables$Mutation$UseRecoveryApiKey
|
|
||||||
_$Variables$Mutation$UseRecoveryApiKeyFromJson(Map<String, dynamic> json) =>
|
|
||||||
Variables$Mutation$UseRecoveryApiKey(
|
|
||||||
input: Input$UseRecoveryKeyInput.fromJson(
|
|
||||||
json['input'] as Map<String, dynamic>),
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Variables$Mutation$UseRecoveryApiKeyToJson(
|
|
||||||
Variables$Mutation$UseRecoveryApiKey instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'input': instance.input.toJson(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$UseRecoveryApiKey _$Mutation$UseRecoveryApiKeyFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$UseRecoveryApiKey(
|
|
||||||
useRecoveryApiKey: Mutation$UseRecoveryApiKey$useRecoveryApiKey.fromJson(
|
|
||||||
json['useRecoveryApiKey'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$UseRecoveryApiKeyToJson(
|
|
||||||
Mutation$UseRecoveryApiKey instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'useRecoveryApiKey': instance.useRecoveryApiKey.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$UseRecoveryApiKey$useRecoveryApiKey
|
|
||||||
_$Mutation$UseRecoveryApiKey$useRecoveryApiKeyFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$UseRecoveryApiKey$useRecoveryApiKey(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
token: json['token'] as String?,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$UseRecoveryApiKey$useRecoveryApiKeyToJson(
|
|
||||||
Mutation$UseRecoveryApiKey$useRecoveryApiKey instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
'token': instance.token,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$RefreshDeviceApiToken _$Mutation$RefreshDeviceApiTokenFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$RefreshDeviceApiToken(
|
|
||||||
refreshDeviceApiToken:
|
|
||||||
Mutation$RefreshDeviceApiToken$refreshDeviceApiToken.fromJson(
|
|
||||||
json['refreshDeviceApiToken'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$RefreshDeviceApiTokenToJson(
|
|
||||||
Mutation$RefreshDeviceApiToken instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'refreshDeviceApiToken': instance.refreshDeviceApiToken.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$RefreshDeviceApiToken$refreshDeviceApiToken
|
|
||||||
_$Mutation$RefreshDeviceApiToken$refreshDeviceApiTokenFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$RefreshDeviceApiToken$refreshDeviceApiToken(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
token: json['token'] as String?,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic>
|
|
||||||
_$Mutation$RefreshDeviceApiToken$refreshDeviceApiTokenToJson(
|
|
||||||
Mutation$RefreshDeviceApiToken$refreshDeviceApiToken instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
'token': instance.token,
|
|
||||||
};
|
|
||||||
|
|
||||||
Variables$Mutation$DeleteDeviceApiToken
|
|
||||||
_$Variables$Mutation$DeleteDeviceApiTokenFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Variables$Mutation$DeleteDeviceApiToken(
|
|
||||||
device: json['device'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Variables$Mutation$DeleteDeviceApiTokenToJson(
|
|
||||||
Variables$Mutation$DeleteDeviceApiToken instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'device': instance.device,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$DeleteDeviceApiToken _$Mutation$DeleteDeviceApiTokenFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$DeleteDeviceApiToken(
|
|
||||||
deleteDeviceApiToken:
|
|
||||||
Mutation$DeleteDeviceApiToken$deleteDeviceApiToken.fromJson(
|
|
||||||
json['deleteDeviceApiToken'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$DeleteDeviceApiTokenToJson(
|
|
||||||
Mutation$DeleteDeviceApiToken instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'deleteDeviceApiToken': instance.deleteDeviceApiToken.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$DeleteDeviceApiToken$deleteDeviceApiToken
|
|
||||||
_$Mutation$DeleteDeviceApiToken$deleteDeviceApiTokenFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$DeleteDeviceApiToken$deleteDeviceApiToken(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$DeleteDeviceApiToken$deleteDeviceApiTokenToJson(
|
|
||||||
Mutation$DeleteDeviceApiToken$deleteDeviceApiToken instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$GetNewDeviceApiKey _$Mutation$GetNewDeviceApiKeyFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$GetNewDeviceApiKey(
|
|
||||||
getNewDeviceApiKey:
|
|
||||||
Mutation$GetNewDeviceApiKey$getNewDeviceApiKey.fromJson(
|
|
||||||
json['getNewDeviceApiKey'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$GetNewDeviceApiKeyToJson(
|
|
||||||
Mutation$GetNewDeviceApiKey instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'getNewDeviceApiKey': instance.getNewDeviceApiKey.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$GetNewDeviceApiKey$getNewDeviceApiKey
|
|
||||||
_$Mutation$GetNewDeviceApiKey$getNewDeviceApiKeyFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$GetNewDeviceApiKey$getNewDeviceApiKey(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
key: json['key'] as String?,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$GetNewDeviceApiKey$getNewDeviceApiKeyToJson(
|
|
||||||
Mutation$GetNewDeviceApiKey$getNewDeviceApiKey instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
'key': instance.key,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$InvalidateNewDeviceApiKey _$Mutation$InvalidateNewDeviceApiKeyFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$InvalidateNewDeviceApiKey(
|
|
||||||
invalidateNewDeviceApiKey:
|
|
||||||
Mutation$InvalidateNewDeviceApiKey$invalidateNewDeviceApiKey.fromJson(
|
|
||||||
json['invalidateNewDeviceApiKey'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$InvalidateNewDeviceApiKeyToJson(
|
|
||||||
Mutation$InvalidateNewDeviceApiKey instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'invalidateNewDeviceApiKey': instance.invalidateNewDeviceApiKey.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$InvalidateNewDeviceApiKey$invalidateNewDeviceApiKey
|
|
||||||
_$Mutation$InvalidateNewDeviceApiKey$invalidateNewDeviceApiKeyFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$InvalidateNewDeviceApiKey$invalidateNewDeviceApiKey(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic>
|
|
||||||
_$Mutation$InvalidateNewDeviceApiKey$invalidateNewDeviceApiKeyToJson(
|
|
||||||
Mutation$InvalidateNewDeviceApiKey$invalidateNewDeviceApiKey
|
|
||||||
instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Variables$Mutation$AuthorizeWithNewDeviceApiKey
|
|
||||||
_$Variables$Mutation$AuthorizeWithNewDeviceApiKeyFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Variables$Mutation$AuthorizeWithNewDeviceApiKey(
|
|
||||||
input: Input$UseNewDeviceKeyInput.fromJson(
|
|
||||||
json['input'] as Map<String, dynamic>),
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Variables$Mutation$AuthorizeWithNewDeviceApiKeyToJson(
|
|
||||||
Variables$Mutation$AuthorizeWithNewDeviceApiKey instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'input': instance.input.toJson(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$AuthorizeWithNewDeviceApiKey
|
|
||||||
_$Mutation$AuthorizeWithNewDeviceApiKeyFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$AuthorizeWithNewDeviceApiKey(
|
|
||||||
authorizeWithNewDeviceApiKey:
|
|
||||||
Mutation$AuthorizeWithNewDeviceApiKey$authorizeWithNewDeviceApiKey
|
|
||||||
.fromJson(json['authorizeWithNewDeviceApiKey']
|
|
||||||
as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$AuthorizeWithNewDeviceApiKeyToJson(
|
|
||||||
Mutation$AuthorizeWithNewDeviceApiKey instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'authorizeWithNewDeviceApiKey':
|
|
||||||
instance.authorizeWithNewDeviceApiKey.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$AuthorizeWithNewDeviceApiKey$authorizeWithNewDeviceApiKey
|
|
||||||
_$Mutation$AuthorizeWithNewDeviceApiKey$authorizeWithNewDeviceApiKeyFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$AuthorizeWithNewDeviceApiKey$authorizeWithNewDeviceApiKey(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
token: json['token'] as String?,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic>
|
|
||||||
_$Mutation$AuthorizeWithNewDeviceApiKey$authorizeWithNewDeviceApiKeyToJson(
|
|
||||||
Mutation$AuthorizeWithNewDeviceApiKey$authorizeWithNewDeviceApiKey
|
|
||||||
instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
'token': instance.token,
|
|
||||||
};
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,315 +0,0 @@
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
|
||||||
|
|
||||||
part of 'server_settings.graphql.dart';
|
|
||||||
|
|
||||||
// **************************************************************************
|
|
||||||
// JsonSerializableGenerator
|
|
||||||
// **************************************************************************
|
|
||||||
|
|
||||||
Fragment$basicMutationReturnFields _$Fragment$basicMutationReturnFieldsFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Fragment$basicMutationReturnFields(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Fragment$basicMutationReturnFieldsToJson(
|
|
||||||
Fragment$basicMutationReturnFields instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$SystemSettings _$Query$SystemSettingsFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$SystemSettings(
|
|
||||||
system: Query$SystemSettings$system.fromJson(
|
|
||||||
json['system'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$SystemSettingsToJson(
|
|
||||||
Query$SystemSettings instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'system': instance.system.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$SystemSettings$system _$Query$SystemSettings$systemFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$SystemSettings$system(
|
|
||||||
settings: Query$SystemSettings$system$settings.fromJson(
|
|
||||||
json['settings'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$SystemSettings$systemToJson(
|
|
||||||
Query$SystemSettings$system instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'settings': instance.settings.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$SystemSettings$system$settings
|
|
||||||
_$Query$SystemSettings$system$settingsFromJson(Map<String, dynamic> json) =>
|
|
||||||
Query$SystemSettings$system$settings(
|
|
||||||
autoUpgrade:
|
|
||||||
Query$SystemSettings$system$settings$autoUpgrade.fromJson(
|
|
||||||
json['autoUpgrade'] as Map<String, dynamic>),
|
|
||||||
ssh: Query$SystemSettings$system$settings$ssh.fromJson(
|
|
||||||
json['ssh'] as Map<String, dynamic>),
|
|
||||||
timezone: json['timezone'] as String,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$SystemSettings$system$settingsToJson(
|
|
||||||
Query$SystemSettings$system$settings instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'autoUpgrade': instance.autoUpgrade.toJson(),
|
|
||||||
'ssh': instance.ssh.toJson(),
|
|
||||||
'timezone': instance.timezone,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$SystemSettings$system$settings$autoUpgrade
|
|
||||||
_$Query$SystemSettings$system$settings$autoUpgradeFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$SystemSettings$system$settings$autoUpgrade(
|
|
||||||
allowReboot: json['allowReboot'] as bool,
|
|
||||||
enable: json['enable'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$SystemSettings$system$settings$autoUpgradeToJson(
|
|
||||||
Query$SystemSettings$system$settings$autoUpgrade instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'allowReboot': instance.allowReboot,
|
|
||||||
'enable': instance.enable,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$SystemSettings$system$settings$ssh
|
|
||||||
_$Query$SystemSettings$system$settings$sshFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$SystemSettings$system$settings$ssh(
|
|
||||||
enable: json['enable'] as bool,
|
|
||||||
passwordAuthentication: json['passwordAuthentication'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$SystemSettings$system$settings$sshToJson(
|
|
||||||
Query$SystemSettings$system$settings$ssh instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'enable': instance.enable,
|
|
||||||
'passwordAuthentication': instance.passwordAuthentication,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$SystemIsUsingBinds _$Query$SystemIsUsingBindsFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$SystemIsUsingBinds(
|
|
||||||
system: Query$SystemIsUsingBinds$system.fromJson(
|
|
||||||
json['system'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$SystemIsUsingBindsToJson(
|
|
||||||
Query$SystemIsUsingBinds instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'system': instance.system.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$SystemIsUsingBinds$system _$Query$SystemIsUsingBinds$systemFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$SystemIsUsingBinds$system(
|
|
||||||
info: Query$SystemIsUsingBinds$system$info.fromJson(
|
|
||||||
json['info'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$SystemIsUsingBinds$systemToJson(
|
|
||||||
Query$SystemIsUsingBinds$system instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'info': instance.info.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$SystemIsUsingBinds$system$info
|
|
||||||
_$Query$SystemIsUsingBinds$system$infoFromJson(Map<String, dynamic> json) =>
|
|
||||||
Query$SystemIsUsingBinds$system$info(
|
|
||||||
usingBinds: json['usingBinds'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$SystemIsUsingBinds$system$infoToJson(
|
|
||||||
Query$SystemIsUsingBinds$system$info instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'usingBinds': instance.usingBinds,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$DomainInfo _$Query$DomainInfoFromJson(Map<String, dynamic> json) =>
|
|
||||||
Query$DomainInfo(
|
|
||||||
system: Query$DomainInfo$system.fromJson(
|
|
||||||
json['system'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$DomainInfoToJson(Query$DomainInfo instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'system': instance.system.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$DomainInfo$system _$Query$DomainInfo$systemFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$DomainInfo$system(
|
|
||||||
domainInfo: Query$DomainInfo$system$domainInfo.fromJson(
|
|
||||||
json['domainInfo'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$DomainInfo$systemToJson(
|
|
||||||
Query$DomainInfo$system instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'domainInfo': instance.domainInfo.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$DomainInfo$system$domainInfo _$Query$DomainInfo$system$domainInfoFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$DomainInfo$system$domainInfo(
|
|
||||||
domain: json['domain'] as String,
|
|
||||||
hostname: json['hostname'] as String,
|
|
||||||
provider: $enumDecode(_$Enum$DnsProviderEnumMap, json['provider'],
|
|
||||||
unknownValue: Enum$DnsProvider.$unknown),
|
|
||||||
requiredDnsRecords: (json['requiredDnsRecords'] as List<dynamic>)
|
|
||||||
.map((e) =>
|
|
||||||
Fragment$dnsRecordFields.fromJson(e as Map<String, dynamic>))
|
|
||||||
.toList(),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$DomainInfo$system$domainInfoToJson(
|
|
||||||
Query$DomainInfo$system$domainInfo instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'domain': instance.domain,
|
|
||||||
'hostname': instance.hostname,
|
|
||||||
'provider': _$Enum$DnsProviderEnumMap[instance.provider]!,
|
|
||||||
'requiredDnsRecords':
|
|
||||||
instance.requiredDnsRecords.map((e) => e.toJson()).toList(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
const _$Enum$DnsProviderEnumMap = {
|
|
||||||
Enum$DnsProvider.CLOUDFLARE: 'CLOUDFLARE',
|
|
||||||
Enum$DnsProvider.$unknown: r'$unknown',
|
|
||||||
};
|
|
||||||
|
|
||||||
Variables$Mutation$ChangeTimezone _$Variables$Mutation$ChangeTimezoneFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Variables$Mutation$ChangeTimezone(
|
|
||||||
timezone: json['timezone'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Variables$Mutation$ChangeTimezoneToJson(
|
|
||||||
Variables$Mutation$ChangeTimezone instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'timezone': instance.timezone,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$ChangeTimezone _$Mutation$ChangeTimezoneFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$ChangeTimezone(
|
|
||||||
changeTimezone: Mutation$ChangeTimezone$changeTimezone.fromJson(
|
|
||||||
json['changeTimezone'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$ChangeTimezoneToJson(
|
|
||||||
Mutation$ChangeTimezone instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'changeTimezone': instance.changeTimezone.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$ChangeTimezone$changeTimezone
|
|
||||||
_$Mutation$ChangeTimezone$changeTimezoneFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$ChangeTimezone$changeTimezone(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
timezone: json['timezone'] as String?,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$ChangeTimezone$changeTimezoneToJson(
|
|
||||||
Mutation$ChangeTimezone$changeTimezone instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
'timezone': instance.timezone,
|
|
||||||
};
|
|
||||||
|
|
||||||
Variables$Mutation$ChangeAutoUpgradeSettings
|
|
||||||
_$Variables$Mutation$ChangeAutoUpgradeSettingsFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Variables$Mutation$ChangeAutoUpgradeSettings(
|
|
||||||
settings: Input$AutoUpgradeSettingsInput.fromJson(
|
|
||||||
json['settings'] as Map<String, dynamic>),
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Variables$Mutation$ChangeAutoUpgradeSettingsToJson(
|
|
||||||
Variables$Mutation$ChangeAutoUpgradeSettings instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'settings': instance.settings.toJson(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$ChangeAutoUpgradeSettings _$Mutation$ChangeAutoUpgradeSettingsFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$ChangeAutoUpgradeSettings(
|
|
||||||
changeAutoUpgradeSettings:
|
|
||||||
Mutation$ChangeAutoUpgradeSettings$changeAutoUpgradeSettings.fromJson(
|
|
||||||
json['changeAutoUpgradeSettings'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$ChangeAutoUpgradeSettingsToJson(
|
|
||||||
Mutation$ChangeAutoUpgradeSettings instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'changeAutoUpgradeSettings': instance.changeAutoUpgradeSettings.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$ChangeAutoUpgradeSettings$changeAutoUpgradeSettings
|
|
||||||
_$Mutation$ChangeAutoUpgradeSettings$changeAutoUpgradeSettingsFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$ChangeAutoUpgradeSettings$changeAutoUpgradeSettings(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
allowReboot: json['allowReboot'] as bool,
|
|
||||||
enableAutoUpgrade: json['enableAutoUpgrade'] as bool,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic>
|
|
||||||
_$Mutation$ChangeAutoUpgradeSettings$changeAutoUpgradeSettingsToJson(
|
|
||||||
Mutation$ChangeAutoUpgradeSettings$changeAutoUpgradeSettings
|
|
||||||
instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
'allowReboot': instance.allowReboot,
|
|
||||||
'enableAutoUpgrade': instance.enableAutoUpgrade,
|
|
||||||
};
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,458 +0,0 @@
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
|
||||||
|
|
||||||
part of 'services.graphql.dart';
|
|
||||||
|
|
||||||
// **************************************************************************
|
|
||||||
// JsonSerializableGenerator
|
|
||||||
// **************************************************************************
|
|
||||||
|
|
||||||
Fragment$basicMutationReturnFields _$Fragment$basicMutationReturnFieldsFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Fragment$basicMutationReturnFields(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Fragment$basicMutationReturnFieldsToJson(
|
|
||||||
Fragment$basicMutationReturnFields instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$AllServices _$Query$AllServicesFromJson(Map<String, dynamic> json) =>
|
|
||||||
Query$AllServices(
|
|
||||||
services: Query$AllServices$services.fromJson(
|
|
||||||
json['services'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$AllServicesToJson(Query$AllServices instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'services': instance.services.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$AllServices$services _$Query$AllServices$servicesFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$AllServices$services(
|
|
||||||
allServices: (json['allServices'] as List<dynamic>)
|
|
||||||
.map((e) => Query$AllServices$services$allServices.fromJson(
|
|
||||||
e as Map<String, dynamic>))
|
|
||||||
.toList(),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$AllServices$servicesToJson(
|
|
||||||
Query$AllServices$services instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'allServices': instance.allServices.map((e) => e.toJson()).toList(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$AllServices$services$allServices
|
|
||||||
_$Query$AllServices$services$allServicesFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$AllServices$services$allServices(
|
|
||||||
description: json['description'] as String,
|
|
||||||
displayName: json['displayName'] as String,
|
|
||||||
dnsRecords: (json['dnsRecords'] as List<dynamic>?)
|
|
||||||
?.map((e) =>
|
|
||||||
Fragment$dnsRecordFields.fromJson(e as Map<String, dynamic>))
|
|
||||||
.toList(),
|
|
||||||
id: json['id'] as String,
|
|
||||||
isEnabled: json['isEnabled'] as bool,
|
|
||||||
isMovable: json['isMovable'] as bool,
|
|
||||||
isRequired: json['isRequired'] as bool,
|
|
||||||
status: $enumDecode(_$Enum$ServiceStatusEnumEnumMap, json['status'],
|
|
||||||
unknownValue: Enum$ServiceStatusEnum.$unknown),
|
|
||||||
storageUsage:
|
|
||||||
Query$AllServices$services$allServices$storageUsage.fromJson(
|
|
||||||
json['storageUsage'] as Map<String, dynamic>),
|
|
||||||
svgIcon: json['svgIcon'] as String,
|
|
||||||
url: json['url'] as String?,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$AllServices$services$allServicesToJson(
|
|
||||||
Query$AllServices$services$allServices instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'description': instance.description,
|
|
||||||
'displayName': instance.displayName,
|
|
||||||
'dnsRecords': instance.dnsRecords?.map((e) => e.toJson()).toList(),
|
|
||||||
'id': instance.id,
|
|
||||||
'isEnabled': instance.isEnabled,
|
|
||||||
'isMovable': instance.isMovable,
|
|
||||||
'isRequired': instance.isRequired,
|
|
||||||
'status': _$Enum$ServiceStatusEnumEnumMap[instance.status]!,
|
|
||||||
'storageUsage': instance.storageUsage.toJson(),
|
|
||||||
'svgIcon': instance.svgIcon,
|
|
||||||
'url': instance.url,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
const _$Enum$ServiceStatusEnumEnumMap = {
|
|
||||||
Enum$ServiceStatusEnum.ACTIVATING: 'ACTIVATING',
|
|
||||||
Enum$ServiceStatusEnum.ACTIVE: 'ACTIVE',
|
|
||||||
Enum$ServiceStatusEnum.DEACTIVATING: 'DEACTIVATING',
|
|
||||||
Enum$ServiceStatusEnum.FAILED: 'FAILED',
|
|
||||||
Enum$ServiceStatusEnum.INACTIVE: 'INACTIVE',
|
|
||||||
Enum$ServiceStatusEnum.OFF: 'OFF',
|
|
||||||
Enum$ServiceStatusEnum.RELOADING: 'RELOADING',
|
|
||||||
Enum$ServiceStatusEnum.$unknown: r'$unknown',
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$AllServices$services$allServices$storageUsage
|
|
||||||
_$Query$AllServices$services$allServices$storageUsageFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$AllServices$services$allServices$storageUsage(
|
|
||||||
title: json['title'] as String,
|
|
||||||
usedSpace: json['usedSpace'] as String,
|
|
||||||
volume: json['volume'] == null
|
|
||||||
? null
|
|
||||||
: Query$AllServices$services$allServices$storageUsage$volume
|
|
||||||
.fromJson(json['volume'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic>
|
|
||||||
_$Query$AllServices$services$allServices$storageUsageToJson(
|
|
||||||
Query$AllServices$services$allServices$storageUsage instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'title': instance.title,
|
|
||||||
'usedSpace': instance.usedSpace,
|
|
||||||
'volume': instance.volume?.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$AllServices$services$allServices$storageUsage$volume
|
|
||||||
_$Query$AllServices$services$allServices$storageUsage$volumeFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$AllServices$services$allServices$storageUsage$volume(
|
|
||||||
name: json['name'] as String,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String,
|
|
||||||
dynamic> _$Query$AllServices$services$allServices$storageUsage$volumeToJson(
|
|
||||||
Query$AllServices$services$allServices$storageUsage$volume instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'name': instance.name,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Variables$Mutation$EnableService _$Variables$Mutation$EnableServiceFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Variables$Mutation$EnableService(
|
|
||||||
serviceId: json['serviceId'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Variables$Mutation$EnableServiceToJson(
|
|
||||||
Variables$Mutation$EnableService instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'serviceId': instance.serviceId,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$EnableService _$Mutation$EnableServiceFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$EnableService(
|
|
||||||
enableService: Mutation$EnableService$enableService.fromJson(
|
|
||||||
json['enableService'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$EnableServiceToJson(
|
|
||||||
Mutation$EnableService instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'enableService': instance.enableService.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$EnableService$enableService
|
|
||||||
_$Mutation$EnableService$enableServiceFromJson(Map<String, dynamic> json) =>
|
|
||||||
Mutation$EnableService$enableService(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$EnableService$enableServiceToJson(
|
|
||||||
Mutation$EnableService$enableService instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Variables$Mutation$DisableService _$Variables$Mutation$DisableServiceFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Variables$Mutation$DisableService(
|
|
||||||
serviceId: json['serviceId'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Variables$Mutation$DisableServiceToJson(
|
|
||||||
Variables$Mutation$DisableService instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'serviceId': instance.serviceId,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$DisableService _$Mutation$DisableServiceFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$DisableService(
|
|
||||||
disableService: Mutation$DisableService$disableService.fromJson(
|
|
||||||
json['disableService'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$DisableServiceToJson(
|
|
||||||
Mutation$DisableService instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'disableService': instance.disableService.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$DisableService$disableService
|
|
||||||
_$Mutation$DisableService$disableServiceFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$DisableService$disableService(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$DisableService$disableServiceToJson(
|
|
||||||
Mutation$DisableService$disableService instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Variables$Mutation$StopService _$Variables$Mutation$StopServiceFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Variables$Mutation$StopService(
|
|
||||||
serviceId: json['serviceId'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Variables$Mutation$StopServiceToJson(
|
|
||||||
Variables$Mutation$StopService instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'serviceId': instance.serviceId,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$StopService _$Mutation$StopServiceFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$StopService(
|
|
||||||
stopService: Mutation$StopService$stopService.fromJson(
|
|
||||||
json['stopService'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$StopServiceToJson(
|
|
||||||
Mutation$StopService instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'stopService': instance.stopService.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$StopService$stopService _$Mutation$StopService$stopServiceFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$StopService$stopService(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$StopService$stopServiceToJson(
|
|
||||||
Mutation$StopService$stopService instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Variables$Mutation$StartService _$Variables$Mutation$StartServiceFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Variables$Mutation$StartService(
|
|
||||||
serviceId: json['serviceId'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Variables$Mutation$StartServiceToJson(
|
|
||||||
Variables$Mutation$StartService instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'serviceId': instance.serviceId,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$StartService _$Mutation$StartServiceFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$StartService(
|
|
||||||
startService: Mutation$StartService$startService.fromJson(
|
|
||||||
json['startService'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$StartServiceToJson(
|
|
||||||
Mutation$StartService instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'startService': instance.startService.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$StartService$startService _$Mutation$StartService$startServiceFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$StartService$startService(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$StartService$startServiceToJson(
|
|
||||||
Mutation$StartService$startService instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Variables$Mutation$RestartService _$Variables$Mutation$RestartServiceFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Variables$Mutation$RestartService(
|
|
||||||
serviceId: json['serviceId'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Variables$Mutation$RestartServiceToJson(
|
|
||||||
Variables$Mutation$RestartService instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'serviceId': instance.serviceId,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$RestartService _$Mutation$RestartServiceFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$RestartService(
|
|
||||||
restartService: Mutation$RestartService$restartService.fromJson(
|
|
||||||
json['restartService'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$RestartServiceToJson(
|
|
||||||
Mutation$RestartService instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'restartService': instance.restartService.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$RestartService$restartService
|
|
||||||
_$Mutation$RestartService$restartServiceFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$RestartService$restartService(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$RestartService$restartServiceToJson(
|
|
||||||
Mutation$RestartService$restartService instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Variables$Mutation$MoveService _$Variables$Mutation$MoveServiceFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Variables$Mutation$MoveService(
|
|
||||||
input: Input$MoveServiceInput.fromJson(
|
|
||||||
json['input'] as Map<String, dynamic>),
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Variables$Mutation$MoveServiceToJson(
|
|
||||||
Variables$Mutation$MoveService instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'input': instance.input.toJson(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$MoveService _$Mutation$MoveServiceFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$MoveService(
|
|
||||||
moveService: Mutation$MoveService$moveService.fromJson(
|
|
||||||
json['moveService'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$MoveServiceToJson(
|
|
||||||
Mutation$MoveService instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'moveService': instance.moveService.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$MoveService$moveService _$Mutation$MoveService$moveServiceFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$MoveService$moveService(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
job: json['job'] == null
|
|
||||||
? null
|
|
||||||
: Mutation$MoveService$moveService$job.fromJson(
|
|
||||||
json['job'] as Map<String, dynamic>),
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$MoveService$moveServiceToJson(
|
|
||||||
Mutation$MoveService$moveService instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
'job': instance.job?.toJson(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$MoveService$moveService$job
|
|
||||||
_$Mutation$MoveService$moveService$jobFromJson(Map<String, dynamic> json) =>
|
|
||||||
Mutation$MoveService$moveService$job(
|
|
||||||
createdAt: dateTimeFromJson(json['createdAt']),
|
|
||||||
description: json['description'] as String,
|
|
||||||
error: json['error'] as String?,
|
|
||||||
finishedAt: _nullable$dateTimeFromJson(json['finishedAt']),
|
|
||||||
name: json['name'] as String,
|
|
||||||
progress: json['progress'] as int?,
|
|
||||||
result: json['result'] as String?,
|
|
||||||
status: json['status'] as String,
|
|
||||||
statusText: json['statusText'] as String?,
|
|
||||||
uid: json['uid'] as String,
|
|
||||||
updatedAt: dateTimeFromJson(json['updatedAt']),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$MoveService$moveService$jobToJson(
|
|
||||||
Mutation$MoveService$moveService$job instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'createdAt': dateTimeToJson(instance.createdAt),
|
|
||||||
'description': instance.description,
|
|
||||||
'error': instance.error,
|
|
||||||
'finishedAt': _nullable$dateTimeToJson(instance.finishedAt),
|
|
||||||
'name': instance.name,
|
|
||||||
'progress': instance.progress,
|
|
||||||
'result': instance.result,
|
|
||||||
'status': instance.status,
|
|
||||||
'statusText': instance.statusText,
|
|
||||||
'uid': instance.uid,
|
|
||||||
'updatedAt': dateTimeToJson(instance.updatedAt),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,366 +0,0 @@
|
||||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
|
||||||
|
|
||||||
part of 'users.graphql.dart';
|
|
||||||
|
|
||||||
// **************************************************************************
|
|
||||||
// JsonSerializableGenerator
|
|
||||||
// **************************************************************************
|
|
||||||
|
|
||||||
Fragment$basicMutationReturnFields _$Fragment$basicMutationReturnFieldsFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Fragment$basicMutationReturnFields(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Fragment$basicMutationReturnFieldsToJson(
|
|
||||||
Fragment$basicMutationReturnFields instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Fragment$userFields _$Fragment$userFieldsFromJson(Map<String, dynamic> json) =>
|
|
||||||
Fragment$userFields(
|
|
||||||
username: json['username'] as String,
|
|
||||||
userType: $enumDecode(_$Enum$UserTypeEnumMap, json['userType'],
|
|
||||||
unknownValue: Enum$UserType.$unknown),
|
|
||||||
sshKeys:
|
|
||||||
(json['sshKeys'] as List<dynamic>).map((e) => e as String).toList(),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Fragment$userFieldsToJson(
|
|
||||||
Fragment$userFields instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'username': instance.username,
|
|
||||||
'userType': _$Enum$UserTypeEnumMap[instance.userType]!,
|
|
||||||
'sshKeys': instance.sshKeys,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
const _$Enum$UserTypeEnumMap = {
|
|
||||||
Enum$UserType.NORMAL: 'NORMAL',
|
|
||||||
Enum$UserType.PRIMARY: 'PRIMARY',
|
|
||||||
Enum$UserType.ROOT: 'ROOT',
|
|
||||||
Enum$UserType.$unknown: r'$unknown',
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$AllUsers _$Query$AllUsersFromJson(Map<String, dynamic> json) =>
|
|
||||||
Query$AllUsers(
|
|
||||||
users:
|
|
||||||
Query$AllUsers$users.fromJson(json['users'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$AllUsersToJson(Query$AllUsers instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'users': instance.users.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$AllUsers$users _$Query$AllUsers$usersFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Query$AllUsers$users(
|
|
||||||
allUsers: (json['allUsers'] as List<dynamic>)
|
|
||||||
.map((e) => Fragment$userFields.fromJson(e as Map<String, dynamic>))
|
|
||||||
.toList(),
|
|
||||||
rootUser: json['rootUser'] == null
|
|
||||||
? null
|
|
||||||
: Fragment$userFields.fromJson(
|
|
||||||
json['rootUser'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$AllUsers$usersToJson(
|
|
||||||
Query$AllUsers$users instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'allUsers': instance.allUsers.map((e) => e.toJson()).toList(),
|
|
||||||
'rootUser': instance.rootUser?.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Variables$Query$GetUser _$Variables$Query$GetUserFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Variables$Query$GetUser(
|
|
||||||
username: json['username'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Variables$Query$GetUserToJson(
|
|
||||||
Variables$Query$GetUser instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'username': instance.username,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$GetUser _$Query$GetUserFromJson(Map<String, dynamic> json) =>
|
|
||||||
Query$GetUser(
|
|
||||||
users:
|
|
||||||
Query$GetUser$users.fromJson(json['users'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$GetUserToJson(Query$GetUser instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'users': instance.users.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Query$GetUser$users _$Query$GetUser$usersFromJson(Map<String, dynamic> json) =>
|
|
||||||
Query$GetUser$users(
|
|
||||||
getUser: json['getUser'] == null
|
|
||||||
? null
|
|
||||||
: Fragment$userFields.fromJson(
|
|
||||||
json['getUser'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Query$GetUser$usersToJson(
|
|
||||||
Query$GetUser$users instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'getUser': instance.getUser?.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Variables$Mutation$CreateUser _$Variables$Mutation$CreateUserFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Variables$Mutation$CreateUser(
|
|
||||||
user: Input$UserMutationInput.fromJson(
|
|
||||||
json['user'] as Map<String, dynamic>),
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Variables$Mutation$CreateUserToJson(
|
|
||||||
Variables$Mutation$CreateUser instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'user': instance.user.toJson(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$CreateUser _$Mutation$CreateUserFromJson(Map<String, dynamic> json) =>
|
|
||||||
Mutation$CreateUser(
|
|
||||||
createUser: Mutation$CreateUser$createUser.fromJson(
|
|
||||||
json['createUser'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$CreateUserToJson(
|
|
||||||
Mutation$CreateUser instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'createUser': instance.createUser.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$CreateUser$createUser _$Mutation$CreateUser$createUserFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$CreateUser$createUser(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
user: json['user'] == null
|
|
||||||
? null
|
|
||||||
: Fragment$userFields.fromJson(json['user'] as Map<String, dynamic>),
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$CreateUser$createUserToJson(
|
|
||||||
Mutation$CreateUser$createUser instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
'user': instance.user?.toJson(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Variables$Mutation$DeleteUser _$Variables$Mutation$DeleteUserFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Variables$Mutation$DeleteUser(
|
|
||||||
username: json['username'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Variables$Mutation$DeleteUserToJson(
|
|
||||||
Variables$Mutation$DeleteUser instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'username': instance.username,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$DeleteUser _$Mutation$DeleteUserFromJson(Map<String, dynamic> json) =>
|
|
||||||
Mutation$DeleteUser(
|
|
||||||
deleteUser: Mutation$DeleteUser$deleteUser.fromJson(
|
|
||||||
json['deleteUser'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$DeleteUserToJson(
|
|
||||||
Mutation$DeleteUser instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'deleteUser': instance.deleteUser.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$DeleteUser$deleteUser _$Mutation$DeleteUser$deleteUserFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$DeleteUser$deleteUser(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$DeleteUser$deleteUserToJson(
|
|
||||||
Mutation$DeleteUser$deleteUser instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Variables$Mutation$UpdateUser _$Variables$Mutation$UpdateUserFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Variables$Mutation$UpdateUser(
|
|
||||||
user: Input$UserMutationInput.fromJson(
|
|
||||||
json['user'] as Map<String, dynamic>),
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Variables$Mutation$UpdateUserToJson(
|
|
||||||
Variables$Mutation$UpdateUser instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'user': instance.user.toJson(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$UpdateUser _$Mutation$UpdateUserFromJson(Map<String, dynamic> json) =>
|
|
||||||
Mutation$UpdateUser(
|
|
||||||
updateUser: Mutation$UpdateUser$updateUser.fromJson(
|
|
||||||
json['updateUser'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$UpdateUserToJson(
|
|
||||||
Mutation$UpdateUser instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'updateUser': instance.updateUser.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$UpdateUser$updateUser _$Mutation$UpdateUser$updateUserFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$UpdateUser$updateUser(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
user: json['user'] == null
|
|
||||||
? null
|
|
||||||
: Fragment$userFields.fromJson(json['user'] as Map<String, dynamic>),
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$UpdateUser$updateUserToJson(
|
|
||||||
Mutation$UpdateUser$updateUser instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
'user': instance.user?.toJson(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Variables$Mutation$AddSshKey _$Variables$Mutation$AddSshKeyFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Variables$Mutation$AddSshKey(
|
|
||||||
sshInput: Input$SshMutationInput.fromJson(
|
|
||||||
json['sshInput'] as Map<String, dynamic>),
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Variables$Mutation$AddSshKeyToJson(
|
|
||||||
Variables$Mutation$AddSshKey instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'sshInput': instance.sshInput.toJson(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$AddSshKey _$Mutation$AddSshKeyFromJson(Map<String, dynamic> json) =>
|
|
||||||
Mutation$AddSshKey(
|
|
||||||
addSshKey: Mutation$AddSshKey$addSshKey.fromJson(
|
|
||||||
json['addSshKey'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$AddSshKeyToJson(Mutation$AddSshKey instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'addSshKey': instance.addSshKey.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$AddSshKey$addSshKey _$Mutation$AddSshKey$addSshKeyFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$AddSshKey$addSshKey(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
user: json['user'] == null
|
|
||||||
? null
|
|
||||||
: Fragment$userFields.fromJson(json['user'] as Map<String, dynamic>),
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$AddSshKey$addSshKeyToJson(
|
|
||||||
Mutation$AddSshKey$addSshKey instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
'user': instance.user?.toJson(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Variables$Mutation$RemoveSshKey _$Variables$Mutation$RemoveSshKeyFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Variables$Mutation$RemoveSshKey(
|
|
||||||
sshInput: Input$SshMutationInput.fromJson(
|
|
||||||
json['sshInput'] as Map<String, dynamic>),
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Variables$Mutation$RemoveSshKeyToJson(
|
|
||||||
Variables$Mutation$RemoveSshKey instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'sshInput': instance.sshInput.toJson(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$RemoveSshKey _$Mutation$RemoveSshKeyFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$RemoveSshKey(
|
|
||||||
removeSshKey: Mutation$RemoveSshKey$removeSshKey.fromJson(
|
|
||||||
json['removeSshKey'] as Map<String, dynamic>),
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$RemoveSshKeyToJson(
|
|
||||||
Mutation$RemoveSshKey instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'removeSshKey': instance.removeSshKey.toJson(),
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
};
|
|
||||||
|
|
||||||
Mutation$RemoveSshKey$removeSshKey _$Mutation$RemoveSshKey$removeSshKeyFromJson(
|
|
||||||
Map<String, dynamic> json) =>
|
|
||||||
Mutation$RemoveSshKey$removeSshKey(
|
|
||||||
code: json['code'] as int,
|
|
||||||
message: json['message'] as String,
|
|
||||||
success: json['success'] as bool,
|
|
||||||
$__typename: json['__typename'] as String,
|
|
||||||
user: json['user'] == null
|
|
||||||
? null
|
|
||||||
: Fragment$userFields.fromJson(json['user'] as Map<String, dynamic>),
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$Mutation$RemoveSshKey$removeSshKeyToJson(
|
|
||||||
Mutation$RemoveSshKey$removeSshKey instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'code': instance.code,
|
|
||||||
'message': instance.message,
|
|
||||||
'success': instance.success,
|
|
||||||
'__typename': instance.$__typename,
|
|
||||||
'user': instance.user?.toJson(),
|
|
||||||
};
|
|
|
@ -65,9 +65,11 @@ class ConsoleInterceptor extends InterceptorsWrapper {
|
||||||
final RequestInterceptorHandler handler,
|
final RequestInterceptorHandler handler,
|
||||||
) async {
|
) async {
|
||||||
addMessage(
|
addMessage(
|
||||||
Message(
|
RestApiRequestMessage(
|
||||||
text:
|
method: options.method,
|
||||||
'request-uri: ${options.uri}\nheaders: ${options.headers}\ndata: ${options.data}',
|
data: options.data.toString(),
|
||||||
|
headers: options.headers,
|
||||||
|
uri: options.uri,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return super.onRequest(options, handler);
|
return super.onRequest(options, handler);
|
||||||
|
@ -79,9 +81,11 @@ class ConsoleInterceptor extends InterceptorsWrapper {
|
||||||
final ResponseInterceptorHandler handler,
|
final ResponseInterceptorHandler handler,
|
||||||
) async {
|
) async {
|
||||||
addMessage(
|
addMessage(
|
||||||
Message(
|
RestApiResponseMessage(
|
||||||
text:
|
method: response.requestOptions.method,
|
||||||
'response-uri: ${response.realUri}\ncode: ${response.statusCode}\ndata: ${response.toString()}\n',
|
statusCode: response.statusCode,
|
||||||
|
data: response.data.toString(),
|
||||||
|
uri: response.realUri,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return super.onResponse(
|
return super.onResponse(
|
||||||
|
|
|
@ -15,10 +15,12 @@ part 'app_settings_state.dart';
|
||||||
class AppSettingsCubit extends Cubit<AppSettingsState> {
|
class AppSettingsCubit extends Cubit<AppSettingsState> {
|
||||||
AppSettingsCubit({
|
AppSettingsCubit({
|
||||||
required final bool isDarkModeOn,
|
required final bool isDarkModeOn,
|
||||||
|
required final bool isAutoDarkModeOn,
|
||||||
required final bool isOnboardingShowing,
|
required final bool isOnboardingShowing,
|
||||||
}) : super(
|
}) : super(
|
||||||
AppSettingsState(
|
AppSettingsState(
|
||||||
isDarkModeOn: isDarkModeOn,
|
isDarkModeOn: isDarkModeOn,
|
||||||
|
isAutoDarkModeOn: isAutoDarkModeOn,
|
||||||
isOnboardingShowing: isOnboardingShowing,
|
isOnboardingShowing: isOnboardingShowing,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -27,10 +29,12 @@ class AppSettingsCubit extends Cubit<AppSettingsState> {
|
||||||
|
|
||||||
void load() async {
|
void load() async {
|
||||||
final bool? isDarkModeOn = box.get(BNames.isDarkModeOn);
|
final bool? isDarkModeOn = box.get(BNames.isDarkModeOn);
|
||||||
|
final bool? isAutoDarkModeOn = box.get(BNames.isAutoDarkModeOn);
|
||||||
final bool? isOnboardingShowing = box.get(BNames.isOnboardingShowing);
|
final bool? isOnboardingShowing = box.get(BNames.isOnboardingShowing);
|
||||||
emit(
|
emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
isDarkModeOn: isDarkModeOn,
|
isDarkModeOn: isDarkModeOn,
|
||||||
|
isAutoDarkModeOn: isAutoDarkModeOn,
|
||||||
isOnboardingShowing: isOnboardingShowing,
|
isOnboardingShowing: isOnboardingShowing,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -49,9 +53,14 @@ class AppSettingsCubit extends Cubit<AppSettingsState> {
|
||||||
emit(state.copyWith(isDarkModeOn: isDarkModeOn));
|
emit(state.copyWith(isDarkModeOn: isDarkModeOn));
|
||||||
}
|
}
|
||||||
|
|
||||||
void turnOffOnboarding() {
|
void updateAutoDarkMode({required final bool isAutoDarkModeOn}) {
|
||||||
box.put(BNames.isOnboardingShowing, false);
|
box.put(BNames.isAutoDarkModeOn, isAutoDarkModeOn);
|
||||||
|
emit(state.copyWith(isAutoDarkModeOn: isAutoDarkModeOn));
|
||||||
|
}
|
||||||
|
|
||||||
emit(state.copyWith(isOnboardingShowing: false));
|
void turnOffOnboarding({final bool isOnboardingShowing = false}) {
|
||||||
|
box.put(BNames.isOnboardingShowing, isOnboardingShowing);
|
||||||
|
|
||||||
|
emit(state.copyWith(isOnboardingShowing: isOnboardingShowing));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,21 +3,25 @@ part of 'app_settings_cubit.dart';
|
||||||
class AppSettingsState extends Equatable {
|
class AppSettingsState extends Equatable {
|
||||||
const AppSettingsState({
|
const AppSettingsState({
|
||||||
required this.isDarkModeOn,
|
required this.isDarkModeOn,
|
||||||
|
required this.isAutoDarkModeOn,
|
||||||
required this.isOnboardingShowing,
|
required this.isOnboardingShowing,
|
||||||
this.corePalette,
|
this.corePalette,
|
||||||
});
|
});
|
||||||
|
|
||||||
final bool isDarkModeOn;
|
final bool isDarkModeOn;
|
||||||
|
final bool isAutoDarkModeOn;
|
||||||
final bool isOnboardingShowing;
|
final bool isOnboardingShowing;
|
||||||
final color_utils.CorePalette? corePalette;
|
final color_utils.CorePalette? corePalette;
|
||||||
|
|
||||||
AppSettingsState copyWith({
|
AppSettingsState copyWith({
|
||||||
final bool? isDarkModeOn,
|
final bool? isDarkModeOn,
|
||||||
|
final bool? isAutoDarkModeOn,
|
||||||
final bool? isOnboardingShowing,
|
final bool? isOnboardingShowing,
|
||||||
final color_utils.CorePalette? corePalette,
|
final color_utils.CorePalette? corePalette,
|
||||||
}) =>
|
}) =>
|
||||||
AppSettingsState(
|
AppSettingsState(
|
||||||
isDarkModeOn: isDarkModeOn ?? this.isDarkModeOn,
|
isDarkModeOn: isDarkModeOn ?? this.isDarkModeOn,
|
||||||
|
isAutoDarkModeOn: isAutoDarkModeOn ?? this.isAutoDarkModeOn,
|
||||||
isOnboardingShowing: isOnboardingShowing ?? this.isOnboardingShowing,
|
isOnboardingShowing: isOnboardingShowing ?? this.isOnboardingShowing,
|
||||||
corePalette: corePalette ?? this.corePalette,
|
corePalette: corePalette ?? this.corePalette,
|
||||||
);
|
);
|
||||||
|
@ -26,5 +30,6 @@ class AppSettingsState extends Equatable {
|
||||||
corePalette ?? color_utils.CorePalette.of(BrandColors.primary.value);
|
corePalette ?? color_utils.CorePalette.of(BrandColors.primary.value);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<dynamic> get props => [isDarkModeOn, isOnboardingShowing, corePalette];
|
List<dynamic> get props =>
|
||||||
|
[isDarkModeOn, isAutoDarkModeOn, isOnboardingShowing, corePalette];
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,9 @@ class ApiDevicesCubit
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void load() async {
|
void load() async {
|
||||||
if (serverInstallationCubit.state is ServerInstallationFinished) {
|
// if (serverInstallationCubit.state is ServerInstallationFinished) {
|
||||||
_refetch();
|
_refetch();
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> refresh() async {
|
Future<void> refresh() async {
|
||||||
|
|
|
@ -36,10 +36,6 @@ class UserFormCubit extends FormCubit {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureOr<void> onSubmit() {
|
FutureOr<void> onSubmit() {
|
||||||
print('onSubmit');
|
|
||||||
print('initialUser: $initialUser');
|
|
||||||
print('login: ${login.state.value}');
|
|
||||||
print('password: ${password.state.value}');
|
|
||||||
if (initialUser == null) {
|
if (initialUser == null) {
|
||||||
final User user = User(
|
final User user = User(
|
||||||
login: login.state.value,
|
login: login.state.value,
|
||||||
|
|
|
@ -14,21 +14,21 @@ class RecoveryKeyCubit
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void load() async {
|
void load() async {
|
||||||
if (serverInstallationCubit.state is ServerInstallationFinished) {
|
// if (serverInstallationCubit.state is ServerInstallationFinished) {
|
||||||
final RecoveryKeyStatus? status = await _getRecoveryKeyStatus();
|
final RecoveryKeyStatus? status = await _getRecoveryKeyStatus();
|
||||||
if (status == null) {
|
if (status == null) {
|
||||||
emit(state.copyWith(loadingStatus: LoadingStatus.error));
|
emit(state.copyWith(loadingStatus: LoadingStatus.error));
|
||||||
} else {
|
|
||||||
emit(
|
|
||||||
state.copyWith(
|
|
||||||
status: status,
|
|
||||||
loadingStatus: LoadingStatus.success,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
emit(state.copyWith(loadingStatus: LoadingStatus.uninitialized));
|
emit(
|
||||||
|
state.copyWith(
|
||||||
|
status: status,
|
||||||
|
loadingStatus: LoadingStatus.success,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
// } else {
|
||||||
|
// emit(state.copyWith(loadingStatus: LoadingStatus.uninitialized));
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<RecoveryKeyStatus?> _getRecoveryKeyStatus() async {
|
Future<RecoveryKeyStatus?> _getRecoveryKeyStatus() async {
|
||||||
|
|
19
lib/logic/cubit/support_system/support_system_cubit.dart
Normal file
19
lib/logic/cubit/support_system/support_system_cubit.dart
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
part 'support_system_state.dart';
|
||||||
|
|
||||||
|
class SupportSystemCubit extends Cubit<SupportSystemState> {
|
||||||
|
SupportSystemCubit() : super(const SupportSystemState('about'));
|
||||||
|
|
||||||
|
void showArticle({
|
||||||
|
required final String article,
|
||||||
|
final BuildContext? context,
|
||||||
|
}) {
|
||||||
|
emit(SupportSystemState(article));
|
||||||
|
if (context != null) {
|
||||||
|
Scaffold.of(context).openEndDrawer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
lib/logic/cubit/support_system/support_system_state.dart
Normal file
12
lib/logic/cubit/support_system/support_system_state.dart
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
part of 'support_system_cubit.dart';
|
||||||
|
|
||||||
|
class SupportSystemState extends Equatable {
|
||||||
|
const SupportSystemState(
|
||||||
|
this.currentArticle,
|
||||||
|
);
|
||||||
|
|
||||||
|
final String currentArticle;
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [currentArticle];
|
||||||
|
}
|
|
@ -1,16 +1,19 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:selfprivacy/config/brand_colors.dart';
|
|
||||||
import 'package:selfprivacy/config/text_themes.dart';
|
|
||||||
|
|
||||||
class NavigationService {
|
class NavigationService {
|
||||||
final GlobalKey<ScaffoldMessengerState> scaffoldMessengerKey =
|
final GlobalKey<ScaffoldMessengerState> scaffoldMessengerKey =
|
||||||
GlobalKey<ScaffoldMessengerState>();
|
GlobalKey<ScaffoldMessengerState>();
|
||||||
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
|
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
|
||||||
|
|
||||||
NavigatorState? get navigator => navigatorKey.currentState;
|
|
||||||
|
|
||||||
void showPopUpDialog(final AlertDialog dialog) {
|
void showPopUpDialog(final AlertDialog dialog) {
|
||||||
final BuildContext context = navigatorKey.currentState!.overlay!.context;
|
final BuildContext? context = navigatorKey.currentContext;
|
||||||
|
|
||||||
|
if (context == null) {
|
||||||
|
showSnackBar(
|
||||||
|
'Could not show dialog. This should not happen, please report this.',
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
|
@ -21,8 +24,7 @@ class NavigationService {
|
||||||
void showSnackBar(final String text) {
|
void showSnackBar(final String text) {
|
||||||
final ScaffoldMessengerState state = scaffoldMessengerKey.currentState!;
|
final ScaffoldMessengerState state = scaffoldMessengerKey.currentState!;
|
||||||
final SnackBar snack = SnackBar(
|
final SnackBar snack = SnackBar(
|
||||||
backgroundColor: BrandColors.black.withOpacity(0.8),
|
content: Text(text),
|
||||||
content: Text(text, style: buttonTitleText),
|
|
||||||
duration: const Duration(seconds: 2),
|
duration: const Duration(seconds: 2),
|
||||||
);
|
);
|
||||||
state.showSnackBar(snack);
|
state.showSnackBar(snack);
|
||||||
|
|
|
@ -1,20 +1,74 @@
|
||||||
|
import 'package:graphql/client.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
final DateFormat formatter = DateFormat('hh:mm');
|
final DateFormat formatter = DateFormat('hh:mm');
|
||||||
|
|
||||||
class Message {
|
class Message {
|
||||||
Message({this.text, this.type = MessageType.normal}) : time = DateTime.now();
|
Message({this.text, this.severity = MessageSeverity.normal})
|
||||||
|
: time = DateTime.now();
|
||||||
Message.warn({this.text})
|
Message.warn({this.text})
|
||||||
: type = MessageType.warning,
|
: severity = MessageSeverity.warning,
|
||||||
time = DateTime.now();
|
time = DateTime.now();
|
||||||
|
|
||||||
final String? text;
|
final String? text;
|
||||||
final DateTime time;
|
final DateTime time;
|
||||||
final MessageType type;
|
final MessageSeverity severity;
|
||||||
String get timeString => formatter.format(time);
|
String get timeString => formatter.format(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum MessageType {
|
enum MessageSeverity {
|
||||||
normal,
|
normal,
|
||||||
warning,
|
warning,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class RestApiRequestMessage extends Message {
|
||||||
|
RestApiRequestMessage({
|
||||||
|
this.method,
|
||||||
|
this.uri,
|
||||||
|
this.data,
|
||||||
|
this.headers,
|
||||||
|
}) : super(text: 'request-uri: $uri\nheaders: $headers\ndata: $data');
|
||||||
|
|
||||||
|
final String? method;
|
||||||
|
final Uri? uri;
|
||||||
|
final String? data;
|
||||||
|
final Map<String, dynamic>? headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
class RestApiResponseMessage extends Message {
|
||||||
|
RestApiResponseMessage({
|
||||||
|
this.method,
|
||||||
|
this.uri,
|
||||||
|
this.statusCode,
|
||||||
|
this.data,
|
||||||
|
}) : super(text: 'response-uri: $uri\ncode: $statusCode\ndata: $data');
|
||||||
|
|
||||||
|
final String? method;
|
||||||
|
final Uri? uri;
|
||||||
|
final int? statusCode;
|
||||||
|
final String? data;
|
||||||
|
}
|
||||||
|
|
||||||
|
class GraphQlResponseMessage extends Message {
|
||||||
|
GraphQlResponseMessage({
|
||||||
|
this.data,
|
||||||
|
this.errors,
|
||||||
|
this.context,
|
||||||
|
}) : super(text: 'GraphQL Response\ndata: $data');
|
||||||
|
|
||||||
|
final Map<String, dynamic>? data;
|
||||||
|
final List<GraphQLError>? errors;
|
||||||
|
final Context? context;
|
||||||
|
}
|
||||||
|
|
||||||
|
class GraphQlRequestMessage extends Message {
|
||||||
|
GraphQlRequestMessage({
|
||||||
|
this.operation,
|
||||||
|
this.variables,
|
||||||
|
this.context,
|
||||||
|
}) : super(text: 'GraphQL Request\noperation: $operation');
|
||||||
|
|
||||||
|
final Operation? operation;
|
||||||
|
final Map<String, dynamic>? variables;
|
||||||
|
final Context? context;
|
||||||
|
}
|
||||||
|
|
|
@ -5,9 +5,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:selfprivacy/config/brand_colors.dart';
|
import 'package:selfprivacy/config/brand_colors.dart';
|
||||||
import 'package:selfprivacy/config/hive_config.dart';
|
import 'package:selfprivacy/config/hive_config.dart';
|
||||||
import 'package:selfprivacy/theming/factory/app_theme_factory.dart';
|
import 'package:selfprivacy/theming/factory/app_theme_factory.dart';
|
||||||
import 'package:selfprivacy/ui/pages/setup/initializing/initializing.dart';
|
import 'package:selfprivacy/ui/router/router.dart';
|
||||||
import 'package:selfprivacy/ui/pages/onboarding/onboarding.dart';
|
|
||||||
import 'package:selfprivacy/ui/pages/root_route.dart';
|
|
||||||
import 'package:wakelock/wakelock.dart';
|
import 'package:wakelock/wakelock.dart';
|
||||||
import 'package:timezone/data/latest.dart' as tz;
|
import 'package:timezone/data/latest.dart' as tz;
|
||||||
|
|
||||||
|
@ -20,7 +18,7 @@ import 'package:selfprivacy/logic/cubit/app_settings/app_settings_cubit.dart';
|
||||||
void main() async {
|
void main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
await HiveConfig.init();
|
await HiveConfig.init();
|
||||||
await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
// await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
/// Wakelock support for Linux
|
/// Wakelock support for Linux
|
||||||
|
@ -43,21 +41,20 @@ void main() async {
|
||||||
fallbackColor: BrandColors.primary,
|
fallbackColor: BrandColors.primary,
|
||||||
);
|
);
|
||||||
|
|
||||||
BlocOverrides.runZoned(
|
Bloc.observer = SimpleBlocObserver();
|
||||||
() => runApp(
|
|
||||||
Localization(
|
runApp(
|
||||||
child: MyApp(
|
Localization(
|
||||||
lightThemeData: lightThemeData,
|
child: SelfprivacyApp(
|
||||||
darkThemeData: darkThemeData,
|
lightThemeData: lightThemeData,
|
||||||
),
|
darkThemeData: darkThemeData,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
blocObserver: SimpleBlocObserver(),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
class SelfprivacyApp extends StatelessWidget {
|
||||||
const MyApp({
|
SelfprivacyApp({
|
||||||
required this.lightThemeData,
|
required this.lightThemeData,
|
||||||
required this.darkThemeData,
|
required this.darkThemeData,
|
||||||
super.key,
|
super.key,
|
||||||
|
@ -66,42 +63,42 @@ class MyApp extends StatelessWidget {
|
||||||
final ThemeData lightThemeData;
|
final ThemeData lightThemeData;
|
||||||
final ThemeData darkThemeData;
|
final ThemeData darkThemeData;
|
||||||
|
|
||||||
|
final _appRouter = RootRouter(getIt.get<NavigationService>().navigatorKey);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(final BuildContext context) => Localization(
|
Widget build(final BuildContext context) => Localization(
|
||||||
child: AnnotatedRegion<SystemUiOverlayStyle>(
|
child: BlocAndProviderConfig(
|
||||||
value: SystemUiOverlayStyle.light, // Manually changing appbar color
|
child: BlocBuilder<AppSettingsCubit, AppSettingsState>(
|
||||||
child: BlocAndProviderConfig(
|
builder: (
|
||||||
child: BlocBuilder<AppSettingsCubit, AppSettingsState>(
|
final BuildContext context,
|
||||||
builder: (
|
final AppSettingsState appSettings,
|
||||||
final BuildContext context,
|
) =>
|
||||||
final AppSettingsState appSettings,
|
MaterialApp.router(
|
||||||
) =>
|
routeInformationParser: _appRouter.defaultRouteParser(),
|
||||||
MaterialApp(
|
routerDelegate: _appRouter.delegate(),
|
||||||
scaffoldMessengerKey:
|
scaffoldMessengerKey:
|
||||||
getIt.get<NavigationService>().scaffoldMessengerKey,
|
getIt.get<NavigationService>().scaffoldMessengerKey,
|
||||||
navigatorKey: getIt.get<NavigationService>().navigatorKey,
|
localizationsDelegates: context.localizationDelegates,
|
||||||
localizationsDelegates: context.localizationDelegates,
|
supportedLocales: context.supportedLocales,
|
||||||
supportedLocales: context.supportedLocales,
|
locale: context.locale,
|
||||||
locale: context.locale,
|
debugShowCheckedModeBanner: false,
|
||||||
debugShowCheckedModeBanner: false,
|
title: 'SelfPrivacy',
|
||||||
title: 'SelfPrivacy',
|
theme: lightThemeData,
|
||||||
theme: lightThemeData,
|
darkTheme: darkThemeData,
|
||||||
darkTheme: darkThemeData,
|
themeMode: appSettings.isAutoDarkModeOn
|
||||||
themeMode:
|
? ThemeMode.system
|
||||||
appSettings.isDarkModeOn ? ThemeMode.dark : ThemeMode.light,
|
: appSettings.isDarkModeOn
|
||||||
home: appSettings.isOnboardingShowing
|
? ThemeMode.dark
|
||||||
? const OnboardingPage(nextPage: InitializingPage())
|
: ThemeMode.light,
|
||||||
: const RootPage(),
|
builder: (final BuildContext context, final Widget? widget) {
|
||||||
builder: (final BuildContext context, final Widget? widget) {
|
Widget error = const Text('...rendering error...');
|
||||||
Widget error = const Text('...rendering error...');
|
if (widget is Scaffold || widget is Navigator) {
|
||||||
if (widget is Scaffold || widget is Navigator) {
|
error = Scaffold(body: Center(child: error));
|
||||||
error = Scaffold(body: Center(child: error));
|
}
|
||||||
}
|
ErrorWidget.builder =
|
||||||
ErrorWidget.builder =
|
(final FlutterErrorDetails errorDetails) => error;
|
||||||
(final FlutterErrorDetails errorDetails) => error;
|
return widget!;
|
||||||
return widget!;
|
},
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class BrandAlert extends AlertDialog {
|
|
||||||
BrandAlert({
|
|
||||||
super.key,
|
|
||||||
final String? title,
|
|
||||||
final String? contentText,
|
|
||||||
super.actions,
|
|
||||||
}) : super(
|
|
||||||
title: title != null ? Text(title) : null,
|
|
||||||
content: title != null ? Text(contentText!) : null,
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:selfprivacy/config/brand_colors.dart';
|
|
||||||
|
|
||||||
class BrandBottomSheet extends StatelessWidget {
|
|
||||||
const BrandBottomSheet({
|
|
||||||
required this.child,
|
|
||||||
super.key,
|
|
||||||
this.isExpended = false,
|
|
||||||
});
|
|
||||||
|
|
||||||
final Widget child;
|
|
||||||
final bool isExpended;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(final BuildContext context) {
|
|
||||||
final double mainHeight = MediaQuery.of(context).size.height -
|
|
||||||
MediaQuery.of(context).padding.top -
|
|
||||||
300;
|
|
||||||
late Widget innerWidget;
|
|
||||||
if (isExpended) {
|
|
||||||
innerWidget = Scaffold(
|
|
||||||
body: child,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
final ThemeData themeData = Theme.of(context);
|
|
||||||
|
|
||||||
innerWidget = Material(
|
|
||||||
color: themeData.scaffoldBackgroundColor,
|
|
||||||
child: IntrinsicHeight(child: child),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Center(
|
|
||||||
child: Container(
|
|
||||||
height: 4,
|
|
||||||
width: 30,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(2),
|
|
||||||
color: BrandColors.gray4,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 6),
|
|
||||||
ClipRRect(
|
|
||||||
borderRadius: const BorderRadius.vertical(top: Radius.circular(20)),
|
|
||||||
child: ConstrainedBox(
|
|
||||||
constraints: BoxConstraints(maxHeight: mainHeight),
|
|
||||||
child: innerWidget,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,55 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class BrandCards {
|
|
||||||
static Widget big({required final Widget child}) => _BrandCard(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 20,
|
|
||||||
vertical: 15,
|
|
||||||
),
|
|
||||||
shadow: bigShadow,
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
child: child,
|
|
||||||
);
|
|
||||||
static Widget small({required final Widget child}) => _BrandCard(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 15,
|
|
||||||
vertical: 10,
|
|
||||||
),
|
|
||||||
shadow: bigShadow,
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
child: child,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
class _BrandCard extends StatelessWidget {
|
|
||||||
const _BrandCard({
|
|
||||||
required this.child,
|
|
||||||
required this.padding,
|
|
||||||
required this.shadow,
|
|
||||||
required this.borderRadius,
|
|
||||||
});
|
|
||||||
|
|
||||||
final Widget child;
|
|
||||||
final EdgeInsets padding;
|
|
||||||
final List<BoxShadow> shadow;
|
|
||||||
final BorderRadius borderRadius;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(final BuildContext context) => Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Theme.of(context).colorScheme.surface,
|
|
||||||
borderRadius: borderRadius,
|
|
||||||
boxShadow: shadow,
|
|
||||||
),
|
|
||||||
padding: padding,
|
|
||||||
child: child,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<BoxShadow> bigShadow = [
|
|
||||||
BoxShadow(
|
|
||||||
offset: const Offset(0, 4),
|
|
||||||
blurRadius: 8,
|
|
||||||
color: Colors.black.withOpacity(.08),
|
|
||||||
)
|
|
||||||
];
|
|
|
@ -25,5 +25,8 @@ class BrandHeader extends StatelessWidget {
|
||||||
onBackButtonPressed ?? () => Navigator.of(context).pop(),
|
onBackButtonPressed ?? () => Navigator.of(context).pop(),
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
|
actions: const [
|
||||||
|
SizedBox.shrink(),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,147 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:selfprivacy/ui/components/pre_styled_buttons/flash_fab.dart';
|
|
||||||
import 'package:selfprivacy/ui/helpers/widget_size.dart';
|
|
||||||
|
|
||||||
class BrandHeroScreen extends StatelessWidget {
|
|
||||||
const BrandHeroScreen({
|
|
||||||
required this.children,
|
|
||||||
super.key,
|
|
||||||
this.hasBackButton = true,
|
|
||||||
this.hasFlashButton = true,
|
|
||||||
this.heroIcon,
|
|
||||||
this.heroIconWidget,
|
|
||||||
this.heroTitle = '',
|
|
||||||
this.heroSubtitle,
|
|
||||||
this.onBackButtonPressed,
|
|
||||||
});
|
|
||||||
|
|
||||||
final List<Widget> children;
|
|
||||||
final bool hasBackButton;
|
|
||||||
final bool hasFlashButton;
|
|
||||||
final IconData? heroIcon;
|
|
||||||
final Widget? heroIconWidget;
|
|
||||||
final String heroTitle;
|
|
||||||
final String? heroSubtitle;
|
|
||||||
final VoidCallback? onBackButtonPressed;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(final BuildContext context) {
|
|
||||||
final Widget heroIconWidget = this.heroIconWidget ??
|
|
||||||
Icon(
|
|
||||||
heroIcon ?? Icons.help,
|
|
||||||
size: 48.0,
|
|
||||||
color: Theme.of(context).colorScheme.onBackground,
|
|
||||||
);
|
|
||||||
final bool hasHeroIcon = heroIcon != null || this.heroIconWidget != null;
|
|
||||||
|
|
||||||
return Scaffold(
|
|
||||||
floatingActionButton: hasFlashButton ? const BrandFab() : null,
|
|
||||||
body: CustomScrollView(
|
|
||||||
slivers: [
|
|
||||||
HeroSliverAppBar(
|
|
||||||
heroTitle: heroTitle,
|
|
||||||
hasHeroIcon: hasHeroIcon,
|
|
||||||
hasBackButton: hasBackButton,
|
|
||||||
onBackButtonPressed: onBackButtonPressed,
|
|
||||||
heroIconWidget: heroIconWidget,
|
|
||||||
),
|
|
||||||
if (heroSubtitle != null)
|
|
||||||
SliverPadding(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 16.0,
|
|
||||||
vertical: 4.0,
|
|
||||||
),
|
|
||||||
sliver: SliverList(
|
|
||||||
delegate: SliverChildListDelegate([
|
|
||||||
Text(
|
|
||||||
heroSubtitle!,
|
|
||||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
|
||||||
color: Theme.of(context).colorScheme.onBackground,
|
|
||||||
),
|
|
||||||
textAlign: hasHeroIcon ? TextAlign.center : TextAlign.start,
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SliverPadding(
|
|
||||||
padding: const EdgeInsets.all(16.0),
|
|
||||||
sliver: SliverList(
|
|
||||||
delegate: SliverChildListDelegate(children),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class HeroSliverAppBar extends StatefulWidget {
|
|
||||||
const HeroSliverAppBar({
|
|
||||||
required this.heroTitle,
|
|
||||||
required this.hasHeroIcon,
|
|
||||||
required this.hasBackButton,
|
|
||||||
required this.onBackButtonPressed,
|
|
||||||
required this.heroIconWidget,
|
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
final String heroTitle;
|
|
||||||
final bool hasHeroIcon;
|
|
||||||
final bool hasBackButton;
|
|
||||||
final VoidCallback? onBackButtonPressed;
|
|
||||||
final Widget heroIconWidget;
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<HeroSliverAppBar> createState() => _HeroSliverAppBarState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _HeroSliverAppBarState extends State<HeroSliverAppBar> {
|
|
||||||
Size _size = Size.zero;
|
|
||||||
@override
|
|
||||||
Widget build(final BuildContext context) => SliverAppBar(
|
|
||||||
expandedHeight:
|
|
||||||
widget.hasHeroIcon ? 148.0 + _size.height : 72.0 + _size.height,
|
|
||||||
primary: true,
|
|
||||||
pinned: true,
|
|
||||||
stretch: true,
|
|
||||||
leading: widget.hasBackButton
|
|
||||||
? IconButton(
|
|
||||||
icon: const Icon(Icons.arrow_back),
|
|
||||||
onPressed: widget.onBackButtonPressed ??
|
|
||||||
() => Navigator.of(context).pop(),
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
flexibleSpace: FlexibleSpaceBar(
|
|
||||||
title: LayoutBuilder(
|
|
||||||
builder: (final context, final constraints) => SizedBox(
|
|
||||||
width: constraints.maxWidth - 72.0,
|
|
||||||
child: WidgetSize(
|
|
||||||
onChange: (final Size size) => setState(() => _size = size),
|
|
||||||
child: Text(
|
|
||||||
widget.heroTitle,
|
|
||||||
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
|
||||||
color: Theme.of(context).colorScheme.onSurface,
|
|
||||||
),
|
|
||||||
overflow: TextOverflow.fade,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
expandedTitleScale: 1.2,
|
|
||||||
centerTitle: true,
|
|
||||||
collapseMode: CollapseMode.pin,
|
|
||||||
titlePadding: const EdgeInsets.only(
|
|
||||||
bottom: 12.0,
|
|
||||||
top: 16.0,
|
|
||||||
),
|
|
||||||
background: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
const SizedBox(height: 72.0),
|
|
||||||
if (widget.hasHeroIcon) widget.heroIconWidget,
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -27,14 +27,14 @@ class BrandLinearIndicator extends StatelessWidget {
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: AnimatedSlide(
|
child: AnimatedSlide(
|
||||||
duration: const Duration(milliseconds: 400),
|
duration: const Duration(milliseconds: 400),
|
||||||
curve: Curves.easeInOut,
|
curve: Curves.easeInOutCubicEmphasized,
|
||||||
offset: Offset(
|
offset: Offset(
|
||||||
-(1 - value),
|
-(1 - value),
|
||||||
0,
|
0,
|
||||||
),
|
),
|
||||||
child: AnimatedContainer(
|
child: AnimatedContainer(
|
||||||
duration: const Duration(milliseconds: 400),
|
duration: const Duration(milliseconds: 400),
|
||||||
curve: Curves.easeInOut,
|
curve: Curves.easeInOutCubicEmphasized,
|
||||||
width: constraints.maxWidth,
|
width: constraints.maxWidth,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: color,
|
color: color,
|
||||||
|
|
|
@ -2,8 +2,6 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||||
import 'package:flutter/services.dart' show rootBundle;
|
import 'package:flutter/services.dart' show rootBundle;
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:selfprivacy/config/brand_colors.dart';
|
|
||||||
import 'package:selfprivacy/config/text_themes.dart';
|
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
|
|
||||||
class BrandMarkdown extends StatefulWidget {
|
class BrandMarkdown extends StatefulWidget {
|
||||||
|
@ -37,24 +35,7 @@ class _BrandMarkdownState extends State<BrandMarkdown> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(final BuildContext context) {
|
Widget build(final BuildContext context) {
|
||||||
final bool isDark = Theme.of(context).brightness == Brightness.dark;
|
final MarkdownStyleSheet markdown = MarkdownStyleSheet();
|
||||||
final MarkdownStyleSheet markdown = MarkdownStyleSheet(
|
|
||||||
p: defaultTextStyle.copyWith(
|
|
||||||
color: isDark ? BrandColors.white : null,
|
|
||||||
),
|
|
||||||
h1: headline1Style.copyWith(
|
|
||||||
color: isDark ? BrandColors.white : null,
|
|
||||||
),
|
|
||||||
h2: headline2Style.copyWith(
|
|
||||||
color: isDark ? BrandColors.white : null,
|
|
||||||
),
|
|
||||||
h3: headline3Style.copyWith(
|
|
||||||
color: isDark ? BrandColors.white : null,
|
|
||||||
),
|
|
||||||
h4: headline4Style.copyWith(
|
|
||||||
color: isDark ? BrandColors.white : null,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
return MarkdownBody(
|
return MarkdownBody(
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
styleSheet: markdown,
|
styleSheet: markdown,
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:selfprivacy/config/brand_colors.dart';
|
|
||||||
|
|
||||||
// TODO: Delete this file.
|
|
||||||
|
|
||||||
class BrandRadio extends StatelessWidget {
|
|
||||||
const BrandRadio({
|
|
||||||
required this.isChecked,
|
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
final bool isChecked;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(final BuildContext context) => Container(
|
|
||||||
height: 20,
|
|
||||||
width: 20,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
padding: const EdgeInsets.all(2),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
shape: BoxShape.circle,
|
|
||||||
border: _getBorder(),
|
|
||||||
),
|
|
||||||
child: isChecked
|
|
||||||
? Container(
|
|
||||||
height: 10,
|
|
||||||
width: 10,
|
|
||||||
decoration: const BoxDecoration(
|
|
||||||
shape: BoxShape.circle,
|
|
||||||
color: BrandColors.primary,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
);
|
|
||||||
|
|
||||||
BoxBorder? _getBorder() => Border.all(
|
|
||||||
color: isChecked ? BrandColors.primary : BrandColors.gray1,
|
|
||||||
width: 2,
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class BrandSwitch extends StatelessWidget {
|
|
||||||
const BrandSwitch({
|
|
||||||
required this.onChanged,
|
|
||||||
required this.value,
|
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
final ValueChanged<bool> onChanged;
|
|
||||||
final bool value;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(final BuildContext context) => Switch(
|
|
||||||
activeColor: Theme.of(context).colorScheme.primary,
|
|
||||||
value: value,
|
|
||||||
onChanged: onChanged,
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart';
|
|
||||||
|
|
||||||
class BrandTabBar extends StatefulWidget {
|
|
||||||
const BrandTabBar({super.key, this.controller});
|
|
||||||
|
|
||||||
final TabController? controller;
|
|
||||||
@override
|
|
||||||
State<BrandTabBar> createState() => _BrandTabBarState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _BrandTabBarState extends State<BrandTabBar> {
|
|
||||||
int? currentIndex;
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
currentIndex = widget.controller!.index;
|
|
||||||
widget.controller!.addListener(_listener);
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
void _listener() {
|
|
||||||
if (currentIndex != widget.controller!.index) {
|
|
||||||
setState(() {
|
|
||||||
currentIndex = widget.controller!.index;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
widget.controller ?? widget.controller!.removeListener(_listener);
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(final BuildContext context) => NavigationBar(
|
|
||||||
destinations: [
|
|
||||||
_getIconButton('basis.providers'.tr(), BrandIcons.server, 0),
|
|
||||||
_getIconButton('basis.services'.tr(), BrandIcons.box, 1),
|
|
||||||
_getIconButton('basis.users'.tr(), BrandIcons.users, 2),
|
|
||||||
_getIconButton('basis.more'.tr(), Icons.menu_rounded, 3),
|
|
||||||
],
|
|
||||||
onDestinationSelected: (final index) {
|
|
||||||
widget.controller!.animateTo(index);
|
|
||||||
},
|
|
||||||
selectedIndex: currentIndex ?? 0,
|
|
||||||
labelBehavior: NavigationDestinationLabelBehavior.onlyShowSelected,
|
|
||||||
);
|
|
||||||
|
|
||||||
NavigationDestination _getIconButton(
|
|
||||||
final String label,
|
|
||||||
final IconData iconData,
|
|
||||||
final int index,
|
|
||||||
) =>
|
|
||||||
NavigationDestination(
|
|
||||||
icon: Icon(iconData),
|
|
||||||
label: label,
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,238 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:selfprivacy/config/text_themes.dart';
|
|
||||||
export 'package:selfprivacy/utils/extensions/text_extensions.dart';
|
|
||||||
|
|
||||||
// TODO: Delete this file
|
|
||||||
|
|
||||||
enum TextType {
|
|
||||||
h1, // right now only at onboarding and opened providers
|
|
||||||
h2, // cards titles
|
|
||||||
h3, // titles in about page
|
|
||||||
h4, // caption
|
|
||||||
h5, // Table data
|
|
||||||
body1, // normal
|
|
||||||
body2, // with opacity
|
|
||||||
medium,
|
|
||||||
small,
|
|
||||||
onboardingTitle,
|
|
||||||
buttonTitleText, // risen button title text,
|
|
||||||
h4Underlined,
|
|
||||||
}
|
|
||||||
|
|
||||||
class BrandText extends StatelessWidget {
|
|
||||||
factory BrandText.h4(
|
|
||||||
final String? text, {
|
|
||||||
final TextStyle? style,
|
|
||||||
final TextAlign? textAlign,
|
|
||||||
}) =>
|
|
||||||
BrandText(
|
|
||||||
text,
|
|
||||||
type: TextType.h4,
|
|
||||||
style: style,
|
|
||||||
softWrap: true,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
maxLines: 2,
|
|
||||||
textAlign: textAlign,
|
|
||||||
);
|
|
||||||
|
|
||||||
factory BrandText.onboardingTitle(
|
|
||||||
final String text, {
|
|
||||||
final TextStyle? style,
|
|
||||||
}) =>
|
|
||||||
BrandText(
|
|
||||||
text,
|
|
||||||
type: TextType.onboardingTitle,
|
|
||||||
style: style,
|
|
||||||
);
|
|
||||||
factory BrandText.h3(
|
|
||||||
final String text, {
|
|
||||||
final TextStyle? style,
|
|
||||||
final TextAlign? textAlign,
|
|
||||||
}) =>
|
|
||||||
BrandText(
|
|
||||||
text,
|
|
||||||
type: TextType.h3,
|
|
||||||
style: style,
|
|
||||||
textAlign: textAlign,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
);
|
|
||||||
|
|
||||||
factory BrandText.h4Underlined(
|
|
||||||
final String? text, {
|
|
||||||
final TextStyle? style,
|
|
||||||
final TextAlign? textAlign,
|
|
||||||
}) =>
|
|
||||||
BrandText(
|
|
||||||
text,
|
|
||||||
type: TextType.h4Underlined,
|
|
||||||
style: style,
|
|
||||||
softWrap: true,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
maxLines: 2,
|
|
||||||
textAlign: textAlign,
|
|
||||||
);
|
|
||||||
|
|
||||||
factory BrandText.h1(
|
|
||||||
final String? text, {
|
|
||||||
final TextStyle? style,
|
|
||||||
final TextOverflow? overflow,
|
|
||||||
final bool? softWrap,
|
|
||||||
}) =>
|
|
||||||
BrandText(
|
|
||||||
text,
|
|
||||||
type: TextType.h1,
|
|
||||||
style: style,
|
|
||||||
);
|
|
||||||
factory BrandText.h2(
|
|
||||||
final String? text, {
|
|
||||||
final TextStyle? style,
|
|
||||||
final TextAlign? textAlign,
|
|
||||||
}) =>
|
|
||||||
BrandText(
|
|
||||||
text,
|
|
||||||
type: TextType.h2,
|
|
||||||
style: style,
|
|
||||||
textAlign: textAlign,
|
|
||||||
);
|
|
||||||
factory BrandText.body1(final String? text, {final TextStyle? style}) =>
|
|
||||||
BrandText(
|
|
||||||
text,
|
|
||||||
type: TextType.body1,
|
|
||||||
style: style,
|
|
||||||
);
|
|
||||||
factory BrandText.small(final String text, {final TextStyle? style}) =>
|
|
||||||
BrandText(
|
|
||||||
text,
|
|
||||||
type: TextType.small,
|
|
||||||
style: style,
|
|
||||||
);
|
|
||||||
factory BrandText.body2(final String? text, {final TextStyle? style}) =>
|
|
||||||
BrandText(
|
|
||||||
text,
|
|
||||||
type: TextType.body2,
|
|
||||||
style: style,
|
|
||||||
);
|
|
||||||
factory BrandText.buttonTitleText(
|
|
||||||
final String? text, {
|
|
||||||
final TextStyle? style,
|
|
||||||
}) =>
|
|
||||||
BrandText(
|
|
||||||
text,
|
|
||||||
type: TextType.buttonTitleText,
|
|
||||||
style: style,
|
|
||||||
);
|
|
||||||
|
|
||||||
factory BrandText.h5(
|
|
||||||
final String? text, {
|
|
||||||
final TextStyle? style,
|
|
||||||
final TextAlign? textAlign,
|
|
||||||
}) =>
|
|
||||||
BrandText(
|
|
||||||
text,
|
|
||||||
type: TextType.h5,
|
|
||||||
style: style,
|
|
||||||
textAlign: textAlign,
|
|
||||||
);
|
|
||||||
factory BrandText.medium(
|
|
||||||
final String? text, {
|
|
||||||
final TextStyle? style,
|
|
||||||
final TextAlign? textAlign,
|
|
||||||
}) =>
|
|
||||||
BrandText(
|
|
||||||
text,
|
|
||||||
type: TextType.medium,
|
|
||||||
style: style,
|
|
||||||
textAlign: textAlign,
|
|
||||||
);
|
|
||||||
const BrandText(
|
|
||||||
this.text, {
|
|
||||||
required this.type,
|
|
||||||
super.key,
|
|
||||||
this.style,
|
|
||||||
this.overflow,
|
|
||||||
this.softWrap,
|
|
||||||
this.textAlign,
|
|
||||||
this.maxLines,
|
|
||||||
});
|
|
||||||
|
|
||||||
final String? text;
|
|
||||||
final TextStyle? style;
|
|
||||||
final TextType type;
|
|
||||||
final TextOverflow? overflow;
|
|
||||||
final bool? softWrap;
|
|
||||||
final TextAlign? textAlign;
|
|
||||||
final int? maxLines;
|
|
||||||
@override
|
|
||||||
Text build(final BuildContext context) {
|
|
||||||
TextStyle style;
|
|
||||||
final bool isDark = Theme.of(context).brightness == Brightness.dark;
|
|
||||||
switch (type) {
|
|
||||||
case TextType.h1:
|
|
||||||
style = isDark
|
|
||||||
? headline1Style.copyWith(color: Colors.white)
|
|
||||||
: headline1Style;
|
|
||||||
break;
|
|
||||||
case TextType.h2:
|
|
||||||
style = isDark
|
|
||||||
? headline2Style.copyWith(color: Colors.white)
|
|
||||||
: headline2Style;
|
|
||||||
break;
|
|
||||||
case TextType.h3:
|
|
||||||
style = isDark
|
|
||||||
? headline3Style.copyWith(color: Colors.white)
|
|
||||||
: headline3Style;
|
|
||||||
break;
|
|
||||||
case TextType.h4:
|
|
||||||
style = isDark
|
|
||||||
? headline4Style.copyWith(color: Colors.white)
|
|
||||||
: headline4Style;
|
|
||||||
break;
|
|
||||||
case TextType.h4Underlined:
|
|
||||||
style = isDark
|
|
||||||
? headline4UnderlinedStyle.copyWith(color: Colors.white)
|
|
||||||
: headline4UnderlinedStyle;
|
|
||||||
break;
|
|
||||||
case TextType.h5:
|
|
||||||
style = isDark
|
|
||||||
? headline5Style.copyWith(color: Colors.white)
|
|
||||||
: headline5Style;
|
|
||||||
break;
|
|
||||||
case TextType.body1:
|
|
||||||
style = isDark ? body1Style.copyWith(color: Colors.white) : body1Style;
|
|
||||||
break;
|
|
||||||
case TextType.body2:
|
|
||||||
style = isDark
|
|
||||||
? body2Style.copyWith(color: Colors.white.withOpacity(0.6))
|
|
||||||
: body2Style;
|
|
||||||
break;
|
|
||||||
case TextType.small:
|
|
||||||
style = isDark ? smallStyle.copyWith(color: Colors.white) : smallStyle;
|
|
||||||
break;
|
|
||||||
case TextType.onboardingTitle:
|
|
||||||
style = isDark
|
|
||||||
? onboardingTitle.copyWith(color: Colors.white)
|
|
||||||
: onboardingTitle;
|
|
||||||
break;
|
|
||||||
case TextType.medium:
|
|
||||||
style =
|
|
||||||
isDark ? mediumStyle.copyWith(color: Colors.white) : mediumStyle;
|
|
||||||
break;
|
|
||||||
case TextType.buttonTitleText:
|
|
||||||
style = !isDark
|
|
||||||
? buttonTitleText.copyWith(color: Colors.white)
|
|
||||||
: buttonTitleText;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (this.style != null) {
|
|
||||||
style = style.merge(this.style);
|
|
||||||
}
|
|
||||||
return Text(
|
|
||||||
text!,
|
|
||||||
style: style,
|
|
||||||
maxLines: maxLines,
|
|
||||||
overflow: overflow,
|
|
||||||
softWrap: softWrap,
|
|
||||||
textAlign: textAlign,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,7 +2,6 @@ import 'dart:async';
|
||||||
|
|
||||||
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/ui/components/brand_text/brand_text.dart';
|
|
||||||
import 'package:selfprivacy/utils/named_font_weight.dart';
|
import 'package:selfprivacy/utils/named_font_weight.dart';
|
||||||
|
|
||||||
class BrandTimer extends StatefulWidget {
|
class BrandTimer extends StatefulWidget {
|
||||||
|
@ -52,11 +51,12 @@ class _BrandTimerState extends State<BrandTimer> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(final BuildContext context) => BrandText.medium(
|
Widget build(final BuildContext context) => Text(
|
||||||
_timeString,
|
_timeString ?? '',
|
||||||
style: const TextStyle(
|
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||||
fontWeight: NamedFontWeight.demiBold,
|
fontWeight: NamedFontWeight.demiBold,
|
||||||
),
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
void _getTime() {
|
void _getTime() {
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
|
|
||||||
|
|
||||||
enum BrandButtonTypes { rised, text, iconText }
|
|
||||||
|
|
||||||
class BrandButton {
|
class BrandButton {
|
||||||
static ConstrainedBox rised({
|
static ConstrainedBox rised({
|
||||||
|
@ -58,53 +55,4 @@ class BrandButton {
|
||||||
),
|
),
|
||||||
child: TextButton(onPressed: onPressed, child: Text(title)),
|
child: TextButton(onPressed: onPressed, child: Text(title)),
|
||||||
);
|
);
|
||||||
|
|
||||||
static IconTextButton emptyWithIconText({
|
|
||||||
required final VoidCallback onPressed,
|
|
||||||
required final String title,
|
|
||||||
required final Icon icon,
|
|
||||||
final Key? key,
|
|
||||||
}) =>
|
|
||||||
IconTextButton(
|
|
||||||
key: key,
|
|
||||||
title: title,
|
|
||||||
onPressed: onPressed,
|
|
||||||
icon: icon,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
class IconTextButton extends StatelessWidget {
|
|
||||||
const IconTextButton({
|
|
||||||
super.key,
|
|
||||||
this.onPressed,
|
|
||||||
this.title,
|
|
||||||
this.icon,
|
|
||||||
});
|
|
||||||
|
|
||||||
final VoidCallback? onPressed;
|
|
||||||
final String? title;
|
|
||||||
final Icon? icon;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(final BuildContext context) => Material(
|
|
||||||
color: Colors.transparent,
|
|
||||||
child: InkWell(
|
|
||||||
onTap: onPressed,
|
|
||||||
child: Container(
|
|
||||||
height: 48,
|
|
||||||
width: double.infinity,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
BrandText.body1(title),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(12.0),
|
|
||||||
child: icon,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
|
@ -1,7 +1,8 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class ActionButton extends StatelessWidget {
|
/// Basically a [TextButton] to be used in dialogs
|
||||||
const ActionButton({
|
class DialogActionButton extends StatelessWidget {
|
||||||
|
const DialogActionButton({
|
||||||
super.key,
|
super.key,
|
||||||
this.text,
|
this.text,
|
||||||
this.onPressed,
|
this.onPressed,
|
|
@ -1,6 +1,16 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
/// For some reason original [SegmentedButton] does not have animations.
|
||||||
|
///
|
||||||
|
/// The [SegmentedButtons] was written for SelfPrivacy before [SegmentedButton] was introduced.
|
||||||
|
/// While it doesn't have that much options to pass, it has cute little animation.
|
||||||
|
/// It is based on [ToggleButtons].
|
||||||
class SegmentedButtons extends StatelessWidget {
|
class SegmentedButtons extends StatelessWidget {
|
||||||
|
/// Creates a segmented buttons widget. This is a SelfPrivacy implementation.
|
||||||
|
///
|
||||||
|
/// Provide the button titles in [titles] as a [List<String>].
|
||||||
|
/// Current selection is provided in [isSelected] as a [List<bool>].
|
||||||
|
/// This widget will call [onPressed] with the index of the button that was pressed.
|
||||||
const SegmentedButtons({
|
const SegmentedButtons({
|
||||||
required this.isSelected,
|
required this.isSelected,
|
||||||
required this.onPressed,
|
required this.onPressed,
|
||||||
|
@ -8,15 +18,24 @@ class SegmentedButtons extends StatelessWidget {
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// The current selection state of the buttons.
|
||||||
|
///
|
||||||
|
/// The length of this list must be equal to the length of [titles].
|
||||||
|
/// Several buttons can be selected at the same time.
|
||||||
final List<bool> isSelected;
|
final List<bool> isSelected;
|
||||||
|
|
||||||
|
/// The callback that is called when a button is pressed.
|
||||||
|
/// It will be called with the index of the button that was pressed.
|
||||||
final Function(int)? onPressed;
|
final Function(int)? onPressed;
|
||||||
|
|
||||||
|
/// The titles of the buttons.
|
||||||
final List<String> titles;
|
final List<String> titles;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(final BuildContext context) => LayoutBuilder(
|
Widget build(final BuildContext context) => LayoutBuilder(
|
||||||
builder: (final context, final constraints) => ToggleButtons(
|
builder: (final context, final constraints) => ToggleButtons(
|
||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
minWidth: (constraints.maxWidth - 8) / 3,
|
minWidth: (constraints.maxWidth - 8) / titles.length,
|
||||||
minHeight: 40 + Theme.of(context).visualDensity.vertical * 4,
|
minHeight: 40 + Theme.of(context).visualDensity.vertical * 4,
|
||||||
),
|
),
|
||||||
borderRadius: BorderRadius.circular(48),
|
borderRadius: BorderRadius.circular(48),
|
||||||
|
@ -38,7 +57,7 @@ class SegmentedButtons extends StatelessWidget {
|
||||||
opacity: isSelected[index] ? 1 : 0,
|
opacity: isSelected[index] ? 1 : 0,
|
||||||
child: AnimatedScale(
|
child: AnimatedScale(
|
||||||
duration: const Duration(milliseconds: 200),
|
duration: const Duration(milliseconds: 200),
|
||||||
curve: Curves.easeInOut,
|
curve: Curves.easeInOutCubicEmphasized,
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
scale: isSelected[index] ? 1 : 0,
|
scale: isSelected[index] ? 1 : 0,
|
||||||
child: Icon(
|
child: Icon(
|
||||||
|
@ -53,7 +72,7 @@ class SegmentedButtons extends StatelessWidget {
|
||||||
? const EdgeInsets.only(left: 24)
|
? const EdgeInsets.only(left: 24)
|
||||||
: EdgeInsets.zero,
|
: EdgeInsets.zero,
|
||||||
duration: const Duration(milliseconds: 200),
|
duration: const Duration(milliseconds: 200),
|
||||||
curve: Curves.easeInOut,
|
curve: Curves.easeInOutCubicEmphasized,
|
||||||
child: Text(
|
child: Text(
|
||||||
title,
|
title,
|
||||||
style: Theme.of(context).textTheme.labelLarge,
|
style: Theme.of(context).textTheme.labelLarge,
|
113
lib/ui/components/drawers/progress_drawer.dart
Normal file
113
lib/ui/components/drawers/progress_drawer.dart
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class ProgressDrawer extends StatelessWidget {
|
||||||
|
/// A [Drawer] that displays a list of steps and the current step.
|
||||||
|
/// Used in setup wizards. The [trailing] widget is displayed at the bottom.
|
||||||
|
/// The [steps] are translated using [EasyLocalization].
|
||||||
|
const ProgressDrawer({
|
||||||
|
required this.steps,
|
||||||
|
required this.currentStep,
|
||||||
|
required this.constraints,
|
||||||
|
required this.trailing,
|
||||||
|
required this.title,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final List<String> steps;
|
||||||
|
final int currentStep;
|
||||||
|
final Widget trailing;
|
||||||
|
final BoxConstraints constraints;
|
||||||
|
final String title;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) => SizedBox(
|
||||||
|
width: 300,
|
||||||
|
height: constraints.maxHeight,
|
||||||
|
child: Drawer(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: Text(
|
||||||
|
title,
|
||||||
|
style: Theme.of(context).textTheme.titleLarge,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Flexible(
|
||||||
|
fit: FlexFit.tight,
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
...steps.map((final step) {
|
||||||
|
final index = steps.indexOf(step);
|
||||||
|
return _StepIndicator(
|
||||||
|
title: step.tr(),
|
||||||
|
isCurrent: index == currentStep,
|
||||||
|
isCompleted: index < currentStep,
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// const Spacer(),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: trailing,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class _StepIndicator extends StatelessWidget {
|
||||||
|
const _StepIndicator({
|
||||||
|
required this.title,
|
||||||
|
required this.isCompleted,
|
||||||
|
required this.isCurrent,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String title;
|
||||||
|
final bool isCompleted;
|
||||||
|
final bool isCurrent;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) => ListTile(
|
||||||
|
selected: isCurrent,
|
||||||
|
leading: isCurrent
|
||||||
|
? const _StepCurrentIcon()
|
||||||
|
: isCompleted
|
||||||
|
? const _StepCompletedIcon()
|
||||||
|
: const _StepPendingIcon(),
|
||||||
|
title: Text(
|
||||||
|
title,
|
||||||
|
),
|
||||||
|
textColor: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
|
iconColor: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class _StepCompletedIcon extends StatelessWidget {
|
||||||
|
const _StepCompletedIcon();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) => const Icon(Icons.check_circle);
|
||||||
|
}
|
||||||
|
|
||||||
|
class _StepPendingIcon extends StatelessWidget {
|
||||||
|
const _StepPendingIcon();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) => const Icon(Icons.circle_outlined);
|
||||||
|
}
|
||||||
|
|
||||||
|
class _StepCurrentIcon extends StatelessWidget {
|
||||||
|
const _StepCurrentIcon();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) =>
|
||||||
|
const Icon(Icons.build_circle_outlined);
|
||||||
|
}
|
52
lib/ui/components/drawers/support_drawer.dart
Normal file
52
lib/ui/components/drawers/support_drawer.dart
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:selfprivacy/logic/cubit/support_system/support_system_cubit.dart';
|
||||||
|
import 'package:selfprivacy/ui/components/brand_md/brand_md.dart';
|
||||||
|
|
||||||
|
class SupportDrawer extends StatelessWidget {
|
||||||
|
const SupportDrawer({
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) {
|
||||||
|
final currentArticle =
|
||||||
|
context.watch<SupportSystemCubit>().state.currentArticle;
|
||||||
|
return Drawer(
|
||||||
|
width: 440,
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
const Icon(Icons.help_outline),
|
||||||
|
const SizedBox(width: 16),
|
||||||
|
Text(
|
||||||
|
'support.title'.tr(),
|
||||||
|
style: Theme.of(context).textTheme.titleLarge,
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () => Scaffold.of(context).closeEndDrawer(),
|
||||||
|
icon: const Icon(Icons.chevron_right_outlined),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: BrandMarkdown(
|
||||||
|
fileName: currentArticle,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,26 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class BrandError extends StatelessWidget {
|
|
||||||
const BrandError({super.key, this.error, this.stackTrace});
|
|
||||||
|
|
||||||
final Object? error;
|
|
||||||
final StackTrace? stackTrace;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(final BuildContext context) => SafeArea(
|
|
||||||
child: Scaffold(
|
|
||||||
body: Center(
|
|
||||||
child: SingleChildScrollView(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Text(error.toString()),
|
|
||||||
const Text('stackTrace: '),
|
|
||||||
Text(stackTrace.toString()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -6,10 +6,8 @@ import 'package:selfprivacy/logic/cubit/client_jobs/client_jobs_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_jobs/server_jobs_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/models/json/server_job.dart';
|
import 'package:selfprivacy/logic/models/json/server_job.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_cards/brand_cards.dart';
|
|
||||||
import 'package:selfprivacy/ui/components/brand_loader/brand_loader.dart';
|
import 'package:selfprivacy/ui/components/brand_loader/brand_loader.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
|
|
||||||
import 'package:selfprivacy/ui/components/jobs_content/server_job_card.dart';
|
import 'package:selfprivacy/ui/components/jobs_content/server_job_card.dart';
|
||||||
import 'package:selfprivacy/ui/helpers/modals.dart';
|
import 'package:selfprivacy/ui/helpers/modals.dart';
|
||||||
|
|
||||||
|
@ -32,7 +30,12 @@ class JobsContent extends StatelessWidget {
|
||||||
if (state is JobsStateEmpty) {
|
if (state is JobsStateEmpty) {
|
||||||
widgets = [
|
widgets = [
|
||||||
const SizedBox(height: 80),
|
const SizedBox(height: 80),
|
||||||
Center(child: BrandText.body1('jobs.empty'.tr())),
|
Center(
|
||||||
|
child: Text(
|
||||||
|
'jobs.empty'.tr(),
|
||||||
|
style: Theme.of(context).textTheme.bodyLarge,
|
||||||
|
),
|
||||||
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
if (installationState is ServerInstallationFinished) {
|
if (installationState is ServerInstallationFinished) {
|
||||||
|
@ -65,38 +68,49 @@ class JobsContent extends StatelessWidget {
|
||||||
];
|
];
|
||||||
} else if (state is JobsStateWithJobs) {
|
} else if (state is JobsStateWithJobs) {
|
||||||
widgets = [
|
widgets = [
|
||||||
...state.clientJobList
|
...state.clientJobList.map(
|
||||||
.map(
|
(final j) => Row(
|
||||||
(final j) => Row(
|
children: [
|
||||||
children: [
|
Expanded(
|
||||||
Expanded(
|
child: Card(
|
||||||
child: BrandCards.small(
|
color: Theme.of(context).colorScheme.surfaceVariant,
|
||||||
child: Text(j.title),
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 15,
|
||||||
|
vertical: 10,
|
||||||
),
|
),
|
||||||
),
|
|
||||||
const SizedBox(width: 10),
|
|
||||||
ElevatedButton(
|
|
||||||
style: ElevatedButton.styleFrom(
|
|
||||||
backgroundColor:
|
|
||||||
Theme.of(context).colorScheme.errorContainer,
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onPressed: () =>
|
|
||||||
context.read<JobsCubit>().removeJob(j.id),
|
|
||||||
child: Text(
|
child: Text(
|
||||||
'basis.remove'.tr(),
|
j.title,
|
||||||
style: TextStyle(
|
style:
|
||||||
color:
|
Theme.of(context).textTheme.labelLarge?.copyWith(
|
||||||
Theme.of(context).colorScheme.onErrorContainer,
|
color: Theme.of(context)
|
||||||
),
|
.colorScheme
|
||||||
|
.onSurfaceVariant,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
)
|
const SizedBox(width: 10),
|
||||||
.toList(),
|
ElevatedButton(
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor:
|
||||||
|
Theme.of(context).colorScheme.errorContainer,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onPressed: () => context.read<JobsCubit>().removeJob(j.id),
|
||||||
|
child: Text(
|
||||||
|
'basis.remove'.tr(),
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.onErrorContainer,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
BrandButton.rised(
|
BrandButton.rised(
|
||||||
onPressed: () => context.read<JobsCubit>().applyAll(),
|
onPressed: () => context.read<JobsCubit>().applyAll(),
|
||||||
|
@ -109,8 +123,9 @@ class JobsContent extends StatelessWidget {
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(height: 15),
|
const SizedBox(height: 15),
|
||||||
Center(
|
Center(
|
||||||
child: BrandText.h2(
|
child: Text(
|
||||||
'jobs.title'.tr(),
|
'jobs.title'.tr(),
|
||||||
|
style: Theme.of(context).textTheme.headlineSmall,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
|
|
300
lib/ui/components/list_tiles/log_list_tile.dart
Normal file
300
lib/ui/components/list_tiles/log_list_tile.dart
Normal file
|
@ -0,0 +1,300 @@
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:selfprivacy/logic/models/message.dart';
|
||||||
|
|
||||||
|
class LogListItem extends StatelessWidget {
|
||||||
|
const LogListItem({
|
||||||
|
required this.message,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final Message message;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) {
|
||||||
|
final messageItem = message;
|
||||||
|
if (messageItem is RestApiRequestMessage) {
|
||||||
|
return _RestApiRequestMessageItem(message: messageItem);
|
||||||
|
} else if (messageItem is RestApiResponseMessage) {
|
||||||
|
return _RestApiResponseMessageItem(message: messageItem);
|
||||||
|
} else if (messageItem is GraphQlResponseMessage) {
|
||||||
|
return _GraphQlResponseMessageItem(message: messageItem);
|
||||||
|
} else if (messageItem is GraphQlRequestMessage) {
|
||||||
|
return _GraphQlRequestMessageItem(message: messageItem);
|
||||||
|
} else {
|
||||||
|
return _DefaultMessageItem(message: messageItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _RestApiRequestMessageItem extends StatelessWidget {
|
||||||
|
const _RestApiRequestMessageItem({required this.message});
|
||||||
|
|
||||||
|
final RestApiRequestMessage message;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) => ListTile(
|
||||||
|
title: Text(
|
||||||
|
'${message.method}\n${message.uri}',
|
||||||
|
),
|
||||||
|
subtitle: Text(message.timeString),
|
||||||
|
leading: const Icon(Icons.upload_outlined),
|
||||||
|
iconColor: Theme.of(context).colorScheme.secondary,
|
||||||
|
onTap: () => showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (final BuildContext context) => AlertDialog(
|
||||||
|
scrollable: true,
|
||||||
|
title: Text(
|
||||||
|
'${message.method}\n${message.uri}',
|
||||||
|
),
|
||||||
|
content: Column(
|
||||||
|
children: [
|
||||||
|
Text(message.timeString),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
// Headers is a map of key-value pairs
|
||||||
|
if (message.headers != null) const Text('Headers'),
|
||||||
|
if (message.headers != null)
|
||||||
|
Text(
|
||||||
|
message.headers!.entries
|
||||||
|
.map((final entry) => '${entry.key}: ${entry.value}')
|
||||||
|
.join('\n'),
|
||||||
|
),
|
||||||
|
if (message.data != null && message.data != 'null')
|
||||||
|
const Text('Data'),
|
||||||
|
if (message.data != null && message.data != 'null')
|
||||||
|
Text(message.data!),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
// A button to copy the request to the clipboard
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
Clipboard.setData(ClipboardData(text: message.text));
|
||||||
|
},
|
||||||
|
child: Text('console_page.copy'.tr()),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
child: Text('basis.close'.tr()),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class _RestApiResponseMessageItem extends StatelessWidget {
|
||||||
|
const _RestApiResponseMessageItem({required this.message});
|
||||||
|
|
||||||
|
final RestApiResponseMessage message;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) => ListTile(
|
||||||
|
title: Text(
|
||||||
|
'${message.statusCode} ${message.method}\n${message.uri}',
|
||||||
|
),
|
||||||
|
subtitle: Text(message.timeString),
|
||||||
|
leading: const Icon(Icons.download_outlined),
|
||||||
|
iconColor: Theme.of(context).colorScheme.primary,
|
||||||
|
onTap: () => showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (final BuildContext context) => AlertDialog(
|
||||||
|
scrollable: true,
|
||||||
|
title: Text(
|
||||||
|
'${message.statusCode} ${message.method}\n${message.uri}',
|
||||||
|
),
|
||||||
|
content: Column(
|
||||||
|
children: [
|
||||||
|
Text(message.timeString),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
// Headers is a map of key-value pairs
|
||||||
|
if (message.data != null && message.data != 'null')
|
||||||
|
const Text('Data'),
|
||||||
|
if (message.data != null && message.data != 'null')
|
||||||
|
Text(message.data!),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
// A button to copy the request to the clipboard
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
Clipboard.setData(ClipboardData(text: message.text));
|
||||||
|
},
|
||||||
|
child: Text('console_page.copy'.tr()),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
child: Text('basis.close'.tr()),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class _GraphQlResponseMessageItem extends StatelessWidget {
|
||||||
|
const _GraphQlResponseMessageItem({required this.message});
|
||||||
|
|
||||||
|
final GraphQlResponseMessage message;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) => ListTile(
|
||||||
|
title: Text(
|
||||||
|
'GraphQL Response at ${message.timeString}',
|
||||||
|
),
|
||||||
|
subtitle: Text(
|
||||||
|
message.data.toString(),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 1,
|
||||||
|
),
|
||||||
|
leading: const Icon(Icons.arrow_circle_down_outlined),
|
||||||
|
iconColor: Theme.of(context).colorScheme.tertiary,
|
||||||
|
onTap: () => showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (final BuildContext context) => AlertDialog(
|
||||||
|
scrollable: true,
|
||||||
|
title: Text(
|
||||||
|
'GraphQL Response at ${message.timeString}',
|
||||||
|
),
|
||||||
|
content: Column(
|
||||||
|
children: [
|
||||||
|
Text(message.timeString),
|
||||||
|
const Divider(),
|
||||||
|
if (message.data != null) const Text('Data'),
|
||||||
|
// Data is a map of key-value pairs
|
||||||
|
if (message.data != null)
|
||||||
|
Text(
|
||||||
|
message.data!.entries
|
||||||
|
.map((final entry) => '${entry.key}: ${entry.value}')
|
||||||
|
.join('\n'),
|
||||||
|
),
|
||||||
|
const Divider(),
|
||||||
|
if (message.errors != null) const Text('Errors'),
|
||||||
|
if (message.errors != null)
|
||||||
|
Text(
|
||||||
|
message.errors!
|
||||||
|
.map(
|
||||||
|
(final entry) =>
|
||||||
|
'${entry.message} at ${entry.locations}',
|
||||||
|
)
|
||||||
|
.join('\n'),
|
||||||
|
),
|
||||||
|
const Divider(),
|
||||||
|
if (message.context != null) const Text('Context'),
|
||||||
|
if (message.context != null)
|
||||||
|
Text(
|
||||||
|
message.context!.toString(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
// A button to copy the request to the clipboard
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
Clipboard.setData(ClipboardData(text: message.text));
|
||||||
|
},
|
||||||
|
child: Text('console_page.copy'.tr()),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
child: Text('basis.close'.tr()),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class _GraphQlRequestMessageItem extends StatelessWidget {
|
||||||
|
const _GraphQlRequestMessageItem({required this.message});
|
||||||
|
|
||||||
|
final GraphQlRequestMessage message;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) => ListTile(
|
||||||
|
title: Text(
|
||||||
|
'GraphQL Request at ${message.timeString}',
|
||||||
|
),
|
||||||
|
subtitle: Text(
|
||||||
|
message.operation.toString(),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 1,
|
||||||
|
),
|
||||||
|
leading: const Icon(Icons.arrow_circle_up_outlined),
|
||||||
|
iconColor: Theme.of(context).colorScheme.secondary,
|
||||||
|
onTap: () => showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (final BuildContext context) => AlertDialog(
|
||||||
|
scrollable: true,
|
||||||
|
title: Text(
|
||||||
|
'GraphQL Response at ${message.timeString}',
|
||||||
|
),
|
||||||
|
content: Column(
|
||||||
|
children: [
|
||||||
|
Text(message.timeString),
|
||||||
|
const Divider(),
|
||||||
|
if (message.operation != null) const Text('Operation'),
|
||||||
|
// Data is a map of key-value pairs
|
||||||
|
if (message.operation != null)
|
||||||
|
Text(
|
||||||
|
message.operation!.toString(),
|
||||||
|
),
|
||||||
|
const Divider(),
|
||||||
|
if (message.variables != null) const Text('Variables'),
|
||||||
|
if (message.variables != null)
|
||||||
|
Text(
|
||||||
|
message.variables!.entries
|
||||||
|
.map((final entry) => '${entry.key}: ${entry.value}')
|
||||||
|
.join('\n'),
|
||||||
|
),
|
||||||
|
const Divider(),
|
||||||
|
if (message.context != null) const Text('Context'),
|
||||||
|
if (message.context != null)
|
||||||
|
Text(
|
||||||
|
message.context!.toString(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
// A button to copy the request to the clipboard
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
Clipboard.setData(ClipboardData(text: message.text));
|
||||||
|
},
|
||||||
|
child: Text('console_page.copy'.tr()),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
child: Text('basis.close'.tr()),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DefaultMessageItem extends StatelessWidget {
|
||||||
|
const _DefaultMessageItem({required this.message});
|
||||||
|
|
||||||
|
final Message message;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) => Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 4),
|
||||||
|
child: RichText(
|
||||||
|
text: TextSpan(
|
||||||
|
style: DefaultTextStyle.of(context).style,
|
||||||
|
children: <TextSpan>[
|
||||||
|
TextSpan(
|
||||||
|
text: '${message.timeString}: \n',
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextSpan(text: message.text),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_cards/filled_card.dart';
|
import 'package:selfprivacy/ui/components/cards/filled_card.dart';
|
||||||
import 'package:selfprivacy/ui/pages/setup/initializing/initializing.dart';
|
import 'package:selfprivacy/ui/router/router.dart';
|
||||||
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
|
||||||
class NotReadyCard extends StatelessWidget {
|
class NotReadyCard extends StatelessWidget {
|
||||||
|
@ -13,11 +13,7 @@ class NotReadyCard extends StatelessWidget {
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
contentPadding:
|
contentPadding:
|
||||||
const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||||
onTap: () => Navigator.of(context).push(
|
onTap: () => context.pushRoute(const InitializingRoute()),
|
||||||
materialRoute(
|
|
||||||
const InitializingPage(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
title: Text(
|
title: Text(
|
||||||
'not_ready_card.in_menu'.tr(),
|
'not_ready_card.in_menu'.tr(),
|
||||||
style: Theme.of(context).textTheme.titleSmall?.copyWith(
|
style: Theme.of(context).textTheme.titleSmall?.copyWith(
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:ionicons/ionicons.dart';
|
import 'package:ionicons/ionicons.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/client_jobs/client_jobs_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/client_jobs/client_jobs_cubit.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart';
|
|
||||||
import 'package:selfprivacy/ui/components/jobs_content/jobs_content.dart';
|
import 'package:selfprivacy/ui/components/jobs_content/jobs_content.dart';
|
||||||
import 'package:selfprivacy/ui/helpers/modals.dart';
|
|
||||||
|
|
||||||
class BrandFab extends StatefulWidget {
|
class BrandFab extends StatefulWidget {
|
||||||
const BrandFab({super.key});
|
const BrandFab({
|
||||||
|
this.extended = false,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final bool extended;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<BrandFab> createState() => _BrandFabState();
|
State<BrandFab> createState() => _BrandFabState();
|
||||||
|
@ -56,28 +60,40 @@ class _BrandFabState extends State<BrandFab>
|
||||||
child: FloatingActionButton(
|
child: FloatingActionButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// TODO: Make a hero animation to the screen
|
// TODO: Make a hero animation to the screen
|
||||||
showBrandBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (final BuildContext context) => const BrandBottomSheet(
|
builder: (final BuildContext context) => const JobsContent(),
|
||||||
isExpended: true,
|
|
||||||
child: JobsContent(),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: AnimatedBuilder(
|
isExtended: widget.extended,
|
||||||
animation: _colorTween,
|
child: Row(
|
||||||
builder: (final BuildContext context, final Widget? child) {
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
final double v = _animationController.value;
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
final IconData icon =
|
children: [
|
||||||
v > 0.5 ? Ionicons.flash : Ionicons.flash_outline;
|
AnimatedBuilder(
|
||||||
return Transform.scale(
|
animation: _colorTween,
|
||||||
scale: 1 + (v < 0.5 ? v : 1 - v) * 2,
|
builder: (final BuildContext context, final Widget? child) {
|
||||||
child: Icon(
|
final double v = _animationController.value;
|
||||||
icon,
|
final IconData icon =
|
||||||
color: _colorTween.value,
|
v > 0.5 ? Ionicons.flash : Ionicons.flash_outline;
|
||||||
|
return Transform.scale(
|
||||||
|
scale: 1 + (v < 0.5 ? v : 1 - v) * 2,
|
||||||
|
child: Icon(
|
||||||
|
icon,
|
||||||
|
color: _colorTween.value,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
if (widget.extended)
|
||||||
|
const SizedBox(
|
||||||
|
width: 8,
|
||||||
),
|
),
|
||||||
);
|
if (widget.extended)
|
||||||
},
|
Text(
|
||||||
|
'jobs.title'.tr(),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
import 'package:flutter/material.dart';
|
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/logic/cubit/app_settings/app_settings_cubit.dart';
|
||||||
|
|
||||||
class ProgressBar extends StatefulWidget {
|
class ProgressBar extends StatefulWidget {
|
||||||
|
@ -65,7 +63,7 @@ class _ProgressBarState extends State<ProgressBar> {
|
||||||
Container(
|
Container(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: BrandColors.gray4,
|
color: const Color(0xFFDDDDDD),
|
||||||
borderRadius: BorderRadius.circular(5),
|
borderRadius: BorderRadius.circular(5),
|
||||||
),
|
),
|
||||||
child: LayoutBuilder(
|
child: LayoutBuilder(
|
||||||
|
@ -119,3 +117,13 @@ class _ProgressBarState extends State<ProgressBar> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TextStyle progressTextStyleLight = TextStyle(
|
||||||
|
fontSize: 11,
|
||||||
|
color: Colors.black,
|
||||||
|
height: 1.7,
|
||||||
|
);
|
||||||
|
|
||||||
|
final TextStyle progressTextStyleDark = progressTextStyleLight.copyWith(
|
||||||
|
color: Colors.white,
|
||||||
|
);
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:selfprivacy/config/brand_colors.dart';
|
|
||||||
|
|
||||||
// TODO: Delete this file.
|
|
||||||
|
|
||||||
class SwitcherBlock extends StatelessWidget {
|
|
||||||
const SwitcherBlock({
|
|
||||||
required this.child,
|
|
||||||
required this.isActive,
|
|
||||||
required this.onChange,
|
|
||||||
super.key,
|
|
||||||
});
|
|
||||||
|
|
||||||
final Widget child;
|
|
||||||
final bool isActive;
|
|
||||||
final ValueChanged<bool> onChange;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(final BuildContext context) => Container(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
|
||||||
child: Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Flexible(child: child),
|
|
||||||
const SizedBox(width: 5),
|
|
||||||
Switch(
|
|
||||||
activeColor: BrandColors.green1,
|
|
||||||
activeTrackColor: BrandColors.green2,
|
|
||||||
onChanged: onChange,
|
|
||||||
value: isActive,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,21 +1,7 @@
|
||||||
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:modal_bottom_sheet/modal_bottom_sheet.dart';
|
|
||||||
import 'package:selfprivacy/config/get_it_config.dart';
|
import 'package:selfprivacy/config/get_it_config.dart';
|
||||||
import 'package:selfprivacy/ui/components/action_button/action_button.dart';
|
import 'package:selfprivacy/ui/components/buttons/dialog_action_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_alert/brand_alert.dart';
|
|
||||||
|
|
||||||
Future<T?> showBrandBottomSheet<T>({
|
|
||||||
required final BuildContext context,
|
|
||||||
required final WidgetBuilder builder,
|
|
||||||
}) =>
|
|
||||||
showCupertinoModalBottomSheet<T>(
|
|
||||||
builder: builder,
|
|
||||||
barrierColor: Colors.black45,
|
|
||||||
context: context,
|
|
||||||
shadow: const BoxShadow(color: Colors.transparent),
|
|
||||||
backgroundColor: Colors.transparent,
|
|
||||||
);
|
|
||||||
|
|
||||||
void showPopUpAlert({
|
void showPopUpAlert({
|
||||||
required final String description,
|
required final String description,
|
||||||
|
@ -26,16 +12,16 @@ void showPopUpAlert({
|
||||||
final String? cancelButtonTitle,
|
final String? cancelButtonTitle,
|
||||||
}) {
|
}) {
|
||||||
getIt.get<NavigationService>().showPopUpDialog(
|
getIt.get<NavigationService>().showPopUpDialog(
|
||||||
BrandAlert(
|
AlertDialog(
|
||||||
title: alertTitle ?? 'basis.alert'.tr(),
|
title: Text(alertTitle ?? 'basis.alert'.tr()),
|
||||||
contentText: description,
|
content: Text(description),
|
||||||
actions: [
|
actions: [
|
||||||
ActionButton(
|
DialogActionButton(
|
||||||
text: actionButtonTitle,
|
text: actionButtonTitle,
|
||||||
isRed: true,
|
isRed: true,
|
||||||
onPressed: actionButtonOnPressed,
|
onPressed: actionButtonOnPressed,
|
||||||
),
|
),
|
||||||
ActionButton(
|
DialogActionButton(
|
||||||
text: cancelButtonTitle ?? 'basis.cancel'.tr(),
|
text: cancelButtonTitle ?? 'basis.cancel'.tr(),
|
||||||
onPressed: cancelButtonOnPressed,
|
onPressed: cancelButtonOnPressed,
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,14 +1,26 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/scheduler.dart';
|
import 'package:flutter/scheduler.dart';
|
||||||
|
|
||||||
|
/// A helper widget that calls a callback when its size changes.
|
||||||
|
///
|
||||||
|
/// This is useful when you want to know the size of a widget, and use it in
|
||||||
|
/// another leaf of the tree.
|
||||||
|
///
|
||||||
|
/// The [onChange] callback is called after the widget is rendered, and the
|
||||||
|
/// size of the widget is different from the previous render.
|
||||||
class WidgetSize extends StatefulWidget {
|
class WidgetSize extends StatefulWidget {
|
||||||
|
/// Creates a helper widget that calls a callback when its size changes.
|
||||||
const WidgetSize({
|
const WidgetSize({
|
||||||
required this.onChange,
|
required this.onChange,
|
||||||
required this.child,
|
required this.child,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/// The child widget, the size of which is to be measured.
|
||||||
final Widget child;
|
final Widget child;
|
||||||
final Function onChange;
|
|
||||||
|
/// The callback to be called when the size of the widget changes.
|
||||||
|
final Function(Size) onChange;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<WidgetSize> createState() => _WidgetSizeState();
|
State<WidgetSize> createState() => _WidgetSizeState();
|
||||||
|
@ -34,6 +46,11 @@ class _WidgetSizeState extends State<WidgetSize> {
|
||||||
}
|
}
|
||||||
|
|
||||||
final newSize = context.size;
|
final newSize = context.size;
|
||||||
|
|
||||||
|
if (newSize == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (oldSize == newSize) {
|
if (oldSize == newSize) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
195
lib/ui/layouts/brand_hero_screen.dart
Normal file
195
lib/ui/layouts/brand_hero_screen.dart
Normal file
|
@ -0,0 +1,195 @@
|
||||||
|
import 'package:auto_route/auto_route.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:ionicons/ionicons.dart';
|
||||||
|
import 'package:selfprivacy/logic/cubit/client_jobs/client_jobs_cubit.dart';
|
||||||
|
import 'package:selfprivacy/ui/components/jobs_content/jobs_content.dart';
|
||||||
|
import 'package:selfprivacy/ui/components/drawers/support_drawer.dart';
|
||||||
|
import 'package:selfprivacy/ui/helpers/widget_size.dart';
|
||||||
|
import 'package:selfprivacy/utils/breakpoints.dart';
|
||||||
|
|
||||||
|
class BrandHeroScreen extends StatelessWidget {
|
||||||
|
const BrandHeroScreen({
|
||||||
|
required this.children,
|
||||||
|
super.key,
|
||||||
|
this.hasBackButton = true,
|
||||||
|
this.hasFlashButton = false,
|
||||||
|
this.heroIcon,
|
||||||
|
this.heroIconWidget,
|
||||||
|
this.heroTitle = '',
|
||||||
|
this.heroSubtitle,
|
||||||
|
this.onBackButtonPressed,
|
||||||
|
this.bodyPadding = const EdgeInsets.all(16.0),
|
||||||
|
this.ignoreBreakpoints = false,
|
||||||
|
this.hasSupportDrawer = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
final List<Widget> children;
|
||||||
|
final bool hasBackButton;
|
||||||
|
final bool hasFlashButton;
|
||||||
|
final IconData? heroIcon;
|
||||||
|
final Widget? heroIconWidget;
|
||||||
|
final String heroTitle;
|
||||||
|
final String? heroSubtitle;
|
||||||
|
final VoidCallback? onBackButtonPressed;
|
||||||
|
final EdgeInsetsGeometry bodyPadding;
|
||||||
|
|
||||||
|
/// On non-mobile screens the buttons of the app bar are hidden.
|
||||||
|
/// This is because this widget implies that it is nested inside a bigger layout.
|
||||||
|
/// If it is not nested, set this to true.
|
||||||
|
final bool ignoreBreakpoints;
|
||||||
|
|
||||||
|
/// Usually support drawer is provided by the parent layout.
|
||||||
|
/// If it is not provided, set this to true.
|
||||||
|
final bool hasSupportDrawer;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) {
|
||||||
|
final Widget heroIconWidget = this.heroIconWidget ??
|
||||||
|
Icon(
|
||||||
|
heroIcon ?? Icons.help,
|
||||||
|
size: 48.0,
|
||||||
|
color: Theme.of(context).colorScheme.onBackground,
|
||||||
|
);
|
||||||
|
final bool hasHeroIcon = heroIcon != null || this.heroIconWidget != null;
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
endDrawerEnableOpenDragGesture: false,
|
||||||
|
endDrawer: hasSupportDrawer ? const SupportDrawer() : null,
|
||||||
|
body: CustomScrollView(
|
||||||
|
slivers: [
|
||||||
|
HeroSliverAppBar(
|
||||||
|
heroTitle: heroTitle,
|
||||||
|
hasHeroIcon: hasHeroIcon,
|
||||||
|
hasBackButton: hasBackButton,
|
||||||
|
onBackButtonPressed: onBackButtonPressed,
|
||||||
|
heroIconWidget: heroIconWidget,
|
||||||
|
hasFlashButton: hasFlashButton,
|
||||||
|
ignoreBreakpoints: ignoreBreakpoints,
|
||||||
|
),
|
||||||
|
if (heroSubtitle != null)
|
||||||
|
SliverPadding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 16.0,
|
||||||
|
vertical: 4.0,
|
||||||
|
),
|
||||||
|
sliver: SliverList(
|
||||||
|
delegate: SliverChildListDelegate([
|
||||||
|
Text(
|
||||||
|
heroSubtitle!,
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||||
|
color: Theme.of(context).colorScheme.onBackground,
|
||||||
|
),
|
||||||
|
textAlign: hasHeroIcon ? TextAlign.center : TextAlign.start,
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SliverPadding(
|
||||||
|
padding: bodyPadding,
|
||||||
|
sliver: SliverList(
|
||||||
|
delegate: SliverChildListDelegate(children),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HeroSliverAppBar extends StatefulWidget {
|
||||||
|
const HeroSliverAppBar({
|
||||||
|
required this.heroTitle,
|
||||||
|
required this.hasHeroIcon,
|
||||||
|
required this.hasBackButton,
|
||||||
|
required this.onBackButtonPressed,
|
||||||
|
required this.heroIconWidget,
|
||||||
|
required this.hasFlashButton,
|
||||||
|
required this.ignoreBreakpoints,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String heroTitle;
|
||||||
|
final bool hasHeroIcon;
|
||||||
|
final bool hasBackButton;
|
||||||
|
final bool hasFlashButton;
|
||||||
|
final VoidCallback? onBackButtonPressed;
|
||||||
|
final Widget heroIconWidget;
|
||||||
|
final bool ignoreBreakpoints;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<HeroSliverAppBar> createState() => _HeroSliverAppBarState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _HeroSliverAppBarState extends State<HeroSliverAppBar> {
|
||||||
|
Size _size = Size.zero;
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) {
|
||||||
|
final isMobile =
|
||||||
|
widget.ignoreBreakpoints ? true : Breakpoints.small.isActive(context);
|
||||||
|
final isJobsListEmpty = context.watch<JobsCubit>().state is JobsStateEmpty;
|
||||||
|
return SliverAppBar(
|
||||||
|
expandedHeight:
|
||||||
|
widget.hasHeroIcon ? 148.0 + _size.height : 72.0 + _size.height,
|
||||||
|
primary: true,
|
||||||
|
pinned: isMobile,
|
||||||
|
stretch: true,
|
||||||
|
surfaceTintColor: isMobile ? null : Colors.transparent,
|
||||||
|
leading: (widget.hasBackButton && isMobile)
|
||||||
|
? const AutoLeadingButton()
|
||||||
|
: const SizedBox.shrink(),
|
||||||
|
actions: [
|
||||||
|
if (widget.hasFlashButton && isMobile)
|
||||||
|
AnimatedSwitcher(
|
||||||
|
duration: const Duration(milliseconds: 300),
|
||||||
|
child: IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
builder: (final BuildContext context) => const JobsContent(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
icon: Icon(
|
||||||
|
isJobsListEmpty ? Ionicons.flash_outline : Ionicons.flash,
|
||||||
|
),
|
||||||
|
color: isJobsListEmpty
|
||||||
|
? Theme.of(context).colorScheme.onBackground
|
||||||
|
: Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox.shrink(),
|
||||||
|
],
|
||||||
|
flexibleSpace: FlexibleSpaceBar(
|
||||||
|
title: LayoutBuilder(
|
||||||
|
builder: (final context, final constraints) => SizedBox(
|
||||||
|
width: constraints.maxWidth - 72.0,
|
||||||
|
child: WidgetSize(
|
||||||
|
onChange: (final Size size) => setState(() => _size = size),
|
||||||
|
child: Text(
|
||||||
|
widget.heroTitle,
|
||||||
|
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||||
|
color: Theme.of(context).colorScheme.onSurface,
|
||||||
|
),
|
||||||
|
overflow: TextOverflow.fade,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
expandedTitleScale: 1.2,
|
||||||
|
centerTitle: true,
|
||||||
|
collapseMode: CollapseMode.pin,
|
||||||
|
titlePadding: const EdgeInsets.only(
|
||||||
|
bottom: 12.0,
|
||||||
|
top: 16.0,
|
||||||
|
),
|
||||||
|
background: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 72.0),
|
||||||
|
if (widget.hasHeroIcon) widget.heroIconWidget,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
70
lib/ui/layouts/responsive_layout_with_infobox.dart
Normal file
70
lib/ui/layouts/responsive_layout_with_infobox.dart
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:selfprivacy/utils/breakpoints.dart';
|
||||||
|
|
||||||
|
class ResponsiveLayoutWithInfobox extends StatelessWidget {
|
||||||
|
const ResponsiveLayoutWithInfobox({
|
||||||
|
required this.primaryColumn,
|
||||||
|
this.topChild,
|
||||||
|
this.secondaryColumn,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final Widget? topChild;
|
||||||
|
final Widget primaryColumn;
|
||||||
|
final Widget? secondaryColumn;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) {
|
||||||
|
final hasSecondaryColumn = secondaryColumn != null;
|
||||||
|
final hasTopChild = topChild != null;
|
||||||
|
|
||||||
|
if (Breakpoints.large.isActive(context)) {
|
||||||
|
return LayoutBuilder(
|
||||||
|
builder: (final context, final constraints) => Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
if (hasTopChild)
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
width: constraints.maxWidth * 0.9,
|
||||||
|
child: topChild,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (hasTopChild) const SizedBox(height: 16),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
width: hasSecondaryColumn
|
||||||
|
? constraints.maxWidth * 0.7
|
||||||
|
: constraints.maxWidth * 0.9,
|
||||||
|
child: primaryColumn,
|
||||||
|
),
|
||||||
|
if (hasSecondaryColumn) const SizedBox(width: 16),
|
||||||
|
if (hasSecondaryColumn)
|
||||||
|
SizedBox(
|
||||||
|
width: constraints.maxWidth * 0.2,
|
||||||
|
child: secondaryColumn,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
if (hasTopChild) topChild!,
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
primaryColumn,
|
||||||
|
const SizedBox(height: 32),
|
||||||
|
if (hasSecondaryColumn) secondaryColumn!,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
277
lib/ui/layouts/root_scaffold_with_navigation.dart
Normal file
277
lib/ui/layouts/root_scaffold_with_navigation.dart
Normal file
|
@ -0,0 +1,277 @@
|
||||||
|
import 'package:auto_route/auto_route.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:selfprivacy/ui/components/pre_styled_buttons/flash_fab.dart';
|
||||||
|
import 'package:selfprivacy/ui/components/drawers/support_drawer.dart';
|
||||||
|
import 'package:selfprivacy/ui/router/root_destinations.dart';
|
||||||
|
import 'package:selfprivacy/utils/breakpoints.dart';
|
||||||
|
|
||||||
|
class RootScaffoldWithNavigation extends StatelessWidget {
|
||||||
|
const RootScaffoldWithNavigation({
|
||||||
|
required this.child,
|
||||||
|
required this.title,
|
||||||
|
required this.destinations,
|
||||||
|
this.showBottomBar = true,
|
||||||
|
this.showFab = true,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final Widget child;
|
||||||
|
final String title;
|
||||||
|
final bool showBottomBar;
|
||||||
|
final List<RouteDestination> destinations;
|
||||||
|
final bool showFab;
|
||||||
|
|
||||||
|
@override
|
||||||
|
// ignore: prefer_expression_function_bodies
|
||||||
|
Widget build(final BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: Breakpoints.mediumAndUp.isActive(context)
|
||||||
|
? PreferredSize(
|
||||||
|
preferredSize: const Size.fromHeight(52),
|
||||||
|
child: _RootAppBar(title: title),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
endDrawer: const SupportDrawer(),
|
||||||
|
endDrawerEnableOpenDragGesture: false,
|
||||||
|
body: Row(
|
||||||
|
children: [
|
||||||
|
if (Breakpoints.medium.isActive(context))
|
||||||
|
_MainScreenNavigationRail(
|
||||||
|
destinations: destinations,
|
||||||
|
showFab: showFab,
|
||||||
|
),
|
||||||
|
if (Breakpoints.large.isActive(context))
|
||||||
|
_MainScreenNavigationDrawer(
|
||||||
|
destinations: destinations,
|
||||||
|
showFab: showFab,
|
||||||
|
),
|
||||||
|
Expanded(child: child),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
bottomNavigationBar: _BottomBar(
|
||||||
|
destinations: destinations,
|
||||||
|
hidden: !(Breakpoints.small.isActive(context) && showBottomBar),
|
||||||
|
key: const Key('bottomBar'),
|
||||||
|
),
|
||||||
|
floatingActionButton:
|
||||||
|
showFab && Breakpoints.small.isActive(context) && showBottomBar
|
||||||
|
? const BrandFab()
|
||||||
|
: null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _RootAppBar extends StatelessWidget {
|
||||||
|
const _RootAppBar({
|
||||||
|
required this.title,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String title;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) => AppBar(
|
||||||
|
title: AnimatedSwitcher(
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
|
transitionBuilder:
|
||||||
|
(final Widget child, final Animation<double> animation) =>
|
||||||
|
SlideTransition(
|
||||||
|
position: animation.drive(
|
||||||
|
Tween<Offset>(
|
||||||
|
begin: const Offset(0.0, 0.2),
|
||||||
|
end: Offset.zero,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: FadeTransition(
|
||||||
|
opacity: animation,
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: SizedBox(
|
||||||
|
key: ValueKey<String>(title),
|
||||||
|
width: double.infinity,
|
||||||
|
child: Text(
|
||||||
|
title,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
leading: context.router.pageCount > 1
|
||||||
|
? IconButton(
|
||||||
|
icon: const Icon(Icons.arrow_back),
|
||||||
|
onPressed: () => context.router.pop(),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
actions: const [
|
||||||
|
SizedBox.shrink(),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MainScreenNavigationRail extends StatelessWidget {
|
||||||
|
const _MainScreenNavigationRail({
|
||||||
|
required this.destinations,
|
||||||
|
this.showFab = true,
|
||||||
|
});
|
||||||
|
|
||||||
|
final List<RouteDestination> destinations;
|
||||||
|
final bool showFab;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) {
|
||||||
|
int? activeIndex = destinations.indexWhere(
|
||||||
|
(final destination) =>
|
||||||
|
context.router.isRouteActive(destination.route.routeName),
|
||||||
|
);
|
||||||
|
|
||||||
|
final prevActiveIndex = destinations.indexWhere(
|
||||||
|
(final destination) => context.router.stack
|
||||||
|
.any((final route) => route.name == destination.route.routeName),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (activeIndex == -1) {
|
||||||
|
if (prevActiveIndex != -1) {
|
||||||
|
activeIndex = prevActiveIndex;
|
||||||
|
} else {
|
||||||
|
activeIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final isExtended = Breakpoints.large.isActive(context);
|
||||||
|
|
||||||
|
return LayoutBuilder(
|
||||||
|
builder: (final context, final constraints) => SingleChildScrollView(
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(minHeight: constraints.maxHeight),
|
||||||
|
child: IntrinsicHeight(
|
||||||
|
child: NavigationRail(
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
labelType: isExtended
|
||||||
|
? NavigationRailLabelType.none
|
||||||
|
: NavigationRailLabelType.all,
|
||||||
|
extended: isExtended,
|
||||||
|
leading: showFab
|
||||||
|
? const BrandFab(
|
||||||
|
extended: false,
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
groupAlignment: 0.0,
|
||||||
|
destinations: destinations
|
||||||
|
.map(
|
||||||
|
(final destination) => NavigationRailDestination(
|
||||||
|
icon: Icon(destination.icon),
|
||||||
|
label: Text(destination.label),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
selectedIndex: activeIndex,
|
||||||
|
onDestinationSelected: (final index) {
|
||||||
|
context.router.replaceAll([destinations[index].route]);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _BottomBar extends StatelessWidget {
|
||||||
|
const _BottomBar({
|
||||||
|
required this.destinations,
|
||||||
|
required this.hidden,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final List<RouteDestination> destinations;
|
||||||
|
final bool hidden;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) {
|
||||||
|
final prevActiveIndex = destinations.indexWhere(
|
||||||
|
(final destination) => context.router.stack
|
||||||
|
.any((final route) => route.name == destination.route.routeName),
|
||||||
|
);
|
||||||
|
|
||||||
|
return AnimatedContainer(
|
||||||
|
duration: const Duration(milliseconds: 500),
|
||||||
|
height: hidden ? 0 : 80,
|
||||||
|
curve: Curves.easeInOutCubicEmphasized,
|
||||||
|
clipBehavior: Clip.antiAlias,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).scaffoldBackgroundColor,
|
||||||
|
),
|
||||||
|
child: NavigationBar(
|
||||||
|
selectedIndex: prevActiveIndex == -1 ? 0 : prevActiveIndex,
|
||||||
|
labelBehavior: NavigationDestinationLabelBehavior.onlyShowSelected,
|
||||||
|
onDestinationSelected: (final index) {
|
||||||
|
context.router.replaceAll([destinations[index].route]);
|
||||||
|
},
|
||||||
|
destinations: destinations
|
||||||
|
.map(
|
||||||
|
(final destination) => NavigationDestination(
|
||||||
|
icon: Icon(destination.icon),
|
||||||
|
label: destination.label,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MainScreenNavigationDrawer extends StatelessWidget {
|
||||||
|
const _MainScreenNavigationDrawer({
|
||||||
|
required this.destinations,
|
||||||
|
this.showFab = true,
|
||||||
|
});
|
||||||
|
|
||||||
|
final List<RouteDestination> destinations;
|
||||||
|
final bool showFab;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) {
|
||||||
|
int? activeIndex = destinations.indexWhere(
|
||||||
|
(final destination) =>
|
||||||
|
context.router.isRouteActive(destination.route.routeName),
|
||||||
|
);
|
||||||
|
|
||||||
|
final prevActiveIndex = destinations.indexWhere(
|
||||||
|
(final destination) => context.router.stack
|
||||||
|
.any((final route) => route.name == destination.route.routeName),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (activeIndex == -1) {
|
||||||
|
if (prevActiveIndex != -1) {
|
||||||
|
activeIndex = prevActiveIndex;
|
||||||
|
} else {
|
||||||
|
activeIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SizedBox(
|
||||||
|
height: MediaQuery.of(context).size.height,
|
||||||
|
width: 296,
|
||||||
|
child: NavigationDrawer(
|
||||||
|
key: const Key('PrimaryNavigationDrawer'),
|
||||||
|
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||||
|
surfaceTintColor: Colors.transparent,
|
||||||
|
selectedIndex: activeIndex,
|
||||||
|
onDestinationSelected: (final index) {
|
||||||
|
context.router.replaceAll([destinations[index].route]);
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.all(16.0),
|
||||||
|
child: BrandFab(extended: true),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
...destinations.map(
|
||||||
|
(final destination) => NavigationDrawerDestination(
|
||||||
|
icon: Icon(destination.icon),
|
||||||
|
label: Text(destination.label),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,26 +1,27 @@
|
||||||
|
import 'package:auto_route/auto_route.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/logic/cubit/server_installation/server_installation_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/backups/backups_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/backups/backups_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/models/json/backup.dart';
|
import 'package:selfprivacy/logic/models/json/backup.dart';
|
||||||
import 'package:selfprivacy/logic/models/state_types.dart';
|
import 'package:selfprivacy/logic/models/state_types.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_cards/outlined_card.dart';
|
import 'package:selfprivacy/ui/components/cards/outlined_card.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
import 'package:selfprivacy/ui/layouts/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/helpers/modals.dart';
|
import 'package:selfprivacy/ui/helpers/modals.dart';
|
||||||
|
|
||||||
GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
|
GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
|
||||||
|
|
||||||
class BackupDetails extends StatefulWidget {
|
@RoutePage()
|
||||||
const BackupDetails({super.key});
|
class BackupDetailsPage extends StatefulWidget {
|
||||||
|
const BackupDetailsPage({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<BackupDetails> createState() => _BackupDetailsState();
|
State<BackupDetailsPage> createState() => _BackupDetailsPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _BackupDetailsState extends State<BackupDetails>
|
class _BackupDetailsPageState extends State<BackupDetailsPage>
|
||||||
with SingleTickerProviderStateMixin {
|
with SingleTickerProviderStateMixin {
|
||||||
@override
|
@override
|
||||||
Widget build(final BuildContext context) {
|
Widget build(final BuildContext context) {
|
||||||
|
@ -57,7 +58,10 @@ class _BackupDetailsState extends State<BackupDetails>
|
||||||
text: 'backup.initialize'.tr(),
|
text: 'backup.initialize'.tr(),
|
||||||
),
|
),
|
||||||
if (backupStatus == BackupStatusEnum.initializing)
|
if (backupStatus == BackupStatusEnum.initializing)
|
||||||
BrandText.body1('backup.waiting_for_rebuild'.tr()),
|
Text(
|
||||||
|
'backup.waiting_for_rebuild'.tr(),
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
|
),
|
||||||
if (backupStatus != BackupStatusEnum.initializing &&
|
if (backupStatus != BackupStatusEnum.initializing &&
|
||||||
backupStatus != BackupStatusEnum.noKey)
|
backupStatus != BackupStatusEnum.noKey)
|
||||||
OutlinedCard(
|
OutlinedCard(
|
||||||
|
@ -227,7 +231,10 @@ class _BackupDetailsState extends State<BackupDetails>
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (backupStatus == BackupStatusEnum.error)
|
if (backupStatus == BackupStatusEnum.error)
|
||||||
BrandText.body1(backupError.toString()),
|
Text(
|
||||||
|
backupError.toString(),
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:cubit_form/cubit_form.dart';
|
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';
|
||||||
|
@ -5,11 +6,12 @@ import 'package:selfprivacy/logic/common_enum/common_enum.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/devices/devices_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/devices/devices_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/models/json/api_token.dart';
|
import 'package:selfprivacy/logic/models/json/api_token.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
|
||||||
import 'package:selfprivacy/ui/components/info_box/info_box.dart';
|
import 'package:selfprivacy/ui/components/info_box/info_box.dart';
|
||||||
import 'package:selfprivacy/ui/pages/devices/new_device.dart';
|
import 'package:selfprivacy/ui/pages/devices/new_device.dart';
|
||||||
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
||||||
|
|
||||||
|
@RoutePage()
|
||||||
class DevicesScreen extends StatefulWidget {
|
class DevicesScreen extends StatefulWidget {
|
||||||
const DevicesScreen({super.key});
|
const DevicesScreen({super.key});
|
||||||
|
|
||||||
|
@ -25,7 +27,7 @@ class _DevicesScreenState extends State<DevicesScreen> {
|
||||||
|
|
||||||
return RefreshIndicator(
|
return RefreshIndicator(
|
||||||
onRefresh: () async {
|
onRefresh: () async {
|
||||||
context.read<ApiDevicesCubit>().refresh();
|
await context.read<ApiDevicesCubit>().refresh();
|
||||||
},
|
},
|
||||||
child: BrandHeroScreen(
|
child: BrandHeroScreen(
|
||||||
heroTitle: 'devices.main_screen.header'.tr(),
|
heroTitle: 'devices.main_screen.header'.tr(),
|
||||||
|
@ -90,8 +92,7 @@ class _DevicesInfo extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
...devicesStatus.otherDevices
|
...devicesStatus.otherDevices
|
||||||
.map((final device) => _DeviceTile(device: device))
|
.map((final device) => _DeviceTile(device: device)),
|
||||||
.toList(),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/devices/devices_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/devices/devices_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/buttons/brand_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
|
||||||
|
|
||||||
class NewDeviceScreen extends StatelessWidget {
|
class NewDeviceScreen extends StatelessWidget {
|
||||||
const NewDeviceScreen({super.key});
|
const NewDeviceScreen({super.key});
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
|
import 'package:auto_route/auto_route.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/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/filled_card.dart';
|
import 'package:selfprivacy/ui/components/cards/filled_card.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
import 'package:selfprivacy/ui/layouts/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/utils/network_utils.dart';
|
import 'package:selfprivacy/utils/network_utils.dart';
|
||||||
|
|
||||||
|
@RoutePage()
|
||||||
class DnsDetailsPage extends StatefulWidget {
|
class DnsDetailsPage extends StatefulWidget {
|
||||||
const DnsDetailsPage({super.key});
|
const DnsDetailsPage({super.key});
|
||||||
|
|
||||||
|
@ -155,8 +157,7 @@ class _DnsDetailsPageState extends State<DnsDetailsPage> {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
.toList(),
|
|
||||||
const SizedBox(height: 16.0),
|
const SizedBox(height: 16.0),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(
|
title: Text(
|
||||||
|
@ -197,8 +198,7 @@ class _DnsDetailsPageState extends State<DnsDetailsPage> {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
.toList(),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,67 +1,73 @@
|
||||||
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:selfprivacy/config/brand_theme.dart';
|
|
||||||
import 'package:selfprivacy/logic/api_maps/graphql_maps/server_api/server_api.dart';
|
import 'package:selfprivacy/logic/api_maps/graphql_maps/server_api/server_api.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_header/brand_header.dart';
|
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
|
import 'package:selfprivacy/ui/components/brand_md/brand_md.dart';
|
||||||
import 'package:package_info/package_info.dart';
|
import 'package:package_info/package_info.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
|
@RoutePage()
|
||||||
class AboutApplicationPage extends StatelessWidget {
|
class AboutApplicationPage extends StatelessWidget {
|
||||||
const AboutApplicationPage({super.key});
|
const AboutApplicationPage({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(final BuildContext context) => SafeArea(
|
Widget build(final BuildContext context) {
|
||||||
child: Scaffold(
|
final bool isReady = context.watch<ServerInstallationCubit>().state
|
||||||
appBar: PreferredSize(
|
is ServerInstallationFinished;
|
||||||
preferredSize: const Size.fromHeight(52),
|
|
||||||
child: BrandHeader(
|
return BrandHeroScreen(
|
||||||
title: 'about_application_page.title'.tr(),
|
hasBackButton: true,
|
||||||
hasBackButton: true,
|
hasFlashButton: false,
|
||||||
|
heroTitle: 'about_application_page.title'.tr(),
|
||||||
|
children: [
|
||||||
|
FutureBuilder(
|
||||||
|
future: _packageVersion(),
|
||||||
|
builder: (final context, final snapshot) => Text(
|
||||||
|
'about_application_page.application_version_text'
|
||||||
|
.tr(args: [snapshot.data.toString()]),
|
||||||
|
style: Theme.of(context).textTheme.bodyLarge,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (isReady)
|
||||||
|
FutureBuilder(
|
||||||
|
future: _apiVersion(),
|
||||||
|
builder: (final context, final snapshot) => Text(
|
||||||
|
'about_application_page.api_version_text'
|
||||||
|
.tr(args: [snapshot.data.toString()]),
|
||||||
|
style: Theme.of(context).textTheme.bodyLarge,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: ListView(
|
const SizedBox(height: 10),
|
||||||
padding: paddingH15V0,
|
// Button to call showAboutDialog
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => showAboutDialog(
|
||||||
|
context: context,
|
||||||
|
applicationName: 'SelfPrivacy',
|
||||||
|
applicationLegalese: '© 2022 SelfPrivacy',
|
||||||
|
// Link to privacy policy
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(height: 10),
|
|
||||||
FutureBuilder(
|
|
||||||
future: _packageVersion(),
|
|
||||||
builder: (final context, final snapshot) => BrandText.body1(
|
|
||||||
'about_application_page.application_version_text'
|
|
||||||
.tr(args: [snapshot.data.toString()]),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
FutureBuilder(
|
|
||||||
future: _apiVersion(),
|
|
||||||
builder: (final context, final snapshot) => BrandText.body1(
|
|
||||||
'about_application_page.api_version_text'
|
|
||||||
.tr(args: [snapshot.data.toString()]),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
// Button to call showAboutDialog
|
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => showAboutDialog(
|
onPressed: () => launchUrl(
|
||||||
context: context,
|
Uri.parse('https://selfprivacy.ru/privacy-policy'),
|
||||||
applicationName: 'SelfPrivacy',
|
mode: LaunchMode.externalApplication,
|
||||||
applicationLegalese: '© 2022 SelfPrivacy',
|
|
||||||
// Link to privacy policy
|
|
||||||
children: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () => launchUrl(
|
|
||||||
Uri.parse('https://selfprivacy.ru/privacy-policy'),
|
|
||||||
mode: LaunchMode.externalApplication,
|
|
||||||
),
|
|
||||||
child: Text('about_application_page.privacy_policy'.tr()),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
child: const Text('Show about dialog'),
|
child: Text('about_application_page.privacy_policy'.tr()),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
child: const Text('Show about dialog'),
|
||||||
),
|
),
|
||||||
);
|
const SizedBox(height: 8),
|
||||||
|
const Divider(height: 0),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
const BrandMarkdown(
|
||||||
|
fileName: 'about',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Future<String> _packageVersion() async {
|
Future<String> _packageVersion() async {
|
||||||
String packageVersion = 'unknown';
|
String packageVersion = 'unknown';
|
||||||
|
|
|
@ -1,229 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:selfprivacy/config/brand_colors.dart';
|
|
||||||
import 'package:selfprivacy/config/brand_theme.dart';
|
|
||||||
import 'package:selfprivacy/logic/cubit/app_settings/app_settings_cubit.dart';
|
|
||||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.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_header/brand_header.dart';
|
|
||||||
import 'package:selfprivacy/ui/components/brand_switch/brand_switch.dart';
|
|
||||||
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
|
|
||||||
import 'package:selfprivacy/utils/named_font_weight.dart';
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
|
||||||
|
|
||||||
class AppSettingsPage extends StatefulWidget {
|
|
||||||
const AppSettingsPage({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<AppSettingsPage> createState() => _AppSettingsPageState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _AppSettingsPageState extends State<AppSettingsPage> {
|
|
||||||
@override
|
|
||||||
Widget build(final BuildContext context) {
|
|
||||||
final bool isDarkModeOn =
|
|
||||||
context.watch<AppSettingsCubit>().state.isDarkModeOn;
|
|
||||||
|
|
||||||
return SafeArea(
|
|
||||||
child: Builder(
|
|
||||||
builder: (final context) => Scaffold(
|
|
||||||
appBar: PreferredSize(
|
|
||||||
preferredSize: const Size.fromHeight(52),
|
|
||||||
child: BrandHeader(
|
|
||||||
title: 'application_settings.title'.tr(),
|
|
||||||
hasBackButton: true,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
body: ListView(
|
|
||||||
padding: paddingH15V0,
|
|
||||||
children: [
|
|
||||||
const Divider(height: 1),
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
|
||||||
child: Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Flexible(
|
|
||||||
child: _TextColumn(
|
|
||||||
title: 'application_settings.dark_theme_title'.tr(),
|
|
||||||
value:
|
|
||||||
'application_settings.dark_theme_description'.tr(),
|
|
||||||
hasWarning: false,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 5),
|
|
||||||
BrandSwitch(
|
|
||||||
value: Theme.of(context).brightness == Brightness.dark,
|
|
||||||
onChanged: (final value) => context
|
|
||||||
.read<AppSettingsCubit>()
|
|
||||||
.updateDarkMode(isDarkModeOn: !isDarkModeOn),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Divider(height: 0),
|
|
||||||
Container(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
|
||||||
child: Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Flexible(
|
|
||||||
child: _TextColumn(
|
|
||||||
title: 'application_settings.reset_config_title'.tr(),
|
|
||||||
value: 'application_settings.reset_config_description'
|
|
||||||
.tr(),
|
|
||||||
hasWarning: false,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 5),
|
|
||||||
ElevatedButton(
|
|
||||||
style: ElevatedButton.styleFrom(
|
|
||||||
backgroundColor: BrandColors.red1,
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
'basis.reset'.tr(),
|
|
||||||
style: const TextStyle(
|
|
||||||
color: BrandColors.white,
|
|
||||||
fontWeight: NamedFontWeight.demiBold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (final _) => BrandAlert(
|
|
||||||
title: 'modals.are_you_sure'.tr(),
|
|
||||||
contentText: 'modals.purge_all_keys'.tr(),
|
|
||||||
actions: [
|
|
||||||
ActionButton(
|
|
||||||
text: 'modals.purge_all_keys_confirm'.tr(),
|
|
||||||
isRed: true,
|
|
||||||
onPressed: () {
|
|
||||||
context
|
|
||||||
.read<ServerInstallationCubit>()
|
|
||||||
.clearAppConfig();
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
ActionButton(
|
|
||||||
text: 'basis.cancel'.tr(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Divider(height: 0),
|
|
||||||
_deleteServer(context)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _deleteServer(final BuildContext context) {
|
|
||||||
final bool isDisabled =
|
|
||||||
context.watch<ServerInstallationCubit>().state.serverDetails == null;
|
|
||||||
return Container(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
|
||||||
child: Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Flexible(
|
|
||||||
child: _TextColumn(
|
|
||||||
title: 'application_settings.delete_server_title'.tr(),
|
|
||||||
value: 'application_settings.delete_server_description'.tr(),
|
|
||||||
hasWarning: false,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 5),
|
|
||||||
ElevatedButton(
|
|
||||||
style: ElevatedButton.styleFrom(
|
|
||||||
backgroundColor: BrandColors.red1,
|
|
||||||
),
|
|
||||||
onPressed: isDisabled
|
|
||||||
? null
|
|
||||||
: () {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (final _) => BrandAlert(
|
|
||||||
title: 'modals.are_you_sure'.tr(),
|
|
||||||
contentText: 'modals.delete_server_volume'.tr(),
|
|
||||||
actions: [
|
|
||||||
ActionButton(
|
|
||||||
text: 'modals.yes'.tr(),
|
|
||||||
isRed: true,
|
|
||||||
onPressed: () async {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (final context) => Container(
|
|
||||||
alignment: Alignment.center,
|
|
||||||
child: const CircularProgressIndicator(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
await context
|
|
||||||
.read<ServerInstallationCubit>()
|
|
||||||
.serverDelete();
|
|
||||||
if (!mounted) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
ActionButton(
|
|
||||||
text: 'basis.cancel'.tr(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: Text(
|
|
||||||
'basis.delete'.tr(),
|
|
||||||
style: const TextStyle(
|
|
||||||
color: BrandColors.white,
|
|
||||||
fontWeight: NamedFontWeight.demiBold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _TextColumn extends StatelessWidget {
|
|
||||||
const _TextColumn({
|
|
||||||
required this.title,
|
|
||||||
required this.value,
|
|
||||||
this.hasWarning = false,
|
|
||||||
});
|
|
||||||
|
|
||||||
final String title;
|
|
||||||
final String value;
|
|
||||||
final bool hasWarning;
|
|
||||||
@override
|
|
||||||
Widget build(final BuildContext context) => Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
BrandText.body1(
|
|
||||||
title,
|
|
||||||
style: TextStyle(color: hasWarning ? BrandColors.warning : null),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 5),
|
|
||||||
BrandText.body1(
|
|
||||||
value,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 13,
|
|
||||||
height: 1.53,
|
|
||||||
color: BrandColors.gray1,
|
|
||||||
).merge(TextStyle(color: hasWarning ? BrandColors.warning : null)),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
151
lib/ui/pages/more/app_settings/app_settings.dart
Normal file
151
lib/ui/pages/more/app_settings/app_settings.dart
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:auto_route/auto_route.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:selfprivacy/logic/cubit/app_settings/app_settings_cubit.dart';
|
||||||
|
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||||
|
import 'package:selfprivacy/ui/components/buttons/dialog_action_button.dart';
|
||||||
|
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
|
||||||
|
@RoutePage()
|
||||||
|
class AppSettingsPage extends StatefulWidget {
|
||||||
|
const AppSettingsPage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<AppSettingsPage> createState() => _AppSettingsPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AppSettingsPageState extends State<AppSettingsPage> {
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) {
|
||||||
|
final bool isDarkModeOn =
|
||||||
|
context.watch<AppSettingsCubit>().state.isDarkModeOn;
|
||||||
|
|
||||||
|
final bool isSystemDarkModeOn =
|
||||||
|
context.watch<AppSettingsCubit>().state.isAutoDarkModeOn;
|
||||||
|
|
||||||
|
return BrandHeroScreen(
|
||||||
|
hasBackButton: true,
|
||||||
|
hasFlashButton: false,
|
||||||
|
bodyPadding: const EdgeInsets.symmetric(vertical: 16),
|
||||||
|
heroTitle: 'application_settings.title'.tr(),
|
||||||
|
children: [
|
||||||
|
SwitchListTile(
|
||||||
|
title: Text('application_settings.system_dark_theme_title'.tr()),
|
||||||
|
subtitle:
|
||||||
|
Text('application_settings.system_dark_theme_description'.tr()),
|
||||||
|
value: isSystemDarkModeOn,
|
||||||
|
onChanged: (final value) => context
|
||||||
|
.read<AppSettingsCubit>()
|
||||||
|
.updateAutoDarkMode(isAutoDarkModeOn: !isSystemDarkModeOn),
|
||||||
|
),
|
||||||
|
SwitchListTile(
|
||||||
|
title: Text('application_settings.dark_theme_title'.tr()),
|
||||||
|
subtitle: Text('application_settings.dark_theme_description'.tr()),
|
||||||
|
value: Theme.of(context).brightness == Brightness.dark,
|
||||||
|
onChanged: isSystemDarkModeOn
|
||||||
|
? null
|
||||||
|
: (final value) => context
|
||||||
|
.read<AppSettingsCubit>()
|
||||||
|
.updateDarkMode(isDarkModeOn: !isDarkModeOn),
|
||||||
|
),
|
||||||
|
const Divider(height: 0),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Text(
|
||||||
|
'application_settings.dangerous_settings'.tr(),
|
||||||
|
style: Theme.of(context).textTheme.labelLarge!.copyWith(
|
||||||
|
color: Theme.of(context).colorScheme.error,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const _ResetAppTile(),
|
||||||
|
// const Divider(height: 0),
|
||||||
|
_deleteServer(context)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _deleteServer(final BuildContext context) {
|
||||||
|
final bool isDisabled =
|
||||||
|
context.watch<ServerInstallationCubit>().state.serverDetails == null;
|
||||||
|
return ListTile(
|
||||||
|
title: Text('application_settings.delete_server_title'.tr()),
|
||||||
|
subtitle: Text('application_settings.delete_server_description'.tr()),
|
||||||
|
textColor: isDisabled
|
||||||
|
? Theme.of(context).colorScheme.onBackground.withOpacity(0.5)
|
||||||
|
: Theme.of(context).colorScheme.onBackground,
|
||||||
|
onTap: isDisabled
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (final _) => AlertDialog(
|
||||||
|
title: Text('modals.are_you_sure'.tr()),
|
||||||
|
content: Text('modals.delete_server_volume'.tr()),
|
||||||
|
actions: [
|
||||||
|
DialogActionButton(
|
||||||
|
text: 'modals.yes'.tr(),
|
||||||
|
isRed: true,
|
||||||
|
onPressed: () async {
|
||||||
|
unawaited(
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (final context) => Container(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: const CircularProgressIndicator(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await context
|
||||||
|
.read<ServerInstallationCubit>()
|
||||||
|
.serverDelete();
|
||||||
|
if (!mounted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
DialogActionButton(
|
||||||
|
text: 'basis.cancel'.tr(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ResetAppTile extends StatelessWidget {
|
||||||
|
const _ResetAppTile();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) => ListTile(
|
||||||
|
title: Text('application_settings.reset_config_title'.tr()),
|
||||||
|
subtitle: Text('application_settings.reset_config_description'.tr()),
|
||||||
|
onTap: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (final _) => AlertDialog(
|
||||||
|
title: Text('modals.are_you_sure'.tr()),
|
||||||
|
content: Text('modals.purge_all_keys'.tr()),
|
||||||
|
actions: [
|
||||||
|
DialogActionButton(
|
||||||
|
text: 'modals.purge_all_keys_confirm'.tr(),
|
||||||
|
isRed: true,
|
||||||
|
onPressed: () {
|
||||||
|
context.read<ServerInstallationCubit>().clearAppConfig();
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
DialogActionButton(
|
||||||
|
text: 'basis.cancel'.tr(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
85
lib/ui/pages/more/app_settings/developer_settings.dart
Normal file
85
lib/ui/pages/more/app_settings/developer_settings.dart
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
import 'package:auto_route/auto_route.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:selfprivacy/logic/api_maps/staging_options.dart';
|
||||||
|
import 'package:selfprivacy/logic/cubit/app_settings/app_settings_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/ui/layouts/brand_hero_screen.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
|
||||||
|
@RoutePage()
|
||||||
|
class DeveloperSettingsPage extends StatefulWidget {
|
||||||
|
const DeveloperSettingsPage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<DeveloperSettingsPage> createState() => _DeveloperSettingsPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DeveloperSettingsPageState extends State<DeveloperSettingsPage> {
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) => BrandHeroScreen(
|
||||||
|
hasBackButton: true,
|
||||||
|
hasFlashButton: false,
|
||||||
|
bodyPadding: const EdgeInsets.symmetric(vertical: 16),
|
||||||
|
heroTitle: 'developer_settings.title'.tr(),
|
||||||
|
heroSubtitle: 'developer_settings.subtitle'.tr(),
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Text(
|
||||||
|
'developer_settings.server_setup'.tr(),
|
||||||
|
style: Theme.of(context).textTheme.labelLarge!.copyWith(
|
||||||
|
color: Theme.of(context).colorScheme.secondary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SwitchListTile(
|
||||||
|
title: Text('developer_settings.use_staging_acme'.tr()),
|
||||||
|
subtitle:
|
||||||
|
Text('developer_settings.use_staging_acme_description'.tr()),
|
||||||
|
value: StagingOptions.stagingAcme,
|
||||||
|
onChanged: null,
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Text(
|
||||||
|
'developer_settings.routing'.tr(),
|
||||||
|
style: Theme.of(context).textTheme.labelLarge!.copyWith(
|
||||||
|
color: Theme.of(context).colorScheme.secondary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
title: Text('developer_settings.reset_onboarding'.tr()),
|
||||||
|
subtitle:
|
||||||
|
Text('developer_settings.reset_onboarding_description'.tr()),
|
||||||
|
enabled:
|
||||||
|
!context.watch<AppSettingsCubit>().state.isOnboardingShowing,
|
||||||
|
onTap: () => context
|
||||||
|
.read<AppSettingsCubit>()
|
||||||
|
.turnOffOnboarding(isOnboardingShowing: true),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Text(
|
||||||
|
'developer_settings.cubit_statuses'.tr(),
|
||||||
|
style: Theme.of(context).textTheme.labelLarge!.copyWith(
|
||||||
|
color: Theme.of(context).colorScheme.secondary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
title: const Text('ApiDevicesCubit'),
|
||||||
|
subtitle: Text(
|
||||||
|
context.watch<ApiDevicesCubit>().state.status.toString(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
title: const Text('RecoveryKeyCubit'),
|
||||||
|
subtitle: Text(
|
||||||
|
context.watch<RecoveryKeyCubit>().state.loadingStatus.toString(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,20 +1,21 @@
|
||||||
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
|
||||||
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/get_it_config.dart';
|
import 'package:selfprivacy/config/get_it_config.dart';
|
||||||
import 'package:selfprivacy/logic/models/message.dart';
|
import 'package:selfprivacy/logic/models/message.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_header/brand_header.dart';
|
import 'package:selfprivacy/ui/components/list_tiles/log_list_tile.dart';
|
||||||
|
|
||||||
class Console extends StatefulWidget {
|
@RoutePage()
|
||||||
const Console({super.key});
|
class ConsolePage extends StatefulWidget {
|
||||||
|
const ConsolePage({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<Console> createState() => _ConsoleState();
|
State<ConsolePage> createState() => _ConsolePageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ConsoleState extends State<Console> {
|
class _ConsolePageState extends State<ConsolePage> {
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
getIt.get<ConsoleModel>().addListener(update);
|
getIt.get<ConsoleModel>().addListener(update);
|
||||||
|
@ -28,21 +29,30 @@ class _ConsoleState extends State<Console> {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
void update() => setState(() => {});
|
bool paused = false;
|
||||||
|
|
||||||
|
void update() {
|
||||||
|
if (!paused) {
|
||||||
|
setState(() => {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(final BuildContext context) => SafeArea(
|
Widget build(final BuildContext context) => SafeArea(
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: PreferredSize(
|
appBar: AppBar(
|
||||||
preferredSize: const Size.fromHeight(53),
|
title: Text('console_page.title'.tr()),
|
||||||
child: Column(
|
leading: IconButton(
|
||||||
children: [
|
icon: const Icon(Icons.arrow_back),
|
||||||
BrandHeader(
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
title: 'console_page.title'.tr(),
|
|
||||||
hasBackButton: true,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(
|
||||||
|
paused ? Icons.play_arrow_outlined : Icons.pause_outlined),
|
||||||
|
onPressed: () => setState(() => paused = !paused),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
body: FutureBuilder(
|
body: FutureBuilder(
|
||||||
future: getIt.allReady(),
|
future: getIt.allReady(),
|
||||||
|
@ -61,30 +71,7 @@ class _ConsoleState extends State<Console> {
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
...UnmodifiableListView(
|
...UnmodifiableListView(
|
||||||
messages
|
messages
|
||||||
.map((final message) {
|
.map((final message) => LogListItem(message: message))
|
||||||
final bool isError =
|
|
||||||
message.type == MessageType.warning;
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
|
||||||
child: RichText(
|
|
||||||
text: TextSpan(
|
|
||||||
style: DefaultTextStyle.of(context).style,
|
|
||||||
children: <TextSpan>[
|
|
||||||
TextSpan(
|
|
||||||
text:
|
|
||||||
'${message.timeString}${isError ? '(Error)' : ''}: \n',
|
|
||||||
style: TextStyle(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color:
|
|
||||||
isError ? BrandColors.red1 : null,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
TextSpan(text: message.text),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.toList()
|
.toList()
|
||||||
.reversed,
|
.reversed,
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:auto_route/auto_route.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:ionicons/ionicons.dart';
|
import 'package:ionicons/ionicons.dart';
|
||||||
|
@ -5,23 +6,13 @@ import 'package:selfprivacy/config/brand_theme.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/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/filled_card.dart';
|
import 'package:selfprivacy/ui/components/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/utils/breakpoints.dart';
|
||||||
import 'package:selfprivacy/ui/pages/recovery_key/recovery_key.dart';
|
import 'package:selfprivacy/ui/router/router.dart';
|
||||||
import 'package:selfprivacy/ui/pages/server_storage/binds_migration/services_migration.dart';
|
|
||||||
import 'package:selfprivacy/ui/pages/setup/initializing/initializing.dart';
|
|
||||||
import 'package:selfprivacy/ui/pages/onboarding/onboarding.dart';
|
|
||||||
import 'package:selfprivacy/ui/pages/root_route.dart';
|
|
||||||
import 'package:selfprivacy/ui/pages/users/users.dart';
|
|
||||||
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
|
||||||
|
|
||||||
import 'package:selfprivacy/ui/pages/more/about_us.dart';
|
|
||||||
import 'package:selfprivacy/ui/pages/more/app_settings/app_setting.dart';
|
|
||||||
import 'package:selfprivacy/ui/pages/more/console.dart';
|
|
||||||
import 'package:selfprivacy/ui/pages/more/about_application.dart';
|
|
||||||
|
|
||||||
|
@RoutePage()
|
||||||
class MorePage extends StatelessWidget {
|
class MorePage extends StatelessWidget {
|
||||||
const MorePage({super.key});
|
const MorePage({super.key});
|
||||||
|
|
||||||
|
@ -34,12 +25,14 @@ class MorePage extends StatelessWidget {
|
||||||
context.watch<ApiServerVolumeCubit>().state.usesBinds;
|
context.watch<ApiServerVolumeCubit>().state.usesBinds;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: PreferredSize(
|
appBar: Breakpoints.small.isActive(context)
|
||||||
preferredSize: const Size.fromHeight(52),
|
? PreferredSize(
|
||||||
child: BrandHeader(
|
preferredSize: const Size.fromHeight(52),
|
||||||
title: 'basis.more'.tr(),
|
child: BrandHeader(
|
||||||
),
|
title: 'basis.more'.tr(),
|
||||||
),
|
),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
body: ListView(
|
body: ListView(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
|
@ -50,7 +43,7 @@ class MorePage extends StatelessWidget {
|
||||||
_MoreMenuItem(
|
_MoreMenuItem(
|
||||||
title: 'storage.start_migration_button'.tr(),
|
title: 'storage.start_migration_button'.tr(),
|
||||||
iconData: Icons.drive_file_move_outline,
|
iconData: Icons.drive_file_move_outline,
|
||||||
goTo: ServicesMigrationPage(
|
goTo: () => ServicesMigrationRoute(
|
||||||
diskStatus: context
|
diskStatus: context
|
||||||
.watch<ApiServerVolumeCubit>()
|
.watch<ApiServerVolumeCubit>()
|
||||||
.state
|
.state
|
||||||
|
@ -77,7 +70,7 @@ class MorePage extends StatelessWidget {
|
||||||
_MoreMenuItem(
|
_MoreMenuItem(
|
||||||
title: 'more_page.configuration_wizard'.tr(),
|
title: 'more_page.configuration_wizard'.tr(),
|
||||||
iconData: Icons.change_history_outlined,
|
iconData: Icons.change_history_outlined,
|
||||||
goTo: const InitializingPage(),
|
goTo: () => const InitializingRoute(),
|
||||||
subtitle: 'not_ready_card.in_menu'.tr(),
|
subtitle: 'not_ready_card.in_menu'.tr(),
|
||||||
accent: true,
|
accent: true,
|
||||||
),
|
),
|
||||||
|
@ -85,47 +78,43 @@ class MorePage extends StatelessWidget {
|
||||||
_MoreMenuItem(
|
_MoreMenuItem(
|
||||||
title: 'more_page.create_ssh_key'.tr(),
|
title: 'more_page.create_ssh_key'.tr(),
|
||||||
iconData: Ionicons.key_outline,
|
iconData: Ionicons.key_outline,
|
||||||
goTo: const UserDetails(
|
goTo: () => UserDetailsRoute(
|
||||||
login: 'root',
|
login: 'root',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (isReady)
|
if (isReady)
|
||||||
_MoreMenuItem(
|
_MoreMenuItem(
|
||||||
iconData: Icons.password_outlined,
|
iconData: Icons.password_outlined,
|
||||||
goTo: const RecoveryKey(),
|
goTo: () => const RecoveryKeyRoute(),
|
||||||
title: 'recovery_key.key_main_header'.tr(),
|
title: 'recovery_key.key_main_header'.tr(),
|
||||||
),
|
),
|
||||||
if (isReady)
|
if (isReady)
|
||||||
_MoreMenuItem(
|
_MoreMenuItem(
|
||||||
iconData: Icons.devices_outlined,
|
iconData: Icons.devices_outlined,
|
||||||
goTo: const DevicesScreen(),
|
goTo: () => const DevicesRoute(),
|
||||||
title: 'devices.main_screen.header'.tr(),
|
title: 'devices.main_screen.header'.tr(),
|
||||||
),
|
),
|
||||||
_MoreMenuItem(
|
_MoreMenuItem(
|
||||||
title: 'more_page.application_settings'.tr(),
|
title: 'more_page.application_settings'.tr(),
|
||||||
iconData: Icons.settings_outlined,
|
iconData: Icons.settings_outlined,
|
||||||
goTo: const AppSettingsPage(),
|
goTo: () => const AppSettingsRoute(),
|
||||||
),
|
|
||||||
_MoreMenuItem(
|
|
||||||
title: 'more_page.about_project'.tr(),
|
|
||||||
iconData: BrandIcons.engineer,
|
|
||||||
goTo: const AboutUsPage(),
|
|
||||||
),
|
),
|
||||||
_MoreMenuItem(
|
_MoreMenuItem(
|
||||||
title: 'more_page.about_application'.tr(),
|
title: 'more_page.about_application'.tr(),
|
||||||
iconData: BrandIcons.fire,
|
iconData: BrandIcons.fire,
|
||||||
goTo: const AboutApplicationPage(),
|
goTo: () => const AboutApplicationRoute(),
|
||||||
|
longGoTo: const DeveloperSettingsRoute(),
|
||||||
),
|
),
|
||||||
if (!isReady)
|
if (!isReady)
|
||||||
_MoreMenuItem(
|
_MoreMenuItem(
|
||||||
title: 'more_page.onboarding'.tr(),
|
title: 'more_page.onboarding'.tr(),
|
||||||
iconData: BrandIcons.start,
|
iconData: BrandIcons.start,
|
||||||
goTo: const OnboardingPage(nextPage: RootPage()),
|
goTo: () => const OnboardingRoute(),
|
||||||
),
|
),
|
||||||
_MoreMenuItem(
|
_MoreMenuItem(
|
||||||
title: 'more_page.console'.tr(),
|
title: 'more_page.console'.tr(),
|
||||||
iconData: BrandIcons.terminal,
|
iconData: BrandIcons.terminal,
|
||||||
goTo: const Console(),
|
goTo: () => const ConsoleRoute(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -140,14 +129,16 @@ class _MoreMenuItem extends StatelessWidget {
|
||||||
const _MoreMenuItem({
|
const _MoreMenuItem({
|
||||||
required this.iconData,
|
required this.iconData,
|
||||||
required this.title,
|
required this.title,
|
||||||
|
required this.goTo,
|
||||||
this.subtitle,
|
this.subtitle,
|
||||||
this.goTo,
|
this.longGoTo,
|
||||||
this.accent = false,
|
this.accent = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
final IconData iconData;
|
final IconData iconData;
|
||||||
final String title;
|
final String title;
|
||||||
final Widget? goTo;
|
final PageRouteInfo Function() goTo;
|
||||||
|
final PageRouteInfo? longGoTo;
|
||||||
final String? subtitle;
|
final String? subtitle;
|
||||||
final bool accent;
|
final bool accent;
|
||||||
|
|
||||||
|
@ -160,9 +151,9 @@ class _MoreMenuItem extends StatelessWidget {
|
||||||
tertiary: accent,
|
tertiary: accent,
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||||
onTap: goTo != null
|
onTap: () => context.pushRoute(goTo()),
|
||||||
? () => Navigator.of(context).push(materialRoute(goTo!))
|
onLongPress:
|
||||||
: null,
|
longGoTo != null ? () => context.pushRoute(longGoTo!) : null,
|
||||||
leading: Icon(
|
leading: Icon(
|
||||||
iconData,
|
iconData,
|
||||||
size: 24,
|
size: 24,
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.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/ui/components/brand_button/brand_button.dart';
|
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
|
||||||
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
import 'package:selfprivacy/ui/router/router.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
|
||||||
|
@RoutePage()
|
||||||
class OnboardingPage extends StatefulWidget {
|
class OnboardingPage extends StatefulWidget {
|
||||||
const OnboardingPage({required this.nextPage, super.key});
|
const OnboardingPage({super.key});
|
||||||
|
|
||||||
final Widget nextPage;
|
|
||||||
@override
|
@override
|
||||||
State<OnboardingPage> createState() => _OnboardingPageState();
|
State<OnboardingPage> createState() => _OnboardingPageState();
|
||||||
}
|
}
|
||||||
|
@ -22,14 +23,14 @@ class _OnboardingPageState extends State<OnboardingPage> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(final BuildContext context) => Scaffold(
|
Widget build(final BuildContext context) => Scaffold(
|
||||||
body: PageView(
|
body: PageView(
|
||||||
controller: pageController,
|
controller: pageController,
|
||||||
children: [
|
children: [
|
||||||
_withPadding(firstPage()),
|
_withPadding(firstPage()),
|
||||||
_withPadding(secondPage()),
|
_withPadding(secondPage()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
Widget _withPadding(final Widget child) => Padding(
|
Widget _withPadding(final Widget child) => Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
|
@ -76,7 +77,7 @@ class _OnboardingPageState extends State<OnboardingPage> {
|
||||||
pageController.animateToPage(
|
pageController.animateToPage(
|
||||||
1,
|
1,
|
||||||
duration: const Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
curve: Curves.easeIn,
|
curve: Curves.easeInOutCubicEmphasized,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
text: 'basis.next'.tr(),
|
text: 'basis.next'.tr(),
|
||||||
|
@ -142,10 +143,10 @@ class _OnboardingPageState extends State<OnboardingPage> {
|
||||||
BrandButton.rised(
|
BrandButton.rised(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.read<AppSettingsCubit>().turnOffOnboarding();
|
context.read<AppSettingsCubit>().turnOffOnboarding();
|
||||||
Navigator.of(context).pushAndRemoveUntil(
|
context.router.replaceAll([
|
||||||
materialRoute(widget.nextPage),
|
const RootRoute(),
|
||||||
(final route) => false,
|
const InitializingRoute(),
|
||||||
);
|
]);
|
||||||
},
|
},
|
||||||
text: 'basis.got_it'.tr(),
|
text: 'basis.got_it'.tr(),
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:auto_route/auto_route.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_theme.dart';
|
import 'package:selfprivacy/config/brand_theme.dart';
|
||||||
|
@ -10,13 +11,12 @@ 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/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/pages/backup_details/backup_details.dart';
|
import 'package:selfprivacy/ui/router/router.dart';
|
||||||
import 'package:selfprivacy/ui/pages/dns_details/dns_details.dart';
|
import 'package:selfprivacy/utils/breakpoints.dart';
|
||||||
import 'package:selfprivacy/ui/pages/server_details/server_details_screen.dart';
|
|
||||||
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
|
||||||
|
|
||||||
GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
|
GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
|
||||||
|
|
||||||
|
@RoutePage()
|
||||||
class ProvidersPage extends StatefulWidget {
|
class ProvidersPage extends StatefulWidget {
|
||||||
const ProvidersPage({super.key});
|
const ProvidersPage({super.key});
|
||||||
|
|
||||||
|
@ -61,12 +61,14 @@ class _ProvidersPageState extends State<ProvidersPage> {
|
||||||
}
|
}
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: PreferredSize(
|
appBar: Breakpoints.small.isActive(context)
|
||||||
preferredSize: const Size.fromHeight(52),
|
? PreferredSize(
|
||||||
child: BrandHeader(
|
preferredSize: const Size.fromHeight(52),
|
||||||
title: 'basis.providers_title'.tr(),
|
child: BrandHeader(
|
||||||
),
|
title: 'basis.providers_title'.tr(),
|
||||||
),
|
),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
body: ListView(
|
body: ListView(
|
||||||
padding: paddingH15V0,
|
padding: paddingH15V0,
|
||||||
children: [
|
children: [
|
||||||
|
@ -81,8 +83,7 @@ class _ProvidersPageState extends State<ProvidersPage> {
|
||||||
subtitle: diskStatus.isDiskOkay
|
subtitle: diskStatus.isDiskOkay
|
||||||
? 'storage.status_ok'.tr()
|
? 'storage.status_ok'.tr()
|
||||||
: 'storage.status_error'.tr(),
|
: 'storage.status_error'.tr(),
|
||||||
onTap: () => Navigator.of(context)
|
onTap: () => context.pushRoute(const ServerDetailsRoute()),
|
||||||
.push(materialRoute(const ServerDetailsScreen())),
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
_Card(
|
_Card(
|
||||||
|
@ -92,11 +93,7 @@ class _ProvidersPageState extends State<ProvidersPage> {
|
||||||
subtitle: appConfig.isDomainSelected
|
subtitle: appConfig.isDomainSelected
|
||||||
? appConfig.serverDomain!.domainName
|
? appConfig.serverDomain!.domainName
|
||||||
: '',
|
: '',
|
||||||
onTap: () => Navigator.of(context).push(
|
onTap: () => context.pushRoute(const DnsDetailsRoute()),
|
||||||
materialRoute(
|
|
||||||
const DnsDetailsPage(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
// TODO: When backups are fixed, show this card
|
// TODO: When backups are fixed, show this card
|
||||||
|
@ -108,8 +105,7 @@ class _ProvidersPageState extends State<ProvidersPage> {
|
||||||
icon: BrandIcons.save,
|
icon: BrandIcons.save,
|
||||||
title: 'backup.card_title'.tr(),
|
title: 'backup.card_title'.tr(),
|
||||||
subtitle: isBackupInitialized ? 'backup.card_subtitle'.tr() : '',
|
subtitle: isBackupInitialized ? 'backup.card_subtitle'.tr() : '',
|
||||||
onTap: () => Navigator.of(context)
|
onTap: () => context.pushRoute(const BackupDetailsRoute()),
|
||||||
.push(materialRoute(const BackupDetails())),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import 'package:cubit_form/cubit_form.dart';
|
import 'package:auto_route/auto_route.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:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
@ -6,20 +6,21 @@ import 'package:selfprivacy/config/get_it_config.dart';
|
||||||
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
|
import 'package:selfprivacy/logic/common_enum/common_enum.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_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/buttons/brand_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_cards/filled_card.dart';
|
import 'package:selfprivacy/ui/components/cards/filled_card.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
import 'package:selfprivacy/ui/layouts/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';
|
||||||
|
|
||||||
class RecoveryKey extends StatefulWidget {
|
@RoutePage()
|
||||||
const RecoveryKey({super.key});
|
class RecoveryKeyPage extends StatefulWidget {
|
||||||
|
const RecoveryKeyPage({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<RecoveryKey> createState() => _RecoveryKeyState();
|
State<RecoveryKeyPage> createState() => _RecoveryKeyPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _RecoveryKeyState extends State<RecoveryKey> {
|
class _RecoveryKeyPageState extends State<RecoveryKeyPage> {
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
@ -250,7 +251,7 @@ class _RecoveryKeyConfigurationState extends State<RecoveryKeyConfiguration> {
|
||||||
setState(() {
|
setState(() {
|
||||||
_isLoading = false;
|
_isLoading = false;
|
||||||
});
|
});
|
||||||
Navigator.of(context).push(
|
await Navigator.of(context).push(
|
||||||
materialRoute(
|
materialRoute(
|
||||||
RecoveryKeyReceiving(recoveryKey: token), // TO DO
|
RecoveryKeyReceiving(recoveryKey: token), // TO DO
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
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/ui/components/brand_button/brand_button.dart';
|
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
|
||||||
import 'package:selfprivacy/ui/components/info_box/info_box.dart';
|
import 'package:selfprivacy/ui/components/info_box/info_box.dart';
|
||||||
|
|
||||||
class RecoveryKeyReceiving extends StatelessWidget {
|
class RecoveryKeyReceiving extends StatelessWidget {
|
||||||
|
|
|
@ -1,89 +1,153 @@
|
||||||
|
import 'package:auto_route/auto_route.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:selfprivacy/logic/cubit/app_settings/app_settings_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_tab_bar/brand_tab_bar.dart';
|
import 'package:selfprivacy/ui/layouts/root_scaffold_with_navigation.dart';
|
||||||
import 'package:selfprivacy/ui/pages/more/more.dart';
|
import 'package:selfprivacy/ui/router/root_destinations.dart';
|
||||||
import 'package:selfprivacy/ui/pages/providers/providers.dart';
|
|
||||||
import 'package:selfprivacy/ui/pages/services/services.dart';
|
|
||||||
import 'package:selfprivacy/ui/pages/users/users.dart';
|
|
||||||
|
|
||||||
import 'package:selfprivacy/ui/components/pre_styled_buttons/flash_fab.dart';
|
import 'package:selfprivacy/ui/router/router.dart';
|
||||||
|
|
||||||
class RootPage extends StatefulWidget {
|
@RoutePage()
|
||||||
|
class RootPage extends StatefulWidget implements AutoRouteWrapper {
|
||||||
const RootPage({super.key});
|
const RootPage({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<RootPage> createState() => _RootPageState();
|
State<RootPage> createState() => _RootPageState();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget wrappedRoute(final BuildContext context) => this;
|
||||||
}
|
}
|
||||||
|
|
||||||
class _RootPageState extends State<RootPage> with TickerProviderStateMixin {
|
class _RootPageState extends State<RootPage> with TickerProviderStateMixin {
|
||||||
late TabController tabController;
|
bool shouldUseSplitView() => false;
|
||||||
|
|
||||||
late final AnimationController _controller = AnimationController(
|
final destinations = rootDestinations;
|
||||||
duration: const Duration(milliseconds: 400),
|
|
||||||
vsync: this,
|
|
||||||
);
|
|
||||||
late final Animation<double> _animation = CurvedAnimation(
|
|
||||||
parent: _controller,
|
|
||||||
curve: Curves.fastOutSlowIn,
|
|
||||||
);
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
tabController = TabController(length: 4, vsync: this);
|
|
||||||
tabController.addListener(() {
|
|
||||||
setState(() {
|
|
||||||
tabController.index == 2
|
|
||||||
? _controller.forward()
|
|
||||||
: _controller.reverse();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
super.initState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
tabController.dispose();
|
|
||||||
_controller.dispose();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
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;
|
||||||
|
|
||||||
return Provider<ChangeTab>(
|
if (context.read<AppSettingsCubit>().state.isOnboardingShowing) {
|
||||||
create: (final _) => ChangeTab(tabController.animateTo),
|
context.router.replace(const OnboardingRoute());
|
||||||
child: Scaffold(
|
}
|
||||||
body: TabBarView(
|
|
||||||
controller: tabController,
|
return AutoRouter(
|
||||||
children: const [
|
builder: (final context, final child) {
|
||||||
ProvidersPage(),
|
final currentDestinationIndex = destinations.indexWhere(
|
||||||
ServicesPage(),
|
(final destination) =>
|
||||||
UsersPage(),
|
context.router.isRouteActive(destination.route.routeName),
|
||||||
MorePage(),
|
);
|
||||||
|
final isOtherRouterActive =
|
||||||
|
context.router.root.current.name != RootRoute.name;
|
||||||
|
final routeName = getRouteTitle(context.router.current.name).tr();
|
||||||
|
return RootScaffoldWithNavigation(
|
||||||
|
title: routeName,
|
||||||
|
destinations: destinations,
|
||||||
|
showBottomBar:
|
||||||
|
!(currentDestinationIndex == -1 && !isOtherRouterActive),
|
||||||
|
showFab: isReady,
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MainScreenNavigationRail extends StatelessWidget {
|
||||||
|
const MainScreenNavigationRail({
|
||||||
|
required this.destinations,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final List<RouteDestination> destinations;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) {
|
||||||
|
int? activeIndex = destinations.indexWhere(
|
||||||
|
(final destination) =>
|
||||||
|
context.router.isRouteActive(destination.route.routeName),
|
||||||
|
);
|
||||||
|
if (activeIndex == -1) {
|
||||||
|
activeIndex = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: SizedBox(
|
||||||
|
height: MediaQuery.of(context).size.height,
|
||||||
|
width: 72,
|
||||||
|
child: LayoutBuilder(
|
||||||
|
builder: (final context, final constraints) => SingleChildScrollView(
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(minHeight: constraints.maxHeight),
|
||||||
|
child: IntrinsicHeight(
|
||||||
|
child: NavigationRail(
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
labelType: NavigationRailLabelType.all,
|
||||||
|
destinations: destinations
|
||||||
|
.map(
|
||||||
|
(final destination) => NavigationRailDestination(
|
||||||
|
icon: Icon(destination.icon),
|
||||||
|
label: Text(destination.label),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
selectedIndex: activeIndex,
|
||||||
|
onDestinationSelected: (final index) {
|
||||||
|
context.router.replaceAll([destinations[index].route]);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MainScreenNavigationDrawer extends StatelessWidget {
|
||||||
|
const MainScreenNavigationDrawer({
|
||||||
|
required this.destinations,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
final List<RouteDestination> destinations;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) {
|
||||||
|
int? activeIndex = destinations.indexWhere(
|
||||||
|
(final destination) =>
|
||||||
|
context.router.isRouteActive(destination.route.routeName),
|
||||||
|
);
|
||||||
|
if (activeIndex == -1) {
|
||||||
|
activeIndex = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SizedBox(
|
||||||
|
height: MediaQuery.of(context).size.height,
|
||||||
|
width: 296,
|
||||||
|
child: LayoutBuilder(
|
||||||
|
builder: (final context, final constraints) => NavigationDrawer(
|
||||||
|
// backgroundColor: Theme.of(context).colorScheme.surfaceVariant,
|
||||||
|
// surfaceTintColor: Colors.transparent,
|
||||||
|
key: const Key('PrimaryNavigationDrawer'),
|
||||||
|
selectedIndex: activeIndex,
|
||||||
|
onDestinationSelected: (final index) {
|
||||||
|
context.router.replaceAll([destinations[index].route]);
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 18),
|
||||||
|
...destinations.map(
|
||||||
|
(final destination) => NavigationDrawerDestination(
|
||||||
|
icon: Icon(destination.icon),
|
||||||
|
label: Text(destination.label),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
bottomNavigationBar: BrandTabBar(
|
|
||||||
controller: tabController,
|
|
||||||
),
|
|
||||||
floatingActionButton: isReady
|
|
||||||
? SizedBox(
|
|
||||||
height: 104 + 16,
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
|
||||||
children: [
|
|
||||||
ScaleTransition(
|
|
||||||
scale: _animation,
|
|
||||||
child: const AddUserFab(),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
const BrandFab(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:cubit_form/cubit_form.dart';
|
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/logic/common_enum/common_enum.dart';
|
import 'package:selfprivacy/logic/common_enum/common_enum.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/client_jobs/client_jobs_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/client_jobs/client_jobs_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/metrics/metrics_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/metrics/metrics_cubit.dart';
|
||||||
|
@ -10,18 +10,17 @@ import 'package:selfprivacy/logic/cubit/server_installation/server_installation_
|
||||||
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/auto_upgrade_settings.dart';
|
import 'package:selfprivacy/logic/models/auto_upgrade_settings.dart';
|
||||||
import 'package:selfprivacy/logic/models/job.dart';
|
import 'package:selfprivacy/logic/models/job.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_button/segmented_buttons.dart';
|
import 'package:selfprivacy/ui/components/buttons/segmented_buttons.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_cards/filled_card.dart';
|
import 'package:selfprivacy/ui/components/cards/filled_card.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
import 'package:selfprivacy/ui/layouts/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_text/brand_text.dart';
|
|
||||||
import 'package:selfprivacy/ui/components/list_tiles/list_tile_on_surface_variant.dart';
|
import 'package:selfprivacy/ui/components/list_tiles/list_tile_on_surface_variant.dart';
|
||||||
import 'package:selfprivacy/ui/pages/server_details/charts/cpu_chart.dart';
|
import 'package:selfprivacy/ui/pages/server_details/charts/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';
|
||||||
import 'package:selfprivacy/ui/pages/server_storage/storage_card.dart';
|
import 'package:selfprivacy/ui/pages/server_storage/storage_card.dart';
|
||||||
|
import 'package:selfprivacy/utils/breakpoints.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/route_transitions/basic.dart';
|
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
||||||
import 'package:timezone/timezone.dart';
|
import 'package:timezone/timezone.dart';
|
||||||
|
|
||||||
|
@ -32,6 +31,7 @@ part 'time_zone/time_zone.dart';
|
||||||
|
|
||||||
var navigatorKey = GlobalKey<NavigatorState>();
|
var navigatorKey = GlobalKey<NavigatorState>();
|
||||||
|
|
||||||
|
@RoutePage()
|
||||||
class ServerDetailsScreen extends StatefulWidget {
|
class ServerDetailsScreen extends StatefulWidget {
|
||||||
const ServerDetailsScreen({super.key});
|
const ServerDetailsScreen({super.key});
|
||||||
|
|
||||||
|
@ -75,6 +75,7 @@ class _ServerDetailsScreenState extends State<ServerDetailsScreen>
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (final context) => context.read<ServerDetailsCubit>()..check(),
|
create: (final context) => context.read<ServerDetailsCubit>()..check(),
|
||||||
child: BrandHeroScreen(
|
child: BrandHeroScreen(
|
||||||
|
hasFlashButton: true,
|
||||||
heroIcon: BrandIcons.server,
|
heroIcon: BrandIcons.server,
|
||||||
heroTitle: 'server.card_title'.tr(),
|
heroTitle: 'server.card_title'.tr(),
|
||||||
heroSubtitle: 'server.description'.tr(),
|
heroSubtitle: 'server.description'.tr(),
|
||||||
|
|
|
@ -23,15 +23,13 @@ class _TextDetails extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
...details.metadata
|
...details.metadata.map(
|
||||||
.map(
|
(final metadata) => ListTileOnSurfaceVariant(
|
||||||
(final metadata) => ListTileOnSurfaceVariant(
|
leadingIcon: metadata.type.icon,
|
||||||
leadingIcon: metadata.type.icon,
|
title: metadata.name,
|
||||||
title: metadata.name,
|
subtitle: metadata.value,
|
||||||
subtitle: metadata.value,
|
),
|
||||||
),
|
),
|
||||||
)
|
|
||||||
.toList(),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -39,24 +37,6 @@ class _TextDetails extends StatelessWidget {
|
||||||
throw Exception('wrong state');
|
throw Exception('wrong state');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget getRowTitle(final String title) => Padding(
|
|
||||||
padding: const EdgeInsets.only(right: 10),
|
|
||||||
child: BrandText.h5(
|
|
||||||
title,
|
|
||||||
textAlign: TextAlign.right,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
Widget getRowValue(final String title, {final bool isBold = false}) =>
|
|
||||||
BrandText.body1(
|
|
||||||
title,
|
|
||||||
style: isBold
|
|
||||||
? const TextStyle(
|
|
||||||
fontWeight: NamedFontWeight.demiBold,
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _TempMessage extends StatelessWidget {
|
class _TempMessage extends StatelessWidget {
|
||||||
|
@ -69,7 +49,10 @@ class _TempMessage extends StatelessWidget {
|
||||||
Widget build(final BuildContext context) => SizedBox(
|
Widget build(final BuildContext context) => SizedBox(
|
||||||
height: MediaQuery.of(context).size.height - 100,
|
height: MediaQuery.of(context).size.height - 100,
|
||||||
child: Center(
|
child: Center(
|
||||||
child: BrandText.body2(message),
|
child: Text(
|
||||||
|
message,
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,66 +57,72 @@ class _SelectTimezoneState extends State<SelectTimezone> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(final BuildContext context) => Scaffold(
|
Widget build(final BuildContext context) {
|
||||||
appBar: AppBar(
|
final isDesktop = Breakpoints.mediumAndUp.isActive(context);
|
||||||
title: isSearching
|
return Scaffold(
|
||||||
? TextField(
|
appBar: AppBar(
|
||||||
readOnly: false,
|
automaticallyImplyLeading: false,
|
||||||
textAlign: TextAlign.start,
|
title: (isDesktop || isSearching)
|
||||||
textInputAction: TextInputAction.next,
|
? TextField(
|
||||||
enabled: true,
|
readOnly: false,
|
||||||
controller: searchController,
|
textAlign: TextAlign.start,
|
||||||
decoration: InputDecoration(
|
textInputAction: TextInputAction.next,
|
||||||
errorText: null,
|
enabled: true,
|
||||||
hintText: 'server.timezone_search_bar'.tr(),
|
controller: searchController,
|
||||||
),
|
decoration: InputDecoration(
|
||||||
)
|
errorText: null,
|
||||||
: Padding(
|
hintText: 'server.timezone_search_bar'.tr(),
|
||||||
padding: const EdgeInsets.only(top: 4.0),
|
|
||||||
child: Text('server.select_timezone'.tr()),
|
|
||||||
),
|
),
|
||||||
leading: IconButton(
|
)
|
||||||
icon: const Icon(Icons.arrow_back),
|
: Padding(
|
||||||
onPressed: isSearching
|
padding: const EdgeInsets.only(top: 4.0),
|
||||||
? () => setState(() => isSearching = false)
|
child: Text('server.select_timezone'.tr()),
|
||||||
: () => Navigator.of(context).pop(),
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
if (!isSearching)
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Icons.search),
|
|
||||||
onPressed: () => setState(() => isSearching = true),
|
|
||||||
),
|
),
|
||||||
],
|
leading: !isDesktop
|
||||||
|
? IconButton(
|
||||||
|
icon: const Icon(Icons.arrow_back),
|
||||||
|
onPressed: isSearching
|
||||||
|
? () => setState(() => isSearching = false)
|
||||||
|
: () => Navigator.of(context).pop(),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
actions: [
|
||||||
|
if (!isSearching && !isDesktop)
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.search),
|
||||||
|
onPressed: () => setState(() => isSearching = true),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
body: SafeArea(
|
||||||
|
child: ListView(
|
||||||
|
controller: scrollController,
|
||||||
|
children: locations
|
||||||
|
.where(
|
||||||
|
(final Location location) => timezoneFilterValue == null
|
||||||
|
? true
|
||||||
|
: location.name
|
||||||
|
.toLowerCase()
|
||||||
|
.contains(timezoneFilterValue!) ||
|
||||||
|
Duration(
|
||||||
|
milliseconds: location.currentTimeZone.offset,
|
||||||
|
)
|
||||||
|
.toDayHourMinuteFormat()
|
||||||
|
.contains(timezoneFilterValue!),
|
||||||
|
)
|
||||||
|
.toList()
|
||||||
|
.asMap()
|
||||||
|
.map(
|
||||||
|
(final key, final value) => locationToListTile(key, value),
|
||||||
|
)
|
||||||
|
.values
|
||||||
|
.toList(),
|
||||||
),
|
),
|
||||||
body: SafeArea(
|
),
|
||||||
child: ListView(
|
);
|
||||||
controller: scrollController,
|
}
|
||||||
children: locations
|
|
||||||
.where(
|
|
||||||
(final Location location) => timezoneFilterValue == null
|
|
||||||
? true
|
|
||||||
: location.name
|
|
||||||
.toLowerCase()
|
|
||||||
.contains(timezoneFilterValue!) ||
|
|
||||||
Duration(
|
|
||||||
milliseconds: location.currentTimeZone.offset,
|
|
||||||
)
|
|
||||||
.toDayHourMinuteFormat()
|
|
||||||
.contains(timezoneFilterValue!),
|
|
||||||
)
|
|
||||||
.toList()
|
|
||||||
.asMap()
|
|
||||||
.map(
|
|
||||||
(final key, final value) => locationToListTile(key, value),
|
|
||||||
)
|
|
||||||
.values
|
|
||||||
.toList(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
MapEntry<int, Container> locationToListTile(
|
MapEntry<int, ListTile> locationToListTile(
|
||||||
final int key,
|
final int key,
|
||||||
final Location location,
|
final Location location,
|
||||||
) {
|
) {
|
||||||
|
@ -126,46 +132,19 @@ class _SelectTimezoneState extends State<SelectTimezone> {
|
||||||
|
|
||||||
return MapEntry(
|
return MapEntry(
|
||||||
key,
|
key,
|
||||||
Container(
|
ListTile(
|
||||||
height: 75,
|
title: Text(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
location.name,
|
||||||
decoration: const BoxDecoration(
|
|
||||||
border: Border(
|
|
||||||
bottom: BorderSide(
|
|
||||||
color: BrandColors.dividerColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
child: InkWell(
|
subtitle: Text(
|
||||||
onTap: () {
|
'GMT ${duration.toDayHourMinuteFormat()} ${area.isNotEmpty ? '($area)' : ''}',
|
||||||
context.read<ServerDetailsCubit>().repository.setTimezone(
|
|
||||||
location.name,
|
|
||||||
);
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
BrandText.body1(
|
|
||||||
location.name,
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
BrandText.small(
|
|
||||||
'GMT ${duration.toDayHourMinuteFormat()} ${area.isNotEmpty ? '($area)' : ''}',
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 13,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
onTap: () {
|
||||||
|
context.read<ServerDetailsCubit>().repository.setTimezone(
|
||||||
|
location.name,
|
||||||
|
);
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@ import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/server_jobs/server_jobs_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/models/json/server_job.dart';
|
import 'package:selfprivacy/logic/models/json/server_job.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_linear_indicator/brand_linear_indicator.dart';
|
import 'package:selfprivacy/ui/components/brand_linear_indicator/brand_linear_indicator.dart';
|
||||||
import 'package:selfprivacy/ui/pages/root_route.dart';
|
import 'package:selfprivacy/ui/pages/root_route.dart';
|
||||||
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
||||||
|
|
|
@ -1,21 +1,19 @@
|
||||||
|
import 'package:auto_route/auto_route.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/logic/cubit/server_jobs/server_jobs_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/server_jobs/server_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/disk_size.dart';
|
import 'package:selfprivacy/logic/models/disk_size.dart';
|
||||||
import 'package:selfprivacy/logic/models/service.dart';
|
import 'package:selfprivacy/logic/models/service.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart';
|
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_button/brand_button.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/info_box/info_box.dart';
|
import 'package:selfprivacy/ui/components/info_box/info_box.dart';
|
||||||
import 'package:selfprivacy/logic/models/disk_status.dart';
|
import 'package:selfprivacy/logic/models/disk_status.dart';
|
||||||
import 'package:selfprivacy/ui/components/jobs_content/jobs_content.dart';
|
import 'package:selfprivacy/ui/components/jobs_content/jobs_content.dart';
|
||||||
import 'package:selfprivacy/ui/components/storage_list_items/server_storage_list_item.dart';
|
import 'package:selfprivacy/ui/components/storage_list_items/server_storage_list_item.dart';
|
||||||
import 'package:selfprivacy/ui/components/storage_list_items/service_migration_list_item.dart';
|
import 'package:selfprivacy/ui/components/storage_list_items/service_migration_list_item.dart';
|
||||||
import 'package:selfprivacy/ui/helpers/modals.dart';
|
|
||||||
import 'package:selfprivacy/ui/pages/root_route.dart';
|
|
||||||
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
|
||||||
|
|
||||||
|
@RoutePage()
|
||||||
class ServicesMigrationPage extends StatefulWidget {
|
class ServicesMigrationPage extends StatefulWidget {
|
||||||
const ServicesMigrationPage({
|
const ServicesMigrationPage({
|
||||||
required this.services,
|
required this.services,
|
||||||
|
@ -110,22 +108,20 @@ class _ServicesMigrationPageState extends State<ServicesMigrationPage> {
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
...widget.diskStatus.diskVolumes
|
...widget.diskStatus.diskVolumes.map(
|
||||||
.map(
|
(final volume) => Column(
|
||||||
(final volume) => Column(
|
children: [
|
||||||
children: [
|
ServerStorageListItem(
|
||||||
ServerStorageListItem(
|
volume: recalculatedDiskUsages(
|
||||||
volume: recalculatedDiskUsages(
|
volume,
|
||||||
volume,
|
widget.services,
|
||||||
widget.services,
|
),
|
||||||
),
|
dense: true,
|
||||||
dense: true,
|
|
||||||
),
|
|
||||||
const SizedBox(height: headerVerticalPadding),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
)
|
const SizedBox(height: headerVerticalPadding),
|
||||||
.toList(),
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -138,23 +134,21 @@ class _ServicesMigrationPageState extends State<ServicesMigrationPage> {
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
if (widget.services.isEmpty)
|
if (widget.services.isEmpty)
|
||||||
const Center(child: CircularProgressIndicator()),
|
const Center(child: CircularProgressIndicator()),
|
||||||
...widget.services
|
...widget.services.map(
|
||||||
.map(
|
(final service) => Column(
|
||||||
(final service) => Column(
|
children: [
|
||||||
children: [
|
const SizedBox(height: 8),
|
||||||
const SizedBox(height: 8),
|
ServiceMigrationListItem(
|
||||||
ServiceMigrationListItem(
|
service: service,
|
||||||
service: service,
|
diskStatus: widget.diskStatus,
|
||||||
diskStatus: widget.diskStatus,
|
selectedVolume: serviceToDisk[service.id]!,
|
||||||
selectedVolume: serviceToDisk[service.id]!,
|
onChange: onChange,
|
||||||
onChange: onChange,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 4),
|
|
||||||
const Divider(),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
)
|
const SizedBox(height: 4),
|
||||||
.toList(),
|
const Divider(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: InfoBox(
|
child: InfoBox(
|
||||||
|
@ -180,17 +174,10 @@ class _ServicesMigrationPageState extends State<ServicesMigrationPage> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Navigator.of(context).pushAndRemoveUntil(
|
context.router.popUntilRoot();
|
||||||
materialRoute(const RootPage()),
|
showModalBottomSheet(
|
||||||
(final predicate) => false,
|
|
||||||
);
|
|
||||||
showBrandBottomSheet(
|
|
||||||
context: context,
|
context: context,
|
||||||
builder: (final BuildContext context) =>
|
builder: (final BuildContext context) => const JobsContent(),
|
||||||
const BrandBottomSheet(
|
|
||||||
isExpended: true,
|
|
||||||
child: JobsContent(),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:auto_route/auto_route.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/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_dependend_cubit.dart';
|
||||||
|
@ -5,12 +6,11 @@ import 'package:selfprivacy/logic/cubit/provider_volumes/provider_volume_cubit.d
|
||||||
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/disk_size.dart';
|
import 'package:selfprivacy/logic/models/disk_size.dart';
|
||||||
import 'package:selfprivacy/logic/models/price.dart';
|
import 'package:selfprivacy/logic/models/price.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
|
||||||
import 'package:selfprivacy/logic/models/disk_status.dart';
|
import 'package:selfprivacy/logic/models/disk_status.dart';
|
||||||
import 'package:selfprivacy/ui/pages/root_route.dart';
|
|
||||||
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
|
||||||
|
|
||||||
|
@RoutePage()
|
||||||
class ExtendingVolumePage extends StatefulWidget {
|
class ExtendingVolumePage extends StatefulWidget {
|
||||||
const ExtendingVolumePage({
|
const ExtendingVolumePage({
|
||||||
required this.diskVolumeToResize,
|
required this.diskVolumeToResize,
|
||||||
|
@ -155,10 +155,7 @@ class _ExtendingVolumePageState extends State<ExtendingVolumePage> {
|
||||||
DiskSize.fromGibibyte(_currentSliderGbValue),
|
DiskSize.fromGibibyte(_currentSliderGbValue),
|
||||||
context.read<ApiServerVolumeCubit>().reload,
|
context.read<ApiServerVolumeCubit>().reload,
|
||||||
);
|
);
|
||||||
Navigator.of(context).pushAndRemoveUntil(
|
context.router.popUntilRoot();
|
||||||
materialRoute(const RootPage()),
|
|
||||||
(final predicate) => false,
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
child: Text('storage.extend_volume_button.title'.tr()),
|
child: Text('storage.extend_volume_button.title'.tr()),
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
|
import 'package:auto_route/auto_route.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:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.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/services/services_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/models/service.dart';
|
import 'package:selfprivacy/logic/models/service.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_button/outlined_button.dart';
|
import 'package:selfprivacy/ui/components/buttons/outlined_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
|
||||||
import 'package:selfprivacy/logic/models/disk_status.dart';
|
import 'package:selfprivacy/logic/models/disk_status.dart';
|
||||||
import 'package:selfprivacy/ui/pages/server_storage/extending_volume.dart';
|
|
||||||
import 'package:selfprivacy/ui/components/storage_list_items/server_storage_list_item.dart';
|
import 'package:selfprivacy/ui/components/storage_list_items/server_storage_list_item.dart';
|
||||||
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
import 'package:selfprivacy/ui/router/router.dart';
|
||||||
|
|
||||||
|
@RoutePage()
|
||||||
class ServerStoragePage extends StatefulWidget {
|
class ServerStoragePage extends StatefulWidget {
|
||||||
const ServerStoragePage({
|
const ServerStoragePage({
|
||||||
required this.diskStatus,
|
required this.diskStatus,
|
||||||
|
@ -45,28 +46,26 @@ class _ServerStoragePageState extends State<ServerStoragePage> {
|
||||||
heroTitle: 'storage.card_title'.tr(),
|
heroTitle: 'storage.card_title'.tr(),
|
||||||
children: [
|
children: [
|
||||||
// ...sections,
|
// ...sections,
|
||||||
...widget.diskStatus.diskVolumes
|
...widget.diskStatus.diskVolumes.map(
|
||||||
.map(
|
(final volume) => Column(
|
||||||
(final volume) => Column(
|
mainAxisSize: MainAxisSize.min,
|
||||||
mainAxisSize: MainAxisSize.min,
|
children: [
|
||||||
children: [
|
ServerStorageSection(
|
||||||
ServerStorageSection(
|
volume: volume,
|
||||||
volume: volume,
|
diskStatus: widget.diskStatus,
|
||||||
diskStatus: widget.diskStatus,
|
services: services
|
||||||
services: services
|
.where(
|
||||||
.where(
|
(final service) =>
|
||||||
(final service) =>
|
service.storageUsage.volume == volume.name,
|
||||||
service.storageUsage.volume == volume.name,
|
)
|
||||||
)
|
.toList(),
|
||||||
.toList(),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
const Divider(),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
)
|
const SizedBox(height: 16),
|
||||||
.toList(),
|
const Divider(),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -93,24 +92,20 @@ class ServerStorageSection extends StatelessWidget {
|
||||||
volume: volume,
|
volume: volume,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
...services
|
...services.map(
|
||||||
.map(
|
(final service) => ServerConsumptionListTile(
|
||||||
(final service) => ServerConsumptionListTile(
|
service: service,
|
||||||
service: service,
|
volume: volume,
|
||||||
volume: volume,
|
),
|
||||||
),
|
),
|
||||||
)
|
|
||||||
.toList(),
|
|
||||||
if (volume.isResizable) ...[
|
if (volume.isResizable) ...[
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
BrandOutlinedButton(
|
BrandOutlinedButton(
|
||||||
title: 'storage.extend_volume_button.title'.tr(),
|
title: 'storage.extend_volume_button.title'.tr(),
|
||||||
onPressed: () => Navigator.of(context).push(
|
onPressed: () => context.pushRoute(
|
||||||
materialRoute(
|
ExtendingVolumeRoute(
|
||||||
ExtendingVolumePage(
|
diskVolumeToResize: volume,
|
||||||
diskVolumeToResize: volume,
|
diskStatus: diskStatus,
|
||||||
diskStatus: diskStatus,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
|
import 'package:auto_route/auto_route.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/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/icon_status_mask/icon_status_mask.dart';
|
import 'package:selfprivacy/ui/components/icon_status_mask/icon_status_mask.dart';
|
||||||
import 'package:selfprivacy/logic/models/disk_status.dart';
|
import 'package:selfprivacy/logic/models/disk_status.dart';
|
||||||
import 'package:selfprivacy/ui/pages/server_storage/server_storage.dart';
|
|
||||||
import 'package:selfprivacy/ui/components/storage_list_items/server_storage_list_item.dart';
|
import 'package:selfprivacy/ui/components/storage_list_items/server_storage_list_item.dart';
|
||||||
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
import 'package:selfprivacy/ui/router/router.dart';
|
||||||
|
|
||||||
class StorageCard extends StatelessWidget {
|
class StorageCard extends StatelessWidget {
|
||||||
const StorageCard({
|
const StorageCard({
|
||||||
|
@ -45,13 +45,8 @@ class StorageCard extends StatelessWidget {
|
||||||
clipBehavior: Clip.antiAlias,
|
clipBehavior: Clip.antiAlias,
|
||||||
child: InkResponse(
|
child: InkResponse(
|
||||||
highlightShape: BoxShape.rectangle,
|
highlightShape: BoxShape.rectangle,
|
||||||
onTap: () => Navigator.of(context).push(
|
onTap: () =>
|
||||||
materialRoute(
|
context.pushRoute(ServerStorageRoute(diskStatus: diskStatus)),
|
||||||
ServerStoragePage(
|
|
||||||
diskStatus: diskStatus,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:auto_route/auto_route.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:flutter_svg/svg.dart';
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
@ -6,12 +7,12 @@ 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/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/filled_card.dart';
|
import 'package:selfprivacy/ui/components/cards/filled_card.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
|
||||||
import 'package:selfprivacy/ui/pages/server_storage/binds_migration/services_migration.dart';
|
import 'package:selfprivacy/ui/router/router.dart';
|
||||||
import 'package:selfprivacy/utils/launch_url.dart';
|
import 'package:selfprivacy/utils/launch_url.dart';
|
||||||
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
|
||||||
|
|
||||||
|
@RoutePage()
|
||||||
class ServicePage extends StatefulWidget {
|
class ServicePage extends StatefulWidget {
|
||||||
const ServicePage({required this.serviceId, super.key});
|
const ServicePage({required this.serviceId, super.key});
|
||||||
|
|
||||||
|
@ -46,11 +47,15 @@ class _ServicePageState extends State<ServicePage> {
|
||||||
|
|
||||||
return BrandHeroScreen(
|
return BrandHeroScreen(
|
||||||
hasBackButton: true,
|
hasBackButton: true,
|
||||||
|
hasFlashButton: true,
|
||||||
heroIconWidget: SvgPicture.string(
|
heroIconWidget: SvgPicture.string(
|
||||||
service.svgIcon,
|
service.svgIcon,
|
||||||
width: 48.0,
|
width: 48.0,
|
||||||
height: 48.0,
|
height: 48.0,
|
||||||
color: Theme.of(context).colorScheme.onBackground,
|
colorFilter: ColorFilter.mode(
|
||||||
|
Theme.of(context).colorScheme.onBackground,
|
||||||
|
BlendMode.srcIn,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
heroTitle: service.displayName,
|
heroTitle: service.displayName,
|
||||||
children: [
|
children: [
|
||||||
|
@ -108,14 +113,12 @@ class _ServicePageState extends State<ServicePage> {
|
||||||
ListTile(
|
ListTile(
|
||||||
iconColor: Theme.of(context).colorScheme.onBackground,
|
iconColor: Theme.of(context).colorScheme.onBackground,
|
||||||
// Open page ServicesMigrationPage
|
// Open page ServicesMigrationPage
|
||||||
onTap: () => Navigator.of(context).push(
|
onTap: () => context.pushRoute(
|
||||||
materialRoute(
|
ServicesMigrationRoute(
|
||||||
ServicesMigrationPage(
|
services: [service],
|
||||||
services: [service],
|
diskStatus:
|
||||||
diskStatus:
|
context.read<ApiServerVolumeCubit>().state.diskStatus,
|
||||||
context.read<ApiServerVolumeCubit>().state.diskStatus,
|
isMigration: false,
|
||||||
isMigration: false,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
leading: const Icon(Icons.drive_file_move_outlined),
|
leading: const Icon(Icons.drive_file_move_outlined),
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:selfprivacy/config/brand_theme.dart';
|
import 'package:selfprivacy/config/brand_theme.dart';
|
||||||
|
@ -5,17 +6,16 @@ import 'package:selfprivacy/logic/cubit/server_installation/server_installation_
|
||||||
import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/services/services_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/models/service.dart';
|
import 'package:selfprivacy/logic/models/service.dart';
|
||||||
import 'package:selfprivacy/logic/models/state_types.dart';
|
import 'package:selfprivacy/logic/models/state_types.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/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:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:selfprivacy/ui/pages/services/service_page.dart';
|
import 'package:selfprivacy/ui/router/router.dart';
|
||||||
|
import 'package:selfprivacy/utils/breakpoints.dart';
|
||||||
import 'package:selfprivacy/utils/launch_url.dart';
|
import 'package:selfprivacy/utils/launch_url.dart';
|
||||||
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
|
||||||
import 'package:selfprivacy/utils/ui_helpers.dart';
|
import 'package:selfprivacy/utils/ui_helpers.dart';
|
||||||
|
|
||||||
|
@RoutePage()
|
||||||
class ServicesPage extends StatefulWidget {
|
class ServicesPage extends StatefulWidget {
|
||||||
const ServicesPage({super.key});
|
const ServicesPage({super.key});
|
||||||
|
|
||||||
|
@ -34,32 +34,35 @@ class _ServicesPageState extends State<ServicesPage> {
|
||||||
.sort((final a, final b) => a.status.index.compareTo(b.status.index));
|
.sort((final a, final b) => a.status.index.compareTo(b.status.index));
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: PreferredSize(
|
appBar: Breakpoints.small.isActive(context)
|
||||||
preferredSize: const Size.fromHeight(52),
|
? PreferredSize(
|
||||||
child: BrandHeader(
|
preferredSize: const Size.fromHeight(52),
|
||||||
title: 'basis.services'.tr(),
|
child: BrandHeader(
|
||||||
),
|
title: 'basis.services'.tr(),
|
||||||
),
|
),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
body: RefreshIndicator(
|
body: RefreshIndicator(
|
||||||
onRefresh: () async {
|
onRefresh: () async {
|
||||||
context.read<ServicesCubit>().reload();
|
await context.read<ServicesCubit>().reload();
|
||||||
},
|
},
|
||||||
child: ListView(
|
child: ListView(
|
||||||
padding: paddingH15V0,
|
padding: paddingH15V0,
|
||||||
children: [
|
children: [
|
||||||
BrandText.body1('basis.services_title'.tr()),
|
Text(
|
||||||
|
'basis.services_title'.tr(),
|
||||||
|
style: Theme.of(context).textTheme.bodyLarge,
|
||||||
|
),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
if (!isReady) ...[const NotReadyCard(), const SizedBox(height: 24)],
|
if (!isReady) ...[const NotReadyCard(), const SizedBox(height: 24)],
|
||||||
...services
|
...services.map(
|
||||||
.map(
|
(final service) => Padding(
|
||||||
(final service) => Padding(
|
padding: const EdgeInsets.only(
|
||||||
padding: const EdgeInsets.only(
|
bottom: 30,
|
||||||
bottom: 30,
|
),
|
||||||
),
|
child: _Card(service: service),
|
||||||
child: _Card(service: service),
|
),
|
||||||
),
|
)
|
||||||
)
|
|
||||||
.toList()
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -98,81 +101,106 @@ class _Card extends StatelessWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return GestureDetector(
|
return Card(
|
||||||
onTap: isReady
|
clipBehavior: Clip.antiAlias,
|
||||||
? () => Navigator.of(context)
|
child: InkResponse(
|
||||||
.push(materialRoute(ServicePage(serviceId: service.id)))
|
highlightShape: BoxShape.rectangle,
|
||||||
: null,
|
onTap: isReady
|
||||||
child: BrandCards.big(
|
? () => context.pushRoute(
|
||||||
child: Column(
|
ServiceRoute(serviceId: service.id),
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
)
|
||||||
children: [
|
: null,
|
||||||
Row(
|
child: Padding(
|
||||||
children: [
|
padding: const EdgeInsets.all(16.0),
|
||||||
IconStatusMask(
|
child: Column(
|
||||||
status: getStatus(service.status),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
icon: SvgPicture.string(
|
children: [
|
||||||
service.svgIcon,
|
Row(
|
||||||
width: 30.0,
|
|
||||||
height: 30.0,
|
|
||||||
color: Theme.of(context).colorScheme.onBackground,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
ClipRect(
|
|
||||||
child: Stack(
|
|
||||||
children: [
|
children: [
|
||||||
Column(
|
IconStatusMask(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
status: getStatus(service.status),
|
||||||
children: [
|
icon: SvgPicture.string(
|
||||||
const SizedBox(height: 10),
|
service.svgIcon,
|
||||||
BrandText.h2(service.displayName),
|
width: 30.0,
|
||||||
const SizedBox(height: 10),
|
height: 30.0,
|
||||||
if (service.url != '' && service.url != null)
|
colorFilter: const ColorFilter.mode(
|
||||||
Column(
|
Colors.white,
|
||||||
children: [
|
BlendMode.srcIn,
|
||||||
GestureDetector(
|
),
|
||||||
onTap: () => launchURL(
|
),
|
||||||
service.url,
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
'${service.url}',
|
|
||||||
style: TextStyle(
|
|
||||||
color:
|
|
||||||
Theme.of(context).colorScheme.secondary,
|
|
||||||
decoration: TextDecoration.underline,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
if (service.id == 'mailserver')
|
|
||||||
Column(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
domainName,
|
|
||||||
style: TextStyle(
|
|
||||||
color: Theme.of(context).colorScheme.primary,
|
|
||||||
decoration: TextDecoration.underline,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
BrandText.body2(service.loginInfo),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
BrandText.body2(service.description),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
)
|
Column(
|
||||||
],
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
Text(
|
||||||
|
service.displayName,
|
||||||
|
style: Theme.of(context).textTheme.headlineMedium,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
if (service.url != '' && service.url != null)
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
_ServiceLink(
|
||||||
|
url: service.url ?? '',
|
||||||
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (service.id == 'mailserver')
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
_ServiceLink(
|
||||||
|
url: domainName,
|
||||||
|
isActive: false,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
service.loginInfo,
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
Text(
|
||||||
|
service.description,
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _ServiceLink extends StatelessWidget {
|
||||||
|
const _ServiceLink({
|
||||||
|
required this.url,
|
||||||
|
this.isActive = true,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String url;
|
||||||
|
final bool isActive;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(final BuildContext context) => GestureDetector(
|
||||||
|
onTap: isActive
|
||||||
|
? () => launchURL(
|
||||||
|
url,
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
child: Text(
|
||||||
|
url,
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
decoration: TextDecoration.underline,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:cubit_form/cubit_form.dart';
|
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_theme.dart';
|
|
||||||
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/provider_form_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/provider_form_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/forms/factories/field_cubit_factory.dart';
|
import 'package:selfprivacy/logic/cubit/forms/factories/field_cubit_factory.dart';
|
||||||
|
@ -9,18 +9,21 @@ import 'package:selfprivacy/logic/cubit/forms/setup/initializing/backblaze_form_
|
||||||
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/dns_provider_form_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/dns_provider_form_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/domain_setup_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/domain_setup_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/root_user_form_cubit.dart';
|
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/logic/cubit/support_system/support_system_cubit.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_md/brand_md.dart';
|
import 'package:selfprivacy/ui/components/buttons/outlined_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
|
|
||||||
import 'package:selfprivacy/ui/components/brand_timer/brand_timer.dart';
|
import 'package:selfprivacy/ui/components/brand_timer/brand_timer.dart';
|
||||||
|
import 'package:selfprivacy/ui/components/drawers/progress_drawer.dart';
|
||||||
import 'package:selfprivacy/ui/components/progress_bar/progress_bar.dart';
|
import 'package:selfprivacy/ui/components/progress_bar/progress_bar.dart';
|
||||||
import 'package:selfprivacy/ui/pages/root_route.dart';
|
import 'package:selfprivacy/ui/components/drawers/support_drawer.dart';
|
||||||
|
import 'package:selfprivacy/ui/layouts/responsive_layout_with_infobox.dart';
|
||||||
import 'package:selfprivacy/ui/pages/setup/initializing/server_provider_picker.dart';
|
import 'package:selfprivacy/ui/pages/setup/initializing/server_provider_picker.dart';
|
||||||
import 'package:selfprivacy/ui/pages/setup/initializing/server_type_picker.dart';
|
import 'package:selfprivacy/ui/pages/setup/initializing/server_type_picker.dart';
|
||||||
import 'package:selfprivacy/ui/pages/setup/recovering/recovery_routing.dart';
|
import 'package:selfprivacy/ui/pages/setup/recovering/recovery_routing.dart';
|
||||||
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
import 'package:selfprivacy/ui/router/router.dart';
|
||||||
|
import 'package:selfprivacy/utils/breakpoints.dart';
|
||||||
|
|
||||||
|
@RoutePage()
|
||||||
class InitializingPage extends StatelessWidget {
|
class InitializingPage extends StatelessWidget {
|
||||||
const InitializingPage({super.key});
|
const InitializingPage({super.key});
|
||||||
|
|
||||||
|
@ -48,99 +51,155 @@ class InitializingPage extends StatelessWidget {
|
||||||
][cubit.state.progress.index]();
|
][cubit.state.progress.index]();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const steps = [
|
||||||
|
'initializing.steps.hosting',
|
||||||
|
'initializing.steps.server_type',
|
||||||
|
'initializing.steps.dns_provider',
|
||||||
|
'initializing.steps.backups_provider',
|
||||||
|
'initializing.steps.domain',
|
||||||
|
'initializing.steps.master_account',
|
||||||
|
'initializing.steps.server',
|
||||||
|
'initializing.steps.dns_setup',
|
||||||
|
'initializing.steps.nixos_installation',
|
||||||
|
'initializing.steps.server_reboot',
|
||||||
|
'initializing.steps.final_checks',
|
||||||
|
];
|
||||||
|
|
||||||
return BlocListener<ServerInstallationCubit, ServerInstallationState>(
|
return BlocListener<ServerInstallationCubit, ServerInstallationState>(
|
||||||
listener: (final context, final state) {
|
listener: (final context, final state) {
|
||||||
if (cubit.state is ServerInstallationFinished) {
|
if (cubit.state is ServerInstallationFinished) {
|
||||||
Navigator.of(context)
|
context.router.popUntilRoot();
|
||||||
.pushReplacement(materialRoute(const RootPage()));
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: AppBar(
|
endDrawer: const SupportDrawer(),
|
||||||
actions: [
|
endDrawerEnableOpenDragGesture: false,
|
||||||
if (cubit.state is ServerInstallationFinished)
|
appBar: Breakpoints.large.isActive(context)
|
||||||
IconButton(
|
? null
|
||||||
icon: const Icon(Icons.check),
|
: AppBar(
|
||||||
onPressed: () {
|
actions: [
|
||||||
Navigator.of(context)
|
if (cubit.state is ServerInstallationFinished)
|
||||||
.pushReplacement(materialRoute(const RootPage()));
|
IconButton(
|
||||||
},
|
icon: const Icon(Icons.check),
|
||||||
)
|
onPressed: () {
|
||||||
],
|
context.router.popUntilRoot();
|
||||||
title: Text(
|
},
|
||||||
'more_page.configuration_wizard'.tr(),
|
|
||||||
),
|
|
||||||
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,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
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: [
|
|
||||||
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 ||
|
const SizedBox.shrink(),
|
||||||
cubit.state is ServerInstallationNotFinished)
|
],
|
||||||
Container(
|
title: Text(
|
||||||
alignment: Alignment.center,
|
'more_page.configuration_wizard'.tr(),
|
||||||
child: BrandButton.text(
|
),
|
||||||
title: 'basis.connect_to_existing'.tr(),
|
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: LayoutBuilder(
|
||||||
|
builder: (final context, final constraints) => Row(
|
||||||
|
children: [
|
||||||
|
if (Breakpoints.large.isActive(context))
|
||||||
|
ProgressDrawer(
|
||||||
|
steps: steps,
|
||||||
|
currentStep: cubit.state.progress.index,
|
||||||
|
title: 'more_page.configuration_wizard'.tr(),
|
||||||
|
constraints: constraints,
|
||||||
|
trailing: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
if (cubit.state is ServerInstallationEmpty ||
|
||||||
|
cubit.state is ServerInstallationNotFinished)
|
||||||
|
Container(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: BrandButton.filled(
|
||||||
|
text: 'basis.connect_to_existing'.tr(),
|
||||||
|
onPressed: () {
|
||||||
|
context.router.replace(const RecoveryRoute());
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ConstrainedBox(
|
||||||
|
constraints: const BoxConstraints(
|
||||||
|
minWidth: double.infinity,
|
||||||
|
),
|
||||||
|
child: OutlinedButton(
|
||||||
|
child: Text(
|
||||||
|
cubit.state is ServerInstallationFinished
|
||||||
|
? 'basis.close'.tr()
|
||||||
|
: 'basis.later'.tr(),
|
||||||
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).push(
|
context.router.popUntilRoot();
|
||||||
materialRoute(
|
|
||||||
const RecoveryRouting(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: constraints.maxWidth -
|
||||||
|
(Breakpoints.large.isActive(context) ? 300 : 0),
|
||||||
|
height: constraints.maxHeight,
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: Breakpoints.large.isActive(context)
|
||||||
|
? const EdgeInsets.all(16.0)
|
||||||
|
: const EdgeInsets.fromLTRB(16.0, 0, 16.0, 0.0),
|
||||||
|
child: AnimatedSwitcher(
|
||||||
|
duration: const Duration(milliseconds: 300),
|
||||||
|
child: actualInitializingPage,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (!Breakpoints.large.isActive(context))
|
||||||
|
Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: BrandButton.text(
|
||||||
|
title:
|
||||||
|
cubit.state is ServerInstallationFinished
|
||||||
|
? 'basis.close'.tr()
|
||||||
|
: 'basis.later'.tr(),
|
||||||
|
onPressed: () {
|
||||||
|
context.router.popUntilRoot();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (cubit.state is ServerInstallationEmpty ||
|
||||||
|
cubit.state is ServerInstallationNotFinished)
|
||||||
|
Container(
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: BrandButton.text(
|
||||||
|
title: 'basis.connect_to_existing'.tr(),
|
||||||
|
onPressed: () {
|
||||||
|
context.router
|
||||||
|
.replace(const RecoveryRoute());
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -179,57 +238,55 @@ class InitializingPage extends StatelessWidget {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
void _showModal(final BuildContext context, final Widget widget) {
|
|
||||||
showModalBottomSheet<void>(
|
|
||||||
context: context,
|
|
||||||
isScrollControlled: true,
|
|
||||||
backgroundColor: Colors.transparent,
|
|
||||||
builder: (final BuildContext context) => widget,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _stepCloudflare(final ServerInstallationCubit initializingCubit) =>
|
Widget _stepCloudflare(final ServerInstallationCubit initializingCubit) =>
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (final context) => DnsProviderFormCubit(initializingCubit),
|
create: (final context) => DnsProviderFormCubit(initializingCubit),
|
||||||
child: Builder(
|
child: Builder(
|
||||||
builder: (final context) => Column(
|
builder: (final context) => ResponsiveLayoutWithInfobox(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
topChild: Column(
|
||||||
children: [
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
Text(
|
children: [
|
||||||
'${'initializing.connect_to_server_provider'.tr()}Cloudflare',
|
Text(
|
||||||
style: Theme.of(context).textTheme.headlineSmall,
|
'${'initializing.connect_to_server_provider'.tr()}Cloudflare',
|
||||||
),
|
style: Theme.of(context).textTheme.headlineSmall,
|
||||||
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,
|
|
||||||
scrollPadding: const EdgeInsets.only(bottom: 70),
|
|
||||||
decoration: InputDecoration(
|
|
||||||
hintText: 'initializing.cloudflare_api_token'.tr(),
|
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(height: 16),
|
||||||
const SizedBox(height: 32),
|
Text(
|
||||||
BrandButton.rised(
|
'initializing.manage_domain_dns'.tr(),
|
||||||
onPressed: () =>
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
context.read<DnsProviderFormCubit>().trySubmit(),
|
),
|
||||||
text: 'basis.connect'.tr(),
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 10),
|
primaryColumn: Column(
|
||||||
BrandButton.text(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
onPressed: () => _showModal(
|
children: [
|
||||||
context,
|
CubitFormTextField(
|
||||||
const _HowTo(
|
formFieldCubit: context.read<DnsProviderFormCubit>().apiKey,
|
||||||
fileName: 'how_cloudflare',
|
textAlign: TextAlign.center,
|
||||||
|
scrollPadding: const EdgeInsets.only(bottom: 70),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: 'initializing.cloudflare_api_token'.tr(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
title: 'initializing.how'.tr(),
|
const SizedBox(height: 32),
|
||||||
),
|
BrandButton.filled(
|
||||||
],
|
onPressed: () =>
|
||||||
|
context.read<DnsProviderFormCubit>().trySubmit(),
|
||||||
|
text: 'basis.connect'.tr(),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
BrandOutlinedButton(
|
||||||
|
onPressed: () {
|
||||||
|
context.read<SupportSystemCubit>().showArticle(
|
||||||
|
article: 'how_cloudflare',
|
||||||
|
context: context,
|
||||||
|
);
|
||||||
|
Scaffold.of(context).openEndDrawer();
|
||||||
|
},
|
||||||
|
title: 'initializing.how'.tr(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -240,50 +297,57 @@ class InitializingPage extends StatelessWidget {
|
||||||
child: Builder(
|
child: Builder(
|
||||||
builder: (final context) {
|
builder: (final context) {
|
||||||
final formCubitState = context.watch<BackblazeFormCubit>().state;
|
final formCubitState = context.watch<BackblazeFormCubit>().state;
|
||||||
return Column(
|
return ResponsiveLayoutWithInfobox(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
topChild: Column(
|
||||||
children: [
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
Text(
|
children: [
|
||||||
'${'initializing.connect_to_server_provider'.tr()}Backblaze',
|
Text(
|
||||||
style: Theme.of(context).textTheme.headlineSmall,
|
'${'initializing.connect_to_server_provider'.tr()}Backblaze',
|
||||||
),
|
style: Theme.of(context).textTheme.headlineSmall,
|
||||||
const SizedBox(height: 32),
|
|
||||||
CubitFormTextField(
|
|
||||||
formFieldCubit: context.read<BackblazeFormCubit>().keyId,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
scrollPadding: const EdgeInsets.only(bottom: 70),
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
hintText: 'KeyID',
|
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
const SizedBox(height: 16),
|
),
|
||||||
CubitFormTextField(
|
primaryColumn: Column(
|
||||||
formFieldCubit:
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
context.read<BackblazeFormCubit>().applicationKey,
|
children: [
|
||||||
textAlign: TextAlign.center,
|
CubitFormTextField(
|
||||||
scrollPadding: const EdgeInsets.only(bottom: 70),
|
formFieldCubit: context.read<BackblazeFormCubit>().keyId,
|
||||||
decoration: const InputDecoration(
|
textAlign: TextAlign.center,
|
||||||
hintText: 'Master Application Key',
|
scrollPadding: const EdgeInsets.only(bottom: 70),
|
||||||
),
|
decoration: const InputDecoration(
|
||||||
),
|
hintText: 'KeyID',
|
||||||
const SizedBox(height: 32),
|
|
||||||
BrandButton.rised(
|
|
||||||
onPressed: formCubitState.isSubmitting
|
|
||||||
? null
|
|
||||||
: () => context.read<BackblazeFormCubit>().trySubmit(),
|
|
||||||
text: 'basis.connect'.tr(),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
BrandButton.text(
|
|
||||||
onPressed: () => _showModal(
|
|
||||||
context,
|
|
||||||
const _HowTo(
|
|
||||||
fileName: 'how_backblaze',
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
title: 'initializing.how'.tr(),
|
const SizedBox(height: 16),
|
||||||
),
|
CubitFormTextField(
|
||||||
],
|
formFieldCubit:
|
||||||
|
context.read<BackblazeFormCubit>().applicationKey,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
scrollPadding: const EdgeInsets.only(bottom: 70),
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
hintText: 'Master Application Key',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 32),
|
||||||
|
BrandButton.rised(
|
||||||
|
onPressed: formCubitState.isSubmitting
|
||||||
|
? null
|
||||||
|
: () => context.read<BackblazeFormCubit>().trySubmit(),
|
||||||
|
text: 'basis.connect'.tr(),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
BrandButton.text(
|
||||||
|
onPressed: () {
|
||||||
|
context.read<SupportSystemCubit>().showArticle(
|
||||||
|
article: 'how_backblaze',
|
||||||
|
context: context,
|
||||||
|
);
|
||||||
|
Scaffold.of(context).openEndDrawer();
|
||||||
|
},
|
||||||
|
title: 'initializing.how'.tr(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -296,9 +360,8 @@ class InitializingPage extends StatelessWidget {
|
||||||
builder: (final context) {
|
builder: (final context) {
|
||||||
final DomainSetupState state =
|
final DomainSetupState state =
|
||||||
context.watch<DomainSetupCubit>().state;
|
context.watch<DomainSetupCubit>().state;
|
||||||
return SizedBox(
|
return ResponsiveLayoutWithInfobox(
|
||||||
width: double.infinity,
|
topChild: Column(
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
|
@ -310,7 +373,11 @@ class InitializingPage extends StatelessWidget {
|
||||||
'initializing.use_this_domain_text'.tr(),
|
'initializing.use_this_domain_text'.tr(),
|
||||||
style: Theme.of(context).textTheme.bodyMedium,
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 32),
|
],
|
||||||
|
),
|
||||||
|
primaryColumn: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
if (state is Empty)
|
if (state is Empty)
|
||||||
Text(
|
Text(
|
||||||
'initializing.no_connected_domains'.tr(),
|
'initializing.no_connected_domains'.tr(),
|
||||||
|
@ -350,7 +417,7 @@ class InitializingPage extends StatelessWidget {
|
||||||
],
|
],
|
||||||
if (state is Empty) ...[
|
if (state is Empty) ...[
|
||||||
const SizedBox(height: 30),
|
const SizedBox(height: 30),
|
||||||
BrandButton.rised(
|
BrandButton.filled(
|
||||||
onPressed: () => context.read<DomainSetupCubit>().load(),
|
onPressed: () => context.read<DomainSetupCubit>().load(),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
@ -360,14 +427,17 @@ class InitializingPage extends StatelessWidget {
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
BrandText.buttonTitleText('domain.update_list'.tr()),
|
Text(
|
||||||
|
'domain.update_list'.tr(),
|
||||||
|
style: Theme.of(context).textTheme.bodyLarge,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
if (state is Loaded) ...[
|
if (state is Loaded) ...[
|
||||||
const SizedBox(height: 32),
|
const SizedBox(height: 32),
|
||||||
BrandButton.rised(
|
BrandButton.filled(
|
||||||
onPressed: () =>
|
onPressed: () =>
|
||||||
context.read<DomainSetupCubit>().saveDomain(),
|
context.read<DomainSetupCubit>().saveDomain(),
|
||||||
text: 'initializing.save_domain'.tr(),
|
text: 'initializing.save_domain'.tr(),
|
||||||
|
@ -388,74 +458,83 @@ class InitializingPage extends StatelessWidget {
|
||||||
builder: (final context) {
|
builder: (final context) {
|
||||||
final formCubitState = context.watch<RootUserFormCubit>().state;
|
final formCubitState = context.watch<RootUserFormCubit>().state;
|
||||||
|
|
||||||
return Column(
|
return ResponsiveLayoutWithInfobox(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
topChild: Column(
|
||||||
children: [
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
Text(
|
children: [
|
||||||
'initializing.create_master_account'.tr(),
|
|
||||||
style: Theme.of(context).textTheme.headlineSmall,
|
|
||||||
),
|
|
||||||
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(
|
Text(
|
||||||
'users.username_rule'.tr(),
|
'initializing.create_master_account'.tr(),
|
||||||
style: TextStyle(
|
style: Theme.of(context).textTheme.headlineSmall,
|
||||||
color: Theme.of(context).colorScheme.error,
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Text(
|
||||||
|
'initializing.enter_username_and_password'.tr(),
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
primaryColumn: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
if (formCubitState.isErrorShown) const SizedBox(height: 16),
|
||||||
|
if (formCubitState.isErrorShown)
|
||||||
|
Text(
|
||||||
|
'users.username_rule'.tr(),
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).colorScheme.error,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 32),
|
||||||
|
CubitFormTextField(
|
||||||
|
formFieldCubit: context.read<RootUserFormCubit>().userName,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
scrollPadding: const EdgeInsets.only(bottom: 70),
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: 'basis.username'.tr(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 32),
|
const SizedBox(height: 16),
|
||||||
CubitFormTextField(
|
BlocBuilder<FieldCubit<bool>, FieldCubitState<bool>>(
|
||||||
formFieldCubit: context.read<RootUserFormCubit>().userName,
|
bloc: context.read<RootUserFormCubit>().isVisible,
|
||||||
textAlign: TextAlign.center,
|
builder: (final context, final state) {
|
||||||
scrollPadding: const EdgeInsets.only(bottom: 70),
|
final bool isVisible = state.value;
|
||||||
decoration: InputDecoration(
|
return CubitFormTextField(
|
||||||
hintText: 'basis.username'.tr(),
|
obscureText: !isVisible,
|
||||||
),
|
formFieldCubit:
|
||||||
),
|
context.read<RootUserFormCubit>().password,
|
||||||
const SizedBox(height: 16),
|
textAlign: TextAlign.center,
|
||||||
BlocBuilder<FieldCubit<bool>, FieldCubitState<bool>>(
|
scrollPadding: const EdgeInsets.only(bottom: 70),
|
||||||
bloc: context.read<RootUserFormCubit>().isVisible,
|
decoration: InputDecoration(
|
||||||
builder: (final context, final state) {
|
hintText: 'basis.password'.tr(),
|
||||||
final bool isVisible = state.value;
|
suffixIcon: IconButton(
|
||||||
return CubitFormTextField(
|
icon: Icon(
|
||||||
obscureText: !isVisible,
|
isVisible
|
||||||
formFieldCubit:
|
? Icons.visibility
|
||||||
context.read<RootUserFormCubit>().password,
|
: Icons.visibility_off,
|
||||||
textAlign: TextAlign.center,
|
),
|
||||||
scrollPadding: const EdgeInsets.only(bottom: 70),
|
onPressed: () => context
|
||||||
decoration: InputDecoration(
|
.read<RootUserFormCubit>()
|
||||||
hintText: 'basis.password'.tr(),
|
.isVisible
|
||||||
suffixIcon: IconButton(
|
.setValue(!isVisible),
|
||||||
icon: Icon(
|
|
||||||
isVisible ? Icons.visibility : Icons.visibility_off,
|
|
||||||
),
|
),
|
||||||
onPressed: () => context
|
suffixIconConstraints:
|
||||||
.read<RootUserFormCubit>()
|
const BoxConstraints(minWidth: 60),
|
||||||
.isVisible
|
prefixIconConstraints:
|
||||||
.setValue(!isVisible),
|
const BoxConstraints(maxWidth: 60),
|
||||||
|
prefixIcon: Container(),
|
||||||
),
|
),
|
||||||
suffixIconConstraints:
|
);
|
||||||
const BoxConstraints(minWidth: 60),
|
},
|
||||||
prefixIconConstraints:
|
),
|
||||||
const BoxConstraints(maxWidth: 60),
|
const SizedBox(height: 32),
|
||||||
prefixIcon: Container(),
|
BrandButton.filled(
|
||||||
),
|
onPressed: formCubitState.isSubmitting
|
||||||
);
|
? null
|
||||||
},
|
: () => context.read<RootUserFormCubit>().trySubmit(),
|
||||||
),
|
text: 'basis.connect'.tr(),
|
||||||
const SizedBox(height: 32),
|
),
|
||||||
BrandButton.rised(
|
],
|
||||||
onPressed: formCubitState.isSubmitting
|
),
|
||||||
? null
|
|
||||||
: () => context.read<RootUserFormCubit>().trySubmit(),
|
|
||||||
text: 'basis.connect'.tr(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -465,27 +544,28 @@ class InitializingPage extends StatelessWidget {
|
||||||
final bool isLoading =
|
final bool isLoading =
|
||||||
(appConfigCubit.state as ServerInstallationNotFinished).isLoading;
|
(appConfigCubit.state as ServerInstallationNotFinished).isLoading;
|
||||||
return Builder(
|
return Builder(
|
||||||
builder: (final context) => Column(
|
builder: (final context) => ResponsiveLayoutWithInfobox(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
topChild: Column(
|
||||||
children: [
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
Text(
|
children: [
|
||||||
'initializing.final'.tr(),
|
Text(
|
||||||
style: Theme.of(context).textTheme.headlineSmall,
|
'initializing.final'.tr(),
|
||||||
),
|
style: Theme.of(context).textTheme.headlineSmall,
|
||||||
const SizedBox(height: 16),
|
),
|
||||||
Text(
|
const SizedBox(height: 16),
|
||||||
'initializing.create_server'.tr(),
|
Text(
|
||||||
style: Theme.of(context).textTheme.bodyMedium,
|
'initializing.create_server'.tr(),
|
||||||
),
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
const SizedBox(height: 128),
|
),
|
||||||
BrandButton.rised(
|
],
|
||||||
onPressed:
|
),
|
||||||
isLoading ? null : appConfigCubit.createServerAndSetDnsRecords,
|
primaryColumn: BrandButton.filled(
|
||||||
text: isLoading
|
onPressed:
|
||||||
? 'basis.loading'.tr()
|
isLoading ? null : appConfigCubit.createServerAndSetDnsRecords,
|
||||||
: 'initializing.create_server'.tr(),
|
text: isLoading
|
||||||
),
|
? 'basis.loading'.tr()
|
||||||
],
|
: 'initializing.create_server'.tr(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -514,84 +594,67 @@ class InitializingPage extends StatelessWidget {
|
||||||
return Builder(
|
return Builder(
|
||||||
builder: (final context) => SizedBox(
|
builder: (final context) => SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: Column(
|
child: ResponsiveLayoutWithInfobox(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
topChild: Column(
|
||||||
children: [
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
Text(
|
children: [
|
||||||
'initializing.checks'.tr(args: [doneCount.toString(), '4']),
|
|
||||||
style: Theme.of(context).textTheme.headlineSmall,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
if (text != null)
|
|
||||||
Text(
|
Text(
|
||||||
text,
|
'initializing.checks'.tr(args: [doneCount.toString(), '4']),
|
||||||
style: Theme.of(context).textTheme.bodyMedium,
|
style: Theme.of(context).textTheme.headlineSmall,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 128),
|
const SizedBox(height: 16),
|
||||||
const SizedBox(height: 10),
|
if (text != null)
|
||||||
if (doneCount == 0 && state.dnsMatches != null)
|
Text(
|
||||||
Column(
|
text,
|
||||||
children: state.dnsMatches!.entries.map((final entry) {
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
final String domain = entry.key;
|
),
|
||||||
final bool isCorrect = entry.value;
|
],
|
||||||
return Row(
|
),
|
||||||
children: [
|
primaryColumn: Column(
|
||||||
if (isCorrect)
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
const Icon(Icons.check, color: Colors.green),
|
children: [
|
||||||
if (!isCorrect)
|
const SizedBox(height: 128),
|
||||||
const Icon(Icons.schedule, color: Colors.amber),
|
const SizedBox(height: 10),
|
||||||
const SizedBox(width: 10),
|
if (doneCount == 0 && state.dnsMatches != null)
|
||||||
Text(domain),
|
Column(
|
||||||
],
|
children: state.dnsMatches!.entries.map((final entry) {
|
||||||
);
|
final String domain = entry.key;
|
||||||
}).toList(),
|
final bool isCorrect = entry.value;
|
||||||
),
|
return Row(
|
||||||
const SizedBox(height: 10),
|
children: [
|
||||||
if (!state.isLoading)
|
if (isCorrect)
|
||||||
Row(
|
const Icon(Icons.check, color: Colors.green),
|
||||||
children: [
|
if (!isCorrect)
|
||||||
Text(
|
const Icon(Icons.schedule, color: Colors.amber),
|
||||||
'initializing.until_the_next_check'.tr(),
|
const SizedBox(width: 10),
|
||||||
style: Theme.of(context).textTheme.bodyMedium,
|
Text(domain),
|
||||||
),
|
],
|
||||||
BrandTimer(
|
);
|
||||||
startDateTime: state.timerStart!,
|
}).toList(),
|
||||||
duration: state.duration!,
|
),
|
||||||
)
|
const SizedBox(height: 10),
|
||||||
],
|
if (!state.isLoading)
|
||||||
),
|
Row(
|
||||||
if (state.isLoading)
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'initializing.check'.tr(),
|
'initializing.until_the_next_check'.tr(),
|
||||||
style: Theme.of(context).textTheme.bodyMedium,
|
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,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _HowTo extends StatelessWidget {
|
|
||||||
const _HowTo({
|
|
||||||
required this.fileName,
|
|
||||||
});
|
|
||||||
|
|
||||||
final String fileName;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(final BuildContext context) => BrandBottomSheet(
|
|
||||||
isExpended: true,
|
|
||||||
child: Padding(
|
|
||||||
padding: paddingH15V0,
|
|
||||||
child: ListView(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
|
||||||
children: [
|
|
||||||
BrandMarkdown(
|
|
||||||
fileName: fileName,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,16 +2,15 @@ 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:flutter_svg/flutter_svg.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/app_config_dependent/authentication_dependend_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/provider_form_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/provider_form_cubit.dart';
|
||||||
|
import 'package:selfprivacy/logic/cubit/support_system/support_system_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/models/hive/server_details.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/buttons/brand_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
import 'package:selfprivacy/ui/components/buttons/outlined_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_button/outlined_button.dart';
|
import 'package:selfprivacy/ui/components/cards/outlined_card.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:selfprivacy/ui/components/info_box/info_box.dart';
|
||||||
|
import 'package:selfprivacy/ui/layouts/responsive_layout_with_infobox.dart';
|
||||||
import 'package:selfprivacy/utils/launch_url.dart';
|
import 'package:selfprivacy/utils/launch_url.dart';
|
||||||
|
|
||||||
class ServerProviderPicker extends StatefulWidget {
|
class ServerProviderPicker extends StatefulWidget {
|
||||||
|
@ -98,56 +97,49 @@ class ProviderInputDataPage extends StatelessWidget {
|
||||||
final ProviderFormCubit providerCubit;
|
final ProviderFormCubit providerCubit;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(final BuildContext context) => Column(
|
Widget build(final BuildContext context) => ResponsiveLayoutWithInfobox(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
topChild: Column(
|
||||||
children: [
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
Text(
|
children: [
|
||||||
"${'initializing.connect_to_server_provider'.tr()}${providerInfo.providerType.displayName}",
|
Text(
|
||||||
style: Theme.of(context).textTheme.headlineSmall,
|
"${'initializing.connect_to_server_provider'.tr()}${providerInfo.providerType.displayName}",
|
||||||
),
|
style: Theme.of(context).textTheme.headlineSmall,
|
||||||
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,
|
|
||||||
scrollPadding: const EdgeInsets.only(bottom: 70),
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
hintText: 'Provider API Token',
|
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(height: 16),
|
||||||
const SizedBox(height: 32),
|
Text(
|
||||||
BrandButton.filled(
|
'initializing.connect_to_server_provider_text'.tr(),
|
||||||
child: Text('basis.connect'.tr()),
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
onPressed: () => providerCubit.trySubmit(),
|
),
|
||||||
),
|
],
|
||||||
const SizedBox(height: 10),
|
),
|
||||||
BrandOutlinedButton(
|
primaryColumn: Column(
|
||||||
child: Text('initializing.how'.tr()),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
onPressed: () => showModalBottomSheet<void>(
|
children: [
|
||||||
context: context,
|
CubitFormTextField(
|
||||||
isScrollControlled: true,
|
formFieldCubit: providerCubit.apiKey,
|
||||||
backgroundColor: Colors.transparent,
|
textAlign: TextAlign.center,
|
||||||
builder: (final BuildContext context) => BrandBottomSheet(
|
scrollPadding: const EdgeInsets.only(bottom: 70),
|
||||||
isExpended: true,
|
decoration: const InputDecoration(
|
||||||
child: Padding(
|
hintText: 'Provider API Token',
|
||||||
padding: paddingH15V0,
|
|
||||||
child: ListView(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
|
||||||
children: [
|
|
||||||
BrandMarkdown(
|
|
||||||
fileName: providerInfo.pathToHow,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(height: 32),
|
||||||
],
|
BrandButton.filled(
|
||||||
|
child: Text('basis.connect'.tr()),
|
||||||
|
onPressed: () => providerCubit.trySubmit(),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
BrandOutlinedButton(
|
||||||
|
child: Text('initializing.how'.tr()),
|
||||||
|
onPressed: () {
|
||||||
|
context.read<SupportSystemCubit>().showArticle(
|
||||||
|
article: providerInfo.pathToHow,
|
||||||
|
context: context,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,175 +156,182 @@ class ProviderSelectionPage extends StatelessWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(final BuildContext context) => SizedBox(
|
Widget build(final BuildContext context) => SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
child: Column(
|
child: ResponsiveLayoutWithInfobox(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
topChild: Column(
|
||||||
children: [
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
Text(
|
children: [
|
||||||
'initializing.connect_to_server'.tr(),
|
Text(
|
||||||
style: Theme.of(context).textTheme.headlineSmall,
|
'initializing.connect_to_server'.tr(),
|
||||||
),
|
style: Theme.of(context).textTheme.headlineSmall,
|
||||||
const SizedBox(height: 10),
|
),
|
||||||
Text(
|
const SizedBox(height: 10),
|
||||||
'initializing.select_provider'.tr(),
|
Text(
|
||||||
style: Theme.of(context).textTheme.bodyMedium,
|
'initializing.select_provider'.tr(),
|
||||||
),
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
const SizedBox(height: 10),
|
),
|
||||||
OutlinedCard(
|
],
|
||||||
child: Padding(
|
),
|
||||||
padding: const EdgeInsets.all(16.0),
|
primaryColumn: Column(
|
||||||
child: Column(
|
children: [
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
OutlinedCard(
|
||||||
children: [
|
child: Padding(
|
||||||
Row(
|
padding: const EdgeInsets.all(16.0),
|
||||||
children: [
|
child: Column(
|
||||||
Container(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
width: 40,
|
children: [
|
||||||
height: 40,
|
Row(
|
||||||
padding: const EdgeInsets.all(10),
|
children: [
|
||||||
decoration: BoxDecoration(
|
Container(
|
||||||
borderRadius: BorderRadius.circular(40),
|
width: 40,
|
||||||
color: const Color(0xFFD50C2D),
|
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',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: SvgPicture.asset(
|
const SizedBox(width: 16),
|
||||||
'assets/images/logos/hetzner.svg',
|
Text(
|
||||||
|
'Hetzner Cloud',
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
const SizedBox(width: 16),
|
),
|
||||||
Text(
|
const SizedBox(height: 16),
|
||||||
'Hetzner Cloud',
|
Text(
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
'initializing.select_provider_countries_title'.tr(),
|
||||||
),
|
style: Theme.of(context).textTheme.bodyLarge,
|
||||||
],
|
),
|
||||||
),
|
Text(
|
||||||
const SizedBox(height: 16),
|
'initializing.select_provider_countries_text_hetzner'
|
||||||
Text(
|
.tr(),
|
||||||
'initializing.select_provider_countries_title'.tr(),
|
style: Theme.of(context).textTheme.bodySmall,
|
||||||
style: Theme.of(context).textTheme.bodyLarge,
|
),
|
||||||
),
|
const SizedBox(height: 16),
|
||||||
Text(
|
Text(
|
||||||
'initializing.select_provider_countries_text_hetzner'
|
'initializing.select_provider_price_title'.tr(),
|
||||||
.tr(),
|
style: Theme.of(context).textTheme.bodyLarge,
|
||||||
style: Theme.of(context).textTheme.bodySmall,
|
),
|
||||||
),
|
Text(
|
||||||
const SizedBox(height: 16),
|
'initializing.select_provider_price_text_hetzner'.tr(),
|
||||||
Text(
|
style: Theme.of(context).textTheme.bodySmall,
|
||||||
'initializing.select_provider_price_title'.tr(),
|
),
|
||||||
style: Theme.of(context).textTheme.bodyLarge,
|
const SizedBox(height: 16),
|
||||||
),
|
Text(
|
||||||
Text(
|
'initializing.select_provider_payment_title'.tr(),
|
||||||
'initializing.select_provider_price_text_hetzner'.tr(),
|
style: Theme.of(context).textTheme.bodyLarge,
|
||||||
style: Theme.of(context).textTheme.bodySmall,
|
),
|
||||||
),
|
Text(
|
||||||
const SizedBox(height: 16),
|
'initializing.select_provider_payment_text_hetzner'
|
||||||
Text(
|
.tr(),
|
||||||
'initializing.select_provider_payment_title'.tr(),
|
style: Theme.of(context).textTheme.bodySmall,
|
||||||
style: Theme.of(context).textTheme.bodyLarge,
|
),
|
||||||
),
|
const SizedBox(height: 16),
|
||||||
Text(
|
Text(
|
||||||
'initializing.select_provider_payment_text_hetzner'.tr(),
|
'initializing.select_provider_email_notice'.tr(),
|
||||||
style: Theme.of(context).textTheme.bodySmall,
|
style: Theme.of(context).textTheme.bodySmall,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Text(
|
BrandButton.filled(
|
||||||
'initializing.select_provider_email_notice'.tr(),
|
child: Text('basis.select'.tr()),
|
||||||
style: Theme.of(context).textTheme.bodySmall,
|
onPressed: () {
|
||||||
),
|
serverInstallationCubit
|
||||||
const SizedBox(height: 16),
|
.setServerProviderType(ServerProvider.hetzner);
|
||||||
BrandButton.filled(
|
callback(ServerProvider.hetzner);
|
||||||
child: Text('basis.select'.tr()),
|
},
|
||||||
onPressed: () {
|
),
|
||||||
serverInstallationCubit
|
// Outlined button that will open website
|
||||||
.setServerProviderType(ServerProvider.hetzner);
|
BrandOutlinedButton(
|
||||||
callback(ServerProvider.hetzner);
|
onPressed: () =>
|
||||||
},
|
launchURL('https://www.hetzner.com/cloud'),
|
||||||
),
|
title: 'initializing.select_provider_site_button'.tr(),
|
||||||
// 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),
|
||||||
const SizedBox(height: 16),
|
OutlinedCard(
|
||||||
OutlinedCard(
|
child: Padding(
|
||||||
child: Padding(
|
padding: const EdgeInsets.all(16.0),
|
||||||
padding: const EdgeInsets.all(16.0),
|
child: Column(
|
||||||
child: Column(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
children: [
|
||||||
children: [
|
Row(
|
||||||
Row(
|
children: [
|
||||||
children: [
|
Container(
|
||||||
Container(
|
width: 40,
|
||||||
width: 40,
|
height: 40,
|
||||||
height: 40,
|
padding: const EdgeInsets.all(10),
|
||||||
padding: const EdgeInsets.all(10),
|
decoration: BoxDecoration(
|
||||||
decoration: BoxDecoration(
|
borderRadius: BorderRadius.circular(40),
|
||||||
borderRadius: BorderRadius.circular(40),
|
color: const Color(0xFF0080FF),
|
||||||
color: const Color(0xFF0080FF),
|
),
|
||||||
|
child: SvgPicture.asset(
|
||||||
|
'assets/images/logos/digital_ocean.svg',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: SvgPicture.asset(
|
const SizedBox(width: 16),
|
||||||
'assets/images/logos/digital_ocean.svg',
|
Text(
|
||||||
|
'Digital Ocean',
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
const SizedBox(width: 16),
|
),
|
||||||
Text(
|
const SizedBox(height: 16),
|
||||||
'Digital Ocean',
|
Text(
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
'initializing.select_provider_countries_title'.tr(),
|
||||||
),
|
style: Theme.of(context).textTheme.bodyLarge,
|
||||||
],
|
),
|
||||||
),
|
Text(
|
||||||
const SizedBox(height: 16),
|
'initializing.select_provider_countries_text_do'.tr(),
|
||||||
Text(
|
style: Theme.of(context).textTheme.bodySmall,
|
||||||
'initializing.select_provider_countries_title'.tr(),
|
),
|
||||||
style: Theme.of(context).textTheme.bodyLarge,
|
const SizedBox(height: 16),
|
||||||
),
|
Text(
|
||||||
Text(
|
'initializing.select_provider_price_title'.tr(),
|
||||||
'initializing.select_provider_countries_text_do'.tr(),
|
style: Theme.of(context).textTheme.bodyLarge,
|
||||||
style: Theme.of(context).textTheme.bodySmall,
|
),
|
||||||
),
|
Text(
|
||||||
const SizedBox(height: 16),
|
'initializing.select_provider_price_text_do'.tr(),
|
||||||
Text(
|
style: Theme.of(context).textTheme.bodySmall,
|
||||||
'initializing.select_provider_price_title'.tr(),
|
),
|
||||||
style: Theme.of(context).textTheme.bodyLarge,
|
const SizedBox(height: 16),
|
||||||
),
|
Text(
|
||||||
Text(
|
'initializing.select_provider_payment_title'.tr(),
|
||||||
'initializing.select_provider_price_text_do'.tr(),
|
style: Theme.of(context).textTheme.bodyLarge,
|
||||||
style: Theme.of(context).textTheme.bodySmall,
|
),
|
||||||
),
|
Text(
|
||||||
const SizedBox(height: 16),
|
'initializing.select_provider_payment_text_do'.tr(),
|
||||||
Text(
|
style: Theme.of(context).textTheme.bodySmall,
|
||||||
'initializing.select_provider_payment_title'.tr(),
|
),
|
||||||
style: Theme.of(context).textTheme.bodyLarge,
|
const SizedBox(height: 16),
|
||||||
),
|
BrandButton.filled(
|
||||||
Text(
|
child: Text('basis.select'.tr()),
|
||||||
'initializing.select_provider_payment_text_do'.tr(),
|
onPressed: () {
|
||||||
style: Theme.of(context).textTheme.bodySmall,
|
serverInstallationCubit.setServerProviderType(
|
||||||
),
|
ServerProvider.digitalOcean,
|
||||||
const SizedBox(height: 16),
|
);
|
||||||
BrandButton.filled(
|
callback(ServerProvider.digitalOcean);
|
||||||
child: Text('basis.select'.tr()),
|
},
|
||||||
onPressed: () {
|
),
|
||||||
serverInstallationCubit
|
// Outlined button that will open website
|
||||||
.setServerProviderType(ServerProvider.digitalOcean);
|
BrandOutlinedButton(
|
||||||
callback(ServerProvider.digitalOcean);
|
onPressed: () =>
|
||||||
},
|
launchURL('https://www.digitalocean.com'),
|
||||||
),
|
title: 'initializing.select_provider_site_button'.tr(),
|
||||||
// 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()),
|
secondaryColumn:
|
||||||
],
|
InfoBox(text: 'initializing.select_provider_notice'.tr()),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,9 @@ import 'package:selfprivacy/logic/cubit/app_config_dependent/authentication_depe
|
||||||
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/models/server_provider_location.dart';
|
import 'package:selfprivacy/logic/models/server_provider_location.dart';
|
||||||
import 'package:selfprivacy/logic/models/server_type.dart';
|
import 'package:selfprivacy/logic/models/server_type.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/info_box/info_box.dart';
|
import 'package:selfprivacy/ui/components/info_box/info_box.dart';
|
||||||
|
import 'package:selfprivacy/ui/layouts/responsive_layout_with_infobox.dart';
|
||||||
|
|
||||||
class ServerTypePicker extends StatefulWidget {
|
class ServerTypePicker extends StatefulWidget {
|
||||||
const ServerTypePicker({
|
const ServerTypePicker({
|
||||||
|
@ -70,50 +71,67 @@ class SelectLocationPage extends StatelessWidget {
|
||||||
if ((snapshot.data as List<ServerProviderLocation>).isEmpty) {
|
if ((snapshot.data as List<ServerProviderLocation>).isEmpty) {
|
||||||
return Text('initializing.no_locations_found'.tr());
|
return Text('initializing.no_locations_found'.tr());
|
||||||
}
|
}
|
||||||
return Column(
|
return ResponsiveLayoutWithInfobox(
|
||||||
children: [
|
topChild: Column(
|
||||||
Text(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
'initializing.choose_location_type'.tr(),
|
children: [
|
||||||
style: Theme.of(context).textTheme.headlineSmall,
|
Text(
|
||||||
),
|
'initializing.choose_location_type'.tr(),
|
||||||
const SizedBox(height: 16),
|
style: Theme.of(context).textTheme.headlineSmall,
|
||||||
Text(
|
),
|
||||||
'initializing.choose_location_type_text'.tr(),
|
const SizedBox(height: 16),
|
||||||
style: Theme.of(context).textTheme.bodyMedium,
|
Text(
|
||||||
),
|
'initializing.choose_location_type_text'.tr(),
|
||||||
const SizedBox(height: 16),
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
...(snapshot.data! as List<ServerProviderLocation>).map(
|
),
|
||||||
(final location) => SizedBox(
|
],
|
||||||
width: double.infinity,
|
),
|
||||||
child: InkWell(
|
primaryColumn: Column(
|
||||||
onTap: () {
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
callback(location);
|
children: [
|
||||||
},
|
...(snapshot.data! as List<ServerProviderLocation>).map(
|
||||||
child: Card(
|
(final location) => Column(
|
||||||
child: Padding(
|
children: [
|
||||||
padding: const EdgeInsets.all(16.0),
|
SizedBox(
|
||||||
child: Column(
|
width: double.infinity,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
child: Card(
|
||||||
children: [
|
clipBehavior: Clip.antiAlias,
|
||||||
Text(
|
child: InkResponse(
|
||||||
'${location.flag ?? ''} ${location.title}',
|
highlightShape: BoxShape.rectangle,
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
onTap: () {
|
||||||
),
|
callback(location);
|
||||||
const SizedBox(height: 8),
|
},
|
||||||
if (location.description != null)
|
child: Padding(
|
||||||
Text(
|
padding: const EdgeInsets.all(16.0),
|
||||||
location.description!,
|
child: Column(
|
||||||
style: Theme.of(context).textTheme.bodyMedium,
|
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: 8),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
const SizedBox(height: 24),
|
),
|
||||||
],
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
|
@ -180,121 +198,145 @@ class SelectTypePage extends StatelessWidget {
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return Column(
|
return ResponsiveLayoutWithInfobox(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
topChild: Column(
|
||||||
children: [
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
Text(
|
children: [
|
||||||
'initializing.choose_server_type'.tr(),
|
Text(
|
||||||
style: Theme.of(context).textTheme.headlineSmall,
|
'initializing.choose_server_type'.tr(),
|
||||||
),
|
style: Theme.of(context).textTheme.headlineSmall,
|
||||||
const SizedBox(height: 16),
|
),
|
||||||
Text(
|
const SizedBox(height: 16),
|
||||||
'initializing.choose_server_type_text'.tr(),
|
Text(
|
||||||
style: Theme.of(context).textTheme.bodyMedium,
|
'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,
|
primaryColumn: Column(
|
||||||
child: InkWell(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
onTap: () {
|
children: [
|
||||||
serverInstallationCubit.setServerType(type);
|
...(snapshot.data! as List<ServerType>).map(
|
||||||
},
|
(final type) => Column(
|
||||||
child: Card(
|
children: [
|
||||||
child: Padding(
|
SizedBox(
|
||||||
padding: const EdgeInsets.all(16.0),
|
width: double.infinity,
|
||||||
child: Column(
|
child: InkWell(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
onTap: () {
|
||||||
children: [
|
serverInstallationCubit.setServerType(type);
|
||||||
Text(
|
},
|
||||||
type.title,
|
child: Card(
|
||||||
style: Theme.of(context).textTheme.titleMedium,
|
child: Padding(
|
||||||
),
|
padding: const EdgeInsets.all(16.0),
|
||||||
const SizedBox(height: 8),
|
child: Column(
|
||||||
Row(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Icon(
|
Text(
|
||||||
Icons.memory_outlined,
|
type.title,
|
||||||
color:
|
style: Theme.of(context)
|
||||||
Theme.of(context).colorScheme.onSurface,
|
.textTheme
|
||||||
),
|
.titleMedium,
|
||||||
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:
|
const SizedBox(height: 8),
|
||||||
Theme.of(context).textTheme.bodyMedium,
|
Row(
|
||||||
),
|
children: [
|
||||||
],
|
Icon(
|
||||||
),
|
Icons.memory_outlined,
|
||||||
const SizedBox(height: 8),
|
color: Theme.of(context)
|
||||||
const Divider(height: 8),
|
.colorScheme
|
||||||
const SizedBox(height: 8),
|
.onSurface,
|
||||||
Row(
|
),
|
||||||
children: [
|
const SizedBox(width: 8),
|
||||||
Icon(
|
Text(
|
||||||
Icons.payments_outlined,
|
'server.core_count'
|
||||||
color:
|
.plural(type.cores),
|
||||||
Theme.of(context).colorScheme.onSurface,
|
style: Theme.of(context)
|
||||||
),
|
.textTheme
|
||||||
const SizedBox(width: 8),
|
.bodyMedium,
|
||||||
Text(
|
),
|
||||||
'initializing.choose_server_type_payment_per_month'
|
|
||||||
.tr(
|
|
||||||
args: [
|
|
||||||
'${type.price.value.toString()} ${type.price.currency}'
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
style:
|
const SizedBox(height: 8),
|
||||||
Theme.of(context).textTheme.bodyLarge,
|
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: 8),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
const SizedBox(height: 16),
|
),
|
||||||
InfoBox(text: 'initializing.choose_server_type_notice'.tr()),
|
secondaryColumn:
|
||||||
],
|
InfoBox(text: 'initializing.choose_server_type_notice'.tr()),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
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/logic/cubit/forms/setup/recovering/recovery_device_form_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/forms/setup/recovering/recovery_device_form_cubit.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
|
||||||
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
||||||
import 'package:cubit_form/cubit_form.dart';
|
import 'package:cubit_form/cubit_form.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||||
|
@ -17,6 +17,7 @@ class RecoverByNewDeviceKeyInstruction extends StatelessWidget {
|
||||||
heroSubtitle: 'recovering.method_device_description'.tr(),
|
heroSubtitle: 'recovering.method_device_description'.tr(),
|
||||||
hasBackButton: true,
|
hasBackButton: true,
|
||||||
hasFlashButton: false,
|
hasFlashButton: false,
|
||||||
|
ignoreBreakpoints: true,
|
||||||
onBackButtonPressed:
|
onBackButtonPressed:
|
||||||
context.read<ServerInstallationCubit>().revertRecoveryStep,
|
context.read<ServerInstallationCubit>().revertRecoveryStep,
|
||||||
children: [
|
children: [
|
||||||
|
@ -61,6 +62,7 @@ class RecoverByNewDeviceKeyInput extends StatelessWidget {
|
||||||
heroSubtitle: 'recovering.method_device_input_description'.tr(),
|
heroSubtitle: 'recovering.method_device_input_description'.tr(),
|
||||||
hasBackButton: true,
|
hasBackButton: true,
|
||||||
hasFlashButton: false,
|
hasFlashButton: false,
|
||||||
|
ignoreBreakpoints: true,
|
||||||
children: [
|
children: [
|
||||||
CubitFormTextField(
|
CubitFormTextField(
|
||||||
formFieldCubit:
|
formFieldCubit:
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
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/logic/cubit/forms/setup/recovering/recovery_device_form_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/forms/setup/recovering/recovery_device_form_cubit.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_md/brand_md.dart';
|
import 'package:selfprivacy/ui/components/brand_md/brand_md.dart';
|
||||||
import 'package:cubit_form/cubit_form.dart';
|
import 'package:cubit_form/cubit_form.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||||
|
@ -28,6 +28,7 @@ class RecoverByOldTokenInstruction extends StatelessWidget {
|
||||||
heroTitle: 'recovering.recovery_main_header'.tr(),
|
heroTitle: 'recovering.recovery_main_header'.tr(),
|
||||||
hasBackButton: true,
|
hasBackButton: true,
|
||||||
hasFlashButton: false,
|
hasFlashButton: false,
|
||||||
|
ignoreBreakpoints: true,
|
||||||
onBackButtonPressed:
|
onBackButtonPressed:
|
||||||
context.read<ServerInstallationCubit>().revertRecoveryStep,
|
context.read<ServerInstallationCubit>().revertRecoveryStep,
|
||||||
children: [
|
children: [
|
||||||
|
@ -72,6 +73,7 @@ class RecoverByOldToken extends StatelessWidget {
|
||||||
heroSubtitle: 'recovering.method_device_input_description'.tr(),
|
heroSubtitle: 'recovering.method_device_input_description'.tr(),
|
||||||
hasBackButton: true,
|
hasBackButton: true,
|
||||||
hasFlashButton: false,
|
hasFlashButton: false,
|
||||||
|
ignoreBreakpoints: true,
|
||||||
children: [
|
children: [
|
||||||
CubitFormTextField(
|
CubitFormTextField(
|
||||||
formFieldCubit:
|
formFieldCubit:
|
||||||
|
|
|
@ -4,8 +4,8 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/forms/factories/field_cubit_factory.dart';
|
import 'package:selfprivacy/logic/cubit/forms/factories/field_cubit_factory.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/forms/setup/recovering/recovery_device_form_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/forms/setup/recovering/recovery_device_form_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/buttons/brand_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
|
||||||
|
|
||||||
class RecoverByRecoveryKey extends StatelessWidget {
|
class RecoverByRecoveryKey extends StatelessWidget {
|
||||||
const RecoverByRecoveryKey({super.key});
|
const RecoverByRecoveryKey({super.key});
|
||||||
|
@ -31,6 +31,7 @@ class RecoverByRecoveryKey extends StatelessWidget {
|
||||||
heroSubtitle: 'recovering.method_recovery_input_description'.tr(),
|
heroSubtitle: 'recovering.method_recovery_input_description'.tr(),
|
||||||
hasBackButton: true,
|
hasBackButton: true,
|
||||||
hasFlashButton: false,
|
hasFlashButton: false,
|
||||||
|
ignoreBreakpoints: true,
|
||||||
onBackButtonPressed:
|
onBackButtonPressed:
|
||||||
context.read<ServerInstallationCubit>().revertRecoveryStep,
|
context.read<ServerInstallationCubit>().revertRecoveryStep,
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
import 'package:cubit_form/cubit_form.dart';
|
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_theme.dart';
|
|
||||||
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/backblaze_form_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/backblaze_form_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_bottom_sheet/brand_bottom_sheet.dart';
|
import 'package:selfprivacy/logic/cubit/support_system/support_system_cubit.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_md/brand_md.dart';
|
|
||||||
|
|
||||||
class RecoveryConfirmBackblaze extends StatelessWidget {
|
class RecoveryConfirmBackblaze extends StatelessWidget {
|
||||||
const RecoveryConfirmBackblaze({super.key});
|
const RecoveryConfirmBackblaze({super.key});
|
||||||
|
@ -28,6 +26,8 @@ class RecoveryConfirmBackblaze extends StatelessWidget {
|
||||||
heroTitle: 'recovering.confirm_backblaze'.tr(),
|
heroTitle: 'recovering.confirm_backblaze'.tr(),
|
||||||
heroSubtitle: 'recovering.confirm_backblaze_description'.tr(),
|
heroSubtitle: 'recovering.confirm_backblaze_description'.tr(),
|
||||||
hasBackButton: true,
|
hasBackButton: true,
|
||||||
|
ignoreBreakpoints: true,
|
||||||
|
hasSupportDrawer: true,
|
||||||
onBackButtonPressed: () {
|
onBackButtonPressed: () {
|
||||||
Navigator.of(context).popUntil((final route) => route.isFirst);
|
Navigator.of(context).popUntil((final route) => route.isFirst);
|
||||||
},
|
},
|
||||||
|
@ -57,27 +57,15 @@ class RecoveryConfirmBackblaze extends StatelessWidget {
|
||||||
text: 'basis.connect'.tr(),
|
text: 'basis.connect'.tr(),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
BrandButton.text(
|
Builder(
|
||||||
onPressed: () => showModalBottomSheet<void>(
|
builder: (final context) => BrandButton.text(
|
||||||
context: context,
|
onPressed: () =>
|
||||||
isScrollControlled: true,
|
context.read<SupportSystemCubit>().showArticle(
|
||||||
backgroundColor: Colors.transparent,
|
article: 'how_backblaze',
|
||||||
builder: (final BuildContext context) => BrandBottomSheet(
|
context: context,
|
||||||
isExpended: true,
|
|
||||||
child: Padding(
|
|
||||||
padding: paddingH15V0,
|
|
||||||
child: ListView(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
|
||||||
children: const [
|
|
||||||
BrandMarkdown(
|
|
||||||
fileName: 'how_backblaze',
|
|
||||||
),
|
),
|
||||||
],
|
title: 'initializing.how'.tr(),
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
title: 'initializing.how'.tr(),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
import 'package:cubit_form/cubit_form.dart';
|
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_theme.dart';
|
|
||||||
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/dns_provider_form_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/dns_provider_form_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_bottom_sheet/brand_bottom_sheet.dart';
|
import 'package:selfprivacy/logic/cubit/support_system/support_system_cubit.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_md/brand_md.dart';
|
|
||||||
|
|
||||||
class RecoveryConfirmCloudflare extends StatelessWidget {
|
class RecoveryConfirmCloudflare extends StatelessWidget {
|
||||||
const RecoveryConfirmCloudflare({super.key});
|
const RecoveryConfirmCloudflare({super.key});
|
||||||
|
@ -31,6 +29,8 @@ class RecoveryConfirmCloudflare extends StatelessWidget {
|
||||||
),
|
),
|
||||||
hasBackButton: true,
|
hasBackButton: true,
|
||||||
hasFlashButton: false,
|
hasFlashButton: false,
|
||||||
|
ignoreBreakpoints: true,
|
||||||
|
hasSupportDrawer: true,
|
||||||
onBackButtonPressed:
|
onBackButtonPressed:
|
||||||
context.read<ServerInstallationCubit>().revertRecoveryStep,
|
context.read<ServerInstallationCubit>().revertRecoveryStep,
|
||||||
children: [
|
children: [
|
||||||
|
@ -49,27 +49,15 @@ class RecoveryConfirmCloudflare extends StatelessWidget {
|
||||||
text: 'basis.connect'.tr(),
|
text: 'basis.connect'.tr(),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
BrandButton.text(
|
Builder(
|
||||||
onPressed: () => showModalBottomSheet<void>(
|
builder: (final context) => BrandButton.text(
|
||||||
context: context,
|
onPressed: () =>
|
||||||
isScrollControlled: true,
|
context.read<SupportSystemCubit>().showArticle(
|
||||||
backgroundColor: Colors.transparent,
|
article: 'how_cloudflare',
|
||||||
builder: (final BuildContext context) => BrandBottomSheet(
|
context: context,
|
||||||
isExpended: true,
|
|
||||||
child: Padding(
|
|
||||||
padding: paddingH15V0,
|
|
||||||
child: ListView(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
|
||||||
children: const [
|
|
||||||
BrandMarkdown(
|
|
||||||
fileName: 'how_cloudflare',
|
|
||||||
),
|
),
|
||||||
],
|
title: 'initializing.how'.tr(),
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
title: 'initializing.how'.tr(),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,9 +2,9 @@ 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/models/server_basic_info.dart';
|
import 'package:selfprivacy/logic/models/server_basic_info.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_cards/filled_card.dart';
|
import 'package:selfprivacy/ui/components/cards/filled_card.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
|
||||||
|
|
||||||
class RecoveryConfirmServer extends StatefulWidget {
|
class RecoveryConfirmServer extends StatefulWidget {
|
||||||
const RecoveryConfirmServer({super.key});
|
const RecoveryConfirmServer({super.key});
|
||||||
|
@ -38,6 +38,7 @@ class _RecoveryConfirmServerState extends State<RecoveryConfirmServer> {
|
||||||
? 'recovering.choose_server_description'.tr()
|
? 'recovering.choose_server_description'.tr()
|
||||||
: 'recovering.confirm_server_description'.tr(),
|
: 'recovering.confirm_server_description'.tr(),
|
||||||
hasBackButton: true,
|
hasBackButton: true,
|
||||||
|
ignoreBreakpoints: true,
|
||||||
onBackButtonPressed: () {
|
onBackButtonPressed: () {
|
||||||
Navigator.of(context).popUntil((final route) => route.isFirst);
|
Navigator.of(context).popUntil((final route) => route.isFirst);
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,9 +2,9 @@ import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
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/buttons/brand_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_cards/outlined_card.dart';
|
import 'package:selfprivacy/ui/components/cards/outlined_card.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
import 'package:selfprivacy/ui/layouts/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';
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ class RecoveryMethodSelect extends StatelessWidget {
|
||||||
heroSubtitle: 'recovering.method_select_description'.tr(),
|
heroSubtitle: 'recovering.method_select_description'.tr(),
|
||||||
hasBackButton: true,
|
hasBackButton: true,
|
||||||
hasFlashButton: false,
|
hasFlashButton: false,
|
||||||
|
ignoreBreakpoints: true,
|
||||||
onBackButtonPressed:
|
onBackButtonPressed:
|
||||||
context.read<ServerInstallationCubit>().revertRecoveryStep,
|
context.read<ServerInstallationCubit>().revertRecoveryStep,
|
||||||
children: [
|
children: [
|
||||||
|
@ -74,6 +75,7 @@ class RecoveryFallbackMethodSelect extends StatelessWidget {
|
||||||
heroSubtitle: 'recovering.fallback_select_description'.tr(),
|
heroSubtitle: 'recovering.fallback_select_description'.tr(),
|
||||||
hasBackButton: true,
|
hasBackButton: true,
|
||||||
hasFlashButton: false,
|
hasFlashButton: false,
|
||||||
|
ignoreBreakpoints: true,
|
||||||
children: [
|
children: [
|
||||||
OutlinedCard(
|
OutlinedCard(
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:cubit_form/cubit_form.dart';
|
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/logic/cubit/server_installation/server_installation_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/server_installation/server_installation_cubit.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/forms/factories/field_cubit_factory.dart';
|
import 'package:selfprivacy/logic/cubit/forms/factories/field_cubit_factory.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/forms/setup/recovering/recovery_domain_form_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/forms/setup/recovering/recovery_domain_form_cubit.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
|
||||||
import 'package:selfprivacy/ui/pages/root_route.dart';
|
import 'package:selfprivacy/ui/pages/root_route.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/ui/pages/setup/recovering/recover_by_recovery_key.dart';
|
import 'package:selfprivacy/ui/pages/setup/recovering/recover_by_recovery_key.dart';
|
||||||
|
@ -17,6 +18,7 @@ import 'package:selfprivacy/ui/pages/setup/recovering/recovery_server_provider_c
|
||||||
import 'package:selfprivacy/ui/pages/setup/recovering/recovery_method_select.dart';
|
import 'package:selfprivacy/ui/pages/setup/recovering/recovery_method_select.dart';
|
||||||
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
import 'package:selfprivacy/utils/route_transitions/basic.dart';
|
||||||
|
|
||||||
|
@RoutePage()
|
||||||
class RecoveryRouting extends StatelessWidget {
|
class RecoveryRouting extends StatelessWidget {
|
||||||
const RecoveryRouting({super.key});
|
const RecoveryRouting({super.key});
|
||||||
|
|
||||||
|
@ -110,6 +112,7 @@ class SelectDomainToRecover extends StatelessWidget {
|
||||||
heroSubtitle: 'recovering.domain_recovery_description'.tr(),
|
heroSubtitle: 'recovering.domain_recovery_description'.tr(),
|
||||||
hasBackButton: true,
|
hasBackButton: true,
|
||||||
hasFlashButton: false,
|
hasFlashButton: false,
|
||||||
|
ignoreBreakpoints: true,
|
||||||
onBackButtonPressed: () {
|
onBackButtonPressed: () {
|
||||||
Navigator.of(context).pushAndRemoveUntil(
|
Navigator.of(context).pushAndRemoveUntil(
|
||||||
materialRoute(const RootPage()),
|
materialRoute(const RootPage()),
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
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_theme.dart';
|
|
||||||
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/provider_form_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/forms/setup/initializing/provider_form_cubit.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_bottom_sheet/brand_bottom_sheet.dart';
|
import 'package:selfprivacy/logic/cubit/support_system/support_system_cubit.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_button/brand_button.dart';
|
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
import 'package:selfprivacy/ui/layouts/brand_hero_screen.dart';
|
||||||
import 'package:cubit_form/cubit_form.dart';
|
import 'package:cubit_form/cubit_form.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_md/brand_md.dart';
|
|
||||||
|
|
||||||
class RecoveryServerProviderConnected extends StatelessWidget {
|
class RecoveryServerProviderConnected extends StatelessWidget {
|
||||||
const RecoveryServerProviderConnected({super.key});
|
const RecoveryServerProviderConnected({super.key});
|
||||||
|
@ -31,6 +29,8 @@ class RecoveryServerProviderConnected extends StatelessWidget {
|
||||||
),
|
),
|
||||||
hasBackButton: true,
|
hasBackButton: true,
|
||||||
hasFlashButton: false,
|
hasFlashButton: false,
|
||||||
|
ignoreBreakpoints: true,
|
||||||
|
hasSupportDrawer: true,
|
||||||
onBackButtonPressed: () {
|
onBackButtonPressed: () {
|
||||||
Navigator.of(context).popUntil((final route) => route.isFirst);
|
Navigator.of(context).popUntil((final route) => route.isFirst);
|
||||||
},
|
},
|
||||||
|
@ -51,26 +51,14 @@ class RecoveryServerProviderConnected extends StatelessWidget {
|
||||||
child: Text('basis.continue'.tr()),
|
child: Text('basis.continue'.tr()),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
BrandButton.text(
|
Builder(
|
||||||
title: 'initializing.how'.tr(),
|
builder: (final context) => BrandButton.text(
|
||||||
onPressed: () => showModalBottomSheet<void>(
|
title: 'initializing.how'.tr(),
|
||||||
context: context,
|
onPressed: () =>
|
||||||
isScrollControlled: true,
|
context.read<SupportSystemCubit>().showArticle(
|
||||||
backgroundColor: Colors.transparent,
|
article: 'how_hetzner',
|
||||||
builder: (final BuildContext context) => BrandBottomSheet(
|
context: context,
|
||||||
isExpended: true,
|
|
||||||
child: Padding(
|
|
||||||
padding: paddingH15V0,
|
|
||||||
child: ListView(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
|
||||||
children: const [
|
|
||||||
BrandMarkdown(
|
|
||||||
fileName: 'how_hetzner',
|
|
||||||
),
|
),
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue