mirror of
https://github.com/Myzel394/quid_faciam_hodie.git
synced 2025-06-19 15:45:26 +02:00
improved welcome screen photo switching; improvements & bugfixes
This commit is contained in:
parent
6a5d50d1ba
commit
b226908383
@ -136,7 +136,7 @@
|
|||||||
|
|
||||||
|
|
||||||
"emptyScreenTitle": "Houston, we have a problem",
|
"emptyScreenTitle": "Houston, we have a problem",
|
||||||
"emptyScreenSubtitle": "The user hasn't created any mem ories yet!",
|
"emptyScreenSubtitle": "The user hasn't created any memories yet!",
|
||||||
"emptyScreenDescription": "To view your timeline you need to create some memories first! :)",
|
"emptyScreenDescription": "To view your timeline you need to create some memories first! :)",
|
||||||
"emptyScreenCreateMemory": "Create a Memory",
|
"emptyScreenCreateMemory": "Create a Memory",
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
|||||||
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
|
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
|
||||||
import 'package:lottie/lottie.dart';
|
import 'package:lottie/lottie.dart';
|
||||||
import 'package:quid_faciam_hodie/constants/spacing.dart';
|
import 'package:quid_faciam_hodie/constants/spacing.dart';
|
||||||
import 'package:quid_faciam_hodie/screens/main_screen.dart';
|
|
||||||
import 'package:quid_faciam_hodie/utils/theme.dart';
|
import 'package:quid_faciam_hodie/utils/theme.dart';
|
||||||
|
|
||||||
import '../widgets/icon_button_child.dart';
|
import '../widgets/icon_button_child.dart';
|
||||||
@ -56,8 +55,7 @@ class EmptyScreen extends StatelessWidget {
|
|||||||
label: Text(localizations.emptyScreenCreateMemory),
|
label: Text(localizations.emptyScreenCreateMemory),
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pushNamedAndRemoveUntil(
|
Navigator.pop(context);
|
||||||
context, MainScreen.ID, (_) => false);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
|
||||||
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
|
import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
|
||||||
import 'package:quid_faciam_hodie/constants/spacing.dart';
|
import 'package:quid_faciam_hodie/constants/spacing.dart';
|
||||||
|
import 'package:quid_faciam_hodie/constants/values.dart';
|
||||||
|
import 'package:quid_faciam_hodie/managers/photo_manager.dart';
|
||||||
import 'package:quid_faciam_hodie/managers/user_help_sheets_manager.dart';
|
import 'package:quid_faciam_hodie/managers/user_help_sheets_manager.dart';
|
||||||
|
import 'package:quid_faciam_hodie/screens/welcome_screen/pages/view_memories_page.dart';
|
||||||
|
|
||||||
|
import 'welcome_screen/pages/create_memories_page.dart';
|
||||||
import 'welcome_screen/pages/get_started_page.dart';
|
import 'welcome_screen/pages/get_started_page.dart';
|
||||||
import 'welcome_screen/pages/guide_page.dart';
|
|
||||||
import 'welcome_screen/pages/initial_page.dart';
|
import 'welcome_screen/pages/initial_page.dart';
|
||||||
|
|
||||||
class WelcomeScreen extends StatefulWidget {
|
class WelcomeScreen extends StatefulWidget {
|
||||||
@ -18,6 +22,7 @@ class WelcomeScreen extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _WelcomeScreenState extends State<WelcomeScreen> {
|
class _WelcomeScreenState extends State<WelcomeScreen> {
|
||||||
|
NetworkImage? _initialImageForPhotoSwitching;
|
||||||
final controller = PageController();
|
final controller = PageController();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -25,6 +30,7 @@ class _WelcomeScreenState extends State<WelcomeScreen> {
|
|||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
UserHelpSheetsManager.deleteAll();
|
UserHelpSheetsManager.deleteAll();
|
||||||
|
getInitialImageForPhotoSwitching();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -34,6 +40,20 @@ class _WelcomeScreenState extends State<WelcomeScreen> {
|
|||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void getInitialImageForPhotoSwitching() async {
|
||||||
|
final query = WELCOME_SCREEN_PHOTOS_QUERIES[
|
||||||
|
Random().nextInt(WELCOME_SCREEN_PHOTOS_QUERIES.length)];
|
||||||
|
final url = await PhotoManager.getRandomPhoto(query);
|
||||||
|
|
||||||
|
if (!mounted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_initialImageForPhotoSwitching = NetworkImage(url);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void nextPage() {
|
void nextPage() {
|
||||||
controller.animateToPage(
|
controller.animateToPage(
|
||||||
(controller.page! + 1).toInt(),
|
(controller.page! + 1).toInt(),
|
||||||
@ -44,8 +64,6 @@ class _WelcomeScreenState extends State<WelcomeScreen> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final localizations = AppLocalizations.of(context)!;
|
|
||||||
|
|
||||||
return PlatformScaffold(
|
return PlatformScaffold(
|
||||||
body: Padding(
|
body: Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: MEDIUM_SPACE),
|
padding: const EdgeInsets.symmetric(vertical: MEDIUM_SPACE),
|
||||||
@ -53,19 +71,11 @@ class _WelcomeScreenState extends State<WelcomeScreen> {
|
|||||||
child: PageView(
|
child: PageView(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
InitialPage(
|
InitialPage(onNextPage: nextPage),
|
||||||
|
CreateMemoriesPage(onNextPage: nextPage),
|
||||||
|
ViewMemoriesPage(
|
||||||
onNextPage: nextPage,
|
onNextPage: nextPage,
|
||||||
),
|
initialImage: _initialImageForPhotoSwitching,
|
||||||
GuidePage(
|
|
||||||
onNextPage: nextPage,
|
|
||||||
description:
|
|
||||||
localizations.welcomeScreenCreateMemoriesGuideDescription,
|
|
||||||
picture: 'assets/images/live_photo.svg',
|
|
||||||
),
|
|
||||||
GuidePage(
|
|
||||||
onNextPage: nextPage,
|
|
||||||
description:
|
|
||||||
localizations.welcomeScreenViewMemoriesGuideDescription,
|
|
||||||
),
|
),
|
||||||
const GetStartedPage(),
|
const GetStartedPage(),
|
||||||
],
|
],
|
||||||
|
39
lib/screens/welcome_screen/pages/create_memories_page.dart
Normal file
39
lib/screens/welcome_screen/pages/create_memories_page.dart
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:quid_faciam_hodie/constants/spacing.dart';
|
||||||
|
import 'package:quid_faciam_hodie/screens/welcome_screen/crabs/next_button.dart';
|
||||||
|
import 'package:quid_faciam_hodie/utils/theme.dart';
|
||||||
|
|
||||||
|
class CreateMemoriesPage extends StatelessWidget {
|
||||||
|
final VoidCallback onNextPage;
|
||||||
|
|
||||||
|
const CreateMemoriesPage({
|
||||||
|
Key? key,
|
||||||
|
required this.onNextPage,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final localizations = AppLocalizations.of(context)!;
|
||||||
|
|
||||||
|
return Center(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: MEDIUM_SPACE),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
SvgPicture.asset('assets/images/live_photo.svg', height: 400),
|
||||||
|
const SizedBox(height: LARGE_SPACE),
|
||||||
|
Text(
|
||||||
|
localizations.welcomeScreenCreateMemoriesGuideDescription,
|
||||||
|
style: getBodyTextTextStyle(context),
|
||||||
|
),
|
||||||
|
const SizedBox(height: LARGE_SPACE),
|
||||||
|
CrabNextButton(onPressed: onNextPage),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,41 +1,39 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||||
import 'package:quid_faciam_hodie/constants/spacing.dart';
|
import 'package:quid_faciam_hodie/constants/spacing.dart';
|
||||||
import 'package:quid_faciam_hodie/screens/welcome_screen/crabs/next_button.dart';
|
import 'package:quid_faciam_hodie/screens/welcome_screen/crabs/next_button.dart';
|
||||||
import 'package:quid_faciam_hodie/screens/welcome_screen/photo_switching.dart';
|
import 'package:quid_faciam_hodie/screens/welcome_screen/photo_switching.dart';
|
||||||
import 'package:quid_faciam_hodie/utils/theme.dart';
|
import 'package:quid_faciam_hodie/utils/theme.dart';
|
||||||
|
|
||||||
class GuidePage extends StatelessWidget {
|
class ViewMemoriesPage extends StatelessWidget {
|
||||||
final String? picture;
|
|
||||||
final String description;
|
|
||||||
final VoidCallback onNextPage;
|
final VoidCallback onNextPage;
|
||||||
|
final NetworkImage? initialImage;
|
||||||
|
|
||||||
const GuidePage({
|
const ViewMemoriesPage({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.description,
|
|
||||||
required this.onNextPage,
|
required this.onNextPage,
|
||||||
this.picture,
|
this.initialImage,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final localizations = AppLocalizations.of(context)!;
|
||||||
|
|
||||||
return Center(
|
return Center(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: MEDIUM_SPACE),
|
padding: const EdgeInsets.symmetric(horizontal: MEDIUM_SPACE),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
picture == null
|
Expanded(
|
||||||
? const Expanded(
|
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.only(top: LARGE_SPACE),
|
padding: const EdgeInsets.only(top: LARGE_SPACE),
|
||||||
child: PhotoSwitching(),
|
child: PhotoSwitching(initialImage: initialImage),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
|
||||||
: SvgPicture.asset(picture!, height: 400),
|
|
||||||
const SizedBox(height: LARGE_SPACE),
|
const SizedBox(height: LARGE_SPACE),
|
||||||
Text(
|
Text(
|
||||||
description,
|
localizations.welcomeScreenViewMemoriesGuideDescription,
|
||||||
style: getBodyTextTextStyle(context),
|
style: getBodyTextTextStyle(context),
|
||||||
),
|
),
|
||||||
const SizedBox(height: LARGE_SPACE),
|
const SizedBox(height: LARGE_SPACE),
|
@ -5,43 +5,114 @@ import 'package:flutter_platform_widgets/flutter_platform_widgets.dart';
|
|||||||
import 'package:quid_faciam_hodie/constants/spacing.dart';
|
import 'package:quid_faciam_hodie/constants/spacing.dart';
|
||||||
import 'package:quid_faciam_hodie/constants/values.dart';
|
import 'package:quid_faciam_hodie/constants/values.dart';
|
||||||
import 'package:quid_faciam_hodie/managers/photo_manager.dart';
|
import 'package:quid_faciam_hodie/managers/photo_manager.dart';
|
||||||
import 'package:quid_faciam_hodie/utils/loadable.dart';
|
|
||||||
import 'package:quid_faciam_hodie/widgets/status.dart';
|
import 'package:quid_faciam_hodie/widgets/status.dart';
|
||||||
|
|
||||||
class PhotoSwitching extends StatefulWidget {
|
class PhotoSwitching extends StatefulWidget {
|
||||||
const PhotoSwitching({Key? key}) : super(key: key);
|
final NetworkImage? initialImage;
|
||||||
|
|
||||||
|
const PhotoSwitching({
|
||||||
|
Key? key,
|
||||||
|
this.initialImage,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<PhotoSwitching> createState() => _PhotoSwitchingState();
|
State<PhotoSwitching> createState() => _PhotoSwitchingState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PhotoSwitchingState extends State<PhotoSwitching> with Loadable {
|
class _PhotoSwitchingState extends State<PhotoSwitching> {
|
||||||
String photoURL = '';
|
// Contains two photos, the first one is the current photo, the second one is the next photo.
|
||||||
|
// The second one will be precached for faster image switching
|
||||||
|
late final List<NetworkImage> images;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
callWithLoading(getNextPhoto);
|
if (widget.initialImage != null) {
|
||||||
|
images = [widget.initialImage!];
|
||||||
|
getInitialPhoto();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> getNextPhoto() async {
|
@override
|
||||||
|
void didUpdateWidget(PhotoSwitching oldWidget) {
|
||||||
|
super.didUpdateWidget(oldWidget);
|
||||||
|
|
||||||
|
if (widget.initialImage != null) {
|
||||||
|
images = [widget.initialImage!];
|
||||||
|
getInitialPhoto();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> getInitialPhoto() async {
|
||||||
final query = WELCOME_SCREEN_PHOTOS_QUERIES[
|
final query = WELCOME_SCREEN_PHOTOS_QUERIES[
|
||||||
Random().nextInt(WELCOME_SCREEN_PHOTOS_QUERIES.length)];
|
Random().nextInt(WELCOME_SCREEN_PHOTOS_QUERIES.length)];
|
||||||
final url = await PhotoManager.getRandomPhoto(query);
|
final url = await PhotoManager.getRandomPhoto(query);
|
||||||
|
final nextPhotoFuture = PhotoManager.getRandomPhoto(query);
|
||||||
|
|
||||||
if (!mounted) {
|
if (!mounted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
photoURL = url;
|
images.add(NetworkImage(url));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
final nextPhotoURL = await nextPhotoFuture;
|
||||||
|
|
||||||
|
if (!mounted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final nextImage = NetworkImage(nextPhotoURL);
|
||||||
|
precacheImage(nextImage, context);
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
images.add(nextImage);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> getNextPhoto() async {
|
||||||
|
final query = WELCOME_SCREEN_PHOTOS_QUERIES[
|
||||||
|
Random().nextInt(WELCOME_SCREEN_PHOTOS_QUERIES.length)];
|
||||||
|
final nextPhotoFuture = PhotoManager.getRandomPhoto(query);
|
||||||
|
|
||||||
|
if (images.length == 1) {
|
||||||
|
// We need to wait for the next photo to load first
|
||||||
|
final nextPhotoURL = await nextPhotoFuture;
|
||||||
|
|
||||||
|
if (!mounted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final nextImage = NetworkImage(nextPhotoURL);
|
||||||
|
precacheImage(nextImage, context);
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
images[0] = images[1];
|
||||||
|
images[1] = nextImage;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setState(() {
|
||||||
|
images[0] = images[1];
|
||||||
|
});
|
||||||
|
|
||||||
|
final nextPhotoURL = await nextPhotoFuture;
|
||||||
|
|
||||||
|
if (!mounted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final nextImage = NetworkImage(nextPhotoURL);
|
||||||
|
precacheImage(nextImage, context);
|
||||||
|
|
||||||
|
images[1] = nextImage;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (isLoading) {
|
if (widget.initialImage == null) {
|
||||||
return Center(
|
return Center(
|
||||||
child: PlatformCircularProgressIndicator(),
|
child: PlatformCircularProgressIndicator(),
|
||||||
);
|
);
|
||||||
@ -49,23 +120,18 @@ class _PhotoSwitchingState extends State<PhotoSwitching> with Loadable {
|
|||||||
|
|
||||||
return ClipRRect(
|
return ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(MEDIUM_SPACE),
|
borderRadius: BorderRadius.circular(MEDIUM_SPACE),
|
||||||
child: Image.network(
|
child: Status(
|
||||||
photoURL,
|
key: Key(images.toString()),
|
||||||
loadingBuilder: (context, child, loadingProgress) {
|
|
||||||
if (loadingProgress == null) {
|
|
||||||
return Status(
|
|
||||||
autoStart: true,
|
autoStart: true,
|
||||||
onEnd: () async {
|
onEnd: () async {
|
||||||
getNextPhoto();
|
getNextPhoto();
|
||||||
},
|
},
|
||||||
duration: const Duration(seconds: 3),
|
duration: const Duration(seconds: 3),
|
||||||
child: child,
|
child: Image(
|
||||||
);
|
image: images[0],
|
||||||
}
|
|
||||||
return const SizedBox.expand();
|
|
||||||
},
|
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user