diff --git a/.vscode/launch.json b/.vscode/launch.json
index fa7d5d9..4454643 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -50,4 +50,4 @@
"cwd": "${workspaceFolder}/frontend"
}
]
-}
\ No newline at end of file
+}
diff --git a/frontend/assets/README.md b/frontend/assets/README.md
new file mode 100644
index 0000000..68dd298
--- /dev/null
+++ b/frontend/assets/README.md
@@ -0,0 +1,2 @@
+## Vector assets
+As per https://www.svgrepo.com/collection/pixellove-bordered-vectors/ these icons are licensed under CC0.
diff --git a/frontend/assets/cat.svg b/frontend/assets/cat.svg
deleted file mode 100644
index f89158c..0000000
--- a/frontend/assets/cat.svg
+++ /dev/null
@@ -1,107 +0,0 @@
-
-
-
diff --git a/frontend/assets/cel-snow-globe.svg b/frontend/assets/cel-snow-globe.svg
new file mode 100644
index 0000000..bf299ba
--- /dev/null
+++ b/frontend/assets/cel-snow-globe.svg
@@ -0,0 +1,79 @@
+
+
+
\ No newline at end of file
diff --git a/frontend/assets/city.svg b/frontend/assets/city.svg
deleted file mode 100644
index 8f4bf7a..0000000
--- a/frontend/assets/city.svg
+++ /dev/null
@@ -1,273 +0,0 @@
-
-
-
diff --git a/frontend/assets/cld-server.svg b/frontend/assets/cld-server.svg
new file mode 100644
index 0000000..b484198
--- /dev/null
+++ b/frontend/assets/cld-server.svg
@@ -0,0 +1,64 @@
+
+
+
\ No newline at end of file
diff --git a/frontend/assets/con-drill.svg b/frontend/assets/con-drill.svg
new file mode 100644
index 0000000..b095d26
--- /dev/null
+++ b/frontend/assets/con-drill.svg
@@ -0,0 +1,64 @@
+
+
+
\ No newline at end of file
diff --git a/frontend/assets/con-warning.svg b/frontend/assets/con-warning.svg
new file mode 100644
index 0000000..1e085b4
--- /dev/null
+++ b/frontend/assets/con-warning.svg
@@ -0,0 +1,37 @@
+
+
+
\ No newline at end of file
diff --git a/frontend/assets/confused.svg b/frontend/assets/confused.svg
deleted file mode 100644
index e5182a2..0000000
--- a/frontend/assets/confused.svg
+++ /dev/null
@@ -1,427 +0,0 @@
-
-
-
-
diff --git a/frontend/assets/gen-lifebelt.svg b/frontend/assets/gen-lifebelt.svg
new file mode 100644
index 0000000..c32fcef
--- /dev/null
+++ b/frontend/assets/gen-lifebelt.svg
@@ -0,0 +1,76 @@
+
+
+
\ No newline at end of file
diff --git a/frontend/assets/plan.svg b/frontend/assets/plan.svg
deleted file mode 100644
index 62705c9..0000000
--- a/frontend/assets/plan.svg
+++ /dev/null
@@ -1,161 +0,0 @@
-
-
-
diff --git a/frontend/assets/terms_and_conditions.md b/frontend/assets/terms_and_conditions.md
new file mode 100644
index 0000000..924a4ed
--- /dev/null
+++ b/frontend/assets/terms_and_conditions.md
@@ -0,0 +1,126 @@
+# Terms and Conditions
+
+> Last updated: January 09, 2025
+>
+> Also see: https://anydev.info/terms-and-conditions/
+
+Please read these terms and conditions carefully before using our Service.
+
+## Interpretation and Definitions
+### Interpretation
+
+The words of which the initial letter is capitalized have meanings defined under the following conditions. The following definitions shall have the same meaning regardless of whether they appear in singular or in plural.
+
+### Definitions
+
+For the purposes of these Terms and Conditions:
+ - **Application** means the software program provided by the Company downloaded by You on any electronic device, named AnyWay
+ - **Application Store** means the digital distribution service operated and developed by Apple Inc. (Apple App Store) or Google Inc. (Google Play Store) in which the Application has been downloaded.
+ - **Affiliate** means an entity that controls, is controlled by or is under common control with a party, where "control" means ownership of 50% or more of the shares, equity interest or other securities entitled to vote for election of directors or other managing authority.
+ - **Country** refers to: Switzerland
+ - **Company** (referred to as either "the Company", "We", "Us" or "Our" in this Agreement) refers to AnyDev.
+ - **Device** means any device that can access the Service such as a computer, a cellphone or a digital tablet.
+ - **Service** refers to the Application.
+ - **Terms and Conditions** (also referred as "Terms") mean these Terms and Conditions that form the entire agreement between You and the Company regarding the use of the Service. This Terms and Conditions agreement has been created with the help of the Terms and Conditions Generator.
+ - **Third-party Social Media Service** means any services or content (including data, information, products or services) provided by a third-party that may be displayed, included or made available by the Service.
+ - **You** means the individual accessing or using the Service, or the company, or other legal entity on behalf of which such individual is accessing or using the Service, as applicable.
+
+## Acknowledgment
+
+These are the Terms and Conditions governing the use of this Service and the agreement that operates between You and the Company. These Terms and Conditions set out the rights and obligations of all users regarding the use of the Service.
+
+Your access to and use of the Service is conditioned on Your acceptance of and compliance with these Terms and Conditions. These Terms and Conditions apply to all visitors, users and others who access or use the Service.
+
+By accessing or using the Service You agree to be bound by these Terms and Conditions. If You disagree with any part of these Terms and Conditions then You may not access the Service.
+
+You represent that you are over the age of 18. The Company does not permit those under 18 to use the Service.
+
+Your access to and use of the Service is also conditioned on Your acceptance of and compliance with the Privacy Policy of the Company. Our Privacy Policy describes Our policies and procedures on the collection, use and disclosure of Your personal information when You use the Application or the Website and tells You about Your privacy rights and how the law protects You. Please read Our Privacy Policy carefully before using Our Service.
+
+
+## Links to Other Websites
+
+Our Service may contain links to third-party web sites or services that are not owned or controlled by the Company.
+
+The Company has no control over, and assumes no responsibility for, the content, privacy policies, or practices of any third party web sites or services. You further acknowledge and agree that the Company shall not be responsible or liable, directly or indirectly, for any damage or loss caused or alleged to be caused by or in connection with the use of or reliance on any such content, goods or services available on or through any such web sites or services.
+
+We strongly advise You to read the terms and conditions and privacy policies of any third-party web sites or services that You visit.
+
+
+## Termination
+
+We may terminate or suspend Your access immediately, without prior notice or liability, for any reason whatsoever, including without limitation if You breach these Terms and Conditions.
+
+Upon termination, Your right to use the Service will cease immediately.
+
+
+## Limitation of Liability
+
+Notwithstanding any damages that You might incur, the entire liability of the Company and any of its suppliers under any provision of this Terms and Your exclusive remedy for all of the foregoing shall be limited to the amount actually paid by You through the Service or 100 USD if You haven't purchased anything through the Service.
+
+To the maximum extent permitted by applicable law, in no event shall the Company or its suppliers be liable for any special, incidental, indirect, punitive, or consequential damages whatsoever (including, but not limited to, damages for loss of profits, loss of data, loss of use, loss of goodwill, business interruption, personal injury, loss of privacy, or any other pecuniary or non-pecuniary loss or damage) arising out of or in any way related to the use of or inability to use the Service, third-party software and/or third-party hardware used with the Service, or otherwise in connection with any provision of this Terms, even if the Company or any supplier has been advised of the possibility of such damages and even if the remedy fails of its essential purpose.
+
+In particular, the Company and its suppliers are not liable for any damages or losses that may arise from:
+ - Your reliance on any content provided through the Service;
+ - Errors, mistakes, or inaccuracies of content;
+ - Any unauthorized access to or use of our servers and/or any personal information stored therein;
+ - Any interruption or cessation of transmission to or from the Service;
+ - Any bugs, viruses, trojan horses, or the like which may be transmitted to or through the Service by any third party;
+ - Any errors or omissions in any content or for any loss or damage of any kind incurred as a result of Your use of any content posted, emailed, transmitted, or otherwise made available via the Service.
+
+The Company shall not be liable for any loss or damage resulting from failure to meet any of Your expectations related to the use or performance of the Service, including but not limited to inaccuracies in GPS location services, suggested itineraries, or other location-based services.
+
+Some jurisdictions do not allow the exclusion or limitation of certain types of liability, such as incidental or consequential damages or implied warranties. Therefore, the above limitations or exclusions may not apply to You. In such jurisdictions, each party's liability will be limited to the greatest extent permitted by law.
+
+To the extent permitted by applicable law, the Company and its suppliers’ aggregate liability to You for any claims arising from or related to the use of the Service shall in no event exceed the greater of (a) the amount You paid, if any, for accessing the Service during the twelve (12) month period preceding the claim or (b) one hundred (100) USD.
+
+You agree that the limitations of liability set forth in this section will survive any termination or expiration of these Terms and apply even if any limited remedy specified in these Terms is found to have failed its essential purpose.
+"AS IS" and "AS AVAILABLE" Disclaimer
+
+The Service is provided to You "AS IS" and "AS AVAILABLE" and with all faults and defects without warranty of any kind. To the maximum extent permitted under applicable law, the Company, on its own behalf and on behalf of its Affiliates and its and their respective licensors and service providers, expressly disclaims all warranties, whether express, implied, statutory or otherwise, with respect to the Service, including all implied warranties of merchantability, fitness for a particular purpose, title and non-infringement, and warranties that may arise out of course of dealing, course of performance, usage or trade practice. Without limitation to the foregoing, the Company provides no warranty or undertaking, and makes no representation of any kind that the Service will meet Your requirements, achieve any intended results, be compatible or work with any other software, applications, systems or services, operate without interruption, meet any performance or reliability standards or be error free or that any errors or defects can or will be corrected.
+
+Without limiting the foregoing, neither the Company nor any of the company's provider makes any representation or warranty of any kind, express or implied: (i) as to the operation or availability of the Service, or the information, content, and materials or products included thereon; (ii) that the Service will be uninterrupted or error-free; (iii) as to the accuracy, reliability, or currency of any information or content provided through the Service; or (iv) that the Service, its servers, the content, or e-mails sent from or on behalf of the Company are free of viruses, scripts, trojan horses, worms, malware, timebombs or other harmful components.
+
+Some jurisdictions do not allow the exclusion of certain types of warranties or limitations on applicable statutory rights of a consumer, so some or all of the above exclusions and limitations may not apply to You. But in such a case the exclusions and limitations set forth in this section shall be applied to the greatest extent enforceable under applicable law.
+
+
+## Governing Law
+
+The laws of the Country, excluding its conflicts of law rules, shall govern this Terms and Your use of the Service. Your use of the Application may also be subject to other local, state, national, or international laws.
+
+
+## Disputes Resolution
+
+If You have any concern or dispute about the Service, You agree to first try to resolve the dispute informally by contacting the Company.
+For European Union (EU) Users
+
+If You are a European Union consumer, you will benefit from any mandatory provisions of the law of the country in which You are resident.
+
+
+## United States Legal Compliance
+
+You represent and warrant that (i) You are not located in a country that is subject to the United States government embargo, or that has been designated by the United States government as a "terrorist supporting" country, and (ii) You are not listed on any United States government list of prohibited or restricted parties.
+
+
+## Severability and Waiver
+### Severability
+
+If any provision of these Terms is held to be unenforceable or invalid, such provision will be changed and interpreted to accomplish the objectives of such provision to the greatest extent possible under applicable law and the remaining provisions will continue in full force and effect.
+
+### Waiver
+
+Except as provided herein, the failure to exercise a right or to require performance of an obligation under these Terms shall not affect a party's ability to exercise such right or require such performance at any time thereafter nor shall the waiver of a breach constitute a waiver of any subsequent breach.
+Translation Interpretation
+
+These Terms and Conditions may have been translated if We have made them available to You on our Service. You agree that the original English text shall prevail in the case of a dispute.
+Changes to These Terms and Conditions
+
+We reserve the right, at Our sole discretion, to modify or replace these Terms at any time. If a revision is material We will make reasonable efforts to provide at least 30 days' notice prior to any new terms taking effect. What constitutes a material change will be determined at Our sole discretion.
+
+By continuing to access or use Our Service after those revisions become effective, You agree to be bound by the revised terms. If You do not agree to the new terms, in whole or in part, please stop using the website and the Service.
+
+
+## Contact Us
+
+If you have any questions about these Terms and Conditions, You can contact us:
+ - By visiting this page on our website: https://anydev.info
diff --git a/frontend/ios/fastlane/Fastfile b/frontend/ios/fastlane/Fastfile
index f3e23f4..b5e15f1 100644
--- a/frontend/ios/fastlane/Fastfile
+++ b/frontend/ios/fastlane/Fastfile
@@ -71,7 +71,6 @@ platform :ios do
"",
"s/IOS_GOOGLE_MAPS_API_KEY/#{ENV["IOS_GOOGLE_MAPS_API_KEY"]}/g",
"../Runner/AppDelegate.swift"
-
)
sh(
@@ -93,7 +92,7 @@ platform :ios do
skip_screenshots: true,
skip_metadata: true,
precheck_include_in_app_purchases: false,
-
+
submit_for_review: true,
automatic_release: true,
# automatically release the app after review
diff --git a/frontend/lib/main.dart b/frontend/lib/main.dart
index ed4121f..2fe5991 100644
--- a/frontend/lib/main.dart
+++ b/frontend/lib/main.dart
@@ -16,7 +16,6 @@ final SavedTrips savedTrips = SavedTrips();
class App extends StatelessWidget {
const App({super.key});
-
@override
Widget build(BuildContext context) => MaterialApp(
title: APP_NAME,
diff --git a/frontend/lib/modules/landmark_card.dart b/frontend/lib/modules/landmark_card.dart
index 8579219..491b6da 100644
--- a/frontend/lib/modules/landmark_card.dart
+++ b/frontend/lib/modules/landmark_card.dart
@@ -69,7 +69,6 @@ class _LandmarkCardState extends State {
padding: EdgeInsets.all(5),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
- spacing: 5,
children: [
Icon(Icons.timer_outlined, size: 16),
Text("${widget.landmark.duration?.inMinutes} minutes"),
diff --git a/frontend/lib/modules/onbarding_agreement_card.dart b/frontend/lib/modules/onbarding_agreement_card.dart
new file mode 100644
index 0000000..8f3d540
--- /dev/null
+++ b/frontend/lib/modules/onbarding_agreement_card.dart
@@ -0,0 +1,97 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_markdown/flutter_markdown.dart';
+
+import 'package:anyway/modules/onboarding_card.dart';
+
+
+class OnboardingAgreementCard extends StatefulWidget {
+ final String title;
+ final String description;
+ final String imagePath;
+ final String agreementTextPath;
+ final ValueChanged onAgreementChanged;
+
+
+ OnboardingAgreementCard({
+ super.key,
+ required this.title,
+ required this.description,
+ required this.imagePath,
+ required this.agreementTextPath,
+ required this.onAgreementChanged
+ });
+
+ @override
+ State createState() => _OnboardingAgreementCardState();
+}
+
+class _OnboardingAgreementCardState extends State {
+ bool agreed = false;
+ @override
+ Widget build(BuildContext context) {
+ return Padding(
+ padding: EdgeInsets.all(20),
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ OnboardingCard(title: widget.title, description: widget.description, imagePath: widget.imagePath),
+ Padding(padding: EdgeInsets.only(top: 20)),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Checkbox(
+ value: agreed,
+ onChanged: (value) {
+ setState(() {
+ agreed = value!;
+ widget.onAgreementChanged(value);
+ });
+ },
+ ),
+ Text(
+ "I agree to the ",
+ style: Theme.of(context).textTheme.bodyMedium!.copyWith(
+ color: Colors.white,
+ ),
+ ),
+ GestureDetector(
+ onTap: () {
+ // show a dialog with the agreement text
+ showDialog(
+ context: context,
+ builder: (BuildContext context) {
+ return AlertDialog(
+ scrollable: true,
+ content: FutureBuilder(
+ future: DefaultAssetBundle.of(context).loadString(widget.agreementTextPath),
+ builder: (context, snapshot) {
+ if (snapshot.hasData) {
+ return MarkdownBody(
+ data: snapshot.data.toString(),
+ );
+ } else {
+ return CircularProgressIndicator();
+ }
+
+ },
+ )
+ );
+ }
+ );
+
+ },
+ child: Text(
+ "Terms of Service (click to view)",
+ style: Theme.of(context).textTheme.bodyMedium!.copyWith(
+ color: Colors.white,
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ ),
+ ],
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/frontend/lib/modules/onboarding_card.dart b/frontend/lib/modules/onboarding_card.dart
index 05fc340..094d641 100644
--- a/frontend/lib/modules/onboarding_card.dart
+++ b/frontend/lib/modules/onboarding_card.dart
@@ -22,9 +22,7 @@ class OnboardingCard extends StatelessWidget {
children: [
Text(
title,
- style: TextStyle(
- fontSize: 24,
- fontWeight: FontWeight.bold,
+ style: Theme.of(context).textTheme.headlineLarge!.copyWith(
color: Colors.white,
),
),
@@ -36,13 +34,12 @@ class OnboardingCard extends StatelessWidget {
Padding(padding: EdgeInsets.only(top: 20)),
Text(
description,
- style: TextStyle(
- fontSize: 16,
+ style: Theme.of(context).textTheme.bodyMedium!.copyWith(
+ color: Colors.white,
),
),
-
]
),
);
}
-}
\ No newline at end of file
+}
diff --git a/frontend/lib/pages/onboarding.dart b/frontend/lib/pages/onboarding.dart
index 3692cb8..2de42b6 100644
--- a/frontend/lib/pages/onboarding.dart
+++ b/frontend/lib/pages/onboarding.dart
@@ -1,33 +1,37 @@
import 'dart:ui';
import 'package:anyway/constants.dart';
+import 'package:anyway/modules/onbarding_agreement_card.dart';
import 'package:anyway/modules/onboarding_card.dart';
import 'package:anyway/pages/new_trip_location.dart';
import 'package:flutter/material.dart';
+import 'package:shared_preferences/shared_preferences.dart';
-const List onboardingCards = [
- OnboardingCard(
+
+List onboardingCards = [
+ const OnboardingCard(
title: "Welcome to anyway!",
description: "Anyway helps you plan a city trip that suits your wishes.",
- imagePath: "assets/city.svg"
+ imagePath: "assets/cld-server.svg"
),
- OnboardingCard(
- title: "Find your way",
+ const OnboardingCard(
+ title: "Do your thing",
description: "Bored by churches? No problem! Hate shopping? No worries! Instead of suggesting the generic trips that bore you, anyway will try to give you recommendations that really suit you.",
- imagePath: "assets/plan.svg"
+ imagePath: "assets/con-drill.svg"
),
- OnboardingCard(
+ const OnboardingCard(
title: "Change your mind",
description: "Feet get sore, the weather changes. Anyway understands that! Move or remove destinations, visit hidden gems along your journey, do your own thing. Anyway adapts to your spontaneous decisions.",
- imagePath: "assets/cat.svg"
+ imagePath: "assets/cel-snow-globe.svg"
),
- OnboardingCard(
+ const OnboardingCard(
title: "Feeling lost?",
description: "Whenever you are confused or need help with the app, look out for the question mark in the top right corner. Help is just a tap away!",
- imagePath: "assets/confused.svg"
+ imagePath: "assets/gen-lifebelt.svg"
),
];
+
class OnboardingPage extends StatefulWidget {
const OnboardingPage({super.key});
@@ -37,9 +41,24 @@ class OnboardingPage extends StatefulWidget {
class _OnboardingPageState extends State {
final PageController _controller = PageController();
+ late List fullCards;
+
+
@override
Widget build(BuildContext context) {
+
+ Widget agreementCard = OnboardingAgreementCard(
+ title: "The annoying stuff",
+ description: "By using anyway, you agree to our terms and conditions and privacy policy. We don't use cookies or tracking, we don't store the data you submit. We are not responsible for any damage or loss caused by using anyway.",
+ imagePath: "assets/con-warning.svg",
+ agreementTextPath: "assets/terms_and_conditions.md",
+ onAgreementChanged: onAgreementChanged,
+ );
+ // need to add the agreement from within the function because it needs to be able to call setState
+ fullCards = onboardingCards + [agreementCard];
+
+
return Scaffold(
body: Stack(
children: [
@@ -55,8 +74,8 @@ class _OnboardingPageState extends State {
end: Alignment.bottomRight,
colors: APP_GRADIENT.colors,
stops: [
- (_controller.hasClients ? _controller.page ?? _controller.initialPage : _controller.initialPage) / onboardingCards.length,
- (_controller.hasClients ? _controller.page ?? _controller.initialPage + 1 : _controller.initialPage + 1) / onboardingCards.length,
+ (_controller.hasClients ? (_controller.page ?? _controller.initialPage) : _controller.initialPage) / onboardingCards.length,
+ (_controller.hasClients ? (_controller.page ?? _controller.initialPage) + 1 : _controller.initialPage + 1) / onboardingCards.length,
],
),
),
@@ -64,7 +83,7 @@ class _OnboardingPageState extends State {
BackdropFilter(
filter: ImageFilter.blur(sigmaX: 100, sigmaY: 100),
child: Container(
- color: Colors.black.withOpacity(0),
+ color: Colors.black.withValues(alpha: 0.2)
),
),
],
@@ -74,46 +93,73 @@ class _OnboardingPageState extends State {
PageView(
controller: _controller,
children: List.generate(
- onboardingCards.length,
+ fullCards.length,
(index) {
return Container(
alignment: Alignment.center,
- child: onboardingCards[index],
+ child: fullCards[index],
);
}
),
),
],
),
- floatingActionButton: FloatingActionButton.extended(
- onPressed: () {
- if (_controller.page == onboardingCards.length - 1) {
- Navigator.of(context).push(
- MaterialPageRoute(
- builder: (context) => const NewTripPage()
- )
- );
- } else {
- _controller.nextPage(duration: Duration(milliseconds: 500), curve: Curves.ease);
- }
- },
- label: AnimatedBuilder(
- animation: _controller,
- builder: (context, child) {
- if ((_controller.page ?? _controller.initialPage) == onboardingCards.length - 1) {
- return Row(
- children: [
- const Text("Start planning!"),
- Padding(padding: const EdgeInsets.only(right: 8.0)),
- const Icon(Icons.map_outlined)
- ],
- );
- } else {
- return const Icon(Icons.arrow_forward);
- }
- }
- )
- ),
+
+ floatingActionButton: nextButton(_controller)
);
}
-}
\ No newline at end of file
+
+ Widget nextButton(PageController controller) => AnimatedBuilder(
+ animation: _controller,
+ builder: (context, child) {
+ if ((_controller.hasClients ? (_controller.page ?? _controller.initialPage) : 0) != fullCards.length - 1) {
+ return FloatingActionButton.extended(
+ onPressed: () {
+ controller.nextPage(duration: Duration(milliseconds: 500), curve: Curves.ease);
+ },
+ label: Icon(Icons.arrow_forward)
+ );
+ } else {
+ // only allow the user to proceed if they have agreed to the terms and conditions
+ Future hasAgreed = SharedPreferences.getInstance().then(
+ (SharedPreferences prefs) {
+ return prefs.getBool('TC_agree') ?? false;
+ }
+ );
+
+ return FutureBuilder(
+ future: hasAgreed,
+ builder: (context, snapshot){
+ if (snapshot.hasData && snapshot.data!) {
+ return FloatingActionButton.extended(
+ onPressed: () {
+ Navigator.of(context).push(
+ MaterialPageRoute(
+ builder: (context) => const NewTripPage()
+ )
+ );
+ },
+ label: const Row(
+ children: [
+ Text("Start planning!"),
+ Padding(padding: EdgeInsets.only(right: 8.0)),
+ Icon(Icons.map_outlined)
+ ],
+ )
+ );
+ } else {
+ return Container();
+ }
+ }
+ );
+ }
+ }
+ );
+
+ void onAgreementChanged(bool value) async {
+ SharedPreferences prefs = await SharedPreferences.getInstance();
+ await prefs.setBool('TC_agree', value);
+ // Update the state of the OnboardingPage
+ setState(() {});
+ }
+}
diff --git a/frontend/lib/pages/settings.dart b/frontend/lib/pages/settings.dart
index b5d3240..c2e71d2 100644
--- a/frontend/lib/pages/settings.dart
+++ b/frontend/lib/pages/settings.dart
@@ -1,11 +1,12 @@
-import 'package:anyway/constants.dart';
-import 'package:anyway/layouts/scaffold.dart';
-import 'package:anyway/main.dart';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:url_launcher/url_launcher.dart';
+import 'package:anyway/main.dart';
+import 'package:anyway/constants.dart';
+import 'package:anyway/layouts/scaffold.dart';
+
bool debugMode = false;
diff --git a/frontend/pubspec.lock b/frontend/pubspec.lock
index bb2aad4..a79e921 100644
--- a/frontend/pubspec.lock
+++ b/frontend/pubspec.lock
@@ -21,10 +21,10 @@ packages:
dependency: transitive
description:
name: async
- sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
+ sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63
url: "https://pub.dev"
source: hosted
- version: "2.11.0"
+ version: "2.12.0"
auto_size_text:
dependency: "direct main"
description:
@@ -37,10 +37,10 @@ packages:
dependency: transitive
description:
name: boolean_selector
- sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
+ sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
url: "https://pub.dev"
source: hosted
- version: "2.1.1"
+ version: "2.1.2"
cached_network_image:
dependency: "direct main"
description:
@@ -69,10 +69,10 @@ packages:
dependency: transitive
description:
name: characters
- sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
+ sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
url: "https://pub.dev"
source: hosted
- version: "1.3.0"
+ version: "1.4.0"
checked_yaml:
dependency: transitive
description:
@@ -93,18 +93,18 @@ packages:
dependency: transitive
description:
name: clock
- sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
+ sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
url: "https://pub.dev"
source: hosted
- version: "1.1.1"
+ version: "1.1.2"
collection:
dependency: transitive
description:
name: collection
- sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
+ sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
url: "https://pub.dev"
source: hosted
- version: "1.19.0"
+ version: "1.19.1"
crypto:
dependency: transitive
description:
@@ -149,10 +149,10 @@ packages:
dependency: transitive
description:
name: fake_async
- sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
+ sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc"
url: "https://pub.dev"
source: hosted
- version: "1.3.1"
+ version: "1.3.2"
ffi:
dependency: transitive
description:
@@ -206,6 +206,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.0.0"
+ flutter_markdown:
+ dependency: "direct main"
+ description:
+ name: flutter_markdown
+ sha256: e7bbc718adc9476aa14cfddc1ef048d2e21e4e8f18311aaac723266db9f9e7b5
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.7.6+2"
flutter_plugin_android_lifecycle:
dependency: transitive
description:
@@ -412,18 +420,18 @@ packages:
dependency: transitive
description:
name: leak_tracker
- sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06"
+ sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec
url: "https://pub.dev"
source: hosted
- version: "10.0.7"
+ version: "10.0.8"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
- sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379"
+ sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
url: "https://pub.dev"
source: hosted
- version: "3.0.8"
+ version: "3.0.9"
leak_tracker_testing:
dependency: transitive
description:
@@ -448,14 +456,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.5.0"
+ markdown:
+ dependency: transitive
+ description:
+ name: markdown
+ sha256: "935e23e1ff3bc02d390bad4d4be001208ee92cc217cb5b5a6c19bc14aaa318c1"
+ url: "https://pub.dev"
+ source: hosted
+ version: "7.3.0"
matcher:
dependency: transitive
description:
name: matcher
- sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb
+ sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
url: "https://pub.dev"
source: hosted
- version: "0.12.16+1"
+ version: "0.12.17"
material_color_utilities:
dependency: transitive
description:
@@ -468,10 +484,10 @@ packages:
dependency: transitive
description:
name: meta
- sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
+ sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
url: "https://pub.dev"
source: hosted
- version: "1.15.0"
+ version: "1.16.0"
nested:
dependency: transitive
description:
@@ -492,10 +508,10 @@ packages:
dependency: transitive
description:
name: path
- sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
+ sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
url: "https://pub.dev"
source: hosted
- version: "1.9.0"
+ version: "1.9.1"
path_parsing:
dependency: transitive
description:
@@ -721,10 +737,10 @@ packages:
dependency: transitive
description:
name: source_span
- sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
+ sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c"
url: "https://pub.dev"
source: hosted
- version: "1.10.0"
+ version: "1.10.1"
sprintf:
dependency: transitive
description:
@@ -753,18 +769,18 @@ packages:
dependency: transitive
description:
name: stack_trace
- sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377"
+ sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
url: "https://pub.dev"
source: hosted
- version: "1.12.0"
+ version: "1.12.1"
stream_channel:
dependency: transitive
description:
name: stream_channel
- sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
+ sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
url: "https://pub.dev"
source: hosted
- version: "2.1.2"
+ version: "2.1.4"
stream_transform:
dependency: transitive
description:
@@ -777,10 +793,10 @@ packages:
dependency: transitive
description:
name: string_scanner
- sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3"
+ sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
url: "https://pub.dev"
source: hosted
- version: "1.3.0"
+ version: "1.4.1"
synchronized:
dependency: transitive
description:
@@ -793,18 +809,18 @@ packages:
dependency: transitive
description:
name: term_glyph
- sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
+ sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
url: "https://pub.dev"
source: hosted
- version: "1.2.1"
+ version: "1.2.2"
test_api:
dependency: transitive
description:
name: test_api
- sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c"
+ sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
url: "https://pub.dev"
source: hosted
- version: "0.7.3"
+ version: "0.7.4"
typed_data:
dependency: transitive
description:
@@ -921,10 +937,10 @@ packages:
dependency: transitive
description:
name: vm_service
- sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b
+ sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14"
url: "https://pub.dev"
source: hosted
- version: "14.3.0"
+ version: "14.3.1"
web:
dependency: transitive
description:
@@ -966,5 +982,5 @@ packages:
source: hosted
version: "3.1.2"
sdks:
- dart: ">=3.5.0 <4.0.0"
+ dart: ">=3.7.0-0 <4.0.0"
flutter: ">=3.24.0"
diff --git a/frontend/pubspec.yaml b/frontend/pubspec.yaml
index 458a132..ea783ef 100644
--- a/frontend/pubspec.yaml
+++ b/frontend/pubspec.yaml
@@ -52,6 +52,7 @@ dependencies:
permission_handler: ^11.3.1
geolocator: ^13.0.1
fuzzywuzzy: ^1.2.0
+ flutter_markdown: ^0.7.6+2
dev_dependencies:
flutter_test: