reworked page layout inheritence
This commit is contained in:
@@ -1,10 +1,9 @@
|
||||
import 'dart:developer';
|
||||
import 'package:anyway/modules/step_between_landmarks.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:anyway/modules/landmark_card.dart';
|
||||
import 'package:anyway/structs/landmark.dart';
|
||||
import 'package:anyway/structs/trip.dart';
|
||||
import 'package:anyway/modules/step_between_landmarks.dart';
|
||||
import 'package:anyway/modules/landmark_card.dart';
|
||||
|
||||
|
||||
// Returns a list of widgets that represent the landmarks matching the given selector
|
||||
@@ -35,4 +34,3 @@ List<Widget> landmarksList(Trip trip, {required bool Function(Landmark) selector
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
|
@@ -35,29 +35,29 @@ class _CurrentTripLoadingIndicatorState extends State<CurrentTripLoadingIndicato
|
||||
// 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
|
||||
Align(
|
||||
const Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: statusText(),
|
||||
child: StatusText(),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// automatically cycle through the greeter texts
|
||||
class statusText extends StatefulWidget {
|
||||
const statusText({Key? key}) : super(key: key);
|
||||
class StatusText extends StatefulWidget {
|
||||
const StatusText({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_statusTextState createState() => _statusTextState();
|
||||
_StatusTextState createState() => _StatusTextState();
|
||||
}
|
||||
|
||||
class _statusTextState extends State<statusText> {
|
||||
class _StatusTextState extends State<StatusText> {
|
||||
int statusIndex = 0;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
Future.delayed(Duration(seconds: 5), () {
|
||||
Future.delayed(const Duration(seconds: 5), () {
|
||||
setState(() {
|
||||
statusIndex = (statusIndex + 1) % statusTexts.length;
|
||||
});
|
||||
@@ -159,4 +159,3 @@ class _AnimatedGradientTextState extends State<AnimatedGradientText> with Single
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,13 +1,14 @@
|
||||
import 'dart:collection';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||
import 'package:widget_to_marker/widget_to_marker.dart';
|
||||
|
||||
import 'package:anyway/constants.dart';
|
||||
import 'package:anyway/modules/landmark_map_marker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:anyway/structs/landmark.dart';
|
||||
import 'package:anyway/structs/trip.dart';
|
||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:widget_to_marker/widget_to_marker.dart';
|
||||
import 'package:anyway/modules/landmark_map_marker.dart';
|
||||
|
||||
|
||||
class CurrentTripMap extends StatefulWidget {
|
||||
final Trip? trip;
|
||||
@@ -60,25 +61,29 @@ class _CurrentTripMapState extends State<CurrentTripMap> {
|
||||
}
|
||||
|
||||
void setMapMarkers() async {
|
||||
List<Landmark> landmarks = widget.trip?.landmarks.toList() ?? [];
|
||||
Set<Marker> markers = <Marker>{};
|
||||
Iterator<(int, Landmark)> it = (widget.trip?.landmarks.toList() ?? []).indexed.iterator;
|
||||
|
||||
for (int i = 0; i < landmarks.length; i++) {
|
||||
Landmark landmark = landmarks[i];
|
||||
while (it.moveNext()) {
|
||||
int i = it.current.$1;
|
||||
Landmark landmark = it.current.$2;
|
||||
|
||||
MarkerId markerId = MarkerId("${landmark.uuid} - ${landmark.visited}");
|
||||
List<double> location = landmark.location;
|
||||
Marker marker = Marker(
|
||||
markerId: MarkerId(landmark.uuid),
|
||||
position: LatLng(location[0], location[1]),
|
||||
icon: await ThemedMarker(landmark: landmark, position: i).toBitmapDescriptor(
|
||||
logicalSize: const Size(150, 150),
|
||||
imageSize: const Size(150, 150),
|
||||
),
|
||||
);
|
||||
markers.add(marker);
|
||||
// only create a new marker, if there is no marker for this landmark
|
||||
if (!mapMarkers.any((Marker marker) => marker.markerId == markerId)) {
|
||||
Marker marker = Marker(
|
||||
markerId: markerId,
|
||||
position: LatLng(location[0], location[1]),
|
||||
icon: await ThemedMarker(landmark: landmark, position: i).toBitmapDescriptor(
|
||||
logicalSize: const Size(150, 150),
|
||||
imageSize: const Size(150, 150),
|
||||
)
|
||||
);
|
||||
setState(() {
|
||||
mapMarkers.add(marker);
|
||||
});
|
||||
}
|
||||
}
|
||||
setState(() {
|
||||
mapMarkers = markers;
|
||||
});
|
||||
}
|
||||
|
||||
void setMapRoute() async {
|
||||
@@ -98,8 +103,8 @@ class _CurrentTripMapState extends State<CurrentTripMap> {
|
||||
Polyline stepLine = Polyline(
|
||||
polylineId: PolylineId('step-${landmark.uuid}'),
|
||||
points: step,
|
||||
color: landmark.visited ? Colors.grey : PRIMARY_COLOR,
|
||||
width: 5,
|
||||
color: landmark.visited || (landmark.next?.visited ?? false) ? Colors.grey : PRIMARY_COLOR,
|
||||
width: 5
|
||||
);
|
||||
polyLines.add(stepLine);
|
||||
}
|
||||
|
@@ -1,10 +1,12 @@
|
||||
import 'package:anyway/constants.dart';
|
||||
import 'package:anyway/modules/current_trip_error_message.dart';
|
||||
import 'package:anyway/modules/current_trip_loading_indicator.dart';
|
||||
import 'package:anyway/structs/landmark.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:anyway/constants.dart';
|
||||
|
||||
import 'package:anyway/structs/landmark.dart';
|
||||
import 'package:anyway/structs/trip.dart';
|
||||
|
||||
import 'package:anyway/modules/current_trip_error_message.dart';
|
||||
import 'package:anyway/modules/current_trip_loading_indicator.dart';
|
||||
import 'package:anyway/modules/current_trip_summary.dart';
|
||||
import 'package:anyway/modules/current_trip_save_button.dart';
|
||||
import 'package:anyway/modules/current_trip_landmarks_list.dart';
|
||||
@@ -74,20 +76,21 @@ class _CurrentTripPanelState extends State<CurrentTripPanel> {
|
||||
child: Column(
|
||||
children: [
|
||||
CurrentTripSummary(trip: widget.trip),
|
||||
ExpansionTile(
|
||||
leading: Icon(Icons.location_on),
|
||||
title: Text('Visited Landmarks (tap to expand)'),
|
||||
children: [
|
||||
...landmarksList(widget.trip, selector: (Landmark landmark) => landmark.visited),
|
||||
],
|
||||
visualDensity: VisualDensity.compact,
|
||||
collapsedShape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
if (widget.trip.landmarks.where((Landmark landmark) => landmark.visited).isNotEmpty)
|
||||
ExpansionTile(
|
||||
leading: const Icon(Icons.location_on),
|
||||
title: const Text('Visited Landmarks (tap to expand)'),
|
||||
children: [
|
||||
...landmarksList(widget.trip, selector: (Landmark landmark) => landmark.visited),
|
||||
],
|
||||
visualDensity: VisualDensity.compact,
|
||||
collapsedShape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -108,4 +111,4 @@ class _CurrentTripPanelState extends State<CurrentTripPanel> {
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:auto_size_text/auto_size_text.dart';
|
||||
|
||||
import 'package:anyway/main.dart';
|
||||
import 'package:anyway/structs/trip.dart';
|
||||
import 'package:auto_size_text/auto_size_text.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
||||
class saveButton extends StatefulWidget {
|
||||
@@ -52,4 +52,3 @@ class _saveButtonState extends State<saveButton> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import 'package:anyway/structs/trip.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
||||
class CurrentTripSummary extends StatefulWidget {
|
||||
final Trip trip;
|
||||
const CurrentTripSummary({
|
||||
@@ -16,22 +17,22 @@ class _CurrentTripSummaryState extends State<CurrentTripSummary> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 20),
|
||||
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Icon(Icons.flag, size: 20),
|
||||
Padding(padding: EdgeInsets.only(right: 10)),
|
||||
Text('Stops: ${widget.trip.landmarks.length}', style: Theme.of(context).textTheme.bodyLarge,),
|
||||
const Icon(Icons.flag, size: 20),
|
||||
const Padding(padding: EdgeInsets.only(right: 10)),
|
||||
Text('Stops: ${widget.trip.landmarks.length}', style: Theme.of(context).textTheme.bodyLarge),
|
||||
]
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Icon(Icons.hourglass_bottom_rounded, size: 20),
|
||||
Padding(padding: EdgeInsets.only(right: 10)),
|
||||
Text('Duration: ${widget.trip.totalTime} minutes', style: Theme.of(context).textTheme.bodyLarge,),
|
||||
const Icon(Icons.hourglass_bottom_rounded, size: 20),
|
||||
const Padding(padding: EdgeInsets.only(right: 10)),
|
||||
Text('Duration: ${widget.trip.totalTime} minutes', style: Theme.of(context).textTheme.bodyLarge),
|
||||
]
|
||||
),
|
||||
],
|
||||
|
@@ -1,6 +1,6 @@
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
||||
Future<void> helpDialog(BuildContext context, String title, String content) {
|
||||
return showDialog<void>(
|
||||
context: context,
|
||||
|
@@ -1,12 +1,15 @@
|
||||
import 'package:anyway/constants.dart';
|
||||
import 'package:anyway/main.dart';
|
||||
import 'package:anyway/structs/trip.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
import 'package:anyway/constants.dart';
|
||||
|
||||
import 'package:anyway/main.dart';
|
||||
import 'package:anyway/structs/trip.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:anyway/structs/landmark.dart';
|
||||
|
||||
|
||||
|
||||
class LandmarkCard extends StatefulWidget {
|
||||
final Landmark landmark;
|
||||
final Trip parentTrip;
|
||||
@@ -23,20 +26,11 @@ class LandmarkCard extends StatefulWidget {
|
||||
|
||||
class _LandmarkCardState extends State<LandmarkCard> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (widget.landmark.type == typeStart || widget.landmark.type == typeFinish) {
|
||||
return TextButton.icon(
|
||||
onPressed: () {},
|
||||
icon: widget.landmark.type.icon,
|
||||
label: Text(widget.landmark.name),
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
constraints: BoxConstraints(
|
||||
minHeight: 50,
|
||||
maxHeight: 200,
|
||||
// express the max height in terms text lines
|
||||
maxHeight: 7 * (Theme.of(context).textTheme.titleMedium!.fontSize! + 10),
|
||||
),
|
||||
child: Card(
|
||||
shape: RoundedRectangleBorder(
|
||||
@@ -79,23 +73,23 @@ class _LandmarkCardState extends State<LandmarkCard> {
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Container(
|
||||
color: PRIMARY_COLOR,
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(5),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 5,
|
||||
children: [
|
||||
Icon(widget.landmark.type.icon.icon, size: 16),
|
||||
Text(widget.landmark.type.name, style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
],
|
||||
if (widget.landmark.type != typeStart && widget.landmark.type != typeFinish)
|
||||
Container(
|
||||
color: PRIMARY_COLOR,
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(5),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
spacing: 5,
|
||||
children: [
|
||||
Icon(Icons.timer_outlined, size: 16),
|
||||
Text("${widget.landmark.duration?.inMinutes} minutes"),
|
||||
],
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
)
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
),
|
||||
@@ -133,12 +127,6 @@ class _LandmarkCardState extends State<LandmarkCard> {
|
||||
// show the type, the website, and the wikipedia link as buttons/labels in a row
|
||||
children: [
|
||||
doneToggleButton(),
|
||||
// if (widget.landmark.duration != null && widget.landmark.duration!.inMinutes > 0)
|
||||
// TextButton.icon(
|
||||
// onPressed: () {},
|
||||
// icon: Icon(Icons.hourglass_bottom),
|
||||
// label: Text('${widget.landmark.duration!.inMinutes} minutes'),
|
||||
// ),
|
||||
if (widget.landmark.websiteURL != null)
|
||||
websiteButton(),
|
||||
|
||||
@@ -172,33 +160,35 @@ class _LandmarkCardState extends State<LandmarkCard> {
|
||||
// open a browser with the website link
|
||||
await launchUrl(Uri.parse(widget.landmark.websiteURL!));
|
||||
},
|
||||
icon: Icon(Icons.link),
|
||||
label: Text('Website'),
|
||||
icon: const Icon(Icons.link),
|
||||
label: const Text('Website'),
|
||||
);
|
||||
|
||||
|
||||
Widget optionsButton () => PopupMenuButton(
|
||||
icon: Icon(Icons.settings),
|
||||
icon: const Icon(Icons.settings),
|
||||
style: TextButtonTheme.of(context).style,
|
||||
itemBuilder: (context) => [
|
||||
PopupMenuItem(
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.delete),
|
||||
title: Text('Delete'),
|
||||
leading: const Icon(Icons.delete),
|
||||
title: const Text('Delete'),
|
||||
onTap: () async {
|
||||
widget.parentTrip.removeLandmark(widget.landmark);
|
||||
rootScaffoldMessengerKey.currentState!.showSnackBar(
|
||||
SnackBar(content: Text("We won't show ${widget.landmark.name} again"))
|
||||
SnackBar(content: Text("${widget.landmark.name} won't be shown again"))
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.star),
|
||||
title: Text('Favorite'),
|
||||
leading: const Icon(Icons.star),
|
||||
title: const Text('Favorite'),
|
||||
onTap: () async {
|
||||
// delete the landmark
|
||||
// await deleteLandmark(widget.landmark);
|
||||
rootScaffoldMessengerKey.currentState!.showSnackBar(
|
||||
SnackBar(content: Text("Not implemented yet"))
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
@@ -46,11 +46,11 @@ class _NewTripButtonState extends State<NewTripButton> {
|
||||
UserPreferences preferences = widget.preferences;
|
||||
if (preferences.nature.value == 0 && preferences.shopping.value == 0 && preferences.sightseeing.value == 0){
|
||||
rootScaffoldMessengerKey.currentState!.showSnackBar(
|
||||
SnackBar(content: Text("Please specify at least one preference"))
|
||||
const SnackBar(content: Text("Please specify at least one preference"))
|
||||
);
|
||||
} else if (preferences.maxTime.value == 0){
|
||||
rootScaffoldMessengerKey.currentState!.showSnackBar(
|
||||
SnackBar(content: Text("Please choose a longer duration"))
|
||||
const SnackBar(content: Text("Please choose a longer duration"))
|
||||
);
|
||||
} else {
|
||||
Trip trip = widget.trip;
|
||||
@@ -63,4 +63,3 @@ class _NewTripButtonState extends State<NewTripButton> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,14 +1,14 @@
|
||||
// A map that allows the user to select a location for a new trip.
|
||||
import 'dart:developer';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||
import 'package:widget_to_marker/widget_to_marker.dart';
|
||||
|
||||
import 'package:anyway/constants.dart';
|
||||
import 'package:anyway/modules/landmark_map_marker.dart';
|
||||
import 'package:anyway/structs/landmark.dart';
|
||||
|
||||
import 'package:anyway/structs/trip.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:widget_to_marker/widget_to_marker.dart';
|
||||
import 'package:anyway/structs/landmark.dart';
|
||||
import 'package:anyway/modules/landmark_map_marker.dart';
|
||||
|
||||
|
||||
class NewTripMap extends StatefulWidget {
|
||||
|
@@ -1,7 +1,9 @@
|
||||
import 'package:anyway/structs/landmark.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:anyway/structs/landmark.dart';
|
||||
import 'package:anyway/modules/map_chooser.dart';
|
||||
|
||||
|
||||
class StepBetweenLandmarks extends StatefulWidget {
|
||||
final Landmark current;
|
||||
final Landmark next;
|
||||
@@ -19,11 +21,15 @@ class StepBetweenLandmarks extends StatefulWidget {
|
||||
class _StepBetweenLandmarksState extends State<StepBetweenLandmarks> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
int time = widget.current.tripTime?.inMinutes ?? 0;
|
||||
int? time = widget.current.tripTime?.inMinutes;
|
||||
if (time != null && time < 1) {
|
||||
time = 1;
|
||||
}
|
||||
|
||||
return Container(
|
||||
margin: EdgeInsets.all(10),
|
||||
padding: EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
margin: const EdgeInsets.all(10),
|
||||
padding: const EdgeInsets.all(10),
|
||||
decoration: const BoxDecoration(
|
||||
border: Border(
|
||||
left: BorderSide(width: 3.0, color: Colors.black),
|
||||
),
|
||||
@@ -32,21 +38,22 @@ class _StepBetweenLandmarksState extends State<StepBetweenLandmarks> {
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
Icon(Icons.directions_walk),
|
||||
Text("$time min", style: TextStyle(fontSize: 10)),
|
||||
const Icon(Icons.directions_walk),
|
||||
Text(
|
||||
time == null ? "" : "About $time min",
|
||||
style: const TextStyle(fontSize: 10)
|
||||
),
|
||||
],
|
||||
),
|
||||
Spacer(),
|
||||
ElevatedButton(
|
||||
|
||||
const Spacer(),
|
||||
|
||||
ElevatedButton.icon(
|
||||
onPressed: () async {
|
||||
showMapChooser(context, widget.current, widget.next);
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.directions),
|
||||
Text("Directions"),
|
||||
],
|
||||
),
|
||||
icon: const Icon(Icons.directions),
|
||||
label: const Text("Directions"),
|
||||
)
|
||||
],
|
||||
),
|
||||
|
Reference in New Issue
Block a user