reworked page layout inheritence

This commit is contained in:
2025-02-15 19:36:41 +01:00
parent 8f6dfd404d
commit 56c55883ea
21 changed files with 278 additions and 278 deletions

View File

@@ -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;
}

View File

@@ -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
);
}
}

View File

@@ -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);
}

View File

@@ -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> {
}
);
}
}
}

View File

@@ -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> {
);
}
}

View File

@@ -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),
]
),
],

View File

@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
Future<void> helpDialog(BuildContext context, String title, String content) {
return showDialog<void>(
context: context,

View File

@@ -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"))
);
},
),
),

View File

@@ -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> {
}
}
}

View File

@@ -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 {

View File

@@ -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"),
)
],
),