rsflutterapp

Bahnhofsfoto-App for Android and iOS using Flutter
git clone git://archive.git.mtrnord.blog/MTRNord/rsflutterapp.git
Log | Files | Refs | README

commit 31c13956455a68e1df6f8fadba3b4c40bf891ec9
parent 0ab42680c51605fd221eff8dbab4b08149701b40
Author: Marcel <mtrnord1@gmail.com>
Date:   Sun, 23 Feb 2020 20:04:56 +0100

Add basic Profile Page and basic stations list

Took 27 minutes

Diffstat:
Mlib/views/HomePage.dart | 42++++++++++++++++++++++++++++++++++--------
Alib/views/tabs/RankingsTab.dart | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mlib/views/tabs/SettingsTab.dart | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
Alib/views/tabs/StationsTab.dart | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dlib/views/tabs/rankingsTab.dart | 99-------------------------------------------------------------------------------
Mpubspec.lock | 7-------
Mpubspec.yaml | 3+--
7 files changed, 265 insertions(+), 136 deletions(-)

diff --git a/lib/views/HomePage.dart b/lib/views/HomePage.dart @@ -2,13 +2,14 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:http/http.dart' as http; -import 'package:rs_flutter_app/views/tabs/rankingsTab.dart'; import '../blocs/MapBloc.dart'; import '../repos/RailwayStationsApiClient.dart'; import '../repos/repositories.dart'; import 'tabs/MapTab.dart'; +import 'tabs/RankingsTab.dart'; import 'tabs/SettingsTab.dart'; +import 'tabs/StationsTab.dart'; class HomePage extends StatelessWidget { @override @@ -21,7 +22,8 @@ class HomePage extends StatelessWidget { ); return DefaultTabController( - length: 3, + length: 4, + initialIndex: 3, child: Scaffold( bottomNavigationBar: Container( color: Theme.of(context).primaryColor, @@ -29,20 +31,36 @@ class HomePage extends StatelessWidget { labelColor: Colors.white, unselectedLabelColor: Colors.white70, indicatorSize: TabBarIndicatorSize.tab, - indicatorPadding: EdgeInsets.all(5.0), + //indicatorPadding: EdgeInsets.all(5.0), indicatorColor: Theme.of(context).accentColor, tabs: [ Tab( - icon: Icon(CupertinoIcons.location), + icon: Icon( + CupertinoIcons.location, + size: 20, + ), text: 'Map', ), Tab( - icon: Icon(CupertinoIcons.info), + icon: Icon( + CupertinoIcons.info, + size: 20, + ), text: 'Rangliste', ), Tab( - icon: Icon(CupertinoIcons.settings), - text: 'Einstellungen', + icon: Icon( + CupertinoIcons.train_style_one, + size: 20, + ), + text: 'Bahnhöfe', + ), + Tab( + icon: Icon( + CupertinoIcons.profile_circled, + size: 20, + ), + text: 'Meine Daten', ), ], ), @@ -70,7 +88,15 @@ class HomePage extends StatelessWidget { ), Scaffold( appBar: AppBar( - title: Text("Einstellungen"), + title: Text("Bahnhöfe"), + ), + body: StationsTab( + railwayStationsRepository: railwayStationsRepository, + ), + ), + Scaffold( + appBar: AppBar( + title: Text("Meine Daten"), ), body: SettingsTab(), ), diff --git a/lib/views/tabs/RankingsTab.dart b/lib/views/tabs/RankingsTab.dart @@ -0,0 +1,101 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import '../../repos/repositories.dart'; + +class RankingsTab extends StatelessWidget { + final RailwayStationsRepository railwayStationsRepository; + + RankingsTab({@required this.railwayStationsRepository}) + : assert(railwayStationsRepository != null); + + Future<List<List<String>>> getScores() { + return this.railwayStationsRepository.getScores(); + } + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: getScores(), + builder: + (BuildContext context, AsyncSnapshot<List<List<String>>> snapshot) { + switch (snapshot.connectionState) { + case ConnectionState.done: + if (snapshot.hasError) { + // TODO handle error + debugPrint(snapshot.error.toString()); + } + if (snapshot.hasData) { + List<List<String>> scores = snapshot.data; + scores.removeAt(0); + scores.sort( + (a, b) => (int.parse(b.first)).compareTo(int.parse(a.first)), + ); + + return ListView.separated( + itemCount: scores.length, + separatorBuilder: (BuildContext context, int index) { + return Divider(); + }, + itemBuilder: (BuildContext context, int index) { + if (index == 0) { + return ListTile( + leading: SvgPicture.asset( + "assets/crown_gold.svg", + semanticsLabel: 'Golden Crown', + width: 50, + height: 50, + ), + title: Text(scores[index][1]), + ); + } else if (index == 1) { + return ListTile( + leading: SvgPicture.asset( + "assets/crown_silver.svg", + semanticsLabel: 'Silver Crown', + width: 50, + height: 50, + ), + title: Text(scores[index][1]), + ); + } else if (index == 2) { + return ListTile( + leading: SvgPicture.asset( + "assets/crown_bronze.svg", + semanticsLabel: 'Bronze Crown', + width: 50, + height: 50, + ), + title: Text(scores[index][1]), + ); + } else { + return ListTile( + leading: SizedBox( + width: 50, + height: 50, + child: Center( + child: Text( + "${(index + 1)}.", + style: TextStyle( + fontWeight: FontWeight.bold, + ), + ), + ), + ), + title: Text(scores[index][1]), + ); + } + }, + ); + } + // TODO handle missing date + return Container(); + default: + return Center( + child: CircularProgressIndicator(), + ); + } + }, + ); + } +} diff --git a/lib/views/tabs/SettingsTab.dart b/lib/views/tabs/SettingsTab.dart @@ -1,6 +1,5 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:settings_ui/settings_ui.dart'; class SettingsTab extends StatefulWidget { @override @@ -9,30 +8,69 @@ class SettingsTab extends StatefulWidget { class SettingsTabState extends State<SettingsTab> with AutomaticKeepAliveClientMixin<SettingsTab> { + final _formKey = GlobalKey<FormState>(); + @override Widget build(BuildContext context) { super.build(context); - return SettingsList(sections: [ - SettingsSection( - title: 'Bahnhofsdaten', - tiles: [ - SettingsTile( - title: 'Länderdaten aktualisieren', - leading: Icon(Icons.language), - onTap: () {}, - ), - ], - ), - SettingsSection( - title: 'Lizensierung', - tiles: [], - ), - SettingsSection( - title: 'Verlinkung', - tiles: [], + return Padding( + padding: EdgeInsets.all(16), + child: Form( + key: _formKey, + child: Column( + children: <Widget>[ + Text("Profil"), + TextFormField( + decoration: InputDecoration(hintText: "Nickname"), + // The validator receives the text that the user has entered. + validator: (value) { + if (value.isEmpty) { + return 'Please enter a nickname'; + } + return null; + }, + ), + TextFormField( + decoration: InputDecoration(hintText: "E-Mail"), + // The validator receives the text that the user has entered. + validator: (value) { + if (value.isEmpty) { + return 'Please enter an E-Mail'; + } + return null; + }, + ), + // TODO add checkboxes + TextFormField( + decoration: InputDecoration(hintText: "Dein Link"), + // The validator receives the text that the user has entered. + validator: (value) { + if (value.isEmpty) { + return 'Please enter an E-Mail'; + } + return null; + }, + ), + RaisedButton( + onPressed: () { + // Validate returns true if the form is valid, otherwise false. + if (_formKey.currentState.validate()) { + // If the form is valid, display a snackbar. In the real world, + // you'd often call a server or save the information in a database. + + Scaffold.of(context) + .showSnackBar(SnackBar(content: Text('Processing Data'))); + + // TODO do stuff + } + }, + child: Text('Speichern'), + ), + ], + ), ), - ]); + ); } @override diff --git a/lib/views/tabs/StationsTab.dart b/lib/views/tabs/StationsTab.dart @@ -0,0 +1,71 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +import '../../models/models.dart'; +import '../../repos/repositories.dart'; +import '../DetailsPage.dart'; + +class StationsTab extends StatelessWidget { + final RailwayStationsRepository railwayStationsRepository; + + StationsTab({@required this.railwayStationsRepository}) + : assert(railwayStationsRepository != null); + + Future<List<Station>> getStations() { + return this.railwayStationsRepository.getStations(); + } + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: getStations(), + builder: (BuildContext context, AsyncSnapshot<List<Station>> snapshot) { + switch (snapshot.connectionState) { + case ConnectionState.done: + if (snapshot.hasError) { + // TODO handle error + debugPrint(snapshot.error.toString()); + } + if (snapshot.hasData) { + List<Station> stations = snapshot.data; + stations.sort( + (a, b) => (a.title).compareTo(b.title), + ); + + return ListView.separated( + itemCount: stations.length, + separatorBuilder: (BuildContext context, int index) { + return Divider(); + }, + itemBuilder: (BuildContext context, int index) { + return ListTile( + trailing: stations[index].photoUrl != "" + ? Icon(Icons.image) + : null, + title: Text(stations[index].title), + onTap: () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (BuildContext context) => DetailsPage( + station: stations[index], + railwayStationsRepository: + railwayStationsRepository, + ), + ), + ); + }, + ); + }, + ); + } + // TODO handle missing date + return Container(); + default: + return Center( + child: CircularProgressIndicator(), + ); + } + }, + ); + } +} diff --git a/lib/views/tabs/rankingsTab.dart b/lib/views/tabs/rankingsTab.dart @@ -1,99 +0,0 @@ -import 'package:flutter/cupertino.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; -import '../../repos/repositories.dart'; - -class RankingsTab extends StatelessWidget { - final RailwayStationsRepository railwayStationsRepository; - - RankingsTab({@required this.railwayStationsRepository}) - : assert(railwayStationsRepository != null); - - Future<List<List<String>>> getScores() { - return this.railwayStationsRepository.getScores(); - } - - @override - Widget build(BuildContext context) { - return FutureBuilder( - future: getScores(), - builder: - (BuildContext context, AsyncSnapshot<List<List<String>>> snapshot) { - switch (snapshot.connectionState) { - case ConnectionState.done: - if (snapshot.hasError) { - // TODO handle error - debugPrint(snapshot.error.toString()); - } - if (snapshot.hasData) { - List<List<String>> scores = snapshot.data; - scores.removeAt(0); - scores.sort( - (a, b) => (int.parse(b.first)).compareTo(int.parse(a.first)), - ); - - return ListView.separated( - itemCount: scores.length, - separatorBuilder: (BuildContext context, int index) { - return Divider(); - }, - itemBuilder: (BuildContext context, int index) { - if (index == 0) { - return ListTile( - leading: SvgPicture.asset( - "assets/crown_gold.svg", - semanticsLabel: 'Golden Crown', - width: 50, - height: 50, - ), - title: Text(scores[index][1]), - ); - } else if (index == 1) { - return ListTile( - leading: SvgPicture.asset( - "assets/crown_silver.svg", - semanticsLabel: 'Silver Crown', - width: 50, - height: 50, - ), - title: Text(scores[index][1]), - ); - } else if (index == 2) { - return ListTile( - leading: SvgPicture.asset( - "assets/crown_bronze.svg", - semanticsLabel: 'Bronze Crown', - width: 50, - height: 50, - ), - title: Text(scores[index][1]), - ); - } else { - return ListTile( - leading: SizedBox( - width: 50, - height: 50, - child: Center( - child: Text( - "${(index + 1)}.", - style: TextStyle( - fontWeight: FontWeight.bold, - ), - ), - ), - ), - title: Text(scores[index][1]), - ); - } - }, - ); - } - // TODO handle missing date - return Container(); - default: - return CircularProgressIndicator(); - } - }, - ); - } -} diff --git a/pubspec.lock b/pubspec.lock @@ -474,13 +474,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.23.1" - settings_ui: - dependency: "direct main" - description: - name: settings_ui - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.0" shelf: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml @@ -31,11 +31,10 @@ dependencies: flutter_map: ^0.8.2 latlong: ^0.6.1 flutter_map_marker_cluster: ^0.2.7 + url_launcher: ^5.4.2 maps_launcher: ^1.2.0 - settings_ui: ^0.2.0 - flutter_cache_manager: ^1.1.3 grizzly_io: ^2.2.0