mirror of
https://github.com/Myzel394/quid_faciam_hodie.git
synced 2025-06-18 15:25:27 +02:00
improved welcome screen
This commit is contained in:
parent
d17a62db90
commit
0a0e45bac2
1
assets/images/live_photo.svg
Normal file
1
assets/images/live_photo.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 7.3 KiB |
@ -1,3 +1,26 @@
|
||||
const SUPABASE_API_URL = 'https://gmqzelvauqziurlloawb.supabase.co';
|
||||
const SUPABASE_API_KEY =
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImdtcXplbHZhdXF6aXVybGxvYXdiIiwicm9sZSI6ImFub24iLCJpYXQiOjE2NjAzODE5MDcsImV4cCI6MTk3NTk1NzkwN30.D_964EIlD9WRFnG6MWtQtmIg04eMBbZhIEF7zl--bKw';
|
||||
import 'dart:convert';
|
||||
|
||||
// Encode keys to base64 to avoid simple bots from scraping them
|
||||
final SUPABASE_API_URL = String.fromCharCodes(
|
||||
base64.decode(
|
||||
'aHR0cHM6Ly9nbXF6ZWx' + '2YXVxeml1cmxsb2F3Yi5zdXBhYmFzZS5jbwo=',
|
||||
),
|
||||
);
|
||||
final SUPABASE_API_KEY = String.fromCharCodes(
|
||||
base64.decode(
|
||||
'ZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnBjM01pT2lKemRYQmhZbUZ6' +
|
||||
'WlNJc0luSmxaaUk2SW1kdGNYcGxiSFpoZFhGNmFYVnliR3h2WVhkaUlpd2ljbTlzWlNJNkltRnVi' +
|
||||
'MjRpTENKcFlYUWlPakUyTmpBek9ERTVNRGNzSW1WNGNDSTZNVGszTlRrMU56a3dOMzAuRF85NjRF' +
|
||||
'SWxEOVdSRm5HNk1XdFF0bUlnMDRlTUJiWmhJRUY3emwtLWJLdwo=',
|
||||
),
|
||||
);
|
||||
final PEXELS_API_KEY = String.fromCharCodes(
|
||||
base64.decode(
|
||||
'NTYz' +
|
||||
'NDkyYW' +
|
||||
'Q2ZjkxNzAwMDAxM' +
|
||||
'DAwMDAxYzE2ODA' +
|
||||
'0MGU2NjkzNGNlMT' +
|
||||
'kzNjdmZjA5NGU2NDMyM2IK',
|
||||
),
|
||||
);
|
||||
|
@ -8,3 +8,12 @@ final UnmodifiableSetView<double> DEFAULT_ZOOM_LEVELS =
|
||||
UnmodifiableSetView({0.6, 1, 2, 5, 10, 20, 50, 100});
|
||||
const CALENDAR_DATE_IN_MAX_DELAY = Duration(milliseconds: 500);
|
||||
const CACHE_INVALIDATION_DURATION = Duration(days: 7);
|
||||
const WELCOME_SCREEN_PHOTOS_QUERIES = [
|
||||
'happy',
|
||||
'people',
|
||||
'couple',
|
||||
'family',
|
||||
'fun',
|
||||
'friends',
|
||||
'romantic',
|
||||
];
|
||||
|
@ -26,4 +26,10 @@ class StatusController extends PropertyChangeNotifier<String> {
|
||||
_done = true;
|
||||
notifyListeners('done');
|
||||
}
|
||||
|
||||
void reset() {
|
||||
_done = false;
|
||||
_isForwarding = false;
|
||||
notifyListeners('done');
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
"generalError": "Ein Fehler ist aufgetreten",
|
||||
"generalCancelButtonLabel": "Abbrechen",
|
||||
"generalContinueButtonLabel": "Weiter",
|
||||
|
||||
"welcomeScreenDescription": "Finde heraus was du den ganzen Tag gemacht hast und erlebe Erinnerungen wieder, die du komplett vergessen hast!",
|
||||
"welcomeScreenSubtitle": "Was hab ich heute gemacht?",
|
||||
|
@ -3,10 +3,14 @@
|
||||
|
||||
"generalError": "There was an error",
|
||||
"generalCancelButtonLabel": "Cancel",
|
||||
"generalContinueButtonLabel": "Continue",
|
||||
|
||||
"welcomeScreenDescription": "Find out what you did all the days and unlock moments you completely forgot!",
|
||||
"welcomeScreenSubtitle": "What did I do today?",
|
||||
"welcomeScreenStartButtonTitle": "Start",
|
||||
"welcomeScreenCreateMemoriesGuideDescription": "Create photos and video thorough the day...",
|
||||
"welcomeScreenViewMemoriesGuideDescription": "...and relieve your best moments at the end of the day!",
|
||||
"welcomeScreenGetStartedLabel": "Get started",
|
||||
|
||||
|
||||
"serverLoadingScreenDescription": "We are loading your data",
|
||||
|
19
lib/managers/photo_manager.dart
Normal file
19
lib/managers/photo_manager.dart
Normal file
@ -0,0 +1,19 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
class PhotoManager {
|
||||
static const MAX_PHOTOS_PER_PAGE = 80;
|
||||
|
||||
// Searches for photos based on `query` and returns a random one.
|
||||
static Future<String> getRandomPhoto(final String query) async {
|
||||
final url =
|
||||
'https://api.pexels.com/v1/search?query=$query&per_page=$MAX_PHOTOS_PER_PAGE&orientation=portait';
|
||||
final response = await http.get(Uri.parse(url));
|
||||
final data = jsonDecode(response.body);
|
||||
final photoIndex = Random().nextInt(data['per_page']);
|
||||
|
||||
return data['photos'][photoIndex]['src']['portrait'];
|
||||
}
|
||||
}
|
@ -82,6 +82,7 @@ class _MemorySlideState extends State<MemorySlide>
|
||||
return Consumer<TimelineModel>(
|
||||
builder: (___, timeline, ____) => Status(
|
||||
controller: controller,
|
||||
isIndeterminate: controller == null,
|
||||
paused: timeline.paused,
|
||||
hideProgressBar: !timeline.showOverlay,
|
||||
child: MemoryView(
|
||||
|
@ -2,71 +2,74 @@ 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:quid_faciam_hodie/constants/spacing.dart';
|
||||
import 'package:quid_faciam_hodie/widgets/icon_button_child.dart';
|
||||
import 'package:quid_faciam_hodie/widgets/logo.dart';
|
||||
|
||||
import 'grant_permission_screen.dart';
|
||||
import 'welcome_screen/pages/get_started_page.dart';
|
||||
import 'welcome_screen/pages/guide_page.dart';
|
||||
import 'welcome_screen/pages/initial_page.dart';
|
||||
|
||||
class WelcomeScreen extends StatelessWidget {
|
||||
class WelcomeScreen extends StatefulWidget {
|
||||
static const ID = '/welcome';
|
||||
|
||||
const WelcomeScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<WelcomeScreen> createState() => _WelcomeScreenState();
|
||||
}
|
||||
|
||||
class _WelcomeScreenState extends State<WelcomeScreen> {
|
||||
final controller = PageController();
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
controller.dispose();
|
||||
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void nextPage() {
|
||||
controller.animateToPage(
|
||||
(controller.page! + 1).toInt(),
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.ease,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final localizations = AppLocalizations.of(context)!;
|
||||
|
||||
return PlatformScaffold(
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(MEDIUM_SPACE),
|
||||
padding: const EdgeInsets.symmetric(vertical: MEDIUM_SPACE),
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
const Logo(),
|
||||
const SizedBox(height: LARGE_SPACE),
|
||||
Text(
|
||||
localizations.appTitleQuestion,
|
||||
textAlign: TextAlign.center,
|
||||
style: platformThemeData(
|
||||
context,
|
||||
material: (data) => data.textTheme.headline1,
|
||||
cupertino: (data) => data.textTheme.navLargeTitleTextStyle,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: SMALL_SPACE),
|
||||
Text(
|
||||
localizations.welcomeScreenSubtitle,
|
||||
style: platformThemeData(
|
||||
context,
|
||||
material: (data) => data.textTheme.bodySmall,
|
||||
cupertino: (data) => data.textTheme.navTitleTextStyle,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: LARGE_SPACE),
|
||||
Text(
|
||||
localizations.welcomeScreenDescription,
|
||||
textAlign: TextAlign.center,
|
||||
style: platformThemeData(
|
||||
context,
|
||||
material: (data) => data.textTheme.bodyText1,
|
||||
cupertino: (data) => data.textTheme.textStyle,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: LARGE_SPACE),
|
||||
PlatformElevatedButton(
|
||||
child: IconButtonChild(
|
||||
icon: Icon(context.platformIcons.forward),
|
||||
label: Text(localizations.welcomeScreenStartButtonTitle),
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
GrantPermissionScreen.ID,
|
||||
child: PageView.builder(
|
||||
itemBuilder: (context, index) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return InitialPage(
|
||||
onNextPage: nextPage,
|
||||
);
|
||||
},
|
||||
)
|
||||
],
|
||||
case 1:
|
||||
return GuidePage(
|
||||
onNextPage: nextPage,
|
||||
description: localizations
|
||||
.welcomeScreenCreateMemoriesGuideDescription,
|
||||
picture: 'assets/images/live_photo.svg',
|
||||
);
|
||||
case 2:
|
||||
return GuidePage(
|
||||
onNextPage: nextPage,
|
||||
description:
|
||||
localizations.welcomeScreenViewMemoriesGuideDescription,
|
||||
);
|
||||
case 3:
|
||||
return const GetStartedPage();
|
||||
default:
|
||||
return const SizedBox();
|
||||
}
|
||||
},
|
||||
controller: controller,
|
||||
itemCount: 4,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
15
lib/screens/welcome_screen/crabs/logo.dart
Normal file
15
lib/screens/welcome_screen/crabs/logo.dart
Normal file
@ -0,0 +1,15 @@
|
||||
import 'package:coast/coast.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:quid_faciam_hodie/widgets/logo.dart';
|
||||
|
||||
class CrabLogo extends StatelessWidget {
|
||||
const CrabLogo({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Crab(
|
||||
tag: 'logo',
|
||||
child: Logo(),
|
||||
);
|
||||
}
|
||||
}
|
30
lib/screens/welcome_screen/crabs/next_button.dart
Normal file
30
lib/screens/welcome_screen/crabs/next_button.dart
Normal file
@ -0,0 +1,30 @@
|
||||
import 'package:coast/coast.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:quid_faciam_hodie/widgets/icon_button_child.dart';
|
||||
|
||||
class CrabNextButton extends StatelessWidget {
|
||||
final VoidCallback onPressed;
|
||||
|
||||
const CrabNextButton({
|
||||
Key? key,
|
||||
required this.onPressed,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final localizations = AppLocalizations.of(context)!;
|
||||
|
||||
return Crab(
|
||||
tag: 'next_button',
|
||||
child: PlatformElevatedButton(
|
||||
onPressed: onPressed,
|
||||
child: IconButtonChild(
|
||||
icon: Icon(context.platformIcons.forward),
|
||||
label: Text(localizations.generalContinueButtonLabel),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
52
lib/screens/welcome_screen/pages/get_started_page.dart
Normal file
52
lib/screens/welcome_screen/pages/get_started_page.dart
Normal file
@ -0,0 +1,52 @@
|
||||
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:quid_faciam_hodie/constants/spacing.dart';
|
||||
import 'package:quid_faciam_hodie/screens/grant_permission_screen.dart';
|
||||
import 'package:quid_faciam_hodie/screens/welcome_screen/crabs/logo.dart';
|
||||
import 'package:quid_faciam_hodie/utils/theme.dart';
|
||||
import 'package:quid_faciam_hodie/widgets/icon_button_child.dart';
|
||||
|
||||
class GetStartedPage extends StatelessWidget {
|
||||
const GetStartedPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final localizations = AppLocalizations.of(context)!;
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: MEDIUM_SPACE),
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
const CrabLogo(),
|
||||
const SizedBox(height: LARGE_SPACE),
|
||||
Text(
|
||||
localizations.appTitleQuestion,
|
||||
style: getTitleTextStyle(context),
|
||||
),
|
||||
const SizedBox(height: MEDIUM_SPACE),
|
||||
Text(
|
||||
localizations.welcomeScreenGetStartedLabel,
|
||||
style: getSubTitleTextStyle(context),
|
||||
),
|
||||
const SizedBox(height: MEDIUM_SPACE),
|
||||
PlatformElevatedButton(
|
||||
child: IconButtonChild(
|
||||
icon: Icon(context.platformIcons.forward),
|
||||
label: Text(localizations.welcomeScreenStartButtonTitle),
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
GrantPermissionScreen.ID,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
48
lib/screens/welcome_screen/pages/guide_page.dart
Normal file
48
lib/screens/welcome_screen/pages/guide_page.dart
Normal file
@ -0,0 +1,48 @@
|
||||
import 'package:flutter/material.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/screens/welcome_screen/photo_switching.dart';
|
||||
import 'package:quid_faciam_hodie/utils/theme.dart';
|
||||
|
||||
class GuidePage extends StatelessWidget {
|
||||
final String? picture;
|
||||
final String description;
|
||||
final VoidCallback onNextPage;
|
||||
|
||||
const GuidePage({
|
||||
Key? key,
|
||||
required this.description,
|
||||
required this.onNextPage,
|
||||
this.picture,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: MEDIUM_SPACE),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
picture == null
|
||||
? const Expanded(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(top: LARGE_SPACE),
|
||||
child: PhotoSwitching(),
|
||||
),
|
||||
)
|
||||
: SvgPicture.asset(picture!, height: 400),
|
||||
const SizedBox(height: LARGE_SPACE),
|
||||
Text(
|
||||
description,
|
||||
style: getBodyTextTextStyle(context),
|
||||
),
|
||||
const SizedBox(height: LARGE_SPACE),
|
||||
CrabNextButton(onPressed: onNextPage),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
63
lib/screens/welcome_screen/pages/initial_page.dart
Normal file
63
lib/screens/welcome_screen/pages/initial_page.dart
Normal file
@ -0,0 +1,63 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:quid_faciam_hodie/constants/spacing.dart';
|
||||
import 'package:quid_faciam_hodie/screens/welcome_screen/crabs/logo.dart';
|
||||
import 'package:quid_faciam_hodie/screens/welcome_screen/crabs/next_button.dart';
|
||||
import 'package:quid_faciam_hodie/utils/theme.dart';
|
||||
|
||||
class InitialPage extends StatefulWidget {
|
||||
final VoidCallback onNextPage;
|
||||
|
||||
const InitialPage({
|
||||
Key? key,
|
||||
required this.onNextPage,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<InitialPage> createState() => _InitialPageState();
|
||||
}
|
||||
|
||||
class _InitialPageState extends State<InitialPage> {
|
||||
late String photoURL;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final localizations = AppLocalizations.of(context)!;
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: MEDIUM_SPACE),
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
const CrabLogo(),
|
||||
const SizedBox(height: HUGE_SPACE),
|
||||
Text(
|
||||
localizations.appTitleQuestion,
|
||||
style: getTitleTextStyle(context),
|
||||
),
|
||||
const SizedBox(height: SMALL_SPACE),
|
||||
Text(
|
||||
localizations.welcomeScreenSubtitle,
|
||||
style: getSubTitleTextStyle(context),
|
||||
),
|
||||
const SizedBox(height: MEDIUM_SPACE),
|
||||
Text(
|
||||
localizations.welcomeScreenDescription,
|
||||
style: getBodyTextTextStyle(context),
|
||||
),
|
||||
const SizedBox(height: LARGE_SPACE),
|
||||
CrabNextButton(
|
||||
onPressed: widget.onNextPage,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
68
lib/screens/welcome_screen/photo_switching.dart
Normal file
68
lib/screens/welcome_screen/photo_switching.dart
Normal file
@ -0,0 +1,68 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.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/utils/loadable.dart';
|
||||
import 'package:quid_faciam_hodie/widgets/status.dart';
|
||||
|
||||
class PhotoSwitching extends StatefulWidget {
|
||||
const PhotoSwitching({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<PhotoSwitching> createState() => _PhotoSwitchingState();
|
||||
}
|
||||
|
||||
class _PhotoSwitchingState extends State<PhotoSwitching> with Loadable {
|
||||
late String photoURL;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
callWithLoading(getNextPhoto);
|
||||
}
|
||||
|
||||
Future<void> getNextPhoto() async {
|
||||
final query = WELCOME_SCREEN_PHOTOS_QUERIES[
|
||||
Random().nextInt(WELCOME_SCREEN_PHOTOS_QUERIES.length)];
|
||||
final url = await PhotoManager.getRandomPhoto(query);
|
||||
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
|
||||
setState(() {
|
||||
photoURL = url;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (isLoading) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.circular(MEDIUM_SPACE),
|
||||
child: Image.network(
|
||||
photoURL,
|
||||
loadingBuilder: (context, child, loadingProgress) {
|
||||
if (loadingProgress == null) {
|
||||
return Status(
|
||||
autoStart: true,
|
||||
onEnd: () async {
|
||||
getNextPhoto();
|
||||
},
|
||||
duration: const Duration(seconds: 3),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
return const SizedBox.expand();
|
||||
},
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -9,12 +9,20 @@ class Status extends StatefulWidget {
|
||||
final Widget child;
|
||||
final bool paused;
|
||||
final bool hideProgressBar;
|
||||
final bool autoStart;
|
||||
final bool isIndeterminate;
|
||||
final VoidCallback? onEnd;
|
||||
final Duration duration;
|
||||
|
||||
const Status({
|
||||
Key? key,
|
||||
required this.child,
|
||||
this.paused = false,
|
||||
this.hideProgressBar = false,
|
||||
this.autoStart = false,
|
||||
this.isIndeterminate = false,
|
||||
this.duration = const Duration(seconds: 5),
|
||||
this.onEnd,
|
||||
this.controller,
|
||||
}) : super(key: key);
|
||||
|
||||
@ -23,7 +31,7 @@ class Status extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _StatusState extends State<Status> with TickerProviderStateMixin {
|
||||
late final Animation<double> animation;
|
||||
Animation<double>? animation;
|
||||
AnimationController? animationController;
|
||||
|
||||
@override
|
||||
@ -48,28 +56,48 @@ class _StatusState extends State<Status> with TickerProviderStateMixin {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
if (widget.autoStart) {
|
||||
initializeAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
void initializeAnimation() {
|
||||
animationController = AnimationController(
|
||||
duration: widget.controller!.duration,
|
||||
duration: widget.controller?.duration ?? widget.duration,
|
||||
vsync: this,
|
||||
);
|
||||
)..addStatusListener((status) {
|
||||
if (status == AnimationStatus.completed) {
|
||||
widget.onEnd?.call();
|
||||
}
|
||||
});
|
||||
|
||||
animation =
|
||||
Tween<double>(begin: 0.0, end: 1.0).animate(animationController!)
|
||||
..addStatusListener((status) {
|
||||
if (status == AnimationStatus.completed) {
|
||||
widget.controller!.setDone();
|
||||
widget.controller?.setDone();
|
||||
}
|
||||
});
|
||||
|
||||
animationController!.forward();
|
||||
|
||||
widget.controller!.addListener(() {
|
||||
if (widget.controller!.isForwarding) {
|
||||
animationController!.forward();
|
||||
} else {
|
||||
animationController!.stop();
|
||||
}
|
||||
});
|
||||
if (widget.controller != null) {
|
||||
widget.controller!.addListener(() {
|
||||
if (widget.controller!.isForwarding) {
|
||||
animationController!.forward();
|
||||
} else {
|
||||
animationController!.stop();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (widget.autoStart) {
|
||||
animationController?.forward();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@ -82,8 +110,8 @@ class _StatusState extends State<Status> with TickerProviderStateMixin {
|
||||
widget.child,
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: SMALL_SPACE,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height: BAR_HEIGHT,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: SMALL_SPACE),
|
||||
@ -91,7 +119,7 @@ class _StatusState extends State<Status> with TickerProviderStateMixin {
|
||||
duration: const Duration(milliseconds: 500),
|
||||
curve: Curves.linearToEaseOut,
|
||||
opacity: widget.hideProgressBar ? 0.0 : 1.0,
|
||||
child: (widget.controller == null)
|
||||
child: (widget.isIndeterminate || animation == null)
|
||||
? ClipRRect(
|
||||
borderRadius: BorderRadius.circular(HUGE_SPACE),
|
||||
child: LinearProgressIndicator(
|
||||
@ -102,13 +130,13 @@ class _StatusState extends State<Status> with TickerProviderStateMixin {
|
||||
),
|
||||
)
|
||||
: AnimatedBuilder(
|
||||
animation: animation,
|
||||
animation: animation!,
|
||||
builder: (_, __) => ClipRRect(
|
||||
borderRadius: BorderRadius.circular(HUGE_SPACE),
|
||||
child: LinearProgressIndicator(
|
||||
value: animation.value,
|
||||
valueColor:
|
||||
const AlwaysStoppedAnimation<Color>(Colors.white),
|
||||
value: animation!.value,
|
||||
valueColor: const AlwaysStoppedAnimation<Color>(
|
||||
Colors.white),
|
||||
backgroundColor: Colors.white.withOpacity(0.1),
|
||||
),
|
||||
),
|
||||
|
@ -78,6 +78,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
coast:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: coast
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.2"
|
||||
collection:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -295,7 +302,7 @@ packages:
|
||||
source: hosted
|
||||
version: "0.15.0"
|
||||
http:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: http
|
||||
url: "https://pub.dartlang.org"
|
||||
|
@ -56,6 +56,8 @@ dependencies:
|
||||
flutter_platform_widgets: ^2.0.0
|
||||
lottie: ^1.4.1
|
||||
settings_ui: ^2.0.2
|
||||
coast: ^2.0.2
|
||||
http: ^0.13.5
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
@ -83,6 +85,7 @@ flutter:
|
||||
assets:
|
||||
- assets/
|
||||
- assets/lottie/flying-astronaut.json
|
||||
- assets/images/
|
||||
|
||||
# To add assets to your application, add an assets section, like this:
|
||||
# assets:
|
||||
|
Loading…
x
Reference in New Issue
Block a user