First steps to move to Material You
parent
8b5bf24f3a
commit
b4145dc5c8
|
@ -13,7 +13,6 @@ import 'package:timezone/data/latest.dart' as tz;
|
||||||
|
|
||||||
import 'config/bloc_config.dart';
|
import 'config/bloc_config.dart';
|
||||||
import 'config/bloc_observer.dart';
|
import 'config/bloc_observer.dart';
|
||||||
import 'config/brand_theme.dart';
|
|
||||||
import 'config/get_it_config.dart';
|
import 'config/get_it_config.dart';
|
||||||
import 'config/localization.dart';
|
import 'config/localization.dart';
|
||||||
import 'logic/cubit/app_settings/app_settings_cubit.dart';
|
import 'logic/cubit/app_settings/app_settings_cubit.dart';
|
||||||
|
@ -45,7 +44,8 @@ void main() async {
|
||||||
);
|
);
|
||||||
|
|
||||||
BlocOverrides.runZoned(
|
BlocOverrides.runZoned(
|
||||||
() => runApp(Localization(child: MyApp(
|
() => runApp(Localization(
|
||||||
|
child: MyApp(
|
||||||
lightThemeData: lightThemeData,
|
lightThemeData: lightThemeData,
|
||||||
darkThemeData: darkThemeData,
|
darkThemeData: darkThemeData,
|
||||||
))),
|
))),
|
||||||
|
@ -81,7 +81,8 @@ class MyApp extends StatelessWidget {
|
||||||
title: 'SelfPrivacy',
|
title: 'SelfPrivacy',
|
||||||
theme: lightThemeData,
|
theme: lightThemeData,
|
||||||
darkTheme: darkThemeData,
|
darkTheme: darkThemeData,
|
||||||
themeMode: appSettings.isDarkModeOn ? ThemeMode.dark : ThemeMode.light,
|
themeMode:
|
||||||
|
appSettings.isDarkModeOn ? ThemeMode.dark : ThemeMode.light,
|
||||||
home: appSettings.isOnbordingShowing
|
home: appSettings.isOnbordingShowing
|
||||||
? OnboardingPage(nextPage: InitializingPage())
|
? OnboardingPage(nextPage: InitializingPage())
|
||||||
: RootPage(),
|
: RootPage(),
|
||||||
|
|
|
@ -28,13 +28,18 @@ abstract class AppThemeFactory {
|
||||||
|
|
||||||
if (Platform.isLinux) {
|
if (Platform.isLinux) {
|
||||||
GtkThemeData themeData = await GtkThemeData.initialize();
|
GtkThemeData themeData = await GtkThemeData.initialize();
|
||||||
|
final isGtkDark =
|
||||||
|
Color(themeData.theme_base_color).computeLuminance() < 0.5;
|
||||||
|
final isInverseNeeded = isGtkDark != isDark;
|
||||||
gtkColorsScheme = ColorScheme.fromSeed(
|
gtkColorsScheme = ColorScheme.fromSeed(
|
||||||
seedColor: Color(themeData.theme_selected_bg_color),
|
seedColor: Color(themeData.theme_selected_bg_color),
|
||||||
brightness: Color(themeData.theme_base_color).computeLuminance() > 0.5
|
brightness: brightness,
|
||||||
? Brightness.light
|
background: isInverseNeeded
|
||||||
: Brightness.dark,
|
? Color(themeData.theme_base_color)
|
||||||
background: Color(themeData.theme_bg_color),
|
: Color(themeData.theme_bg_color),
|
||||||
surface: Color(themeData.theme_base_color),
|
surface: isInverseNeeded
|
||||||
|
? Color(themeData.theme_bg_color)
|
||||||
|
: Color(themeData.theme_base_color),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +51,8 @@ abstract class AppThemeFactory {
|
||||||
brightness: brightness,
|
brightness: brightness,
|
||||||
);
|
);
|
||||||
|
|
||||||
final colorScheme = dynamicColorsScheme ?? gtkColorsScheme ?? fallbackColorScheme;
|
final colorScheme =
|
||||||
|
dynamicColorsScheme ?? gtkColorsScheme ?? fallbackColorScheme;
|
||||||
|
|
||||||
final appTypography = Typography.material2021();
|
final appTypography = Typography.material2021();
|
||||||
|
|
||||||
|
@ -55,6 +61,7 @@ abstract class AppThemeFactory {
|
||||||
brightness: colorScheme.brightness,
|
brightness: colorScheme.brightness,
|
||||||
typography: appTypography,
|
typography: appTypography,
|
||||||
useMaterial3: true,
|
useMaterial3: true,
|
||||||
|
scaffoldBackgroundColor: colorScheme.background,
|
||||||
appBarTheme: AppBarTheme(
|
appBarTheme: AppBarTheme(
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
backgroundColor: colorScheme.primary,
|
backgroundColor: colorScheme.primary,
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class FilledButton extends StatelessWidget {
|
||||||
|
const FilledButton({
|
||||||
|
Key? key,
|
||||||
|
this.onPressed,
|
||||||
|
this.title,
|
||||||
|
this.child,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final VoidCallback? onPressed;
|
||||||
|
final String? title;
|
||||||
|
final Widget? child;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ElevatedButton(
|
||||||
|
onPressed: onPressed,
|
||||||
|
child: child ?? Text(title ?? ''),
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
onPrimary: Theme.of(context).colorScheme.onPrimary,
|
||||||
|
primary: Theme.of(context).colorScheme.primary,
|
||||||
|
).copyWith(elevation: ButtonStyleButton.allOrNull(0.0)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:selfprivacy/config/brand_colors.dart';
|
import 'package:selfprivacy/ui/components/brand_button/FilledButton.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
|
import 'package:selfprivacy/ui/components/brand_text/brand_text.dart';
|
||||||
|
|
||||||
enum BrandButtonTypes { rised, text, iconText }
|
enum BrandButtonTypes { rised, text, iconText }
|
||||||
|
@ -13,11 +13,17 @@ class BrandButton {
|
||||||
}) {
|
}) {
|
||||||
assert(text == null || child == null, 'required title or child');
|
assert(text == null || child == null, 'required title or child');
|
||||||
assert(text != null || child != null, 'required title or child');
|
assert(text != null || child != null, 'required title or child');
|
||||||
return _RisedButton(
|
return ConstrainedBox(
|
||||||
key: key,
|
constraints: BoxConstraints(
|
||||||
title: text,
|
minHeight: 48,
|
||||||
onPressed: onPressed,
|
minWidth: double.infinity,
|
||||||
child: child,
|
),
|
||||||
|
child: FilledButton(
|
||||||
|
key: key,
|
||||||
|
title: text,
|
||||||
|
onPressed: onPressed,
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,10 +32,12 @@ class BrandButton {
|
||||||
required VoidCallback onPressed,
|
required VoidCallback onPressed,
|
||||||
required String title,
|
required String title,
|
||||||
}) =>
|
}) =>
|
||||||
_TextButton(
|
ConstrainedBox(
|
||||||
key: key,
|
constraints: BoxConstraints(
|
||||||
title: title,
|
minHeight: 48,
|
||||||
onPressed: onPressed,
|
minWidth: double.infinity,
|
||||||
|
),
|
||||||
|
child: TextButton(onPressed: onPressed, child: Text(title)),
|
||||||
);
|
);
|
||||||
|
|
||||||
static emptyWithIconText({
|
static emptyWithIconText({
|
||||||
|
@ -46,78 +54,6 @@ class BrandButton {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class _RisedButton extends StatelessWidget {
|
|
||||||
const _RisedButton({
|
|
||||||
Key? key,
|
|
||||||
this.onPressed,
|
|
||||||
this.title,
|
|
||||||
this.child,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
final VoidCallback? onPressed;
|
|
||||||
final String? title;
|
|
||||||
final Widget? child;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return ClipRRect(
|
|
||||||
borderRadius: BorderRadius.circular(24),
|
|
||||||
child: ColoredBox(
|
|
||||||
color: onPressed == null
|
|
||||||
? BrandColors.gray2
|
|
||||||
: Theme.of(context).primaryColor,
|
|
||||||
child: Material(
|
|
||||||
color: Colors.transparent,
|
|
||||||
child: InkWell(
|
|
||||||
onTap: onPressed,
|
|
||||||
child: Container(
|
|
||||||
height: 48,
|
|
||||||
width: double.infinity,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
padding: EdgeInsets.all(12),
|
|
||||||
child: child ?? BrandText.buttonTitleText(title),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _TextButton extends StatelessWidget {
|
|
||||||
const _TextButton({
|
|
||||||
Key? key,
|
|
||||||
this.onPressed,
|
|
||||||
this.title,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
final VoidCallback? onPressed;
|
|
||||||
final String? title;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return GestureDetector(
|
|
||||||
onTap: onPressed,
|
|
||||||
behavior: HitTestBehavior.opaque,
|
|
||||||
child: Container(
|
|
||||||
height: 48,
|
|
||||||
width: double.infinity,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
padding: EdgeInsets.all(12),
|
|
||||||
child: Text(
|
|
||||||
title!,
|
|
||||||
style: TextStyle(
|
|
||||||
color: BrandColors.blue,
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
height: 1.5,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _IconTextButton extends StatelessWidget {
|
class _IconTextButton extends StatelessWidget {
|
||||||
const _IconTextButton({Key? key, this.onPressed, this.title, this.icon})
|
const _IconTextButton({Key? key, this.onPressed, this.title, this.icon})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
|
@ -37,20 +37,27 @@ class BrandHeroScreen extends StatelessWidget {
|
||||||
padding: EdgeInsets.all(16.0),
|
padding: EdgeInsets.all(16.0),
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
if (heroIcon != null)
|
if (heroIcon != null)
|
||||||
Icon(
|
Container(
|
||||||
heroIcon,
|
child: Icon(
|
||||||
size: 48.0,
|
heroIcon,
|
||||||
|
size: 48.0,
|
||||||
|
),
|
||||||
|
alignment: Alignment.bottomLeft,
|
||||||
),
|
),
|
||||||
SizedBox(height: 16.0),
|
SizedBox(height: 8.0),
|
||||||
if (heroTitle != null)
|
if (heroTitle != null)
|
||||||
Text(heroTitle!,
|
Text(
|
||||||
style: Theme.of(context).textTheme.headline2,
|
heroTitle!,
|
||||||
textAlign: TextAlign.center),
|
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.start,
|
||||||
|
),
|
||||||
SizedBox(height: 8.0),
|
SizedBox(height: 8.0),
|
||||||
if (heroSubtitle != null)
|
if (heroSubtitle != null)
|
||||||
Text(heroSubtitle!,
|
Text(heroSubtitle!,
|
||||||
style: Theme.of(context).textTheme.bodyMedium,
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
textAlign: TextAlign.center),
|
textAlign: TextAlign.start),
|
||||||
SizedBox(height: 16.0),
|
SizedBox(height: 16.0),
|
||||||
...children,
|
...children,
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,10 +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/config/brand_colors.dart';
|
|
||||||
import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart';
|
import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart';
|
||||||
|
|
||||||
final _kBottomTabBarHeight = 51;
|
|
||||||
|
|
||||||
class BrandTabBar extends StatefulWidget {
|
class BrandTabBar extends StatefulWidget {
|
||||||
BrandTabBar({Key? key, this.controller}) : super(key: key);
|
BrandTabBar({Key? key, this.controller}) : super(key: key);
|
||||||
|
|
||||||
|
@ -43,24 +40,17 @@ class _BrandTabBarState extends State<BrandTabBar> {
|
||||||
_getIconButton('basis.providers'.tr(), BrandIcons.server, 0),
|
_getIconButton('basis.providers'.tr(), BrandIcons.server, 0),
|
||||||
_getIconButton('basis.services'.tr(), BrandIcons.box, 1),
|
_getIconButton('basis.services'.tr(), BrandIcons.box, 1),
|
||||||
_getIconButton('basis.users'.tr(), BrandIcons.users, 2),
|
_getIconButton('basis.users'.tr(), BrandIcons.users, 2),
|
||||||
_getIconButton('basis.more'.tr(), BrandIcons.menu, 3),
|
_getIconButton('basis.more'.tr(), Icons.menu_rounded, 3),
|
||||||
],
|
],
|
||||||
onDestinationSelected: (index) {
|
onDestinationSelected: (index) {
|
||||||
widget.controller!.animateTo(index);
|
widget.controller!.animateTo(index);
|
||||||
},
|
},
|
||||||
selectedIndex: currentIndex ?? 0,
|
selectedIndex: currentIndex ?? 0,
|
||||||
labelBehavior: NavigationDestinationLabelBehavior.onlyShowSelected,
|
labelBehavior: NavigationDestinationLabelBehavior.onlyShowSelected,
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_getIconButton(String label, IconData iconData, int index) {
|
_getIconButton(String label, IconData iconData, int index) {
|
||||||
var activeColor = Theme.of(context).brightness == Brightness.dark
|
|
||||||
? BrandColors.white
|
|
||||||
: BrandColors.black;
|
|
||||||
|
|
||||||
var isActive = currentIndex == index;
|
|
||||||
var color = isActive ? activeColor : BrandColors.inactive;
|
|
||||||
return NavigationDestination(
|
return NavigationDestination(
|
||||||
icon: Icon(iconData),
|
icon: Icon(iconData),
|
||||||
label: label,
|
label: label,
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:ionicons/ionicons.dart';
|
||||||
|
import 'package:selfprivacy/config/brand_colors.dart';
|
||||||
|
import 'package:selfprivacy/logic/cubit/jobs/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/helpers/modals.dart';
|
||||||
|
|
||||||
|
class BrandFab extends StatefulWidget {
|
||||||
|
BrandFab({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_BrandFabState createState() => _BrandFabState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _BrandFabState extends State<BrandFab>
|
||||||
|
with SingleTickerProviderStateMixin {
|
||||||
|
late AnimationController _animationController;
|
||||||
|
late Animation _colorTween;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
_animationController =
|
||||||
|
AnimationController(vsync: this, duration: Duration(milliseconds: 800));
|
||||||
|
_colorTween = ColorTween(
|
||||||
|
begin: BrandColors.black,
|
||||||
|
end: BrandColors.primary,
|
||||||
|
).animate(_animationController);
|
||||||
|
|
||||||
|
super.initState();
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback(_afterLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _afterLayout(_) {
|
||||||
|
if (Theme.of(context).brightness == Brightness.dark) {
|
||||||
|
setState(() {
|
||||||
|
_colorTween = ColorTween(
|
||||||
|
begin: BrandColors.white,
|
||||||
|
end: BrandColors.primary,
|
||||||
|
).animate(_animationController);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_animationController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wasPrevStateIsEmpty = true;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocListener<JobsCubit, JobsState>(
|
||||||
|
listener: (context, state) {
|
||||||
|
if (wasPrevStateIsEmpty && state is! JobsStateEmpty) {
|
||||||
|
wasPrevStateIsEmpty = false;
|
||||||
|
_animationController.forward();
|
||||||
|
} else if (!wasPrevStateIsEmpty && state is JobsStateEmpty) {
|
||||||
|
wasPrevStateIsEmpty = true;
|
||||||
|
|
||||||
|
_animationController.reverse();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: FloatingActionButton(
|
||||||
|
onPressed: () {
|
||||||
|
showBrandBottomSheet(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => BrandBottomSheet(
|
||||||
|
isExpended: true,
|
||||||
|
child: JobsContent(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: AnimatedBuilder(
|
||||||
|
animation: _colorTween,
|
||||||
|
builder: (context, child) {
|
||||||
|
var v = _animationController.value;
|
||||||
|
var icon = 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,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,14 +1,14 @@
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:selfprivacy/logic/api_maps/server.dart';
|
import 'package:selfprivacy/logic/api_maps/server.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_icons/brand_icons.dart';
|
|
||||||
import 'package:selfprivacy/ui/components/brand_tab_bar/brand_tab_bar.dart';
|
import 'package:selfprivacy/ui/components/brand_tab_bar/brand_tab_bar.dart';
|
||||||
import 'package:selfprivacy/ui/pages/more/more.dart';
|
import 'package:selfprivacy/ui/pages/more/more.dart';
|
||||||
import 'package:selfprivacy/ui/pages/providers/providers.dart';
|
import 'package:selfprivacy/ui/pages/providers/providers.dart';
|
||||||
import 'package:selfprivacy/ui/pages/services/services.dart';
|
import 'package:selfprivacy/ui/pages/services/services.dart';
|
||||||
import 'package:selfprivacy/ui/pages/users/users.dart';
|
import 'package:selfprivacy/ui/pages/users/users.dart';
|
||||||
|
|
||||||
|
import '../components/pre_styled_buttons/flashFab.dart';
|
||||||
|
|
||||||
class RootPage extends StatefulWidget {
|
class RootPage extends StatefulWidget {
|
||||||
const RootPage({Key? key}) : super(key: key);
|
const RootPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@ -53,6 +53,7 @@ class _RootPageState extends State<RootPage>
|
||||||
bottomNavigationBar: BrandTabBar(
|
bottomNavigationBar: BrandTabBar(
|
||||||
controller: tabController,
|
controller: tabController,
|
||||||
),
|
),
|
||||||
|
floatingActionButton: BrandFab(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:selfprivacy/logic/cubit/app_config/app_config_cubit.dart';
|
import 'package:selfprivacy/logic/cubit/app_config/app_config_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/brand_button/FilledButton.dart';
|
||||||
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
import 'package:selfprivacy/ui/components/brand_hero_screen/brand_hero_screen.dart';
|
||||||
|
|
||||||
class RecoveryDomain extends StatelessWidget {
|
class RecoveryDomain extends StatelessWidget {
|
||||||
|
@ -29,18 +29,17 @@ class RecoveryDomain extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SizedBox(height: 16),
|
SizedBox(height: 16),
|
||||||
BrandButton.rised(
|
FilledButton(
|
||||||
|
title: "more.continue".tr(),
|
||||||
onPressed: formCubitState.isSubmitting
|
onPressed: formCubitState.isSubmitting
|
||||||
? null
|
? null
|
||||||
: () => context.read<RecoveryDomainFormCubit>().trySubmit(),
|
: () => context.read<RecoveryDomainFormCubit>().trySubmit(),
|
||||||
text: "more.continue".tr(),
|
)
|
||||||
),
|
|
||||||
],
|
],
|
||||||
heroTitle: "recovering.recovery_main_header".tr(),
|
heroTitle: "recovering.recovery_main_header".tr(),
|
||||||
heroSubtitle: "recovering.domain_recovery_description".tr(),
|
heroSubtitle: "recovering.domain_recovery_description".tr(),
|
||||||
hasBackButton: true,
|
hasBackButton: true,
|
||||||
hasFlashButton: false,
|
hasFlashButton: false,
|
||||||
heroIcon: Icons.link,
|
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue