From 6c25519aba33ed09ab8133614acf859f3841321a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakob=20K=C3=B6rber?= <56073945+jakobkoerber@users.noreply.github.com> Date: Mon, 6 May 2024 11:03:41 +0200 Subject: [PATCH] Improve App's Stability (#254) --- README.md | 1 - android/app/build.gradle | 2 +- android/app/src/main/AndroidManifest.xml | 1 - .../de/tum/in/tumcampus/MainActivity.kt | 25 +- .../widgets/calendar/WidgetCalendarItem.kt | 8 +- android/app/src/main/res/values/dimens.xml | 1 + .../gradle/wrapper/gradle-wrapper.properties | 2 +- android/settings.gradle | 2 +- assets/translations/de.json | 225 +++++++++++ assets/translations/en.json | 225 +++++++++++ ios/Podfile.lock | 73 ++-- l10n.yaml | 3 - lib/base/enums/campus.dart | 24 +- lib/base/enums/remote_config_message.dart | 39 ++ lib/base/enums/search_category.dart | 24 +- lib/base/enums/user_preference.dart | 3 +- .../errorHandling/default_error_router.dart | 6 +- .../errorHandling/dio_exception_router.dart | 26 +- .../errorHandling/error_handling_view.dart | 3 +- lib/base/errorHandling/grpc_error_router.dart | 4 +- .../tum_online_api_exception_router.dart | 9 +- lib/base/errorHandling/type_error_router.dart | 6 +- lib/base/extensions/context.dart | 5 - lib/base/localization/app_de.arb | 368 ------------------ lib/base/localization/app_en.arb | 368 ------------------ .../tum_online_api_exception.dart | 108 +++-- .../tumOnlineApi/tum_online_api_service.dart | 6 +- lib/base/networking/cache/cache_entry.g.dart | 2 +- .../networking/protocols/api_exception.dart | 5 +- lib/base/util/delayed_loading_indicator.dart | 6 +- lib/base/util/last_updated_text.dart | 15 +- lib/base/util/map_launcher.dart | 7 +- lib/base/util/places_util.dart | 19 +- lib/base/util/string_parser.dart | 45 ++- .../model/calendar_event.dart | 13 +- .../model/calendar_event.g.dart | 4 +- .../services/calendar_view_service.dart | 8 +- .../calendar_addition_viewmodel.dart | 2 +- .../views/calendars_view.dart | 11 +- .../views/custom_event_view.dart | 7 +- .../views/event_creation_view.dart | 14 +- .../calendar_widget_event_view.dart | 12 +- .../homeWidget/calendar_widget_view.dart | 12 +- .../model/departures_preference.g.dart | 1 + .../viewModel/departures_viewmodel.dart | 4 +- .../views/departures_details_row_view.dart | 5 +- .../views/departures_details_view.dart | 15 +- .../homeWidget/departures_widget_view.dart | 9 +- .../viewModels/feedback_viewmodel.dart | 7 +- .../views/feedback_form_view.dart | 25 +- .../views/feedback_success_view.dart | 5 +- lib/gradeComponent/model/grade.dart | 10 +- lib/gradeComponent/views/chart_view.dart | 4 +- lib/gradeComponent/views/grades_view.dart | 9 +- .../views/contact_card_error_view.dart | 31 ++ .../views/contact_card_unauthorized_view.dart | 36 ++ .../views/contact_card_view.dart | 4 +- .../contactComponent/views/contact_view.dart | 28 +- .../contactComponent/views/link_view.dart | 5 +- .../contactComponent/views/tuition_view.dart | 17 +- .../views/unauthorized_view.dart | 31 -- .../viewModels/home_viewmodel.dart | 14 +- .../views/home_settings_view.dart | 7 +- lib/lectureComponent/model/lecture.dart | 14 +- .../model/lecture_details.dart | 14 +- .../views/basic_lecture_info_view.dart | 3 +- .../views/detailed_lecture_info_view.dart | 10 +- .../views/lecture_details_view.dart | 3 +- .../views/lecture_links_view.dart | 10 +- .../views/lecture_meeting_info_view.dart | 7 +- lib/lectureComponent/views/lectures_view.dart | 9 +- lib/main.dart | 89 ++++- .../views/homeWidget/movies_widget_view.dart | 4 +- .../model/navigatum_overlay_map.g.dart | 2 +- .../model/navigatum_roomfinder_map.g.dart | 8 +- .../views/navigatum_room_building_view.dart | 4 +- .../views/navigatum_room_details_view.dart | 3 +- .../views/navigatum_room_maps_view.dart | 9 +- .../views/navigatum_room_view.dart | 5 +- lib/navigation.dart | 1 + lib/navigation_service.dart | 52 ++- .../views/homeWidget/news_widget_view.dart | 11 +- lib/newsComponent/views/news_card_view.dart | 7 +- .../viewModels/onboarding_viewmodel.dart | 57 ++- .../views/confirm_view.dart | 13 +- .../views/location_permissions_view.dart | 6 +- lib/onboardingComponent/views/login_view.dart | 187 ++++----- .../views/permission_check_view.dart | 20 +- .../views/person_details_view.dart | 19 +- .../model/cafeterias/cafeteria.g.dart | 4 +- .../model/cafeterias/meal_plan.g.dart | 4 +- .../model/studyRooms/study_room.dart | 17 +- .../model/studyRooms/study_room.g.dart | 10 +- .../model/studyRooms/study_room_group.g.dart | 8 +- .../viewModels/cafeterias_viewmodel.dart | 5 +- .../viewModels/study_rooms_viewmodel.dart | 8 +- .../views/cafeterias/cafeteria_view.dart | 31 +- .../views/cafeterias/cafeterias_view.dart | 7 +- .../campuses/campus_most_searched_view.dart | 10 +- .../views/campuses/campus_view.dart | 8 +- .../homeWidget/cafeteria_widget_view.dart | 12 +- .../homeWidget/study_room_widget_view.dart | 11 +- lib/placesComponent/views/places_screen.dart | 5 +- lib/placesComponent/views/places_view.dart | 5 +- .../studyGroups/study_room_group_view.dart | 6 +- .../studyGroups/study_room_row_view.dart | 6 +- .../views/studyGroups/study_rooms_view.dart | 7 +- .../calendar_search_result_view.dart | 5 +- .../search_result_card_view.dart | 16 +- .../views/appWideSearch/search_scaffold.dart | 4 +- .../appWideSearch/search_textfield_view.dart | 3 +- .../views/appWideSearch/search_view.dart | 4 +- .../views/personRoomSearch/search_view.dart | 13 +- .../user_preferences_viewmodel.dart | 5 - .../views/appearance_settings_view.dart | 12 +- lib/settingsComponent/views/contact_view.dart | 12 +- .../views/general_settings_view.dart | 38 +- .../views/settings_scaffold.dart | 3 +- .../views/settings_view.dart | 18 +- .../views/bar_code_view.dart | 27 +- .../views/information_view.dart | 10 +- .../views/snapping_slider.dart | 6 +- .../views/student_card_view.dart | 8 +- pubspec.lock | 164 ++++---- pubspec.yaml | 29 +- 125 files changed, 1589 insertions(+), 1535 deletions(-) create mode 100644 assets/translations/de.json create mode 100644 assets/translations/en.json delete mode 100644 l10n.yaml create mode 100644 lib/base/enums/remote_config_message.dart delete mode 100644 lib/base/localization/app_de.arb delete mode 100644 lib/base/localization/app_en.arb create mode 100644 lib/homeComponent/contactComponent/views/contact_card_error_view.dart create mode 100644 lib/homeComponent/contactComponent/views/contact_card_unauthorized_view.dart delete mode 100644 lib/homeComponent/contactComponent/views/unauthorized_view.dart diff --git a/README.md b/README.md index 35ec120e..4130c094 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,6 @@ To ensure that campus_flutter runs on every supported platform, we need to make | Package | Reason | Link | |-------------------------|-------------------------------------------|----------------------------------------------| | gRPC | Caching | https://github.com/jakobkoerber/grpc-dart | -| Google Maps Flutter iOS | Enable usage of SDK in ARM iOS Simulators | https://github.com/jakobkoerber/packages | | Xml2Json | Fix Parsing of XML to JSON | https://github.com/jakobkoerber/xml2json | diff --git a/android/app/build.gradle b/android/app/build.gradle index 6b4a4a43..94e2f9c2 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -46,7 +46,7 @@ android { applicationId "de.tum.in.tumcampus" minSdkVersion 26 targetSdkVersion flutter.targetSdkVersion - ndkVersion "25.1.8937393" + ndkVersion "26.1.10909125" versionCode flutterVersionCode.toInteger() versionName flutterVersionName multiDexEnabled true diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 6bd7593b..b3d05e06 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -57,7 +57,6 @@ android:exported="true" android:hardwareAccelerated="true" android:launchMode="singleTop" - android:screenOrientation="portrait" android:theme="@style/LaunchTheme" android:windowSoftInputMode="adjustResize"> diff --git a/android/app/src/main/kotlin/de/tum/in/tumcampus/MainActivity.kt b/android/app/src/main/kotlin/de/tum/in/tumcampus/MainActivity.kt index 291b5ec8..c3b3b499 100644 --- a/android/app/src/main/kotlin/de/tum/in/tumcampus/MainActivity.kt +++ b/android/app/src/main/kotlin/de/tum/in/tumcampus/MainActivity.kt @@ -1,5 +1,28 @@ package de.tum.`in`.tumcampus +import android.annotation.SuppressLint +import android.content.Context +import android.content.pm.ActivityInfo +import android.os.Bundle import io.flutter.embedding.android.FlutterActivity -class MainActivity : FlutterActivity() + +class MainActivity : FlutterActivity() { + @SuppressLint("SourceLockedOrientationActivity") + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + requestedOrientation = if (isTablet(this)) { + ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED + } else { + ActivityInfo.SCREEN_ORIENTATION_PORTRAIT + } + } +} + +fun isTablet(context: Context): Boolean { + val resources = context.resources + val configuration = resources.configuration + val screenWidthDp = configuration.screenWidthDp + return screenWidthDp >= resources.getDimension(R.dimen.min_tablet_width_dp) +} \ No newline at end of file diff --git a/android/app/src/main/kotlin/de/tum/in/tumcampus/widgets/calendar/WidgetCalendarItem.kt b/android/app/src/main/kotlin/de/tum/in/tumcampus/widgets/calendar/WidgetCalendarItem.kt index 256ae273..33ff067f 100644 --- a/android/app/src/main/kotlin/de/tum/in/tumcampus/widgets/calendar/WidgetCalendarItem.kt +++ b/android/app/src/main/kotlin/de/tum/in/tumcampus/widgets/calendar/WidgetCalendarItem.kt @@ -14,17 +14,17 @@ data class WidgetCalendarItem( @SerialName("nr") val id: String, val status: String, - val url: String?, + val url: String? = null, val title: String, - val description: String?, + val description: String? = null, @Serializable(with = DateTimeSerializer::class) @SerialName("dtstart") val startDate: LocalDateTime, @Serializable(with = DateTimeSerializer::class) @SerialName("dtend") val endDate: LocalDateTime, - val location: String?, - val color: Long?, + val location: String? = null, + val color: Long? = null, var isFirstOnDay: Boolean = false ) { fun getEventColor(context: Context): Int { diff --git a/android/app/src/main/res/values/dimens.xml b/android/app/src/main/res/values/dimens.xml index 78071afa..5a1e000a 100644 --- a/android/app/src/main/res/values/dimens.xml +++ b/android/app/src/main/res/values/dimens.xml @@ -4,4 +4,5 @@ 8dp 4dp 2dp + 600dp \ No newline at end of file diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 5e6b5427..5d6560a4 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-all.zip diff --git a/android/settings.gradle b/android/settings.gradle index d183927c..2943c0cd 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -18,7 +18,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version '8.3.2' apply false + id "com.android.application" version '8.4.0' apply false id "org.jetbrains.kotlin.android" version "1.9.20" apply false id "org.jetbrains.kotlin.plugin.serialization" version "1.9.20" apply false id "com.google.gms.google-services" version "4.4.0" apply false diff --git a/assets/translations/de.json b/assets/translations/de.json new file mode 100644 index 00000000..47317da2 --- /dev/null +++ b/assets/translations/de.json @@ -0,0 +1,225 @@ +{ + "home": "Start", + "grades": "Noten", + "lectures": "Vorlesungen", + "calendar": "Kalender", + "identification": "Identifikation", + "places": "Orte", + "settings": "Einstellungen", + "settingsAndFeedback": "Einstellungen & Feedback", + "generalSettings": "Allgemeine Einstellungen", + "comingSoon": "Demnächst verfügbar", + "appearance": "Darstellung", + "language": "Sprache", + "theme": "Theme", + "useWebView": "Web-Ansicht verwenden", + "hideFailedGrades": "Durchgefallene Noten ausblenden", + "defaultMapsApplication": "Standard-Kartenanwendung", + "map": "Karte", + "maps": "Karten", + "contactMore": "Kontakt & Mehr", + "tokenPermissions": "Berechtigungen für Token", + "permissionChangePossibleInTUMonline": "Du kannst deine Berechtigungen in TUMOnline ändern", + "login": "Anmelden", + "notLoggedIn": "Nicht angemeldet!", + "profileError": "Profil konnte nicht geladen werden!", + "welcomeToTheApp": "Willkommen in der\n TUM Campus App", + "enterYourIDToStart": "Gib deine TUM ID ein, um zu starten", + "continueWithoutID": "Ohne TUM ID fortfahren", + "unknown": "Unbekannt", + "loading": "Lade", + "loadingName": "Lade {}", + "checkPermissions": "Berechtigungen prüfen", + "done": "Fertig", + "studyRoom": "Lernraum", + "studyRooms": "Lernräume", + "nearestStudyRooms": "Nächste Lernräume", + "noNearFreeStudyRoomsFound": "Keine Lernräume in deiner Nähe gefunden", + "mostSearchedRooms": "Meist gesuchte Räume", + "tuition": "Tuition", + "tuitionFees": "Studiengebühren", + "tuitionPaid": "Bezahlt", + "tuitionDueDate": "Fälligkeitsdatum", + "tuitionOpenAmount": "Offener Betrag", + "versionNumber": "Version {} ({})", + "checkToken": "Token prüfen", + "tryAgain": "Erneut versuchen", + "contactSupport": "Support kontaktieren", + "cafeteria": "Mensa", + "cafeterias": "Mensen", + "latestNews": "Neueste Nachrichten", + "scheduledLectureDates": "Termine", + "lectureExamDate": "Prüfung", + "lectureCurriculum": "Lehrplan", + "basicLectureInformation": "Grundlegende Informationen", + "detailedLectureInformation": "Detaillierte Informationen", + "lectureLinks": "Veranstaltungslinks", + "thisMeeting": "Dieser Termin", + "lectureDetails": "Vorlesungsdetails", + "noLecturesSelected": "Keine Vorlesungen ausgewählt", + "showDirections": "Wegbeschreibung anzeigen", + "notAvailableAbbrev": "n. v.", + "becomeABetaTester": "Werde Beta-Tester", + "usOnGitHub": "TUM-Dev auf GitHub", + "lastUpdatedAt": "zuletzt aktualisiert {}", + "averageGrade": "Durchschnittsnote", + "fullWinter": "Wintersemester {}/{}", + "fullSummer": "Sommersemester {}", + "shortWinter": "WiSe {}/{}", + "shortSummer": "SoSe {}", + "lecture": "Vorlesung", + "courseContents": "Inhalte der Veranstaltung", + "courseObjective": "Ziel der Veranstaltung", + "note": "Anmerkung", + "exercise": "Tutorium", + "seminar": "Übung", + "tutorial": "Praktikum", + "practicalCourse": "Seminar", + "lectureWithIntegratedExcercises": "Vorlesung mit integrierten Übungen", + "written": "Schriftlich", + "graded": "Beurteilt", + "writtenAndOral": "Schriftlich/Mündlich", + "oral": "Mündlich", + "source": "Quelle: {}", + "news": "Nachrichten", + "movies": "Filme", + "personalData": "Persönliche Daten", + "calendarViewToday": "Heute", + "calendarViewDay": "Tag", + "calendarViewWeek": "Woche", + "calendarViewMonth": "Monat", + "events": "Veranstaltungen", + "noUpcomingEvents": "Keine Anstehenden Ereignisse", + "noEventsToday": "Keine Ereignisse heute", + "departures": "Abfahrten", + "departure": "Abfahrt", + "direction": "Richtung", + "station": "Haltestelle: ", + "line": "Linie", + "now": "JETZT", + "free": "Frei", + "occupiedUntil": "Belegt bis {}", + "rooms": "Räume", + "roomDetails": "Raumdetails", + "building": "Gebäude", + "nFreeRooms": { + "zero": "Keine freien Räume", + "one": "1 freier Raum", + "other": "{} freie Räume" + }, + "mealPlans": "Essenspläne", + "noEntriesFound": "Keine {} gefunden!", + "enterQueryStart": "Stelle eine Suchanfrage", + "personalLectures": "Persönliche Vorlesungen", + "persons": "Personen", + "search": "Suche", + "today": "Heute", + "tomorrow": "Morgen", + "roomSearch": "Raum Suche", + "personSearch": "Personen Suche", + "badResponse": "Ungültige Antwort", + "pleaseTryAgain": "Bitte versuche es erneut!", + "connectionError": "Verbindungsfehler", + "makeSureInternetConnection": "Stelle sicher, dass du eine\n funktionierende Internetverbindung hast!", + "requestCancelled": "Anfrage abgebrochen", + "pleaseReport": "Bitte melden Sie dies als Fehler \nper E-Mail oder auf GitHub", + "connectionTimeout": "Zeitüberschreitung", + "decodingError": "Dekodierungsfehler", + "unknownError": "Unbekannter Fehler", + "monday": "Montag", + "tuesday": "Dienstag", + "wednesday": "Mittwoch", + "thursday": "Donnerstag", + "friday": "Freitag", + "weekend": "Wochenende", + "openingHours": "Öffnungszeiten", + "open": "{} offen von {} - {}", + "closed": "Geschlossen", + "closedOn": "{} geschlossen", + "closedToday": "Heute geschlossen", + "submitFeedback": "Feedback einreichen", + "name": "Name", + "message": "Nachricht", + "shareLocation": "Aktuellen Standort teilen", + "shareDeviceInformation": "Informationen über das Gerät teilen", + "submit": "Senden", + "yourMessage": "Deine Nachricht...", + "yourName": "Dein Name...", + "yourEmailTitle": "Deine E-Mail-Adresse", + "yourEmail": "deineemail@tum.de", + "invalidName": "Ungültiger Name", + "invalidMessage": "Ungültige Nachricht", + "invalidEmail": "Ungültige E-Mail-Adresse", + "unableToSend": "Nachricht kann nicht gesendet werden!", + "successfullySent": "Nachricht erfolgreich gesendet!\n Danke für Dein Feedback!", + "signInToTumOnline": "1. Melden Dich bei TUMonline an\n", + "selectTokenManagement": "2. Token-Verwaltung auswählen\n", + "activateToken": "3. Aktivieren Sie den neu erstellten Token und\n aktivieren Sie die gewünschten Berechtigungen", + "location": "Standort", + "locationOnboarding": "Aktiviere Standorte, um personalisierte Erlebnisse zu erreichen und Deinen Standort auf Raumfinder-Karten zu sehen.", + "continueOnboarding": "Weiter", + "showMore": "Mehr Anzeigen", + "licenses": "Lizenzen", + "privacyPolicy": "Datenschutzrichtlinie", + "createCalendarEvent": "Kalenderereignis erstellen", + "title": "Titel", + "annotation": "Bemerkung", + "from": "Von", + "to": "Bis", + "timeFrame": "Zeitrahmen", + "delete": "Löschen", + "deviceSettings": "Geräte-Einstellungen", + "edit": "Editieren", + "digitalStudentCard": "Digitale StudentCard", + "currentlyInBeta": "Aktuell in Testphase mit eingeschränkter Funktionalität!", + "validUntil": "Gültig bis", + "libraryBarcode": "Bibliotheks-Barcode", + "libraryNumber": "Bibliotheksnummer", + "birthday": "Geb.", + "studyId": "Matr.Nr.", + "locationServiceDisabled": "Ortungsdienst deaktiviert", + "permissionDenied": "Erlaubnis verweigert", + "onlyLetters": "Achte drauf, nur Buchstaben zu benutzen", + "onlyNumbers": "Achte drauf, nur Zahlen zu benutzen", + "personDetails": "Details zur Person", + "contact": "Kontakt", + "room": "Raum", + "back": "Zurück", + "editHome": "Home Anpassen", + "reorderDisable": "Widgets neu anordnen & deaktivieren", + "reset": "Zurücksetzen", + "selectPreferred": "Wähle deine bevorzugte {}", + "closest": "Näheste", + "noClosestStudyRoom": "Näheste Lernräume nicht ermittelbar!", + "cancel": "Abbrechen", + "selectAction": "Wähle eine Aktion", + "openIn": "In {} öffnen", + "unknownDirection": "Unbekannte Richtung", + "showWeekends": "Wochenenden anzeigen", + "color": "Farbe", + "resetLogin": "Zurücksetzen & Anmelden", + "resetPreferences": "Einstellungen zurücksetzen", + "noPermission": "Keine Berechtigung", + "tokenNotConfirmed": "Token nicht bestätigt", + "loginNeeded": "Login benötigt", + "tokenInvalid": "Token ungültig", + "rateExceeded": "Anfragequote überschritten", + "limitReached": "Token-Limit erreicht, maximal 10 Token pro Benutzer erlaubt", + "noUserSpecified": "Kein Benutzer spezifiziert", + "noUserFound": "Kein Benutzer gefunden", + "personNotFound": "Person nicht gefunden", + "invalidSearch": "Ungültige Suche", + "unknownException": "Unbekannter Fehler", + "noPermissionRecovery": "Stelle sicher, dass du die richtigen Berechtigungen für deinen Token aktivierst!", + "tokenNotConfirmedRecovery": "Gehe zu TumOnline und bestätige deinen Token!", + "loginNeededRecovery": "Diese Funktion kann nur genutzt werden, wenn du dich anmeldest!", + "tokenInvalidRecovery": "Bitte versuch einen neuen Token zu erstellen!", + "rateExceededRecovery": "Bitte versuche es später noch einmal!", + "limitReachedRecovery": "Bitte lösche einen deiner Token!", + "noUserSpecifiedRecovery": "Bitte gib deine Tum ID ein!", + "noUserFoundRecovery": "Überprüfe, ob du deine Tum ID richtig eingegeben hast!", + "personNotFoundRecovery": "Überprüfe, ob du den Namen richtig eingegeben hast!", + "invalidSearchRecovery": "Ein Suchbegriff mit weniger als 4 Zeichen darf keine Wildcards oder Sonderzeichen enthalten!", + "tumOnlineDegraded": "TUMonline Services sind derzeit beeinträchtigt!", + "tumOnlineMaintenance": "TUMonline Services werden derzeit gewartet!" +} diff --git a/assets/translations/en.json b/assets/translations/en.json new file mode 100644 index 00000000..d91ca314 --- /dev/null +++ b/assets/translations/en.json @@ -0,0 +1,225 @@ +{ + "home": "Home", + "grades": "Grades", + "lectures": "Lectures", + "calendar": "Calendar", + "identification": "Identification", + "places": "Places", + "settings": "Settings", + "settingsAndFeedback": "Settings & Feedback", + "generalSettings": "General Settings", + "comingSoon": "Coming Soon", + "language": "Language", + "appearance": "Appearance", + "theme": "Theme", + "useWebView": "Use Web View", + "hideFailedGrades": "Hide Failed Grades", + "defaultMapsApplication": "Default Maps Application", + "map": "Map", + "maps": "Maps", + "contactMore": "Contact & More", + "tokenPermissions": "Token Permissions", + "permissionChangePossibleInTUMonline": "You can change your permissions on TUMOnline", + "login": "Login", + "notLoggedIn": "Not Logged In!", + "profileError": "Error fetching profile!", + "welcomeToTheApp": "Welcome to the TUM Campus App", + "enterYourIDToStart": "Enter your TUM ID to get started", + "continueWithoutID": "Continue without TUM ID", + "unknown": "Unknown", + "loading": "Loading", + "loadingName": "Loading {}", + "checkPermissions": "Check Permissions", + "done": "Done", + "studyRoom": "Study Room", + "studyRooms": "Study Rooms", + "nearestStudyRooms": "Nearest Study Rooms", + "noNearFreeStudyRoomsFound": "No Study Rooms Near You Found!", + "mostSearchedRooms": "Most Searched Rooms", + "tuition": "Tuition", + "tuitionFees": "Tuition fees", + "tuitionPaid": "Tuition Paid", + "tuitionDueDate": "Due Date", + "tuitionOpenAmount": "Open Amount", + "versionNumber": "Version {} ({})", + "checkToken": "Check Token", + "tryAgain": "Try Again", + "contactSupport": "Contact Support", + "cafeteria": "Cafeteria", + "cafeterias": "Cafeterias", + "latestNews": "Latest News", + "scheduledLectureDates": "Dates", + "lectureExamDate": "Exam", + "lectureCurriculum": "Curriculum", + "basicLectureInformation": "Basic Lecture Information", + "detailedLectureInformation": "Detailed Lecture Information", + "lectureLinks": "Lecture Links", + "thisMeeting": "This Meeting", + "lectureDetails": "Lecture Details", + "noLecturesSelected": "no lecture selected", + "showDirections": "Show Directions", + "notAvailableAbbrev": "n/a", + "becomeABetaTester": "Become a Beta Tester", + "usOnGitHub": "TUM-Dev on GitHub", + "lastUpdatedAt": "last updated {}", + "averageGrade": "Average Grade", + "fullWinter": "Wintersemester {}/{}", + "fullSummer": "Summersemester {}", + "shortWinter": "WiSe {}/{}", + "shortSummer": "SoSe {}", + "lecture": "Lecture", + "courseContents": "Course Contents", + "courseObjective": "Course Objective", + "note": "Note", + "exercise": "Exercise", + "seminar": "Seminar", + "tutorial": "Exercise", + "practicalCourse": "Practical Course", + "lectureWithIntegratedExcercises": "Lecture with integrated Exercises", + "written": "Written", + "graded": "Graded", + "writtenAndOral": "WrittenOral", + "oral": "Oral", + "source": "Source: {}", + "news": "News", + "movies": "Movies", + "personalData": "Personal Data", + "calendarViewToday": "Today", + "calendarViewDay": "Day", + "calendarViewWeek": "Week", + "calendarViewMonth": "Month", + "events": "Events", + "noUpcomingEvents": "No Upcoming Events", + "noEventsToday": "No Events Today", + "departures": "Departures", + "departure": "Departure", + "direction": "Direction", + "station": "Station: ", + "line": "Line", + "now": "NOW", + "free": "Free", + "occupiedUntil": "Occupied until {}", + "rooms": "Rooms", + "roomDetails": "Room Details", + "building": "Building", + "nFreeRooms": { + "zero": "no free rooms", + "one": "1 free room", + "other": "{} free rooms" + }, + "mealPlans": "Meal Plans", + "noEntriesFound": "No {} Found!", + "enterQueryStart": "Enter a Query to Start", + "personalLectures": "Personal Lectures", + "persons": "Persons", + "search": "Search", + "today": "Today", + "tomorrow": "Tomorrow", + "roomSearch": "Room Search", + "personSearch": "Person Search", + "badResponse": "Bad Response", + "pleaseTryAgain": "Please try again!", + "connectionError": "Connection Error", + "makeSureInternetConnection": "Make sure you have \na working internet connection!", + "requestCancelled": "Request Cancelled", + "pleaseReport": "Please report this is as a bug \nvia Email or on GitHub", + "connectionTimeout": "Connection Timeout", + "decodingError": "Decoding Error", + "unknownError": "Unknown Error", + "monday": "Monday", + "tuesday": "Tuesday", + "wednesday": "Wednesday", + "thursday": "Thursday", + "friday": "Friday", + "weekend": "Weekend", + "openingHours": "Opening Hours", + "open": "Open {} from {} - {}", + "closed": "Closed", + "closedOn": "Closed on {}", + "closedToday": "Closed Today", + "submitFeedback": "Submit Feedback", + "name": "Name", + "message": "Message", + "shareLocation": "Share Current Location", + "shareDeviceInformation": "Share Device's Information", + "submit": "Submit", + "yourMessage": "Your Message...", + "yourName": "Your Name...", + "yourEmailTitle": "Your Email Address", + "yourEmail": "youremail@tum.de", + "invalidName": "Invalid Name", + "invalidMessage": "Invalid Message", + "invalidEmail": "Invalid Email Address", + "unableToSend": "Unable to Send Message!", + "successfullySent": "Message Successfully Sent!\n Thanks for Your Feedback!", + "signInToTumOnline": "1. Sign in to TUMonline\n", + "selectTokenManagement": "2. Select Token-Management\n", + "activateToken": "3. Activate the newly created token \nand enable your desired permissions", + "location": "Location", + "locationOnboarding": "Enable locations to access personalized experiences and your location on the room finder maps.", + "continueOnboarding": "Continue", + "showMore": "Show More", + "licenses": "Licenses", + "privacyPolicy": "Privacy Policy", + "createCalendarEvent": "Create Calendar Event", + "title": "Title", + "annotation": "Annotation", + "from": "From", + "to": "To", + "timeFrame": "Time Frame", + "delete": "Delete", + "deviceSettings": "Device Settings", + "edit": "Edit", + "digitalStudentCard": "Digital StudentCard", + "currentlyInBeta": "Currently in Beta with Limited Functionality!", + "validUntil": "Valid until", + "libraryBarcode": "Library Barcode", + "libraryNumber": "Library Number", + "birthday": "Birthday", + "studyId": "Study ID", + "locationServiceDisabled": "Location Service disabled", + "permissionDenied": "Permission denied", + "onlyLetters": "Make Sure to Use Letters Only", + "onlyNumbers": "Make Sure to Use Numbers Only", + "personDetails": "Person Details", + "contact": "Contact", + "room": "Room", + "back": "Back", + "editHome": "Edit Home", + "reorderDisable": "Reorder & Disable Widgets", + "reset": "Reset", + "selectPreferred": "Select your preferred {}", + "closest": "Closest", + "noClosestStudyRoom": "Closest learning spaces cannot be determined!", + "cancel": "Cancel", + "selectAction": "Select an action", + "openIn": "Open in {}", + "unknownDirection": "Unknown Direction", + "showWeekends": "Show Weekends", + "color": "Color", + "resetLogin": "Reset & Login", + "resetPreferences": "Reset Preferences", + "noPermission": "No Permission", + "tokenNotConfirmed": "Token Not Confirmed", + "loginNeeded": "Login Needed", + "tokenInvalid": "Token Invalid", + "rateExceeded": "Request Rate Exceeded", + "limitReached": "Token limit Reached, Maximum 10 Tokens per User Allowed", + "noUserSpecified": "No User Specified", + "noUserFound": "No User Found", + "personNotFound": "Person Not Found", + "invalidSearch": "Invalid Search", + "unknownException": "Unknown Exception", + "noPermissionRecovery": "Make sure to enable the right permissions for your token!", + "tokenNotConfirmedRecovery": "Go to TumOnline and confirm your token!", + "loginNeededRecovery": "This feature can only be used if you log in!", + "tokenInvalidRecovery": "Try creating a new token!", + "rateExceededRecovery": "Please try again later!", + "limitReachedRecovery": "Please delete one of your tokens!", + "noUserSpecifiedRecovery": "Please enter your Tum ID!", + "noUserFoundRecovery": "Make sure you entered your Tum ID correctly!", + "personNotFoundRecovery": "Make sure you entered the name correctly!", + "invalidSearchRecovery": "A search string with less than 4 characters must not contain wildcards or special characters!", + "tumOnlineDegraded": "TUMonline Services are currently degraded!", + "tumOnlineMaintenance": "TUMonline Services are currently under maintenance!" +} diff --git a/ios/Podfile.lock b/ios/Podfile.lock index ef9bc1d5..88152741 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -6,20 +6,29 @@ PODS: - Firebase/Crashlytics (10.24.0): - Firebase/CoreOnly - FirebaseCrashlytics (~> 10.24.0) - - firebase_core (2.30.0): + - Firebase/RemoteConfig (10.24.0): + - Firebase/CoreOnly + - FirebaseRemoteConfig (~> 10.24.0) + - firebase_core (2.30.1): - Firebase/CoreOnly (= 10.24.0) - Flutter - - firebase_crashlytics (3.5.2): + - firebase_crashlytics (3.5.4): - Firebase/Crashlytics (= 10.24.0) - firebase_core - Flutter + - firebase_remote_config (4.4.4): + - Firebase/RemoteConfig (= 10.24.0) + - firebase_core + - Flutter + - FirebaseABTesting (10.25.0): + - FirebaseCore (~> 10.0) - FirebaseCore (10.24.0): - FirebaseCoreInternal (~> 10.0) - GoogleUtilities/Environment (~> 7.12) - GoogleUtilities/Logger (~> 7.12) - - FirebaseCoreExtension (10.24.0): + - FirebaseCoreExtension (10.25.0): - FirebaseCore (~> 10.0) - - FirebaseCoreInternal (10.24.0): + - FirebaseCoreInternal (10.25.0): - "GoogleUtilities/NSData+zlib (~> 7.8)" - FirebaseCrashlytics (10.24.0): - FirebaseCore (~> 10.5) @@ -30,20 +39,30 @@ PODS: - GoogleUtilities/Environment (~> 7.8) - nanopb (< 2.30911.0, >= 2.30908.0) - PromisesObjC (~> 2.1) - - FirebaseInstallations (10.24.0): + - FirebaseInstallations (10.25.0): - FirebaseCore (~> 10.0) - GoogleUtilities/Environment (~> 7.8) - GoogleUtilities/UserDefaults (~> 7.8) - PromisesObjC (~> 2.1) - - FirebaseRemoteConfigInterop (10.24.0) - - FirebaseSessions (10.24.0): + - FirebaseRemoteConfig (10.24.0): + - FirebaseABTesting (~> 10.0) + - FirebaseCore (~> 10.0) + - FirebaseInstallations (~> 10.0) + - FirebaseRemoteConfigInterop (~> 10.23) + - FirebaseSharedSwift (~> 10.0) + - GoogleUtilities/Environment (~> 7.8) + - "GoogleUtilities/NSData+zlib (~> 7.8)" + - FirebaseRemoteConfigInterop (10.25.0) + - FirebaseSessions (10.25.0): - FirebaseCore (~> 10.5) - FirebaseCoreExtension (~> 10.0) - FirebaseInstallations (~> 10.0) - GoogleDataTransport (~> 9.2) - - GoogleUtilities/Environment (~> 7.10) + - GoogleUtilities/Environment (~> 7.13) + - GoogleUtilities/UserDefaults (~> 7.13) - nanopb (< 2.30911.0, >= 2.30908.0) - PromisesSwift (~> 2.1) + - FirebaseSharedSwift (10.25.0) - Flutter (1.0.0) - flutter_native_splash (0.0.1): - Flutter @@ -63,16 +82,16 @@ PODS: - GoogleMaps/Base (8.4.0) - GoogleMaps/Maps (8.4.0): - GoogleMaps/Base - - GoogleUtilities/Environment (7.13.0): + - GoogleUtilities/Environment (7.13.2): - GoogleUtilities/Privacy - PromisesObjC (< 3.0, >= 1.2) - - GoogleUtilities/Logger (7.13.0): + - GoogleUtilities/Logger (7.13.2): - GoogleUtilities/Environment - GoogleUtilities/Privacy - - "GoogleUtilities/NSData+zlib (7.13.0)": + - "GoogleUtilities/NSData+zlib (7.13.2)": - GoogleUtilities/Privacy - - GoogleUtilities/Privacy (7.13.0) - - GoogleUtilities/UserDefaults (7.13.0): + - GoogleUtilities/Privacy (7.13.2) + - GoogleUtilities/UserDefaults (7.13.2): - GoogleUtilities/Logger - GoogleUtilities/Privacy - home_widget (0.0.1): @@ -114,6 +133,7 @@ DEPENDENCIES: - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) - firebase_core (from `.symlinks/plugins/firebase_core/ios`) - firebase_crashlytics (from `.symlinks/plugins/firebase_crashlytics/ios`) + - firebase_remote_config (from `.symlinks/plugins/firebase_remote_config/ios`) - Flutter (from `Flutter`) - flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`) - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) @@ -134,13 +154,16 @@ DEPENDENCIES: SPEC REPOS: trunk: - Firebase + - FirebaseABTesting - FirebaseCore - FirebaseCoreExtension - FirebaseCoreInternal - FirebaseCrashlytics - FirebaseInstallations + - FirebaseRemoteConfig - FirebaseRemoteConfigInterop - FirebaseSessions + - FirebaseSharedSwift - GoogleDataTransport - GoogleMaps - GoogleUtilities @@ -155,6 +178,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/firebase_core/ios" firebase_crashlytics: :path: ".symlinks/plugins/firebase_crashlytics/ios" + firebase_remote_config: + :path: ".symlinks/plugins/firebase_remote_config/ios" Flutter: :path: Flutter flutter_native_splash: @@ -191,15 +216,19 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: device_info_plus: 97af1d7e84681a90d0693e63169a5d50e0839a0d Firebase: 91fefd38712feb9186ea8996af6cbdef41473442 - firebase_core: 66b99b4fb4e5d7cc4e88d4c195fe986681f3466a - firebase_crashlytics: 7ccf6bc9a3310a5c53bca1150203f9b91b42732a + firebase_core: 7f1e1156934d0da3be260174812842df9420e4ab + firebase_crashlytics: 9815effbfaad6c94c65d4eff479c0d9284bf1a38 + firebase_remote_config: bb9853d3dbca8dc788152371fdfefe982e25a2c8 + FirebaseABTesting: e6e3c3e0e35813874f571d1b7bdae2aab319dd38 FirebaseCore: 11dc8a16dfb7c5e3c3f45ba0e191a33ac4f50894 - FirebaseCoreExtension: af5fd85e817ea9d19f9a2659a376cf9cf99f03c0 - FirebaseCoreInternal: bcb5acffd4ea05e12a783ecf835f2210ce3dc6af + FirebaseCoreExtension: 8a47811d0b155501559ef05d089518152a0a1677 + FirebaseCoreInternal: 910a81992c33715fec9263ca7381d59ab3a750b7 FirebaseCrashlytics: af38ea4adfa606f6e63fcc22091b61e7938fcf66 - FirebaseInstallations: 8f581fca6478a50705d2bd2abd66d306e0f5736e - FirebaseRemoteConfigInterop: 6c349a466490aeace3ce9c091c86be1730711634 - FirebaseSessions: 2651b464e241c93fd44112f995d5ab663c970487 + FirebaseInstallations: 91950fe859846fff0fbd296180909dd273103b09 + FirebaseRemoteConfig: 95dddc50496b37eef199dadce850d5652b534b43 + FirebaseRemoteConfigInterop: b25018791b204c0d78a90e394d6c62d9b1f22da8 + FirebaseSessions: c0939656253a1fa0e94ecc266ccf770cc8b33732 + FirebaseSharedSwift: 0274086954b1b2d5fd7e829eccc587044d72a4ba Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 flutter_native_splash: edf599c81f74d093a4daf8e17bd7a018854bc778 flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be @@ -207,9 +236,9 @@ SPEC CHECKSUMS: google_maps_flutter_ios: c454f18e0e22df6ac0e9f2a4df340858f5a3680c GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a GoogleMaps: 8939898920281c649150e0af74aa291c60f2e77d - GoogleUtilities: d053d902a8edaa9904e1bd00c37535385b8ed152 + GoogleUtilities: c56430aef51a1aa57b25da78c3f8397e522c67b7 home_widget: 0434835a4c9a75704264feff6be17ea40e0f0d57 - isar_flutter_libs: b69f437aeab9c521821c3f376198c4371fa21073 + isar_flutter_libs: fdf730ca925d05687f36d7f1d355e482529ed097 map_launcher: 5fde49ac9a52672bf99da746599f507b4490d7b5 nanopb: 438bc412db1928dac798aa6fd75726007be04262 package_info_plus: 58f0028419748fad15bf008b270aaa8e54380b1c diff --git a/l10n.yaml b/l10n.yaml deleted file mode 100644 index e2f58bf2..00000000 --- a/l10n.yaml +++ /dev/null @@ -1,3 +0,0 @@ -arb-dir: lib/base/localization/ -template-arb-file: app_en.arb -output-localization-file: app_localizations.dart \ No newline at end of file diff --git a/lib/base/enums/campus.dart b/lib/base/enums/campus.dart index 588bf922..705dbea2 100644 --- a/lib/base/enums/campus.dart +++ b/lib/base/enums/campus.dart @@ -4,7 +4,7 @@ import 'package:campus_flutter/departuresComponent/model/station.dart'; enum Campus { stammgelaende("Stammgelände"), olympiapark("Campus Olympiapark"), - // klinikumRechts("Klinikum rechts der Isar"), + klinikumRechts("Klinikum rechts der Isar"), grosshadern("Klinikum Großhadern"), garching("Garching Forschungszentrum"), freising("Campus Freising"); @@ -20,7 +20,7 @@ extension CampusExtension on Campus { Campus.stammgelaende, Campus.garching, Campus.olympiapark, - // Campus.klinikumRechts, + Campus.klinikumRechts, Campus.freising, ]; } @@ -31,8 +31,8 @@ extension CampusExtension on Campus { return "Stammgelände"; case Campus.olympiapark: return "Olympiapark"; - /* case Campus.klinikumRechts: - return "Klinikum Isar"; */ + case Campus.klinikumRechts: + return "Klinikum Isar"; case Campus.grosshadern: return "Großhadern"; case Campus.garching: @@ -48,8 +48,8 @@ extension CampusExtension on Campus { return "assets/images/campus/campus-stamm.jpeg"; case Campus.olympiapark: return "assets/images/campus/campus-olympia.jpg"; - /* case Campus.klinikumRechts: - return "assets/images/campus/campus-klinikum.jpg"; */ + case Campus.klinikumRechts: + return "assets/images/campus/campus-klinikum.jpg"; case Campus.garching: return "assets/images/campus/campus-garching.jpeg"; case Campus.freising: @@ -71,11 +71,11 @@ extension CampusExtension on Campus { latitude: 48.17957305879896, longitude: 11.546601863009668, ); - /* case Campus.klinikumRechts: + case Campus.klinikumRechts: return Location( latitude: 48.13760759635786, longitude: 11.60083902677729, - ); */ + ); case Campus.grosshadern: return Location( latitude: 48.1116433849602, @@ -118,7 +118,7 @@ extension CampusExtension on Campus { longitude: 11.555783595899824, ), ); - /* case Campus.klinikumRechts: + case Campus.klinikumRechts: return Station( name: "Max-Weber-Platz", apiName: "91000580", @@ -126,7 +126,7 @@ extension CampusExtension on Campus { latitude: 48.13573243097588, longitude: 11.599014647301777, ), - ); */ + ); case Campus.grosshadern: return Station( name: "Klinikum Großhadern", @@ -181,7 +181,7 @@ extension CampusExtension on Campus { ]; case Campus.olympiapark: return [defaultStation]; - /* case Campus.klinikumRechts: + case Campus.klinikumRechts: return [ defaultStation, Station( @@ -192,7 +192,7 @@ extension CampusExtension on Campus { longitude: 11.600075277341709, ), ), - ]; */ + ]; case Campus.grosshadern: return [ defaultStation, diff --git a/lib/base/enums/remote_config_message.dart b/lib/base/enums/remote_config_message.dart new file mode 100644 index 00000000..095fbe91 --- /dev/null +++ b/lib/base/enums/remote_config_message.dart @@ -0,0 +1,39 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/cupertino.dart'; + +enum RemoteConfigMessage { + tumOnlineDegraded, + tumOnlineMaintenance; + + String get firebaseId { + switch (this) { + case RemoteConfigMessage.tumOnlineDegraded: + return "isTUMOnlineDegraded"; + case RemoteConfigMessage.tumOnlineMaintenance: + return "isTUMOnlineMaintenanceMode"; + } + } + + String message(BuildContext context) { + switch (this) { + case RemoteConfigMessage.tumOnlineDegraded: + return context.tr("tumOnlineDegraded"); + case RemoteConfigMessage.tumOnlineMaintenance: + return context.tr("tumOnlineMaintenance"); + } + } + + static RemoteConfigMessage? fromString(String key) { + if (key == "isTUMOnlineDegraded") { + return RemoteConfigMessage.tumOnlineDegraded; + } else if (key == "isTUMOnlineMaintenanceMode") { + return RemoteConfigMessage.tumOnlineMaintenance; + } else { + return null; + } + } + + static Set get keys { + return RemoteConfigMessage.values.map((e) => e.firebaseId).toSet(); + } +} diff --git a/lib/base/enums/search_category.dart b/lib/base/enums/search_category.dart index af6e9876..f99bd199 100644 --- a/lib/base/enums/search_category.dart +++ b/lib/base/enums/search_category.dart @@ -1,4 +1,4 @@ -import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.dart'; enum SearchCategory { @@ -25,27 +25,27 @@ extension SearchCategoryExtension on SearchCategory { ) { switch (searchCategory) { case SearchCategory.cafeterias: - return context.localizations.cafeterias; + return context.tr("cafeterias"); case SearchCategory.calendar: - return context.localizations.calendar; + return context.tr("calendar"); case SearchCategory.grade: - return context.localizations.grades; + return context.tr("grades"); case SearchCategory.movie: - return context.localizations.movies; + return context.tr("movies"); case SearchCategory.news: - return context.localizations.news; + return context.tr("news"); case SearchCategory.studyRoom: - return context.localizations.studyRooms; + return context.tr("studyRooms"); case SearchCategory.lectures: - return context.localizations.lectures; + return context.tr("lectures"); case SearchCategory.personalLectures: - return context.localizations.personalLectures; + return context.tr("personalLectures"); case SearchCategory.persons: - return context.localizations.persons; + return context.tr("persons"); case SearchCategory.rooms: - return context.localizations.rooms; + return context.tr("rooms"); default: - return context.localizations.unknown; + return context.tr("unknown"); } } diff --git a/lib/base/enums/user_preference.dart b/lib/base/enums/user_preference.dart index 414e3a8a..f58329d1 100644 --- a/lib/base/enums/user_preference.dart +++ b/lib/base/enums/user_preference.dart @@ -7,8 +7,7 @@ enum UserPreference { calendarColors(String), browser(bool), failedGrades(bool), - weekends(bool), - locale(String); + weekends(bool); final Type type; diff --git a/lib/base/errorHandling/default_error_router.dart b/lib/base/errorHandling/default_error_router.dart index ef41cbfe..1628d3c5 100644 --- a/lib/base/errorHandling/default_error_router.dart +++ b/lib/base/errorHandling/default_error_router.dart @@ -1,6 +1,6 @@ import 'package:campus_flutter/base/enums/error_handling_view_type.dart'; import 'package:campus_flutter/base/errorHandling/error_handling_view.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; class DefaultErrorRouter extends StatelessWidget with ErrorHandlingView { @@ -23,8 +23,8 @@ class DefaultErrorRouter extends StatelessWidget with ErrorHandlingView { @override Widget build(BuildContext context) { return exceptionMessage( - errorMessage: context.localizations.unknownError, - fixMessage: context.localizations.pleaseReport, + errorMessage: context.tr("unknownError"), + fixMessage: context.tr("pleaseReport"), context: context, ); } diff --git a/lib/base/errorHandling/dio_exception_router.dart b/lib/base/errorHandling/dio_exception_router.dart index 60113385..a6cfad09 100644 --- a/lib/base/errorHandling/dio_exception_router.dart +++ b/lib/base/errorHandling/dio_exception_router.dart @@ -1,7 +1,7 @@ import 'package:campus_flutter/base/enums/error_handling_view_type.dart'; import 'package:campus_flutter/base/errorHandling/error_handling_view.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; import 'package:dio/dio.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; class DioExceptionRouter extends StatelessWidget with ErrorHandlingView { @@ -26,41 +26,41 @@ class DioExceptionRouter extends StatelessWidget with ErrorHandlingView { switch (dioException.type) { case DioExceptionType.badResponse: return exceptionMessage( - errorMessage: context.localizations.badResponse, - fixMessage: context.localizations.pleaseTryAgain, + errorMessage: context.tr("badResponse"), + fixMessage: context.tr("pleaseTryAgain"), context: context, ); case DioExceptionType.connectionError: return exceptionMessage( - errorMessage: context.localizations.connectionError, - fixMessage: context.localizations.makeSureInternetConnection, + errorMessage: context.tr("connectionError"), + fixMessage: context.tr("makeSureInternetConnection"), context: context, ); case DioExceptionType.cancel: return exceptionMessage( - errorMessage: context.localizations.requestCancelled, - fixMessage: context.localizations.pleaseReport, + errorMessage: context.tr("requestCancelled"), + fixMessage: context.tr("pleaseReport"), context: context, ); case DioExceptionType.connectionTimeout: case DioExceptionType.sendTimeout: case DioExceptionType.receiveTimeout: return exceptionMessage( - errorMessage: context.localizations.connectionTimeout, - fixMessage: context.localizations.makeSureInternetConnection, + errorMessage: context.tr("connectionTimeout"), + fixMessage: context.tr("makeSureInternetConnection"), context: context, ); default: if (dioException.error.toString().contains("SocketException")) { return exceptionMessage( - fixMessage: context.localizations.connectionError, - errorMessage: context.localizations.makeSureInternetConnection, + fixMessage: context.tr("connectionError"), + errorMessage: context.tr("makeSureInternetConnection"), context: context, ); } else { return exceptionMessage( - fixMessage: context.localizations.unknownError, - errorMessage: context.localizations.pleaseReport, + fixMessage: context.tr("unknownError"), + errorMessage: context.tr("pleaseReport"), context: context, ); } diff --git a/lib/base/errorHandling/error_handling_view.dart b/lib/base/errorHandling/error_handling_view.dart index b4a03835..ea9c44f8 100644 --- a/lib/base/errorHandling/error_handling_view.dart +++ b/lib/base/errorHandling/error_handling_view.dart @@ -1,5 +1,6 @@ import 'package:campus_flutter/base/enums/error_handling_view_type.dart'; import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -74,7 +75,7 @@ mixin ErrorHandlingView { if (retry != null || this.retry != null) ...[ ElevatedButton( onPressed: () => retry != null ? retry() : this.retry!(), - child: Text(retryMessage ?? context.localizations.tryAgain), + child: Text(retryMessage ?? context.tr("tryAgain")), ), const Spacer(), ], diff --git a/lib/base/errorHandling/grpc_error_router.dart b/lib/base/errorHandling/grpc_error_router.dart index 53969495..6a35d69f 100644 --- a/lib/base/errorHandling/grpc_error_router.dart +++ b/lib/base/errorHandling/grpc_error_router.dart @@ -1,6 +1,6 @@ import 'package:campus_flutter/base/enums/error_handling_view_type.dart'; import 'package:campus_flutter/base/errorHandling/error_handling_view.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:grpc/grpc.dart'; @@ -24,7 +24,7 @@ class GrpcErrorRouter extends StatelessWidget with ErrorHandlingView { @override Widget build(BuildContext context) { return exceptionMessage( - errorMessage: grpcError.message ?? context.localizations.unknownError, + errorMessage: grpcError.message ?? context.tr("unknownError"), context: context, ); } diff --git a/lib/base/errorHandling/tum_online_api_exception_router.dart b/lib/base/errorHandling/tum_online_api_exception_router.dart index 69ab9e29..d9b31cb0 100644 --- a/lib/base/errorHandling/tum_online_api_exception_router.dart +++ b/lib/base/errorHandling/tum_online_api_exception_router.dart @@ -2,8 +2,9 @@ import 'package:campus_flutter/base/enums/error_handling_view_type.dart'; import 'package:campus_flutter/base/errorHandling/error_handling_view.dart'; import 'package:campus_flutter/base/networking/apis/tumOnlineApi/tum_online_api_exception.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; -class TumOnlineApiExceptionRouter extends StatelessWidget +class TumOnlineApiExceptionRouter extends ConsumerWidget with ErrorHandlingView { TumOnlineApiExceptionRouter({ super.key, @@ -22,10 +23,10 @@ class TumOnlineApiExceptionRouter extends StatelessWidget final TumOnlineApiException tumOnlineApiException; @override - Widget build(BuildContext context) { + Widget build(BuildContext context, WidgetRef ref) { return exceptionMessage( - errorMessage: tumOnlineApiException.message(context), - fixMessage: tumOnlineApiException.recoverySuggestion(context), + errorMessage: tumOnlineApiException.message(context, ref), + fixMessage: tumOnlineApiException.recoverySuggestion(context, ref), retry: tumOnlineApiException.overwriteRetry(context) ?? retry, retryMessage: tumOnlineApiException.overwriteRetryMessage(context), context: context, diff --git a/lib/base/errorHandling/type_error_router.dart b/lib/base/errorHandling/type_error_router.dart index 9ea66588..92a2b510 100644 --- a/lib/base/errorHandling/type_error_router.dart +++ b/lib/base/errorHandling/type_error_router.dart @@ -1,6 +1,6 @@ import 'package:campus_flutter/base/enums/error_handling_view_type.dart'; import 'package:campus_flutter/base/errorHandling/error_handling_view.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; class TypeErrorRouter extends StatelessWidget with ErrorHandlingView { @@ -23,8 +23,8 @@ class TypeErrorRouter extends StatelessWidget with ErrorHandlingView { @override Widget build(BuildContext context) { return exceptionMessage( - errorMessage: context.localizations.decodingError, - fixMessage: context.localizations.pleaseReport, + errorMessage: context.tr("decodingError"), + fixMessage: context.tr("pleaseReport"), context: context, ); } diff --git a/lib/base/extensions/context.dart b/lib/base/extensions/context.dart index 6e8f1ffa..7b93100c 100644 --- a/lib/base/extensions/context.dart +++ b/lib/base/extensions/context.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; extension ContextTheme on BuildContext { ThemeData get theme => Theme.of(this); @@ -10,7 +9,3 @@ extension ContextTheme on BuildContext { Color get primaryColor => Theme.of(this).primaryColor; } - -extension Localization on BuildContext { - AppLocalizations get localizations => AppLocalizations.of(this)!; -} diff --git a/lib/base/localization/app_de.arb b/lib/base/localization/app_de.arb deleted file mode 100644 index 530c7179..00000000 --- a/lib/base/localization/app_de.arb +++ /dev/null @@ -1,368 +0,0 @@ -{ - "home":"Start", - "grades":"Noten", - "lectures":"Vorlesungen", - "calendar":"Kalender", - "identification":"Identifikation", - "places":"Orte", - "settings":"Einstellungen", - "settingsAndFeedback":"Einstellungen & Feedback", - "generalSettings":"Allgemeine Einstellungen", - "comingSoon":"Demnächst verfügbar", - "appearance":"Darstellung", - "language":"Sprache", - "theme":"Theme", - "useWebView":"Web-Ansicht verwenden", - "hideFailedGrades":"Durchgefallene Noten ausblenden", - "defaultMapsApplication":"Standard-Kartenanwendung", - "map":"Karte", - "maps":"Karten", - "contactMore":"Kontakt & Mehr", - "tokenPermissions":"Berechtigungen für Token", - "permissionChangePossibleInTUMonline":"Du kannst deine Berechtigungen in TUMOnline ändern", - "login":"Anmelden", - "notLoggedIn":"Nicht angemeldet", - "welcomeToTheApp":"Willkommen in der\n TUM Campus App", - "enterYourIDToStart":"Gib deine TUM ID ein, um zu starten", - "continueWithoutID":"Ohne TUM ID fortfahren", - "unknown":"Unbekannt", - "loading":"Lade", - "loadingName":"Lade {name}", - "@loadingName":{ - "description":"Während Ladeanimationen angezeigt", - "placeholders":{ - "name":{ - "type":"String", - "example":"Noten" - } - } - }, - "checkPermissions":"Berechtigungen prüfen", - "done":"Fertig", - "studyRoom":"Lernraum", - "studyRooms":"Lernräume", - "nearestStudyRooms":"Nächste Lernräume", - "noNearFreeStudyRoomsFound":"Keine Lernräume in deiner Nähe gefunden", - "mostSearchedRooms":"Meist gesuchte Räume", - "tuition":"Tuition", - "tuitionFees":"Studiengebühren", - "tuitionPaid":"Bezahlt", - "tuitionDueDate":"Fälligkeitsdatum", - "tuitionOpenAmount":"Offener Betrag", - "versionNumber":"Version {number} ({build})", - "@versionNumber":{ - "description":"Aktuelle Version der App", - "placeholders":{ - "number":{ - "type":"String", - "example":"-.-.-" - }, - "build":{ - "type":"String", - "example":"1" - } - } - }, - "checkToken":"Token prüfen", - "tryAgain":"Erneut versuchen", - "contactSupport":"Support kontaktieren", - "cafeteria":"Mensa", - "cafeterias":"Mensen", - "latestNews":"Neueste Nachrichten", - "scheduledLectureDates":"Termine", - "@scheduledLectureDates":{ - "description":"Link-Text in der Ansicht der Vorlesungslinks" - }, - "lectureExamDate":"Prüfung", - "@lectureExamDate":{ - "description":"Link-Text in der Ansicht der Vorlesungslinks" - }, - "lectureCurriculum":"Lehrplan", - "@lectureCurriculum":{ - "description":"Link-Text in der Ansicht der Vorlesungslinks" - }, - "basicLectureInformation":"Grundlegende Informationen", - "detailedLectureInformation":"Detaillierte Informationen", - "lectureLinks":"Veranstaltungslinks", - "thisMeeting":"Dieser Termin", - "lectureDetails":"Vorlesungsdetails", - "noLecturesSelected":"Keine Vorlesungen ausgewählt", - "showDirections":"Wegbeschreibung anzeigen", - "notAvailableAbbrev":"n. v.", - "becomeABetaTester":"Werde Beta-Tester", - "usOnGitHub":"TUM-Dev auf GitHub", - "lastUpdatedAt":"zuletzt aktualisiert {lastUpdate}", - "@lastUpdatedAt":{ - "description":"Wann etwas zuletzt aktualisiert wurde", - "placeholders":{ - "lastUpdate":{ - "type":"String", - "format":"vor 42 Sekunden" - } - } - }, - "averageGrade":"Durchschnittsnote", - "fullSemesterName":"{semesterType, select, W{Wintersemester {year}/{nextYearShort}} S{Sommersemester {year}} other{Unbekannt}}", - "@fullSemesterName":{ - "description":"Bezeichnung des Semesters", - "placeholders":{ - "semesterType":{ - "type":"String", - "example":"W" - }, - "year":{ - "type":"int", - "example":"2023" - }, - "nextYearShort":{ - "type":"int", - "example":"2024" - } - } - }, - "shortSemesterName":"{semesterType, select, W{WiSe {year}/{nextYearShort}} S{SoSe {year}} other{}}", - "@shortSemesterName":{ - "description":"Kurzbezeichnung des Semesters", - "placeholders":{ - "semesterType":{ - "type":"String", - "example":"W" - }, - "year":{ - "type":"int", - "example":"2023" - }, - "nextYearShort":{ - "type":"int", - "example":"2024" - } - } - }, - "lecture":"Vorlesung", - "courseContents":"Inhalte der Veranstaltung", - "courseObjective":"Ziel der Veranstaltung", - "note":"Anmerkung", - "exercise":"Tutorium", - "seminar":"Übung", - "tutorial":"Praktikum", - "practicalCourse":"Seminar", - "lectureWithIntegratedExcercises":"Vorlesung mit integrierten Übungen", - "written":"Schriftlich", - "graded":"Beurteilt", - "writtenAndOral":"Schriftlich/Mündlich", - "oral":"Mündlich", - "source":"Quelle: {source}", - "@source":{ - "description":"Woher dies stammt", - "placeholders":{ - "source":{ - "type":"String?", - "example":"Newspread Live CH magistrale" - } - } - }, - "news":"Nachrichten", - "movies":"Filme", - "personalData":"Persönliche Daten", - "calendarViewToday":"Heute", - "calendarViewDay":"Tag", - "calendarViewWeek":"Woche", - "calendarViewMonth":"Monat", - "events":"Veranstaltungen", - "noUpcomingEvents":"Keine Anstehenden Ereignisse", - "noEventsToday":"Keine Ereignisse heute", - "departures":"Abfahrten", - "departure":"Abfahrt", - "direction":"Richtung", - "station":"Haltestelle: ", - "line":"Linie", - "now":"JETZT", - "free":"Frei", - "occupiedUntil":"Belegt bis {occupiedEndTime}", - "@occupiedUntil":{ - "description":"time until occupied", - "placeholders":{ - "occupiedEndTime":{ - "type":"DateTime", - "format":"Hm" - } - } - }, - "rooms":"Räume", - "roomDetails":"Raumdetails", - "building":"Gebäude", - "nfreeRooms":"{count, plural, =0{Keine freien Räume} =1{1 freier Raum} other{{count} freie Räume}}", - "@nfreeRooms":{ - "description":"How many free rooms there are", - "placeholders":{ - "count":{ - "type":"num", - "format":"compact" - } - } - }, - "mealPlans":"Essenspläne", - "noEntriesFound":"Keine {category} gefunden!", - "@noEntriesFound":{ - "description":"Category", - "placeholders":{ - "category":{ - "type":"String", - "example":"Grades" - } - } - }, - "enterQueryStart":"Stelle eine Suchanfrage", - "personalLectures":"Persönliche Vorlesungen", - "persons":"Personen", - "search":"Suche", - "today":"Heute", - "tomorrow":"Morgen", - "roomSearch":"Raum Suche", - "personSearch":"Personen Suche", - "badResponse":"Ungültige Antwort", - "pleaseTryAgain":"Bitte versuche es erneut!", - "connectionError":"Verbindungsfehler", - "makeSureInternetConnection":"Stelle sicher, dass du eine\n funktionierende Internetverbindung hast!", - "requestCancelled":"Anfrage abgebrochen", - "pleaseReport":"Bitte melden Sie dies als Fehler \nper E-Mail oder auf GitHub", - "connectionTimeout":"Zeitüberschreitung", - "decodingError":"Dekodierungsfehler", - "unknownError":"Unbekannter Fehler", - "monday":"Montag", - "tuesday":"Dienstag", - "wednesday":"Mittwoch", - "thursday":"Donnerstag", - "friday":"Freitag", - "weekend":"Wochenende", - "openingHours":"Öffnungszeiten", - "open":"{day} offen von {start} - {end}", - "@open":{ - "description":"Opening Times", - "placeholders":{ - "day":{ - "type":"String", - "example":"Monday" - }, - "start":{ - "type":"String", - "example":"11:00" - }, - "end":{ - "type":"String", - "example":"14:00" - } - } - }, - "closed":"Geschlossen", - "closedOn":"{day} geschlossen", - "@closedOn":{ - "description":"Day", - "placeholders":{ - "day":{ - "type":"String", - "example":"Montag" - } - } - }, - "closedToday":"Heute geschlossen", - "submitFeedback":"Feedback einreichen", - "name":"Name", - "message":"Nachricht", - "shareLocation":"Aktuellen Standort teilen", - "shareDeviceInformation":"Informationen über das Gerät teilen", - "submit":"Senden", - "yourMessage":"Deine Nachricht...", - "yourName":"Dein Name...", - "yourEmailTitle":"Deine E-Mail-Adresse", - "yourEmail":"deineemail@tum.de", - "invalidName":"Ungültiger Name", - "invalidMessage":"Ungültige Nachricht", - "invalidEmail":"Ungültige E-Mail-Adresse", - "unableToSend":"Nachricht kann nicht gesendet werden!", - "successfullySent":"Nachricht erfolgreich gesendet!\n Danke für Dein Feedback!", - "signInToTumOnline":"1. Melden Dich bei TUMonline an\n", - "selectTokenManagement":"2. Token-Verwaltung auswählen\n", - "activateToken":"3. Aktivieren Sie den neu erstellten Token und\n aktivieren Sie die gewünschten Berechtigungen", - "location":"Standort", - "locationOnboarding":"Aktiviere Standorte, um personalisierte Erlebnisse zu erreichen und Deinen Standort auf Raumfinder-Karten zu sehen.", - "continueOnboarding":"Weiter", - "showMore":"Mehr Anzeigen", - "licenses":"Lizenzen", - "privacyPolicy":"Datenschutzrichtlinie", - "createCalendarEvent":"Kalenderereignis erstellen", - "title":"Titel", - "annotation":"Bemerkung", - "from":"Von", - "to":"Bis", - "timeFrame":"Zeitrahmen", - "delete":"Löschen", - "deviceSettings":"Geräte-Einstellungen", - "edit":"Editieren", - "digitalStudentCard":"Digitale StudentCard", - "currentlyInBeta":"Aktuell in Testphase mit eingeschränkter Funktionalität!", - "validUntil":"Gültig bis", - "libraryBarcode":"Bibliotheks-Barcode", - "libraryNumber":"Bibliotheksnummer", - "birthday":"Geb.", - "studyId":"Matr.Nr.", - "locationServiceDisabled":"Ortungsdienst deaktiviert", - "permissionDenied":"Erlaubnis verweigert", - "onlyLetters":"Achte drauf, nur Buchstaben zu benutzen", - "onlyNumbers":"Achte drauf, nur Zahlen zu benutzen", - "personDetails":"Details zur Person", - "contact":"Kontakt", - "room":"Raum", - "back":"Zurück", - "editHome":"Home Anpassen", - "reorderDisable":"Widgets neu anordnen & deaktivieren", - "reset":"Zurücksetzen", - "selectPreferred":"Wähle deine bevorzugte {item}", - "@selectPreferred":{ - "description":"Item", - "placeholders":{ - "item":{ - "type":"String", - "example":"Cafeteria" - } - } - }, - "closest":"Näheste", - "noClosestStudyRoom":"Näheste Lernräume nicht ermittelbar!", - "cancel":"Abbrechen", - "selectAction":"Wähle eine Aktion", - "openIn":"In {item} öffnen", - "@openIn":{ - "description":"Item", - "placeholders":{ - "item":{ - "type":"String", - "example":"Apple Maps" - } - } - }, - "unknownDirection":"Unbekannte Richtung", - "showWeekends":"Wochenenden anzeigen", - "color":"Farbe", - "resetLogin":"Zurücksetzen & Anmelden", - "resetPreferences":"Einstellungen zurücksetzen", - "noPermission":"Keine Berechtigung", - "tokenNotConfirmed":"Token nicht bestätigt", - "loginNeeded":"Login benötigt", - "rateExceeded":"Anfragequote überschritten", - "limitReached":"Token-Limit erreicht, maximal 10 Token pro Benutzer erlaubt", - "noUserSpecified":"Kein Benutzer spezifiziert", - "noUserFound":"Kein Benutzer gefunden", - "personNotFound":"Person nicht gefunden", - "invalidSearch":"Ungültige Suche", - "unknownException":"Unbekannter Fehler", - "noPermissionRecovery":"Stelle sicher, dass du die richtigen Berechtigungen für deinen Token aktivierst!", - "tokenNotConfirmedRecovery":"Gehe zu TumOnline und bestätige deinen Token!", - "loginNeededRecovery":"Diese Funktion kann nur genutzt werden, wenn du dich anmeldest!", - "rateExceededRecovery":"Bitte versuche es später noch einmal!", - "limitReachedRecovery":"Bitte lösche einen deiner Token!", - "noUserSpecifiedRecovery":"Bitte gib deine Tum ID ein!", - "noUserFoundRecovery":"Überprüfe, ob du deine Tum ID richtig eingegeben hast!", - "personNotFoundRecovery":"Überprüfe, ob du den Namen richtig eingegeben hast!", - "invalidSearchRecovery":"Ein Suchbegriff mit weniger als 4 Zeichen darf keine Wildcards oder Sonderzeichen enthalten!" -} diff --git a/lib/base/localization/app_en.arb b/lib/base/localization/app_en.arb deleted file mode 100644 index e01b0b15..00000000 --- a/lib/base/localization/app_en.arb +++ /dev/null @@ -1,368 +0,0 @@ -{ - "home":"Home", - "grades":"Grades", - "lectures":"Lectures", - "calendar":"Calendar", - "identification":"Identification", - "places":"Places", - "settings":"Settings", - "settingsAndFeedback":"Settings & Feedback", - "generalSettings":"General Settings", - "comingSoon":"Coming Soon", - "language":"Language", - "appearance":"Appearance", - "theme":"Theme", - "useWebView":"Use Web View", - "hideFailedGrades":"Hide Failed Grades", - "defaultMapsApplication":"Default Maps Application", - "map":"Map", - "maps":"Maps", - "contactMore":"Contact & More", - "tokenPermissions":"Token Permissions", - "permissionChangePossibleInTUMonline":"You can change your permissions on TUMOnline", - "login":"Login", - "notLoggedIn":"Not Logged In", - "welcomeToTheApp":"Welcome to the TUM Campus App", - "enterYourIDToStart":"Enter your TUM ID to get started", - "continueWithoutID":"Continue without TUM ID", - "unknown":"Unknown", - "loading":"Loading", - "loadingName":"Loading {name}", - "@loadingName":{ - "description":"Shown during loading animations", - "placeholders":{ - "name":{ - "type":"String", - "example":"Grades" - } - } - }, - "checkPermissions":"Check Permissions", - "done":"Done", - "studyRoom":"Study Room", - "studyRooms":"Study Rooms", - "nearestStudyRooms":"Nearest Study Rooms", - "noNearFreeStudyRoomsFound":"No Study Rooms Near You Found!", - "mostSearchedRooms":"Most Searched Rooms", - "tuition":"Tuition", - "tuitionFees":"Tuition fees", - "tuitionPaid":"Tuition Paid", - "tuitionDueDate":"Due Date", - "tuitionOpenAmount":"Open Amount", - "versionNumber":"Version {number} ({build})", - "@versionNumber":{ - "description":"What version number the app is currently on", - "placeholders":{ - "number":{ - "type":"String", - "example":"-.-.-" - }, - "build":{ - "type":"String", - "example":"1" - } - } - }, - "checkToken":"Check Token", - "tryAgain":"Try Again", - "contactSupport":"Contact Support", - "cafeteria":"Cafeteria", - "cafeterias":"Cafeterias", - "latestNews":"Latest News", - "scheduledLectureDates":"Dates", - "@scheduledLectureDates":{ - "description":"Link-text in the lecture links view" - }, - "lectureExamDate":"Exam", - "@lectureExamDate":{ - "description":"Link-text in the lecture links view" - }, - "lectureCurriculum":"Curriculum", - "@lectureCurriculum":{ - "description":"Link-text in the lecture links view" - }, - "basicLectureInformation":"Basic Lecture Information", - "detailedLectureInformation":"Detailed Lecture Information", - "lectureLinks":"Lecture Links", - "thisMeeting":"This Meeting", - "lectureDetails":"Lecture Details", - "noLecturesSelected":"no lecture selected", - "showDirections":"Show Directions", - "notAvailableAbbrev":"n/a", - "becomeABetaTester":"Become a Beta Tester", - "usOnGitHub":"TUM-Dev on GitHub", - "lastUpdatedAt":"last updated {lastUpdate}", - "@lastUpdatedAt":{ - "description":"When something was last updated", - "placeholders":{ - "lastUpdate":{ - "type":"String", - "format":"42 seconds ago" - } - } - }, - "averageGrade":"Average Grade", - "fullSemesterName":"{semesterType, select, W{Wintersemester {year}/{nextYearShort}} S{Summersemester {year}} other{Unknown}}", - "@fullSemesterName":{ - "description":"When something was last updated", - "placeholders":{ - "semesterType":{ - "type":"String", - "example":"W" - }, - "year":{ - "type":"int", - "example":"2023" - }, - "nextYearShort":{ - "type":"int", - "example":"2024" - } - } - }, - "shortSemesterName":"{semesterType, select, W{WiSe {year}/{nextYearShort}} S{SoSe {year}} other{}}", - "@shortSemesterName":{ - "description":"When something was last updated", - "placeholders":{ - "semesterType":{ - "type":"String", - "example":"W" - }, - "year":{ - "type":"int", - "example":"2023" - }, - "nextYearShort":{ - "type":"int", - "example":"2024" - } - } - }, - "lecture":"Lecture", - "courseContents":"Course Contents", - "courseObjective":"Course Objective", - "note":"Note", - "exercise":"Exercise", - "seminar":"Seminar", - "tutorial":"Exercise", - "practicalCourse":"Practical Course", - "lectureWithIntegratedExcercises":"Lecture with integrated Exercises", - "written":"Written", - "graded":"Graded", - "writtenAndOral":"WrittenOral", - "oral":"Oral", - "source":"Source: {source}", - "@source":{ - "description":"Where this is from", - "placeholders":{ - "source":{ - "type":"String?", - "example":"Newspread Live CH magistrale" - } - } - }, - "news":"News", - "movies":"Movies", - "personalData":"Personal Data", - "calendarViewToday":"Today", - "calendarViewDay":"Day", - "calendarViewWeek":"Week", - "calendarViewMonth":"Month", - "events":"Events", - "noUpcomingEvents":"No Upcoming Events", - "noEventsToday":"No Events Today", - "departures":"Departures", - "departure":"Departure", - "direction":"Direction", - "station":"Station: ", - "line":"Line", - "now":"NOW", - "free":"Free", - "occupiedUntil":"Occupied until {occupiedEndTime}", - "@occupiedUntil":{ - "description":"time until occupied", - "placeholders":{ - "occupiedEndTime":{ - "type":"DateTime", - "format":"Hm" - } - } - }, - "rooms":"Rooms", - "roomDetails":"Room Details", - "building":"Building", - "nfreeRooms":"{count, plural, =0{no free rooms} =1{1 free room} other{{count} free rooms}}", - "@nfreeRooms":{ - "description":"How many free rooms there are", - "placeholders":{ - "count":{ - "type":"num", - "format":"compact" - } - } - }, - "mealPlans":"Meal Plans", - "noEntriesFound":"No {category} Found!", - "@noEntriesFound":{ - "description":"Category", - "placeholders":{ - "category":{ - "type":"String", - "example":"Grades" - } - } - }, - "enterQueryStart":"Enter a Query to Start", - "personalLectures":"Personal Lectures", - "persons":"Persons", - "search":"Search", - "today":"Today", - "tomorrow":"Tomorrow", - "roomSearch":"Room Search", - "personSearch":"Person Search", - "badResponse":"Bad Response", - "pleaseTryAgain":"Please try again!", - "connectionError":"Connection Error", - "makeSureInternetConnection":"Make sure you have \na working internet connection!", - "requestCancelled":"Request Cancelled", - "pleaseReport":"Please report this is as a bug \nvia Email or on GitHub", - "connectionTimeout":"Connection Timeout", - "decodingError":"Decoding Error", - "unknownError":"Unknown Error", - "monday":"Monday", - "tuesday":"Tuesday", - "wednesday":"Wednesday", - "thursday":"Thursday", - "friday":"Friday", - "weekend":"Weekend", - "openingHours":"Opening Hours", - "open":"Open {day} from {start} - {end}", - "@open":{ - "description":"Opening Times", - "placeholders":{ - "day":{ - "type":"String", - "example":"Monday" - }, - "start":{ - "type":"String", - "example":"11:00" - }, - "end":{ - "type":"String", - "example":"14:00" - } - } - }, - "closed":"Closed", - "closedOn":"Closed on {day}", - "@closedOn":{ - "description":"Day", - "placeholders":{ - "day":{ - "type":"String", - "example":"Monday" - } - } - }, - "closedToday":"Closed Today", - "submitFeedback":"Submit Feedback", - "name":"Name", - "message":"Message", - "shareLocation":"Share Current Location", - "shareDeviceInformation":"Share Device's Information", - "submit":"Submit", - "yourMessage":"Your Message...", - "yourName":"Your Name...", - "yourEmailTitle":"Your Email Address", - "yourEmail":"youremail@tum.de", - "invalidName":"Invalid Name", - "invalidMessage":"Invalid Message", - "invalidEmail":"Invalid Email Address", - "unableToSend":"Unable to Send Message!", - "successfullySent":"Message Successfully Sent!\n Thanks for Your Feedback!", - "signInToTumOnline":"1. Sign in to TUMonline\n", - "selectTokenManagement":"2. Select Token-Management\n", - "activateToken":"3. Activate the newly created token \nand enable your desired permissions", - "location":"Location", - "locationOnboarding":"Enable locations to access personalized experiences and your location on the room finder maps.", - "continueOnboarding":"Continue", - "showMore":"Show More", - "licenses":"Licenses", - "privacyPolicy":"Privacy Policy", - "createCalendarEvent":"Create Calendar Event", - "title":"Title", - "annotation":"Annotation", - "from":"From", - "to":"To", - "timeFrame":"Time Frame", - "delete":"Delete", - "deviceSettings":"Device Settings", - "edit":"Edit", - "digitalStudentCard":"Digital StudentCard", - "currentlyInBeta":"Currently in Beta with Limited Functionality!", - "validUntil":"Valid until", - "libraryBarcode":"Library Barcode", - "libraryNumber":"Library Number", - "birthday":"Birthday", - "studyId":"Study ID", - "locationServiceDisabled":"Location Service disabled", - "permissionDenied":"Permission denied", - "onlyLetters":"Make Sure to Use Letters Only", - "onlyNumbers":"Make Sure to Use Numbers Only", - "personDetails":"Person Details", - "contact":"Contact", - "room":"Room", - "back":"Back", - "editHome":"Edit Home", - "reorderDisable":"Reorder & Disable Widgets", - "reset":"Reset", - "selectPreferred":"Select your preferred {item}", - "@selectPreferred":{ - "description":"Item", - "placeholders":{ - "item":{ - "type":"String", - "example":"Cafeteria" - } - } - }, - "closest":"Closest", - "noClosestStudyRoom":"Closest learning spaces cannot be determined!", - "cancel":"Cancel", - "selectAction":"Select an action", - "openIn":"Open in {item}", - "@openIn":{ - "description":"Item", - "placeholders":{ - "item":{ - "type":"String", - "example":"Apple Maps" - } - } - }, - "unknownDirection":"Unknown Direction", - "showWeekends":"Show Weekends", - "color":"Color", - "resetLogin":"Reset & Login", - "resetPreferences":"Reset Preferences", - "noPermission":"No Permission", - "tokenNotConfirmed":"Token Not Confirmed", - "loginNeeded":"Login Needed", - "rateExceeded":"Request Rate Exceeded", - "limitReached":"Token limit Reached, Maximum 10 Tokens per User Allowed", - "noUserSpecified":"No User Specified", - "noUserFound":"No User Found", - "personNotFound":"Person Not Found", - "invalidSearch":"Invalid Search", - "unknownException":"Unknown Exception", - "noPermissionRecovery":"Make sure to enable the right permissions for your token!", - "tokenNotConfirmedRecovery":"Go to TumOnline and confirm your token!", - "loginNeededRecovery":"This feature can only be used if you log in!", - "rateExceededRecovery":"Please try again later!", - "limitReachedRecovery":"Please delete one of your tokens!", - "noUserSpecifiedRecovery":"Please enter your Tum ID!", - "noUserFoundRecovery":"Make sure you entered your Tum ID correctly!", - "personNotFoundRecovery":"Make sure you entered the name correctly!", - "invalidSearchRecovery":"A search string with less than 4 characters must not contain wildcards or special characters!" -} diff --git a/lib/base/networking/apis/tumOnlineApi/tum_online_api_exception.dart b/lib/base/networking/apis/tumOnlineApi/tum_online_api_exception.dart index 70511857..b7aab34b 100644 --- a/lib/base/networking/apis/tumOnlineApi/tum_online_api_exception.dart +++ b/lib/base/networking/apis/tumOnlineApi/tum_online_api_exception.dart @@ -1,7 +1,10 @@ -import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:campus_flutter/base/enums/credentials.dart'; import 'package:campus_flutter/base/networking/protocols/api_exception.dart'; import 'package:campus_flutter/base/routing/routes.dart'; +import 'package:campus_flutter/onboardingComponent/viewModels/onboarding_viewmodel.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; class TumOnlineApiException implements ApiException { @@ -46,52 +49,87 @@ class TumOnlineApiException implements ApiException { } @override - String message(BuildContext context) { - switch (tumOnlineApiExceptionType) { - case TumOnlineApiExceptionNoPermission _: - return context.localizations.noPermission; - case TumOnlineApiExceptionTokenNotConfirmed _: - return context.localizations.tokenNotConfirmed; - case TumOnlineApiExceptionInvalidToken _: - return context.localizations.loginNeeded; - case TumOnlineApiExceptionRequestRate _: - return context.localizations.rateExceeded; - case TumOnlineApiExceptionTokenLimitReached _: - return context.localizations.limitReached; - case TumOnlineApiExceptionNoUserSpecified _: - return context.localizations.noUserSpecified; - case TumOnlineApiExceptionNoUserFound _: - return context.localizations.noUserFound; - case TumOnlineApiExceptionPersonNotFound _: - return context.localizations.personNotFound; - case TumOnlineApiExceptionInvalidSearchString _: - return context.localizations.invalidSearch; - case TumOnlineApiExceptionUnknown _: - return context.localizations.unknownException; + String message(BuildContext? context, WidgetRef? ref) { + if (context != null && ref != null) { + switch (tumOnlineApiExceptionType) { + case TumOnlineApiExceptionNoPermission _: + return context.tr("noPermission"); + case TumOnlineApiExceptionTokenNotConfirmed _: + return context.tr("tokenNotConfirmed"); + case TumOnlineApiExceptionInvalidToken _: + if (ref.read(onboardingViewModel).credentials.value == + Credentials.tumId) { + return context.tr("tokenInvalid"); + } else { + return context.tr("loginNeeded"); + } + case TumOnlineApiExceptionRequestRate _: + return context.tr("rateExceeded"); + case TumOnlineApiExceptionTokenLimitReached _: + return context.tr("limitReached"); + case TumOnlineApiExceptionNoUserSpecified _: + return context.tr("noUserSpecified"); + case TumOnlineApiExceptionNoUserFound _: + return context.tr("noUserFound"); + case TumOnlineApiExceptionPersonNotFound _: + return context.tr("personNotFound"); + case TumOnlineApiExceptionInvalidSearchString _: + return context.tr("invalidSearch"); + case TumOnlineApiExceptionUnknown _: + return context.tr("unknownException"); + } + } else { + switch (tumOnlineApiExceptionType) { + case TumOnlineApiExceptionNoPermission _: + return tr("noPermission"); + case TumOnlineApiExceptionTokenNotConfirmed _: + return tr("tokenNotConfirmed"); + case TumOnlineApiExceptionInvalidToken _: + return tr("tokenInvalid"); + case TumOnlineApiExceptionRequestRate _: + return tr("rateExceeded"); + case TumOnlineApiExceptionTokenLimitReached _: + return tr("limitReached"); + case TumOnlineApiExceptionNoUserSpecified _: + return tr("noUserSpecified"); + case TumOnlineApiExceptionNoUserFound _: + return tr("noUserFound"); + case TumOnlineApiExceptionPersonNotFound _: + return tr("personNotFound"); + case TumOnlineApiExceptionInvalidSearchString _: + return tr("invalidSearch"); + case TumOnlineApiExceptionUnknown _: + return tr("unknownException"); + } } } @override - String? recoverySuggestion(BuildContext context) { + String? recoverySuggestion(BuildContext context, WidgetRef ref) { switch (tumOnlineApiExceptionType) { case TumOnlineApiExceptionNoPermission _: - return context.localizations.noPermissionRecovery; + return context.tr("noPermissionRecovery"); case TumOnlineApiExceptionTokenNotConfirmed _: - return context.localizations.tokenNotConfirmedRecovery; + return context.tr("tokenNotConfirmedRecovery"); case TumOnlineApiExceptionInvalidToken _: - return context.localizations.loginNeededRecovery; + if (ref.read(onboardingViewModel).credentials.value == + Credentials.tumId) { + return context.tr("tokenInvalidRecovery"); + } else { + return context.tr("loginNeededRecovery"); + } case TumOnlineApiExceptionRequestRate _: - return context.localizations.rateExceededRecovery; + return context.tr("rateExceededRecovery"); case TumOnlineApiExceptionTokenLimitReached _: - return context.localizations.limitReachedRecovery; + return context.tr("limitReachedRecovery"); case TumOnlineApiExceptionNoUserSpecified _: - return context.localizations.noUserSpecifiedRecovery; + return context.tr("noUserSpecifiedRecovery"); case TumOnlineApiExceptionNoUserFound _: - return context.localizations.noUserFoundRecovery; + return context.tr("noUserFoundRecovery"); case TumOnlineApiExceptionPersonNotFound _: - return context.localizations.personNotFoundRecovery; + return context.tr("personNotFoundRecovery"); case TumOnlineApiExceptionInvalidSearchString _: - return context.localizations.invalidSearchRecovery; + return context.tr("invalidSearchRecovery"); case TumOnlineApiExceptionUnknown unknown: return unknown.message; } @@ -99,7 +137,7 @@ class TumOnlineApiException implements ApiException { @override String toString() { - return "TumOnlineException: $message"; + return "TumOnlineException: ${message(null, null)}"; } @override @@ -116,7 +154,7 @@ class TumOnlineApiException implements ApiException { String? overwriteRetryMessage(BuildContext context) { switch (tumOnlineApiExceptionType) { case TumOnlineApiExceptionInvalidToken _: - return context.localizations.login; + return context.tr("login"); default: return null; } diff --git a/lib/base/networking/apis/tumOnlineApi/tum_online_api_service.dart b/lib/base/networking/apis/tumOnlineApi/tum_online_api_service.dart index 43921abf..79a2276c 100644 --- a/lib/base/networking/apis/tumOnlineApi/tum_online_api_service.dart +++ b/lib/base/networking/apis/tumOnlineApi/tum_online_api_service.dart @@ -9,8 +9,10 @@ class TumOnlineServiceTokenRequest extends TumOnlineService { TumOnlineServiceTokenRequest({required this.tumId, required this.deviceName}); @override - Map getParameters() => - {"pUsername": tumId, "pTokenName": deviceName}; + Map getParameters() => { + "pUsername": tumId, + "pTokenName": deviceName, + }; } class TumOnlineServiceTokenConfirmation extends TumOnlineService {} diff --git a/lib/base/networking/cache/cache_entry.g.dart b/lib/base/networking/cache/cache_entry.g.dart index 8fa1aa5c..93d8a762 100644 --- a/lib/base/networking/cache/cache_entry.g.dart +++ b/lib/base/networking/cache/cache_entry.g.dart @@ -49,7 +49,7 @@ const CacheEntrySchema = CollectionSchema( getId: _cacheEntryGetId, getLinks: _cacheEntryGetLinks, attach: _cacheEntryAttach, - version: '3.1.5', + version: '3.1.7', ); int _cacheEntryEstimateSize( diff --git a/lib/base/networking/protocols/api_exception.dart b/lib/base/networking/protocols/api_exception.dart index 6d5700a6..975af6cc 100644 --- a/lib/base/networking/protocols/api_exception.dart +++ b/lib/base/networking/protocols/api_exception.dart @@ -1,12 +1,13 @@ import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:json_annotation/json_annotation.dart'; part 'api_exception.g.dart'; abstract class ApiException implements Exception { - String message(BuildContext context); + String message(BuildContext? context, WidgetRef? ref); - String? recoverySuggestion(BuildContext context); + String? recoverySuggestion(BuildContext context, WidgetRef ref); Function()? overwriteRetry(BuildContext context); diff --git a/lib/base/util/delayed_loading_indicator.dart b/lib/base/util/delayed_loading_indicator.dart index 46413d18..1de5d8c6 100644 --- a/lib/base/util/delayed_loading_indicator.dart +++ b/lib/base/util/delayed_loading_indicator.dart @@ -1,4 +1,4 @@ -import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; class DelayedLoadingIndicator extends StatelessWidget { @@ -27,8 +27,8 @@ class DelayedLoadingIndicator extends StatelessWidget { const CircularProgressIndicator.adaptive(), Text( name != null - ? context.localizations.loadingName(name!) - : context.localizations.loading, + ? context.tr("loadingName", args: [name!]) + : context.tr("loading"), ), ], ), diff --git a/lib/base/util/last_updated_text.dart b/lib/base/util/last_updated_text.dart index 19e0ecf7..8f99b536 100644 --- a/lib/base/util/last_updated_text.dart +++ b/lib/base/util/last_updated_text.dart @@ -1,4 +1,4 @@ -import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:timeago/timeago.dart' as timeago; @@ -13,11 +13,14 @@ class LastUpdatedText extends ConsumerWidget { timeago.setLocaleMessages("de", timeago.DeMessages()); return Center( child: Text( - context.localizations.lastUpdatedAt( - timeago.format( - dateTime, - locale: Localizations.localeOf(context).languageCode, - ), + context.tr( + "lastUpdatedAt", + args: [ + timeago.format( + dateTime, + locale: Localizations.localeOf(context).languageCode, + ), + ], ), style: Theme.of(context) .textTheme diff --git a/lib/base/util/map_launcher.dart b/lib/base/util/map_launcher.dart index 4e5aef1e..386ce082 100644 --- a/lib/base/util/map_launcher.dart +++ b/lib/base/util/map_launcher.dart @@ -1,6 +1,7 @@ import 'package:campus_flutter/base/classes/location.dart'; import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/base/util/padded_divider.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:go_router/go_router.dart'; @@ -24,7 +25,7 @@ Future showDirectionsDialog( padding: EdgeInsets.only( bottom: context.halfPadding, ), - child: Text(context.localizations.selectAction), + child: Text(context.tr("selectAction")), ), Card( child: ListView.separated( @@ -41,7 +42,7 @@ Future showDirectionsDialog( ), ), title: Text( - context.localizations.openIn(value[index].mapName), + context.tr("openIn", args: [value[index].mapName]), ), onTap: () => MapLauncher.showMarker( mapType: value[index].mapType, @@ -60,7 +61,7 @@ Future showDirectionsDialog( ), child: ElevatedButton( onPressed: () => context.pop(), - child: Text(context.localizations.cancel), + child: Text(context.tr("cancel")), ), ), ], diff --git a/lib/base/util/places_util.dart b/lib/base/util/places_util.dart index 33eceee3..f6ad1175 100644 --- a/lib/base/util/places_util.dart +++ b/lib/base/util/places_util.dart @@ -2,8 +2,8 @@ import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/base/extensions/date_time.dart'; import 'package:campus_flutter/base/util/string_parser.dart'; import 'package:campus_flutter/placesComponent/model/cafeterias/opening_hours.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; class PlacesUtil { static Widget? openingHours( @@ -16,10 +16,12 @@ class PlacesUtil { padding: EdgeInsets.only(left: context.padding), child: Text( dateTime.isAtSameDay(DateTime.now()) - ? context.localizations.closedToday - : context.localizations.closedOn( - DateFormat.EEEE(context.localizations.localeName) - .format(dateTime), + ? context.tr("closedToday") + : context.tr( + "closedOn", + args: [ + DateFormat.EEEE(context.tr("localeName")).format(dateTime), + ], ), ), ); @@ -28,10 +30,9 @@ class PlacesUtil { return Padding( padding: EdgeInsets.only(left: context.padding), child: Text( - context.localizations.open( - dayString, - openingHours!.$2!.start, - openingHours.$2!.end, + context.tr( + "open", + args: [dayString, openingHours!.$2!.start, openingHours.$2!.end], ), ), ); diff --git a/lib/base/util/string_parser.dart b/lib/base/util/string_parser.dart index 30884b61..45b52524 100644 --- a/lib/base/util/string_parser.dart +++ b/lib/base/util/string_parser.dart @@ -1,31 +1,46 @@ import 'package:campus_flutter/base/extensions/date_time.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; -import 'package:intl/intl.dart'; class StringParser { static String toFullSemesterName(BuildContext context, String semester) { final yearOffset = int.parse(semester.substring(0, 2)); - return context.localizations.fullSemesterName( - semester.substring(2), - 2000 + yearOffset, - yearOffset + 1, - ); + if (semester.substring(2) == "W") { + return context.tr( + "fullWinter", + args: [(2000 + yearOffset).toString(), (yearOffset + 1).toString()], + ); + } else if (semester.substring(2) == "S") { + return context.tr( + "fullSummer", + args: [(2000 + yearOffset).toString(), (yearOffset + 1).toString()], + ); + } else { + return context.tr("unknown"); + } } static String toShortSemesterName(BuildContext context, String semester) { final yearOffset = int.parse(semester.substring(0, 2)); - return context.localizations.shortSemesterName( - semester.substring(2), - 2000 + yearOffset, - yearOffset + 1, - ); + if (semester.substring(2) == "W") { + return context.tr( + "shortWinter", + args: [(2000 + yearOffset).toString(), (yearOffset + 1).toString()], + ); + } else if (semester.substring(2) == "S") { + return context.tr( + "shortSummer", + args: [(2000 + yearOffset).toString(), (yearOffset + 1).toString()], + ); + } else { + return context.tr("unknown"); + } } static String dateFormatter(DateTime dateTime, BuildContext context) { return DateFormat( DateFormat.YEAR_MONTH_DAY, - context.localizations.localeName, + context.locale.languageCode, ).format(dateTime); } @@ -62,9 +77,9 @@ class StringParser { static String getDayString(DateTime dateTime, BuildContext context) { final today = DateTime.now(); if (dateTime.isAtSameDay(today)) { - return context.localizations.today; + return context.tr("today"); } else { - return DateFormat.EEEE(context.localizations.localeName).format(dateTime); + return DateFormat.EEEE(context.locale.languageCode).format(dateTime); } } } diff --git a/lib/calendarComponent/model/calendar_event.dart b/lib/calendarComponent/model/calendar_event.dart index a09cb28f..d757eaad 100644 --- a/lib/calendarComponent/model/calendar_event.dart +++ b/lib/calendarComponent/model/calendar_event.dart @@ -1,9 +1,8 @@ import 'package:campus_flutter/base/theme/constants.dart'; import 'package:campus_flutter/searchComponent/model/comparison_token.dart'; import 'package:campus_flutter/searchComponent/protocols/searchable.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; import 'package:json_annotation/json_annotation.dart'; part 'calendar_event.g.dart'; @@ -14,7 +13,7 @@ class CalendarEvent extends Searchable { final String id; final String status; final String? url; - final String title; + final String? title; final String? description; @JsonKey(name: "dtstart") final DateTime startDate; @@ -39,7 +38,7 @@ class CalendarEvent extends Searchable { String _dateTimePeriod(BuildContext context) { final start = DateFormat( "EE, dd.MM.yyyy, HH:mm", - context.localizations.localeName, + context.locale.languageCode, ).format(startDate); final end = DateFormat("HH:mm").format(endDate); return "$start - $end"; @@ -57,7 +56,7 @@ class CalendarEvent extends Searchable { null, "de", ).format(endDate); - return "$start ${context.localizations.to.toLowerCase()}\n$end"; + return "$start ${context.tr("to").toLowerCase()}\n$end"; } } @@ -80,7 +79,7 @@ class CalendarEvent extends Searchable { @override @JsonKey(includeFromJson: false, includeToJson: false) List get comparisonTokens => [ - ComparisonToken(value: title), + if (title != null) ComparisonToken(value: title!), if (location != null) ComparisonToken(value: location!), ]; @@ -88,7 +87,7 @@ class CalendarEvent extends Searchable { required this.id, required this.status, this.url, - required this.title, + this.title, this.description, required this.startDate, required this.endDate, diff --git a/lib/calendarComponent/model/calendar_event.g.dart b/lib/calendarComponent/model/calendar_event.g.dart index 95696148..37f61b1e 100644 --- a/lib/calendarComponent/model/calendar_event.g.dart +++ b/lib/calendarComponent/model/calendar_event.g.dart @@ -11,12 +11,12 @@ CalendarEvent _$CalendarEventFromJson(Map json) => id: json['nr'] as String, status: json['status'] as String, url: json['url'] as String?, - title: json['title'] as String, + title: json['title'] as String?, description: json['description'] as String?, startDate: DateTime.parse(json['dtstart'] as String), endDate: DateTime.parse(json['dtend'] as String), location: json['location'] as String?, - color: json['color'] as int?, + color: (json['color'] as num?)?.toInt(), ); Map _$CalendarEventToJson(CalendarEvent instance) => diff --git a/lib/calendarComponent/services/calendar_view_service.dart b/lib/calendarComponent/services/calendar_view_service.dart index d02cc6d9..3f391533 100644 --- a/lib/calendarComponent/services/calendar_view_service.dart +++ b/lib/calendarComponent/services/calendar_view_service.dart @@ -1,8 +1,8 @@ -import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/base/routing/routes.dart'; import 'package:campus_flutter/calendarComponent/model/calendar_event.dart'; import 'package:campus_flutter/calendarComponent/viewModels/calendar_viewmodel.dart'; import 'package:campus_flutter/calendarComponent/views/custom_event_view.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -57,7 +57,7 @@ class CalendarViewService { context: context, builder: (context) => AlertDialog( title: Text( - calendarEvent!.title, + calendarEvent!.title ?? "-", textAlign: TextAlign.center, maxLines: 3, overflow: TextOverflow.ellipsis, @@ -75,14 +75,14 @@ class CalendarViewService { .deleteCalendarElement(calendarEvent!.id) .then((value) => context.pop()); }, - child: Text(context.localizations.delete), + child: Text(context.tr("delete")), ), ElevatedButton( onPressed: () { context.pop(); context.push(eventCreation, extra: calendarEvent); }, - child: Text(context.localizations.edit), + child: Text(context.tr("edit")), ), ], ), diff --git a/lib/calendarComponent/viewModels/calendar_addition_viewmodel.dart b/lib/calendarComponent/viewModels/calendar_addition_viewmodel.dart index aa8c8d70..5023bfa1 100644 --- a/lib/calendarComponent/viewModels/calendar_addition_viewmodel.dart +++ b/lib/calendarComponent/viewModels/calendar_addition_viewmodel.dart @@ -38,7 +38,7 @@ class CalendarAdditionViewModel { } CalendarAdditionViewModel.edit(this.ref, CalendarEvent calendarEvent) { - titleController.text = calendarEvent.title; + titleController.text = calendarEvent.title ?? ""; annotationController.text = calendarEvent.description ?? ""; from = BehaviorSubject.seeded(calendarEvent.startDate); to = BehaviorSubject.seeded(calendarEvent.endDate); diff --git a/lib/calendarComponent/views/calendars_view.dart b/lib/calendarComponent/views/calendars_view.dart index 33628b37..cb064e45 100644 --- a/lib/calendarComponent/views/calendars_view.dart +++ b/lib/calendarComponent/views/calendars_view.dart @@ -6,6 +6,7 @@ import 'package:campus_flutter/calendarComponent/viewModels/calendar_viewmodel.d import 'package:campus_flutter/calendarComponent/views/calendar_day_view.dart'; import 'package:campus_flutter/calendarComponent/views/calendar_month_view.dart'; import 'package:campus_flutter/calendarComponent/views/calendar_week_view.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:syncfusion_flutter_calendar/calendar.dart'; @@ -64,7 +65,7 @@ class _CalendarsViewState extends ConsumerState null, ), child: Text( - context.localizations.calendarViewToday, + context.tr("calendarViewToday"), style: Theme.of(context).textTheme.titleMedium, ), ), @@ -78,19 +79,19 @@ class _CalendarsViewState extends ConsumerState ButtonSegment( value: 0, label: Text( - context.localizations.calendarViewDay, + context.tr("calendarViewDay"), ), ), ButtonSegment( value: 1, label: Text( - context.localizations.calendarViewWeek, + context.tr("calendarViewWeek"), ), ), ButtonSegment( value: 2, label: Text( - context.localizations.calendarViewMonth, + context.tr("calendarViewMonth"), ), ), ], @@ -128,7 +129,7 @@ class _CalendarsViewState extends ConsumerState ); } else { return DelayedLoadingIndicator( - name: context.localizations.calendar, + name: context.tr("calendar"), ); } }, diff --git a/lib/calendarComponent/views/custom_event_view.dart b/lib/calendarComponent/views/custom_event_view.dart index 32b2a41c..97c0fcff 100644 --- a/lib/calendarComponent/views/custom_event_view.dart +++ b/lib/calendarComponent/views/custom_event_view.dart @@ -2,6 +2,7 @@ import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/base/views/color_picker_view.dart'; import 'package:campus_flutter/calendarComponent/model/calendar_event.dart'; import 'package:campus_flutter/calendarComponent/viewModels/calendar_viewmodel.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -20,13 +21,13 @@ class CustomEventView extends ConsumerWidget { mainAxisSize: MainAxisSize.min, children: [ _infoEntry( - context.localizations.timeFrame, + context.tr("timeFrame"), Text(calendarEvent.timePeriodText(context)), context, ), if (calendarEvent.description != null) _infoEntry( - context.localizations.annotation, + context.tr("annotation"), Text( calendarEvent.description!, maxLines: 10, @@ -35,7 +36,7 @@ class CustomEventView extends ConsumerWidget { context, ), _infoEntry( - context.localizations.color, + context.tr("color"), ColorPickerView( color: calendarEvent.getColor(), onColorChanged: (color) { diff --git a/lib/calendarComponent/views/event_creation_view.dart b/lib/calendarComponent/views/event_creation_view.dart index a2e55b0b..49d75584 100644 --- a/lib/calendarComponent/views/event_creation_view.dart +++ b/lib/calendarComponent/views/event_creation_view.dart @@ -1,10 +1,10 @@ -import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/base/routing/routes.dart'; import 'package:campus_flutter/base/util/custom_back_button.dart'; import 'package:campus_flutter/calendarComponent/model/calendar_event.dart'; import 'package:campus_flutter/calendarComponent/viewModels/calendar_addition_viewmodel.dart'; import 'package:campus_flutter/calendarComponent/views/event_creation_date_time_picker.dart'; import 'package:campus_flutter/calendarComponent/views/event_creation_form_field.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -27,7 +27,7 @@ class EventCreationScaffold extends ConsumerWidget { context.pop(); }, ), - title: Text(context.localizations.createCalendarEvent), + title: Text(context.tr("createCalendarEvent")), ), body: EventCreationView( calendarEvent: calendarEvent, @@ -51,7 +51,7 @@ class EventCreationView extends ConsumerWidget { child: Column( children: [ EventCreationFormField( - title: context.localizations.title, + title: context.tr("title"), controller: ref .read(calendarAdditionViewModel(calendarEvent)) .titleController, @@ -60,7 +60,7 @@ class EventCreationView extends ConsumerWidget { calendarEvent: calendarEvent, ), EventCreationFormField( - title: context.localizations.annotation, + title: context.tr("annotation"), controller: ref .read(calendarAdditionViewModel(calendarEvent)) .annotationController, @@ -69,7 +69,7 @@ class EventCreationView extends ConsumerWidget { calendarEvent: calendarEvent, ), EventCreationDateTimePicker( - title: context.localizations.from, + title: context.tr("from"), currentDate: ref.watch(calendarAdditionViewModel(calendarEvent)).from, onDateSet: ref @@ -80,7 +80,7 @@ class EventCreationView extends ConsumerWidget { .setFromTimeOfDay, ), EventCreationDateTimePicker( - title: context.localizations.to, + title: context.tr("to"), currentDate: ref.watch(calendarAdditionViewModel(calendarEvent)).to, onDateSet: @@ -110,7 +110,7 @@ class EventCreationView extends ConsumerWidget { context.canPop() ? context.pop() : context.go(calendar); }) : null, - child: Text(context.localizations.submit), + child: Text(context.tr("submit")), ); }, ); diff --git a/lib/calendarComponent/views/homeWidget/calendar_widget_event_view.dart b/lib/calendarComponent/views/homeWidget/calendar_widget_event_view.dart index 328e5166..e14239f3 100644 --- a/lib/calendarComponent/views/homeWidget/calendar_widget_event_view.dart +++ b/lib/calendarComponent/views/homeWidget/calendar_widget_event_view.dart @@ -2,9 +2,9 @@ import 'package:campus_flutter/calendarComponent/model/calendar_event.dart'; import 'package:campus_flutter/calendarComponent/services/calendar_view_service.dart'; import 'package:campus_flutter/main.dart'; import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:intl/intl.dart'; class CalendarHomeWidgetEventView extends ConsumerWidget { const CalendarHomeWidgetEventView({super.key, required this.calendarEvent}); @@ -38,12 +38,12 @@ class CalendarHomeWidgetEventView extends ConsumerWidget { children: [ Text( startDate.isAtSameMomentAs(todayDate) - ? context.localizations.today + ? context.tr("today") : startDate.isAtSameMomentAs(tomorrowDate) - ? context.localizations.tomorrow + ? context.tr("tomorrow") : DateFormat( "EEEE, d. MMM", - context.localizations.localeName, + context.locale.languageCode, ).format(calendarEvent.startDate), style: TextStyle(color: Theme.of(context).colorScheme.secondary), ), @@ -65,7 +65,7 @@ class CalendarHomeWidgetEventView extends ConsumerWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - calendarEvent.title, + calendarEvent.title ?? "-", maxLines: 1, overflow: TextOverflow.ellipsis, style: Theme.of(context).textTheme.labelMedium, @@ -77,7 +77,7 @@ class CalendarHomeWidgetEventView extends ConsumerWidget { style: Theme.of(context).textTheme.labelSmall, ), Text( - calendarEvent.location ?? context.localizations.unknown, + calendarEvent.location ?? context.tr("unknown"), maxLines: 1, overflow: TextOverflow.ellipsis, style: Theme.of(context).textTheme.labelSmall, diff --git a/lib/calendarComponent/views/homeWidget/calendar_widget_view.dart b/lib/calendarComponent/views/homeWidget/calendar_widget_view.dart index ef4c6ae4..45646f89 100644 --- a/lib/calendarComponent/views/homeWidget/calendar_widget_view.dart +++ b/lib/calendarComponent/views/homeWidget/calendar_widget_view.dart @@ -6,9 +6,9 @@ import 'package:campus_flutter/calendarComponent/model/calendar_event.dart'; import 'package:campus_flutter/calendarComponent/viewModels/calendar_viewmodel.dart'; import 'package:campus_flutter/calendarComponent/views/homeWidget/calendar_widget_event_view.dart'; import 'package:campus_flutter/homeComponent/widgetComponent/views/widget_frame_view.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:intl/intl.dart'; import 'package:campus_flutter/base/extensions/context.dart'; class CalendarHomeWidgetView extends ConsumerStatefulWidget { @@ -29,7 +29,7 @@ class _CalendarHomeWidgetView extends ConsumerState { @override Widget build(BuildContext context) { return WidgetFrameView( - title: context.localizations.calendar, + title: context.tr("calendar"), child: CardWithPadding( height: 220, child: StreamBuilder( @@ -50,7 +50,7 @@ class _CalendarHomeWidgetView extends ConsumerState { ); } else { return DelayedLoadingIndicator( - name: context.localizations.events, + name: context.tr("events"), ); } }, @@ -65,7 +65,7 @@ class _CalendarHomeWidgetView extends ConsumerState { children: [ _todayWidget(), Center( - child: Text(context.localizations.noUpcomingEvents), + child: Text(context.tr("noUpcomingEvents")), ), ], ); @@ -125,11 +125,11 @@ class _CalendarHomeWidgetView extends ConsumerState { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - DateFormat.EEEE(context.localizations.localeName).format(today), + DateFormat.EEEE(context.locale.languageCode).format(today), style: TextStyle(color: context.primaryColor), ), Text( - DateFormat.MMMd(context.localizations.localeName).format(today), + DateFormat.MMMd(context.locale.languageCode).format(today), style: Theme.of(context).textTheme.headlineSmall, ), ], diff --git a/lib/departuresComponent/model/departures_preference.g.dart b/lib/departuresComponent/model/departures_preference.g.dart index 58245d02..f3267180 100644 --- a/lib/departuresComponent/model/departures_preference.g.dart +++ b/lib/departuresComponent/model/departures_preference.g.dart @@ -25,6 +25,7 @@ Map _$DeparturesPreferenceToJson( const _$CampusEnumMap = { Campus.stammgelaende: 'stammgelaende', Campus.olympiapark: 'olympiapark', + Campus.klinikumRechts: 'klinikumRechts', Campus.grosshadern: 'grosshadern', Campus.garching: 'garching', Campus.freising: 'freising', diff --git a/lib/departuresComponent/viewModel/departures_viewmodel.dart b/lib/departuresComponent/viewModel/departures_viewmodel.dart index 2fbea895..be6c833a 100644 --- a/lib/departuresComponent/viewModel/departures_viewmodel.dart +++ b/lib/departuresComponent/viewModel/departures_viewmodel.dart @@ -3,7 +3,6 @@ import 'dart:convert'; import 'package:campus_flutter/base/enums/campus.dart'; import 'package:campus_flutter/base/enums/user_preference.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/base/util/icon_text.dart'; import 'package:campus_flutter/base/services/location_service.dart'; import 'package:campus_flutter/departuresComponent/model/departure.dart'; @@ -13,6 +12,7 @@ import 'package:campus_flutter/departuresComponent/model/station.dart'; import 'package:campus_flutter/departuresComponent/services/departures_service.dart'; import 'package:campus_flutter/main.dart'; import 'package:campus_flutter/settingsComponent/service/user_preferences_service.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:geolocator/geolocator.dart'; import 'package:go_router/go_router.dart'; @@ -264,7 +264,7 @@ class DeparturesViewModel { 0, ListTile( dense: true, - title: Text(context.localizations.closest), + title: Text(context.tr("closest")), trailing: getIt().load( UserPreference.departure, ) == diff --git a/lib/departuresComponent/views/departures_details_row_view.dart b/lib/departuresComponent/views/departures_details_row_view.dart index 90e5f817..868c5389 100644 --- a/lib/departuresComponent/views/departures_details_row_view.dart +++ b/lib/departuresComponent/views/departures_details_row_view.dart @@ -1,8 +1,7 @@ import 'package:campus_flutter/departuresComponent/model/departure.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:intl/intl.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; class DeparturesDetailsRowView extends ConsumerWidget { const DeparturesDetailsRowView({super.key, required this.departure}); @@ -80,7 +79,7 @@ class DeparturesDetailsRowView extends ConsumerWidget { Widget timeBuilder(BuildContext context, DateTime? dateTime, Color? color) { if (departure.countdown < 1) { return Text( - context.localizations.now, + context.tr("now"), style: TextStyle(color: color, fontWeight: FontWeight.w500), ); } else { diff --git a/lib/departuresComponent/views/departures_details_view.dart b/lib/departuresComponent/views/departures_details_view.dart index faaaa45b..6b7816b1 100644 --- a/lib/departuresComponent/views/departures_details_view.dart +++ b/lib/departuresComponent/views/departures_details_view.dart @@ -10,6 +10,7 @@ import 'package:campus_flutter/departuresComponent/model/departure.dart'; import 'package:campus_flutter/departuresComponent/model/station.dart'; import 'package:campus_flutter/departuresComponent/viewModel/departures_viewmodel.dart'; import 'package:campus_flutter/departuresComponent/views/departures_details_row_view.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:campus_flutter/base/extensions/context.dart'; @@ -33,7 +34,7 @@ class DeparturesDetailsScaffold extends ConsumerWidget { backgroundColor: isSplitView ? null : backgroundColor, title: Text( ref.watch(departureViewModel).selectedStation.value?.name ?? - context.localizations.departures, + context.tr("departures"), ), actions: [ PopupMenuButton( @@ -89,7 +90,7 @@ class _DeparturesDetailsViewState extends ConsumerState { null) ...[ Text.rich( TextSpan( - text: context.localizations.station, + text: context.tr("station"), children: [ TextSpan( text: ref @@ -120,7 +121,7 @@ class _DeparturesDetailsViewState extends ConsumerState { }, child: IconText( iconData: Icons.open_in_new, - label: context.localizations.showDirections, + label: context.tr("showDirections"), ), ), ], @@ -143,7 +144,7 @@ class _DeparturesDetailsViewState extends ConsumerState { retry: (() => ref.read(departureViewModel).fetch(true)), ); } else { - return DelayedLoadingIndicator(name: context.localizations.departures); + return DelayedLoadingIndicator(name: context.tr("departures")); } } @@ -155,18 +156,18 @@ class _DeparturesDetailsViewState extends ConsumerState { SizedBox( width: 50, child: Text( - context.localizations.line, + context.tr("line"), style: const TextStyle(fontWeight: FontWeight.w500), ), ), const Padding(padding: EdgeInsets.symmetric(horizontal: 7.5)), Text( - context.localizations.direction, + context.tr("direction"), style: const TextStyle(fontWeight: FontWeight.w500), ), const Spacer(), Text( - context.localizations.departure, + context.tr("departure"), style: const TextStyle(fontWeight: FontWeight.w500), ), ], diff --git a/lib/departuresComponent/views/homeWidget/departures_widget_view.dart b/lib/departuresComponent/views/homeWidget/departures_widget_view.dart index c6330ab6..b7e8c95a 100644 --- a/lib/departuresComponent/views/homeWidget/departures_widget_view.dart +++ b/lib/departuresComponent/views/homeWidget/departures_widget_view.dart @@ -11,6 +11,7 @@ import 'package:campus_flutter/departuresComponent/views/departures_details_row_ import 'package:campus_flutter/homeComponent/widgetComponent/views/preference_selection_view.dart'; import 'package:campus_flutter/homeComponent/widgetComponent/views/widget_frame_view.dart'; import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -55,7 +56,7 @@ class _DeparturesHomeWidgetState extends ConsumerState { builder: (context) => PreferenceSelectionView( data: ref.read(departureViewModel).getCampusEntries(context), - entry: context.localizations.departure, + entry: context.tr("departure"), ), context: context, useRootNavigator: true, @@ -88,7 +89,7 @@ class _DeparturesHomeWidgetState extends ConsumerState { ); } else { return DelayedLoadingIndicator( - name: context.localizations.departures, + name: context.tr("departures"), ); } }, @@ -105,7 +106,7 @@ class _DeparturesHomeWidgetState extends ConsumerState { if (ref.watch(departureViewModel).widgetCampus.value?.name != null) { return ref.watch(departureViewModel).widgetCampus.value!.name; } else { - return context.localizations.departures; + return context.tr("departures"); } } @@ -119,7 +120,7 @@ class _DeparturesHomeWidgetState extends ConsumerState { children: [ RichText( text: TextSpan( - text: "${context.localizations.station} ", + text: "${context.tr("station")} ", style: Theme.of(context).textTheme.bodyMedium, children: [ TextSpan( diff --git a/lib/feedbackComponent/viewModels/feedback_viewmodel.dart b/lib/feedbackComponent/viewModels/feedback_viewmodel.dart index 773cdc94..73d04f5b 100644 --- a/lib/feedbackComponent/viewModels/feedback_viewmodel.dart +++ b/lib/feedbackComponent/viewModels/feedback_viewmodel.dart @@ -1,12 +1,12 @@ import 'package:campus_flutter/base/enums/error_handling_view_type.dart'; import 'package:campus_flutter/base/errorHandling/error_handling_router.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/base/networking/apis/tumdev/campus_backend.pb.dart'; import 'package:campus_flutter/base/routing/routes.dart'; import 'package:campus_flutter/base/services/location_service.dart'; import 'package:campus_flutter/feedbackComponent/services/feedback_service.dart'; import 'package:campus_flutter/personDetailedComponent/viewModel/person_details_viewmodel.dart'; import 'package:device_info_plus/device_info_plus.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:geolocator/geolocator.dart'; @@ -36,6 +36,7 @@ class FeedbackViewModel { if (personDetails != null) { name.text = personDetails.fullName; emailAddress.text = personDetails.email; + validEmail.add(true); validName.add(true); } else { showEmailTextField.add(true); @@ -86,7 +87,7 @@ class FeedbackViewModel { context: context, builder: (context) => AlertDialog( title: Text( - context.localizations.unableToSend, + context.tr("unableToSend"), textAlign: TextAlign.center, ), content: ErrorHandlingRouter( @@ -97,7 +98,7 @@ class FeedbackViewModel { actions: [ ElevatedButton( onPressed: () => context.pop(), - child: Text(context.localizations.back), + child: Text(context.tr("back")), ), ], ), diff --git a/lib/feedbackComponent/views/feedback_form_view.dart b/lib/feedbackComponent/views/feedback_form_view.dart index 73a8fe2d..caf2e907 100644 --- a/lib/feedbackComponent/views/feedback_form_view.dart +++ b/lib/feedbackComponent/views/feedback_form_view.dart @@ -4,6 +4,7 @@ import 'package:campus_flutter/base/views/seperated_list.dart'; import 'package:campus_flutter/feedbackComponent/viewModels/feedback_viewmodel.dart'; import 'package:campus_flutter/feedbackComponent/views/feedback_checkmark_view.dart'; import 'package:campus_flutter/feedbackComponent/views/feedback_textfield.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -21,7 +22,7 @@ class FeedbackFormScaffold extends ConsumerWidget { ref.read(feedbackViewModel).clearForm(); }, ), - title: Text(context.localizations.submitFeedback), + title: Text(context.tr("submitFeedback")), ), body: const FeedbackFormView(), ); @@ -50,30 +51,30 @@ class _FeedbackFormViewState extends ConsumerState { child: Column( children: [ FeedbackTextField( - title: context.localizations.name, + title: context.tr("name"), textEditingController: ref.read(feedbackViewModel).name, validInput: ref.watch(feedbackViewModel).validName, onChanged: (text) => ref.read(feedbackViewModel).checkNameValidity(), - invalidMessage: context.localizations.invalidName, - decorationMessage: context.localizations.yourName, + invalidMessage: context.tr("invalidName"), + decorationMessage: context.tr("yourName"), ), optionalEmailTextField(), FeedbackTextField( - title: context.localizations.message, + title: context.tr("message"), textEditingController: ref.read(feedbackViewModel).message, validInput: ref.watch(feedbackViewModel).validMessage, onChanged: (text) => ref.read(feedbackViewModel).checkMessageValidity(), - invalidMessage: context.localizations.invalidMessage, - decorationMessage: context.localizations.yourMessage, + invalidMessage: context.tr("invalidMessage"), + decorationMessage: context.tr("yourMessage"), expanded: true, ), Card( child: SeparatedList.widgets( widgets: [ FeedbackCheckMarkView( - text: context.localizations.shareLocation, + text: context.tr("shareLocation"), isChecked: ref.read(feedbackViewModel).shareLocation, ), ], @@ -89,7 +90,7 @@ class _FeedbackFormViewState extends ConsumerState { ? () => ref.read(feedbackViewModel).sendFeedBack(context) : null, - child: Text(context.localizations.submit), + child: Text(context.tr("submit")), ), ); }, @@ -106,13 +107,13 @@ class _FeedbackFormViewState extends ConsumerState { builder: (context, snapshot) { if (snapshot.hasData && snapshot.data!) { return FeedbackTextField( - title: context.localizations.yourEmailTitle, + title: context.tr("yourEmailTitle"), textEditingController: ref.read(feedbackViewModel).emailAddress, validInput: ref.watch(feedbackViewModel).validEmail, onChanged: (text) => ref.read(feedbackViewModel).checkEmailValidity(), - invalidMessage: context.localizations.invalidEmail, - decorationMessage: context.localizations.yourEmail, + invalidMessage: context.tr("invalidEmail"), + decorationMessage: context.tr("yourEmail"), ); } else { return const SizedBox.shrink(); diff --git a/lib/feedbackComponent/views/feedback_success_view.dart b/lib/feedbackComponent/views/feedback_success_view.dart index ac442b83..6b096645 100644 --- a/lib/feedbackComponent/views/feedback_success_view.dart +++ b/lib/feedbackComponent/views/feedback_success_view.dart @@ -1,4 +1,5 @@ import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; @@ -24,14 +25,14 @@ class FeedbackSuccessView extends StatelessWidget { Padding( padding: EdgeInsets.symmetric(vertical: context.padding * 2), child: Text( - context.localizations.successfullySent, + context.tr("successfullySent"), textAlign: TextAlign.center, style: Theme.of(context).textTheme.titleMedium, ), ), ElevatedButton( onPressed: () => context.pop(), - child: Text(context.localizations.back), + child: Text(context.tr("back")), ), ], ), diff --git a/lib/gradeComponent/model/grade.dart b/lib/gradeComponent/model/grade.dart index fbad9789..fca07b83 100644 --- a/lib/gradeComponent/model/grade.dart +++ b/lib/gradeComponent/model/grade.dart @@ -1,8 +1,8 @@ import 'package:campus_flutter/searchComponent/model/comparison_token.dart'; import 'package:campus_flutter/searchComponent/protocols/searchable.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.dart'; import 'package:json_annotation/json_annotation.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; part 'grade.g.dart'; @@ -42,13 +42,13 @@ class Grade extends Searchable { String modeShort(BuildContext context) { switch (mode) { case "Schriftlich": - return context.localizations.written; + return context.tr("written"); case "Beurteilt/immanenter Prüfungscharakter": - return context.localizations.graded; + return context.tr("graded"); case "Schriftlich und Mündlich": - return context.localizations.writtenAndOral; + return context.tr("writtenAndOral"); case "Mündlich": - return context.localizations.oral; + return context.tr("oral"); default: return mode; } diff --git a/lib/gradeComponent/views/chart_view.dart b/lib/gradeComponent/views/chart_view.dart index 0653c703..e14f827e 100644 --- a/lib/gradeComponent/views/chart_view.dart +++ b/lib/gradeComponent/views/chart_view.dart @@ -3,10 +3,10 @@ import 'dart:math'; import 'package:campus_flutter/base/util/card_with_padding.dart'; import 'package:campus_flutter/base/util/icon_text.dart'; import 'package:campus_flutter/gradeComponent/viewModels/grade_viewmodel.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:syncfusion_flutter_charts/charts.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; class ChartView extends ConsumerWidget { const ChartView({ @@ -66,7 +66,7 @@ class ChartView extends ConsumerWidget { children: [ Expanded( child: Text( - context.localizations.averageGrade, + context.tr("averageGrade"), style: Theme.of(context).textTheme.bodyLarge, ), ), diff --git a/lib/gradeComponent/views/grades_view.dart b/lib/gradeComponent/views/grades_view.dart index 7a5d8cf4..73dd354b 100644 --- a/lib/gradeComponent/views/grades_view.dart +++ b/lib/gradeComponent/views/grades_view.dart @@ -1,5 +1,4 @@ import 'package:campus_flutter/base/enums/error_handling_view_type.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/base/util/delayed_loading_indicator.dart'; import 'package:campus_flutter/base/util/last_updated_text.dart'; import 'package:campus_flutter/base/util/padded_divider.dart'; @@ -10,6 +9,7 @@ import 'package:campus_flutter/gradeComponent/model/grade.dart'; import 'package:campus_flutter/gradeComponent/viewModels/grade_viewmodel.dart'; import 'package:campus_flutter/gradeComponent/views/chart_view.dart'; import 'package:campus_flutter/gradeComponent/views/grade_view.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -41,8 +41,9 @@ class _GradesViewState extends ConsumerState if (snapshot.data!.isEmpty) { return Center( child: Text( - context.localizations.noEntriesFound( - context.localizations.grades, + context.tr( + "noEntriesFound", + args: [context.tr("grades")], ), ), ); @@ -65,7 +66,7 @@ class _GradesViewState extends ConsumerState retry: (() => ref.read(gradeViewModel).fetch(true)), ); } else { - return DelayedLoadingIndicator(name: context.localizations.grades); + return DelayedLoadingIndicator(name: context.tr("grades")); } }, ); diff --git a/lib/homeComponent/contactComponent/views/contact_card_error_view.dart b/lib/homeComponent/contactComponent/views/contact_card_error_view.dart new file mode 100644 index 00000000..61be077c --- /dev/null +++ b/lib/homeComponent/contactComponent/views/contact_card_error_view.dart @@ -0,0 +1,31 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; + +class ContactCardErrorView extends StatelessWidget { + const ContactCardErrorView({super.key}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(10.0), + child: Row( + children: [ + const CircleAvatar( + backgroundImage: AssetImage( + 'assets/images/placeholders/portrait_placeholder.png', + ), + radius: 50, + ), + const Padding(padding: EdgeInsets.only(left: 15)), + Expanded( + child: Text( + context.tr("profileError"), + style: Theme.of(context).textTheme.titleLarge, + textAlign: TextAlign.center, + ), + ), + ], + ), + ); + } +} diff --git a/lib/homeComponent/contactComponent/views/contact_card_unauthorized_view.dart b/lib/homeComponent/contactComponent/views/contact_card_unauthorized_view.dart new file mode 100644 index 00000000..a1aaeb09 --- /dev/null +++ b/lib/homeComponent/contactComponent/views/contact_card_unauthorized_view.dart @@ -0,0 +1,36 @@ +import 'package:campus_flutter/base/routing/routes.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; + +class ContactCardUnauthorizedView extends StatelessWidget { + const ContactCardUnauthorizedView({super.key}); + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: () => context.push(onboarding), + child: Padding( + padding: const EdgeInsets.all(10.0), + child: Row( + children: [ + const CircleAvatar( + backgroundImage: AssetImage( + 'assets/images/placeholders/portrait_placeholder.png', + ), + radius: 50, + ), + const Padding(padding: EdgeInsets.only(left: 15)), + Expanded( + child: Text( + context.tr("notLoggedIn"), + style: Theme.of(context).textTheme.titleLarge, + textAlign: TextAlign.center, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/homeComponent/contactComponent/views/contact_card_view.dart b/lib/homeComponent/contactComponent/views/contact_card_view.dart index f0f2c64f..bc609465 100644 --- a/lib/homeComponent/contactComponent/views/contact_card_view.dart +++ b/lib/homeComponent/contactComponent/views/contact_card_view.dart @@ -7,9 +7,9 @@ import 'package:campus_flutter/personDetailedComponent/model/person_details.dart import 'package:campus_flutter/personDetailedComponent/viewModel/person_details_viewmodel.dart'; import 'package:campus_flutter/profileComponent/model/profile.dart'; import 'package:campus_flutter/studentCardComponent/viewModel/student_card_viewmodel.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; class ContactCardView extends ConsumerStatefulWidget { const ContactCardView({super.key, required this.profile}); @@ -44,7 +44,7 @@ class _ContactCardViewState extends ConsumerState { ); } else { return DelayedLoadingIndicator( - name: context.localizations.personalData, + name: context.tr("personalData"), alternativeLoadingIndicator: const ContactCardLoadingView(), delayWidget: Container(), ); diff --git a/lib/homeComponent/contactComponent/views/contact_view.dart b/lib/homeComponent/contactComponent/views/contact_view.dart index d8e3eaf8..64fda5ea 100644 --- a/lib/homeComponent/contactComponent/views/contact_view.dart +++ b/lib/homeComponent/contactComponent/views/contact_view.dart @@ -1,8 +1,12 @@ +import 'package:campus_flutter/base/enums/credentials.dart'; import 'package:campus_flutter/base/util/card_with_padding.dart'; +import 'package:campus_flutter/homeComponent/contactComponent/views/contact_card_error_view.dart'; import 'package:campus_flutter/homeComponent/contactComponent/views/contact_card_view.dart'; import 'package:campus_flutter/homeComponent/contactComponent/views/link_view.dart'; import 'package:campus_flutter/homeComponent/contactComponent/views/tuition_view.dart'; -import 'package:campus_flutter/homeComponent/contactComponent/views/unauthorized_view.dart'; +import 'package:campus_flutter/homeComponent/contactComponent/views/contact_card_unauthorized_view.dart'; +import 'package:campus_flutter/onboardingComponent/viewModels/onboarding_viewmodel.dart'; +import 'package:campus_flutter/profileComponent/model/profile.dart'; import 'package:campus_flutter/profileComponent/viewModel/profile_viewmodel.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -35,13 +39,7 @@ class _ContactScreenState extends ConsumerState { ), child: CardWithPadding( child: Center( - child: snapshot.hasData - ? ContactCardView( - profile: snapshot.data!, - ) - : snapshot.hasError - ? const UnauthorizedView() - : Container(), + child: _body(snapshot), ), ), ), @@ -52,4 +50,18 @@ class _ContactScreenState extends ConsumerState { }, ); } + + Widget _body(AsyncSnapshot snapshot) { + if (ref.read(onboardingViewModel).credentials.value != Credentials.tumId) { + return const ContactCardUnauthorizedView(); + } else { + if (snapshot.hasData) { + return ContactCardView(profile: snapshot.data!); + } else if (snapshot.hasError) { + return const ContactCardErrorView(); + } else { + return Container(); + } + } + } } diff --git a/lib/homeComponent/contactComponent/views/link_view.dart b/lib/homeComponent/contactComponent/views/link_view.dart index ef85124b..6d7ecdd2 100644 --- a/lib/homeComponent/contactComponent/views/link_view.dart +++ b/lib/homeComponent/contactComponent/views/link_view.dart @@ -1,6 +1,7 @@ import 'package:auto_size_text/auto_size_text.dart'; import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/base/routing/routes.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -24,7 +25,7 @@ class LinkView extends ConsumerWidget { leading: const Icon(Icons.school), title: Center( child: AutoSizeText( - context.localizations.studyRooms, + context.tr("studyRooms"), maxLines: 1, ), ), @@ -44,7 +45,7 @@ class LinkView extends ConsumerWidget { leading: const Icon(Icons.restaurant), title: Center( child: AutoSizeText( - context.localizations.cafeterias, + context.tr("cafeterias"), maxLines: 1, ), ), diff --git a/lib/homeComponent/contactComponent/views/tuition_view.dart b/lib/homeComponent/contactComponent/views/tuition_view.dart index be68342a..5f07b520 100644 --- a/lib/homeComponent/contactComponent/views/tuition_view.dart +++ b/lib/homeComponent/contactComponent/views/tuition_view.dart @@ -3,11 +3,10 @@ import 'package:campus_flutter/base/util/icon_text.dart'; import 'package:campus_flutter/base/util/info_row.dart'; import 'package:campus_flutter/profileComponent/model/tuition.dart'; import 'package:campus_flutter/profileComponent/viewModel/profile_viewmodel.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; -import 'package:intl/intl.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; class TuitionView extends ConsumerWidget { const TuitionView({super.key}); @@ -20,7 +19,7 @@ class TuitionView extends ConsumerWidget { return Card( child: ListTile( leading: const Icon(Icons.euro), - title: Text(context.localizations.tuitionFees), + title: Text(context.tr("tuitionFees")), trailing: _tuitionStatus(context, snapshot), onTap: () => _alertDialog(context, snapshot), ), @@ -35,7 +34,7 @@ class TuitionView extends ConsumerWidget { context: context, builder: (context) => AlertDialog( title: Text( - context.localizations.tuitionFees, + context.tr("tuitionFees"), style: Theme.of(context).textTheme.titleMedium, textAlign: TextAlign.center, ), @@ -51,11 +50,11 @@ class TuitionView extends ConsumerWidget { ), const Padding(padding: EdgeInsets.symmetric(vertical: 5.0)), InfoRow( - title: context.localizations.tuitionDueDate, + title: context.tr("tuitionDueDate"), info: DateFormat.yMd("de").format(snapshot.data!.deadline), ), InfoRow( - title: context.localizations.tuitionOpenAmount, + title: context.tr("tuitionOpenAmount"), info: NumberFormat.currency(locale: "de", symbol: '€') .format(snapshot.data!.amount), ), @@ -81,7 +80,7 @@ class TuitionView extends ConsumerWidget { if (snapshot.data?.amount == 0.0) { return IconText( iconData: Icons.check, - label: context.localizations.tuitionPaid, + label: context.tr("tuitionPaid"), style: Theme.of(context) .textTheme .bodyMedium @@ -101,9 +100,9 @@ class TuitionView extends ConsumerWidget { } } else { return DelayedLoadingIndicator( - name: context.localizations.tuition, + name: context.tr("tuition"), alternativeLoadingIndicator: Text( - context.localizations.notAvailableAbbrev, + context.tr("notAvailableAbbrev"), style: Theme.of(context) .textTheme .bodyMedium diff --git a/lib/homeComponent/contactComponent/views/unauthorized_view.dart b/lib/homeComponent/contactComponent/views/unauthorized_view.dart deleted file mode 100644 index 2bc63967..00000000 --- a/lib/homeComponent/contactComponent/views/unauthorized_view.dart +++ /dev/null @@ -1,31 +0,0 @@ -import 'package:campus_flutter/base/routing/routes.dart'; -import 'package:flutter/material.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; -import 'package:go_router/go_router.dart'; - -class UnauthorizedView extends StatelessWidget { - const UnauthorizedView({super.key}); - - @override - Widget build(BuildContext context) { - return InkWell( - onTap: () => context.push(onboarding), - child: Row( - children: [ - const CircleAvatar( - backgroundImage: AssetImage( - 'assets/images/placeholders/portrait_placeholder.png', - ), - radius: 50, - ), - const Spacer(), - Text( - context.localizations.notLoggedIn, - style: Theme.of(context).textTheme.titleLarge, - ), - const Spacer(flex: 2), - ], - ), - ); - } -} diff --git a/lib/homeComponent/widgetComponent/viewModels/home_viewmodel.dart b/lib/homeComponent/widgetComponent/viewModels/home_viewmodel.dart index a174d5c5..2bdd80fb 100644 --- a/lib/homeComponent/widgetComponent/viewModels/home_viewmodel.dart +++ b/lib/homeComponent/widgetComponent/viewModels/home_viewmodel.dart @@ -1,7 +1,6 @@ import 'package:campus_flutter/base/enums/home_widget.dart'; import 'package:campus_flutter/base/enums/user_preference.dart'; import 'package:campus_flutter/base/enums/widget_type.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/calendarComponent/views/homeWidget/calendar_widget_view.dart'; import 'package:campus_flutter/departuresComponent/views/homeWidget/departures_widget_view.dart'; import 'package:campus_flutter/main.dart'; @@ -10,6 +9,7 @@ import 'package:campus_flutter/newsComponent/views/homeWidget/news_widget_view.d import 'package:campus_flutter/placesComponent/views/homeWidget/cafeteria_widget_view.dart'; import 'package:campus_flutter/placesComponent/views/homeWidget/study_room_widget_view.dart'; import 'package:campus_flutter/settingsComponent/service/user_preferences_service.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:rxdart/rxdart.dart'; @@ -89,17 +89,17 @@ class HomeViewModel { static String getTitle(WidgetType widgetType, BuildContext context) { switch (widgetType) { case WidgetType.cafeterias: - return context.localizations.cafeteria; + return context.tr("cafeteria"); case WidgetType.calendar: - return context.localizations.calendar; + return context.tr("calendar"); case WidgetType.departures: - return context.localizations.departures; + return context.tr("departures"); case WidgetType.studyRooms: - return context.localizations.nearestStudyRooms; + return context.tr("nearestStudyRooms"); case WidgetType.movies: - return context.localizations.movies; + return context.tr("movies"); case WidgetType.news: - return context.localizations.news; + return context.tr("news"); } } diff --git a/lib/homeComponent/widgetComponent/views/home_settings_view.dart b/lib/homeComponent/widgetComponent/views/home_settings_view.dart index bb75859a..eff7c75a 100644 --- a/lib/homeComponent/widgetComponent/views/home_settings_view.dart +++ b/lib/homeComponent/widgetComponent/views/home_settings_view.dart @@ -1,6 +1,7 @@ import 'package:campus_flutter/base/enums/home_widget.dart'; import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/homeComponent/widgetComponent/viewModels/home_viewmodel.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -12,19 +13,19 @@ class HomeSettingsView extends ConsumerWidget { return Column( children: [ Text( - context.localizations.editHome, + context.tr("editHome"), style: Theme.of(context) .textTheme .titleLarge ?.apply(color: context.primaryColor), ), - Text(context.localizations.reorderDisable), + Text(context.tr("reorderDisable")), Padding( padding: EdgeInsets.symmetric(vertical: context.halfPadding), ), TextButton( onPressed: () => ref.read(homeViewModel).reset(), - child: Text(context.localizations.reset), + child: Text(context.tr("reset")), ), _list(ref), ], diff --git a/lib/lectureComponent/model/lecture.dart b/lib/lectureComponent/model/lecture.dart index 0ff80e7d..63843227 100644 --- a/lib/lectureComponent/model/lecture.dart +++ b/lib/lectureComponent/model/lecture.dart @@ -1,8 +1,8 @@ import 'package:campus_flutter/searchComponent/model/comparison_token.dart'; import 'package:campus_flutter/searchComponent/protocols/searchable.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.dart'; import 'package:json_annotation/json_annotation.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; part 'lecture.g.dart'; @@ -42,17 +42,17 @@ class Lecture extends Searchable { String eventType(BuildContext context) { switch (eventTypeDefault) { case "Vorlesung": - return context.localizations.lecture; + return context.tr("lecture"); case "Tutorium": - return context.localizations.tutorial; + return context.tr("tutorial"); case "Übung": - return context.localizations.exercise; + return context.tr("exercise"); case "Praktikum": - return context.localizations.practicalCourse; + return context.tr("practicalCourse"); case "Seminar": - return context.localizations.seminar; + return context.tr("seminar"); case "Vorlesung mit integrierten Übungen": - return context.localizations.lectureWithIntegratedExcercises; + return context.tr("lectureWithIntegratedExcercises"); default: return eventTypeDefault; } diff --git a/lib/lectureComponent/model/lecture_details.dart b/lib/lectureComponent/model/lecture_details.dart index 4927f87b..cc85ea2b 100644 --- a/lib/lectureComponent/model/lecture_details.dart +++ b/lib/lectureComponent/model/lecture_details.dart @@ -1,6 +1,6 @@ import 'package:campus_flutter/base/util/string_parser.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/widgets.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; import 'package:json_annotation/json_annotation.dart'; part 'lecture_details.g.dart'; @@ -64,17 +64,17 @@ class LectureDetails { String eventType(BuildContext context) { switch (eventTypeDefault) { case "Vorlesung": - return context.localizations.lecture; + return context.tr("lecture"); case "Tutorium": - return context.localizations.tutorial; + return context.tr("tutorial"); case "Übung": - return context.localizations.exercise; + return context.tr("exercise"); case "Praktikum": - return context.localizations.practicalCourse; + return context.tr("practicalCourse"); case "Seminar": - return context.localizations.seminar; + return context.tr("seminar"); case "Vorlesung mit integrierten Übungen": - return context.localizations.lectureWithIntegratedExcercises; + return context.tr("lectureWithIntegratedExcercises"); default: return eventTypeDefault; } diff --git a/lib/lectureComponent/views/basic_lecture_info_view.dart b/lib/lectureComponent/views/basic_lecture_info_view.dart index 611745e2..6b87bff2 100644 --- a/lib/lectureComponent/views/basic_lecture_info_view.dart +++ b/lib/lectureComponent/views/basic_lecture_info_view.dart @@ -4,6 +4,7 @@ import 'package:campus_flutter/lectureComponent/model/lecture_details.dart'; import 'package:campus_flutter/lectureComponent/views/basic_lecture_info_row_view.dart'; import 'package:campus_flutter/lectureComponent/views/lecture_info_card_view.dart'; import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -22,7 +23,7 @@ class BasicLectureInfoView extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { return LectureInfoCardView( icon: Icons.folder, - title: context.localizations.basicLectureInformation, + title: context.tr("basicLectureInformation"), widgets: [ BasicLectureInfoRowView( information: "${lectureDetails.stpSpSst} SWS", diff --git a/lib/lectureComponent/views/detailed_lecture_info_view.dart b/lib/lectureComponent/views/detailed_lecture_info_view.dart index c9170449..48c9a86c 100644 --- a/lib/lectureComponent/views/detailed_lecture_info_view.dart +++ b/lib/lectureComponent/views/detailed_lecture_info_view.dart @@ -1,7 +1,7 @@ import 'package:campus_flutter/lectureComponent/model/lecture_details.dart'; import 'package:campus_flutter/lectureComponent/views/detailed_lecture_info_row_view.dart'; import 'package:campus_flutter/lectureComponent/views/lecture_info_card_view.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; class DetailedLectureInfoView extends StatelessWidget { @@ -16,21 +16,21 @@ class DetailedLectureInfoView extends StatelessWidget { Widget build(BuildContext context) { return LectureInfoCardView( icon: Icons.info_outline_rounded, - title: context.localizations.detailedLectureInformation, + title: context.tr("detailedLectureInformation"), widgets: [ if (lectureDetails.courseContents != null) DetailedLectureInfoRowView( - title: context.localizations.courseContents, + title: context.tr("courseContents"), information: lectureDetails.courseContents!, ), if (lectureDetails.courseObjective != null) DetailedLectureInfoRowView( - title: context.localizations.courseObjective, + title: context.tr("courseObjective"), information: lectureDetails.courseObjective!, ), if (lectureDetails.note != null) DetailedLectureInfoRowView( - title: context.localizations.note, + title: context.tr("note"), information: lectureDetails.note!, ), ], diff --git a/lib/lectureComponent/views/lecture_details_view.dart b/lib/lectureComponent/views/lecture_details_view.dart index 5117f02c..07dc468e 100644 --- a/lib/lectureComponent/views/lecture_details_view.dart +++ b/lib/lectureComponent/views/lecture_details_view.dart @@ -14,6 +14,7 @@ import 'package:campus_flutter/lectureComponent/views/detailed_lecture_info_view import 'package:campus_flutter/lectureComponent/views/lecture_links_view.dart'; import 'package:campus_flutter/lectureComponent/views/lecture_meeting_info_view.dart'; import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; @@ -110,7 +111,7 @@ class _LectureDetailsViewState extends ConsumerState { ); } else { return DelayedLoadingIndicator( - name: context.localizations.lectureDetails, + name: context.tr("lectureDetails"), ); } }, diff --git a/lib/lectureComponent/views/lecture_links_view.dart b/lib/lectureComponent/views/lecture_links_view.dart index 152385cd..2b8637d0 100644 --- a/lib/lectureComponent/views/lecture_links_view.dart +++ b/lib/lectureComponent/views/lecture_links_view.dart @@ -1,7 +1,7 @@ import 'package:campus_flutter/base/util/hyperlink_text.dart'; import 'package:campus_flutter/lectureComponent/model/lecture_details.dart'; import 'package:campus_flutter/lectureComponent/views/lecture_info_card_view.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; class LectureLinksView extends StatelessWidget { @@ -13,25 +13,25 @@ class LectureLinksView extends StatelessWidget { Widget build(BuildContext context) { return LectureInfoCardView( icon: Icons.link, - title: context.localizations.lectureLinks, + title: context.tr("lectureLinks"), widgets: [ if (lectureDetails.curriculumURL != null) HyperLinkListTile( dense: true, link: lectureDetails.curriculumURL, - label: context.localizations.lectureCurriculum, + label: context.tr("lectureCurriculum"), ), if (lectureDetails.scheduledDatesURL != null) HyperLinkListTile( dense: true, link: lectureDetails.scheduledDatesURL, - label: context.localizations.scheduledLectureDates, + label: context.tr("scheduledLectureDates"), ), if (lectureDetails.examDateURL != null) HyperLinkListTile( dense: true, link: lectureDetails.examDateURL, - label: context.localizations.lectureExamDate, + label: context.tr("lectureExamDate"), ), ], ); diff --git a/lib/lectureComponent/views/lecture_meeting_info_view.dart b/lib/lectureComponent/views/lecture_meeting_info_view.dart index 7a4f8b12..ab29153b 100644 --- a/lib/lectureComponent/views/lecture_meeting_info_view.dart +++ b/lib/lectureComponent/views/lecture_meeting_info_view.dart @@ -3,6 +3,7 @@ import 'package:campus_flutter/lectureComponent/viewModels/lecture_details_viewm import 'package:campus_flutter/lectureComponent/views/basic_lecture_info_row_view.dart'; import 'package:campus_flutter/lectureComponent/views/lecture_info_card_view.dart'; import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -16,15 +17,15 @@ class LectureMeetingInfoView extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { return LectureInfoCardView( icon: Icons.calendar_month, - title: context.localizations.thisMeeting, + title: context.tr("thisMeeting"), widgets: [ BasicLectureInfoRowView( information: ref.read(viewModel).event!.timePeriodText(context), iconData: Icons.hourglass_top, ), BasicLectureInfoRowView( - information: ref.read(viewModel).event!.location ?? - context.localizations.unknown, + information: + ref.read(viewModel).event!.location ?? context.tr("unknown"), iconData: Icons.location_on, trailingWidget: IconButton( onPressed: () => context.push( diff --git a/lib/lectureComponent/views/lectures_view.dart b/lib/lectureComponent/views/lectures_view.dart index 9b42fe43..f7adbdd6 100644 --- a/lib/lectureComponent/views/lectures_view.dart +++ b/lib/lectureComponent/views/lectures_view.dart @@ -5,9 +5,9 @@ import 'package:campus_flutter/base/errorHandling/error_handling_router.dart'; import 'package:campus_flutter/lectureComponent/model/lecture.dart'; import 'package:campus_flutter/lectureComponent/viewModels/lecture_viewmodel.dart'; import 'package:campus_flutter/lectureComponent/views/semester_view.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; class LecturesView extends ConsumerStatefulWidget { const LecturesView({super.key}); @@ -36,8 +36,9 @@ class _LecturesViewState extends ConsumerState if (snapshot.data!.isEmpty) { return Center( child: Text( - context.localizations.noEntriesFound( - context.localizations.lecture, + context.tr( + "noEntriesFound", + args: [context.tr("lecture")], ), ), ); @@ -67,7 +68,7 @@ class _LecturesViewState extends ConsumerState retry: (() => ref.read(lectureViewModel).fetch(true)), ); } else { - return DelayedLoadingIndicator(name: context.localizations.lectures); + return DelayedLoadingIndicator(name: context.tr("lectures")); } }, ); diff --git a/lib/main.dart b/lib/main.dart index 7595077f..a6c7edc7 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,6 +1,5 @@ -import 'dart:io'; - import 'package:campus_flutter/base/enums/appearance.dart'; +import 'package:campus_flutter/base/enums/remote_config_message.dart'; import 'package:campus_flutter/base/enums/shortcut_item.dart'; import 'package:campus_flutter/base/networking/cache/cache_entry.dart'; import 'package:campus_flutter/base/util/enum_parser.dart'; @@ -18,6 +17,9 @@ import 'package:campus_flutter/onboardingComponent/services/onboarding_service.d import 'package:campus_flutter/navigation_service.dart'; import 'package:campus_flutter/placesComponent/services/map_theme_service.dart'; import 'package:campus_flutter/settingsComponent/service/user_preferences_service.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:easy_logger/easy_logger.dart'; +import 'package:firebase_remote_config/firebase_remote_config.dart'; import 'package:flutter/material.dart'; import 'package:flutter_native_splash/flutter_native_splash.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -26,7 +28,6 @@ import 'package:home_widget/home_widget.dart'; import 'package:isar/isar.dart'; import 'package:path_provider/path_provider.dart'; import 'package:flutter/foundation.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:firebase_crashlytics/firebase_crashlytics.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:quick_actions/quick_actions.dart'; @@ -35,20 +36,37 @@ import 'package:shared_preferences/shared_preferences.dart'; final getIt = GetIt.instance; final customLocale = StateProvider((ref) => null); final appearance = StateProvider((ref) => Appearance.system); +final hasStatusMessage = StateProvider<(bool, RemoteConfigMessage?)>( + (ref) => (false, null), +); main() async { WidgetsBinding widgetsBinding = WidgetsFlutterBinding.ensureInitialized(); FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding); + await _initializeLocalization(); await _initializeFirebase(); await _initializeNetworkingClients(); await _initializeServices(); runApp( - ProviderScope( - child: CampusApp(launchedFromWidget: await _initializeHomeWidgets()), + EasyLocalization( + supportedLocales: const [Locale('en'), Locale('de')], + path: 'assets/translations', + fallbackLocale: const Locale('en'), + child: ProviderScope( + child: CampusApp(launchedFromWidget: await _initializeHomeWidgets()), + ), ), ); } +Future _initializeLocalization() async { + EasyLocalization.logger.enableLevels = [ + LevelMessages.error, + LevelMessages.warning, + ]; + await EasyLocalization.ensureInitialized(); +} + Future _initializeFirebase() async { if (!kDebugMode) { await Firebase.initializeApp(); @@ -57,6 +75,13 @@ Future _initializeFirebase() async { FirebaseCrashlytics.instance.recordError(error, stack, fatal: true); return true; }; + final remoteConfig = FirebaseRemoteConfig.instance; + await remoteConfig.setConfigSettings( + RemoteConfigSettings( + fetchTimeout: const Duration(minutes: 1), + minimumFetchInterval: const Duration(hours: 1), + ), + ); } } @@ -109,6 +134,7 @@ class _CampusAppState extends ConsumerState @override void initState() { getIt.registerSingleton(RouterService(ref)); + firebaseCallback(); quickActionsCallback(); homeWidgetLaunchCallback(); homeWidgetCallback(); @@ -124,9 +150,9 @@ class _CampusAppState extends ConsumerState theme: lightTheme(context), darkTheme: darkTheme(context), themeMode: ref.watch(appearance).themeMode, - locale: ref.watch(customLocale) ?? getDeviceLocale(), - localizationsDelegates: AppLocalizations.localizationsDelegates, - supportedLocales: AppLocalizations.supportedLocales, + locale: context.locale, + localizationsDelegates: context.localizationDelegates, + supportedLocales: context.supportedLocales, localeResolutionCallback: (locale, locales) { quickActions.setShortcutItems([ for (var shortcutItemType in ActiveShortcuts.items) @@ -138,6 +164,44 @@ class _CampusAppState extends ConsumerState ); } + void firebaseCallback() { + if (!kDebugMode) { + final remoteConfig = FirebaseRemoteConfig.instance; + remoteConfig.fetchAndActivate(); + remoteConfig.fetchAndActivate().then((value) { + if (value) { + _handleFirebaseValues( + RemoteConfigMessage.keys, + remoteConfig.getAll(), + ); + } + }); + remoteConfig.onConfigUpdated.listen((event) async { + await remoteConfig.activate(); + _handleFirebaseValues(event.updatedKeys, remoteConfig.getAll()); + }); + } + } + + void _handleFirebaseValues( + Set updatedKeys, + Map values, + ) { + var shouldClear = true; + for (var updatedKey in updatedKeys) { + if (values[updatedKey]?.asBool() ?? false) { + shouldClear = false; + ref.read(hasStatusMessage.notifier).state = ( + true, + RemoteConfigMessage.fromString(updatedKey), + ); + } + } + if (shouldClear) { + ref.read(hasStatusMessage.notifier).state = (false, null); + } + } + void quickActionsCallback() { quickActions = const QuickActions() ..initialize((shortcutType) { @@ -170,15 +234,6 @@ class _CampusAppState extends ConsumerState }); } - Locale getDeviceLocale() { - final deviceLocal = Platform.localeName; - if (deviceLocal.contains("de")) { - return const Locale("de", "DE"); - } else { - return const Locale("en", "DE"); - } - } - @override bool get wantKeepAlive => true; } diff --git a/lib/movieComponent/views/homeWidget/movies_widget_view.dart b/lib/movieComponent/views/homeWidget/movies_widget_view.dart index ff405880..10bbf534 100644 --- a/lib/movieComponent/views/homeWidget/movies_widget_view.dart +++ b/lib/movieComponent/views/homeWidget/movies_widget_view.dart @@ -6,9 +6,9 @@ import 'package:campus_flutter/base/errorHandling/error_handling_router.dart'; import 'package:campus_flutter/homeComponent/widgetComponent/views/widget_frame_view.dart'; import 'package:campus_flutter/movieComponent/viewModel/movies_viewmodel.dart'; import 'package:campus_flutter/movieComponent/views/homeWidget/movie_card_view.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; class MoviesHomeWidget extends ConsumerStatefulWidget { const MoviesHomeWidget({super.key}); @@ -61,7 +61,7 @@ class _MoviesHomeWidgetState extends ConsumerState { return Card( child: SizedBox( height: MediaQuery.of(context).size.height * 0.34, - child: DelayedLoadingIndicator(name: context.localizations.movies), + child: DelayedLoadingIndicator(name: context.tr("movies")), ), ); } diff --git a/lib/navigaTumComponent/model/navigatum_overlay_map.g.dart b/lib/navigaTumComponent/model/navigatum_overlay_map.g.dart index a76c0238..3545a3e4 100644 --- a/lib/navigaTumComponent/model/navigatum_overlay_map.g.dart +++ b/lib/navigaTumComponent/model/navigatum_overlay_map.g.dart @@ -8,7 +8,7 @@ part of 'navigatum_overlay_map.dart'; NavigaTumOverlayMap _$NavigaTumOverlayMapFromJson(Map json) => NavigaTumOverlayMap( - json['id'] as int, + (json['id'] as num).toInt(), json['floor'] as String, json['file'] as String, json['name'] as String, diff --git a/lib/navigaTumComponent/model/navigatum_roomfinder_map.g.dart b/lib/navigaTumComponent/model/navigatum_roomfinder_map.g.dart index 893cf5a0..c3540ecf 100644 --- a/lib/navigaTumComponent/model/navigatum_roomfinder_map.g.dart +++ b/lib/navigaTumComponent/model/navigatum_roomfinder_map.g.dart @@ -12,10 +12,10 @@ NavigaTumRoomFinderMap _$NavigaTumRoomFinderMapFromJson( id: json['id'] as String, name: json['name'] as String, imageUrl: json['file'] as String, - height: json['height'] as int, - width: json['width'] as int, - x: json['x'] as int, - y: json['y'] as int, + height: (json['height'] as num).toInt(), + width: (json['width'] as num).toInt(), + x: (json['x'] as num).toInt(), + y: (json['y'] as num).toInt(), scale: json['scale'] as String, ); diff --git a/lib/navigaTumComponent/views/navigatum_room_building_view.dart b/lib/navigaTumComponent/views/navigatum_room_building_view.dart index a912bfcc..5e4f103b 100644 --- a/lib/navigaTumComponent/views/navigatum_room_building_view.dart +++ b/lib/navigaTumComponent/views/navigatum_room_building_view.dart @@ -1,7 +1,7 @@ import 'package:campus_flutter/homeComponent/widgetComponent/views/widget_frame_view.dart'; import 'package:campus_flutter/navigaTumComponent/model/details/navigatum_navigation_coordinates.dart'; import 'package:campus_flutter/placesComponent/views/map_widget.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; @@ -18,7 +18,7 @@ class NavigaTumRoomBuildingView extends StatelessWidget { @override Widget build(BuildContext context) { return WidgetFrameView( - title: context.localizations.building, + title: context.tr("building"), child: isLandScape ? Expanded(child: _map()) : _map(), ); } diff --git a/lib/navigaTumComponent/views/navigatum_room_details_view.dart b/lib/navigaTumComponent/views/navigatum_room_details_view.dart index 4db1b8ec..4ab0b95b 100644 --- a/lib/navigaTumComponent/views/navigatum_room_details_view.dart +++ b/lib/navigaTumComponent/views/navigatum_room_details_view.dart @@ -3,6 +3,7 @@ import 'package:campus_flutter/homeComponent/widgetComponent/views/widget_frame_ import 'package:campus_flutter/navigaTumComponent/model/navigatum_navigation_property.dart'; import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/navigaTumComponent/viewModels/navigatum_details_viewmodel.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -19,7 +20,7 @@ class NavigaTumRoomDetailsView extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { return WidgetFrameView( - title: context.localizations.roomDetails, + title: context.tr("roomDetails"), child: Card( child: SeparatedList.list( data: properties, diff --git a/lib/navigaTumComponent/views/navigatum_room_maps_view.dart b/lib/navigaTumComponent/views/navigatum_room_maps_view.dart index e052c090..da05c61c 100644 --- a/lib/navigaTumComponent/views/navigatum_room_maps_view.dart +++ b/lib/navigaTumComponent/views/navigatum_room_maps_view.dart @@ -6,7 +6,7 @@ import 'package:campus_flutter/base/networking/apis/navigaTumApi/navigatum_api_s import 'package:campus_flutter/base/routing/routes.dart'; import 'package:campus_flutter/homeComponent/widgetComponent/views/widget_frame_view.dart'; import 'package:campus_flutter/navigaTumComponent/model/navigatum_roomfinder_map.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; @@ -18,7 +18,7 @@ class NavigaTumRoomMapsView extends StatelessWidget { @override Widget build(BuildContext context) { return WidgetFrameView( - title: context.localizations.map, + title: context.tr("map"), child: CardWithPadding( child: maps.isNotEmpty ? HorizontalSlider.aspectRatio( @@ -48,8 +48,9 @@ class NavigaTumRoomMapsView extends StatelessWidget { ) : Center( child: Text( - context.localizations.noEntriesFound( - context.localizations.maps, + context.tr( + "noEntriesFound", + args: [context.tr("maps")], ), ), ), diff --git a/lib/navigaTumComponent/views/navigatum_room_view.dart b/lib/navigaTumComponent/views/navigatum_room_view.dart index bca309f6..8f9a85fb 100644 --- a/lib/navigaTumComponent/views/navigatum_room_view.dart +++ b/lib/navigaTumComponent/views/navigatum_room_view.dart @@ -10,6 +10,7 @@ import 'package:campus_flutter/navigaTumComponent/views/navigatum_room_details_v import 'package:campus_flutter/navigaTumComponent/views/navigatum_room_building_view.dart'; import 'package:campus_flutter/navigaTumComponent/views/navigatum_room_maps_view.dart'; import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -23,7 +24,7 @@ class NavigaTumRoomScaffold extends ConsumerWidget { return Scaffold( appBar: AppBar( leading: const CustomBackButton(), - title: Text(context.localizations.roomDetails), + title: Text(context.tr("roomDetails")), actions: [ StreamBuilder( stream: ref.watch(navigaTumDetailsViewModel(id)).details, @@ -110,7 +111,7 @@ class _NavigaTumRoomState extends ConsumerState { ); } else { return DelayedLoadingIndicator( - name: context.localizations.roomDetails, + name: context.tr("roomDetails"), ); } }, diff --git a/lib/navigation.dart b/lib/navigation.dart index 9e3fd6a4..17317533 100644 --- a/lib/navigation.dart +++ b/lib/navigation.dart @@ -38,6 +38,7 @@ class Navigation extends ConsumerWidget { navigationShell.currentIndex, context, ), + bottom: getIt().bottom(context, ref), ), bottomNavigationBar: DecoratedBox( decoration: const BoxDecoration( diff --git a/lib/navigation_service.dart b/lib/navigation_service.dart index c0950e0f..f9832927 100644 --- a/lib/navigation_service.dart +++ b/lib/navigation_service.dart @@ -3,10 +3,12 @@ import 'dart:io'; import 'package:campus_flutter/base/enums/credentials.dart'; import 'package:campus_flutter/base/routing/routes.dart'; import 'package:campus_flutter/homeComponent/widgetComponent/views/widget_screen.dart'; +import 'package:campus_flutter/main.dart'; import 'package:campus_flutter/onboardingComponent/viewModels/onboarding_viewmodel.dart'; import 'package:campus_flutter/searchComponent/viewModels/global_search_viewmodel.dart'; import 'package:campus_flutter/studentCardComponent/views/student_card_view.dart'; import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -32,22 +34,22 @@ class NavigationService { ); case 1: return Text( - context.localizations.grades, + context.tr("grades"), style: Theme.of(context).textTheme.titleLarge, ); case 2: return Text( - context.localizations.lectures, + context.tr("lectures"), style: Theme.of(context).textTheme.titleLarge, ); case 3: return Text( - context.localizations.calendar, + context.tr("calendar"), style: Theme.of(context).textTheme.titleLarge, ); case 4: return Text( - context.localizations.places, + context.tr("places"), style: Theme.of(context).textTheme.titleLarge, ); default: @@ -105,32 +107,64 @@ class NavigationService { ]; } + PreferredSizeWidget? bottom(BuildContext context, WidgetRef ref) { + final message = ref.watch(hasStatusMessage); + if (message.$1 && message.$2 != null) { + return PreferredSize( + preferredSize: Size( + MediaQuery.sizeOf(context).width, + 30 + context.halfPadding, + ), + child: Padding( + padding: EdgeInsets.only(bottom: context.halfPadding), + child: Container( + color: context.primaryColor, + height: 30, + width: MediaQuery.sizeOf(context).width, + child: Center( + child: Text( + message.$2!.message(context), + style: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.w500, + ), + maxLines: 1, + ), + ), + ), + ), + ); + } else { + return null; + } + } + List bottomNavItems(BuildContext context) => [ NavigationDestination( icon: const Icon(Icons.house_outlined), selectedIcon: const Icon(Icons.house), - label: context.localizations.home, + label: context.tr("home"), ), NavigationDestination( icon: const Icon(Icons.school_outlined), selectedIcon: const Icon(Icons.school), - label: context.localizations.grades, + label: context.tr("grades"), ), NavigationDestination( icon: const Icon(Icons.class_outlined), selectedIcon: const Icon(Icons.class_), - label: context.localizations.lectures, + label: context.tr("lectures"), ), NavigationDestination( icon: const Icon(Icons.calendar_month_outlined), selectedIcon: const Icon(Icons.calendar_month), - label: context.localizations.calendar, + label: context.tr("calendar"), ), NavigationDestination( icon: const Icon(Icons.place_outlined), selectedIcon: const Icon(Icons.place), - label: context.localizations.places, + label: context.tr("places"), ), ]; diff --git a/lib/newsComponent/views/homeWidget/news_widget_view.dart b/lib/newsComponent/views/homeWidget/news_widget_view.dart index 065fd100..d05530f8 100644 --- a/lib/newsComponent/views/homeWidget/news_widget_view.dart +++ b/lib/newsComponent/views/homeWidget/news_widget_view.dart @@ -5,9 +5,9 @@ import 'package:campus_flutter/base/errorHandling/error_handling_router.dart'; import 'package:campus_flutter/homeComponent/widgetComponent/views/widget_frame_view.dart'; import 'package:campus_flutter/newsComponent/viewModel/news_viewmodel.dart'; import 'package:campus_flutter/newsComponent/views/news_card_view.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; class NewsWidgetView extends ConsumerStatefulWidget { const NewsWidgetView({super.key}); @@ -26,7 +26,7 @@ class _NewsWidgetViewState extends ConsumerState { @override Widget build(BuildContext context) { return WidgetFrameView( - title: context.localizations.latestNews, + title: context.tr("latestNews"), child: StreamBuilder( stream: ref.watch(newsViewModel).news, builder: (context, snapshot) { @@ -53,8 +53,9 @@ class _NewsWidgetViewState extends ConsumerState { child: Card( child: Center( child: Text( - context.localizations.noEntriesFound( - context.localizations.news, + context.tr( + "noEntriesFound", + args: [context.tr("news")], ), ), ), @@ -77,7 +78,7 @@ class _NewsWidgetViewState extends ConsumerState { height: 300, child: Card( child: DelayedLoadingIndicator( - name: context.localizations.news, + name: context.tr("news"), ), ), ); diff --git a/lib/newsComponent/views/news_card_view.dart b/lib/newsComponent/views/news_card_view.dart index cbbc0ae8..081890c4 100644 --- a/lib/newsComponent/views/news_card_view.dart +++ b/lib/newsComponent/views/news_card_view.dart @@ -1,8 +1,8 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:campus_flutter/base/util/string_parser.dart'; import 'package:campus_flutter/base/networking/apis/tumdev/campus_backend.pbgrpc.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/base/routing/routes.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -94,7 +94,10 @@ class NewsCardView extends ConsumerWidget { ), Expanded( child: Text( - context.localizations.source(news.sourceTitle), + context.tr( + "noEntriesFound", + args: [news.sourceTitle], + ), style: Theme.of(context).textTheme.bodySmall, maxLines: 1, overflow: TextOverflow.ellipsis, diff --git a/lib/onboardingComponent/viewModels/onboarding_viewmodel.dart b/lib/onboardingComponent/viewModels/onboarding_viewmodel.dart index f9c8ba42..5db5e23d 100644 --- a/lib/onboardingComponent/viewModels/onboarding_viewmodel.dart +++ b/lib/onboardingComponent/viewModels/onboarding_viewmodel.dart @@ -1,7 +1,6 @@ import 'dart:developer'; import 'package:campus_flutter/base/enums/credentials.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/base/networking/protocols/api.dart'; import 'package:campus_flutter/base/networking/base/rest_client.dart'; import 'package:campus_flutter/base/routing/router_service.dart'; @@ -16,6 +15,7 @@ import 'package:campus_flutter/profileComponent/viewModel/profile_viewmodel.dart import 'package:campus_flutter/settingsComponent/service/user_preferences_service.dart'; import 'package:campus_flutter/settingsComponent/viewModels/user_preferences_viewmodel.dart'; import 'package:campus_flutter/studentCardComponent/viewModel/student_card_viewmodel.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; @@ -42,43 +42,39 @@ class OnboardingViewModel { } void checkTumId(BuildContext context) { - final RegExp lettersRegex = RegExp(r'^[a-zA-Z]+$'); + final RegExp lettersRegex = RegExp(r'^[a-z]+$'); final RegExp numberRegex = RegExp(r'^[0-9]+$'); - validateField( - textEditingController1.text, - lettersRegex, - context.localizations.onlyLetters, - ); - validateField( - textEditingController2.text, - numberRegex, - context.localizations.onlyNumbers, - ); - validateField( - textEditingController3.text, - lettersRegex, - context.localizations.onlyLetters, - ); + if (textEditingController1.text.isEmpty || + textEditingController2.text.isEmpty || + textEditingController3.text.isEmpty) { + tumIdValid.add(false); + return; + } - validateLength(textEditingController1.text, 2); - validateLength(textEditingController2.text, 2); - validateLength(textEditingController3.text, 3); + if (!lettersRegex.hasMatch(textEditingController1.text)) { + tumIdValid.addError(context.tr("onlyLetters")); + return; + } - tumIdValid.add(true); - } + if (!numberRegex.hasMatch(textEditingController2.text)) { + tumIdValid.addError(context.tr("onlyNumbers")); + return; + } - void validateField(String text, RegExp regex, String errorMessage) { - if (!regex.hasMatch(text)) { - tumIdValid.addError(errorMessage); - tumIdValid.add(false); + if (!lettersRegex.hasMatch(textEditingController3.text)) { + tumIdValid.addError(context.tr("onlyLetters")); + return; } - } - void validateLength(String text, int length) { - if (text.length != length) { + if (textEditingController1.text.length != 2 || + textEditingController2.text.length != 2 || + textEditingController3.text.length != 3) { tumIdValid.add(false); + return; } + + tumIdValid.add(true); } Future checkLogin() async { @@ -163,8 +159,7 @@ class OnboardingViewModel { iOSName: "CalendarWidget", androidName: "widgets.calendar.CalendarWidget", ); - getIt().resetAll(); - getIt().resetColorPreferences(); + await resetPreferences(ref); Api.tumToken = ""; credentials.add(Credentials.none); } diff --git a/lib/onboardingComponent/views/confirm_view.dart b/lib/onboardingComponent/views/confirm_view.dart index 72db2d99..69fb473d 100644 --- a/lib/onboardingComponent/views/confirm_view.dart +++ b/lib/onboardingComponent/views/confirm_view.dart @@ -7,6 +7,7 @@ import 'package:campus_flutter/base/networking/apis/tumOnlineApi/tum_online_api_ import 'package:campus_flutter/base/errorHandling/error_handling_router.dart'; import 'package:campus_flutter/base/routing/routes.dart'; import 'package:campus_flutter/onboardingComponent/viewModels/onboarding_viewmodel.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -41,9 +42,9 @@ class _ConfirmViewState extends ConsumerState { @override void didChangeDependencies() { texts = [ - context.localizations.signInToTumOnline, - context.localizations.selectTokenManagement, - context.localizations.activateToken, + context.tr("signInToTumOnline"), + context.tr("selectTokenManagement"), + context.tr("activateToken"), ]; super.didChangeDependencies(); } @@ -100,7 +101,7 @@ class _ConfirmViewState extends ConsumerState { appBar: AppBar( leading: const CustomBackButton(), backgroundColor: backgroundColor, - title: Text(context.localizations.checkToken), + title: Text(context.tr("checkToken")), ), body: _body(), ); @@ -239,7 +240,7 @@ class _ConfirmViewState extends ConsumerState { }, child: IconText( iconData: Icons.arrow_forward, - label: context.localizations.checkToken, + label: context.tr("checkToken"), style: const TextStyle(color: Colors.white), leadingIcon: false, ), @@ -251,7 +252,7 @@ class _ConfirmViewState extends ConsumerState { child: MaterialButton( onPressed: () => context.push(feedback), child: Text( - context.localizations.contactSupport, + context.tr("contactSupport"), style: TextStyle(color: context.primaryColor), ), ), diff --git a/lib/onboardingComponent/views/location_permissions_view.dart b/lib/onboardingComponent/views/location_permissions_view.dart index bc6a5b2e..a051d809 100644 --- a/lib/onboardingComponent/views/location_permissions_view.dart +++ b/lib/onboardingComponent/views/location_permissions_view.dart @@ -1,6 +1,6 @@ -import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/onboardingComponent/viewModels/onboarding_viewmodel.dart'; import 'package:campus_flutter/onboardingComponent/views/permission_view.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -11,8 +11,8 @@ class LocationPermissionView extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { return PermissionView( imagePath: "assets/images/location.png", - title: context.localizations.location, - description: context.localizations.locationOnboarding, + title: context.tr("location"), + description: context.tr("locationOnboarding"), onButtonPress: () => ref.read(onboardingViewModel).requestLocation( ref, context, diff --git a/lib/onboardingComponent/views/login_view.dart b/lib/onboardingComponent/views/login_view.dart index 6e378c77..f18ccd39 100644 --- a/lib/onboardingComponent/views/login_view.dart +++ b/lib/onboardingComponent/views/login_view.dart @@ -2,6 +2,7 @@ import 'package:campus_flutter/base/enums/error_handling_view_type.dart'; import 'package:campus_flutter/base/errorHandling/error_handling_router.dart'; import 'package:campus_flutter/base/routing/routes.dart'; import 'package:campus_flutter/onboardingComponent/viewModels/onboarding_viewmodel.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -53,7 +54,7 @@ class _LoginViewState extends ConsumerState { padding: EdgeInsets.symmetric(vertical: 10.0), ), Text( - context.localizations.welcomeToTheApp, + context.tr("welcomeToTheApp"), style: Theme.of(context).textTheme.titleLarge, textAlign: TextAlign.center, ), @@ -61,7 +62,7 @@ class _LoginViewState extends ConsumerState { padding: EdgeInsets.symmetric(vertical: 10.0), ), Text( - context.localizations.enterYourIDToStart, + context.tr("enterYourIDToStart"), style: Theme.of(context).textTheme.titleMedium, textAlign: TextAlign.center, ), @@ -97,21 +98,18 @@ class _LoginViewState extends ConsumerState { padding: EdgeInsets.symmetric(vertical: 10.0), ), Text( - context.localizations.welcomeToTheApp, + context.tr("welcomeToTheApp"), style: Theme.of(context).textTheme.titleLarge, textAlign: TextAlign.center, ), const Spacer(), Text( - context.localizations.enterYourIDToStart, + context.tr("enterYourIDToStart"), style: Theme.of(context).textTheme.titleMedium, textAlign: TextAlign.center, ), const Padding(padding: EdgeInsets.symmetric(vertical: 5.0)), _tumIdTextFields(context, ref), - const Padding( - padding: EdgeInsets.symmetric(vertical: 10.0), - ), _loginButton(context, ref), const Padding( padding: EdgeInsets.symmetric(vertical: 10.0), @@ -134,62 +132,29 @@ class _LoginViewState extends ConsumerState { children: [ const Spacer(), Expanded( - child: TextField( - decoration: const InputDecoration( - hintText: "go", - border: OutlineInputBorder(), - ), - inputFormatters: [LengthLimitingTextInputFormatter(2)], - controller: ref.read(onboardingViewModel).textEditingController1, - onChanged: (text) { - ref.read(onboardingViewModel).checkTumId(context); - if (text.length == 2) { - FocusScope.of(context).nextFocus(); - } - }, - enableSuggestions: false, - onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(), + child: _loginTextField( + "go", + TextInputType.text, + 2, + ref.read(onboardingViewModel).textEditingController1, ), ), const Padding(padding: EdgeInsets.symmetric(horizontal: 4.0)), Expanded( - child: TextField( - decoration: const InputDecoration( - hintText: "42", - border: OutlineInputBorder(), - ), - keyboardType: TextInputType.number, - inputFormatters: [LengthLimitingTextInputFormatter(2)], - controller: ref.read(onboardingViewModel).textEditingController2, - onChanged: (text) { - ref.read(onboardingViewModel).checkTumId(context); - if (text.length == 2 && int.tryParse(text) != null) { - FocusScope.of(context).nextFocus(); - } else if (text.isEmpty) { - FocusScope.of(context).previousFocus(); - } - }, - enableSuggestions: false, - onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(), + child: _loginTextField( + "42", + TextInputType.number, + 2, + ref.read(onboardingViewModel).textEditingController2, ), ), const Padding(padding: EdgeInsets.symmetric(horizontal: 4.0)), Expanded( - child: TextField( - decoration: const InputDecoration( - hintText: "tum", - border: OutlineInputBorder(), - ), - controller: ref.read(onboardingViewModel).textEditingController3, - inputFormatters: [LengthLimitingTextInputFormatter(3)], - onChanged: (text) { - ref.read(onboardingViewModel).checkTumId(context); - if (text.isEmpty) { - FocusScope.of(context).previousFocus(); - } - }, - enableSuggestions: false, - onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(), + child: _loginTextField( + "tum", + TextInputType.text, + 3, + ref.read(onboardingViewModel).textEditingController3, ), ), const Spacer(), @@ -197,57 +162,93 @@ class _LoginViewState extends ConsumerState { ); } + Widget _loginTextField( + String hintText, + TextInputType keyboardType, + int maxLength, + TextEditingController controller, + ) { + return TextField( + decoration: InputDecoration( + hintText: hintText, + hintStyle: TextStyle( + color: MediaQuery.platformBrightnessOf(context) == Brightness.dark + ? Colors.grey.shade700 + : Colors.grey.shade400, + ), + border: const OutlineInputBorder(), + ), + keyboardType: keyboardType, + inputFormatters: [LengthLimitingTextInputFormatter(maxLength)], + controller: controller, + onChanged: (text) { + ref.read(onboardingViewModel).checkTumId(context); + if (text.length == maxLength && maxLength != 3) { + FocusScope.of(context).nextFocus(); + } + }, + enableSuggestions: false, + onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(), + ); + } + Widget _loginButton(BuildContext context, WidgetRef ref) { - return StreamBuilder( - stream: ref.watch(onboardingViewModel).tumIdValid, - builder: (context, snapshot) { - return Column( - children: [ - if (snapshot.hasError) _textFieldError(snapshot.error!), - ElevatedButton( - onPressed: (snapshot.data != null && snapshot.data!) - ? () { - ref.read(onboardingViewModel).requestLogin().then( - (value) => context.push(confirm), - onError: (error) { - ScaffoldMessenger.maybeOf(context)?.showSnackBar( - SnackBar( - duration: const Duration(seconds: 10), - content: ErrorHandlingRouter( - error: error, - errorHandlingViewType: - ErrorHandlingViewType.textOnly, - titleColor: Colors.white, + return Padding( + padding: const EdgeInsets.only(top: 10.0), + child: StreamBuilder( + stream: ref.watch(onboardingViewModel).tumIdValid, + builder: (context, snapshot) { + return Column( + children: [ + if (snapshot.hasError) _textFieldError(snapshot.error!), + ElevatedButton( + onPressed: (snapshot.data != null && snapshot.data!) + ? () { + ref.read(onboardingViewModel).requestLogin().then( + (value) => context.push(confirm), + onError: (error) { + ScaffoldMessenger.maybeOf(context)?.showSnackBar( + SnackBar( + duration: const Duration(seconds: 10), + content: ErrorHandlingRouter( + error: error, + errorHandlingViewType: + ErrorHandlingViewType.textOnly, + titleColor: Colors.white, + ), ), - ), - ); - }, - ); - } - : null, - child: Text( - context.localizations.login, - style: Theme.of(context) - .textTheme - .titleLarge - ?.copyWith(color: Colors.white), + ); + }, + ); + } + : null, + child: Text( + context.tr("login"), + style: Theme.of(context) + .textTheme + .titleLarge + ?.copyWith(color: Colors.white), + ), ), - ), - ], - ); - }, + ], + ); + }, + ), ); } Widget _textFieldError(Object error) { - return Text(error.toString(), style: const TextStyle(color: Colors.red)); + return Padding( + padding: const EdgeInsets.only(bottom: 10), + child: Text(error.toString(), style: const TextStyle(color: Colors.red)), + ); } Widget _skipLoginButton(BuildContext context, WidgetRef ref) { return GestureDetector( onTap: () => ref.read(onboardingViewModel).skip(context), child: Text( - context.localizations.continueWithoutID, + context.tr("continueWithoutID"), style: Theme.of(context) .textTheme .bodySmall diff --git a/lib/onboardingComponent/views/permission_check_view.dart b/lib/onboardingComponent/views/permission_check_view.dart index c590e66c..796fc79b 100644 --- a/lib/onboardingComponent/views/permission_check_view.dart +++ b/lib/onboardingComponent/views/permission_check_view.dart @@ -4,9 +4,9 @@ import 'package:campus_flutter/calendarComponent/services/calendar_service.dart' import 'package:campus_flutter/gradeComponent/services/grade_service.dart'; import 'package:campus_flutter/lectureComponent/services/lecture_service.dart'; import 'package:campus_flutter/profileComponent/services/profile_service.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; import 'package:go_router/go_router.dart'; class PermissionCheckView extends ConsumerStatefulWidget { @@ -55,7 +55,7 @@ class _PermissionCheckViewState extends ConsumerState { backgroundColor: backgroundColor, appBar: AppBar( leading: widget.isSettingsView ? const CustomBackButton() : null, - title: Text(context.localizations.checkPermissions), + title: Text(context.tr("checkPermissions")), backgroundColor: backgroundColor, ), body: Padding( @@ -65,22 +65,22 @@ class _PermissionCheckViewState extends ConsumerState { Expanded( flex: 0, child: Text( - context.localizations.permissionChangePossibleInTUMonline, + context.tr("permissionChangePossibleInTUMonline"), style: Theme.of(context).textTheme.titleMedium, textAlign: TextAlign.center, ), ), const Spacer(), - _permissionCheck(context.localizations.calendar, fetchCalendar), + _permissionCheck(context.tr("calendar"), fetchCalendar), const Spacer(), - _permissionCheck(context.localizations.lectures, fetchLecture), + _permissionCheck(context.tr("lectures"), fetchLecture), const Spacer(), - _permissionCheck(context.localizations.grades, fetchGrades), + _permissionCheck(context.tr("grades"), fetchGrades), const Spacer(), - _permissionCheck(context.localizations.tuition, fetchTuition), + _permissionCheck(context.tr("tuition"), fetchTuition), const Spacer(), _permissionCheck( - context.localizations.identification, + context.tr("identification"), fetchProfile, ), const Spacer(flex: 3), @@ -99,8 +99,8 @@ class _PermissionCheckViewState extends ConsumerState { }, child: Text( widget.isSettingsView - ? context.localizations.back - : context.localizations.continueOnboarding, + ? context.tr("back") + : context.tr("continueOnboarding"), ), ), ), diff --git a/lib/personDetailedComponent/views/person_details_view.dart b/lib/personDetailedComponent/views/person_details_view.dart index 0c59c582..5e0ba6db 100644 --- a/lib/personDetailedComponent/views/person_details_view.dart +++ b/lib/personDetailedComponent/views/person_details_view.dart @@ -10,6 +10,7 @@ import 'package:campus_flutter/homeComponent/widgetComponent/views/widget_frame_ import 'package:campus_flutter/personDetailedComponent/model/person_details.dart'; import 'package:campus_flutter/personDetailedComponent/viewModel/person_details_viewmodel.dart'; import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -24,7 +25,7 @@ class PersonDetailsScaffold extends StatelessWidget { return Scaffold( appBar: AppBar( leading: const CustomBackButton(), - title: Text(context.localizations.personDetails), + title: Text(context.tr("personDetails")), ), body: PersonDetailsView( obfuscatedId: obfuscatedId, @@ -68,7 +69,7 @@ class _PersonDetailsViewState extends ConsumerState { } else { return Center( child: DelayedLoadingIndicator( - name: context.localizations.personDetails, + name: context.tr("personDetails"), ), ); } @@ -117,7 +118,7 @@ class _PersonDetailsViewState extends ConsumerState { Widget _contact(PersonDetails personDetails) { return WidgetFrameView( - title: context.localizations.contact, + title: context.tr("contact"), child: Card( child: SeparatedList.widgets( widgets: [ @@ -141,7 +142,7 @@ class _PersonDetailsViewState extends ConsumerState { ), title: Text( personDetails.phoneExtensions.first.phoneNumber ?? - context.localizations.unknown, + context.tr("unknown"), style: const TextStyle( decoration: TextDecoration.underline, ), @@ -174,7 +175,7 @@ class _PersonDetailsViewState extends ConsumerState { Widget _room(PersonDetails personDetails) { return WidgetFrameView( - title: context.localizations.room, + title: context.tr("room"), child: Card( child: SeparatedList.widgets( widgets: [ @@ -185,7 +186,7 @@ class _PersonDetailsViewState extends ConsumerState { ), title: Text( personDetails.rooms.first.shortLocationDescription ?? - context.localizations.unknown, + context.tr("unknown"), ), trailing: const Icon( Icons.arrow_forward_ios, @@ -205,8 +206,7 @@ class _PersonDetailsViewState extends ConsumerState { color: context.theme.primaryColor, ), title: Text( - personDetails.rooms.first.floorName ?? - context.localizations.unknown, + personDetails.rooms.first.floorName ?? context.tr("unknown"), ), ), ListTile( @@ -215,8 +215,7 @@ class _PersonDetailsViewState extends ConsumerState { color: context.theme.primaryColor, ), title: Text( - personDetails.rooms.first.buildingName ?? - context.localizations.unknown, + personDetails.rooms.first.buildingName ?? context.tr("unknown"), ), ), ], diff --git a/lib/placesComponent/model/cafeterias/cafeteria.g.dart b/lib/placesComponent/model/cafeterias/cafeteria.g.dart index b9272dd7..8759bdda 100644 --- a/lib/placesComponent/model/cafeterias/cafeteria.g.dart +++ b/lib/placesComponent/model/cafeterias/cafeteria.g.dart @@ -19,8 +19,8 @@ Map _$LocationToJson(Location instance) => { }; Queue _$QueueFromJson(Map json) => Queue( - current: json['current'] as int, - percent: json['percent'] as int, + current: (json['current'] as num).toInt(), + percent: (json['percent'] as num).toInt(), ); Map _$QueueToJson(Queue instance) => { diff --git a/lib/placesComponent/model/cafeterias/meal_plan.g.dart b/lib/placesComponent/model/cafeterias/meal_plan.g.dart index a17a4418..ef7874b0 100644 --- a/lib/placesComponent/model/cafeterias/meal_plan.g.dart +++ b/lib/placesComponent/model/cafeterias/meal_plan.g.dart @@ -7,8 +7,8 @@ part of 'meal_plan.dart'; // ************************************************************************** MealPlan _$MealPlanFromJson(Map json) => MealPlan( - week: json['number'] as int, - year: json['year'] as int, + week: (json['number'] as num).toInt(), + year: (json['year'] as num).toInt(), days: (json['days'] as List) .map((e) => MensaMenu.fromJson(e as Map)) .toList(), diff --git a/lib/placesComponent/model/studyRooms/study_room.dart b/lib/placesComponent/model/studyRooms/study_room.dart index c9037bd4..3adb7c1c 100644 --- a/lib/placesComponent/model/studyRooms/study_room.dart +++ b/lib/placesComponent/model/studyRooms/study_room.dart @@ -1,7 +1,7 @@ import 'package:campus_flutter/placesComponent/model/studyRooms/study_room_attribute.dart'; import 'package:campus_flutter/searchComponent/model/comparison_token.dart'; import 'package:campus_flutter/searchComponent/protocols/searchable.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:json_annotation/json_annotation.dart'; @@ -26,11 +26,11 @@ class StudyRoom extends Searchable { @JsonKey(name: "belegung_durch") final String? occupiedBy; @JsonKey(name: "belegung_fuer") - final int occupiedFor; + final int? occupiedFor; @JsonKey(name: "belegung_ab", fromJson: DateTime.tryParse) final DateTime? occupiedFrom; @JsonKey(name: "belegung_in") - final int occupiedIn; + final int? occupiedIn; @JsonKey(name: "belegung_bis", fromJson: DateTime.tryParse) final DateTime? occupiedUntil; @JsonKey(name: "raum_nr_architekt") @@ -44,15 +44,18 @@ class StudyRoom extends Searchable { String localizedStatus(BuildContext context) { switch (status) { case "frei": - return context.localizations.free; + return context.tr("free"); case "belegt": if (occupiedUntil != null) { - return context.localizations.occupiedUntil(occupiedUntil!); + return context.tr( + "occupiedUntil", + args: [DateFormat.Hm().format(occupiedUntil!)], + ); } else { - return context.localizations.unknown; + return context.tr("unknown"); } default: - return context.localizations.unknown; + return context.tr("unknown"); } } diff --git a/lib/placesComponent/model/studyRooms/study_room.g.dart b/lib/placesComponent/model/studyRooms/study_room.g.dart index a1694afb..713c5e2d 100644 --- a/lib/placesComponent/model/studyRooms/study_room.g.dart +++ b/lib/placesComponent/model/studyRooms/study_room.g.dart @@ -9,18 +9,18 @@ part of 'study_room.dart'; StudyRoom _$StudyRoomFromJson(Map json) => StudyRoom( buildingCode: json['gebaeude_code'] as String?, buildingName: json['gebaeude_name'] as String?, - buildingNumber: json['gebaeude_nr'] as int, + buildingNumber: (json['gebaeude_nr'] as num).toInt(), code: json['raum_code'] as String?, - id: json['raum_nr'] as int, + id: (json['raum_nr'] as num).toInt(), name: json['raum_name'] as String?, number: json['raum_nummer'] as String?, occupiedBy: json['belegung_durch'] as String?, - occupiedFor: json['belegung_fuer'] as int, + occupiedFor: (json['belegung_fuer'] as num?)?.toInt(), occupiedFrom: DateTime.tryParse(json['belegung_ab'] as String), - occupiedIn: json['belegung_in'] as int, + occupiedIn: (json['belegung_in'] as num?)?.toInt(), occupiedUntil: DateTime.tryParse(json['belegung_bis'] as String), roomNoArchitect: json['raum_nr_architekt'] as String?, - resNo: json['res_nr'] as int, + resNo: (json['res_nr'] as num).toInt(), status: json['status'] as String?, attributes: (json['attribute'] as List?) ?.map((e) => StudyRoomAttribute.fromJson(e as Map)) diff --git a/lib/placesComponent/model/studyRooms/study_room_group.g.dart b/lib/placesComponent/model/studyRooms/study_room_group.g.dart index 91de046e..40582196 100644 --- a/lib/placesComponent/model/studyRooms/study_room_group.g.dart +++ b/lib/placesComponent/model/studyRooms/study_room_group.g.dart @@ -9,10 +9,12 @@ part of 'study_room_group.dart'; StudyRoomGroup _$StudyRoomGroupFromJson(Map json) => StudyRoomGroup( detail: json['detail'] as String?, - id: json['nr'] as int, + id: (json['nr'] as num).toInt(), name: json['name'] as String, - sorting: json['sortierung'] as int, - rooms: (json['raeume'] as List?)?.map((e) => e as int).toList(), + sorting: (json['sortierung'] as num).toInt(), + rooms: (json['raeume'] as List?) + ?.map((e) => (e as num).toInt()) + .toList(), ); Map _$StudyRoomGroupToJson(StudyRoomGroup instance) => diff --git a/lib/placesComponent/viewModels/cafeterias_viewmodel.dart b/lib/placesComponent/viewModels/cafeterias_viewmodel.dart index 8331c098..f79760b6 100644 --- a/lib/placesComponent/viewModels/cafeterias_viewmodel.dart +++ b/lib/placesComponent/viewModels/cafeterias_viewmodel.dart @@ -1,6 +1,5 @@ import 'package:campus_flutter/base/enums/campus.dart'; import 'package:campus_flutter/base/enums/user_preference.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/base/routing/routes.dart'; import 'package:campus_flutter/base/services/location_service.dart'; import 'package:campus_flutter/main.dart'; @@ -12,12 +11,12 @@ import 'package:campus_flutter/placesComponent/services/cafeterias_service.dart' import 'package:campus_flutter/placesComponent/services/mealplan_service.dart'; import 'package:campus_flutter/settingsComponent/service/user_preferences_service.dart'; import 'package:collection/collection.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:geolocator/geolocator.dart'; import 'package:go_router/go_router.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; -import 'package:intl/intl.dart'; import 'package:rxdart/rxdart.dart'; import 'package:uuid/uuid.dart'; @@ -194,7 +193,7 @@ class CafeteriasViewModel { 0, ListTile( dense: true, - title: Text(context.localizations.closest), + title: Text(context.tr("closest")), trailing: getIt().load( UserPreference.cafeteria, ) == diff --git a/lib/placesComponent/viewModels/study_rooms_viewmodel.dart b/lib/placesComponent/viewModels/study_rooms_viewmodel.dart index 0fad467e..a6ca4212 100644 --- a/lib/placesComponent/viewModels/study_rooms_viewmodel.dart +++ b/lib/placesComponent/viewModels/study_rooms_viewmodel.dart @@ -1,6 +1,5 @@ import 'package:campus_flutter/base/enums/campus.dart'; import 'package:campus_flutter/base/enums/user_preference.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/base/routing/routes.dart'; import 'package:campus_flutter/base/services/location_service.dart'; import 'package:campus_flutter/main.dart'; @@ -9,6 +8,7 @@ import 'package:campus_flutter/placesComponent/model/studyRooms/study_room_data. import 'package:campus_flutter/placesComponent/model/studyRooms/study_room_group.dart'; import 'package:campus_flutter/placesComponent/services/study_rooms_service.dart'; import 'package:campus_flutter/settingsComponent/service/user_preferences_service.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:collection/collection.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -89,7 +89,7 @@ class StudyRoomsViewModel { _getClosestStudyRoomGroup(Position? position, BuildContext context) { if (studyRoomData?.groups == null) { - widgetStudyRoom.addError(context.localizations.noClosestStudyRoom); + widgetStudyRoom.addError(context.tr("noClosestStudyRoom")); return; } @@ -99,7 +99,7 @@ class StudyRoomsViewModel { ) ?? studyRoomData?.groups?.firstOrNull; if (defaultStudyRoom == null) { - widgetStudyRoom.addError(context.localizations.noClosestStudyRoom); + widgetStudyRoom.addError(context.tr("noClosestStudyRoom")); } else { widgetStudyRoom.add(defaultStudyRoom); } @@ -213,7 +213,7 @@ class StudyRoomsViewModel { 0, ListTile( dense: true, - title: Text(context.localizations.closest), + title: Text(context.tr("closest")), trailing: getIt().load( UserPreference.studyRoom, ) == diff --git a/lib/placesComponent/views/cafeterias/cafeteria_view.dart b/lib/placesComponent/views/cafeterias/cafeteria_view.dart index 55ccbf54..ec412f3c 100644 --- a/lib/placesComponent/views/cafeterias/cafeteria_view.dart +++ b/lib/placesComponent/views/cafeterias/cafeteria_view.dart @@ -13,6 +13,7 @@ import 'package:campus_flutter/placesComponent/views/cafeterias/dish_grid_view.d import 'package:campus_flutter/placesComponent/views/map_widget.dart'; import 'package:campus_flutter/base/extensions/context.dart'; import 'package:collection/collection.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -70,7 +71,7 @@ class CafeteriaScaffold extends ConsumerWidget { final openingHours = cafeteria.openingHours; return AlertDialog( title: Text( - context.localizations.openingHours, + context.tr("openingHours"), style: Theme.of(context).textTheme.titleMedium, textAlign: TextAlign.center, ), @@ -78,28 +79,28 @@ class CafeteriaScaffold extends ConsumerWidget { mainAxisSize: MainAxisSize.min, children: [ InfoRow( - title: context.localizations.monday, + title: context.tr("monday"), info: _openingHourStringBuilder(openingHours?.mon, context), ), InfoRow( - title: context.localizations.tuesday, + title: context.tr("tuesday"), info: _openingHourStringBuilder(openingHours?.tue, context), ), InfoRow( - title: context.localizations.wednesday, + title: context.tr("wednesday"), info: _openingHourStringBuilder(openingHours?.wed, context), ), InfoRow( - title: context.localizations.thursday, + title: context.tr("thursday"), info: _openingHourStringBuilder(openingHours?.thu, context), ), InfoRow( - title: context.localizations.friday, + title: context.tr("friday"), info: _openingHourStringBuilder(openingHours?.fri, context), ), InfoRow( - title: context.localizations.weekend, - info: context.localizations.closed, + title: context.tr("weekend"), + info: context.tr("closed"), ), ], ), @@ -120,7 +121,7 @@ class CafeteriaScaffold extends ConsumerWidget { BuildContext context, ) { if (openingHour == null) { - return context.localizations.unknown; + return context.tr("unknown"); } else { return "${openingHour.start} - ${openingHour.end}"; } @@ -201,8 +202,9 @@ class _CafeteriaViewState extends ConsumerState { if (snapshot.data!.isEmpty) { return Center( child: Text( - context.localizations.noEntriesFound( - context.localizations.mealPlans, + context.tr( + "noEntriesFound", + args: [context.tr("mealPlans")], ), ), ); @@ -268,8 +270,9 @@ class _CafeteriaViewState extends ConsumerState { if (todayMeals.isEmpty) Center( child: Text( - context.localizations.noEntriesFound( - context.localizations.mealPlans, + context.tr( + "noEntriesFound", + args: [context.tr("mealPlans")], ), ), ), @@ -282,7 +285,7 @@ class _CafeteriaViewState extends ConsumerState { errorHandlingViewType: ErrorHandlingViewType.descriptionOnly, ); } else { - return DelayedLoadingIndicator(name: context.localizations.mealPlans); + return DelayedLoadingIndicator(name: context.tr("mealPlans")); } }, ); diff --git a/lib/placesComponent/views/cafeterias/cafeterias_view.dart b/lib/placesComponent/views/cafeterias/cafeterias_view.dart index be5285b5..b3c07814 100644 --- a/lib/placesComponent/views/cafeterias/cafeterias_view.dart +++ b/lib/placesComponent/views/cafeterias/cafeterias_view.dart @@ -10,6 +10,7 @@ import 'package:campus_flutter/placesComponent/viewModels/cafeterias_viewmodel.d import 'package:campus_flutter/placesComponent/views/cafeterias/cafeteria_row_view.dart'; import 'package:campus_flutter/placesComponent/views/map_widget.dart'; import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -21,7 +22,7 @@ class CafeteriasScaffold extends StatelessWidget { return Scaffold( appBar: AppBar( leading: const CustomBackButton(), - title: Text(context.localizations.cafeterias), + title: Text(context.tr("cafeterias")), ), body: const CafeteriasView(), ); @@ -98,7 +99,7 @@ class _CafeteriasState extends ConsumerState { ); } else { return DelayedLoadingIndicator( - name: context.localizations.cafeterias, + name: context.tr("cafeterias"), ); } }, @@ -107,7 +108,7 @@ class _CafeteriasState extends ConsumerState { Widget _cafeteriaList(List cafeterias, bool portrait) { return WidgetFrameView( - title: portrait ? context.localizations.cafeterias : null, + title: portrait ? context.tr("cafeterias") : null, child: Card( child: SeparatedList.list( data: cafeterias, diff --git a/lib/placesComponent/views/campuses/campus_most_searched_view.dart b/lib/placesComponent/views/campuses/campus_most_searched_view.dart index 08e6fa42..d1bd5ee7 100644 --- a/lib/placesComponent/views/campuses/campus_most_searched_view.dart +++ b/lib/placesComponent/views/campuses/campus_most_searched_view.dart @@ -5,6 +5,7 @@ import 'package:campus_flutter/base/routing/routes.dart'; import 'package:campus_flutter/homeComponent/widgetComponent/views/widget_frame_view.dart'; import 'package:campus_flutter/navigaTumComponent/viewModels/navigatum_campus_viewmodel.dart'; import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -20,7 +21,7 @@ class CampusMostSearchedView extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { return WidgetFrameView( - title: context.localizations.mostSearchedRooms, + title: context.tr("mostSearchedRooms"), child: Card( child: StreamBuilder( stream: @@ -32,8 +33,9 @@ class CampusMostSearchedView extends ConsumerWidget { padding: EdgeInsets.all(context.padding), child: Center( child: Text( - context.localizations.noEntriesFound( - context.localizations.rooms, + context.tr( + "noEntriesFound", + args: [context.tr("rooms")], ), ), ), @@ -65,7 +67,7 @@ class CampusMostSearchedView extends ConsumerWidget { return Padding( padding: EdgeInsets.all(context.padding), child: DelayedLoadingIndicator( - name: context.localizations.mostSearchedRooms, + name: context.tr("mostSearchedRooms"), ), ); } diff --git a/lib/placesComponent/views/campuses/campus_view.dart b/lib/placesComponent/views/campuses/campus_view.dart index d95e0d00..f121b381 100644 --- a/lib/placesComponent/views/campuses/campus_view.dart +++ b/lib/placesComponent/views/campuses/campus_view.dart @@ -12,7 +12,7 @@ import 'package:campus_flutter/placesComponent/views/cafeterias/cafeteria_row_vi import 'package:campus_flutter/placesComponent/views/campuses/campus_most_searched_view.dart'; import 'package:campus_flutter/placesComponent/views/homeWidget/study_room_widget_view.dart'; import 'package:campus_flutter/placesComponent/views/map_widget.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; @@ -83,7 +83,7 @@ class _CampusViewState extends ConsumerState { children: [ Expanded( child: WidgetFrameView( - title: context.localizations.map, + title: context.tr("map"), child: Expanded( child: MapWidget.fullPadding( aspectRatioNeeded: false, @@ -126,7 +126,7 @@ class _CampusViewState extends ConsumerState { WidgetFrameView( titleWidget: IconText( iconData: Icons.location_pin, - label: context.localizations.cafeterias, + label: context.tr("cafeterias"), style: Theme.of(context).textTheme.titleMedium, leadingIcon: false, ), @@ -141,7 +141,7 @@ class _CampusViewState extends ConsumerState { WidgetFrameView( titleWidget: IconText( iconData: Icons.location_pin, - label: context.localizations.studyRooms, + label: context.tr("studyRooms"), iconColor: Colors.red, style: Theme.of(context).textTheme.titleMedium, leadingIcon: false, diff --git a/lib/placesComponent/views/homeWidget/cafeteria_widget_view.dart b/lib/placesComponent/views/homeWidget/cafeteria_widget_view.dart index c083b770..26bbb8a8 100644 --- a/lib/placesComponent/views/homeWidget/cafeteria_widget_view.dart +++ b/lib/placesComponent/views/homeWidget/cafeteria_widget_view.dart @@ -10,6 +10,7 @@ import 'package:campus_flutter/placesComponent/model/cafeterias/cafeteria_menu.d import 'package:campus_flutter/placesComponent/viewModels/cafeterias_viewmodel.dart'; import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/placesComponent/views/cafeterias/dish_slider_view.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -40,7 +41,7 @@ class _CafeteriaWidgetViewState extends ConsumerState { Expanded( child: InkWell( child: Text( - snapshot.data?.$1.name ?? context.localizations.cafeteria, + snapshot.data?.$1.name ?? context.tr("cafeteria"), style: Theme.of(context).textTheme.titleMedium, maxLines: 1, overflow: TextOverflow.ellipsis, @@ -60,7 +61,7 @@ class _CafeteriaWidgetViewState extends ConsumerState { data: ref .read(cafeteriasViewModel) .getCafeteriaEntries(context), - entry: context.localizations.cafeteria, + entry: context.tr("cafeteria"), ), context: context, useRootNavigator: true, @@ -94,8 +95,9 @@ class _CafeteriaWidgetViewState extends ConsumerState { height: 150, child: Center( child: Text( - context.localizations.noEntriesFound( - context.localizations.mealPlans, + context.tr( + "noEntriesFound", + args: [context.tr("mealPlans")], ), ), ), @@ -118,7 +120,7 @@ class _CafeteriaWidgetViewState extends ConsumerState { return Card( child: SizedBox( height: 150, - child: DelayedLoadingIndicator(name: context.localizations.mealPlans), + child: DelayedLoadingIndicator(name: context.tr("mealPlans")), ), ); } diff --git a/lib/placesComponent/views/homeWidget/study_room_widget_view.dart b/lib/placesComponent/views/homeWidget/study_room_widget_view.dart index 9d1cb928..415fde7e 100644 --- a/lib/placesComponent/views/homeWidget/study_room_widget_view.dart +++ b/lib/placesComponent/views/homeWidget/study_room_widget_view.dart @@ -7,6 +7,7 @@ import 'package:campus_flutter/homeComponent/widgetComponent/views/widget_frame_ import 'package:campus_flutter/placesComponent/model/studyRooms/study_room_group.dart'; import 'package:campus_flutter/placesComponent/viewModels/study_rooms_viewmodel.dart'; import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -64,7 +65,7 @@ class _StudyRoomWidgetViewState extends ConsumerState { children: [ Expanded( child: Text( - context.localizations.studyRooms, + context.tr("studyRooms"), style: Theme.of(context).textTheme.titleMedium, maxLines: 1, overflow: TextOverflow.ellipsis, @@ -81,7 +82,7 @@ class _StudyRoomWidgetViewState extends ConsumerState { data: ref .read(studyRoomsViewModel) .getStudyRoomEntries(context), - entry: context.localizations.studyRoom, + entry: context.tr("studyRoom"), ), context: context, useRootNavigator: true, @@ -133,7 +134,7 @@ class _StudyRoomWidgetViewState extends ConsumerState { } else { return ListTile( title: Center( - child: Text(context.localizations.noNearFreeStudyRoomsFound), + child: Text(context.tr("noNearFreeStudyRoomsFound")), ), ); } @@ -147,7 +148,7 @@ class _StudyRoomWidgetViewState extends ConsumerState { } else { return ListTile( title: DelayedLoadingIndicator( - name: context.localizations.nearestStudyRooms, + name: context.tr("nearestStudyRooms"), ), ); } @@ -167,7 +168,7 @@ class _StudyRoomWidgetViewState extends ConsumerState { Widget _freeRooms(StudyRoomGroup studyRoomGroup) { final freeRooms = ref.read(studyRoomsViewModel).freeRooms(studyRoomGroup); return Text( - context.localizations.nfreeRooms(freeRooms), + context.plural("nFreeRooms", freeRooms), style: TextStyle(color: freeRooms > 0 ? Colors.green : Colors.red), ); } diff --git a/lib/placesComponent/views/places_screen.dart b/lib/placesComponent/views/places_screen.dart index 73198304..550c0161 100644 --- a/lib/placesComponent/views/places_screen.dart +++ b/lib/placesComponent/views/places_screen.dart @@ -5,7 +5,7 @@ import 'package:campus_flutter/placesComponent/viewModels/cafeterias_viewmodel.d import 'package:campus_flutter/placesComponent/viewModels/places_viewmodel.dart'; import 'package:campus_flutter/placesComponent/viewModels/study_rooms_viewmodel.dart'; import 'package:campus_flutter/placesComponent/views/places_view.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -44,8 +44,7 @@ class _PlacesScreenState extends ConsumerState ); } else { return DelayedLoadingIndicator( - name: - "${context.localizations.cafeterias} & ${context.localizations.studyRooms}", + name: "${context.tr("cafeterias")} & ${context.tr("studyRooms")}", ); } }, diff --git a/lib/placesComponent/views/places_view.dart b/lib/placesComponent/views/places_view.dart index e9a69560..526d65c3 100644 --- a/lib/placesComponent/views/places_view.dart +++ b/lib/placesComponent/views/places_view.dart @@ -3,6 +3,7 @@ import 'package:campus_flutter/base/routing/routes.dart'; import 'package:campus_flutter/placesComponent/viewModels/places_viewmodel.dart'; import 'package:campus_flutter/placesComponent/views/campuses/campus_card_view.dart'; import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -96,7 +97,7 @@ class PlacesView extends ConsumerWidget { Widget _studyRoomsTile(BuildContext context) { return ListTile( leading: const Icon(Icons.school), - title: Text(context.localizations.studyRooms), + title: Text(context.tr("studyRooms")), trailing: const Icon(Icons.arrow_forward_ios, size: 15), onTap: () => context.push(studyRooms), ); @@ -105,7 +106,7 @@ class PlacesView extends ConsumerWidget { Widget _cafeteriasTile(BuildContext context) { return ListTile( leading: const Icon(Icons.restaurant), - title: Text(context.localizations.cafeterias), + title: Text(context.tr("cafeterias")), trailing: const Icon(Icons.arrow_forward_ios, size: 15), onTap: () => context.push(cafeterias), ); diff --git a/lib/placesComponent/views/studyGroups/study_room_group_view.dart b/lib/placesComponent/views/studyGroups/study_room_group_view.dart index 2ed61682..f2704319 100644 --- a/lib/placesComponent/views/studyGroups/study_room_group_view.dart +++ b/lib/placesComponent/views/studyGroups/study_room_group_view.dart @@ -10,7 +10,7 @@ import 'package:campus_flutter/placesComponent/viewModels/study_rooms_viewmodel. import 'package:campus_flutter/placesComponent/views/map_widget.dart'; import 'package:campus_flutter/placesComponent/views/studyGroups/study_room_row_view.dart'; import 'package:collection/collection.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; @@ -107,7 +107,7 @@ class StudyRoomGroupView extends ConsumerWidget { Padding( padding: const EdgeInsets.symmetric(horizontal: 10), child: Text( - studyRoomGroup?.name ?? context.localizations.unknown, + studyRoomGroup?.name ?? context.tr("unknown"), style: Theme.of(context).textTheme.titleLarge, ), ), @@ -116,7 +116,7 @@ class StudyRoomGroupView extends ConsumerWidget { _portraitMap(studyRoomGroup, context), ], WidgetFrameView( - title: context.localizations.rooms, + title: context.tr("rooms"), subtitle: lastFetched != null ? LastUpdatedText(lastFetched) : null, child: Card( diff --git a/lib/placesComponent/views/studyGroups/study_room_row_view.dart b/lib/placesComponent/views/studyGroups/study_room_row_view.dart index a7d91b42..58748a48 100644 --- a/lib/placesComponent/views/studyGroups/study_room_row_view.dart +++ b/lib/placesComponent/views/studyGroups/study_room_row_view.dart @@ -1,6 +1,6 @@ import 'package:campus_flutter/base/routing/routes.dart'; import 'package:campus_flutter/placesComponent/model/studyRooms/study_room.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -14,7 +14,7 @@ class StudyRoomRowView extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { return ListTile( title: Text( - "${studyRoom.name ?? context.localizations.unknown} (${studyRoom.code ?? context.localizations.unknown})", + "${studyRoom.name ?? context.tr("unknown")} (${studyRoom.code ?? context.tr("unknown")})", ), subtitle: Text( studyRoom.localizedStatus(context), @@ -32,7 +32,7 @@ class StudyRoomRowView extends ConsumerWidget { } Color _statusColor(String status, BuildContext context) { - if (status == context.localizations.free) { + if (status == context.tr("free")) { return Colors.green; } else { return Colors.red; diff --git a/lib/placesComponent/views/studyGroups/study_rooms_view.dart b/lib/placesComponent/views/studyGroups/study_rooms_view.dart index b79a5333..0091e925 100644 --- a/lib/placesComponent/views/studyGroups/study_rooms_view.dart +++ b/lib/placesComponent/views/studyGroups/study_rooms_view.dart @@ -10,6 +10,7 @@ import 'package:campus_flutter/placesComponent/viewModels/study_rooms_viewmodel. import 'package:campus_flutter/placesComponent/views/homeWidget/study_room_widget_view.dart'; import 'package:campus_flutter/placesComponent/views/map_widget.dart'; import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -21,7 +22,7 @@ class StudyRoomsScaffold extends StatelessWidget { return Scaffold( appBar: AppBar( leading: const CustomBackButton(), - title: Text(context.localizations.studyRooms), + title: Text(context.tr("studyRooms")), ), body: const StudyRoomsView(), ); @@ -96,7 +97,7 @@ class _StudyRoomsViewState extends ConsumerState { ); } else { return DelayedLoadingIndicator( - name: context.localizations.studyRooms, + name: context.tr("studyRooms"), ); } }, @@ -105,7 +106,7 @@ class _StudyRoomsViewState extends ConsumerState { Widget _studyRoomList(List studyRoomGroups, bool portrait) { return WidgetFrameView( - title: portrait ? context.localizations.studyRooms : null, + title: portrait ? context.tr("studyRooms") : null, child: Column( children: [ Card( diff --git a/lib/searchComponent/views/appWideSearch/resultViews/calendar_search_result_view.dart b/lib/searchComponent/views/appWideSearch/resultViews/calendar_search_result_view.dart index e6103b90..f2fe3a0d 100644 --- a/lib/searchComponent/views/appWideSearch/resultViews/calendar_search_result_view.dart +++ b/lib/searchComponent/views/appWideSearch/resultViews/calendar_search_result_view.dart @@ -5,6 +5,7 @@ import 'package:campus_flutter/base/enums/search_category.dart'; import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/calendar_search_viewmodel.dart'; import 'package:campus_flutter/searchComponent/views/appWideSearch/search_result_card_view.dart'; import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -18,7 +19,7 @@ class CalendarSearchResultView extends ConsumerWidget { searchCategory: SearchCategory.calendar, viewModel: calendarSearchViewModel, body: (calendarEvent) => ListTile( - title: Text(calendarEvent.title), + title: Text(calendarEvent.title ?? "-"), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -32,7 +33,7 @@ class CalendarSearchResultView extends ConsumerWidget { ), IconText( iconData: Icons.location_pin, - label: calendarEvent.location ?? context.localizations.unknown, + label: calendarEvent.location ?? context.tr("unknown"), style: Theme.of(context).textTheme.bodySmall?.copyWith( color: Theme.of(context).colorScheme.secondary, ), diff --git a/lib/searchComponent/views/appWideSearch/search_result_card_view.dart b/lib/searchComponent/views/appWideSearch/search_result_card_view.dart index ab720df5..57cdd872 100644 --- a/lib/searchComponent/views/appWideSearch/search_result_card_view.dart +++ b/lib/searchComponent/views/appWideSearch/search_result_card_view.dart @@ -9,6 +9,7 @@ import 'package:campus_flutter/searchComponent/protocols/search_viewmodel.dart'; import 'package:campus_flutter/searchComponent/protocols/searchable.dart'; import 'package:campus_flutter/searchComponent/viewModels/global_search_viewmodel.dart'; import 'package:campus_flutter/searchComponent/views/appWideSearch/search_result_details_view.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -40,11 +41,14 @@ class SearchResultCardView, S extends Searchable> padding: EdgeInsets.all(context.padding), child: Center( child: Text( - context.localizations.noEntriesFound( - SearchCategoryExtension.localizedEnumTitle( - searchCategory, - context, - ), + context.tr( + "noEntriesFound", + args: [ + SearchCategoryExtension.localizedEnumTitle( + searchCategory, + context, + ), + ], ), ), ), @@ -108,7 +112,7 @@ class SearchResultCardView, S extends Searchable> dense: true, title: Center( child: Text( - context.localizations.showMore, + context.tr("showMore"), style: Theme.of(context).textTheme.titleMedium, ), ), diff --git a/lib/searchComponent/views/appWideSearch/search_scaffold.dart b/lib/searchComponent/views/appWideSearch/search_scaffold.dart index 7621de7c..9f89365d 100644 --- a/lib/searchComponent/views/appWideSearch/search_scaffold.dart +++ b/lib/searchComponent/views/appWideSearch/search_scaffold.dart @@ -1,7 +1,7 @@ import 'package:campus_flutter/base/util/custom_back_button.dart'; import 'package:campus_flutter/searchComponent/viewModels/global_search_viewmodel.dart'; import 'package:campus_flutter/searchComponent/views/appWideSearch/search_view.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -13,7 +13,7 @@ class SearchScaffold extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { return Scaffold( appBar: AppBar( - title: Text(context.localizations.search), + title: Text(context.tr("search")), leading: CustomBackButton( onPressed: () { ref.read(searchViewModel).clear(); diff --git a/lib/searchComponent/views/appWideSearch/search_textfield_view.dart b/lib/searchComponent/views/appWideSearch/search_textfield_view.dart index 3575ac9b..8a4d5379 100644 --- a/lib/searchComponent/views/appWideSearch/search_textfield_view.dart +++ b/lib/searchComponent/views/appWideSearch/search_textfield_view.dart @@ -1,5 +1,6 @@ import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/searchComponent/viewModels/global_search_viewmodel.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -29,7 +30,7 @@ class _SearchTextFieldState extends ConsumerState { }); }, decoration: InputDecoration( - hintText: context.localizations.search, + hintText: context.tr("search"), suffixIcon: showIcon ? GestureDetector( onTap: () { diff --git a/lib/searchComponent/views/appWideSearch/search_view.dart b/lib/searchComponent/views/appWideSearch/search_view.dart index a3b49023..03dc43dc 100644 --- a/lib/searchComponent/views/appWideSearch/search_view.dart +++ b/lib/searchComponent/views/appWideSearch/search_view.dart @@ -3,7 +3,7 @@ import 'package:campus_flutter/searchComponent/viewModels/global_search_viewmode import 'package:campus_flutter/searchComponent/views/appWideSearch/search_category_picker_view.dart'; import 'package:campus_flutter/searchComponent/views/appWideSearch/search_result_view_builder.dart'; import 'package:campus_flutter/searchComponent/views/appWideSearch/search_textfield_view.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; @@ -43,7 +43,7 @@ class SearchView extends ConsumerWidget { builder: (context, snapshot) { if (!snapshot.hasData && textEditingController.text.isEmpty) { return Center( - child: Text(context.localizations.enterQueryStart), + child: Text(context.tr("enterQueryStart")), ); } else { final orientation = MediaQuery.orientationOf(context); diff --git a/lib/searchComponent/views/personRoomSearch/search_view.dart b/lib/searchComponent/views/personRoomSearch/search_view.dart index ca9d6dcc..319633c1 100644 --- a/lib/searchComponent/views/personRoomSearch/search_view.dart +++ b/lib/searchComponent/views/personRoomSearch/search_view.dart @@ -9,6 +9,7 @@ import 'package:campus_flutter/navigaTumComponent/viewModels/navigatum_search_vi import 'package:campus_flutter/personSearchComponent/model/person.dart'; import 'package:campus_flutter/personSearchComponent/viewModel/person_search_viewmodel.dart'; import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -38,9 +39,7 @@ class PersonRoomSearchScaffold extends ConsumerWidget { }, ), title: Text( - isRoomSearch - ? context.localizations.roomSearch - : context.localizations.personSearch, + isRoomSearch ? context.tr("roomSearch") : context.tr("personSearch"), ), ), body: PersonRoomSearchView( @@ -126,7 +125,7 @@ class _SearchViewState extends ConsumerState { } }, decoration: InputDecoration( - hintText: context.localizations.search, + hintText: context.tr("search"), suffixIcon: showClearButton ? GestureDetector( onTap: () { @@ -211,15 +210,15 @@ class _SearchViewState extends ConsumerState { child: Center( child: DelayedLoadingIndicator( name: widget.isRoomSearch - ? context.localizations.rooms - : context.localizations.persons, + ? context.tr("rooms") + : context.tr("persons"), ), ), ); } else { return Expanded( child: Center( - child: Text(context.localizations.enterQueryStart), + child: Text(context.tr("enterQueryStart")), ), ); } diff --git a/lib/settingsComponent/viewModels/user_preferences_viewmodel.dart b/lib/settingsComponent/viewModels/user_preferences_viewmodel.dart index b25000e2..c4e98f4e 100644 --- a/lib/settingsComponent/viewModels/user_preferences_viewmodel.dart +++ b/lib/settingsComponent/viewModels/user_preferences_viewmodel.dart @@ -34,8 +34,6 @@ class UserPreferencesViewModel { ref.read(hideFailedGrades.notifier).state = value as bool; case UserPreference.weekends: ref.read(showWeekends.notifier).state = value as bool; - case UserPreference.locale: - ref.read(customLocale.notifier).state = Locale(value as String); default: break; } @@ -56,9 +54,6 @@ class UserPreferencesViewModel { ref.read(hideFailedGrades.notifier).state = value as bool; case UserPreference.weekends: ref.read(showWeekends.notifier).state = value as bool; - case UserPreference.locale: - ref.read(customLocale.notifier).state = value as Locale?; - value = value?.languageCode; default: break; } diff --git a/lib/settingsComponent/views/appearance_settings_view.dart b/lib/settingsComponent/views/appearance_settings_view.dart index 4eaf7041..dfc1f49b 100644 --- a/lib/settingsComponent/views/appearance_settings_view.dart +++ b/lib/settingsComponent/views/appearance_settings_view.dart @@ -2,7 +2,6 @@ import 'dart:io'; import 'package:campus_flutter/base/enums/appearance.dart'; import 'package:campus_flutter/base/enums/user_preference.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/base/views/seperated_list.dart'; import 'package:campus_flutter/calendarComponent/views/calendars_view.dart'; import 'package:campus_flutter/gradeComponent/viewModels/grade_viewmodel.dart'; @@ -10,6 +9,7 @@ import 'package:campus_flutter/homeComponent/widgetComponent/views/widget_frame_ import 'package:campus_flutter/main.dart'; import 'package:campus_flutter/settingsComponent/viewModels/user_preferences_viewmodel.dart'; import 'package:campus_flutter/settingsComponent/views/settings_view.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:syncfusion_flutter_calendar/calendar.dart'; @@ -20,7 +20,7 @@ class AppearanceSettingsView extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { return WidgetFrameView( - title: context.localizations.appearance, + title: context.tr("appearance"), child: Card( child: SeparatedList.widgets( widgets: [ @@ -38,7 +38,7 @@ class AppearanceSettingsView extends ConsumerWidget { return ListTile( dense: true, title: Text( - context.localizations.theme, + context.tr("theme"), style: Theme.of(context).textTheme.bodyMedium, ), trailing: DropdownButton( @@ -60,7 +60,7 @@ class AppearanceSettingsView extends ConsumerWidget { return ListTile( dense: true, title: Text( - context.localizations.useWebView, + context.tr("useWebView"), style: Theme.of(context).textTheme.bodyMedium, ), trailing: Switch( @@ -80,7 +80,7 @@ class AppearanceSettingsView extends ConsumerWidget { return ListTile( dense: true, title: Text( - context.localizations.hideFailedGrades, + context.tr("hideFailedGrades"), style: Theme.of(context).textTheme.bodyMedium, ), trailing: Switch( @@ -100,7 +100,7 @@ class AppearanceSettingsView extends ConsumerWidget { return ListTile( dense: true, title: Text( - context.localizations.showWeekends, + context.tr("showWeekends"), style: Theme.of(context).textTheme.bodyMedium, ), trailing: Switch( diff --git a/lib/settingsComponent/views/contact_view.dart b/lib/settingsComponent/views/contact_view.dart index 23ee4f9c..2b12bed1 100644 --- a/lib/settingsComponent/views/contact_view.dart +++ b/lib/settingsComponent/views/contact_view.dart @@ -1,10 +1,10 @@ import 'dart:io'; -import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/base/util/hyperlink_text.dart'; import 'package:campus_flutter/base/routing/routes.dart'; import 'package:campus_flutter/base/views/seperated_list.dart'; import 'package:campus_flutter/homeComponent/widgetComponent/views/widget_frame_view.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -15,19 +15,19 @@ class ContactView extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { return WidgetFrameView( - title: context.localizations.contactMore, + title: context.tr("contactMore"), child: Card( child: SeparatedList.widgets( widgets: [ HyperLinkListTile( dense: true, link: _betaTester(), - label: context.localizations.becomeABetaTester, + label: context.tr("becomeABetaTester"), ), HyperLinkListTile( dense: true, link: "https://github.com/TUM-Dev", - label: context.localizations.usOnGitHub, + label: context.tr("usOnGitHub"), ), const HyperLinkListTile( dense: true, @@ -37,7 +37,7 @@ class ContactView extends ConsumerWidget { HyperLinkListTile( dense: true, link: "https://www.tum.app/privacy", - label: context.localizations.privacyPolicy, + label: context.tr("privacyPolicy"), ), _licensesButton(context), _feedbackButton(context), @@ -70,7 +70,7 @@ class ContactView extends ConsumerWidget { return ListTile( dense: true, title: Text( - context.localizations.licenses, + context.tr("licenses"), style: Theme.of(context).textTheme.bodyMedium, ), onTap: () => showLicensePage(context: context), diff --git a/lib/settingsComponent/views/general_settings_view.dart b/lib/settingsComponent/views/general_settings_view.dart index 9acfb478..2cd7f2e0 100644 --- a/lib/settingsComponent/views/general_settings_view.dart +++ b/lib/settingsComponent/views/general_settings_view.dart @@ -1,12 +1,9 @@ -import 'package:campus_flutter/base/enums/user_preference.dart'; import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/base/extensions/locale_fullname.dart'; import 'package:campus_flutter/base/routing/routes.dart'; import 'package:campus_flutter/base/views/seperated_list.dart'; import 'package:campus_flutter/homeComponent/widgetComponent/views/widget_frame_view.dart'; -import 'package:campus_flutter/main.dart'; -import 'package:campus_flutter/settingsComponent/viewModels/user_preferences_viewmodel.dart'; -import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -18,7 +15,7 @@ class GeneralSettingsView extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { return WidgetFrameView( - title: context.localizations.generalSettings, + title: context.tr("generalSettings"), child: Card( child: SeparatedList.widgets( widgets: [ @@ -36,7 +33,7 @@ class GeneralSettingsView extends ConsumerWidget { dense: true, leading: Icon(Icons.key, size: 20, color: context.primaryColor), title: Text( - context.localizations.tokenPermissions, + context.tr("tokenPermissions"), style: Theme.of(context).textTheme.bodyMedium, ), trailing: const Icon(Icons.arrow_forward_ios, size: 15), @@ -53,30 +50,19 @@ class GeneralSettingsView extends ConsumerWidget { color: context.primaryColor, ), title: Text( - context.localizations.language, + context.tr("language"), style: Theme.of(context).textTheme.bodyMedium, ), trailing: DropdownButton( onChanged: (Locale? newLocale) { - ref.read(userPreferencesViewModel).savePreference( - UserPreference.locale, - newLocale, - ); + if (newLocale != null) { + context.setLocale(newLocale); + } }, - value: ref.watch(customLocale), - items: () { - final availableLocales = AppLocalizations.supportedLocales - .map((e) => DropdownMenuItem(value: e, child: Text(e.fullName()))) - .toList(); - availableLocales.insert( - 0, - const DropdownMenuItem( - value: null, - child: Text("System"), - ), - ); - return availableLocales; - }(), + value: context.locale, + items: context.supportedLocales + .map((e) => DropdownMenuItem(value: e, child: Text(e.fullName()))) + .toList(), ), ); } @@ -89,7 +75,7 @@ class GeneralSettingsView extends ConsumerWidget { size: 20, color: context.primaryColor, ), - title: Text(context.localizations.deviceSettings), + title: Text(context.tr("deviceSettings")), trailing: const Icon(Icons.arrow_forward_ios, size: 15), onTap: () => openAppSettings(), ); diff --git a/lib/settingsComponent/views/settings_scaffold.dart b/lib/settingsComponent/views/settings_scaffold.dart index 51513844..61340a18 100644 --- a/lib/settingsComponent/views/settings_scaffold.dart +++ b/lib/settingsComponent/views/settings_scaffold.dart @@ -2,6 +2,7 @@ import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/base/util/custom_back_button.dart'; import 'package:campus_flutter/base/routing/routes.dart'; import 'package:campus_flutter/settingsComponent/views/settings_view.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; @@ -14,7 +15,7 @@ class SettingsScaffold extends StatelessWidget { appBar: AppBar( leading: const CustomBackButton(), titleSpacing: 0, - title: Text(context.localizations.settingsAndFeedback), + title: Text(context.tr("settingsAndFeedback")), actions: [ IconButton( onPressed: () => context.push(feedback), diff --git a/lib/settingsComponent/views/settings_view.dart b/lib/settingsComponent/views/settings_view.dart index c5e47f3a..8c91bff8 100644 --- a/lib/settingsComponent/views/settings_view.dart +++ b/lib/settingsComponent/views/settings_view.dart @@ -5,8 +5,8 @@ import 'package:campus_flutter/homeComponent/widgetComponent/views/widget_frame_ import 'package:campus_flutter/onboardingComponent/viewModels/onboarding_viewmodel.dart'; import 'package:campus_flutter/settingsComponent/views/appearance_settings_view.dart'; import 'package:campus_flutter/settingsComponent/views/contact_view.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/settingsComponent/views/general_settings_view.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -80,7 +80,7 @@ class SettingsView extends ConsumerWidget { onTap: () => ref.read(onboardingViewModel).resetPreferences(ref), dense: true, title: Text( - context.localizations.resetPreferences, + context.tr("resetPreferences"), style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: Colors.red, fontWeight: FontWeight.w500, @@ -96,7 +96,7 @@ class SettingsView extends ConsumerWidget { dense: true, title: loginStatus != Credentials.tumId ? Text( - context.localizations.login, + context.tr("login"), style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: Colors.green, fontWeight: FontWeight.w500, @@ -104,7 +104,7 @@ class SettingsView extends ConsumerWidget { textAlign: TextAlign.center, ) : Text( - context.localizations.resetLogin, + context.tr("resetLogin"), style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: Colors.red, fontWeight: FontWeight.w500, @@ -127,13 +127,15 @@ class SettingsView extends ConsumerWidget { builder: (context, snapshot) { if (snapshot.hasData) { return Text( - context.localizations.versionNumber( - snapshot.data!.version, - snapshot.data!.buildNumber, + context.tr( + "versionNumber", + args: [snapshot.data!.version, snapshot.data!.buildNumber], ), ); } else { - return Text(context.localizations.versionNumber("-.-.-", "-")); + return Text( + context.tr("versionNumber", args: ["-.-.-", "-"]), + ); } }, ), diff --git a/lib/studentCardComponent/views/bar_code_view.dart b/lib/studentCardComponent/views/bar_code_view.dart index 360b8e8c..a64bfe28 100644 --- a/lib/studentCardComponent/views/bar_code_view.dart +++ b/lib/studentCardComponent/views/bar_code_view.dart @@ -1,5 +1,6 @@ import 'package:barcode_widget/barcode_widget.dart'; import 'package:campus_flutter/base/extensions/context.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; class BarCodeView extends StatelessWidget { @@ -11,25 +12,29 @@ class BarCodeView extends StatelessWidget { Widget build(BuildContext context) { return Card( child: ExpansionTile( - title: Text(context.localizations.libraryBarcode), + title: Text(context.tr("libraryBarcode")), initiallyExpanded: true, children: [ Padding( - padding: EdgeInsets.symmetric(vertical: context.halfPadding), - child: BarcodeWidget( - height: 60, - width: MediaQuery.of(context).size.width, - padding: const EdgeInsets.symmetric(horizontal: 20.0), - data: libraryID, - barcode: Barcode.code39(), - color: Theme.of(context).colorScheme.onSurface, - drawText: false, + padding: EdgeInsets.symmetric(horizontal: context.padding), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + color: Colors.white, + ), + child: BarcodeWidget( + height: 70, + padding: const EdgeInsets.all(10), + data: libraryID, + barcode: Barcode.code39(), + drawText: false, + ), ), ), Padding( padding: EdgeInsets.symmetric(vertical: context.halfPadding), child: Text( - "${context.localizations.libraryNumber}: $libraryID", + "${context.tr("libraryNumber")}: $libraryID", style: Theme.of(context).textTheme.labelLarge, ), ), diff --git a/lib/studentCardComponent/views/information_view.dart b/lib/studentCardComponent/views/information_view.dart index 07ebff38..5c8568d0 100644 --- a/lib/studentCardComponent/views/information_view.dart +++ b/lib/studentCardComponent/views/information_view.dart @@ -3,8 +3,8 @@ import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/base/util/card_with_padding.dart'; import 'package:campus_flutter/base/util/string_parser.dart'; import 'package:campus_flutter/studentCardComponent/model/student_card.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; -import 'package:intl/intl.dart'; import 'package:lottie/lottie.dart'; class InformationView extends StatelessWidget { @@ -33,12 +33,12 @@ class InformationView extends StatelessWidget { _name(context), const Padding(padding: EdgeInsets.symmetric(vertical: 5.0)), _infoEntryRow( - context.localizations.birthday, + context.tr("birthday"), DateFormat("dd.MM.yyyy", "de") .format(studentCard.birthday), ), _infoEntryRow( - context.localizations.studyId, + context.tr("studyId"), studentCard.studyID, ), _infoEntryRow( @@ -104,7 +104,7 @@ class InformationView extends StatelessWidget { Widget _title(BuildContext context) { return Text( - context.localizations.digitalStudentCard, + context.tr("digitalStudentCard"), style: Theme.of(context) .textTheme .titleLarge @@ -153,7 +153,7 @@ class InformationView extends StatelessWidget { Widget _validUntil(BuildContext context) { return Text( - "${context.localizations.validUntil}: ${DateFormat("dd.MM.yyyy", "de").format(studentCard.validUntil)}", + "${context.tr("validUntil")}: ${DateFormat("dd.MM.yyyy", "de").format(studentCard.validUntil)}", style: Theme.of(context) .textTheme .bodyLarge diff --git a/lib/studentCardComponent/views/snapping_slider.dart b/lib/studentCardComponent/views/snapping_slider.dart index a8415f51..8df180eb 100644 --- a/lib/studentCardComponent/views/snapping_slider.dart +++ b/lib/studentCardComponent/views/snapping_slider.dart @@ -1,6 +1,6 @@ import 'package:barcode_widget/barcode_widget.dart'; -import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/base/util/card_with_padding.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; class SnappingSlider extends StatefulWidget { @@ -77,7 +77,7 @@ class _SnappingSliderState extends State { return Column( children: [ Text( - context.localizations.libraryBarcode, + context.tr("libraryBarcode"), style: Theme.of(context).textTheme.titleMedium, ), const Spacer(), @@ -89,7 +89,7 @@ class _SnappingSliderState extends State { padding: const EdgeInsets.symmetric(horizontal: 10.0), height: 100, ), - Text("${context.localizations.libraryNumber}: ${widget.libraryID}"), + Text("${context.tr("libraryNumber")}: ${widget.libraryID}"), const Spacer(), ], ); diff --git a/lib/studentCardComponent/views/student_card_view.dart b/lib/studentCardComponent/views/student_card_view.dart index 114141e9..dffabe50 100644 --- a/lib/studentCardComponent/views/student_card_view.dart +++ b/lib/studentCardComponent/views/student_card_view.dart @@ -7,6 +7,7 @@ import 'package:campus_flutter/base/util/last_updated_text.dart'; import 'package:campus_flutter/studentCardComponent/viewModel/student_card_viewmodel.dart'; import 'package:campus_flutter/studentCardComponent/views/bar_code_view.dart'; import 'package:campus_flutter/studentCardComponent/views/information_view.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; @@ -35,8 +36,9 @@ class StudentCardView extends ConsumerWidget { } else { return Center( child: Text( - context.localizations.noEntriesFound( - "StudentCard", + context.tr( + "noEntriesFound", + args: ["StudentCard"], ), ), ); @@ -85,7 +87,7 @@ class StudentCardView extends ConsumerWidget { const Padding(padding: EdgeInsets.symmetric(horizontal: 8.0)), Expanded( child: Text( - context.localizations.currentlyInBeta, + context.tr("currentlyInBeta"), style: TextStyle(color: context.primaryColor), textAlign: TextAlign.center, ), diff --git a/pubspec.lock b/pubspec.lock index 7a02cee4..1aecdd07 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -13,10 +13,10 @@ packages: dependency: transitive description: name: _flutterfire_internals - sha256: "99b5dec989287c1aca71bf27339e0022b4dc3679225f442fb75790ef44535bf8" + sha256: "3dee3db3468c5f4640a4e8aa9c1e22561c298976d8c39ed2fdd456a9a3db26e1" url: "https://pub.dev" source: hosted - version: "1.3.30" + version: "1.3.32" analyzer: dependency: transitive description: @@ -37,10 +37,10 @@ packages: dependency: transitive description: name: archive - sha256: "22600aa1e926be775fa5fe7e6894e7fb3df9efda8891c73f70fb3262399a432d" + sha256: ecf4273855368121b1caed0d10d4513c7241dfc813f7d3c8933b36622ae9b265 url: "https://pub.dev" source: hosted - version: "3.4.10" + version: "3.5.1" args: dependency: transitive description: @@ -69,10 +69,10 @@ packages: dependency: transitive description: name: barcode - sha256: "1fe4a55344505850517ce72d4a3a7b9ccf51b0dc1631ee7e552f6eacc4947f96" + sha256: ab180ce22c6555d77d45f0178a523669db67f95856e3378259ef2ffeb43e6003 url: "https://pub.dev" source: hosted - version: "2.2.7" + version: "2.2.8" barcode_widget: dependency: "direct main" description: @@ -173,10 +173,10 @@ packages: dependency: transitive description: name: cached_network_image_web - sha256: "42a835caa27c220d1294311ac409a43361088625a4f23c820b006dd9bffb3316" + sha256: "205d6a9f1862de34b93184f22b9d2d94586b2f05c581d546695e3d8f6a805cd7" url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.2.0" characters: dependency: transitive description: @@ -289,6 +289,22 @@ packages: url: "https://pub.dev" source: hosted version: "5.4.3+1" + easy_localization: + dependency: "direct main" + description: + name: easy_localization + sha256: "432698c31a488dd64c56d4759f20d04844baba5e9e4f2cb1abb9676257918b17" + url: "https://pub.dev" + source: hosted + version: "3.0.6" + easy_logger: + dependency: "direct main" + description: + name: easy_logger + sha256: c764a6e024846f33405a2342caf91c62e357c24b02c04dbc712ef232bf30ffb7 + url: "https://pub.dev" + source: hosted + version: "0.0.2" fake_async: dependency: transitive description: @@ -317,10 +333,10 @@ packages: dependency: "direct main" description: name: firebase_core - sha256: "6b1152a5af3b1cfe7e45309e96fc1aa14873f410f7aadb3878aa7812acfa7531" + sha256: "4aef2a23d0f3265545807d68fbc2f76a6b994ca3c778d88453b99325abd63284" url: "https://pub.dev" source: hosted - version: "2.30.0" + version: "2.30.1" firebase_core_platform_interface: dependency: transitive description: @@ -333,26 +349,50 @@ packages: dependency: transitive description: name: firebase_core_web - sha256: c8b02226e548f35aace298e2bb2e6c24e34e8a203d614e742bb1146e5a4ad3c8 + sha256: "67f2fcc600fc78c2f731c370a3a5e6c87ee862e3a2fba6f951eca6d5dafe5c29" url: "https://pub.dev" source: hosted - version: "2.15.0" + version: "2.16.0" firebase_crashlytics: dependency: "direct main" description: name: firebase_crashlytics - sha256: c39ad1df819130dbb3468e1ad4e6fcd09fa37f8bc1581e8881d515a54a181757 + sha256: "1c499d1d97b93d24aee099259f89a5fbd6ce7d11d0fe98824586087f1291931b" url: "https://pub.dev" source: hosted - version: "3.5.2" + version: "3.5.4" firebase_crashlytics_platform_interface: dependency: transitive description: name: firebase_crashlytics_platform_interface - sha256: "22492a34fa1405b57a6eb37c251434c38f780b88c9e87a9f35fa41189b2b2b61" + sha256: "3160d049c220422f8de34690c39be42af8309a030d9dd370051582272181238e" + url: "https://pub.dev" + source: hosted + version: "3.6.32" + firebase_remote_config: + dependency: "direct main" + description: + name: firebase_remote_config + sha256: c7e20f26e595c7bedf48c6565af70b82658f602163c0718d32211f3e4ba09da3 url: "https://pub.dev" source: hosted - version: "3.6.30" + version: "4.4.4" + firebase_remote_config_platform_interface: + dependency: transitive + description: + name: firebase_remote_config_platform_interface + sha256: "1c712f80946b32399967bf72de1f386c8c07636bb48cd627afdc5a92c844f362" + url: "https://pub.dev" + source: hosted + version: "1.4.32" + firebase_remote_config_web: + dependency: transitive + description: + name: firebase_remote_config_web + sha256: "1ffd862e0f31e272386bfc1b778298fa503dfab9e7d2b57dcbfc96215ffcc775" + url: "https://pub.dev" + source: hosted + version: "1.6.4" fixnum: dependency: transitive description: @@ -370,10 +410,10 @@ packages: dependency: transitive description: name: flutter_cache_manager - sha256: "8207f27539deb83732fdda03e259349046a39a4c767269285f449ade355d54ba" + sha256: "395d6b7831f21f3b989ebedbb785545932adb9afe2622c1ffacf7f4b53a7e544" url: "https://pub.dev" source: hosted - version: "3.3.1" + version: "3.3.2" flutter_colorpicker: dependency: "direct main" description: @@ -400,7 +440,7 @@ packages: source: hosted version: "3.0.2" flutter_localizations: - dependency: "direct main" + dependency: transitive description: flutter source: sdk version: "0.0.0" @@ -522,10 +562,10 @@ packages: dependency: transitive description: name: geolocator_android - sha256: f15d1536cd01b1399578f1da1eb5d566e7a718db6a3648f2c24d2e2f859f0692 + sha256: "80cd39a94100957431a6dd37cebd686f6d446bbc9a884d90c9a07b34fd28b923" url: "https://pub.dev" source: hosted - version: "4.5.4" + version: "4.5.5" geolocator_apple: dependency: transitive description: @@ -578,10 +618,10 @@ packages: dependency: "direct main" description: name: go_router - sha256: "771c8feb40ad0ef639973d7ecf1b43d55ffcedb2207fd43fab030f5639e40446" + sha256: "9e0f7d1a3e7dc5010903e330fbc5497872c4c3cf6626381d69083cc1d5113c1e" url: "https://pub.dev" source: hosted - version: "13.2.4" + version: "14.0.2" google_identity_services_web: dependency: transitive description: @@ -610,10 +650,10 @@ packages: dependency: transitive description: name: google_maps_flutter_android - sha256: "256b3c974e415bd17555ceff76a5d0badd2cbfd29febfc23070993358f639550" + sha256: "0bcadb80eba39afda77dede89a6caafd3b68f2786b90491eceea4a01c3db181c" url: "https://pub.dev" source: hosted - version: "2.7.0" + version: "2.8.0" google_maps_flutter_ios: dependency: transitive description: @@ -634,10 +674,10 @@ packages: dependency: transitive description: name: google_maps_flutter_web - sha256: "861c6dd430123e58bb1154342345c5bfa36064120c8ec3dbc0d0b7522add1861" + sha256: "0c0d5c723d94b295cf86dd1c45ff91d2ac1fff7c05ddca4f01bef9fa0a014690" url: "https://pub.dev" source: hosted - version: "0.5.6+2" + version: "0.5.7" googleapis_auth: dependency: transitive description: @@ -659,10 +699,10 @@ packages: description: path: "." ref: master - resolved-ref: e631635424e41a5ed5bd993cd75ce8967d87772a + resolved-ref: ebcb4b876e34c0daffa9df8ea96a97b07059deb1 url: "https://github.com/jakobkoerber/grpc-dart.git" source: git - version: "3.2.4" + version: "4.0.0" home_widget: dependency: "direct main" description: @@ -739,26 +779,26 @@ packages: dependency: "direct main" description: name: isar - sha256: "45bbdb3a746fa415e3f85da7abd1a781686d088febf6dbbf85f6952ef3676c44" - url: "https://isar-community.dev" + sha256: e7135ff16ae4e4624bce608757b2d22aeeeb09225d9f16ec3e3a5c9f3d05e66a + url: "https://pub.isar-community.dev" source: hosted - version: "3.1.5" + version: "3.1.7" isar_flutter_libs: dependency: "direct main" description: name: isar_flutter_libs - sha256: f3eb69f560d192e99e5c2194f9bb77a7d82db4eef985da27ab3c9bc8fa280989 - url: "https://isar-community.dev" + sha256: cb2cc60aac929ca190c0332d10417cab405f666dc96773ab66eb2958866a5e20 + url: "https://pub.isar-community.dev" source: hosted - version: "3.1.5" + version: "3.1.7" isar_generator: dependency: "direct dev" description: name: isar_generator - sha256: "46b44b1679c58e31f8232124b0c02dfbd6a8dbf6fd5bc91a5ef6dec68355c399" - url: "https://isar-community.dev" + sha256: "9409d8c95abc67953165dea302f75d957cd40965fcbcd0134ab2b2e4c5e35042" + url: "https://pub.isar-community.dev" source: hosted - version: "3.1.5" + version: "3.1.7" js: dependency: transitive description: @@ -779,18 +819,18 @@ packages: dependency: "direct main" description: name: json_annotation - sha256: b10a7b2ff83d83c777edba3c6a0f97045ddadd56c944e1a23a3fdf43a1bf4467 + sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" url: "https://pub.dev" source: hosted - version: "4.8.1" + version: "4.9.0" json_serializable: dependency: "direct main" description: name: json_serializable - sha256: aa1f5a8912615733e0fdc7a02af03308933c93235bdc8d50d0b0c8a8ccb0b969 + sha256: ea1432d167339ea9b5bb153f0571d0039607a873d6e04e0117af043f14a1fd4b url: "https://pub.dev" source: hosted - version: "6.7.1" + version: "6.8.0" leak_tracker: dependency: transitive description: @@ -915,10 +955,10 @@ packages: dependency: "direct main" description: name: package_info_plus - sha256: "2c582551839386fa7ddbc7770658be7c0f87f388a4bff72066478f597c34d17f" + sha256: b93d8b4d624b4ea19b0a5a208b2d6eff06004bc3ce74c06040b120eeadd00ce0 url: "https://pub.dev" source: hosted - version: "7.0.0" + version: "8.0.0" package_info_plus_platform_interface: dependency: transitive description: @@ -1003,10 +1043,10 @@ packages: dependency: transitive description: name: permission_handler_android - sha256: "1acac6bae58144b442f11e66621c062aead9c99841093c38f5bcdcc24c1c3474" + sha256: "8bb852cd759488893805c3161d0b2b5db55db52f773dbb014420b304055ba2c5" url: "https://pub.dev" source: hosted - version: "12.0.5" + version: "12.0.6" permission_handler_apple: dependency: transitive description: @@ -1063,14 +1103,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" - pointycastle: - dependency: transitive - description: - name: pointycastle - sha256: "79fbafed02cfdbe85ef3fd06c7f4bc2cbcba0177e61b765264853d4253b21744" - url: "https://pub.dev" - source: hosted - version: "3.9.0" pool: dependency: transitive description: @@ -1320,10 +1352,10 @@ packages: dependency: transitive description: name: sqflite - sha256: "5ce2e1a15e822c3b4bfb5400455775e421da7098eed8adc8f26298ada7c9308c" + sha256: a43e5a27235518c03ca238e7b4732cf35eabe863a369ceba6cbefa537a66f16d url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.3.3+1" sqflite_common: dependency: transitive description: @@ -1376,34 +1408,34 @@ packages: dependency: "direct main" description: name: syncfusion_flutter_calendar - sha256: "24070f4ca1558d994e8232b250a2ce3edc920845c8b0f3597895afc8338c901e" + sha256: "9f26ec19fb2f4f018a7512d02dee619a485aac6c89e77fe315b1b66076fc5b40" url: "https://pub.dev" source: hosted - version: "25.1.40" + version: "25.1.42" syncfusion_flutter_charts: dependency: "direct main" description: name: syncfusion_flutter_charts - sha256: f3327077c4816573895b15545ea85b12c6a6cab7f8c2cde1a7eec05c36bfb432 + sha256: "75253e2d32ce2e739c8efe0aec52668334d880e2a96f6d0d2b4422f49af7c608" url: "https://pub.dev" source: hosted - version: "25.1.40" + version: "25.1.42+1" syncfusion_flutter_core: dependency: "direct main" description: name: syncfusion_flutter_core - sha256: "8e19260d292ed77e1cbd4ee1baafb3c9486079cad856e7891478131d25076039" + sha256: fc61878342caee6da7979ca0ca9bb178f1eb5ca9b836dada34b83caa39e4bfed url: "https://pub.dev" source: hosted - version: "25.1.40" + version: "25.1.42" syncfusion_flutter_datepicker: dependency: "direct main" description: name: syncfusion_flutter_datepicker - sha256: "04e7cc46b2c0ebfcd76e6082284f7daaf4731df37ddcc876d3073159a6e55d25" + sha256: "90398b38bceedc34575823ea27d6a1927934852ff2de8f1c1326e35d5b186b58" url: "https://pub.dev" source: hosted - version: "25.1.40" + version: "25.1.42" synchronized: dependency: transitive description: @@ -1680,10 +1712,10 @@ packages: dependency: transitive description: name: win32 - sha256: "0a989dc7ca2bb51eac91e8fd00851297cfffd641aa7538b165c62637ca0eaa4a" + sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb" url: "https://pub.dev" source: hosted - version: "5.4.0" + version: "5.5.0" win32_registry: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 3cd39a4f..4c1781f0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,8 @@ name: campus_flutter description: "A new Flutter project." publish_to: 'none' -version: 5.0.3+1 +version: 5.0.4+1 +isar_version: &isar_version 3.1.7 environment: sdk: '>=3.2.3 <4.0.0' @@ -13,11 +14,11 @@ dependencies: # networking dio: ^5.1.2 isar: - version: ^3.1.0+1 - hosted: https://isar-community.dev/ + version: *isar_version + hosted: https://pub.isar-community.dev/ isar_flutter_libs: - version: ^3.1.0+1 - hosted: https://isar-community.dev/ + version: *isar_version + hosted: https://pub.isar-community.dev/ json_annotation: ^4.8.0 json_serializable: ^6.6.1 cached_network_image: ^3.2.3 @@ -28,7 +29,7 @@ dependencies: # state management rxdart: ^0.27.7 - go_router: ^13.2.0 + go_router: ^14.0.1 flutter_riverpod: ^2.3.6 get_it: ^7.6.0 @@ -59,7 +60,7 @@ dependencies: device_info_plus: ^10.0.1 flutter_secure_storage: ^9.0.0 geolocator: ^11.0.0 - package_info_plus: ^7.0.0 + package_info_plus: ^8.0.0 path_provider: ^2.0.15 url_launcher: ^6.1.10 permission_handler: ^11.1.0 @@ -71,11 +72,12 @@ dependencies: # firebase firebase_crashlytics: ^3.4.6 firebase_core: ^2.24.0 + firebase_remote_config: ^4.4.4 # localization - flutter_localizations: - sdk: flutter - intl: any + easy_localization: ^3.0.6 + easy_logger: ^0.0.2 + intl: ^0.18.1 dependency_overrides: xml2json: @@ -91,8 +93,8 @@ dev_dependencies: # code generation build_runner: ^2.3.3 isar_generator: - version: ^3.1.0+1 - hosted: https://isar-community.dev/ + version: *isar_version + hosted: https://pub.isar-community.dev/ # testing flutter_test: @@ -104,10 +106,9 @@ dev_dependencies: lints: ^3.0.0 flutter: - generate: true uses-material-design: true assets: - - assets/ + - assets/translations/ - assets/mapStyles/ - assets/images/logos/tum-logo-blue.png - assets/images/logos/tum-logo-blue-text.png