Transition to Material 3, main page redesign
This commit is contained in:
parent
bf654ea837
commit
7fcbdc18bd
13 changed files with 493 additions and 349 deletions
|
@ -1,3 +1,10 @@
|
||||||
|
v2.7.6
|
||||||
|
Transitioned to Material 3.
|
||||||
|
Redesigned main page on Material.
|
||||||
|
On Android (Material), tapping station card in train information screen opens departures/arrivals board.
|
||||||
|
Added past tense to trains already arrived/departed.
|
||||||
|
Fixed download button on Android.
|
||||||
|
|
||||||
v2.7.5
|
v2.7.5
|
||||||
Added about page and in-app changelog.
|
Added about page and in-app changelog.
|
||||||
On Android, added download buttons.
|
On Android, added download buttons.
|
||||||
|
|
157
lib/components/badge.dart
Normal file
157
lib/components/badge.dart
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:info_tren/pages/train_info_page/train_info_constants.dart';
|
||||||
|
import 'package:info_tren/pages/train_info_page/view_train/train_info_material.dart';
|
||||||
|
|
||||||
|
class MaterialBadge extends StatelessWidget {
|
||||||
|
final String text;
|
||||||
|
final String caption;
|
||||||
|
final bool isNotScheduled;
|
||||||
|
final bool isOnTime;
|
||||||
|
final bool isDelayed;
|
||||||
|
|
||||||
|
MaterialBadge({
|
||||||
|
required this.text,
|
||||||
|
required this.caption,
|
||||||
|
this.isNotScheduled = false,
|
||||||
|
this.isOnTime = false,
|
||||||
|
this.isDelayed = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
Color foregroundColor = Colors.white70;
|
||||||
|
Color? backgroundColor;
|
||||||
|
|
||||||
|
if (isNotScheduled) {
|
||||||
|
foregroundColor = Colors.orange.shade300;
|
||||||
|
backgroundColor = Colors.orange.shade900.withOpacity(0.3);
|
||||||
|
}
|
||||||
|
else if (isOnTime) {
|
||||||
|
foregroundColor = Colors.green.shade300;
|
||||||
|
backgroundColor = Colors.green.shade900.withOpacity(0.3);
|
||||||
|
}
|
||||||
|
else if (isDelayed) {
|
||||||
|
foregroundColor = Colors.red.shade300;
|
||||||
|
backgroundColor = Colors.red.shade900.withOpacity(0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
border: Border.all(
|
||||||
|
width: 2,
|
||||||
|
color: foregroundColor,
|
||||||
|
),
|
||||||
|
color: backgroundColor,
|
||||||
|
),
|
||||||
|
width: isSmallScreen(context) ? 42 : 48,
|
||||||
|
height: isSmallScreen(context) ? 42 : 48,
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: <Widget>[
|
||||||
|
Expanded(
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
text,
|
||||||
|
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
||||||
|
fontSize: isSmallScreen(context) ? 16 : 20,
|
||||||
|
fontWeight: MediaQuery.of(context).boldText ? FontWeight.w400 : FontWeight.w200,
|
||||||
|
color: MediaQuery.of(context).boldText ? Colors.white70 : foregroundColor,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
caption,
|
||||||
|
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
||||||
|
fontSize: 10,
|
||||||
|
color: MediaQuery.of(context).boldText ? Colors.white70 : foregroundColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CupertinoBadge extends StatelessWidget {
|
||||||
|
final String text;
|
||||||
|
final String caption;
|
||||||
|
final bool isNotScheduled;
|
||||||
|
final bool isOnTime;
|
||||||
|
final bool isDelayed;
|
||||||
|
|
||||||
|
CupertinoBadge({
|
||||||
|
required this.text,
|
||||||
|
required this.caption,
|
||||||
|
this.isNotScheduled = false,
|
||||||
|
this.isOnTime = false,
|
||||||
|
this.isDelayed = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
Color foregroundColor = FOREGROUND_WHITE;
|
||||||
|
Color? backgroundColor;
|
||||||
|
|
||||||
|
if (isNotScheduled) {
|
||||||
|
foregroundColor = Color.fromRGBO(225, 175, 30, 1);
|
||||||
|
backgroundColor = Color.fromRGBO(80, 40, 10, 1);
|
||||||
|
}
|
||||||
|
else if (isOnTime) {
|
||||||
|
foregroundColor = Color.fromRGBO(130, 175, 65, 1);
|
||||||
|
backgroundColor = Color.fromRGBO(40, 80, 10, 1);
|
||||||
|
}
|
||||||
|
else if (isDelayed) {
|
||||||
|
foregroundColor = Color.fromRGBO(225, 75, 30, 1);
|
||||||
|
backgroundColor = Color.fromRGBO(80, 20, 10, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
border: Border.all(
|
||||||
|
width: 2,
|
||||||
|
color: foregroundColor,
|
||||||
|
),
|
||||||
|
color: backgroundColor,
|
||||||
|
// color: CupertinoColors.activeOrange,
|
||||||
|
),
|
||||||
|
width: 48,
|
||||||
|
height: 48,
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: <Widget>[
|
||||||
|
Expanded(
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
text,
|
||||||
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: MediaQuery.of(context).boldText ? FontWeight.w400 : FontWeight.w200,
|
||||||
|
color: MediaQuery.of(context).boldText ? FOREGROUND_WHITE : foregroundColor,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
caption,
|
||||||
|
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
|
||||||
|
fontSize: 12,
|
||||||
|
color: MediaQuery.of(context).boldText ? FOREGROUND_WHITE : foregroundColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -97,6 +97,7 @@ class StartPoint extends StatelessWidget {
|
||||||
primarySwatch: Colors.blue,
|
primarySwatch: Colors.blue,
|
||||||
accentColor: Colors.blue.shade700,
|
accentColor: Colors.blue.shade700,
|
||||||
),
|
),
|
||||||
|
useMaterial3: true,
|
||||||
// fontFamily: 'Atkinson Hyperlegible',
|
// fontFamily: 'Atkinson Hyperlegible',
|
||||||
),
|
),
|
||||||
routes: routesByUiDesign(UiDesign.MATERIAL),
|
routes: routesByUiDesign(UiDesign.MATERIAL),
|
||||||
|
|
|
@ -100,7 +100,10 @@ class AboutPageStateCupertino extends AboutPageState {
|
||||||
padding: EdgeInsets.all(4),
|
padding: EdgeInsets.all(4),
|
||||||
minSize: 0,
|
minSize: 0,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
launchUrl(log.apkLink!);
|
launchUrl(
|
||||||
|
log.apkLink!,
|
||||||
|
mode: LaunchMode.externalApplication,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
child: Icon(CupertinoIcons.arrow_down_circle),
|
child: Icon(CupertinoIcons.arrow_down_circle),
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:info_tren/pages/about/about_page.dart';
|
import 'package:info_tren/pages/about/about_page.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
|
@ -85,12 +87,33 @@ class AboutPageStateMaterial extends AboutPageState {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (AboutPageState.DOWNLOAD == 'apk' && log.apkLink != null)
|
if (AboutPageState.DOWNLOAD == 'apk' && log.apkLink != null)
|
||||||
IconButton(
|
GestureDetector(
|
||||||
onPressed: () {
|
onSecondaryTap: () {
|
||||||
launchUrl(log.apkLink!);
|
Clipboard.setData(ClipboardData(text: log.apkLink!.toString()));
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
||||||
|
content: Text('Link copied to clipboard'),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
onLongPress: () {
|
||||||
|
Clipboard.setData(ClipboardData(text: log.apkLink!.toString()));
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
||||||
|
content: Text('Link copied to clipboard'),
|
||||||
|
));
|
||||||
|
},
|
||||||
|
onTap: () {
|
||||||
|
launchUrl(
|
||||||
|
log.apkLink!,
|
||||||
|
mode: LaunchMode.externalApplication,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
icon: Icon(Icons.download),
|
behavior: HitTestBehavior.translucent,
|
||||||
tooltip: 'Download APK',
|
child: Tooltip(
|
||||||
|
message: 'Download APK',
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(4),
|
||||||
|
child: Icon(Icons.download),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
@ -43,18 +43,21 @@ abstract class MainPageShared extends StatelessWidget {
|
||||||
List<MainPageAction> get options => [
|
List<MainPageAction> get options => [
|
||||||
MainPageAction(
|
MainPageAction(
|
||||||
name: 'Informații despre tren',
|
name: 'Informații despre tren',
|
||||||
|
description: 'Află informații despre parcursul unui anumit tren',
|
||||||
action: (context) {
|
action: (context) {
|
||||||
onTrainInfoPageInvoke(context);
|
onTrainInfoPageInvoke(context);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
MainPageAction(
|
MainPageAction(
|
||||||
name: 'Tabelă plecari/sosiri',
|
name: 'Tabelă plecari/sosiri',
|
||||||
|
description: 'Vezi trenurile care pleacă și sosesc dintr-o gară',
|
||||||
action: (context) {
|
action: (context) {
|
||||||
onStationBoardPageInvoke(context);
|
onStationBoardPageInvoke(context);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
MainPageAction(
|
MainPageAction(
|
||||||
name: 'Planificare rută',
|
name: 'Planificare rută',
|
||||||
|
description: 'Găsește trenurile disponibile pentru călătoria între două gări',
|
||||||
// TODO: Implement route planning
|
// TODO: Implement route planning
|
||||||
action: null,
|
action: null,
|
||||||
),
|
),
|
||||||
|
@ -75,7 +78,8 @@ abstract class MainPageShared extends StatelessWidget {
|
||||||
|
|
||||||
class MainPageAction {
|
class MainPageAction {
|
||||||
final String name;
|
final String name;
|
||||||
|
final String? description;
|
||||||
final void Function(BuildContext context)? action;
|
final void Function(BuildContext context)? action;
|
||||||
|
|
||||||
MainPageAction({required this.name, this.action});
|
MainPageAction({required this.name, this.action, this.description});
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,12 +26,29 @@ class MainPageMaterial extends MainPageShared {
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: options.map((option) => ElevatedButton(
|
children: options.map((option) => Card(
|
||||||
child: Text(
|
color: option.action != null ? Theme.of(context).colorScheme.secondaryContainer : null,
|
||||||
option.name,
|
child: InkWell(
|
||||||
style: Theme.of(context).textTheme.button?.copyWith(fontSize: 18),
|
onTap: option.action != null ? () => option.action!(context) : null,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Text(
|
||||||
|
option.name,
|
||||||
|
style: Theme.of(context).textTheme.headline4?.copyWith(
|
||||||
|
color: Theme.of(context).colorScheme.onSecondaryContainer,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Text(option.description!),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
onPressed: option.action != null ? () => option.action!(context) : null,
|
|
||||||
)).map((w) => Padding(
|
)).map((w) => Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(4, 2, 4, 2),
|
padding: const EdgeInsets.fromLTRB(4, 2, 4, 2),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
|
|
|
@ -33,7 +33,9 @@ abstract class ViewStationPageState extends State<ViewStationPage> {
|
||||||
static const departures = 'Pleacări';
|
static const departures = 'Pleacări';
|
||||||
static const loadingText = 'Se încarcă...';
|
static const loadingText = 'Se încarcă...';
|
||||||
static const arrivesFrom = 'Sosește de la';
|
static const arrivesFrom = 'Sosește de la';
|
||||||
|
static const arrivedFrom = 'A sosit de la';
|
||||||
static const departsTo = 'Pleacă către';
|
static const departsTo = 'Pleacă către';
|
||||||
|
static const departedTo = 'A plecat către';
|
||||||
|
|
||||||
ViewStationPageTab tab = ViewStationPageTab.departures;
|
ViewStationPageTab tab = ViewStationPageTab.departures;
|
||||||
late String stationName;
|
late String stationName;
|
||||||
|
|
|
@ -13,19 +13,23 @@ class ViewStationPageStateMaterial extends ViewStationPageState {
|
||||||
title: Text(snapshot.hasData ? snapshot.data!.stationName : stationName),
|
title: Text(snapshot.hasData ? snapshot.data!.stationName : stationName),
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
),
|
),
|
||||||
body: snapshot.state == RefreshFutureBuilderState.waiting ? Loading(text: ViewStationPageState.loadingText, uiDesign: widget.uiDesign,) : CustomScrollView(
|
body: snapshot.state == RefreshFutureBuilderState.waiting
|
||||||
slivers: [
|
? Loading(text: ViewStationPageState.loadingText, uiDesign: widget.uiDesign,)
|
||||||
SliverToBoxAdapter(child: SafeArea(child: Container(), left: false, bottom: false, right: false,),),
|
: snapshot.state == RefreshFutureBuilderState.error
|
||||||
SliverList(
|
? Container()
|
||||||
delegate: SliverChildBuilderDelegate(
|
: CustomScrollView(
|
||||||
(context, index) {
|
slivers: [
|
||||||
return tab == ViewStationPageTab.arrivals ? buildStationArrivalItem(context, snapshot.data!.arrivals![index]) : buildStationDepartureItem(context, snapshot.data!.departures![index]);
|
SliverToBoxAdapter(child: SafeArea(child: Container(), left: false, bottom: false, right: false,),),
|
||||||
},
|
SliverList(
|
||||||
childCount: tab == ViewStationPageTab.arrivals ? snapshot.data!.arrivals?.length ?? 0 : snapshot.data!.departures?.length ?? 0,
|
delegate: SliverChildBuilderDelegate(
|
||||||
|
(context, index) {
|
||||||
|
return tab == ViewStationPageTab.arrivals ? buildStationArrivalItem(context, snapshot.data!.arrivals![index]) : buildStationDepartureItem(context, snapshot.data!.departures![index]);
|
||||||
|
},
|
||||||
|
childCount: tab == ViewStationPageTab.arrivals ? snapshot.data!.arrivals?.length ?? 0 : snapshot.data!.departures?.length ?? 0,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
|
||||||
bottomNavigationBar: snapshot.hasData ? BottomNavigationBar(
|
bottomNavigationBar: snapshot.hasData ? BottomNavigationBar(
|
||||||
items: [
|
items: [
|
||||||
BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
|
@ -64,7 +68,7 @@ class ViewStationPageStateMaterial extends ViewStationPageState {
|
||||||
subtitle: Text.rich(
|
subtitle: Text.rich(
|
||||||
TextSpan(
|
TextSpan(
|
||||||
children: [
|
children: [
|
||||||
TextSpan(text: ViewStationPageState.arrivesFrom),
|
TextSpan(text: item.time.compareTo(DateTime.now()) < 0 ? ViewStationPageState.arrivedFrom : ViewStationPageState.arrivesFrom),
|
||||||
TextSpan(text: ' '),
|
TextSpan(text: ' '),
|
||||||
TextSpan(text: item.train.origin),
|
TextSpan(text: item.train.origin),
|
||||||
],
|
],
|
||||||
|
@ -95,7 +99,7 @@ class ViewStationPageStateMaterial extends ViewStationPageState {
|
||||||
subtitle: Text.rich(
|
subtitle: Text.rich(
|
||||||
TextSpan(
|
TextSpan(
|
||||||
children: [
|
children: [
|
||||||
TextSpan(text: ViewStationPageState.departsTo),
|
TextSpan(text: item.time.compareTo(DateTime.now()) < 0 ? ViewStationPageState.departedTo : ViewStationPageState.departsTo),
|
||||||
TextSpan(text: ' '),
|
TextSpan(text: ' '),
|
||||||
TextSpan(text: item.train.destination),
|
TextSpan(text: item.train.destination),
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:info_tren/models/train_data.dart';
|
import 'package:info_tren/models/train_data.dart';
|
||||||
import 'package:info_tren/pages/train_info_page/train_info_constants.dart';
|
import 'package:info_tren/components/badge.dart';
|
||||||
|
|
||||||
class DisplayTrainStation extends StatelessWidget {
|
class DisplayTrainStation extends StatelessWidget {
|
||||||
final Station station;
|
final Station station;
|
||||||
|
@ -47,7 +47,7 @@ class DisplayTrainStation extends StatelessWidget {
|
||||||
final isOnTime = delay <= 0 && real == true;
|
final isOnTime = delay <= 0 && real == true;
|
||||||
final isNotScheduled = false;
|
final isNotScheduled = false;
|
||||||
|
|
||||||
return Badge(
|
return CupertinoBadge(
|
||||||
text: station.km.toString(),
|
text: station.km.toString(),
|
||||||
caption: 'km',
|
caption: 'km',
|
||||||
isNotScheduled: isNotScheduled,
|
isNotScheduled: isNotScheduled,
|
||||||
|
@ -65,7 +65,7 @@ class DisplayTrainStation extends StatelessWidget {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
child: Align(
|
child: Align(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: station.platform == null ? Container() : Badge(text: station.platform!, caption: 'linia'),
|
child: station.platform == null ? Container() : CupertinoBadge(text: station.platform!, caption: 'linia'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -81,83 +81,6 @@ class DisplayTrainStation extends StatelessWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Badge extends StatelessWidget {
|
|
||||||
final String text;
|
|
||||||
final String caption;
|
|
||||||
final bool isNotScheduled;
|
|
||||||
final bool isOnTime;
|
|
||||||
final bool isDelayed;
|
|
||||||
|
|
||||||
Badge({
|
|
||||||
required this.text,
|
|
||||||
required this.caption,
|
|
||||||
this.isNotScheduled = false,
|
|
||||||
this.isOnTime = false,
|
|
||||||
this.isDelayed = false,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
Color foregroundColor = FOREGROUND_WHITE;
|
|
||||||
Color? backgroundColor;
|
|
||||||
|
|
||||||
if (isNotScheduled) {
|
|
||||||
foregroundColor = Color.fromRGBO(225, 175, 30, 1);
|
|
||||||
backgroundColor = Color.fromRGBO(80, 40, 10, 1);
|
|
||||||
}
|
|
||||||
else if (isOnTime) {
|
|
||||||
foregroundColor = Color.fromRGBO(130, 175, 65, 1);
|
|
||||||
backgroundColor = Color.fromRGBO(40, 80, 10, 1);
|
|
||||||
}
|
|
||||||
else if (isDelayed) {
|
|
||||||
foregroundColor = Color.fromRGBO(225, 75, 30, 1);
|
|
||||||
backgroundColor = Color.fromRGBO(80, 20, 10, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.all(8),
|
|
||||||
child: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
border: Border.all(
|
|
||||||
width: 2,
|
|
||||||
color: foregroundColor,
|
|
||||||
),
|
|
||||||
color: backgroundColor,
|
|
||||||
// color: CupertinoColors.activeOrange,
|
|
||||||
),
|
|
||||||
width: 48,
|
|
||||||
height: 48,
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: <Widget>[
|
|
||||||
Expanded(
|
|
||||||
child: Center(
|
|
||||||
child: Text(
|
|
||||||
text,
|
|
||||||
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: MediaQuery.of(context).boldText ? FontWeight.w400 : FontWeight.w200,
|
|
||||||
color: MediaQuery.of(context).boldText ? FOREGROUND_WHITE : foregroundColor,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
caption,
|
|
||||||
style: CupertinoTheme.of(context).textTheme.textStyle.copyWith(
|
|
||||||
fontSize: 12,
|
|
||||||
color: MediaQuery.of(context).boldText ? FOREGROUND_WHITE : foregroundColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Title extends StatelessWidget {
|
class Title extends StatelessWidget {
|
||||||
final Station station;
|
final Station station;
|
||||||
|
|
||||||
|
|
|
@ -3,18 +3,24 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:info_tren/components/slim_app_bar.dart';
|
import 'package:info_tren/components/slim_app_bar.dart';
|
||||||
import 'package:info_tren/models/train_data.dart' hide State;
|
import 'package:info_tren/models/train_data.dart' hide State;
|
||||||
import 'package:info_tren/models/ui_design.dart';
|
import 'package:info_tren/models/ui_design.dart';
|
||||||
|
import 'package:info_tren/pages/station_arrdep_page/view_station/view_station.dart';
|
||||||
import 'package:info_tren/pages/train_info_page/view_train/train_info.dart';
|
import 'package:info_tren/pages/train_info_page/view_train/train_info.dart';
|
||||||
import 'package:info_tren/pages/train_info_page/view_train/train_info_material_DisplayTrainStation.dart';
|
import 'package:info_tren/pages/train_info_page/view_train/train_info_material_DisplayTrainStation.dart';
|
||||||
import 'package:info_tren/utils/state_to_string.dart';
|
import 'package:info_tren/utils/state_to_string.dart';
|
||||||
|
|
||||||
class TrainInfoLoadingMaterial extends TrainInfoLoading {
|
class TrainInfoLoadingMaterial extends TrainInfoLoading {
|
||||||
TrainInfoLoadingMaterial({required String title, String? loadingText}) : super(title: title, loadingText: loadingText, uiDesign: UiDesign.MATERIAL);
|
TrainInfoLoadingMaterial({required String title, String? loadingText})
|
||||||
|
: super(
|
||||||
|
title: title,
|
||||||
|
loadingText: loadingText,
|
||||||
|
uiDesign: UiDesign.MATERIAL);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(title),
|
title: Text(title),
|
||||||
|
centerTitle: true,
|
||||||
),
|
),
|
||||||
body: Center(
|
body: Center(
|
||||||
child: loadingWidget,
|
child: loadingWidget,
|
||||||
|
@ -25,10 +31,14 @@ class TrainInfoLoadingMaterial extends TrainInfoLoading {
|
||||||
|
|
||||||
class TrainInfoErrorMaterial extends TrainInfoError {
|
class TrainInfoErrorMaterial extends TrainInfoError {
|
||||||
TrainInfoErrorMaterial({
|
TrainInfoErrorMaterial({
|
||||||
required Object error,
|
required Object error,
|
||||||
required String title,
|
required String title,
|
||||||
Future Function()? refresh,
|
Future Function()? refresh,
|
||||||
}) : super(error: error, title: title, refresh: refresh,);
|
}) : super(
|
||||||
|
error: error,
|
||||||
|
title: title,
|
||||||
|
refresh: refresh,
|
||||||
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -56,24 +66,32 @@ class TrainInfoErrorMaterial extends TrainInfoError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isSmallScreen(BuildContext context) => MediaQuery.of(context).size.height <= 425;
|
bool isSmallScreen(BuildContext context) =>
|
||||||
|
MediaQuery.of(context).size.height <= 425;
|
||||||
|
|
||||||
class TrainInfoMaterial extends StatelessWidget {
|
class TrainInfoMaterial extends StatelessWidget {
|
||||||
final TrainData trainData;
|
final TrainData trainData;
|
||||||
final Future Function()? refresh;
|
final Future Function()? refresh;
|
||||||
final void Function()? onViewYesterdayTrain;
|
final void Function()? onViewYesterdayTrain;
|
||||||
|
|
||||||
TrainInfoMaterial({required this.trainData, this.refresh, this.onViewYesterdayTrain,});
|
TrainInfoMaterial({
|
||||||
|
required this.trainData,
|
||||||
|
this.refresh,
|
||||||
|
this.onViewYesterdayTrain,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Builder(
|
return Builder(
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: isSmallScreen(context) ? null : AppBar(
|
appBar: isSmallScreen(context)
|
||||||
centerTitle: true,
|
? null
|
||||||
title: Text("Informații despre ${trainData.rank} ${trainData.number}"),
|
: AppBar(
|
||||||
),
|
centerTitle: true,
|
||||||
|
title: Text(
|
||||||
|
"Informații despre ${trainData.rank} ${trainData.number}"),
|
||||||
|
),
|
||||||
body: Column(
|
body: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
if (isSmallScreen(context))
|
if (isSmallScreen(context))
|
||||||
|
@ -82,8 +100,8 @@ class TrainInfoMaterial extends StatelessWidget {
|
||||||
left: false,
|
left: false,
|
||||||
right: false,
|
right: false,
|
||||||
child: SlimAppBar(
|
child: SlimAppBar(
|
||||||
title: 'INFO TREN - ${trainData.rank} ${trainData.number}'
|
title:
|
||||||
),
|
'INFO TREN - ${trainData.rank} ${trainData.number}'),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: SafeArea(
|
child: SafeArea(
|
||||||
|
@ -94,19 +112,27 @@ class TrainInfoMaterial extends StatelessWidget {
|
||||||
child: CustomScrollView(
|
child: CustomScrollView(
|
||||||
slivers: <Widget>[
|
slivers: <Widget>[
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: DisplayTrainID(trainData: trainData,),
|
child: DisplayTrainID(
|
||||||
|
trainData: trainData,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: DisplayTrainOperator(trainData: trainData,),
|
child: DisplayTrainOperator(
|
||||||
|
trainData: trainData,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SliverPadding(
|
SliverPadding(
|
||||||
padding: const EdgeInsets.only(left: 2, right: 2),
|
padding: const EdgeInsets.only(left: 2, right: 2),
|
||||||
sliver: SliverToBoxAdapter(
|
sliver: SliverToBoxAdapter(
|
||||||
child: DisplayTrainRoute(trainData: trainData,),
|
child: DisplayTrainRoute(
|
||||||
|
trainData: trainData,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: DisplayTrainDeparture(trainData: trainData,),
|
child: DisplayTrainDeparture(
|
||||||
|
trainData: trainData,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
// SliverToBoxAdapter(
|
// SliverToBoxAdapter(
|
||||||
// child: Divider(
|
// child: Divider(
|
||||||
|
@ -115,7 +141,9 @@ class TrainInfoMaterial extends StatelessWidget {
|
||||||
// ),
|
// ),
|
||||||
// ),
|
// ),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: DisplayTrainLastInfo(trainData: trainData,),
|
child: DisplayTrainLastInfo(
|
||||||
|
trainData: trainData,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: IntrinsicHeight(
|
child: IntrinsicHeight(
|
||||||
|
@ -123,8 +151,15 @@ class TrainInfoMaterial extends StatelessWidget {
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
// Expanded(child: DisplayTrainNextStop(trainData: trainData,)),
|
// Expanded(child: DisplayTrainNextStop(trainData: trainData,)),
|
||||||
// Expanded(child: DisplayTrainDestination(trainData: trainData,)),
|
// Expanded(child: DisplayTrainDestination(trainData: trainData,)),
|
||||||
Expanded(child: DisplayTrainRouteDuration(trainData: trainData,)),
|
Expanded(
|
||||||
Expanded(child: DisplayTrainRouteDistance(trainData: trainData,),),
|
child: DisplayTrainRouteDuration(
|
||||||
|
trainData: trainData,
|
||||||
|
)),
|
||||||
|
Expanded(
|
||||||
|
child: DisplayTrainRouteDistance(
|
||||||
|
trainData: trainData,
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -146,9 +181,13 @@ class TrainInfoMaterial extends StatelessWidget {
|
||||||
height: isSmallScreen(context) ? 8 : 16,
|
height: isSmallScreen(context) ? 8 : 16,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (onViewYesterdayTrain != null && trainData.stations.first.departure!.scheduleTime.compareTo(DateTime.now()) > 0) ...[
|
if (onViewYesterdayTrain != null &&
|
||||||
|
trainData.stations.first.departure!.scheduleTime
|
||||||
|
.compareTo(DateTime.now()) >
|
||||||
|
0) ...[
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: DisplayTrainYesterdayWarningMaterial(onViewYesterdayTrain!),
|
child: DisplayTrainYesterdayWarningMaterial(
|
||||||
|
onViewYesterdayTrain!),
|
||||||
),
|
),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: Divider(
|
child: Divider(
|
||||||
|
@ -191,19 +230,24 @@ class DisplayTrainID extends StatelessWidget {
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: trainData.rank,
|
text: trainData.rank,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: trainData.rank.startsWith('IR') ? Color.fromARGB(255, 255, 0, 0) : null,
|
color: trainData.rank.startsWith('IR')
|
||||||
|
? Color.fromARGB(255, 255, 0, 0)
|
||||||
|
: null,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
TextSpan(text: ' '),
|
TextSpan(text: ' '),
|
||||||
TextSpan(text: trainData.number,),
|
TextSpan(
|
||||||
|
text: trainData.number,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
style: (isSmallScreen(context)
|
style: (isSmallScreen(context)
|
||||||
? Theme.of(context).textTheme.headline4
|
? Theme.of(context).textTheme.headline4
|
||||||
: Theme.of(context).textTheme.headline3)?.copyWith(
|
: Theme.of(context).textTheme.headline3)
|
||||||
color: Theme.of(context).textTheme.bodyText2?.color,
|
?.copyWith(
|
||||||
fontWeight: FontWeight.bold,
|
color: Theme.of(context).textTheme.bodyText2?.color,
|
||||||
),
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -219,9 +263,9 @@ class DisplayTrainOperator extends StatelessWidget {
|
||||||
return Text(
|
return Text(
|
||||||
trainData.operator,
|
trainData.operator,
|
||||||
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
||||||
fontStyle: FontStyle.italic,
|
fontStyle: FontStyle.italic,
|
||||||
fontSize: isSmallScreen(context) ? 12 : 14,
|
fontSize: isSmallScreen(context) ? 12 : 14,
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -243,8 +287,8 @@ class DisplayTrainRoute extends StatelessWidget {
|
||||||
child: Text(
|
child: Text(
|
||||||
trainData.route.from,
|
trainData.route.from,
|
||||||
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -257,8 +301,8 @@ class DisplayTrainRoute extends StatelessWidget {
|
||||||
child: Text(
|
child: Text(
|
||||||
trainData.route.to,
|
trainData.route.to,
|
||||||
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.right,
|
textAlign: TextAlign.right,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -282,10 +326,10 @@ class DisplayTrainDeparture extends StatelessWidget {
|
||||||
// "Plecare în ${dataPlecare.day.toString().padLeft(2, '0')}.${dataPlecare.month.toString().padLeft(2, '0')}.${dataPlecare.year.toString().padLeft(4, '0')}",
|
// "Plecare în ${dataPlecare.day.toString().padLeft(2, '0')}.${dataPlecare.month.toString().padLeft(2, '0')}.${dataPlecare.year.toString().padLeft(4, '0')}",
|
||||||
"Plecare în ${trainData.date}",
|
"Plecare în ${trainData.date}",
|
||||||
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
||||||
fontStyle: FontStyle.italic,
|
fontStyle: FontStyle.italic,
|
||||||
fontWeight: FontWeight.w200,
|
fontWeight: FontWeight.w200,
|
||||||
fontSize: isSmallScreen(context) ? 14 : 16,
|
fontSize: isSmallScreen(context) ? 14 : 16,
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -315,9 +359,9 @@ class DisplayTrainLastInfo extends StatelessWidget {
|
||||||
child: Text(
|
child: Text(
|
||||||
"Ultima informație",
|
"Ultima informație",
|
||||||
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
||||||
fontSize: isSmallScreen(context) ? 20 : 22,
|
fontSize: isSmallScreen(context) ? 20 : 22,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -328,19 +372,21 @@ class DisplayTrainLastInfo extends StatelessWidget {
|
||||||
child: Text(
|
child: Text(
|
||||||
trainData.status!.station,
|
trainData.status!.station,
|
||||||
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
||||||
fontSize: isSmallScreen(context) ? 16 : 18,
|
fontSize: isSmallScreen(context) ? 16 : 18,
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.left,
|
textAlign: TextAlign.left,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(child: Container(),),
|
Expanded(
|
||||||
|
child: Container(),
|
||||||
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(4),
|
padding: const EdgeInsets.all(4),
|
||||||
child: Text(
|
child: Text(
|
||||||
stateToString(trainData.status!.state),
|
stateToString(trainData.status!.state),
|
||||||
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
||||||
fontSize: isSmallScreen(context) ? 16 : 18,
|
fontSize: isSmallScreen(context) ? 16 : 18,
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.right,
|
textAlign: TextAlign.right,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -359,7 +405,9 @@ class DisplayTrainLastInfo extends StatelessWidget {
|
||||||
// );
|
// );
|
||||||
// },
|
// },
|
||||||
// ),
|
// ),
|
||||||
Expanded(child: Container(),),
|
Expanded(
|
||||||
|
child: Container(),
|
||||||
|
),
|
||||||
Builder(
|
Builder(
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
final data = trainData.status!.delay;
|
final data = trainData.status!.delay;
|
||||||
|
@ -370,19 +418,20 @@ class DisplayTrainLastInfo extends StatelessWidget {
|
||||||
if (data > 0) {
|
if (data > 0) {
|
||||||
return Text(
|
return Text(
|
||||||
"$data ${data == 1 ? 'minut' : 'minute'} întârziere",
|
"$data ${data == 1 ? 'minut' : 'minute'} întârziere",
|
||||||
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
style:
|
||||||
fontSize: isSmallScreen(context) ? 14 : 16,
|
Theme.of(context).textTheme.bodyText2?.copyWith(
|
||||||
color: Colors.red.shade300,
|
fontSize: isSmallScreen(context) ? 14 : 16,
|
||||||
),
|
color: Colors.red.shade300,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return Text(
|
return Text(
|
||||||
"${-data} ${data == -1 ? 'minut' : 'minute'} mai devreme",
|
"${-data} ${data == -1 ? 'minut' : 'minute'} mai devreme",
|
||||||
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
style:
|
||||||
fontSize: isSmallScreen(context) ? 14 : 16,
|
Theme.of(context).textTheme.bodyText2?.copyWith(
|
||||||
color: Colors.green.shade300,
|
fontSize: isSmallScreen(context) ? 14 : 16,
|
||||||
),
|
color: Colors.green.shade300,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -408,7 +457,7 @@ class DisplayTrainLastInfo extends StatelessWidget {
|
||||||
// future: trainData.nextStop.stationName,
|
// future: trainData.nextStop.stationName,
|
||||||
// builder: (context, snapshot) {
|
// builder: (context, snapshot) {
|
||||||
// if (!snapshot.hasData) return Container(height: 0,);
|
// if (!snapshot.hasData) return Container(height: 0,);
|
||||||
//
|
//
|
||||||
// return Card(
|
// return Card(
|
||||||
// child: Center(
|
// child: Center(
|
||||||
// child: Padding(
|
// child: Padding(
|
||||||
|
@ -500,9 +549,9 @@ class DisplayTrainDestination extends StatelessWidget {
|
||||||
child: Text(
|
child: Text(
|
||||||
"Destinația",
|
"Destinația",
|
||||||
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
||||||
fontSize: isSmallScreen(context) ? 20 : 22,
|
fontSize: isSmallScreen(context) ? 20 : 22,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -511,18 +560,21 @@ class DisplayTrainDestination extends StatelessWidget {
|
||||||
child: Text(
|
child: Text(
|
||||||
destination.name,
|
destination.name,
|
||||||
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
||||||
fontSize: isSmallScreen(context) ? 18 : 20,
|
fontSize: isSmallScreen(context) ? 18 : 20,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Builder(
|
Builder(
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
final arrival = destination.arrival!.scheduleTime.toLocal();
|
final arrival = destination.arrival!.scheduleTime.toLocal();
|
||||||
final delay = trainData.stations.last.arrival!.status?.delay ?? 0;
|
final delay =
|
||||||
final arrivalWithDelay = arrival.add(Duration(minutes: delay));
|
trainData.stations.last.arrival!.status?.delay ?? 0;
|
||||||
final arrivalWithDelayString = '${arrivalWithDelay.hour}:${arrivalWithDelay.minute.toString().padLeft(2, "0")}';
|
final arrivalWithDelay =
|
||||||
|
arrival.add(Duration(minutes: delay));
|
||||||
|
final arrivalWithDelayString =
|
||||||
|
'${arrivalWithDelay.hour}:${arrivalWithDelay.minute.toString().padLeft(2, "0")}';
|
||||||
// const months = ["ian", "feb", "mar", "apr", "mai", "iun", "iul", "aug", "sep", "oct", "noi", "dec"];
|
// const months = ["ian", "feb", "mar", "apr", "mai", "iun", "iul", "aug", "sep", "oct", "noi", "dec"];
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
|
@ -542,25 +594,30 @@ class DisplayTrainDestination extends StatelessWidget {
|
||||||
children: [
|
children: [
|
||||||
TextSpan(text: ' '),
|
TextSpan(text: ' '),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: '${arrival.hour.toString().padLeft(2, '0')}:${arrival.minute.toString().padLeft(2, '0')}',
|
text:
|
||||||
style: delay == 0 ? null : TextStyle(
|
'${arrival.hour.toString().padLeft(2, '0')}:${arrival.minute.toString().padLeft(2, '0')}',
|
||||||
decoration: TextDecoration.lineThrough,
|
style: delay == 0
|
||||||
),
|
? null
|
||||||
|
: TextStyle(
|
||||||
|
decoration: TextDecoration.lineThrough,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
if (delay != 0) ...[
|
if (delay != 0) ...[
|
||||||
TextSpan(text: ' '),
|
TextSpan(text: ' '),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: '$arrivalWithDelayString',
|
text: '$arrivalWithDelayString',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: delay > 0 ? Colors.red.shade300 : Colors.green.shade300,
|
color: delay > 0
|
||||||
|
? Colors.red.shade300
|
||||||
|
: Colors.green.shade300,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
||||||
fontSize: isSmallScreen(context) ? 14 : 16,
|
fontSize: isSmallScreen(context) ? 14 : 16,
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -592,16 +649,16 @@ class DisplayTrainRouteDistance extends StatelessWidget {
|
||||||
Text(
|
Text(
|
||||||
"Distanța rutei",
|
"Distanța rutei",
|
||||||
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
||||||
fontSize: isSmallScreen(context) ? 20 : 22,
|
fontSize: isSmallScreen(context) ? 20 : 22,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"${trainData.stations.last.km} km",
|
"${trainData.stations.last.km} km",
|
||||||
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
||||||
fontSize: isSmallScreen(context) ? 18 : 20,
|
fontSize: isSmallScreen(context) ? 18 : 20,
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -629,22 +686,26 @@ class DisplayTrainRouteDuration extends StatelessWidget {
|
||||||
Text(
|
Text(
|
||||||
"Durata rutei",
|
"Durata rutei",
|
||||||
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
||||||
fontSize: isSmallScreen(context) ? 20 : 22,
|
fontSize: isSmallScreen(context) ? 20 : 22,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
Builder(
|
Builder(
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
var duration = trainData.stations.last.arrival!.scheduleTime.difference(trainData.stations.first.departure!.scheduleTime);
|
var duration = trainData.stations.last.arrival!.scheduleTime
|
||||||
|
.difference(
|
||||||
|
trainData.stations.first.departure!.scheduleTime);
|
||||||
var durationString = StringBuffer();
|
var durationString = StringBuffer();
|
||||||
|
|
||||||
bool firstWritten = false;
|
bool firstWritten = false;
|
||||||
|
|
||||||
if (duration.inDays > 0) {
|
if (duration.inDays > 0) {
|
||||||
firstWritten = true;
|
firstWritten = true;
|
||||||
if (duration.inDays == 1) durationString.write("1 zi");
|
if (duration.inDays == 1)
|
||||||
else durationString.write("${duration.inDays} zile");
|
durationString.write("1 zi");
|
||||||
|
else
|
||||||
|
durationString.write("${duration.inDays} zile");
|
||||||
duration -= Duration(days: duration.inDays);
|
duration -= Duration(days: duration.inDays);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -653,8 +714,10 @@ class DisplayTrainRouteDuration extends StatelessWidget {
|
||||||
durationString.write(", ");
|
durationString.write(", ");
|
||||||
}
|
}
|
||||||
firstWritten = true;
|
firstWritten = true;
|
||||||
if (duration.inHours == 1) durationString.write("1 oră");
|
if (duration.inHours == 1)
|
||||||
else durationString.write("${duration.inHours} ore");
|
durationString.write("1 oră");
|
||||||
|
else
|
||||||
|
durationString.write("${duration.inHours} ore");
|
||||||
duration -= Duration(hours: duration.inHours);
|
duration -= Duration(hours: duration.inHours);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -663,16 +726,18 @@ class DisplayTrainRouteDuration extends StatelessWidget {
|
||||||
durationString.write(", ");
|
durationString.write(", ");
|
||||||
}
|
}
|
||||||
firstWritten = true;
|
firstWritten = true;
|
||||||
if (duration.inMinutes == 1) durationString.write("1 minut");
|
if (duration.inMinutes == 1)
|
||||||
else durationString.write("${duration.inMinutes} minute");
|
durationString.write("1 minut");
|
||||||
|
else
|
||||||
|
durationString.write("${duration.inMinutes} minute");
|
||||||
duration -= Duration(minutes: duration.inMinutes);
|
duration -= Duration(minutes: duration.inMinutes);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Text(
|
return Text(
|
||||||
durationString.toString(),
|
durationString.toString(),
|
||||||
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
||||||
fontSize: isSmallScreen(context) ? 18 : 20,
|
fontSize: isSmallScreen(context) ? 18 : 20,
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -685,8 +750,10 @@ class DisplayTrainRouteDuration extends StatelessWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DisplayTrainYesterdayWarningMaterial extends DisplayTrainYesterdayWarningCommon {
|
class DisplayTrainYesterdayWarningMaterial
|
||||||
DisplayTrainYesterdayWarningMaterial(void Function() onViewYesterdayTrain) : super(onViewYesterdayTrain);
|
extends DisplayTrainYesterdayWarningCommon {
|
||||||
|
DisplayTrainYesterdayWarningMaterial(void Function() onViewYesterdayTrain)
|
||||||
|
: super(onViewYesterdayTrain);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -698,7 +765,9 @@ class DisplayTrainYesterdayWarningMaterial extends DisplayTrainYesterdayWarningC
|
||||||
child: Text.rich(
|
child: Text.rich(
|
||||||
TextSpan(
|
TextSpan(
|
||||||
children: [
|
children: [
|
||||||
TextSpan(text: DisplayTrainYesterdayWarningCommon.trainDidNotDepart,),
|
TextSpan(
|
||||||
|
text: DisplayTrainYesterdayWarningCommon.trainDidNotDepart,
|
||||||
|
),
|
||||||
TextSpan(text: '\n'),
|
TextSpan(text: '\n'),
|
||||||
TextSpan(
|
TextSpan(
|
||||||
text: DisplayTrainYesterdayWarningCommon.seeYesterdayTrain,
|
text: DisplayTrainYesterdayWarningCommon.seeYesterdayTrain,
|
||||||
|
@ -730,6 +799,12 @@ class DisplayTrainStations extends StatelessWidget {
|
||||||
return IndexedSemantics(
|
return IndexedSemantics(
|
||||||
child: DisplayTrainStation(
|
child: DisplayTrainStation(
|
||||||
station: trainData.stations[index],
|
station: trainData.stations[index],
|
||||||
|
onTap: () {
|
||||||
|
Navigator.of(context).pushNamed(
|
||||||
|
ViewStationPage.routeName,
|
||||||
|
arguments: trainData.stations[index].name,
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
index: index,
|
index: index,
|
||||||
);
|
);
|
||||||
|
@ -740,4 +815,3 @@ class DisplayTrainStations extends StatelessWidget {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,163 +1,92 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:info_tren/models/train_data.dart';
|
import 'package:info_tren/models/train_data.dart';
|
||||||
import 'package:info_tren/pages/train_info_page/view_train/train_info_material.dart' show isSmallScreen;
|
import 'package:info_tren/components/badge.dart';
|
||||||
|
import 'package:info_tren/pages/train_info_page/view_train/train_info_material.dart';
|
||||||
|
|
||||||
class DisplayTrainStation extends StatelessWidget {
|
class DisplayTrainStation extends StatelessWidget {
|
||||||
final Station station;
|
final Station station;
|
||||||
|
final void Function()? onTap;
|
||||||
|
|
||||||
DisplayTrainStation({required this.station});
|
DisplayTrainStation({required this.station, this.onTap});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Card(
|
return Card(
|
||||||
child: Padding(
|
child: InkWell(
|
||||||
padding: const EdgeInsets.all(2),
|
onTap: onTap,
|
||||||
child: Column(
|
child: Padding(
|
||||||
mainAxisSize: MainAxisSize.min,
|
padding: const EdgeInsets.all(2),
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
child: Column(
|
||||||
children: <Widget>[
|
mainAxisSize: MainAxisSize.min,
|
||||||
Row(
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
mainAxisSize: MainAxisSize.max,
|
children: <Widget>[
|
||||||
children: <Widget>[
|
Row(
|
||||||
Expanded(
|
mainAxisSize: MainAxisSize.max,
|
||||||
flex: 1,
|
children: <Widget>[
|
||||||
child: Align(
|
Expanded(
|
||||||
alignment: Alignment.centerLeft,
|
flex: 1,
|
||||||
child: Builder(
|
child: Align(
|
||||||
builder: (context) {
|
alignment: Alignment.centerLeft,
|
||||||
final departureStatus = station.departure?.status;
|
child: Builder(
|
||||||
final arrivalStatus = station.arrival?.status;
|
builder: (context) {
|
||||||
int delay;
|
final departureStatus = station.departure?.status;
|
||||||
bool real;
|
final arrivalStatus = station.arrival?.status;
|
||||||
if (departureStatus == null) {
|
int delay;
|
||||||
delay = arrivalStatus?.delay ?? 0;
|
bool real;
|
||||||
real = arrivalStatus?.real ?? false;
|
if (departureStatus == null) {
|
||||||
}
|
delay = arrivalStatus?.delay ?? 0;
|
||||||
else if (arrivalStatus == null) {
|
real = arrivalStatus?.real ?? false;
|
||||||
delay = departureStatus.delay;
|
|
||||||
real = departureStatus.real;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
delay = departureStatus.delay;
|
|
||||||
real = departureStatus.real;
|
|
||||||
if (!real && arrivalStatus.real) {
|
|
||||||
delay = arrivalStatus.delay;
|
|
||||||
real = arrivalStatus.real;
|
|
||||||
}
|
}
|
||||||
|
else if (arrivalStatus == null) {
|
||||||
|
delay = departureStatus.delay;
|
||||||
|
real = departureStatus.real;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
delay = departureStatus.delay;
|
||||||
|
real = departureStatus.real;
|
||||||
|
if (!real && arrivalStatus.real) {
|
||||||
|
delay = arrivalStatus.delay;
|
||||||
|
real = arrivalStatus.real;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final isDelayed = delay > 0 && real == true;
|
||||||
|
final isOnTime = delay <= 0 && real == true;
|
||||||
|
final isNotScheduled = false;
|
||||||
|
|
||||||
|
return MaterialBadge(
|
||||||
|
text: station.km.toString(),
|
||||||
|
caption: 'km',
|
||||||
|
isNotScheduled: isNotScheduled,
|
||||||
|
isDelayed: isDelayed,
|
||||||
|
isOnTime: isOnTime,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
),
|
||||||
final isDelayed = delay > 0 && real == true;
|
|
||||||
final isOnTime = delay <= 0 && real == true;
|
|
||||||
final isNotScheduled = false;
|
|
||||||
|
|
||||||
return Badge(
|
|
||||||
text: station.km.toString(),
|
|
||||||
caption: 'km',
|
|
||||||
isNotScheduled: isNotScheduled,
|
|
||||||
isDelayed: isDelayed,
|
|
||||||
isOnTime: isOnTime,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
Title(
|
||||||
Title(
|
station: station,
|
||||||
station: station,
|
),
|
||||||
),
|
Expanded(
|
||||||
Expanded(
|
flex: 1,
|
||||||
flex: 1,
|
child: (station.platform == null)
|
||||||
child: (station.platform == null)
|
? Container()
|
||||||
? Container()
|
: Align(
|
||||||
: Align(
|
alignment: Alignment.centerRight,
|
||||||
alignment: Alignment.centerRight,
|
child: MaterialBadge(text: station.platform!, caption: 'linia',),
|
||||||
child: Badge(text: station.platform!, caption: 'linia',),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
),
|
||||||
),
|
Time(
|
||||||
Time(
|
station: station,
|
||||||
station: station,
|
),
|
||||||
),
|
Delay(
|
||||||
Delay(
|
station: station,
|
||||||
station: station,
|
),
|
||||||
),
|
],
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Badge extends StatelessWidget {
|
|
||||||
final String text;
|
|
||||||
final String caption;
|
|
||||||
final bool isNotScheduled;
|
|
||||||
final bool isOnTime;
|
|
||||||
final bool isDelayed;
|
|
||||||
|
|
||||||
Badge({
|
|
||||||
required this.text,
|
|
||||||
required this.caption,
|
|
||||||
this.isNotScheduled = false,
|
|
||||||
this.isOnTime = false,
|
|
||||||
this.isDelayed = false,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
Color foregroundColor = Colors.white70;
|
|
||||||
Color? backgroundColor;
|
|
||||||
|
|
||||||
if (isNotScheduled) {
|
|
||||||
foregroundColor = Colors.orange.shade300;
|
|
||||||
backgroundColor = Colors.orange.shade900.withOpacity(0.3);
|
|
||||||
}
|
|
||||||
else if (isOnTime) {
|
|
||||||
foregroundColor = Colors.green.shade300;
|
|
||||||
backgroundColor = Colors.green.shade900.withOpacity(0.3);
|
|
||||||
}
|
|
||||||
else if (isDelayed) {
|
|
||||||
foregroundColor = Colors.red.shade300;
|
|
||||||
backgroundColor = Colors.red.shade900.withOpacity(0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.all(8),
|
|
||||||
child: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
border: Border.all(
|
|
||||||
width: 2,
|
|
||||||
color: foregroundColor,
|
|
||||||
),
|
),
|
||||||
color: backgroundColor,
|
|
||||||
),
|
|
||||||
width: isSmallScreen(context) ? 42 : 48,
|
|
||||||
height: isSmallScreen(context) ? 42 : 48,
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: <Widget>[
|
|
||||||
Expanded(
|
|
||||||
child: Center(
|
|
||||||
child: Text(
|
|
||||||
text,
|
|
||||||
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
|
||||||
fontSize: isSmallScreen(context) ? 16 : 20,
|
|
||||||
fontWeight: MediaQuery.of(context).boldText ? FontWeight.w400 : FontWeight.w200,
|
|
||||||
color: MediaQuery.of(context).boldText ? Colors.white70 : foregroundColor,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
caption,
|
|
||||||
style: Theme.of(context).textTheme.bodyText2?.copyWith(
|
|
||||||
fontSize: 10,
|
|
||||||
color: MediaQuery.of(context).boldText ? Colors.white70 : foregroundColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -11,7 +11,7 @@ description: O aplicație de vizualizare a datelor puse la dispoziție de Inform
|
||||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||||
# Read more about iOS versioning at
|
# Read more about iOS versioning at
|
||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
version: 2.7.4
|
version: 2.7.6
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.15.0 <3.0.0"
|
sdk: ">=2.15.0 <3.0.0"
|
||||||
|
|
Loading…
Add table
Reference in a new issue