feat: make the transition when navigating to the introduction screen more fluent

This commit is contained in:
mike doornenbal 2025-02-18 16:18:33 +01:00
parent 25b3988aea
commit d3d76de017
7 changed files with 68 additions and 38 deletions

View file

@ -7,12 +7,18 @@ import "package:introduction_repository_interface/introduction_repository_interf
class FirebaseIntroductionRepository class FirebaseIntroductionRepository
implements IntroductionRepositoryInterface { implements IntroductionRepositoryInterface {
bool? _shouldShowIntroduction;
List<IntroductionPageData>? _introductionPages;
final _introductionCollection = FirebaseFirestore.instance final _introductionCollection = FirebaseFirestore.instance
.collection("flutter_introduction") .collection("flutter_introduction")
.doc("flutter_introduction"); .doc("flutter_introduction");
@override @override
Future<List<IntroductionPageData>> fetchIntroductionPages() async { Future<List<IntroductionPageData>> fetchIntroductionPages() async {
if (_introductionPages != null) {
return _introductionPages!;
}
try { try {
var introductionPagesData = await _introductionCollection var introductionPagesData = await _introductionCollection
.collection("pages") .collection("pages")
@ -27,6 +33,7 @@ class FirebaseIntroductionRepository
introductionPagesData.docs.map((e) => e.data()).toList(); introductionPagesData.docs.map((e) => e.data()).toList();
introductionPages.sort((a, b) => a.id.compareTo(b.id)); introductionPages.sort((a, b) => a.id.compareTo(b.id));
_introductionPages = introductionPages;
return introductionPages; return introductionPages;
} on Exception catch (_) { } on Exception catch (_) {
throw Exception(); throw Exception();
@ -51,6 +58,9 @@ class FirebaseIntroductionRepository
@override @override
Future<bool> shouldShow() async { Future<bool> shouldShow() async {
if (_shouldShowIntroduction != null) {
return _shouldShowIntroduction!;
}
try { try {
await FirebaseAuth.instance.signInAnonymously(); await FirebaseAuth.instance.signInAnonymously();
var deviceId = await _getDeviceId(); var deviceId = await _getDeviceId();
@ -64,8 +74,10 @@ class FirebaseIntroductionRepository
if (!introductionCompleted.exists) { if (!introductionCompleted.exists) {
return true; return true;
} }
// ignore: avoid_dynamic_calls _shouldShowIntroduction =
return !introductionCompleted.data()!["introduction_completed"]; // ignore: avoid_dynamic_calls
!introductionCompleted.data()!["introduction_completed"];
return _shouldShowIntroduction!;
} on Exception catch (_) { } on Exception catch (_) {
throw Exception(); throw Exception();
} }
@ -83,4 +95,10 @@ class FirebaseIntroductionRepository
} }
return null; return null;
} }
@override
Future<void> prefetchIntroduction() async {
await shouldShow();
await fetchIntroductionPages();
}
} }

View file

@ -17,38 +17,33 @@ class Button extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var theme = Theme.of(context); var theme = Theme.of(context);
return Expanded( return Expanded(
child: ConstrainedBox( child: showButton
constraints: const BoxConstraints( ? FilledButton(
maxWidth: 180, style: ButtonStyle(
maxHeight: 32, tapTargetSize: MaterialTapTargetSize.shrinkWrap,
), minimumSize: WidgetStateProperty.all(const Size(160, 32)),
child: showButton backgroundColor: WidgetStateProperty.all(
? FilledButton( introductionTheme.buttonBackgroundColor,
style: ButtonStyle( ),
backgroundColor: WidgetStateProperty.all( shape: WidgetStateProperty.all(
introductionTheme.buttonBackgroundColor, RoundedRectangleBorder(
), borderRadius: const BorderRadius.all(Radius.circular(16)),
shape: WidgetStateProperty.all( side: BorderSide(
RoundedRectangleBorder( color: introductionTheme.buttonBorderColor,
borderRadius: const BorderRadius.all(Radius.circular(16)), width: 1,
side: BorderSide(
color: introductionTheme.buttonBorderColor,
width: 1,
),
), ),
), ),
), ),
onPressed: onPressed, ),
child: Text( onPressed: onPressed,
text, child: Text(
style: introductionTheme.buttonTextStyle ?? text,
theme.textTheme.bodyMedium, style: introductionTheme.buttonTextStyle ??
), theme.textTheme.bodyMedium,
) ),
: const SizedBox(), )
), : const SizedBox.shrink(),
); );
} }
} }

View file

@ -1,7 +1,5 @@
import "package:flutter/material.dart"; import "package:flutter/material.dart";
import "package:flutter_introduction/flutter_introduction.dart"; import "package:flutter_introduction/flutter_introduction.dart";
import "package:flutter_introduction/src/config/introduction_theme.dart";
import "package:flutter_introduction/src/enums/introduction_layout_style.dart";
class IntroductionPage extends StatelessWidget { class IntroductionPage extends StatelessWidget {
const IntroductionPage({ const IntroductionPage({

View file

@ -7,4 +7,6 @@ abstract class IntroductionRepositoryInterface {
Future<void> setCompleted({bool value = true}); Future<void> setCompleted({bool value = true});
Future<bool> shouldShow(); Future<bool> shouldShow();
Future<void> prefetchIntroduction();
} }

View file

@ -11,7 +11,11 @@ class LocalIntroductionRepository implements IntroductionRepositoryInterface {
Future<bool> shouldShow() async => !_completed; Future<bool> shouldShow() async => !_completed;
@override @override
Future<List<IntroductionPageData>> fetchIntroductionPages() { Future<List<IntroductionPageData>> fetchIntroductionPages() async => [];
throw Exception();
@override
Future<void> prefetchIntroduction() async {
await shouldShow();
await fetchIntroductionPages();
} }
} }

View file

@ -16,4 +16,7 @@ class IntroductionService {
Future<bool> shouldShow() async => Future<bool> shouldShow() async =>
introductionRepositoryInterface.shouldShow(); introductionRepositoryInterface.shouldShow();
Future<void> prefetchIntroduction() async =>
introductionRepositoryInterface.prefetchIntroduction();
} }

View file

@ -3,10 +3,10 @@ import "package:shared_preferences/shared_preferences.dart";
class SharedPreferencesIntroductionRepository class SharedPreferencesIntroductionRepository
implements IntroductionRepositoryInterface { implements IntroductionRepositoryInterface {
bool? _shouldShowIntroduction;
@override @override
Future<List<IntroductionPageData>> fetchIntroductionPages() async { Future<List<IntroductionPageData>> fetchIntroductionPages() async => [];
throw Exception();
}
@override @override
Future<void> setCompleted({bool value = true}) async { Future<void> setCompleted({bool value = true}) async {
@ -16,8 +16,18 @@ class SharedPreferencesIntroductionRepository
@override @override
Future<bool> shouldShow() async { Future<bool> shouldShow() async {
if (_shouldShowIntroduction != null) {
return !_shouldShowIntroduction!;
}
var sharedPrefs = await SharedPreferences.getInstance(); var sharedPrefs = await SharedPreferences.getInstance();
var shouldShow = sharedPrefs.getBool("_completedIntroduction") ?? true; var shouldShow = sharedPrefs.getBool("_completedIntroduction") ?? true;
return !shouldShow; _shouldShowIntroduction = shouldShow;
return !_shouldShowIntroduction!;
}
@override
Future<void> prefetchIntroduction() async {
await shouldShow();
await fetchIntroductionPages();
} }
} }