adding missing const
This commit is contained in:
@@ -37,8 +37,8 @@ jobs:
|
|||||||
|
|
||||||
- uses: https://github.com/actions/setup-java@v4
|
- uses: https://github.com/actions/setup-java@v4
|
||||||
with:
|
with:
|
||||||
java-version: '17'
|
java-version: '21'
|
||||||
distribution: 'zulu'
|
distribution: 'oracle'
|
||||||
|
|
||||||
- name: Setup Android SDK
|
- name: Setup Android SDK
|
||||||
uses: https://github.com/android-actions/setup-android@v3
|
uses: https://github.com/android-actions/setup-android@v3
|
||||||
|
|||||||
5
.vscode/launch.json
vendored
5
.vscode/launch.json
vendored
@@ -33,8 +33,11 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "lib/main.dart",
|
"program": "lib/main.dart",
|
||||||
"cwd": "${workspaceFolder}/frontend",
|
"cwd": "${workspaceFolder}/frontend",
|
||||||
|
"args": [
|
||||||
|
"--dart-define-from-file=secrets.json"
|
||||||
|
],
|
||||||
"env": {
|
"env": {
|
||||||
"GOOGLE_MAPS_API_KEY": "testing"
|
"ANDROID_GOOGLE_MAPS_API_KEY": "AIzaSyD6RK_pzKFc8T-t1t0jiC3PNRZwNXECFG4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
16
default.nix
16
default.nix
@@ -1,17 +1,19 @@
|
|||||||
{ pkgs ? import <nixpkgs> { config.android_sdk.accept_license = true; config.allowUnfree = true; } }:
|
{ pkgs ? import <nixpkgs> { config.android_sdk.accept_license = true; config.allowUnfree = true; } }:
|
||||||
|
|
||||||
pkgs.mkShell {
|
pkgs.mkShell {
|
||||||
buildInputs = [
|
|
||||||
pkgs.flutter
|
buildInputs = with pkgs; [
|
||||||
#pkgs.android-tools # for adb
|
flutter
|
||||||
#pkgs.openjdk # required for Android builds
|
android-tools # for adb
|
||||||
|
openjdk # required for Android builds
|
||||||
|
# pkgs.androidenv.androidPkgs.androidsdk # The customized SDK that we've made above
|
||||||
|
# androidenv.androidPkgs.ndk-bundle
|
||||||
];
|
];
|
||||||
|
|
||||||
# Set up Android SDK paths if needed
|
# Set up Android SDK paths if needed
|
||||||
|
ANDROID_HOME = "/scratch/remy/android";
|
||||||
|
|
||||||
shellHook = ''
|
shellHook = ''
|
||||||
export ANDROID_SDK_ROOT=${pkgs.androidsdk}/libexec/android-sdk
|
|
||||||
export PATH=$PATH:${pkgs.androidsdk}/libexec/android-sdk/platform-tools
|
|
||||||
echo "Flutter dev environment ready. 'adb' and 'flutter' are available."
|
echo "Flutter dev environment ready. 'adb' and 'flutter' are available."
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ pluginManagement {
|
|||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
||||||
id "com.android.application" version "8.1.0" apply false
|
id "com.android.application" version "8.7.0" apply false
|
||||||
id "org.jetbrains.kotlin.android" version "2.0.20" apply false
|
id "org.jetbrains.kotlin.android" version "2.0.20" apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,13 +26,13 @@ ThemeData APP_THEME = ThemeData(
|
|||||||
cardColor: Colors.white,
|
cardColor: Colors.white,
|
||||||
useMaterial3: true,
|
useMaterial3: true,
|
||||||
|
|
||||||
colorScheme: ColorScheme.light(
|
colorScheme: const ColorScheme.light(
|
||||||
primary: PRIMARY_COLOR,
|
primary: PRIMARY_COLOR,
|
||||||
secondary: GRADIENT_END,
|
secondary: GRADIENT_END,
|
||||||
surface: Colors.white,
|
surface: Colors.white,
|
||||||
error: Colors.red,
|
error: Colors.red,
|
||||||
onPrimary: Colors.white,
|
onPrimary: Colors.white,
|
||||||
onSecondary: const Color.fromARGB(255, 30, 22, 22),
|
onSecondary: Color.fromARGB(255, 30, 22, 22),
|
||||||
onSurface: Colors.black,
|
onSurface: Colors.black,
|
||||||
onError: Colors.white,
|
onError: Colors.white,
|
||||||
brightness: Brightness.light,
|
brightness: Brightness.light,
|
||||||
@@ -64,12 +64,6 @@ ThemeData APP_THEME = ThemeData(
|
|||||||
),
|
),
|
||||||
|
|
||||||
|
|
||||||
cardTheme: const CardTheme(
|
|
||||||
shadowColor: Colors.grey,
|
|
||||||
elevation: 2,
|
|
||||||
margin: EdgeInsets.all(10),
|
|
||||||
),
|
|
||||||
|
|
||||||
sliderTheme: const SliderThemeData(
|
sliderTheme: const SliderThemeData(
|
||||||
trackHeight: 15,
|
trackHeight: 15,
|
||||||
inactiveTrackColor: Colors.grey,
|
inactiveTrackColor: Colors.grey,
|
||||||
@@ -83,4 +77,4 @@ const Gradient APP_GRADIENT = LinearGradient(
|
|||||||
begin: Alignment.topLeft,
|
begin: Alignment.topLeft,
|
||||||
end: Alignment.bottomRight,
|
end: Alignment.bottomRight,
|
||||||
colors: [GRADIENT_START, GRADIENT_END],
|
colors: [GRADIENT_START, GRADIENT_END],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class _CurrentTripErrorMessageState extends State<CurrentTripErrorMessage> {
|
|||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
const Text(
|
||||||
"😢",
|
"😢",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 40,
|
fontSize: 40,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import 'package:anyway/structs/trip.dart';
|
|||||||
class CurrentTripGreeter extends StatefulWidget {
|
class CurrentTripGreeter extends StatefulWidget {
|
||||||
final Trip trip;
|
final Trip trip;
|
||||||
|
|
||||||
CurrentTripGreeter({
|
const CurrentTripGreeter({
|
||||||
super.key,
|
super.key,
|
||||||
required this.trip,
|
required this.trip,
|
||||||
});
|
});
|
||||||
@@ -47,4 +47,4 @@ class _CurrentTripGreeterState extends State<CurrentTripGreeter> {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import 'package:anyway/modules/landmark_card.dart';
|
|||||||
|
|
||||||
// Returns a list of widgets that represent the landmarks matching the given selector
|
// Returns a list of widgets that represent the landmarks matching the given selector
|
||||||
List<Widget> landmarksList(Trip trip, {required bool Function(Landmark) selector}) {
|
List<Widget> landmarksList(Trip trip, {required bool Function(Landmark) selector}) {
|
||||||
|
|
||||||
List<Widget> children = [];
|
List<Widget> children = [];
|
||||||
|
|
||||||
if (trip.landmarks.isEmpty || trip.landmarks.length <= 1 && trip.landmarks.first.type == typeStart ) {
|
if (trip.landmarks.isEmpty || trip.landmarks.length <= 1 && trip.landmarks.first.type == typeStart ) {
|
||||||
@@ -30,10 +30,10 @@ List<Widget> landmarksList(Trip trip, {required bool Function(Landmark) selector
|
|||||||
Landmark? nextLandmark = landmark.next;
|
Landmark? nextLandmark = landmark.next;
|
||||||
while (nextLandmark != null && nextLandmark.visited) {
|
while (nextLandmark != null && nextLandmark.visited) {
|
||||||
nextLandmark = nextLandmark.next;
|
nextLandmark = nextLandmark.next;
|
||||||
}
|
}
|
||||||
if (nextLandmark != null) {
|
if (nextLandmark != null) {
|
||||||
children.add(
|
children.add(
|
||||||
StepBetweenLandmarks(current: landmark, next: nextLandmark!)
|
StepBetweenLandmarks(current: landmark, next: nextLandmark)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class _CurrentTripLoadingIndicatorState extends State<CurrentTripLoadingIndicato
|
|||||||
|
|
||||||
// automatically cycle through the greeter texts
|
// automatically cycle through the greeter texts
|
||||||
class StatusText extends StatefulWidget {
|
class StatusText extends StatefulWidget {
|
||||||
const StatusText({Key? key}) : super(key: key);
|
const StatusText({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_StatusTextState createState() => _StatusTextState();
|
_StatusTextState createState() => _StatusTextState();
|
||||||
@@ -110,10 +110,10 @@ class AnimatedDotsText extends StatefulWidget {
|
|||||||
final TextStyle style;
|
final TextStyle style;
|
||||||
|
|
||||||
const AnimatedDotsText({
|
const AnimatedDotsText({
|
||||||
Key? key,
|
super.key,
|
||||||
required this.baseText,
|
required this.baseText,
|
||||||
required this.style,
|
required this.style,
|
||||||
}) : super(key: key);
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_AnimatedDotsTextState createState() => _AnimatedDotsTextState();
|
_AnimatedDotsTextState createState() => _AnimatedDotsTextState();
|
||||||
|
|||||||
53
frontend/lib/modules/current_trip_locations.dart
Normal file
53
frontend/lib/modules/current_trip_locations.dart
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:auto_size_text/auto_size_text.dart';
|
||||||
|
|
||||||
|
import 'package:anyway/structs/trip.dart';
|
||||||
|
|
||||||
|
|
||||||
|
List<Map<String, dynamic>> locationActions = [
|
||||||
|
{'name': 'Toilet', 'action': () {}},
|
||||||
|
{'name': 'Food', 'action': () {}},
|
||||||
|
{'name': 'Surrounding landmarks', 'action': () {}},
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
class CurrentTripLocations extends StatefulWidget {
|
||||||
|
final Trip? trip;
|
||||||
|
|
||||||
|
const CurrentTripLocations({super.key, this.trip});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<CurrentTripLocations> createState() => _CurrentTripLocationsState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CurrentTripLocationsState extends State<CurrentTripLocations> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
// A horizontally scrolling list of buttons with predefined actions
|
||||||
|
return SingleChildScrollView(
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 10.0),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
if (widget.trip != null)
|
||||||
|
for (Map action in locationActions)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 3.0),
|
||||||
|
child: ElevatedButton(
|
||||||
|
onPressed: action['action'],
|
||||||
|
child: AutoSizeText(
|
||||||
|
action['name'],
|
||||||
|
maxLines: 1,
|
||||||
|
minFontSize: 8,
|
||||||
|
maxFontSize: 16,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,7 +13,7 @@ import 'package:anyway/modules/landmark_map_marker.dart';
|
|||||||
class CurrentTripMap extends StatefulWidget {
|
class CurrentTripMap extends StatefulWidget {
|
||||||
final Trip? trip;
|
final Trip? trip;
|
||||||
|
|
||||||
CurrentTripMap({this.trip});
|
const CurrentTripMap({super.key, this.trip});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<CurrentTripMap> createState() => _CurrentTripMapState();
|
State<CurrentTripMap> createState() => _CurrentTripMapState();
|
||||||
@@ -22,7 +22,7 @@ class CurrentTripMap extends StatefulWidget {
|
|||||||
class _CurrentTripMapState extends State<CurrentTripMap> {
|
class _CurrentTripMapState extends State<CurrentTripMap> {
|
||||||
late GoogleMapController mapController;
|
late GoogleMapController mapController;
|
||||||
|
|
||||||
CameraPosition _cameraPosition = CameraPosition(
|
final CameraPosition _cameraPosition = const CameraPosition(
|
||||||
target: LatLng(48.8566, 2.3522),
|
target: LatLng(48.8566, 2.3522),
|
||||||
zoom: 11.0,
|
zoom: 11.0,
|
||||||
);
|
);
|
||||||
@@ -41,7 +41,7 @@ class _CurrentTripMapState extends State<CurrentTripMap> {
|
|||||||
void dispose() {
|
void dispose() {
|
||||||
widget.trip?.removeListener(setMapMarkers);
|
widget.trip?.removeListener(setMapMarkers);
|
||||||
widget.trip?.removeListener(setMapRoute);
|
widget.trip?.removeListener(setMapRoute);
|
||||||
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
31
frontend/lib/modules/current_trip_overview.dart
Normal file
31
frontend/lib/modules/current_trip_overview.dart
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import 'package:anyway/structs/trip.dart';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import 'package:anyway/modules/current_trip_map.dart';
|
||||||
|
import 'package:anyway/modules/current_trip_locations.dart';
|
||||||
|
|
||||||
|
|
||||||
|
class CurrentTripOverview extends StatefulWidget {
|
||||||
|
final Trip? trip;
|
||||||
|
|
||||||
|
const CurrentTripOverview({super.key, this.trip});
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<CurrentTripOverview> createState() => _CurrentTripOverviewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CurrentTripOverviewState extends State<CurrentTripOverview> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
// The background map has a horizontally scrolling list of rounded buttons overlaid
|
||||||
|
return Stack(
|
||||||
|
alignment: Alignment.topLeft,
|
||||||
|
children: [
|
||||||
|
CurrentTripMap(trip: widget.trip),
|
||||||
|
CurrentTripLocations(trip: widget.trip),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -45,7 +45,7 @@ class _CurrentTripPanelState extends State<CurrentTripPanel> {
|
|||||||
// this way the greeter will be centered when the panel is collapsed
|
// this way the greeter will be centered when the panel is collapsed
|
||||||
// note that we need to account for the padding above
|
// note that we need to account for the padding above
|
||||||
height: MediaQuery.of(context).size.height * TRIP_PANEL_MIN_HEIGHT - 10,
|
height: MediaQuery.of(context).size.height * TRIP_PANEL_MIN_HEIGHT - 10,
|
||||||
child: Center(child:
|
child: Center(child:
|
||||||
AutoSizeText(
|
AutoSizeText(
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
'Error',
|
'Error',
|
||||||
@@ -81,7 +81,7 @@ class _CurrentTripPanelState extends State<CurrentTripPanel> {
|
|||||||
),
|
),
|
||||||
|
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.all(10),
|
padding: const EdgeInsets.all(10),
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.grey[100],
|
color: Colors.grey[100],
|
||||||
@@ -94,9 +94,6 @@ class _CurrentTripPanelState extends State<CurrentTripPanel> {
|
|||||||
ExpansionTile(
|
ExpansionTile(
|
||||||
leading: const Icon(Icons.location_on),
|
leading: const Icon(Icons.location_on),
|
||||||
title: const Text('Visited Landmarks (tap to expand)'),
|
title: const Text('Visited Landmarks (tap to expand)'),
|
||||||
children: [
|
|
||||||
...landmarksList(widget.trip, selector: (Landmark landmark) => landmark.visited),
|
|
||||||
],
|
|
||||||
visualDensity: VisualDensity.compact,
|
visualDensity: VisualDensity.compact,
|
||||||
collapsedShape: RoundedRectangleBorder(
|
collapsedShape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
@@ -104,12 +101,15 @@ class _CurrentTripPanelState extends State<CurrentTripPanel> {
|
|||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
),
|
),
|
||||||
|
children: [
|
||||||
|
...landmarksList(widget.trip, selector: (Landmark landmark) => landmark.visited),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
|
||||||
const Padding(padding: EdgeInsets.only(top: 10)),
|
const Padding(padding: EdgeInsets.only(top: 10)),
|
||||||
|
|
||||||
|
|||||||
@@ -20,14 +20,14 @@ class _saveButtonState extends State<saveButton> {
|
|||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
savedTrips.addTrip(widget.trip);
|
savedTrips.addTrip(widget.trip);
|
||||||
rootScaffoldMessengerKey.currentState!.showSnackBar(
|
rootScaffoldMessengerKey.currentState!.showSnackBar(
|
||||||
SnackBar(
|
const SnackBar(
|
||||||
content: Text('Trip saved'),
|
content: Text('Trip saved'),
|
||||||
duration: Duration(seconds: 2),
|
duration: Duration(seconds: 2),
|
||||||
dismissDirection: DismissDirection.horizontal
|
dismissDirection: DismissDirection.horizontal
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: SizedBox(
|
child: const SizedBox(
|
||||||
width: 100,
|
width: 100,
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
|||||||
@@ -13,12 +13,12 @@ import 'package:anyway/structs/landmark.dart';
|
|||||||
class LandmarkCard extends StatefulWidget {
|
class LandmarkCard extends StatefulWidget {
|
||||||
final Landmark landmark;
|
final Landmark landmark;
|
||||||
final Trip parentTrip;
|
final Trip parentTrip;
|
||||||
|
|
||||||
LandmarkCard(
|
const LandmarkCard(
|
||||||
this.landmark,
|
this.landmark,
|
||||||
this.parentTrip,
|
this.parentTrip,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_LandmarkCardState createState() => _LandmarkCardState();
|
_LandmarkCardState createState() => _LandmarkCardState();
|
||||||
}
|
}
|
||||||
@@ -26,7 +26,7 @@ class LandmarkCard extends StatefulWidget {
|
|||||||
|
|
||||||
class _LandmarkCardState extends State<LandmarkCard> {
|
class _LandmarkCardState extends State<LandmarkCard> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
// express the max height in terms text lines
|
// express the max height in terms text lines
|
||||||
@@ -38,7 +38,7 @@ class _LandmarkCardState extends State<LandmarkCard> {
|
|||||||
),
|
),
|
||||||
elevation: 5,
|
elevation: 5,
|
||||||
clipBehavior: Clip.antiAliasWithSaveLayer,
|
clipBehavior: Clip.antiAliasWithSaveLayer,
|
||||||
|
|
||||||
// if the image is available, display it on the left side of the card, otherwise only display the text
|
// if the image is available, display it on the left side of the card, otherwise only display the text
|
||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@@ -66,11 +66,11 @@ class _LandmarkCardState extends State<LandmarkCard> {
|
|||||||
color: PRIMARY_COLOR,
|
color: PRIMARY_COLOR,
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.all(5),
|
padding: const EdgeInsets.all(5),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Icon(Icons.timer_outlined, size: 16),
|
const Icon(Icons.timer_outlined, size: 16),
|
||||||
Text("${widget.landmark.duration?.inMinutes} minutes"),
|
Text("${widget.landmark.duration?.inMinutes} minutes"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@@ -97,7 +97,7 @@ class _LandmarkCardState extends State<LandmarkCard> {
|
|||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
),
|
),
|
||||||
|
|
||||||
if (widget.landmark.nameEN != null)
|
if (widget.landmark.nameEN != null)
|
||||||
Text(
|
Text(
|
||||||
widget.landmark.nameEN!,
|
widget.landmark.nameEN!,
|
||||||
@@ -114,7 +114,7 @@ class _LandmarkCardState extends State<LandmarkCard> {
|
|||||||
|
|
||||||
SingleChildScrollView(
|
SingleChildScrollView(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
padding: EdgeInsets.only(left: 5, right: 5, bottom: 10),
|
padding: const EdgeInsets.only(left: 5, right: 5, bottom: 10),
|
||||||
// the scroll view should be flush once the buttons are scrolled to the left
|
// the scroll view should be flush once the buttons are scrolled to the left
|
||||||
// but initially there should be some padding
|
// but initially there should be some padding
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
@@ -124,7 +124,7 @@ class _LandmarkCardState extends State<LandmarkCard> {
|
|||||||
doneToggleButton(),
|
doneToggleButton(),
|
||||||
if (widget.landmark.websiteURL != null)
|
if (widget.landmark.websiteURL != null)
|
||||||
websiteButton(),
|
websiteButton(),
|
||||||
|
|
||||||
optionsButton()
|
optionsButton()
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -181,7 +181,7 @@ class _LandmarkCardState extends State<LandmarkCard> {
|
|||||||
title: const Text('Favorite'),
|
title: const Text('Favorite'),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
rootScaffoldMessengerKey.currentState!.showSnackBar(
|
rootScaffoldMessengerKey.currentState!.showSnackBar(
|
||||||
SnackBar(content: Text("Not implemented yet"))
|
const SnackBar(content: Text("Not implemented yet"))
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -193,7 +193,7 @@ class _LandmarkCardState extends State<LandmarkCard> {
|
|||||||
|
|
||||||
|
|
||||||
Widget imagePlaceholder (Landmark landmark) => Expanded(
|
Widget imagePlaceholder (Landmark landmark) => Expanded(
|
||||||
child:
|
child:
|
||||||
Container(
|
Container(
|
||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
gradient: LinearGradient(
|
gradient: LinearGradient(
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ class ThemedMarker extends StatelessWidget {
|
|||||||
final Landmark landmark;
|
final Landmark landmark;
|
||||||
final int position;
|
final int position;
|
||||||
|
|
||||||
ThemedMarker({
|
const ThemedMarker({
|
||||||
super.key,
|
super.key,
|
||||||
required this.landmark,
|
required this.landmark,
|
||||||
required this.position
|
required this.position
|
||||||
@@ -24,12 +24,12 @@ class ThemedMarker extends StatelessWidget {
|
|||||||
top: 0,
|
top: 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: EdgeInsets.all(5),
|
padding: const EdgeInsets.all(5),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.grey[100],
|
color: Colors.grey[100],
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
),
|
),
|
||||||
child: Text('$position', style: TextStyle(color: Colors.black, fontSize: 25)),
|
child: Text('$position', style: const TextStyle(color: Colors.black, fontSize: 25)),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -40,7 +40,7 @@ class ThemedMarker extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
gradient: landmark.visited ? LinearGradient(colors: [Colors.grey, Colors.white]) : APP_GRADIENT,
|
gradient: landmark.visited ? const LinearGradient(colors: [Colors.grey, Colors.white]) : APP_GRADIENT,
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
border: Border.all(color: Colors.black, width: 5),
|
border: Border.all(color: Colors.black, width: 5),
|
||||||
),
|
),
|
||||||
@@ -54,4 +54,4 @@ class ThemedMarker extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class NewTripButton extends StatefulWidget {
|
|||||||
final Trip trip;
|
final Trip trip;
|
||||||
final UserPreferences preferences;
|
final UserPreferences preferences;
|
||||||
|
|
||||||
const NewTripButton({
|
const NewTripButton({super.key,
|
||||||
required this.trip,
|
required this.trip,
|
||||||
required this.preferences,
|
required this.preferences,
|
||||||
});
|
});
|
||||||
@@ -35,8 +35,8 @@ class _NewTripButtonState extends State<NewTripButton> {
|
|||||||
return FloatingActionButton.extended(
|
return FloatingActionButton.extended(
|
||||||
onPressed: onPressed,
|
onPressed: onPressed,
|
||||||
icon: const Icon(Icons.directions),
|
icon: const Icon(Icons.directions),
|
||||||
label: AutoSizeText('Start planning!'),
|
label: const AutoSizeText('Start planning!'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ const Map<String, List> debugLocations = {
|
|||||||
class NewTripLocationSearch extends StatefulWidget {
|
class NewTripLocationSearch extends StatefulWidget {
|
||||||
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
|
Future<SharedPreferences> prefs = SharedPreferences.getInstance();
|
||||||
Trip trip;
|
Trip trip;
|
||||||
|
|
||||||
NewTripLocationSearch(
|
NewTripLocationSearch(
|
||||||
this.trip,
|
this.trip,
|
||||||
);
|
);
|
||||||
@@ -71,13 +71,13 @@ class _NewTripLocationSearchState extends State<NewTripLocationSearch> {
|
|||||||
hintText: 'Enter a city name or long press on the map.',
|
hintText: 'Enter a city name or long press on the map.',
|
||||||
onSubmitted: setTripLocation,
|
onSubmitted: setTripLocation,
|
||||||
controller: _controller,
|
controller: _controller,
|
||||||
leading: Icon(Icons.search),
|
leading: const Icon(Icons.search),
|
||||||
trailing: [
|
trailing: [
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
setTripLocation(_controller.text);
|
setTripLocation(_controller.text);
|
||||||
},
|
},
|
||||||
child: Text('Search'),
|
child: const Text('Search'),
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
@@ -97,7 +97,7 @@ class _NewTripLocationSearchState extends State<NewTripLocationSearch> {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: Text('Use current location'),
|
child: const Text('Use current location'),
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -106,4 +106,4 @@ class _NewTripMapState extends State<NewTripMap> {
|
|||||||
myLocationEnabled: useLocation,
|
myLocationEnabled: useLocation,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import 'package:flutter/material.dart';
|
|||||||
class NewTripOptionsButton extends StatefulWidget {
|
class NewTripOptionsButton extends StatefulWidget {
|
||||||
final Trip trip;
|
final Trip trip;
|
||||||
|
|
||||||
const NewTripOptionsButton({required this.trip});
|
const NewTripOptionsButton({super.key, required this.trip});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<NewTripOptionsButton> createState() => _NewTripOptionsButtonState();
|
State<NewTripOptionsButton> createState() => _NewTripOptionsButtonState();
|
||||||
@@ -33,7 +33,7 @@ class _NewTripOptionsButtonState extends State<NewTripOptionsButton> {
|
|||||||
},
|
},
|
||||||
icon: const Icon(Icons.add),
|
icon: const Icon(Icons.add),
|
||||||
label: const AutoSizeText('Set preferences')
|
label: const AutoSizeText('Set preferences')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ class OnboardingAgreementCard extends StatefulWidget {
|
|||||||
final ValueChanged<bool> onAgreementChanged;
|
final ValueChanged<bool> onAgreementChanged;
|
||||||
|
|
||||||
|
|
||||||
OnboardingAgreementCard({
|
const OnboardingAgreementCard({
|
||||||
super.key,
|
super.key,
|
||||||
required this.title,
|
required this.title,
|
||||||
required this.description,
|
required this.description,
|
||||||
required this.imagePath,
|
required this.imagePath,
|
||||||
@@ -30,12 +30,12 @@ class _OnboardingAgreementCardState extends State<OnboardingAgreementCard> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: EdgeInsets.all(20),
|
padding: const EdgeInsets.all(20),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
OnboardingCard(title: widget.title, description: widget.description, imagePath: widget.imagePath),
|
OnboardingCard(title: widget.title, description: widget.description, imagePath: widget.imagePath),
|
||||||
Padding(padding: EdgeInsets.only(top: 20)),
|
const Padding(padding: EdgeInsets.only(top: 20)),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
@@ -65,7 +65,7 @@ class _OnboardingAgreementCardState extends State<OnboardingAgreementCard> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
// The text of the agreement
|
// The text of the agreement
|
||||||
Text(
|
Text(
|
||||||
"I agree to the ",
|
"I agree to the ",
|
||||||
@@ -73,7 +73,7 @@ class _OnboardingAgreementCardState extends State<OnboardingAgreementCard> {
|
|||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
// The clickable text of the agreement that shows the agreement text
|
// The clickable text of the agreement that shows the agreement text
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
@@ -91,9 +91,9 @@ class _OnboardingAgreementCardState extends State<OnboardingAgreementCard> {
|
|||||||
data: snapshot.data.toString(),
|
data: snapshot.data.toString(),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return CircularProgressIndicator();
|
return const CircularProgressIndicator();
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ class OnboardingCard extends StatelessWidget {
|
|||||||
final String description;
|
final String description;
|
||||||
final String imagePath;
|
final String imagePath;
|
||||||
|
|
||||||
const OnboardingCard({
|
const OnboardingCard({super.key,
|
||||||
required this.title,
|
required this.title,
|
||||||
required this.description,
|
required this.description,
|
||||||
required this.imagePath,
|
required this.imagePath,
|
||||||
@@ -14,9 +14,9 @@ class OnboardingCard extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: EdgeInsets.all(20),
|
padding: const EdgeInsets.all(20),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
@@ -26,12 +26,12 @@ class OnboardingCard extends StatelessWidget {
|
|||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(padding: EdgeInsets.only(top: 20)),
|
const Padding(padding: EdgeInsets.only(top: 20)),
|
||||||
SvgPicture.asset(
|
SvgPicture.asset(
|
||||||
imagePath,
|
imagePath,
|
||||||
height: 200,
|
height: 200,
|
||||||
),
|
),
|
||||||
Padding(padding: EdgeInsets.only(top: 20)),
|
const Padding(padding: EdgeInsets.only(top: 20)),
|
||||||
Text(
|
Text(
|
||||||
description,
|
description,
|
||||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||||
|
|||||||
@@ -17,48 +17,78 @@ class TripsOverview extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _TripsOverviewState extends State<TripsOverview> {
|
class _TripsOverviewState extends State<TripsOverview> {
|
||||||
Widget listBuild (BuildContext context, SavedTrips trips) {
|
Widget tripListItemBuilder(BuildContext context, int index) {
|
||||||
List<Widget> children;
|
Trip trip = widget.trips.trips[index];
|
||||||
List<Trip> items = trips.trips;
|
return ListTile(
|
||||||
children = List<Widget>.generate(items.length, (index) {
|
title: FutureBuilder(
|
||||||
Trip trip = items[index];
|
future: trip.cityName,
|
||||||
return ListTile(
|
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
|
||||||
title: FutureBuilder(
|
if (snapshot.hasData) {
|
||||||
future: trip.cityName,
|
return Text("Trip to ${snapshot.data}");
|
||||||
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
|
} else if (snapshot.hasError) {
|
||||||
if (snapshot.hasData) {
|
return Text("Error: ${snapshot.error}");
|
||||||
return Text("Trip to ${snapshot.data}");
|
} else {
|
||||||
} else if (snapshot.hasError) {
|
return const Text("Trip to ...");
|
||||||
return Text("Error: ${snapshot.error}");
|
}
|
||||||
} else {
|
|
||||||
return const Text("Trip to ...");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
leading: Icon(Icons.pin_drop),
|
|
||||||
onTap: () {
|
|
||||||
Navigator.of(context).push(
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => TripPage(trip: trip)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
);
|
),
|
||||||
});
|
// emoji of the country flag of the trip's country
|
||||||
|
leading: const Icon(Icons.pin_drop),
|
||||||
|
|
||||||
return ListView(
|
onTap: () {
|
||||||
children: children,
|
Navigator.of(context).push(
|
||||||
padding: const EdgeInsets.only(top: 0),
|
MaterialPageRoute(
|
||||||
|
builder: (context) => TripPage(trip: trip)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Widget listBuild (BuildContext context, SavedTrips trips) {
|
||||||
|
// List<Widget> children;
|
||||||
|
// List<Trip> items = trips.trips;
|
||||||
|
// children = List<Widget>.generate(items.length, (index) {
|
||||||
|
// Trip trip = items[index];
|
||||||
|
// return ListTile(
|
||||||
|
// title: FutureBuilder(
|
||||||
|
// future: trip.cityName,
|
||||||
|
// builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
|
||||||
|
// if (snapshot.hasData) {
|
||||||
|
// return Text("Trip to ${snapshot.data}");
|
||||||
|
// } else if (snapshot.hasError) {
|
||||||
|
// return Text("Error: ${snapshot.error}");
|
||||||
|
// } else {
|
||||||
|
// return const Text("Trip to ...");
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
// leading: const Icon(Icons.pin_drop),
|
||||||
|
// onTap: () {
|
||||||
|
// Navigator.of(context).push(
|
||||||
|
// MaterialPageRoute(
|
||||||
|
// builder: (context) => TripPage(trip: trip)
|
||||||
|
// )
|
||||||
|
// );
|
||||||
|
// },
|
||||||
|
// );
|
||||||
|
// });
|
||||||
|
|
||||||
|
// return ListView(
|
||||||
|
// padding: const EdgeInsets.only(top: 0),
|
||||||
|
// children: children,
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ListenableBuilder(
|
return ListenableBuilder(
|
||||||
listenable: widget.trips,
|
listenable: widget.trips,
|
||||||
builder: (BuildContext context, Widget? child) {
|
builder: (BuildContext context, Widget? child) => ListView.builder(
|
||||||
return listBuild(context, widget.trips);
|
itemCount: widget.trips.trips.length,
|
||||||
}
|
itemBuilder: tripListItemBuilder,
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:sliding_up_panel/sliding_up_panel.dart';
|
import 'package:sliding_up_panel/sliding_up_panel.dart';
|
||||||
|
|
||||||
import 'package:anyway/structs/trip.dart';
|
import 'package:anyway/structs/trip.dart';
|
||||||
import 'package:anyway/modules/current_trip_map.dart';
|
import 'package:anyway/modules/current_trip_overview.dart';
|
||||||
import 'package:anyway/modules/current_trip_panel.dart';
|
import 'package:anyway/modules/current_trip_panel.dart';
|
||||||
|
|
||||||
final Shader textGradient = APP_GRADIENT.createShader(Rect.fromLTWH(0.0, 0.0, 200.0, 70.0));
|
final Shader textGradient = APP_GRADIENT.createShader(const Rect.fromLTWH(0.0, 0.0, 200.0, 70.0));
|
||||||
TextStyle greeterStyle = TextStyle(
|
TextStyle greeterStyle = TextStyle(
|
||||||
foreground: Paint()..shader = textGradient,
|
foreground: Paint()..shader = textGradient,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
@@ -18,7 +18,7 @@ TextStyle greeterStyle = TextStyle(
|
|||||||
class TripPage extends StatefulWidget {
|
class TripPage extends StatefulWidget {
|
||||||
final Trip trip;
|
final Trip trip;
|
||||||
|
|
||||||
TripPage({
|
const TripPage({super.key,
|
||||||
required this.trip,
|
required this.trip,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ class _TripPageState extends State<TripPage> with ScaffoldLayout{
|
|||||||
panelBuilder: (scrollcontroller) => CurrentTripPanel(controller: scrollcontroller, trip: widget.trip),
|
panelBuilder: (scrollcontroller) => CurrentTripPanel(controller: scrollcontroller, trip: widget.trip),
|
||||||
// using collapsed and panelBuilder seems to show both at the same time, so we include the greeter in the panelBuilder
|
// using collapsed and panelBuilder seems to show both at the same time, so we include the greeter in the panelBuilder
|
||||||
// collapsed: Greeter(trip: widget.trip),
|
// collapsed: Greeter(trip: widget.trip),
|
||||||
body: CurrentTripMap(trip: widget.trip),
|
body: CurrentTripOverview(trip: widget.trip),
|
||||||
minHeight: MediaQuery.of(context).size.height * TRIP_PANEL_MIN_HEIGHT,
|
minHeight: MediaQuery.of(context).size.height * TRIP_PANEL_MIN_HEIGHT,
|
||||||
maxHeight: MediaQuery.of(context).size.height * TRIP_PANEL_MAX_HEIGHT,
|
maxHeight: MediaQuery.of(context).size.height * TRIP_PANEL_MAX_HEIGHT,
|
||||||
// padding in this context is annoying: it offsets the notion of vertical alignment.
|
// padding in this context is annoying: it offsets the notion of vertical alignment.
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import 'package:anyway/modules/new_trip_map.dart';
|
|||||||
|
|
||||||
|
|
||||||
class NewTripPage extends StatefulWidget {
|
class NewTripPage extends StatefulWidget {
|
||||||
const NewTripPage({Key? key}) : super(key: key);
|
const NewTripPage({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_NewTripPageState createState() => _NewTripPageState();
|
_NewTripPageState createState() => _NewTripPageState();
|
||||||
@@ -30,14 +30,14 @@ class _NewTripPageState extends State<NewTripPage> with ScaffoldLayout {
|
|||||||
children: [
|
children: [
|
||||||
NewTripMap(trip),
|
NewTripMap(trip),
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.all(15),
|
padding: const EdgeInsets.all(15),
|
||||||
child: NewTripLocationSearch(trip),
|
child: NewTripLocationSearch(trip),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
floatingActionButton: NewTripOptionsButton(trip: trip),
|
floatingActionButton: NewTripOptionsButton(trip: trip),
|
||||||
),
|
),
|
||||||
title: Text("New Trip"),
|
title: const Text("New Trip"),
|
||||||
helpTexts: [
|
helpTexts: [
|
||||||
"Setting the start location",
|
"Setting the start location",
|
||||||
"To set the starting point, type a city name in the search bar. You can also navigate the map like you're used to and long press anywhere to set a starting point."
|
"To set the starting point, type a city name in the search bar. You can also navigate the map like you're used to and long press anywhere to set a starting point."
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import 'package:flutter/material.dart';
|
|||||||
|
|
||||||
class NewTripPreferencesPage extends StatefulWidget {
|
class NewTripPreferencesPage extends StatefulWidget {
|
||||||
final Trip trip;
|
final Trip trip;
|
||||||
const NewTripPreferencesPage({required this.trip});
|
const NewTripPreferencesPage({super.key, required this.trip});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_NewTripPreferencesPageState createState() => _NewTripPreferencesPageState();
|
_NewTripPreferencesPageState createState() => _NewTripPreferencesPageState();
|
||||||
@@ -34,14 +34,14 @@ class _NewTripPreferencesPageState extends State<NewTripPreferencesPage> with Sc
|
|||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
body: ListView(
|
body: ListView(
|
||||||
children: [
|
children: [
|
||||||
Center(
|
const Center(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.only(left: 10, right: 10, top: 20, bottom: 0),
|
padding: EdgeInsets.only(left: 10, right: 10, top: 20, bottom: 0),
|
||||||
child: Text('Tell us about your ideal trip.', style: TextStyle(fontSize: 18))
|
child: Text('Tell us about your ideal trip.', style: TextStyle(fontSize: 18))
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
Divider(indent: 25, endIndent: 25, height: 50),
|
const Divider(indent: 25, endIndent: 25, height: 50),
|
||||||
|
|
||||||
durationPicker(preferences.maxTime),
|
durationPicker(preferences.maxTime),
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ class _NewTripPreferencesPageState extends State<NewTripPreferencesPage> with Sc
|
|||||||
title: Text(preferences.maxTime.description),
|
title: Text(preferences.maxTime.description),
|
||||||
subtitle: CupertinoTimerPicker(
|
subtitle: CupertinoTimerPicker(
|
||||||
mode: CupertinoTimerPickerMode.hm,
|
mode: CupertinoTimerPickerMode.hm,
|
||||||
initialTimerDuration: Duration(minutes: 90),
|
initialTimerDuration: const Duration(minutes: 90),
|
||||||
minuteInterval: 15,
|
minuteInterval: 15,
|
||||||
onTimerDurationChanged: (Duration newDuration) {
|
onTimerDurationChanged: (Duration newDuration) {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class _NoTripsPageState extends State<NoTripsPage> with ScaffoldLayout {
|
|||||||
style: Theme.of(context).textTheme.headlineMedium,
|
style: Theme.of(context).textTheme.headlineMedium,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
Padding(padding: EdgeInsets.only(bottom: 10)),
|
const Padding(padding: EdgeInsets.only(bottom: 10)),
|
||||||
Text(
|
Text(
|
||||||
"You can start a new trip by clicking the button below",
|
"You can start a new trip by clicking the button below",
|
||||||
style: Theme.of(context).textTheme.bodyMedium,
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
@@ -50,4 +50,4 @@ class _NoTripsPageState extends State<NoTripsPage> with ScaffoldLayout {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,9 +116,9 @@ class _OnboardingPageState extends State<OnboardingPage> {
|
|||||||
if ((_controller.hasClients ? (_controller.page ?? _controller.initialPage) : 0) != fullCards.length - 1) {
|
if ((_controller.hasClients ? (_controller.page ?? _controller.initialPage) : 0) != fullCards.length - 1) {
|
||||||
return FloatingActionButton.extended(
|
return FloatingActionButton.extended(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
controller.nextPage(duration: Duration(milliseconds: 500), curve: Curves.ease);
|
controller.nextPage(duration: const Duration(milliseconds: 500), curve: Curves.ease);
|
||||||
},
|
},
|
||||||
label: Icon(Icons.arrow_forward)
|
label: const Icon(Icons.arrow_forward)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// only allow the user to proceed if they have agreed to the terms and conditions
|
// only allow the user to proceed if they have agreed to the terms and conditions
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import 'package:anyway/layouts/scaffold.dart';
|
|||||||
bool debugMode = false;
|
bool debugMode = false;
|
||||||
|
|
||||||
class SettingsPage extends StatefulWidget {
|
class SettingsPage extends StatefulWidget {
|
||||||
|
const SettingsPage({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_SettingsPageState createState() => _SettingsPageState();
|
_SettingsPageState createState() => _SettingsPageState();
|
||||||
}
|
}
|
||||||
@@ -20,31 +22,31 @@ class _SettingsPageState extends State<SettingsPage> with ScaffoldLayout {
|
|||||||
Widget build (BuildContext context) => mainScaffold(
|
Widget build (BuildContext context) => mainScaffold(
|
||||||
context,
|
context,
|
||||||
child: ListView(
|
child: ListView(
|
||||||
padding: EdgeInsets.all(15),
|
padding: const EdgeInsets.all(15),
|
||||||
children: [
|
children: [
|
||||||
// First a round, centered image
|
// First a round, centered image
|
||||||
Center(
|
const Center(
|
||||||
child: CircleAvatar(
|
child: CircleAvatar(
|
||||||
radius: 75,
|
radius: 75,
|
||||||
child: Icon(Icons.settings, size: 100),
|
child: Icon(Icons.settings, size: 100),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
Center(
|
const Center(
|
||||||
child: Text('Global settings', style: TextStyle(fontSize: 24))
|
child: Text('Global settings', style: TextStyle(fontSize: 24))
|
||||||
),
|
),
|
||||||
|
|
||||||
Divider(indent: 25, endIndent: 25, height: 50),
|
const Divider(indent: 25, endIndent: 25, height: 50),
|
||||||
|
|
||||||
darkMode(),
|
darkMode(),
|
||||||
setLocationUsage(),
|
setLocationUsage(),
|
||||||
setDebugMode(),
|
setDebugMode(),
|
||||||
|
|
||||||
Divider(indent: 25, endIndent: 25, height: 50),
|
const Divider(indent: 25, endIndent: 25, height: 50),
|
||||||
|
|
||||||
privacyInfo(),
|
privacyInfo(),
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
title: Text('Settings'),
|
title: const Text('Settings'),
|
||||||
helpTexts: [
|
helpTexts: [
|
||||||
'Settings',
|
'Settings',
|
||||||
'Preferences set in this page are global and will affect the entire application.'
|
'Preferences set in this page are global and will affect the entire application.'
|
||||||
@@ -54,9 +56,9 @@ class _SettingsPageState extends State<SettingsPage> with ScaffoldLayout {
|
|||||||
Widget setDebugMode() {
|
Widget setDebugMode() {
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
Text('Debugging: use a custom API URL'),
|
const Text('Debugging: use a custom API URL'),
|
||||||
// white space
|
// white space
|
||||||
Spacer(),
|
const Spacer(),
|
||||||
Switch(
|
Switch(
|
||||||
value: debugMode,
|
value: debugMode,
|
||||||
onChanged: (bool? newValue) {
|
onChanged: (bool? newValue) {
|
||||||
@@ -67,7 +69,7 @@ class _SettingsPageState extends State<SettingsPage> with ScaffoldLayout {
|
|||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
title: Text('Debug mode - use a custom API endpoint'),
|
title: const Text('Debug mode - use a custom API endpoint'),
|
||||||
content: TextField(
|
content: TextField(
|
||||||
controller: TextEditingController(text: API_URL_DEBUG),
|
controller: TextEditingController(text: API_URL_DEBUG),
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
@@ -78,7 +80,7 @@ class _SettingsPageState extends State<SettingsPage> with ScaffoldLayout {
|
|||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
child: Text('OK'),
|
child: const Text('OK'),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
},
|
},
|
||||||
@@ -98,14 +100,14 @@ class _SettingsPageState extends State<SettingsPage> with ScaffoldLayout {
|
|||||||
Widget darkMode() {
|
Widget darkMode() {
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
Text('Dark mode'),
|
const Text('Dark mode'),
|
||||||
Spacer(),
|
const Spacer(),
|
||||||
Switch(
|
Switch(
|
||||||
value: Theme.of(context).brightness == Brightness.dark,
|
value: Theme.of(context).brightness == Brightness.dark,
|
||||||
onChanged: (bool? newValue) {
|
onChanged: (bool? newValue) {
|
||||||
setState(() {
|
setState(() {
|
||||||
rootScaffoldMessengerKey.currentState!.showSnackBar(
|
rootScaffoldMessengerKey.currentState!.showSnackBar(
|
||||||
SnackBar(content: Text('Dark mode is not implemented yet'))
|
const SnackBar(content: Text('Dark mode is not implemented yet'))
|
||||||
);
|
);
|
||||||
// if (newValue!) {
|
// if (newValue!) {
|
||||||
// // Dark mode
|
// // Dark mode
|
||||||
@@ -125,9 +127,9 @@ class _SettingsPageState extends State<SettingsPage> with ScaffoldLayout {
|
|||||||
Future<SharedPreferences> preferences = SharedPreferences.getInstance();
|
Future<SharedPreferences> preferences = SharedPreferences.getInstance();
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
Text('Use location services'),
|
const Text('Use location services'),
|
||||||
// white space
|
// white space
|
||||||
Spacer(),
|
const Spacer(),
|
||||||
FutureBuilder(
|
FutureBuilder(
|
||||||
future: preferences,
|
future: preferences,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
@@ -138,7 +140,7 @@ class _SettingsPageState extends State<SettingsPage> with ScaffoldLayout {
|
|||||||
onChanged: setUseLocation,
|
onChanged: setUseLocation,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return CircularProgressIndicator();
|
return const CircularProgressIndicator();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -150,12 +152,12 @@ class _SettingsPageState extends State<SettingsPage> with ScaffoldLayout {
|
|||||||
await Permission.locationWhenInUse
|
await Permission.locationWhenInUse
|
||||||
.onDeniedCallback(() {
|
.onDeniedCallback(() {
|
||||||
rootScaffoldMessengerKey.currentState!.showSnackBar(
|
rootScaffoldMessengerKey.currentState!.showSnackBar(
|
||||||
SnackBar(content: Text('Location services are required for this feature'))
|
const SnackBar(content: Text('Location services are required for this feature'))
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
.onGrantedCallback(() {
|
.onGrantedCallback(() {
|
||||||
rootScaffoldMessengerKey.currentState!.showSnackBar(
|
rootScaffoldMessengerKey.currentState!.showSnackBar(
|
||||||
SnackBar(content: Text('Location services are now enabled'))
|
const SnackBar(content: Text('Location services are now enabled'))
|
||||||
);
|
);
|
||||||
SharedPreferences.getInstance().then(
|
SharedPreferences.getInstance().then(
|
||||||
(SharedPreferences prefs) {
|
(SharedPreferences prefs) {
|
||||||
@@ -167,9 +169,9 @@ class _SettingsPageState extends State<SettingsPage> with ScaffoldLayout {
|
|||||||
})
|
})
|
||||||
.onPermanentlyDeniedCallback(() {
|
.onPermanentlyDeniedCallback(() {
|
||||||
rootScaffoldMessengerKey.currentState!.showSnackBar(
|
rootScaffoldMessengerKey.currentState!.showSnackBar(
|
||||||
SnackBar(content: Text('Location services are required for this feature'))
|
const SnackBar(content: Text('Location services are required for this feature'))
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
.request();
|
.request();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,12 +179,12 @@ class _SettingsPageState extends State<SettingsPage> with ScaffoldLayout {
|
|||||||
return Center(
|
return Center(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Text('AnyWay does not collect or store any of the data that is submitted via the app. The location of your trip is not stored. The location feature is only used to show your current location on the map.', textAlign: TextAlign.center),
|
const Text('AnyWay does not collect or store any of the data that is submitted via the app. The location of your trip is not stored. The location feature is only used to show your current location on the map.', textAlign: TextAlign.center),
|
||||||
Padding(padding: EdgeInsets.only(top: 3)),
|
const Padding(padding: EdgeInsets.only(top: 3)),
|
||||||
Text('Our full privacy policy is available under:', textAlign: TextAlign.center),
|
const Text('Our full privacy policy is available under:', textAlign: TextAlign.center),
|
||||||
|
|
||||||
TextButton.icon(
|
TextButton.icon(
|
||||||
icon: Icon(Icons.info),
|
icon: const Icon(Icons.info),
|
||||||
label: Text(PRIVACY_URL),
|
label: Text(PRIVACY_URL),
|
||||||
onPressed: () async{
|
onPressed: () async{
|
||||||
await launchUrl(Uri.parse(PRIVACY_URL));
|
await launchUrl(Uri.parse(PRIVACY_URL));
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ class UserPreferences {
|
|||||||
value: 30,
|
value: 30,
|
||||||
minVal: 30,
|
minVal: 30,
|
||||||
maxVal: 720,
|
maxVal: 720,
|
||||||
icon: Icon(Icons.timer),
|
icon: const Icon(Icons.timer),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@@ -66,4 +66,4 @@ class UserPreferences {
|
|||||||
"max_time_minute": maxTime.value
|
"max_time_minute": maxTime.value
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class Trip with ChangeNotifier {
|
|||||||
String? errorDescription;
|
String? errorDescription;
|
||||||
|
|
||||||
Future<String> get cityName async {
|
Future<String> get cityName async {
|
||||||
List<double>? location = landmarks.firstOrNull?.location;
|
List<double>? location = landmarks.firstOrNull?.location;
|
||||||
if (GeocodingPlatform.instance == null) {
|
if (GeocodingPlatform.instance == null) {
|
||||||
return '$location';
|
return '$location';
|
||||||
} else if (location == null) {
|
} else if (location == null) {
|
||||||
@@ -48,7 +48,7 @@ class Trip with ChangeNotifier {
|
|||||||
LinkedList<Landmark>? landmarks
|
LinkedList<Landmark>? landmarks
|
||||||
// a trip can be created with no landmarks, but the list should be initialized anyway
|
// a trip can be created with no landmarks, but the list should be initialized anyway
|
||||||
}) : landmarks = landmarks ?? LinkedList<Landmark>();
|
}) : landmarks = landmarks ?? LinkedList<Landmark>();
|
||||||
|
|
||||||
|
|
||||||
factory Trip.fromJson(Map<String, dynamic> json) {
|
factory Trip.fromJson(Map<String, dynamic> json) {
|
||||||
Trip trip = Trip(
|
Trip trip = Trip(
|
||||||
@@ -82,11 +82,11 @@ class Trip with ChangeNotifier {
|
|||||||
// removing the landmark means we need to recompute the time between the two adjoined landmarks
|
// removing the landmark means we need to recompute the time between the two adjoined landmarks
|
||||||
if (previous != null && next != null) {
|
if (previous != null && next != null) {
|
||||||
// previous.next = next happens automatically since we are using a LinkedList
|
// previous.next = next happens automatically since we are using a LinkedList
|
||||||
this.totalTime -= previous.tripTime ?? Duration.zero;
|
totalTime -= previous.tripTime ?? Duration.zero;
|
||||||
previous.tripTime = null;
|
previous.tripTime = null;
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
this.totalTime -= landmark.tripTime ?? Duration.zero;
|
totalTime -= landmark.tripTime ?? Duration.zero;
|
||||||
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ Dio dio = Dio(
|
|||||||
validateStatus: (status) => status! <= 500,
|
validateStatus: (status) => status! <= 500,
|
||||||
receiveDataWhenStatusError: true,
|
receiveDataWhenStatusError: true,
|
||||||
contentType: Headers.jsonContentType,
|
contentType: Headers.jsonContentType,
|
||||||
responseType: ResponseType.json,
|
responseType: ResponseType.json,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ fetchTrip(
|
|||||||
) async {
|
) async {
|
||||||
Map<String, dynamic> data = {
|
Map<String, dynamic> data = {
|
||||||
"preferences": preferences.toJson(),
|
"preferences": preferences.toJson(),
|
||||||
"start": trip.landmarks!.first.location,
|
"start": trip.landmarks.first.location,
|
||||||
};
|
};
|
||||||
String dataString = jsonEncode(data);
|
String dataString = jsonEncode(data);
|
||||||
log(dataString);
|
log(dataString);
|
||||||
@@ -45,7 +45,7 @@ fetchTrip(
|
|||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
trip.updateUUID("error");
|
trip.updateUUID("error");
|
||||||
|
|
||||||
// Format the error message to be more user friendly
|
// Format the error message to be more user friendly
|
||||||
String errorDescription;
|
String errorDescription;
|
||||||
if (e is DioException) {
|
if (e is DioException) {
|
||||||
@@ -93,7 +93,7 @@ fetchTrip(
|
|||||||
// Actualy no need to throw an exception, we can just log the error and let the user retry
|
// Actualy no need to throw an exception, we can just log the error and let the user retry
|
||||||
// throw Exception(errorDetail);
|
// throw Exception(errorDetail);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// if the response data is not json, throw an error
|
// if the response data is not json, throw an error
|
||||||
if (response.data is! Map<String, dynamic>) {
|
if (response.data is! Map<String, dynamic>) {
|
||||||
log("${response.data.runtimeType}");
|
log("${response.data.runtimeType}");
|
||||||
@@ -142,7 +142,7 @@ patchLandmarkImage(Landmark landmark) async {
|
|||||||
// the image is a google photos link, we should get the image behind the link
|
// the image is a google photos link, we should get the image behind the link
|
||||||
String? newUrl = await getImageUrlFromGooglePhotos(landmark.imageURL!);
|
String? newUrl = await getImageUrlFromGooglePhotos(landmark.imageURL!);
|
||||||
// also set the new url if it is null
|
// also set the new url if it is null
|
||||||
landmark.imageURL = newUrl;
|
landmark.imageURL = newUrl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,28 +23,28 @@ Widget getFirstPage() {
|
|||||||
if (snapshot.connectionState == ConnectionState.done) {
|
if (snapshot.connectionState == ConnectionState.done) {
|
||||||
if (snapshot.hasData) {
|
if (snapshot.hasData) {
|
||||||
List<Trip> trips = snapshot.data!;
|
List<Trip> trips = snapshot.data!;
|
||||||
if (trips.length > 0) {
|
if (trips.isNotEmpty) {
|
||||||
return TripPage(trip: trips[0]);
|
return TripPage(trip: trips[0]);
|
||||||
} else {
|
} else {
|
||||||
return NoTripsPage();
|
return const NoTripsPage();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return OnboardingPage();
|
return const OnboardingPage();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return OnboardingPage();
|
return const OnboardingPage();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return OnboardingPage();
|
return const OnboardingPage();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: async
|
name: async
|
||||||
sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63
|
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.12.0"
|
version: "2.13.0"
|
||||||
auto_size_text:
|
auto_size_text:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -149,10 +149,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: fake_async
|
name: fake_async
|
||||||
sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc"
|
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.2"
|
version: "1.3.3"
|
||||||
ffi:
|
ffi:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -420,10 +420,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: leak_tracker
|
name: leak_tracker
|
||||||
sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec
|
sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "10.0.8"
|
version: "10.0.9"
|
||||||
leak_tracker_flutter_testing:
|
leak_tracker_flutter_testing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -969,10 +969,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vm_service
|
name: vm_service
|
||||||
sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14"
|
sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "14.3.1"
|
version: "15.0.0"
|
||||||
web:
|
web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
3
frontend/secrets.json
Normal file
3
frontend/secrets.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"ANDROID_GOOGLE_MAPS_API_KEY": "lfhasölkjfslöfjöksjf"
|
||||||
|
}
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
// This is a basic Flutter widget test.
|
|
||||||
//
|
|
||||||
// To perform an interaction with a widget in your test, use the WidgetTester
|
|
||||||
// utility in the flutter_test package. For example, you can send tap and scroll
|
|
||||||
// gestures. You can also use WidgetTester to find child widgets in the widget
|
|
||||||
// tree, read text, and verify that the values of widget properties are correct.
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
|
||||||
|
|
||||||
import 'package:anyway/main.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
|
||||||
// Build our app and trigger a frame.
|
|
||||||
await tester.pumpWidget(const MyApp());
|
|
||||||
|
|
||||||
// Verify that our counter starts at 0.
|
|
||||||
expect(find.text('0'), findsOneWidget);
|
|
||||||
expect(find.text('1'), findsNothing);
|
|
||||||
|
|
||||||
// Tap the '+' icon and trigger a frame.
|
|
||||||
await tester.tap(find.byIcon(Icons.add));
|
|
||||||
await tester.pump();
|
|
||||||
|
|
||||||
// Verify that our counter has incremented.
|
|
||||||
expect(find.text('0'), findsNothing);
|
|
||||||
expect(find.text('1'), findsOneWidget);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user