Skip to content

Commit

Permalink
feat: onboarding (#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
matisiekpl authored Jan 15, 2025
2 parents 15da053 + 23e168c commit f81f157
Show file tree
Hide file tree
Showing 19 changed files with 551 additions and 17 deletions.
2 changes: 1 addition & 1 deletion assets/aed_poland.geojson

Large diffs are not rendered by default.

Binary file added assets/onboarding/onboarding1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/onboarding/onboarding2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
277 changes: 277 additions & 0 deletions assets/onboarding/osm.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion assets/world.geojson

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ PODS:
- Flutter (1.0.0)
- flutter_compass (0.0.1):
- Flutter
- flutter_keyboard_visibility (0.0.1):
- Flutter
- flutter_web_auth (0.6.0):
- Flutter
- geolocator_apple (1.2.0):
Expand Down Expand Up @@ -142,6 +144,7 @@ DEPENDENCIES:
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
- Flutter (from `Flutter`)
- flutter_compass (from `.symlinks/plugins/flutter_compass/ios`)
- flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
- flutter_web_auth (from `.symlinks/plugins/flutter_web_auth/ios`)
- geolocator_apple (from `.symlinks/plugins/geolocator_apple/ios`)
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
Expand Down Expand Up @@ -180,6 +183,8 @@ EXTERNAL SOURCES:
:path: Flutter
flutter_compass:
:path: ".symlinks/plugins/flutter_compass/ios"
flutter_keyboard_visibility:
:path: ".symlinks/plugins/flutter_keyboard_visibility/ios"
flutter_web_auth:
:path: ".symlinks/plugins/flutter_web_auth/ios"
geolocator_apple:
Expand Down Expand Up @@ -216,6 +221,7 @@ SPEC CHECKSUMS:
FirebaseInstallations: 6ef4a1c7eb2a61ee1f74727d7f6ce2e72acf1414
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_compass: cbbd285cea1584c7ac9c4e0c3e1f17cbea55e855
flutter_keyboard_visibility: 0339d06371254c3eb25eeb90ba8d17dca8f9c069
flutter_web_auth: acc15a8fd7bba796a933c724a6dffc3d00f07c27
geolocator_apple: 9bcea1918ff7f0062d98345d238ae12718acfbc1
GoogleAppMeasurement: 987769c4ca6b968f2479fbcc9fe3ce34af454b8e
Expand Down
10 changes: 9 additions & 1 deletion lib/l10n/app_de.arb
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,13 @@
"dataSourceDescription": "Die Daten über die Standorte von Defibrillatoren stammen von OpenStreetMap. Ihre Qualität kann variieren. Der Autor übernimmt keine Verantwortung für die Richtigkeit der Daten. Wir ermutigen Sie, die Datenbank auf openaedmap.org mitzugestalten",
"lastUpdate": "Letzte Aktualisierung",
"refreshing": "Aktualisieren",
"refresh": "Jetzt aktualisieren"
"refresh": "Jetzt aktualisieren",
"onboardingTitle0": "Willkommen bei der AED-Karten-App!",
"onboardingBody0": "App zum Auffinden von Defibrillatoren in Ihrer Umgebung",
"onboardingTitle1": "Nahegelegene Defibrillatoren anzeigen",
"onboardingBody1": "Finden Sie den nächstgelegenen Defibrillator zu Ihrem Standort",
"onboardingTitle2": "Route zum nächstgelegenen Defibrillator",
"onboardingBody2": "Erhalten Sie Wegbeschreibungen zum nächstgelegenen Defibrillator",
"onboardingTitle3": "Wir verwenden die OpenStreetMap-Datenbank",
"onboardingBody3": "Beachten Sie, dass die Daten möglicherweise nicht zu 100% aktuell sind"
}
10 changes: 9 additions & 1 deletion lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,13 @@
"dataSourceDescription": "The data about the location of defibrillators comes from OpenStreetMap. Their quality may vary. The author is not responsible for the correctness of the data. We encourage you to co-create the database on openaedmap.org",
"lastUpdate": "Last update",
"refreshing": "Refreshing",
"refresh": "Refresh now"
"refresh": "Refresh now",
"onboardingTitle0": "Welcome to AED Map app!",
"onboardingBody0": "App made for finding defibrillators in your area",
"onboardingTitle1": "View nearby defibrillators",
"onboardingBody1": "Find the closest defibrillator to your location",
"onboardingTitle2": "Route to the nearest defibrillator",
"onboardingBody2": "Get directions to the nearest defibrillator",
"onboardingTitle3": "We are using OpenStreetMap database",
"onboardingBody3": "Keep in mind that the data may not be up 100% up to date"
}
10 changes: 9 additions & 1 deletion lib/l10n/app_es.arb
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,13 @@
"dataSourceDescription": "Los datos sobre la ubicación de los desfibriladores provienen de OpenStreetMap. Su calidad puede variar. El autor no es responsable de la exactitud de los datos. Te animamos a co-crear la base de datos en openaedmap.org",
"lastUpdate": "Última actualización",
"refreshing": "Actualizando",
"refresh": "Actualizar ahora"
"refresh": "Actualizar ahora",
"onboardingTitle0": "¡Bienvenido a la aplicación Mapa de DEA!",
"onboardingBody0": "Aplicación hecha para encontrar desfibriladores en tu área",
"onboardingTitle1": "Ver desfibriladores cercanos",
"onboardingBody1": "Encuentra el desfibrilador más cercano a tu ubicación",
"onboardingTitle2": "Ruta al desfibrilador más cercano",
"onboardingBody2": "Obtén direcciones al desfibrilador más cercano",
"onboardingTitle3": "Estamos usando la base de datos de OpenStreetMap",
"onboardingBody3": "Ten en cuenta que los datos pueden no estar 100% actualizados"
}
10 changes: 9 additions & 1 deletion lib/l10n/app_fr.arb
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,13 @@
"dataSourceDescription": "Les données sur l'emplacement des défibrillateurs proviennent d'OpenStreetMap. Leur qualité peut varier. L'auteur n'est pas responsable de l'exactitude des données. Nous vous encourageons à co-créer la base de données sur openaedmap.org",
"lastUpdate": "Dernière mise à jour",
"refreshing": "Actualisation en cours",
"refresh": "Actualiser maintenant"
"refresh": "Actualiser maintenant",
"onboardingTitle0": "Bienvenue dans l'application Carte des DAE !",
"onboardingBody0": "Application conçue pour trouver des défibrillateurs dans votre région",
"onboardingTitle1": "Voir les défibrillateurs à proximité",
"onboardingBody1": "Trouvez le défibrillateur le plus proche de votre emplacement",
"onboardingTitle2": "Itinéraire vers le défibrillateur le plus proche",
"onboardingBody2": "Obtenez des directions vers le défibrillateur le plus proche",
"onboardingTitle3": "Nous utilisons la base de données OpenStreetMap",
"onboardingBody3": "Gardez à l'esprit que les données peuvent ne pas être à jour à 100%"
}
10 changes: 9 additions & 1 deletion lib/l10n/app_it.arb
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,13 @@
"dataSourceDescription": "I dati sulla posizione dei defibrillatori provengono da OpenStreetMap. La loro qualità può variare. L'autore non è responsabile per la correttezza dei dati. Ti incoraggiamo a co-creare il database su openaedmap.org",
"lastUpdate": "Ultimo aggiornamento",
"refreshing": "Aggiornamento in corso",
"refresh": "Aggiorna ora"
"refresh": "Aggiorna ora",
"onboardingTitle0": "Benvenuto nell'app AED Map!",
"onboardingBody0": "App creata per trovare defibrillatori nella tua zona",
"onboardingTitle1": "Visualizza i defibrillatori nelle vicinanze",
"onboardingBody1": "Trova il defibrillatore più vicino alla tua posizione",
"onboardingTitle2": "Percorso verso il defibrillatore più vicino",
"onboardingBody2": "Ottieni indicazioni per il defibrillatore più vicino",
"onboardingTitle3": "Stiamo utilizzando il database di OpenStreetMap",
"onboardingBody3": "Tieni presente che i dati potrebbero non essere aggiornati al 100%"
}
10 changes: 9 additions & 1 deletion lib/l10n/app_pl.arb
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,13 @@
"dataSourceDescription": "Dane o lokalizacji defibrylatorów pochodzą z OpenStreetMap. Ich jakość może się różnić. Autor nie ponosi odpowiedzialności za poprawność danych. Zachęcamy do współtworzenia bazy na openaedmap.org",
"lastUpdate": "Ostatnia aktualizacja",
"refreshing": "Odświeżanie",
"refresh": "Odśwież teraz"
"refresh": "Odśwież teraz",
"onboardingTitle0": "Witamy w aplikacji AED Map!",
"onboardingBody0": "Aplikacja stworzona do znajdowania defibrylatorów w Twojej okolicy",
"onboardingTitle1": "Zobacz pobliskie defibrylatory",
"onboardingBody1": "Znajdź najbliższy defibrylator w Twojej lokalizacji",
"onboardingTitle2": "Trasa do najbliższego defibrylatora",
"onboardingBody2": "Uzyskaj wskazówki do najbliższego defibrylatora",
"onboardingTitle3": "Używamy bazy danych OpenStreetMap",
"onboardingBody3": "Pamiętaj, że dane mogą nie być w 100% aktualne"
}
30 changes: 26 additions & 4 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,19 @@ import 'package:aed_map/repositories/points_repository.dart';
import 'package:aed_map/repositories/routing_repository.dart';
import 'package:aed_map/screens/edit/edit_form.dart';
import 'package:aed_map/screens/map/map_screen.dart';
import 'package:aed_map/screens/onboarding/onboarding_screen.dart';
import 'package:feedback/feedback.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_phoenix/flutter_phoenix.dart';
import 'package:mixpanel_flutter/mixpanel_flutter.dart';
import 'package:plausible_analytics/plausible_analytics.dart';
import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:shared_preferences/shared_preferences.dart';

import 'constants.dart';

Expand All @@ -44,13 +48,15 @@ void main() async {
options.experimental.replay.sessionSampleRate = 1.0;
options.experimental.replay.onErrorSampleRate = 1.0;
},
appRunner: () =>
runApp(SentryWidget(child: const BetterFeedback(child: App()))),
appRunner: () => runApp(
SentryWidget(child: BetterFeedback(child: Phoenix(child: App())))),
);
}

class App extends StatefulWidget {
const App({super.key});
const App({super.key, this.skipOnboarding = false});

final bool skipOnboarding;

@override
State<App> createState() => _AppState();
Expand All @@ -60,13 +66,29 @@ class _AppState extends State<App> {
@override
void initState() {
super.initState();
SharedPreferences.getInstance().then((prefs) {
setState(() {
if (!prefs.containsKey('onboarded')) {
home = OnboardingScreen();
} else {
home = Home();
}
});
});
}

final GeolocationRepository geolocationRepository = GeolocationRepository();
final PointsRepository pointsRepository = PointsRepository();
final FeedbackRepository feedbackRepository = FeedbackRepository();
final RoutingRepository routingRepository = RoutingRepository();

Widget home = Scaffold(
body: Center(
child: CircularProgressIndicator(
color: Colors.green.shade400,
),
));

@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([
Expand Down Expand Up @@ -110,7 +132,7 @@ class _AppState extends State<App> {
create: (BuildContext context) =>
FeedbackCubit(feedbackRepository: feedbackRepository)),
],
child: const Home(),
child: widget.skipOnboarding ? Home() : home,
),
);
}
Expand Down
3 changes: 2 additions & 1 deletion lib/screens/map/map_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ class _MapScreenState extends State<MapScreen> {
},
child: BlocBuilder<PointsCubit, PointsState>(builder: (context, state) {
if (state is PointsLoadInProgress) {
return const Center(child: CircularProgressIndicator());
return Center(
child: CircularProgressIndicator(color: Colors.green.shade400));
}
if (state is PointsLoadSuccess) {
return Stack(
Expand Down
4 changes: 3 additions & 1 deletion lib/screens/map/raster_map.dart
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,9 @@ class _RasterMapState extends State<RasterMap> with TickerProviderStateMixin {
);
if (MediaQuery.of(context)
.platformBrightness !=
Brightness.dark) return map;
Brightness.dark) {
return map;
}
return ColorFiltered(
colorFilter: invert,
child: map,
Expand Down
103 changes: 103 additions & 0 deletions lib/screens/onboarding/onboarding_screen.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import 'package:flutter/material.dart';
import 'package:flutter_phoenix/flutter_phoenix.dart';
import 'package:flutter_svg/svg.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:introduction_screen/introduction_screen.dart';
import 'package:shared_preferences/shared_preferences.dart';

class OnboardingScreen extends StatefulWidget {
const OnboardingScreen({super.key});

@override
State<OnboardingScreen> createState() => _OnboardingScreenState();
}

class _OnboardingScreenState extends State<OnboardingScreen> {
@override
Widget build(BuildContext context) {
var titleTextStyle = TextStyle(
color: Colors.black,
fontSize: 20,
fontFamily: 'Manrope',
fontWeight: FontWeight.w500,
);
return Theme(
data: ThemeData(
colorScheme: ColorScheme.light(primary: Colors.green.shade400),
),
child: IntroductionScreen(
globalBackgroundColor: Colors.white,
dotsDecorator: DotsDecorator(
activeColor: Colors.green.shade400,
),
pages: [
PageViewModel(
title: AppLocalizations.of(context)!.onboardingTitle0,
body: AppLocalizations.of(context)!.onboardingBody0,
image: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 128),
child: ClipRRect(
borderRadius: BorderRadius.circular(8.0),
child: Image.asset("assets/icon.png"),
),
),
),
decoration: PageDecoration(
bodyPadding: EdgeInsets.symmetric(horizontal: 24),
imageFlex: 2,
imagePadding: EdgeInsets.only(top: 24),
titleTextStyle: titleTextStyle,
)),
PageViewModel(
title: AppLocalizations.of(context)!.onboardingTitle1,
body: AppLocalizations.of(context)!.onboardingBody1,
image: SafeArea(
child: Image.asset("assets/onboarding/onboarding1.png")),
decoration: PageDecoration(
bodyPadding: EdgeInsets.symmetric(horizontal: 24),
imageFlex: 4,
imagePadding: EdgeInsets.only(top: 24),
titleTextStyle: titleTextStyle,
)),
PageViewModel(
title: AppLocalizations.of(context)!.onboardingTitle2,
body: AppLocalizations.of(context)!.onboardingBody2,
image: SafeArea(
child: Image.asset("assets/onboarding/onboarding2.png")),
decoration: PageDecoration(
bodyPadding: EdgeInsets.symmetric(horizontal: 24),
imageFlex: 4,
imagePadding: EdgeInsets.only(top: 24),
titleTextStyle: titleTextStyle,
)),
PageViewModel(
title: AppLocalizations.of(context)!.onboardingTitle3,
body: AppLocalizations.of(context)!.onboardingBody3,
image: SafeArea(
child: SvgPicture.asset("assets/onboarding/osm.svg")),
decoration: PageDecoration(
bodyPadding: EdgeInsets.symmetric(horizontal: 24),
imageFlex: 2,
imagePadding: EdgeInsets.only(top: 24),
titleTextStyle: titleTextStyle,
))
],
done: Text(
AppLocalizations.of(context)!.next,
style: TextStyle(color: Colors.green.shade400),
),
next: Text(
AppLocalizations.of(context)!.next,
style: TextStyle(color: Colors.green.shade400),
),
onDone: () {
SharedPreferences.getInstance().then((prefs) {
prefs.setBool('onboarded', true);
});
Phoenix.rebirth(context);
},
),
);
}
}
Loading

0 comments on commit f81f157

Please sign in to comment.