refactor: onboarding page ui
parent
803530e959
commit
9050677ab2
|
@ -2,7 +2,7 @@ import 'package:auto_route/auto_route.dart';
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/logic/cubit/app_settings/app_settings_cubit.dart';
|
||||
import 'package:selfprivacy/ui/components/buttons/brand_button.dart';
|
||||
import 'package:selfprivacy/ui/pages/onboarding/views/views.dart';
|
||||
import 'package:selfprivacy/ui/router/router.dart';
|
||||
|
||||
@RoutePage()
|
||||
|
@ -17,152 +17,35 @@ class _OnboardingPageState extends State<OnboardingPage> {
|
|||
PageController pageController = PageController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
void dispose() {
|
||||
pageController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> scrollTo(final int targetView) => pageController.animateToPage(
|
||||
targetView,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeInOutCubicEmphasized,
|
||||
);
|
||||
|
||||
@override
|
||||
Widget build(final BuildContext context) => Scaffold(
|
||||
body: PageView(
|
||||
Widget build(final BuildContext context) => Material(
|
||||
child: PageView(
|
||||
controller: pageController,
|
||||
children: [
|
||||
_withPadding(firstPage()),
|
||||
_withPadding(secondPage()),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
Widget _withPadding(final Widget child) => Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 15,
|
||||
),
|
||||
child: child,
|
||||
);
|
||||
|
||||
Widget firstPage() => ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxHeight: MediaQuery.of(context).size.height,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: ListView(
|
||||
children: [
|
||||
const SizedBox(height: 30),
|
||||
Text(
|
||||
'onboarding.page1_title'.tr(),
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'onboarding.page1_text'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
Center(
|
||||
child: Image.asset(
|
||||
_fileName(
|
||||
context: context,
|
||||
path: 'assets/images/onboarding',
|
||||
fileExtention: 'png',
|
||||
fileName: 'onboarding1',
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
OnboardingFirstView(
|
||||
onProceed: () => scrollTo(1),
|
||||
),
|
||||
BrandButton.rised(
|
||||
onPressed: () {
|
||||
pageController.animateToPage(
|
||||
1,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeInOutCubicEmphasized,
|
||||
);
|
||||
},
|
||||
text: 'basis.next'.tr(),
|
||||
),
|
||||
const SizedBox(height: 30),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
Widget secondPage() => ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxHeight: MediaQuery.of(context).size.height,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: ListView(
|
||||
children: [
|
||||
const SizedBox(height: 30),
|
||||
Text(
|
||||
'onboarding.page2_title'.tr(),
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'onboarding.page2_text'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'onboarding.page2_server_provider_title'.tr(),
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'onboarding.page2_server_provider_text'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'onboarding.page2_dns_provider_title'.tr(),
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'onboarding.page2_dns_provider_text'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'onboarding.page2_backup_provider_title'.tr(),
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'onboarding.page2_backup_provider_text'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
BrandButton.rised(
|
||||
onPressed: () {
|
||||
OnboardingSecondView(
|
||||
onProceed: () {
|
||||
context.read<AppSettingsCubit>().turnOffOnboarding();
|
||||
context.router.replaceAll([
|
||||
const RootRoute(),
|
||||
const InitializingRoute(),
|
||||
]);
|
||||
},
|
||||
text: 'basis.got_it'.tr(),
|
||||
),
|
||||
const SizedBox(height: 30),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String _fileName({
|
||||
required final BuildContext context,
|
||||
required final String path,
|
||||
required final String fileName,
|
||||
required final String fileExtention,
|
||||
}) {
|
||||
final ThemeData theme = Theme.of(context);
|
||||
final bool isDark = theme.brightness == Brightness.dark;
|
||||
return '$path/$fileName${isDark ? '-dark' : '-light'}.$fileExtention';
|
||||
}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:selfprivacy/ui/pages/onboarding/views/onboarding_view.dart';
|
||||
|
||||
class OnboardingFirstView extends StatelessWidget {
|
||||
const OnboardingFirstView({
|
||||
required this.onProceed,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final VoidCallback onProceed;
|
||||
|
||||
String assetName({
|
||||
required final BuildContext context,
|
||||
required final String path,
|
||||
required final String fileName,
|
||||
required final String fileExtension,
|
||||
}) {
|
||||
final String suffix =
|
||||
Theme.of(context).brightness == Brightness.dark ? '-dark' : '-light';
|
||||
return '$path/$fileName$suffix.$fileExtension';
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(final BuildContext context) => OnboardingView(
|
||||
onProceed: onProceed,
|
||||
children: [
|
||||
Text(
|
||||
'onboarding.page1_title'.tr(),
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
const Gap(15),
|
||||
Text(
|
||||
'onboarding.page1_text'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
const Gap(30),
|
||||
Image.asset(
|
||||
assetName(
|
||||
context: context,
|
||||
path: 'assets/images/onboarding',
|
||||
fileName: 'onboarding1',
|
||||
fileExtension: 'png',
|
||||
),
|
||||
fit: BoxFit.fitWidth,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:selfprivacy/ui/pages/onboarding/views/onboarding_view.dart';
|
||||
|
||||
class OnboardingSecondView extends StatelessWidget {
|
||||
const OnboardingSecondView({
|
||||
required this.onProceed,
|
||||
super.key,
|
||||
});
|
||||
|
||||
final VoidCallback onProceed;
|
||||
|
||||
@override
|
||||
Widget build(final BuildContext context) => OnboardingView(
|
||||
buttonTitle: 'basis.got_it',
|
||||
onProceed: onProceed,
|
||||
children: [
|
||||
Text(
|
||||
'onboarding.page2_title'.tr(),
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
const Gap(16),
|
||||
Text(
|
||||
'onboarding.page2_text'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
const Gap(16),
|
||||
Text(
|
||||
'onboarding.page2_server_provider_title'.tr(),
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
const Gap(16),
|
||||
Text(
|
||||
'onboarding.page2_server_provider_text'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
const Gap(16),
|
||||
Text(
|
||||
'onboarding.page2_dns_provider_title'.tr(),
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
const Gap(16),
|
||||
Text(
|
||||
'onboarding.page2_dns_provider_text'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
const Gap(16),
|
||||
Text(
|
||||
'onboarding.page2_backup_provider_title'.tr(),
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
const Gap(16),
|
||||
Text(
|
||||
'onboarding.page2_backup_provider_text'.tr(),
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:selfprivacy/ui/components/buttons/buttons.dart';
|
||||
|
||||
// base widget for onboarding view
|
||||
class OnboardingView extends StatelessWidget {
|
||||
const OnboardingView({
|
||||
required this.onProceed,
|
||||
required this.children,
|
||||
this.buttonTitle = 'basis.next',
|
||||
super.key,
|
||||
});
|
||||
|
||||
/// Proceed button title
|
||||
final String buttonTitle;
|
||||
|
||||
/// Proceed button callback
|
||||
final VoidCallback onProceed;
|
||||
|
||||
/// Current view content
|
||||
final List<Widget> children;
|
||||
|
||||
@override
|
||||
Widget build(final BuildContext context) => Scaffold(
|
||||
body: Align(
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 480),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Expanded(
|
||||
child: ListView(
|
||||
primary: true,
|
||||
shrinkWrap: true,
|
||||
padding: const EdgeInsets.all(15) +
|
||||
const EdgeInsets.only(top: 15),
|
||||
children: children,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15) +
|
||||
const EdgeInsets.only(bottom: 30),
|
||||
child: SPBrandButton.text(
|
||||
title: buttonTitle.tr(),
|
||||
onPressed: onProceed,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
export 'onboarding_first_view.dart';
|
||||
export 'onboarding_second_view.dart';
|
Loading…
Reference in New Issue