944 lines
32 KiB
Dart
944 lines
32 KiB
Dart
import 'package:info_tren/train_info_page/train_info_animation_helpers.dart';
|
|
import 'package:info_tren/train_info_page/train_info_material_DisplayTrainStation.dart';
|
|
import 'package:info_tren/utils/stream_list.dart';
|
|
|
|
import '../models/train_data.dart';
|
|
import './train_info.dart';
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
class TrainInfoMaterial extends StatefulWidget {
|
|
final int trainNumber;
|
|
|
|
TrainInfoMaterial({@required this.trainNumber});
|
|
|
|
@override
|
|
_TrainInfoMaterialState createState() => _TrainInfoMaterialState();
|
|
}
|
|
|
|
class _TrainInfoMaterialState extends State<TrainInfoMaterial> with TrainInfoMixin {
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
title = widget.trainNumber.toString();
|
|
showTrainData = false;
|
|
requestedData = false;
|
|
}
|
|
|
|
@override
|
|
void didChangeDependencies() {
|
|
super.didChangeDependencies();
|
|
|
|
if (!requestedData) {
|
|
requestedData = true;
|
|
|
|
TrainDataWebViewAdapter.of(context).loadTrain(widget.trainNumber).then((value) {
|
|
setState(() {
|
|
lookupResult = value;
|
|
});
|
|
|
|
if (lookupResult == TrainLookupResult.NOT_FOUND) {
|
|
Future.delayed(Duration(seconds: 5), () {
|
|
Navigator.of(context).pop();
|
|
});
|
|
}
|
|
else if (lookupResult == TrainLookupResult.FOUND) {
|
|
Future.delayed(Duration(seconds: 1, milliseconds: 500), () {
|
|
setState(() {
|
|
showTrainData = true;
|
|
});
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
if (!showTrainData) {
|
|
return _TrainInfoMaterialBefore(
|
|
title: title,
|
|
lookupResult: lookupResult,
|
|
);
|
|
}
|
|
else {
|
|
return _TrainDataMaterialAfter(
|
|
title: title,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
class _TrainInfoMaterialBefore extends StatefulWidget {
|
|
final String title;
|
|
final TrainLookupResult lookupResult;
|
|
|
|
_TrainInfoMaterialBefore({@required this.title, @required this.lookupResult});
|
|
|
|
@override
|
|
_TrainInfoMaterialBeforeState createState() => _TrainInfoMaterialBeforeState();
|
|
}
|
|
|
|
class _TrainInfoMaterialBeforeState extends State<_TrainInfoMaterialBefore> {
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
centerTitle: true,
|
|
title: Text(widget.title ?? ""),
|
|
),
|
|
body: SafeArea(
|
|
bottom: false,
|
|
child: StreamBuilder<ProgressReport>(
|
|
stream: TrainDataWebViewAdapter.of(context).progressStream,
|
|
builder: (context, snapshot) {
|
|
switch (snapshot.connectionState) {
|
|
case ConnectionState.none:
|
|
return Container();
|
|
case ConnectionState.waiting:
|
|
return Center(
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: <Widget>[
|
|
CircularProgressIndicator(),
|
|
Text(
|
|
"Conectare...",
|
|
style: Theme.of(context).textTheme.title,
|
|
),
|
|
],
|
|
),
|
|
);
|
|
case ConnectionState.active:
|
|
break;
|
|
case ConnectionState.done:
|
|
Navigator.of(context).pop();
|
|
return Container();
|
|
}
|
|
|
|
return Center(
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: <Widget>[
|
|
ProgressReportDisplayEntry(
|
|
key: ValueKey(1),
|
|
completed: 1 <= snapshot.data.current,
|
|
waitingText: "Se crează WebView",
|
|
completedText: "WebView a fost creat",
|
|
),
|
|
ProgressReportDisplayEntry(
|
|
key: ValueKey(2),
|
|
completed: 2 <= snapshot.data.current,
|
|
waitingText: "Se încarcă pagina Informatica Feroviară",
|
|
completedText: "Pagina Informatica Feroviară a fost încărcată",
|
|
),
|
|
ProgressReportDisplayEntry(
|
|
key: ValueKey(3),
|
|
completed: 3 <= snapshot.data.current,
|
|
waitingText: "Se încarcă informațiile despre tren",
|
|
completedText: "Informațiile despre tren au fost încărcate",
|
|
),
|
|
if (widget.lookupResult != null)
|
|
...[
|
|
Container(height: 20,),
|
|
SizedBox(
|
|
width: double.infinity,
|
|
child: AnimatedBackground(
|
|
animationDuration: Duration(milliseconds: 250),
|
|
initialColor: Theme.of(context).scaffoldBackgroundColor,
|
|
backgroundColor:
|
|
widget.lookupResult == TrainLookupResult.FOUND
|
|
? Colors.green
|
|
: Colors.red,
|
|
child: Center(
|
|
child: Row(
|
|
children: <Widget>[
|
|
Expanded(child: Container(),),
|
|
if (widget.lookupResult == TrainLookupResult.FOUND)
|
|
Padding(
|
|
padding: const EdgeInsets.fromLTRB(8, 8, 0, 8),
|
|
child: Center(
|
|
child: CircularProgressIndicator(
|
|
strokeWidth: 2,
|
|
valueColor: AlwaysStoppedAnimation(Colors.greenAccent),
|
|
)
|
|
),
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Text(
|
|
widget.lookupResult == TrainLookupResult.FOUND
|
|
? "Trenul a fost găsit"
|
|
: widget.lookupResult == TrainLookupResult.NOT_FOUND
|
|
? "Trenul nu a fost găsit"
|
|
: "A apărut o eroare în căutarea trenului",
|
|
style: Theme.of(context).textTheme.title,
|
|
),
|
|
),
|
|
Expanded(child: Container(),),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
],
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
bool isSmallScreen(BuildContext context) => MediaQuery.of(context).size.height <= 425;
|
|
|
|
class _TrainDataMaterialAfter extends StatefulWidget {
|
|
final String title;
|
|
|
|
_TrainDataMaterialAfter({@required this.title});
|
|
|
|
@override
|
|
_TrainDataMaterialAfterState createState() => _TrainDataMaterialAfterState();
|
|
}
|
|
|
|
class _TrainDataMaterialAfterState extends State<_TrainDataMaterialAfter> {
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return FutureBuilder<OnDemandTrainData>(
|
|
future: TrainDataWebViewAdapter.of(context).trainData(onInvalidation: () {
|
|
Navigator.of(context).pop();
|
|
}),
|
|
builder: (context, snapshot) {
|
|
if (!snapshot.hasData) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
centerTitle: true,
|
|
title: Text(widget.title ?? ""),
|
|
),
|
|
body: SafeArea(
|
|
child: Center(
|
|
child: CircularProgressIndicator(),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
return Scaffold(
|
|
appBar: isSmallScreen(context) ? null : AppBar(
|
|
centerTitle: true,
|
|
title: FutureBuilder<List<String>>(
|
|
future: Future.wait([
|
|
snapshot.data.rang,
|
|
snapshot.data.trainNumber
|
|
]),
|
|
builder: (context, snapshot) {
|
|
if (snapshot.hasData) {
|
|
return Text("Informații despre ${snapshot.data[0]} ${snapshot.data[1]}");
|
|
}
|
|
else {
|
|
return Text(widget.title ?? "");
|
|
}
|
|
},
|
|
),
|
|
),
|
|
body: Column(
|
|
children: <Widget>[
|
|
if (isSmallScreen(context))
|
|
FutureBuilder<List<String>>(
|
|
future: Future.wait([
|
|
snapshot.data.rang,
|
|
snapshot.data.trainNumber,
|
|
]),
|
|
builder: (context, snapshot) {
|
|
var title = "INFO TREN";
|
|
if (snapshot.hasData) title = "INFO TREN ─ ${snapshot.data[0]} ${snapshot.data[1]}";
|
|
|
|
return SlimAppBar(
|
|
title: title,
|
|
);
|
|
}
|
|
),
|
|
Expanded(
|
|
child: SafeArea(
|
|
bottom: false,
|
|
child: CustomScrollView(
|
|
slivers: <Widget>[
|
|
SliverToBoxAdapter(
|
|
child: DisplayTrainID(trainData: snapshot.data,),
|
|
),
|
|
SliverToBoxAdapter(
|
|
child: DisplayTrainOperator(trainData: snapshot.data,),
|
|
),
|
|
SliverPadding(
|
|
padding: const EdgeInsets.only(left: 2, right: 2),
|
|
sliver: SliverToBoxAdapter(
|
|
child: DisplayTrainRoute(trainData: snapshot.data,),
|
|
),
|
|
),
|
|
SliverToBoxAdapter(
|
|
child: DisplayTrainDeparture(trainData: snapshot.data,),
|
|
),
|
|
SliverToBoxAdapter(
|
|
child: Divider(
|
|
color: Colors.white70,
|
|
height: isSmallScreen(context) ? 8 : 16,
|
|
),
|
|
),
|
|
SliverToBoxAdapter(
|
|
child: DisplayTrainLastInfo(trainData: snapshot.data,),
|
|
),
|
|
SliverToBoxAdapter(
|
|
child: IntrinsicHeight(
|
|
child: Row(
|
|
children: <Widget>[
|
|
Expanded(child: DisplayTrainNextStop(trainData: snapshot.data,)),
|
|
Expanded(child: DisplayTrainDestination(trainData: snapshot.data,)),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
SliverToBoxAdapter(
|
|
child: IntrinsicHeight(
|
|
child: Row(
|
|
children: <Widget>[
|
|
Expanded(child: DisplayTrainRouteDuration(trainData: snapshot.data,)),
|
|
Expanded(child: DisplayTrainRouteDistance(trainData: snapshot.data,)),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
SliverToBoxAdapter(
|
|
child: Divider(
|
|
color: Colors.white70,
|
|
height: isSmallScreen(context) ? 8 : 16,
|
|
),
|
|
),
|
|
DisplayTrainStations(
|
|
trainData: snapshot.data,
|
|
pageLoadFuture: TrainDataWebViewAdapter.of(context).nextLoadFuture,
|
|
),
|
|
SliverToBoxAdapter(
|
|
child: Container(
|
|
height: MediaQuery.of(context).viewPadding.bottom,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
class DisplayTrainID extends StatelessWidget {
|
|
final OnDemandTrainData trainData;
|
|
|
|
DisplayTrainID({@required this.trainData});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return FutureDisplay<List<String>>(
|
|
future: Future.wait([
|
|
trainData.rang,
|
|
trainData.trainNumber,
|
|
]),
|
|
builder: (context, list) {
|
|
return Text(
|
|
"${list[0]} ${list[1]}",
|
|
style: (isSmallScreen(context)
|
|
? Theme.of(context).textTheme.display1
|
|
: Theme.of(context).textTheme.display2).copyWith(
|
|
color: Theme.of(context).textTheme.body1.color,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
class DisplayTrainOperator extends StatelessWidget {
|
|
final OnDemandTrainData trainData;
|
|
|
|
DisplayTrainOperator({@required this.trainData});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return FutureDisplay<String>(
|
|
future: trainData.operator,
|
|
builder: (context, op) {
|
|
return Text(
|
|
op,
|
|
style: Theme.of(context).textTheme.body1.copyWith(
|
|
fontStyle: FontStyle.italic,
|
|
fontSize: isSmallScreen(context) ? 12 : 14,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
class DisplayTrainRoute extends StatelessWidget {
|
|
final OnDemandTrainData trainData;
|
|
|
|
DisplayTrainRoute({@required this.trainData});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return FutureDisplay(
|
|
future: Future.wait([trainData.route.from, trainData.route.to]),
|
|
builder: (context, routePieces) {
|
|
return Row(
|
|
children: <Widget>[
|
|
Center(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(4),
|
|
child: Text(
|
|
routePieces[0],
|
|
style: Theme.of(context).textTheme.body1.copyWith(
|
|
fontSize: 16,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
Expanded(child: Container(),),
|
|
Center(child: Text("-")),
|
|
Expanded(child: Container(),),
|
|
Center(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(4),
|
|
child: Text(
|
|
routePieces[1],
|
|
style: Theme.of(context).textTheme.body1.copyWith(
|
|
fontSize: 16,
|
|
),
|
|
textAlign: TextAlign.right,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
class DisplayTrainDeparture extends StatelessWidget {
|
|
final OnDemandTrainData trainData;
|
|
|
|
DisplayTrainDeparture({@required this.trainData});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Padding(
|
|
padding: const EdgeInsets.all(2),
|
|
child: FutureDisplay<DateTime>(
|
|
future: trainData.departureDate,
|
|
builder: (context, dataPlecare) {
|
|
return Text(
|
|
"Plecare în ${dataPlecare.day.toString().padLeft(2, '0')}.${dataPlecare.month.toString().padLeft(2, '0')}.${dataPlecare.year.toString().padLeft(4, '0')}",
|
|
style: Theme.of(context).textTheme.body1.copyWith(
|
|
fontStyle: FontStyle.italic,
|
|
fontWeight: FontWeight.w200,
|
|
fontSize: isSmallScreen(context) ? 12 : 14,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
);
|
|
},
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class DisplayTrainLastInfo extends StatelessWidget {
|
|
final OnDemandTrainData trainData;
|
|
|
|
DisplayTrainLastInfo({@required this.trainData});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Card(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(2),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: <Widget>[
|
|
Center(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(2),
|
|
child: Text(
|
|
"Ultima informație",
|
|
style: Theme.of(context).textTheme.body1.copyWith(
|
|
fontSize: isSmallScreen(context) ? 18 : 20,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
Row(
|
|
children: <Widget>[
|
|
Padding(
|
|
padding: const EdgeInsets.all(4),
|
|
child: FutureDisplay(
|
|
future: trainData.lastInfo.station,
|
|
builder: (context, station) {
|
|
return Text(
|
|
station,
|
|
style: Theme.of(context).textTheme.body1,
|
|
textAlign: TextAlign.left,
|
|
);
|
|
},
|
|
),
|
|
),
|
|
Expanded(child: Container(),),
|
|
Padding(
|
|
padding: const EdgeInsets.all(4),
|
|
child: FutureDisplay(
|
|
future: trainData.lastInfo.event,
|
|
builder: (context, event) {
|
|
return Text(
|
|
event,
|
|
style: Theme.of(context).textTheme.body1,
|
|
textAlign: TextAlign.right,
|
|
);
|
|
},
|
|
),
|
|
),
|
|
],
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.all(2),
|
|
child: Row(
|
|
children: <Widget>[
|
|
FutureDisplay<DateTime>(
|
|
future: trainData.lastInfo.dateAndTime,
|
|
builder: (context, dt) {
|
|
return Text(
|
|
"Raportat în ${dt.day.toString().padLeft(2, '0')}.${dt.month.toString().padLeft(2, '0')}.${dt.year.toString().padLeft(4, '0')}, la ${dt.hour.toString().padLeft(2, '0')}:${dt.minute.toString().padLeft(2, '0')}",
|
|
textAlign: TextAlign.center,
|
|
);
|
|
},
|
|
),
|
|
Expanded(child: Container(),),
|
|
FutureBuilder(
|
|
initialData: 0,
|
|
future: trainData.lastInfo.delay,
|
|
builder: (context, snapshot) {
|
|
if (snapshot.data == 0) {
|
|
return Container();
|
|
}
|
|
|
|
if (snapshot.data > 0) {
|
|
return Text(
|
|
"${snapshot.data} minute întârziere",
|
|
style: Theme.of(context).textTheme.body1.copyWith(
|
|
fontSize: 14,
|
|
color: Color.fromRGBO(200, 30, 15, 1),
|
|
),
|
|
);
|
|
}
|
|
else {
|
|
return Text(
|
|
"${-snapshot.data} minute mai devreme",
|
|
style: Theme.of(context).textTheme.body1.copyWith(
|
|
fontSize: 12,
|
|
color: Color.fromRGBO(15, 200, 15, 1),
|
|
),
|
|
);
|
|
}
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class DisplayTrainNextStop extends StatelessWidget {
|
|
final OnDemandTrainData trainData;
|
|
|
|
DisplayTrainNextStop({@required this.trainData});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return FutureBuilder(
|
|
future: trainData.nextStop.stationName,
|
|
builder: (context, snapshot) {
|
|
if (!snapshot.hasData) return Container(height: 0,);
|
|
|
|
return Card(
|
|
child: Center(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(2),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: <Widget>[
|
|
Padding(
|
|
padding: const EdgeInsets.all(4),
|
|
child: Text(
|
|
"Următoarea oprire",
|
|
style: Theme.of(context).textTheme.body1.copyWith(
|
|
fontSize: isSmallScreen(context) ? 18 : 20,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
),
|
|
FutureDisplay(
|
|
future: trainData.nextStop.stationName,
|
|
builder: (context, station) {
|
|
return Padding(
|
|
padding: const EdgeInsets.fromLTRB(4, 0, 4, 0),
|
|
child: Text(
|
|
station,
|
|
style: Theme.of(context).textTheme.body1.copyWith(
|
|
fontSize: isSmallScreen(context) ? 16 : 18,
|
|
fontWeight: FontWeight.w500,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
);
|
|
},
|
|
),
|
|
FutureDisplay<DateTime>(
|
|
future: trainData.nextStop.arrival,
|
|
builder: (context, arrival) {
|
|
const months = ["ian", "feb", "mar", "apr", "mai", "iun", "iul", "aug", "sep", "oct", "noi", "dec"];
|
|
|
|
return Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: <Widget>[
|
|
Text(
|
|
"în ${arrival.day} ${months[arrival.month - 1]} ${arrival.year}",
|
|
style: Theme.of(context).textTheme.body1.copyWith(
|
|
fontSize: isSmallScreen(context) ? 12 : 14,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
Text(
|
|
"la ${arrival.hour.toString().padLeft(2, '0')}:${arrival.minute.toString().padLeft(2, '0')}",
|
|
style: Theme.of(context).textTheme.body1.copyWith(
|
|
fontSize: isSmallScreen(context) ? 12 : 14,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
],
|
|
);
|
|
},
|
|
)
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|
|
class DisplayTrainDestination extends StatelessWidget {
|
|
final OnDemandTrainData trainData;
|
|
|
|
DisplayTrainDestination({@required this.trainData});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return FutureBuilder(
|
|
future: trainData.destination.stationName,
|
|
builder: (context, snapshot) {
|
|
if (!snapshot.hasData) return Container(height: 0,);
|
|
|
|
return Card(
|
|
child: Center(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(2),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: <Widget>[
|
|
Padding(
|
|
padding: const EdgeInsets.all(4),
|
|
child: Text(
|
|
"Destinația",
|
|
style: Theme.of(context).textTheme.body1.copyWith(
|
|
fontSize: isSmallScreen(context) ? 18 : 20,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
),
|
|
FutureDisplay(
|
|
future: trainData.destination.stationName,
|
|
builder: (context, station) {
|
|
return Padding(
|
|
padding: const EdgeInsets.fromLTRB(4, 0, 4, 0),
|
|
child: Text(
|
|
station,
|
|
style: Theme.of(context).textTheme.body1.copyWith(
|
|
fontSize: isSmallScreen(context) ? 16 : 18,
|
|
fontWeight: FontWeight.w500,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
);
|
|
},
|
|
),
|
|
FutureDisplay<DateTime>(
|
|
future: trainData.destination.arrival,
|
|
builder: (context, arrival) {
|
|
const months = ["ian", "feb", "mar", "apr", "mai", "iun", "iul", "aug", "sep", "oct", "noi", "dec"];
|
|
|
|
return Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: <Widget>[
|
|
Text(
|
|
"în ${arrival.day} ${months[arrival.month - 1]} ${arrival.year}",
|
|
style: Theme.of(context).textTheme.body1.copyWith(
|
|
fontSize: isSmallScreen(context) ? 12 : 14,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
Text(
|
|
"la ${arrival.hour.toString().padLeft(2, '0')}:${arrival.minute.toString().padLeft(2, '0')}",
|
|
style: Theme.of(context).textTheme.body1.copyWith(
|
|
fontSize: isSmallScreen(context) ? 12 : 14,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
],
|
|
);
|
|
},
|
|
)
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|
|
class DisplayTrainRouteDistance extends StatelessWidget {
|
|
final OnDemandTrainData trainData;
|
|
|
|
DisplayTrainRouteDistance({@required this.trainData});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Card(
|
|
child: Center(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(2),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: <Widget>[
|
|
Text(
|
|
"Distanța rutei",
|
|
style: Theme.of(context).textTheme.body1.copyWith(
|
|
fontSize: isSmallScreen(context) ? 16 : 18,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
FutureDisplay(
|
|
future: trainData.routeDistance,
|
|
builder: (context, distance) {
|
|
return Text(
|
|
"$distance km",
|
|
style: Theme.of(context).textTheme.body1.copyWith(
|
|
fontSize: isSmallScreen(context) ? 14 : 16,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class DisplayTrainRouteDuration extends StatelessWidget {
|
|
final OnDemandTrainData trainData;
|
|
|
|
DisplayTrainRouteDuration({@required this.trainData});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Card(
|
|
child: Center(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(2),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: <Widget>[
|
|
Text(
|
|
"Durata rutei",
|
|
style: Theme.of(context).textTheme.body1.copyWith(
|
|
fontSize: isSmallScreen(context) ? 16 : 18,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
),
|
|
FutureDisplay<Duration>(
|
|
future: trainData.routeDuration,
|
|
builder: (context, duration) {
|
|
var durationString = StringBuffer();
|
|
|
|
bool firstWritten = false;
|
|
|
|
if (duration.inDays > 0) {
|
|
firstWritten = true;
|
|
if (duration.inDays == 1) durationString.write("1 zi");
|
|
else durationString.write("${duration.inDays} zile");
|
|
duration -= Duration(days: duration.inDays);
|
|
}
|
|
|
|
if (duration.inHours > 0) {
|
|
if (firstWritten) {
|
|
durationString.write(", ");
|
|
}
|
|
firstWritten = true;
|
|
if (duration.inHours == 1) durationString.write("1 oră");
|
|
else durationString.write("${duration.inHours} ore");
|
|
duration -= Duration(hours: duration.inHours);
|
|
}
|
|
|
|
if (duration.inMinutes > 0) {
|
|
if (firstWritten) {
|
|
durationString.write(", ");
|
|
}
|
|
firstWritten = true;
|
|
if (duration.inMinutes == 1) durationString.write("1 minut");
|
|
else durationString.write("${duration.inMinutes} minute");
|
|
duration -= Duration(minutes: duration.inMinutes);
|
|
}
|
|
|
|
return Text(
|
|
durationString.toString(),
|
|
style: Theme.of(context).textTheme.body1.copyWith(
|
|
fontSize: isSmallScreen(context) ? 14 : 16,
|
|
),
|
|
textAlign: TextAlign.center,
|
|
);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class DisplayTrainStations extends StatelessWidget {
|
|
final OnDemandTrainData trainData;
|
|
final Future pageLoadFuture;
|
|
|
|
DisplayTrainStations({@required this.trainData, @required this.pageLoadFuture});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return StreamBuilder<List<OnDemandStation>>(
|
|
stream: listifyStream(trainData.stations(pageLoadFuture: pageLoadFuture)),
|
|
builder: (context, snapshot) {
|
|
if (!snapshot.hasData) {
|
|
return SliverToBoxAdapter(
|
|
child: Container(),
|
|
);
|
|
}
|
|
|
|
return SliverList(
|
|
delegate: SliverChildBuilderDelegate(
|
|
(context, index) {
|
|
return IndexedSemantics(
|
|
child: DisplayTrainStation(
|
|
station: snapshot.data[index],
|
|
),
|
|
index: index,
|
|
);
|
|
},
|
|
childCount: snapshot.data.length,
|
|
addSemanticIndexes: true,
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
class SlimAppBar extends StatelessWidget {
|
|
final String title;
|
|
final double size;
|
|
// final Function onBackTap;
|
|
|
|
SlimAppBar({
|
|
@required this.title,
|
|
this.size = 24,
|
|
// this.onBackTap,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return SizedBox(
|
|
width: double.infinity,
|
|
height: size,
|
|
child: Container(
|
|
color:
|
|
Theme.of(context).appBarTheme?.color ??
|
|
Theme.of(context).primaryColor,
|
|
child: InkWell(
|
|
onTap: (ModalRoute.of(context)?.canPop ?? false)
|
|
? () => Navigator.of(context).pop()
|
|
: null,
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.max,
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
children: <Widget>[
|
|
Container(
|
|
height: size,
|
|
width: size,
|
|
child: (ModalRoute.of(context)?.canPop ?? false)
|
|
? BackButtonIcon()
|
|
: null,
|
|
),
|
|
Expanded(
|
|
child: Center(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(2),
|
|
child: Text(
|
|
title,
|
|
textAlign: TextAlign.center,
|
|
style:
|
|
Theme.of(context).appBarTheme.textTheme?.caption?.copyWith(color: Theme.of(context).appBarTheme.textTheme?.body1?.color) ??
|
|
Theme.of(context).textTheme.caption.copyWith(color: Theme.of(context).textTheme.body1.color),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
Container(
|
|
height: size,
|
|
width: size,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|