149 lines
3.5 KiB
Dart
149 lines
3.5 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:auto_size_text/auto_size_text.dart';
|
|
|
|
import 'package:anyway/structs/trip.dart';
|
|
import 'package:anyway/pages/current_trip.dart';
|
|
|
|
|
|
final List<String> statusTexts = [
|
|
'Parsing your preferences...',
|
|
'Finding the best places...',
|
|
'Crunching the numbers...',
|
|
'Calculating the best route...',
|
|
'Making sure you have a great time...',
|
|
];
|
|
|
|
|
|
class CurrentTripLoadingIndicator extends StatefulWidget {
|
|
final Trip trip;
|
|
const CurrentTripLoadingIndicator({
|
|
super.key,
|
|
required this.trip,
|
|
});
|
|
|
|
@override
|
|
State<CurrentTripLoadingIndicator> createState() => _CurrentTripLoadingIndicatorState();
|
|
}
|
|
|
|
|
|
class _CurrentTripLoadingIndicatorState extends State<CurrentTripLoadingIndicator> {
|
|
@override
|
|
Widget build(BuildContext context) => Stack(
|
|
fit: StackFit.expand,
|
|
children: [
|
|
// In the very center of the panel, show the greeter which tells the user that the trip is being generated
|
|
Center(child: loadingText(widget.trip)),
|
|
// As a gimmick, and a way to show that the app is still working, show a few loading dots
|
|
const Align(
|
|
alignment: Alignment.bottomCenter,
|
|
child: Padding(
|
|
padding: EdgeInsets.only(bottom: 12),
|
|
child: StatusText(),
|
|
)
|
|
)
|
|
],
|
|
);
|
|
}
|
|
|
|
// automatically cycle through the greeter texts
|
|
class StatusText extends StatefulWidget {
|
|
const StatusText({Key? key}) : super(key: key);
|
|
|
|
@override
|
|
_StatusTextState createState() => _StatusTextState();
|
|
}
|
|
|
|
class _StatusTextState extends State<StatusText> {
|
|
int statusIndex = 0;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
Future.delayed(const Duration(seconds: 5), () {
|
|
setState(() {
|
|
statusIndex = (statusIndex + 1) % statusTexts.length;
|
|
});
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return AutoSizeText(
|
|
statusTexts[statusIndex],
|
|
style: Theme.of(context).textTheme.labelSmall,
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
Widget loadingText(Trip trip) => FutureBuilder(
|
|
future: trip.cityName,
|
|
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
|
|
Widget greeter;
|
|
|
|
if (snapshot.hasData) {
|
|
greeter = AnimatedDotsText(
|
|
baseText: 'Creating your trip to ${snapshot.data}',
|
|
style: greeterStyle,
|
|
);
|
|
} else if (snapshot.hasError) {
|
|
// the exact error is shown in the central part of the trip overview. No need to show it here
|
|
greeter = Text(
|
|
'Error while loading trip.',
|
|
style: greeterStyle,
|
|
);
|
|
} else {
|
|
greeter = AnimatedDotsText(
|
|
baseText: 'Creating your trip',
|
|
style: greeterStyle,
|
|
);
|
|
}
|
|
return greeter;
|
|
}
|
|
);
|
|
|
|
class AnimatedDotsText extends StatefulWidget {
|
|
final String baseText;
|
|
final TextStyle style;
|
|
|
|
const AnimatedDotsText({
|
|
Key? key,
|
|
required this.baseText,
|
|
required this.style,
|
|
}) : super(key: key);
|
|
|
|
@override
|
|
_AnimatedDotsTextState createState() => _AnimatedDotsTextState();
|
|
}
|
|
|
|
class _AnimatedDotsTextState extends State<AnimatedDotsText> {
|
|
int dotCount = 0;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
Timer.periodic(const Duration(seconds: 1), (timer) {
|
|
if (mounted) {
|
|
setState(() {
|
|
dotCount = (dotCount + 1) % 4;
|
|
// show up to 3 dots
|
|
});
|
|
} else {
|
|
timer.cancel();
|
|
}
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
String dots = '.' * dotCount;
|
|
return Text(
|
|
'${widget.baseText}$dots',
|
|
style: widget.style,
|
|
);
|
|
}
|
|
}
|