refactor: onboarding page ui

pull/444/head
Aliaksei Tratseuski 2024-02-05 14:13:37 +04:00 committed by aliaksei tratseuski
parent 803530e959
commit 9050677ab2
5 changed files with 181 additions and 133 deletions

View File

@ -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';
}

View File

@ -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,
),
],
);
}

View File

@ -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,
),
],
);
}

View File

@ -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,
),
),
],
),
),
),
);
}

View File

@ -0,0 +1,2 @@
export 'onboarding_first_view.dart';
export 'onboarding_second_view.dart';