From e223ab707f95952e23ac1dab2e1d011b683dead8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakob=20K=C3=B6rber?= <56073945+jakobkoerber@users.noreply.github.com> Date: Thu, 14 Nov 2024 15:27:51 +0100 Subject: [PATCH] Add Room Search to Quick Actions (#284) --- android/app/build.gradle | 2 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- android/settings.gradle | 2 +- ios/Podfile.lock | 2 +- lib/base/enums/search_category.dart | 40 +++ lib/base/enums/search_type.dart | 5 + lib/base/enums/shortcut_item.dart | 18 +- lib/base/routing/router.dart | 34 ++- lib/base/routing/routes.dart | 7 +- lib/base/util/custom_back_button.dart | 14 +- lib/base/util/speaker.dart | 7 + .../views/calendars_view.dart | 7 +- lib/homeComponent/screen/home_screen.dart | 7 +- lib/main.dart | 7 +- lib/navigation_service.dart | 7 +- .../model/studyRooms/study_room.dart | 2 +- lib/placesComponent/views/places_screen.dart | 7 +- .../protocols/search_category_viewmodel.dart | 10 + .../protocols/search_viewmodel.dart | 6 - .../viewModels/global_search_viewmodel.dart | 208 ---------------- .../viewModels/search_viewmodel.dart | 151 ++++++++++++ .../cafeteria_search_viewmodel.dart | 12 +- .../calendar_search_viewmodel.dart | 13 +- .../grades_search_viewmodel.dart | 12 +- .../lecture_search_viewmodel.dart | 12 +- .../movie_search_viewmodel.dart | 12 +- .../navigatum_search_viewmodel.dart | 12 +- .../news_search_viewmodel.dart | 12 +- .../person_search_viewmodel.dart | 12 +- .../personal_lecture_seach_viewmodel.dart | 13 +- .../student_club_search_viewmodel.dart | 13 +- .../study_room_search_viewmodel.dart | 12 +- .../search_result_view_builder.dart | 49 ---- .../views/appWideSearch/search_scaffold.dart | 27 --- .../views/personRoomSearch/search_view.dart | 229 ------------------ .../cafeteria_search_result_view.dart | 10 +- .../calendar_search_result_view.dart | 10 +- .../resultViews/grade_search_result_view.dart | 10 +- .../lecture_search_result_view.dart | 10 +- .../resultViews/movie_search_result_view.dart | 10 +- .../navigatum_search_result_view.dart | 12 +- .../resultViews/news_search_result_view.dart | 10 +- .../person_search_result_view.dart | 10 +- .../personal_lecture_search_result_view.dart | 10 +- .../student_club_search_result_view.dart | 10 +- .../study_room_search_result_view.dart | 10 +- .../search_category_picker_view.dart | 20 +- .../search_result_card_view.dart | 35 +-- .../search_result_details_view.dart | 0 .../views/search_result_view_builder.dart | 56 +++++ .../views/search_scaffold.dart | 41 ++++ .../search_textfield_view.dart | 23 +- .../{appWideSearch => }/search_view.dart | 39 +-- .../screen/studies_screen.dart | 7 +- .../view/grade/grades_view.dart | 7 +- .../view/lecture/lecture_view.dart | 7 +- .../view/lecture/lectures_view.dart | 7 +- .../basic_lecture_info_view.dart | 28 ++- .../lecture_meeting_info_view.dart | 5 +- pubspec.lock | 4 +- pubspec.yaml | 2 +- 61 files changed, 651 insertions(+), 727 deletions(-) create mode 100644 lib/base/enums/search_type.dart create mode 100644 lib/base/util/speaker.dart create mode 100644 lib/searchComponent/protocols/search_category_viewmodel.dart delete mode 100644 lib/searchComponent/protocols/search_viewmodel.dart delete mode 100644 lib/searchComponent/viewModels/global_search_viewmodel.dart create mode 100644 lib/searchComponent/viewModels/search_viewmodel.dart rename lib/{navigaTumComponent/viewModels => searchComponent/viewModels/searchableViewModels}/navigatum_search_viewmodel.dart (85%) delete mode 100644 lib/searchComponent/views/appWideSearch/search_result_view_builder.dart delete mode 100644 lib/searchComponent/views/appWideSearch/search_scaffold.dart delete mode 100644 lib/searchComponent/views/personRoomSearch/search_view.dart rename lib/searchComponent/views/{appWideSearch => }/resultViews/cafeteria_search_result_view.dart (73%) rename lib/searchComponent/views/{appWideSearch => }/resultViews/calendar_search_result_view.dart (84%) rename lib/searchComponent/views/{appWideSearch => }/resultViews/grade_search_result_view.dart (66%) rename lib/searchComponent/views/{appWideSearch => }/resultViews/lecture_search_result_view.dart (68%) rename lib/searchComponent/views/{appWideSearch => }/resultViews/movie_search_result_view.dart (82%) rename lib/searchComponent/views/{appWideSearch => }/resultViews/navigatum_search_result_view.dart (65%) rename lib/searchComponent/views/{appWideSearch => }/resultViews/news_search_result_view.dart (85%) rename lib/searchComponent/views/{appWideSearch => }/resultViews/person_search_result_view.dart (73%) rename lib/searchComponent/views/{appWideSearch => }/resultViews/personal_lecture_search_result_view.dart (68%) rename lib/searchComponent/views/{appWideSearch => }/resultViews/student_club_search_result_view.dart (86%) rename lib/searchComponent/views/{appWideSearch => }/resultViews/study_room_search_result_view.dart (67%) rename lib/searchComponent/views/{appWideSearch => }/search_category_picker_view.dart (75%) rename lib/searchComponent/views/{appWideSearch => }/search_result_card_view.dart (81%) rename lib/searchComponent/views/{appWideSearch => }/search_result_details_view.dart (100%) create mode 100644 lib/searchComponent/views/search_result_view_builder.dart create mode 100644 lib/searchComponent/views/search_scaffold.dart rename lib/searchComponent/views/{appWideSearch => }/search_textfield_view.dart (68%) rename lib/searchComponent/views/{appWideSearch => }/search_view.dart (60%) diff --git a/android/app/build.gradle b/android/app/build.gradle index e7b7a46b..819570ec 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -46,7 +46,7 @@ android { applicationId "de.tum.in.tumcampus" minSdkVersion 29 targetSdkVersion flutter.targetSdkVersion - ndkVersion "26.1.10909125" + ndkVersion "27.0.12077973" versionCode flutterVersionCode.toInteger() versionName flutterVersionName multiDexEnabled true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 3c85cfe0..348c409e 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.7-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/android/settings.gradle b/android/settings.gradle index c6c09f05..d7172598 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.6.1' apply false + id "com.android.application" version '8.7.0' apply false id "org.jetbrains.kotlin.android" version "1.9.20" apply false id "org.jetbrains.kotlin.plugin.serialization" version "2.0.21" apply false id "com.google.gms.google-services" version "4.4.2" apply false diff --git a/ios/Podfile.lock b/ios/Podfile.lock index d85df077..cc6133bb 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -251,7 +251,7 @@ SPEC CHECKSUMS: Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 flutter_native_splash: edf599c81f74d093a4daf8e17bd7a018854bc778 flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12 - geolocator_apple: 6cbaf322953988e009e5ecb481f07efece75c450 + geolocator_apple: 9bcea1918ff7f0062d98345d238ae12718acfbc1 Google-Maps-iOS-Utils: 66d6de12be1ce6d3742a54661e7a79cb317a9321 google_maps_flutter_ios: e31555a04d1986ab130f2b9f24b6cdc861acc6d3 GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7 diff --git a/lib/base/enums/search_category.dart b/lib/base/enums/search_category.dart index 5a8d5d12..d55cfe73 100644 --- a/lib/base/enums/search_category.dart +++ b/lib/base/enums/search_category.dart @@ -1,5 +1,18 @@ +import 'package:campus_flutter/searchComponent/protocols/search_category_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/cafeteria_search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/calendar_search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/grades_search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/lecture_search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/movie_search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/navigatum_search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/news_search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/person_search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/personal_lecture_seach_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/student_club_search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/study_room_search_viewmodel.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; enum SearchCategory { cafeterias, @@ -62,4 +75,31 @@ extension SearchCategoryExtension on SearchCategory { SearchCategory.studentClub, ]; } + + Provider get viewModel { + switch (this) { + case SearchCategory.cafeterias: + return cafeteriaSearchViewModel; + case SearchCategory.calendar: + return calendarSearchViewModel; + case SearchCategory.grade: + return gradesSearchViewModel; + case SearchCategory.movie: + return movieSearchViewModel; + case SearchCategory.news: + return newsSearchViewModel; + case SearchCategory.studyRoom: + return studyRoomSearchViewModel; + case SearchCategory.lectures: + return lectureSearchViewModel; + case SearchCategory.personalLectures: + return personalLectureSearchViewModel; + case SearchCategory.persons: + return personSearchViewModel; + case SearchCategory.rooms: + return navigaTumSearchViewModel; + case SearchCategory.studentClub: + return studentClubSearchViewModel; + } + } } diff --git a/lib/base/enums/search_type.dart b/lib/base/enums/search_type.dart new file mode 100644 index 00000000..a2568e2b --- /dev/null +++ b/lib/base/enums/search_type.dart @@ -0,0 +1,5 @@ +enum SearchType { + general, + room, + person; +} diff --git a/lib/base/enums/shortcut_item.dart b/lib/base/enums/shortcut_item.dart index 94025d81..3a296c5b 100644 --- a/lib/base/enums/shortcut_item.dart +++ b/lib/base/enums/shortcut_item.dart @@ -7,7 +7,8 @@ enum ShortcutItemType { cafeterias(en: "Cafeterias", de: "Mensen"), studyRooms(en: "Study Rooms", de: "Lernräume"), calendar(en: "Calendar", de: "Kalendar"), - studies(en: "Studies", de: "Studium"); + studies(en: "Studies", de: "Studium"), + roomSearch(en: "Room Search", de: "Raumsuche"); final String en; final String? de; @@ -24,16 +25,7 @@ extension Routing on ShortcutItemType { return isGerman ? de! : en; } - String? get icon { - switch (this) { - case ShortcutItemType.home: - case ShortcutItemType.cafeterias: - case ShortcutItemType.studyRooms: - case ShortcutItemType.calendar: - case ShortcutItemType.studies: - return null; - } - } + String? get icon => null; ShortcutItem shortcutItem(Locale? locale) { return ShortcutItem( @@ -55,6 +47,8 @@ extension Routing on ShortcutItemType { return routes.calendar; case ShortcutItemType.studies: return routes.studies; + case ShortcutItemType.roomSearch: + return routes.roomSearch; } } } @@ -62,7 +56,7 @@ extension Routing on ShortcutItemType { extension ActiveShortcuts on ShortcutItemType { static List get items => [ ShortcutItemType.cafeterias, - ShortcutItemType.studyRooms, + ShortcutItemType.roomSearch, ShortcutItemType.calendar, ShortcutItemType.studies, ]; diff --git a/lib/base/routing/router.dart b/lib/base/routing/router.dart index 172eac3d..5c0b8b87 100644 --- a/lib/base/routing/router.dart +++ b/lib/base/routing/router.dart @@ -1,4 +1,5 @@ import 'package:campus_flutter/base/enums/campus.dart'; +import 'package:campus_flutter/base/enums/search_type.dart'; import 'package:campus_flutter/base/util/fullscreen_image_view.dart'; import 'package:campus_flutter/base/routing/router_service.dart'; import 'package:campus_flutter/base/routing/routes.dart'; @@ -31,8 +32,8 @@ import 'package:campus_flutter/placesComponent/views/campuses/campus_scaffold.da import 'package:campus_flutter/placesComponent/views/places_screen.dart'; import 'package:campus_flutter/placesComponent/views/studyGroups/study_room_group_scaffold.dart'; import 'package:campus_flutter/placesComponent/views/studyGroups/study_rooms_view.dart'; -import 'package:campus_flutter/searchComponent/views/appWideSearch/search_scaffold.dart'; -import 'package:campus_flutter/searchComponent/views/personRoomSearch/search_view.dart'; +import 'package:campus_flutter/searchComponent/viewModels/search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/views/search_scaffold.dart'; import 'package:campus_flutter/settingsComponent/views/settings_scaffold.dart'; import 'package:campus_flutter/studiesComponent/model/lecture.dart'; import 'package:campus_flutter/studiesComponent/screen/studies_screen.dart'; @@ -220,7 +221,24 @@ final _router = GoRouter( ), GoRoute( path: search, - builder: (context, state) => const SearchScaffold(), + builder: (context, state) => SearchScaffold( + searchVM: searchViewModel(SearchType.general), + searchString: state.extra as String?, + ), + ), + GoRoute( + path: roomSearch, + builder: (context, state) => SearchScaffold( + searchVM: searchViewModel(SearchType.room), + searchString: state.extra as String?, + ), + ), + GoRoute( + path: personSearch, + builder: (context, state) => SearchScaffold( + searchVM: searchViewModel(SearchType.person), + searchString: state.extra as String?, + ), ), GoRoute( path: studyRoom, @@ -244,16 +262,6 @@ final _router = GoRouter( imageData: state.extra as String, ), ), - GoRoute( - path: roomSearch, - builder: (context, state) { - final data = state.extra as (String?, bool?); - return PersonRoomSearchScaffold( - searchString: data.$1, - isRoomSearch: data.$2 ?? true, - ); - }, - ), GoRoute( path: eventCreation, builder: (context, state) => EventCreationScaffold( diff --git a/lib/base/routing/routes.dart b/lib/base/routing/routes.dart index 94964b7d..60700284 100644 --- a/lib/base/routing/routes.dart +++ b/lib/base/routing/routes.dart @@ -37,12 +37,15 @@ const menuSettings = "/menu+settings"; const feedback = "$menuSettings/feedback"; const feedbackSuccess = "$feedback/success"; -/// General +/// Search const search = "/search"; +const roomSearch = "/roomSearch"; +const personSearch = "/personSearch"; + +/// General const navigaTum = "/navigaTum"; const personDetails = "/personDetails"; const cafeteria = "/cafeteria"; const studyRoom = "/studyRoom"; const networkImage = "/networkImage"; const localeImage = "/localeImage"; -const roomSearch = "/roomSearch"; diff --git a/lib/base/util/custom_back_button.dart b/lib/base/util/custom_back_button.dart index 13e7e0f8..8adbc7d7 100644 --- a/lib/base/util/custom_back_button.dart +++ b/lib/base/util/custom_back_button.dart @@ -5,18 +5,30 @@ import 'package:go_router/go_router.dart'; class CustomBackButton extends StatelessWidget { const CustomBackButton({ super.key, + this.beforeOnPressed, this.onPressed, this.color, }); final Function()? onPressed; + final Function()? beforeOnPressed; final Color? color; @override Widget build(BuildContext context) { return BackButton( color: color, - onPressed: onPressed ?? () => defaultOnPressed(context), + onPressed: () { + if (beforeOnPressed != null) { + beforeOnPressed!(); + } + + if (onPressed != null) { + onPressed!(); + } else { + defaultOnPressed(context); + } + }, ); } diff --git a/lib/base/util/speaker.dart b/lib/base/util/speaker.dart new file mode 100644 index 00000000..27329a86 --- /dev/null +++ b/lib/base/util/speaker.dart @@ -0,0 +1,7 @@ +class Speaker { + static String getSpeakerName(String speakerString) { + final speakers = speakerString.split(", "); + final mainSpeaker = speakers.first.split(" [L]"); + return mainSpeaker.first.split(" (").first; + } +} diff --git a/lib/calendarComponent/views/calendars_view.dart b/lib/calendarComponent/views/calendars_view.dart index d517ec3a..02ee0a02 100644 --- a/lib/calendarComponent/views/calendars_view.dart +++ b/lib/calendarComponent/views/calendars_view.dart @@ -27,8 +27,7 @@ class CalendarsView extends ConsumerStatefulWidget { ConsumerState createState() => _CalendarsViewState(); } -class _CalendarsViewState extends ConsumerState - with AutomaticKeepAliveClientMixin { +class _CalendarsViewState extends ConsumerState { late int _selectedCalendarTab; final CalendarController dayController = CalendarController(); @@ -47,7 +46,6 @@ class _CalendarsViewState extends ConsumerState @override Widget build(BuildContext context) { - super.build(context); return StreamBuilder( stream: ref.watch(calendarViewModel).events, builder: (context, snapshot) { @@ -141,9 +139,6 @@ class _CalendarsViewState extends ConsumerState ); } - @override - bool get wantKeepAlive => true; - void _selectedDateListener((DateTime?, CalendarView?) state) { switch (state.$2) { case CalendarView.day: diff --git a/lib/homeComponent/screen/home_screen.dart b/lib/homeComponent/screen/home_screen.dart index ee119686..ba67ffdc 100644 --- a/lib/homeComponent/screen/home_screen.dart +++ b/lib/homeComponent/screen/home_screen.dart @@ -11,13 +11,11 @@ class HomeScreen extends ConsumerStatefulWidget { ConsumerState createState() => _HomeScreenState(); } -class _HomeScreenState extends ConsumerState - with AutomaticKeepAliveClientMixin { +class _HomeScreenState extends ConsumerState { final ScrollController scrollController = ScrollController(); @override Widget build(BuildContext context) { - super.build(context); return OrientationBuilder( builder: (context, orientation) { if (orientation == Orientation.portrait) { @@ -43,7 +41,4 @@ class _HomeScreenState extends ConsumerState ), ); } - - @override - bool get wantKeepAlive => true; } diff --git a/lib/main.dart b/lib/main.dart index 726ed0cd..5444d283 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -130,8 +130,7 @@ class CampusApp extends ConsumerStatefulWidget { ConsumerState createState() => _CampusAppState(); } -class _CampusAppState extends ConsumerState - with AutomaticKeepAliveClientMixin { +class _CampusAppState extends ConsumerState { late QuickActions quickActions; @override @@ -146,7 +145,6 @@ class _CampusAppState extends ConsumerState @override Widget build(BuildContext context) { - super.build(context); return MaterialApp.router( title: "TUM Campus App", debugShowCheckedModeBanner: false, @@ -235,7 +233,4 @@ class _CampusAppState extends ConsumerState } }); } - - @override - bool get wantKeepAlive => true; } diff --git a/lib/navigation_service.dart b/lib/navigation_service.dart index ebd21369..eac3f977 100644 --- a/lib/navigation_service.dart +++ b/lib/navigation_service.dart @@ -1,11 +1,12 @@ import 'dart:io'; import 'package:campus_flutter/base/enums/credentials.dart'; +import 'package:campus_flutter/base/enums/search_type.dart'; import 'package:campus_flutter/base/routing/routes.dart'; import 'package:campus_flutter/homeComponent/view/widget/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/searchComponent/viewModels/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'; @@ -81,7 +82,9 @@ class NavigationService { Widget searchButton(int currentIndex, WidgetRef ref, BuildContext context) { return IconButton( onPressed: () { - ref.read(searchViewModel).setSearchCategories(currentIndex); + ref + .read(searchViewModel(SearchType.general)) + .setSearchCategories(currentIndex); context.push(search); }, icon: const Icon(Icons.search), diff --git a/lib/placesComponent/model/studyRooms/study_room.dart b/lib/placesComponent/model/studyRooms/study_room.dart index 031406d2..976c176e 100644 --- a/lib/placesComponent/model/studyRooms/study_room.dart +++ b/lib/placesComponent/model/studyRooms/study_room.dart @@ -92,7 +92,7 @@ class StudyRoom extends Searchable { } bool get isAvailable { - return status == "frei" || (percent != null && percent! < 100); + return status == "frei" || (percent != null && percent! < 1); } @override diff --git a/lib/placesComponent/views/places_screen.dart b/lib/placesComponent/views/places_screen.dart index 550c0161..738b6f5e 100644 --- a/lib/placesComponent/views/places_screen.dart +++ b/lib/placesComponent/views/places_screen.dart @@ -16,8 +16,7 @@ class PlacesScreen extends ConsumerStatefulWidget { ConsumerState createState() => _PlacesScreenState(); } -class _PlacesScreenState extends ConsumerState - with AutomaticKeepAliveClientMixin { +class _PlacesScreenState extends ConsumerState { @override void initState() { ref.read(placesViewModel).fetch(false); @@ -26,7 +25,6 @@ class _PlacesScreenState extends ConsumerState @override Widget build(BuildContext context) { - super.build(context); return FutureBuilder( future: Future.wait([ ref.watch(studyRoomsViewModel).fetch(false), @@ -50,7 +48,4 @@ class _PlacesScreenState extends ConsumerState }, ); } - - @override - bool get wantKeepAlive => true; } diff --git a/lib/searchComponent/protocols/search_category_viewmodel.dart b/lib/searchComponent/protocols/search_category_viewmodel.dart new file mode 100644 index 00000000..fb22ce4b --- /dev/null +++ b/lib/searchComponent/protocols/search_category_viewmodel.dart @@ -0,0 +1,10 @@ +import 'package:campus_flutter/searchComponent/protocols/searchable.dart'; +import 'package:rxdart/rxdart.dart'; + +abstract class SearchCategoryViewModel { + BehaviorSubject?> searchResults = BehaviorSubject.seeded(null); + + Future search({bool forcedRefresh = false, required String query}); + + void clearSearch(); +} diff --git a/lib/searchComponent/protocols/search_viewmodel.dart b/lib/searchComponent/protocols/search_viewmodel.dart deleted file mode 100644 index 471b8390..00000000 --- a/lib/searchComponent/protocols/search_viewmodel.dart +++ /dev/null @@ -1,6 +0,0 @@ -import 'package:campus_flutter/searchComponent/protocols/searchable.dart'; -import 'package:rxdart/rxdart.dart'; - -abstract class SearchViewModel { - late BehaviorSubject?> searchResults; -} diff --git a/lib/searchComponent/viewModels/global_search_viewmodel.dart b/lib/searchComponent/viewModels/global_search_viewmodel.dart deleted file mode 100644 index 38dc993e..00000000 --- a/lib/searchComponent/viewModels/global_search_viewmodel.dart +++ /dev/null @@ -1,208 +0,0 @@ -import 'package:campus_flutter/base/enums/credentials.dart'; -import 'package:campus_flutter/base/enums/search_category.dart'; -import 'package:campus_flutter/onboardingComponent/viewModels/onboarding_viewmodel.dart'; -import 'package:campus_flutter/navigaTumComponent/viewModels/navigatum_search_viewmodel.dart'; -import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/person_search_viewmodel.dart'; -import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/cafeteria_search_viewmodel.dart'; -import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/calendar_search_viewmodel.dart'; -import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/grades_search_viewmodel.dart'; -import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/lecture_search_viewmodel.dart'; -import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/movie_search_viewmodel.dart'; -import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/news_search_viewmodel.dart'; -import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/personal_lecture_seach_viewmodel.dart'; -import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/student_club_search_viewmodel.dart'; -import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/study_room_search_viewmodel.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:rxdart/rxdart.dart'; - -final searchViewModel = Provider((ref) => GlobalSearchViewModel(ref)); - -class GlobalSearchViewModel { - BehaviorSubject?> result = BehaviorSubject.seeded(null); - BehaviorSubject> selectedCategories = - BehaviorSubject.seeded([]); - - String searchString = ""; - - bool isAuthorized = false; - - final Ref ref; - - GlobalSearchViewModel(this.ref); - - void search(String searchString) async { - if (searchString.isEmpty) { - clear(); - return; - } - this.searchString = searchString; - if (selectedCategories.value.isEmpty) { - if (ref.read(onboardingViewModel).credentials.value == - Credentials.tumId) { - result.add(SearchCategory.values); - } else { - result.add(SearchCategoryExtension.unAuthorizedSearch()); - } - } else { - result.add(selectedCategories.value); - } - } - - void updateCategory(SearchCategory searchCategory) { - final categories = selectedCategories.value; - if (selectedCategories.value.contains(searchCategory)) { - categories.remove(searchCategory); - } else { - categories.add(searchCategory); - } - selectedCategories.add(categories); - } - - void selectSingleCategory(SearchCategory searchCategory) { - selectedCategories.add([searchCategory]); - } - - void clear() { - searchString = ""; - result.add(null); - } - - void triggerSearchAfterUpdate(String? searchString) { - if (searchString != null) { - this.searchString = searchString; - } - search(this.searchString); - if (selectedCategories.value.isEmpty) { - for (var category in SearchCategory.values) { - if (isAuthorized) { - _authorizedSearchTriggerBuilder(searchString, category); - } else { - _unauthorizedSearchTriggerBuilder(searchString, category); - } - } - } else { - for (var selectedCategory in selectedCategories.value) { - if (isAuthorized) { - _authorizedSearchTriggerBuilder(searchString, selectedCategory); - } else { - _unauthorizedSearchTriggerBuilder(searchString, selectedCategory); - } - } - } - } - - void setSearchCategories(int index) { - isAuthorized = - ref.read(onboardingViewModel).credentials.value == Credentials.tumId; - switch (index) { - case 1: - if (isAuthorized) { - selectedCategories.add([ - SearchCategory.grade, - SearchCategory.personalLectures, - SearchCategory.lectures, - ]); - } else { - selectedCategories.add([]); - } - case 2: - if (isAuthorized) { - selectedCategories.add([ - SearchCategory.calendar, - ]); - } else { - selectedCategories.add([]); - } - case 3: - selectedCategories.add([ - SearchCategory.news, - SearchCategory.movie, - SearchCategory.studentClub, - ]); - case 4: - selectedCategories.add([ - SearchCategory.studyRoom, - SearchCategory.cafeterias, - SearchCategory.rooms, - ]); - default: - selectedCategories.add([]); - } - } - - void _authorizedSearchTriggerBuilder( - String? searchString, - SearchCategory searchCategory, - ) { - switch (searchCategory) { - case SearchCategory.grade: - ref.read(gradesSearchViewModel).gradesSearch(query: this.searchString); - case SearchCategory.cafeterias: - ref - .read(cafeteriaSearchViewModel) - .cafeteriaSearch(query: this.searchString); - case SearchCategory.calendar: - ref - .read(calendarSearchViewModel) - .calendarSearch(query: this.searchString); - case SearchCategory.movie: - ref.read(movieSearchViewModel).movieSearch(query: this.searchString); - case SearchCategory.news: - ref.read(newsSearchViewModel).newsSearch(query: this.searchString); - case SearchCategory.studentClub: - ref - .read(studentClubSearchViewModel) - .studentClubSearch(query: this.searchString); - case SearchCategory.studyRoom: - ref - .read(studyRoomSearchViewModel) - .studyRoomSearch(query: this.searchString); - case SearchCategory.lectures: - ref - .read(lectureSearchViewModel) - .lectureSearch(query: this.searchString); - case SearchCategory.personalLectures: - ref - .read(personalLectureSearchViewModel) - .personalLectureSearch(query: this.searchString); - case SearchCategory.persons: - ref.read(personSearchViewModel).personSearch(query: this.searchString); - case SearchCategory.rooms: - ref - .read(navigaTumSearchViewModel) - .navigaTumSearch(query: this.searchString); - default: - return; - } - } - - void _unauthorizedSearchTriggerBuilder( - String? searchString, - SearchCategory searchCategory, - ) { - switch (searchCategory) { - case SearchCategory.cafeterias: - ref - .read(cafeteriaSearchViewModel) - .cafeteriaSearch(query: this.searchString); - case SearchCategory.movie: - ref.read(movieSearchViewModel).movieSearch(query: this.searchString); - case SearchCategory.news: - ref.read(newsSearchViewModel).newsSearch(query: this.searchString); - case SearchCategory.studentClub: - ref - .read(studentClubSearchViewModel) - .studentClubSearch(query: this.searchString); - case SearchCategory.studyRoom: - ref - .read(studyRoomSearchViewModel) - .studyRoomSearch(query: this.searchString); - case SearchCategory.rooms: - ref - .read(navigaTumSearchViewModel) - .navigaTumSearch(query: this.searchString); - default: - return; - } - } -} diff --git a/lib/searchComponent/viewModels/search_viewmodel.dart b/lib/searchComponent/viewModels/search_viewmodel.dart new file mode 100644 index 00000000..89bd66ea --- /dev/null +++ b/lib/searchComponent/viewModels/search_viewmodel.dart @@ -0,0 +1,151 @@ +import 'package:campus_flutter/base/enums/credentials.dart'; +import 'package:campus_flutter/base/enums/search_category.dart'; +import 'package:campus_flutter/base/enums/search_type.dart'; +import 'package:campus_flutter/onboardingComponent/viewModels/onboarding_viewmodel.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:rxdart/rxdart.dart'; + +final searchViewModel = Provider.family( + (ref, data) => SearchViewModel(ref, searchType: data), +); + +class SearchViewModel { + BehaviorSubject?> results = BehaviorSubject.seeded(null); + BehaviorSubject> selectedCategories = + BehaviorSubject.seeded([]); + + late final TextEditingController searchTextController; + final SearchType searchType; + final Ref ref; + + bool isAuthorized = false; + + SearchViewModel( + this.ref, { + required this.searchType, + }) { + searchTextController = TextEditingController(); + selectedCategories.add(_initialSearchCategories()); + _checkAuthorizationStatus(); + } + + void _checkAuthorizationStatus() { + isAuthorized = + ref.read(onboardingViewModel).credentials.value == Credentials.tumId; + } + + List _initialSearchCategories() { + switch (searchType) { + case SearchType.general: + return []; + case SearchType.room: + return [SearchCategory.rooms, SearchCategory.studyRoom]; + case SearchType.person: + return [SearchCategory.persons]; + } + } + + void _validateSearch() async { + if (searchTextController.text.isEmpty) { + clear(); + return; + } + if (selectedCategories.value.isEmpty) { + if (ref.read(onboardingViewModel).credentials.value == + Credentials.tumId) { + results.add(SearchCategory.values); + } else { + results.add(SearchCategoryExtension.unAuthorizedSearch()); + } + } else { + results.add(selectedCategories.value); + } + } + + void updateCategory(SearchCategory searchCategory) { + final categories = selectedCategories.value; + if (selectedCategories.value.contains(searchCategory)) { + categories.remove(searchCategory); + } else { + categories.add(searchCategory); + } + selectedCategories.add(categories); + search(); + } + + void selectSingleCategory(SearchCategory searchCategory) { + selectedCategories.add([searchCategory]); + search(); + } + + void clear() { + _clearCategoryViewModels(); + searchTextController.clear(); + results.add(null); + } + + void _clearCategoryViewModels() { + for (var result in results.value ?? []) { + ref.read(result.viewModel).clearSearch(); + } + } + + void search({String? searchString}) { + if (searchString != null) { + searchTextController.text = searchString; + } + _validateSearch(); + if (selectedCategories.value.isEmpty) { + for (var category in SearchCategory.values) { + _searchBuilder(category); + } + } else { + for (var selectedCategory in selectedCategories.value) { + _searchBuilder(selectedCategory); + } + } + } + + void setSearchCategories(int index) { + switch (index) { + case 1: + if (isAuthorized) { + selectedCategories.add([ + SearchCategory.grade, + SearchCategory.personalLectures, + SearchCategory.lectures, + ]); + } else { + selectedCategories.add([]); + } + case 2: + if (isAuthorized) { + selectedCategories.add([ + SearchCategory.calendar, + ]); + } else { + selectedCategories.add([]); + } + case 3: + selectedCategories.add([ + SearchCategory.news, + SearchCategory.movie, + SearchCategory.studentClub, + ]); + case 4: + selectedCategories.add([ + SearchCategory.studyRoom, + SearchCategory.cafeterias, + SearchCategory.rooms, + ]); + default: + break; + } + } + + void _searchBuilder(SearchCategory searchCategory) { + final searchString = searchTextController.text; + ref.read(searchCategory.viewModel).search(query: searchString); + } +} diff --git a/lib/searchComponent/viewModels/searchableViewModels/cafeteria_search_viewmodel.dart b/lib/searchComponent/viewModels/searchableViewModels/cafeteria_search_viewmodel.dart index 366f4608..76883d85 100644 --- a/lib/searchComponent/viewModels/searchableViewModels/cafeteria_search_viewmodel.dart +++ b/lib/searchComponent/viewModels/searchableViewModels/cafeteria_search_viewmodel.dart @@ -2,20 +2,21 @@ import 'package:campus_flutter/placesComponent/model/cafeterias/cafeteria.dart'; import 'package:campus_flutter/placesComponent/services/cafeterias_service.dart'; import 'package:campus_flutter/searchComponent/model/search_exception.dart'; import 'package:campus_flutter/searchComponent/protocols/global_search.dart'; -import 'package:campus_flutter/searchComponent/protocols/search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/protocols/search_category_viewmodel.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:rxdart/rxdart.dart'; final cafeteriaSearchViewModel = Provider((ref) => CafeteriaSearchViewModel()); -class CafeteriaSearchViewModel implements SearchViewModel { +class CafeteriaSearchViewModel implements SearchCategoryViewModel { @override BehaviorSubject?> searchResults = BehaviorSubject.seeded(null); List cafeteriaData = []; - Future cafeteriaSearch({ + @override + Future search({ bool forcedRefresh = false, required String query, }) async { @@ -40,4 +41,9 @@ class CafeteriaSearchViewModel implements SearchViewModel { searchResults.add(results); } } + + @override + void clearSearch() { + searchResults.add(null); + } } diff --git a/lib/searchComponent/viewModels/searchableViewModels/calendar_search_viewmodel.dart b/lib/searchComponent/viewModels/searchableViewModels/calendar_search_viewmodel.dart index 03c13b04..ae2cd61a 100644 --- a/lib/searchComponent/viewModels/searchableViewModels/calendar_search_viewmodel.dart +++ b/lib/searchComponent/viewModels/searchableViewModels/calendar_search_viewmodel.dart @@ -2,20 +2,22 @@ import 'package:campus_flutter/calendarComponent/model/calendar_event.dart'; import 'package:campus_flutter/calendarComponent/services/calendar_service.dart'; import 'package:campus_flutter/searchComponent/model/search_exception.dart'; import 'package:campus_flutter/searchComponent/protocols/global_search.dart'; -import 'package:campus_flutter/searchComponent/protocols/search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/protocols/search_category_viewmodel.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:rxdart/rxdart.dart'; final calendarSearchViewModel = Provider((ref) => CalendarSearchViewModel()); -class CalendarSearchViewModel implements SearchViewModel { +class CalendarSearchViewModel + implements SearchCategoryViewModel { @override BehaviorSubject?> searchResults = BehaviorSubject.seeded(null); List calendarData = []; - Future calendarSearch({ + @override + Future search({ bool forcedRefresh = false, required String query, }) async { @@ -59,4 +61,9 @@ class CalendarSearchViewModel implements SearchViewModel { searchResults.add(results); } } + + @override + void clearSearch() { + searchResults.add(null); + } } diff --git a/lib/searchComponent/viewModels/searchableViewModels/grades_search_viewmodel.dart b/lib/searchComponent/viewModels/searchableViewModels/grades_search_viewmodel.dart index 05679f81..9b74bea9 100644 --- a/lib/searchComponent/viewModels/searchableViewModels/grades_search_viewmodel.dart +++ b/lib/searchComponent/viewModels/searchableViewModels/grades_search_viewmodel.dart @@ -2,19 +2,20 @@ import 'package:campus_flutter/studiesComponent/model/grade.dart'; import 'package:campus_flutter/studiesComponent/service/grade_service.dart'; import 'package:campus_flutter/searchComponent/model/search_exception.dart'; import 'package:campus_flutter/searchComponent/protocols/global_search.dart'; -import 'package:campus_flutter/searchComponent/protocols/search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/protocols/search_category_viewmodel.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:rxdart/rxdart.dart'; final gradesSearchViewModel = Provider((ref) => GradesSearchViewModel()); -class GradesSearchViewModel implements SearchViewModel { +class GradesSearchViewModel implements SearchCategoryViewModel { @override BehaviorSubject?> searchResults = BehaviorSubject.seeded(null); List gradesData = []; - Future gradesSearch({ + @override + Future search({ bool forcedRefresh = false, required String query, }) async { @@ -39,4 +40,9 @@ class GradesSearchViewModel implements SearchViewModel { searchResults.add(results); } } + + @override + void clearSearch() { + searchResults.add(null); + } } diff --git a/lib/searchComponent/viewModels/searchableViewModels/lecture_search_viewmodel.dart b/lib/searchComponent/viewModels/searchableViewModels/lecture_search_viewmodel.dart index 213aba2f..d2ee74af 100644 --- a/lib/searchComponent/viewModels/searchableViewModels/lecture_search_viewmodel.dart +++ b/lib/searchComponent/viewModels/searchableViewModels/lecture_search_viewmodel.dart @@ -2,17 +2,18 @@ import 'package:campus_flutter/studiesComponent/model/lecture.dart'; import 'package:campus_flutter/studiesComponent/service/lecture_search_service.dart'; import 'package:campus_flutter/searchComponent/model/search_exception.dart'; import 'package:campus_flutter/searchComponent/protocols/global_search.dart'; -import 'package:campus_flutter/searchComponent/protocols/search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/protocols/search_category_viewmodel.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:rxdart/rxdart.dart'; final lectureSearchViewModel = Provider((ref) => LectureSearchViewModel()); -class LectureSearchViewModel implements SearchViewModel { +class LectureSearchViewModel implements SearchCategoryViewModel { @override BehaviorSubject?> searchResults = BehaviorSubject.seeded(null); - Future lectureSearch({ + @override + Future search({ bool forcedRefresh = false, required String query, }) async { @@ -28,4 +29,9 @@ class LectureSearchViewModel implements SearchViewModel { onError: (error) => searchResults.addError(error), ); } + + @override + void clearSearch() { + searchResults.add(null); + } } diff --git a/lib/searchComponent/viewModels/searchableViewModels/movie_search_viewmodel.dart b/lib/searchComponent/viewModels/searchableViewModels/movie_search_viewmodel.dart index 844016bf..8e308787 100644 --- a/lib/searchComponent/viewModels/searchableViewModels/movie_search_viewmodel.dart +++ b/lib/searchComponent/viewModels/searchableViewModels/movie_search_viewmodel.dart @@ -3,21 +3,22 @@ import 'package:campus_flutter/campusComponent/service/movie_service.dart'; import 'package:campus_flutter/searchComponent/model/comparison_token.dart'; import 'package:campus_flutter/searchComponent/model/search_exception.dart'; import 'package:campus_flutter/searchComponent/protocols/global_search.dart'; -import 'package:campus_flutter/searchComponent/protocols/search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/protocols/search_category_viewmodel.dart'; import 'package:campus_flutter/searchComponent/protocols/searchable.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:rxdart/rxdart.dart'; final movieSearchViewModel = Provider((ref) => MovieSearchViewModel()); -class MovieSearchViewModel implements SearchViewModel { +class MovieSearchViewModel implements SearchCategoryViewModel { @override BehaviorSubject?> searchResults = BehaviorSubject.seeded(null); List movieData = []; - Future movieSearch({ + @override + Future search({ bool forcedRefresh = false, required String query, }) async { @@ -47,6 +48,11 @@ class MovieSearchViewModel implements SearchViewModel { searchResults.add(results); } } + + @override + void clearSearch() { + searchResults.add(null); + } } class MovieSearch extends Searchable { diff --git a/lib/navigaTumComponent/viewModels/navigatum_search_viewmodel.dart b/lib/searchComponent/viewModels/searchableViewModels/navigatum_search_viewmodel.dart similarity index 85% rename from lib/navigaTumComponent/viewModels/navigatum_search_viewmodel.dart rename to lib/searchComponent/viewModels/searchableViewModels/navigatum_search_viewmodel.dart index a46c6491..b3349f07 100644 --- a/lib/navigaTumComponent/viewModels/navigatum_search_viewmodel.dart +++ b/lib/searchComponent/viewModels/searchableViewModels/navigatum_search_viewmodel.dart @@ -1,6 +1,6 @@ import 'package:campus_flutter/navigaTumComponent/model/navigatum_navigation_entity.dart'; import 'package:campus_flutter/navigaTumComponent/services/navigatum_search_service.dart'; -import 'package:campus_flutter/searchComponent/protocols/search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/protocols/search_category_viewmodel.dart'; import 'package:collection/collection.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:rxdart/rxdart.dart'; @@ -8,12 +8,13 @@ import 'package:rxdart/rxdart.dart'; final navigaTumSearchViewModel = Provider((ref) => NavigaTumSearchViewModel()); class NavigaTumSearchViewModel - implements SearchViewModel { + implements SearchCategoryViewModel { @override BehaviorSubject?> searchResults = BehaviorSubject.seeded(null); - Future navigaTumSearch({ + @override + Future search({ bool forcedRefresh = false, required String query, }) async { @@ -33,4 +34,9 @@ class NavigaTumSearchViewModel ); } } + + @override + void clearSearch() { + searchResults.add(null); + } } diff --git a/lib/searchComponent/viewModels/searchableViewModels/news_search_viewmodel.dart b/lib/searchComponent/viewModels/searchableViewModels/news_search_viewmodel.dart index bc2e16a9..87b10349 100644 --- a/lib/searchComponent/viewModels/searchableViewModels/news_search_viewmodel.dart +++ b/lib/searchComponent/viewModels/searchableViewModels/news_search_viewmodel.dart @@ -3,21 +3,22 @@ import 'package:campus_flutter/campusComponent/service/news_service.dart'; import 'package:campus_flutter/searchComponent/model/comparison_token.dart'; import 'package:campus_flutter/searchComponent/model/search_exception.dart'; import 'package:campus_flutter/searchComponent/protocols/global_search.dart'; -import 'package:campus_flutter/searchComponent/protocols/search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/protocols/search_category_viewmodel.dart'; import 'package:campus_flutter/searchComponent/protocols/searchable.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:rxdart/rxdart.dart'; final newsSearchViewModel = Provider((ref) => NewsSearchViewModel()); -class NewsSearchViewModel implements SearchViewModel { +class NewsSearchViewModel implements SearchCategoryViewModel { @override BehaviorSubject?> searchResults = BehaviorSubject.seeded(null); List newsData = []; - Future newsSearch({bool forcedRefresh = false, required String query}) async { + @override + Future search({bool forcedRefresh = false, required String query}) async { if (newsData.isEmpty) { return NewsService.fetchNews(forcedRefresh).then( (value) { @@ -48,6 +49,11 @@ class NewsSearchViewModel implements SearchViewModel { searchResults.add(results); } } + + @override + void clearSearch() { + searchResults.add(null); + } } class NewsSearch extends Searchable { diff --git a/lib/searchComponent/viewModels/searchableViewModels/person_search_viewmodel.dart b/lib/searchComponent/viewModels/searchableViewModels/person_search_viewmodel.dart index 9ce5703f..811a35e9 100644 --- a/lib/searchComponent/viewModels/searchableViewModels/person_search_viewmodel.dart +++ b/lib/searchComponent/viewModels/searchableViewModels/person_search_viewmodel.dart @@ -1,16 +1,17 @@ import 'package:campus_flutter/personComponent/model/personSearch/person.dart'; import 'package:campus_flutter/personComponent/services/person_search_service.dart'; -import 'package:campus_flutter/searchComponent/protocols/search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/protocols/search_category_viewmodel.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:rxdart/rxdart.dart'; final personSearchViewModel = Provider((ref) => PersonSearchViewModel()); -class PersonSearchViewModel implements SearchViewModel { +class PersonSearchViewModel implements SearchCategoryViewModel { @override BehaviorSubject?> searchResults = BehaviorSubject.seeded(null); - Future personSearch({ + @override + Future search({ bool forcedRefresh = false, required String query, }) async { @@ -21,4 +22,9 @@ class PersonSearchViewModel implements SearchViewModel { onError: (error) => searchResults.addError(error), ); } + + @override + void clearSearch() { + searchResults.add(null); + } } diff --git a/lib/searchComponent/viewModels/searchableViewModels/personal_lecture_seach_viewmodel.dart b/lib/searchComponent/viewModels/searchableViewModels/personal_lecture_seach_viewmodel.dart index c3fcd3bd..5209d47d 100644 --- a/lib/searchComponent/viewModels/searchableViewModels/personal_lecture_seach_viewmodel.dart +++ b/lib/searchComponent/viewModels/searchableViewModels/personal_lecture_seach_viewmodel.dart @@ -2,20 +2,22 @@ import 'package:campus_flutter/studiesComponent/model/lecture.dart'; import 'package:campus_flutter/studiesComponent/service/lecture_service.dart'; import 'package:campus_flutter/searchComponent/model/search_exception.dart'; import 'package:campus_flutter/searchComponent/protocols/global_search.dart'; -import 'package:campus_flutter/searchComponent/protocols/search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/protocols/search_category_viewmodel.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:rxdart/rxdart.dart'; final personalLectureSearchViewModel = Provider((ref) => PersonalLectureSearchViewModel()); -class PersonalLectureSearchViewModel implements SearchViewModel { +class PersonalLectureSearchViewModel + implements SearchCategoryViewModel { @override BehaviorSubject?> searchResults = BehaviorSubject.seeded(null); List _personalLectureData = []; - Future personalLectureSearch({ + @override + Future search({ bool forcedRefresh = false, required String query, }) async { @@ -40,4 +42,9 @@ class PersonalLectureSearchViewModel implements SearchViewModel { searchResults.add(results); } } + + @override + void clearSearch() { + searchResults.add(null); + } } diff --git a/lib/searchComponent/viewModels/searchableViewModels/student_club_search_viewmodel.dart b/lib/searchComponent/viewModels/searchableViewModels/student_club_search_viewmodel.dart index 97ab6377..9ad7df5e 100644 --- a/lib/searchComponent/viewModels/searchableViewModels/student_club_search_viewmodel.dart +++ b/lib/searchComponent/viewModels/searchableViewModels/student_club_search_viewmodel.dart @@ -3,7 +3,7 @@ import 'package:campus_flutter/campusComponent/service/student_club_service.dart import 'package:campus_flutter/searchComponent/model/comparison_token.dart'; import 'package:campus_flutter/searchComponent/model/search_exception.dart'; import 'package:campus_flutter/searchComponent/protocols/global_search.dart'; -import 'package:campus_flutter/searchComponent/protocols/search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/protocols/search_category_viewmodel.dart'; import 'package:campus_flutter/searchComponent/protocols/searchable.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:rxdart/rxdart.dart'; @@ -11,14 +11,16 @@ import 'package:rxdart/rxdart.dart'; final studentClubSearchViewModel = Provider((ref) => StudentClubSearchViewModel()); -class StudentClubSearchViewModel implements SearchViewModel { +class StudentClubSearchViewModel + implements SearchCategoryViewModel { @override BehaviorSubject?> searchResults = BehaviorSubject.seeded(null); List studentClubData = []; - Future studentClubSearch({ + @override + Future search({ bool forcedRefresh = false, required String query, }) async { @@ -46,6 +48,11 @@ class StudentClubSearchViewModel implements SearchViewModel { searchResults.add(results); } } + + @override + void clearSearch() { + searchResults.add(null); + } } class StudentClubSearch extends Searchable { diff --git a/lib/searchComponent/viewModels/searchableViewModels/study_room_search_viewmodel.dart b/lib/searchComponent/viewModels/searchableViewModels/study_room_search_viewmodel.dart index 4cdd414c..630b44e7 100644 --- a/lib/searchComponent/viewModels/searchableViewModels/study_room_search_viewmodel.dart +++ b/lib/searchComponent/viewModels/searchableViewModels/study_room_search_viewmodel.dart @@ -5,7 +5,7 @@ import 'package:campus_flutter/placesComponent/services/study_rooms_service.dart import 'package:campus_flutter/searchComponent/model/comparison_token.dart'; import 'package:campus_flutter/searchComponent/model/search_exception.dart'; import 'package:campus_flutter/searchComponent/protocols/global_search.dart'; -import 'package:campus_flutter/searchComponent/protocols/search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/protocols/search_category_viewmodel.dart'; import 'package:campus_flutter/searchComponent/protocols/searchable.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:json_annotation/json_annotation.dart'; @@ -14,14 +14,15 @@ import 'package:rxdart/rxdart.dart'; final studyRoomSearchViewModel = Provider((ref) => StudyRoomSearchViewModel()); class StudyRoomSearchViewModel - implements SearchViewModel { + implements SearchCategoryViewModel { @override BehaviorSubject?> searchResults = BehaviorSubject.seeded(null); StudyRoomData? studyRoomData; - Future studyRoomSearch({ + @override + Future search({ bool forcedRefresh = false, required String query, }) async { @@ -61,6 +62,11 @@ class StudyRoomSearchViewModel searchResults.add(results); } } + + @override + void clearSearch() { + searchResults.add(null); + } } class StudyRoomSearchResult extends Searchable { diff --git a/lib/searchComponent/views/appWideSearch/search_result_view_builder.dart b/lib/searchComponent/views/appWideSearch/search_result_view_builder.dart deleted file mode 100644 index b7f32f17..00000000 --- a/lib/searchComponent/views/appWideSearch/search_result_view_builder.dart +++ /dev/null @@ -1,49 +0,0 @@ -import 'package:campus_flutter/base/enums/search_category.dart'; -import 'package:campus_flutter/searchComponent/views/appWideSearch/resultViews/cafeteria_search_result_view.dart'; -import 'package:campus_flutter/searchComponent/views/appWideSearch/resultViews/calendar_search_result_view.dart'; -import 'package:campus_flutter/searchComponent/views/appWideSearch/resultViews/grade_search_result_view.dart'; -import 'package:campus_flutter/searchComponent/views/appWideSearch/resultViews/lecture_search_result_view.dart'; -import 'package:campus_flutter/searchComponent/views/appWideSearch/resultViews/movie_search_result_view.dart'; -import 'package:campus_flutter/searchComponent/views/appWideSearch/resultViews/navigatum_search_result_view.dart'; -import 'package:campus_flutter/searchComponent/views/appWideSearch/resultViews/news_search_result_view.dart'; -import 'package:campus_flutter/searchComponent/views/appWideSearch/resultViews/person_search_result_view.dart'; -import 'package:campus_flutter/searchComponent/views/appWideSearch/resultViews/personal_lecture_search_result_view.dart'; -import 'package:campus_flutter/searchComponent/views/appWideSearch/resultViews/student_club_search_result_view.dart'; -import 'package:campus_flutter/searchComponent/views/appWideSearch/resultViews/study_room_search_result_view.dart'; -import 'package:flutter/material.dart'; - -class SearchResultViewBuilder extends StatelessWidget { - const SearchResultViewBuilder(this.searchCategory, {super.key}); - - final SearchCategory searchCategory; - - @override - Widget build(BuildContext context) { - switch (searchCategory) { - case SearchCategory.grade: - return const GradeSearchResultView(); - case SearchCategory.cafeterias: - return const CafeteriasSearchResultView(); - case SearchCategory.calendar: - return const CalendarSearchResultView(); - case SearchCategory.movie: - return const MovieSearchResultView(); - case SearchCategory.news: - return const NewsSearchResultView(); - case SearchCategory.studentClub: - return const StudentClubSearchResultView(); - case SearchCategory.studyRoom: - return const StudyRoomSearchResultView(); - case SearchCategory.lectures: - return const LectureSearchResultView(); - case SearchCategory.personalLectures: - return const PersonalLectureSearchResultView(); - case SearchCategory.persons: - return const PersonSearchResultView(); - case SearchCategory.rooms: - return const NavigaTumSearchResultView(); - default: - return Container(); - } - } -} diff --git a/lib/searchComponent/views/appWideSearch/search_scaffold.dart b/lib/searchComponent/views/appWideSearch/search_scaffold.dart deleted file mode 100644 index 9f89365d..00000000 --- a/lib/searchComponent/views/appWideSearch/search_scaffold.dart +++ /dev/null @@ -1,27 +0,0 @@ -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:easy_localization/easy_localization.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:go_router/go_router.dart'; - -class SearchScaffold extends ConsumerWidget { - const SearchScaffold({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - return Scaffold( - appBar: AppBar( - title: Text(context.tr("search")), - leading: CustomBackButton( - onPressed: () { - ref.read(searchViewModel).clear(); - context.pop(); - }, - ), - ), - body: SearchView(showContent: true), - ); - } -} diff --git a/lib/searchComponent/views/personRoomSearch/search_view.dart b/lib/searchComponent/views/personRoomSearch/search_view.dart deleted file mode 100644 index 37d1c35d..00000000 --- a/lib/searchComponent/views/personRoomSearch/search_view.dart +++ /dev/null @@ -1,229 +0,0 @@ -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/util/custom_back_button.dart'; -import 'package:campus_flutter/base/util/delayed_loading_indicator.dart'; -import 'package:campus_flutter/base/routing/routes.dart'; -import 'package:campus_flutter/base/util/seperated_list.dart'; -import 'package:campus_flutter/navigaTumComponent/model/navigatum_navigation_entity.dart'; -import 'package:campus_flutter/navigaTumComponent/viewModels/navigatum_search_viewmodel.dart'; -import 'package:campus_flutter/personComponent/model/personSearch/person.dart'; -import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/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'; - -class PersonRoomSearchScaffold extends ConsumerWidget { - const PersonRoomSearchScaffold({ - super.key, - this.searchString, - this.isRoomSearch = true, - }); - - final bool isRoomSearch; - final String? searchString; - - @override - Widget build(BuildContext context, WidgetRef ref) { - return Scaffold( - appBar: AppBar( - leading: CustomBackButton( - onPressed: () { - context.canPop() ? context.pop() : context.go(search); - if (isRoomSearch) { - ref.read(navigaTumSearchViewModel).searchResults.add([]); - } else { - ref.read(personSearchViewModel).searchResults.add([]); - } - }, - ), - title: Text( - isRoomSearch ? context.tr("roomSearch") : context.tr("personSearch"), - ), - ), - body: PersonRoomSearchView( - searchString: searchString, - isRoomSearch: isRoomSearch, - ), - ); - } -} - -class PersonRoomSearchView extends ConsumerStatefulWidget { - const PersonRoomSearchView({ - super.key, - this.searchString, - required this.isRoomSearch, - }); - - final bool isRoomSearch; - final String? searchString; - - @override - ConsumerState createState() => _SearchViewState(); -} - -class _SearchViewState extends ConsumerState { - final TextEditingController textEditingController = TextEditingController(); - - bool showClearButton = false; - - @override - void initState() { - if (widget.searchString != null) { - if (widget.isRoomSearch) { - ref - .read(navigaTumSearchViewModel) - .navigaTumSearch(query: widget.searchString!); - } else { - ref - .read(personSearchViewModel) - .personSearch(query: widget.searchString!); - } - setState(() { - textEditingController.text = widget.searchString!; - }); - } - super.initState(); - } - - @override - Widget build(BuildContext context) { - return Column( - children: [ - _textField(), - Padding(padding: EdgeInsets.symmetric(vertical: context.halfPadding)), - _searchBody(), - ], - ); - } - - Widget _textField() { - return Padding( - padding: EdgeInsets.symmetric(horizontal: context.padding), - child: TextField( - controller: textEditingController, - onChanged: (searchString) { - setState(() { - showClearButton = searchString.isNotEmpty; - }); - if (widget.isRoomSearch) { - if (searchString.isNotEmpty) { - ref - .read(navigaTumSearchViewModel) - .navigaTumSearch(query: searchString); - } else { - ref.read(navigaTumSearchViewModel).searchResults.add(null); - } - } else { - if (searchString.isNotEmpty) { - ref.read(personSearchViewModel).personSearch(query: searchString); - } else { - ref.read(navigaTumSearchViewModel).searchResults.add(null); - } - } - }, - decoration: InputDecoration( - hintText: context.tr("search"), - suffixIcon: showClearButton - ? GestureDetector( - onTap: () { - setState(() { - textEditingController.text = ""; - showClearButton = false; - }); - if (widget.isRoomSearch) { - ref - .read(navigaTumSearchViewModel) - .searchResults - .add(null); - } else { - ref - .read(navigaTumSearchViewModel) - .searchResults - .add(null); - } - }, - child: const Icon(Icons.clear), - ) - : null, - ), - onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(), - ), - ); - } - - Widget _searchBody() { - return StreamBuilder( - stream: widget.isRoomSearch - ? ref.watch(navigaTumSearchViewModel).searchResults - : ref.watch(personSearchViewModel).searchResults, - builder: (context, snapshot) { - if (snapshot.hasData) { - return Expanded( - child: SingleChildScrollView( - child: Card( - child: SeparatedList.list( - data: snapshot.data!, - tile: (searchable) { - if (widget.isRoomSearch) { - final navigaTumEntity = - searchable as NavigaTumNavigationEntity; - return ListTile( - title: Text(navigaTumEntity.getFormattedName()), - subtitle: Text( - navigaTumEntity.getFormattedSubtext(), - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - trailing: const Icon(Icons.arrow_forward_ios, size: 15), - onTap: () => - context.push(navigaTum, extra: navigaTumEntity.id), - ); - } else { - final person = searchable as Person; - return ListTile( - title: Text(person.fullNameWithTitle), - trailing: const Icon(Icons.arrow_forward_ios, size: 15), - onTap: () => context.push( - personDetails, - extra: person.obfuscatedID, - ), - ); - } - }, - ), - ), - ), - ); - } else if (snapshot.hasError) { - return Expanded( - child: ErrorHandlingRouter( - error: snapshot.error!, - errorHandlingViewType: ErrorHandlingViewType.textOnly, - ), - ); - } else { - if (widget.searchString != null) { - return Expanded( - child: Center( - child: DelayedLoadingIndicator( - name: widget.isRoomSearch - ? context.tr("rooms") - : context.tr("persons"), - ), - ), - ); - } else { - return Expanded( - child: Center( - child: Text(context.tr("enterQueryStart")), - ), - ); - } - } - }, - ); - } -} diff --git a/lib/searchComponent/views/appWideSearch/resultViews/cafeteria_search_result_view.dart b/lib/searchComponent/views/resultViews/cafeteria_search_result_view.dart similarity index 73% rename from lib/searchComponent/views/appWideSearch/resultViews/cafeteria_search_result_view.dart rename to lib/searchComponent/views/resultViews/cafeteria_search_result_view.dart index 8ee44025..2fc9b8aa 100644 --- a/lib/searchComponent/views/appWideSearch/resultViews/cafeteria_search_result_view.dart +++ b/lib/searchComponent/views/resultViews/cafeteria_search_result_view.dart @@ -1,20 +1,24 @@ import 'package:campus_flutter/base/routing/routes.dart' as routes; import 'package:campus_flutter/placesComponent/model/cafeterias/cafeteria.dart'; import 'package:campus_flutter/base/enums/search_category.dart'; +import 'package:campus_flutter/searchComponent/viewModels/search_viewmodel.dart'; import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/cafeteria_search_viewmodel.dart'; -import 'package:campus_flutter/searchComponent/views/appWideSearch/search_result_card_view.dart'; +import 'package:campus_flutter/searchComponent/views/search_result_card_view.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; class CafeteriasSearchResultView extends ConsumerWidget { - const CafeteriasSearchResultView({super.key}); + const CafeteriasSearchResultView({super.key, required this.searchVM}); + + final Provider searchVM; @override Widget build(BuildContext context, WidgetRef ref) { return SearchResultCardView( searchCategory: SearchCategory.cafeterias, - viewModel: cafeteriaSearchViewModel, + searchVM: searchVM, + searchCategoryVM: cafeteriaSearchViewModel, body: (cafeteria) => ListTile( title: Text(cafeteria.name), trailing: const Icon( diff --git a/lib/searchComponent/views/appWideSearch/resultViews/calendar_search_result_view.dart b/lib/searchComponent/views/resultViews/calendar_search_result_view.dart similarity index 84% rename from lib/searchComponent/views/appWideSearch/resultViews/calendar_search_result_view.dart rename to lib/searchComponent/views/resultViews/calendar_search_result_view.dart index f2fe3a0d..8d0baa46 100644 --- a/lib/searchComponent/views/appWideSearch/resultViews/calendar_search_result_view.dart +++ b/lib/searchComponent/views/resultViews/calendar_search_result_view.dart @@ -2,8 +2,9 @@ import 'package:campus_flutter/base/routing/routes.dart'; import 'package:campus_flutter/base/util/icon_text.dart'; import 'package:campus_flutter/calendarComponent/model/calendar_event.dart'; import 'package:campus_flutter/base/enums/search_category.dart'; +import 'package:campus_flutter/searchComponent/viewModels/search_viewmodel.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/searchComponent/views/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'; @@ -11,13 +12,16 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; class CalendarSearchResultView extends ConsumerWidget { - const CalendarSearchResultView({super.key}); + const CalendarSearchResultView({super.key, required this.searchVM}); + + final Provider searchVM; @override Widget build(BuildContext context, WidgetRef ref) { return SearchResultCardView( searchCategory: SearchCategory.calendar, - viewModel: calendarSearchViewModel, + searchVM: searchVM, + searchCategoryVM: calendarSearchViewModel, body: (calendarEvent) => ListTile( title: Text(calendarEvent.title ?? "-"), subtitle: Column( diff --git a/lib/searchComponent/views/appWideSearch/resultViews/grade_search_result_view.dart b/lib/searchComponent/views/resultViews/grade_search_result_view.dart similarity index 66% rename from lib/searchComponent/views/appWideSearch/resultViews/grade_search_result_view.dart rename to lib/searchComponent/views/resultViews/grade_search_result_view.dart index d05c89f4..44eeaa11 100644 --- a/lib/searchComponent/views/appWideSearch/resultViews/grade_search_result_view.dart +++ b/lib/searchComponent/views/resultViews/grade_search_result_view.dart @@ -1,19 +1,23 @@ +import 'package:campus_flutter/searchComponent/viewModels/search_viewmodel.dart'; import 'package:campus_flutter/studiesComponent/model/grade.dart'; import 'package:campus_flutter/studiesComponent/view/grade/grade_view.dart'; import 'package:campus_flutter/base/enums/search_category.dart'; import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/grades_search_viewmodel.dart'; -import 'package:campus_flutter/searchComponent/views/appWideSearch/search_result_card_view.dart'; +import 'package:campus_flutter/searchComponent/views/search_result_card_view.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; class GradeSearchResultView extends ConsumerWidget { - const GradeSearchResultView({super.key}); + const GradeSearchResultView({super.key, required this.searchVM}); + + final Provider searchVM; @override Widget build(BuildContext context, WidgetRef ref) { return SearchResultCardView( searchCategory: SearchCategory.grade, - viewModel: gradesSearchViewModel, + searchVM: searchVM, + searchCategoryVM: gradesSearchViewModel, body: (grade) => GradeRow(grade: grade), ); } diff --git a/lib/searchComponent/views/appWideSearch/resultViews/lecture_search_result_view.dart b/lib/searchComponent/views/resultViews/lecture_search_result_view.dart similarity index 68% rename from lib/searchComponent/views/appWideSearch/resultViews/lecture_search_result_view.dart rename to lib/searchComponent/views/resultViews/lecture_search_result_view.dart index 65198cb0..ea2ee5aa 100644 --- a/lib/searchComponent/views/appWideSearch/resultViews/lecture_search_result_view.dart +++ b/lib/searchComponent/views/resultViews/lecture_search_result_view.dart @@ -1,19 +1,23 @@ +import 'package:campus_flutter/searchComponent/viewModels/search_viewmodel.dart'; import 'package:campus_flutter/studiesComponent/model/lecture.dart'; import 'package:campus_flutter/studiesComponent/view/lecture/lecture_view.dart'; import 'package:campus_flutter/base/enums/search_category.dart'; import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/lecture_search_viewmodel.dart'; -import 'package:campus_flutter/searchComponent/views/appWideSearch/search_result_card_view.dart'; +import 'package:campus_flutter/searchComponent/views/search_result_card_view.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; class LectureSearchResultView extends ConsumerWidget { - const LectureSearchResultView({super.key}); + const LectureSearchResultView({super.key, required this.searchVM}); + + final Provider searchVM; @override Widget build(BuildContext context, WidgetRef ref) { return SearchResultCardView( searchCategory: SearchCategory.lectures, - viewModel: lectureSearchViewModel, + searchVM: searchVM, + searchCategoryVM: lectureSearchViewModel, body: (lecture) => LectureView( lecture: lecture, isSearch: true, diff --git a/lib/searchComponent/views/appWideSearch/resultViews/movie_search_result_view.dart b/lib/searchComponent/views/resultViews/movie_search_result_view.dart similarity index 82% rename from lib/searchComponent/views/appWideSearch/resultViews/movie_search_result_view.dart rename to lib/searchComponent/views/resultViews/movie_search_result_view.dart index 64de822e..0f57149b 100644 --- a/lib/searchComponent/views/appWideSearch/resultViews/movie_search_result_view.dart +++ b/lib/searchComponent/views/resultViews/movie_search_result_view.dart @@ -2,19 +2,23 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:campus_flutter/base/util/string_parser.dart'; import 'package:campus_flutter/base/util/url_launcher.dart'; import 'package:campus_flutter/base/enums/search_category.dart'; +import 'package:campus_flutter/searchComponent/viewModels/search_viewmodel.dart'; import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/movie_search_viewmodel.dart'; -import 'package:campus_flutter/searchComponent/views/appWideSearch/search_result_card_view.dart'; +import 'package:campus_flutter/searchComponent/views/search_result_card_view.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; class MovieSearchResultView extends ConsumerWidget { - const MovieSearchResultView({super.key}); + const MovieSearchResultView({super.key, required this.searchVM}); + + final Provider searchVM; @override Widget build(BuildContext context, WidgetRef ref) { return SearchResultCardView( searchCategory: SearchCategory.movie, - viewModel: movieSearchViewModel, + searchVM: searchVM, + searchCategoryVM: movieSearchViewModel, body: (movieSearch) => ListTile( leading: ClipRRect( borderRadius: BorderRadius.circular(5), diff --git a/lib/searchComponent/views/appWideSearch/resultViews/navigatum_search_result_view.dart b/lib/searchComponent/views/resultViews/navigatum_search_result_view.dart similarity index 65% rename from lib/searchComponent/views/appWideSearch/resultViews/navigatum_search_result_view.dart rename to lib/searchComponent/views/resultViews/navigatum_search_result_view.dart index e098bf5e..481e4753 100644 --- a/lib/searchComponent/views/appWideSearch/resultViews/navigatum_search_result_view.dart +++ b/lib/searchComponent/views/resultViews/navigatum_search_result_view.dart @@ -1,21 +1,25 @@ import 'package:campus_flutter/base/enums/search_category.dart'; import 'package:campus_flutter/base/routing/routes.dart'; import 'package:campus_flutter/navigaTumComponent/model/navigatum_navigation_entity.dart'; -import 'package:campus_flutter/navigaTumComponent/viewModels/navigatum_search_viewmodel.dart'; -import 'package:campus_flutter/searchComponent/views/appWideSearch/search_result_card_view.dart'; +import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/navigatum_search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/viewModels/search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/views/search_result_card_view.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; class NavigaTumSearchResultView extends ConsumerWidget { - const NavigaTumSearchResultView({super.key}); + const NavigaTumSearchResultView({super.key, required this.searchVM}); + + final Provider searchVM; @override Widget build(BuildContext context, WidgetRef ref) { return SearchResultCardView( searchCategory: SearchCategory.rooms, - viewModel: navigaTumSearchViewModel, + searchVM: searchVM, + searchCategoryVM: navigaTumSearchViewModel, body: (entity) => ListTile( title: Text(entity.getFormattedName()), subtitle: Text(entity.getFormattedName()), diff --git a/lib/searchComponent/views/appWideSearch/resultViews/news_search_result_view.dart b/lib/searchComponent/views/resultViews/news_search_result_view.dart similarity index 85% rename from lib/searchComponent/views/appWideSearch/resultViews/news_search_result_view.dart rename to lib/searchComponent/views/resultViews/news_search_result_view.dart index 4f66e160..9560fe6d 100644 --- a/lib/searchComponent/views/appWideSearch/resultViews/news_search_result_view.dart +++ b/lib/searchComponent/views/resultViews/news_search_result_view.dart @@ -2,20 +2,24 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:campus_flutter/base/enums/search_category.dart'; import 'package:campus_flutter/base/util/string_parser.dart'; import 'package:campus_flutter/base/routing/routes.dart'; +import 'package:campus_flutter/searchComponent/viewModels/search_viewmodel.dart'; import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/news_search_viewmodel.dart'; -import 'package:campus_flutter/searchComponent/views/appWideSearch/search_result_card_view.dart'; +import 'package:campus_flutter/searchComponent/views/search_result_card_view.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; class NewsSearchResultView extends ConsumerWidget { - const NewsSearchResultView({super.key}); + const NewsSearchResultView({super.key, required this.searchVM}); + + final Provider searchVM; @override Widget build(BuildContext context, WidgetRef ref) { return SearchResultCardView( searchCategory: SearchCategory.news, - viewModel: newsSearchViewModel, + searchVM: searchVM, + searchCategoryVM: newsSearchViewModel, body: (newsSearch) { final imageUrl = newsSearch.news.imageUrl.toString().contains("src_1.png") diff --git a/lib/searchComponent/views/appWideSearch/resultViews/person_search_result_view.dart b/lib/searchComponent/views/resultViews/person_search_result_view.dart similarity index 73% rename from lib/searchComponent/views/appWideSearch/resultViews/person_search_result_view.dart rename to lib/searchComponent/views/resultViews/person_search_result_view.dart index e812eead..ab2309bb 100644 --- a/lib/searchComponent/views/appWideSearch/resultViews/person_search_result_view.dart +++ b/lib/searchComponent/views/resultViews/person_search_result_view.dart @@ -1,20 +1,24 @@ import 'package:campus_flutter/base/routing/routes.dart'; import 'package:campus_flutter/personComponent/model/personSearch/person.dart'; +import 'package:campus_flutter/searchComponent/viewModels/search_viewmodel.dart'; import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/person_search_viewmodel.dart'; import 'package:campus_flutter/base/enums/search_category.dart'; -import 'package:campus_flutter/searchComponent/views/appWideSearch/search_result_card_view.dart'; +import 'package:campus_flutter/searchComponent/views/search_result_card_view.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; class PersonSearchResultView extends ConsumerWidget { - const PersonSearchResultView({super.key}); + const PersonSearchResultView({super.key, required this.searchVM}); + + final Provider searchVM; @override Widget build(BuildContext context, WidgetRef ref) { return SearchResultCardView( searchCategory: SearchCategory.persons, - viewModel: personSearchViewModel, + searchVM: searchVM, + searchCategoryVM: personSearchViewModel, body: (person) => ListTile( title: Text(person.fullNameWithTitle), trailing: const Icon( diff --git a/lib/searchComponent/views/appWideSearch/resultViews/personal_lecture_search_result_view.dart b/lib/searchComponent/views/resultViews/personal_lecture_search_result_view.dart similarity index 68% rename from lib/searchComponent/views/appWideSearch/resultViews/personal_lecture_search_result_view.dart rename to lib/searchComponent/views/resultViews/personal_lecture_search_result_view.dart index 532c4444..ae10edb5 100644 --- a/lib/searchComponent/views/appWideSearch/resultViews/personal_lecture_search_result_view.dart +++ b/lib/searchComponent/views/resultViews/personal_lecture_search_result_view.dart @@ -1,19 +1,23 @@ +import 'package:campus_flutter/searchComponent/viewModels/search_viewmodel.dart'; import 'package:campus_flutter/studiesComponent/model/lecture.dart'; import 'package:campus_flutter/studiesComponent/view/lecture/lecture_view.dart'; import 'package:campus_flutter/base/enums/search_category.dart'; import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/personal_lecture_seach_viewmodel.dart'; -import 'package:campus_flutter/searchComponent/views/appWideSearch/search_result_card_view.dart'; +import 'package:campus_flutter/searchComponent/views/search_result_card_view.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; class PersonalLectureSearchResultView extends ConsumerWidget { - const PersonalLectureSearchResultView({super.key}); + const PersonalLectureSearchResultView({super.key, required this.searchVM}); + + final Provider searchVM; @override Widget build(BuildContext context, WidgetRef ref) { return SearchResultCardView( searchCategory: SearchCategory.personalLectures, - viewModel: personalLectureSearchViewModel, + searchVM: searchVM, + searchCategoryVM: personalLectureSearchViewModel, body: (lecture) => LectureView( lecture: lecture, isSearch: true, diff --git a/lib/searchComponent/views/appWideSearch/resultViews/student_club_search_result_view.dart b/lib/searchComponent/views/resultViews/student_club_search_result_view.dart similarity index 86% rename from lib/searchComponent/views/appWideSearch/resultViews/student_club_search_result_view.dart rename to lib/searchComponent/views/resultViews/student_club_search_result_view.dart index 44b71497..3572b809 100644 --- a/lib/searchComponent/views/appWideSearch/resultViews/student_club_search_result_view.dart +++ b/lib/searchComponent/views/resultViews/student_club_search_result_view.dart @@ -1,20 +1,24 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:campus_flutter/base/enums/search_category.dart'; import 'package:campus_flutter/base/util/url_launcher.dart'; +import 'package:campus_flutter/searchComponent/viewModels/search_viewmodel.dart'; import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/student_club_search_viewmodel.dart'; -import 'package:campus_flutter/searchComponent/views/appWideSearch/search_result_card_view.dart'; +import 'package:campus_flutter/searchComponent/views/search_result_card_view.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; class StudentClubSearchResultView extends ConsumerWidget { - const StudentClubSearchResultView({super.key}); + const StudentClubSearchResultView({super.key, required this.searchVM}); + + final Provider searchVM; @override Widget build(BuildContext context, WidgetRef ref) { return SearchResultCardView( searchCategory: SearchCategory.studentClub, - viewModel: studentClubSearchViewModel, + searchVM: searchVM, + searchCategoryVM: studentClubSearchViewModel, body: (studentClubSearch) { return ListTile( leading: image(studentClubSearch.studentClub.coverUrl), diff --git a/lib/searchComponent/views/appWideSearch/resultViews/study_room_search_result_view.dart b/lib/searchComponent/views/resultViews/study_room_search_result_view.dart similarity index 67% rename from lib/searchComponent/views/appWideSearch/resultViews/study_room_search_result_view.dart rename to lib/searchComponent/views/resultViews/study_room_search_result_view.dart index c6705300..cf58dafd 100644 --- a/lib/searchComponent/views/appWideSearch/resultViews/study_room_search_result_view.dart +++ b/lib/searchComponent/views/resultViews/study_room_search_result_view.dart @@ -1,19 +1,23 @@ import 'package:campus_flutter/placesComponent/views/homeWidget/study_room_widget_view.dart'; import 'package:campus_flutter/base/enums/search_category.dart'; +import 'package:campus_flutter/searchComponent/viewModels/search_viewmodel.dart'; import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/study_room_search_viewmodel.dart'; -import 'package:campus_flutter/searchComponent/views/appWideSearch/search_result_card_view.dart'; +import 'package:campus_flutter/searchComponent/views/search_result_card_view.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; class StudyRoomSearchResultView extends ConsumerWidget { - const StudyRoomSearchResultView({super.key}); + const StudyRoomSearchResultView({super.key, required this.searchVM}); + + final Provider searchVM; @override Widget build(BuildContext context, WidgetRef ref) { return SearchResultCardView( searchCategory: SearchCategory.studyRoom, - viewModel: studyRoomSearchViewModel, + searchVM: searchVM, + searchCategoryVM: studyRoomSearchViewModel, body: (studyRoomSearchResult) => StudyRoomWidgetView(studyRoomSearchResult.studyRoomGroup), ); diff --git a/lib/searchComponent/views/appWideSearch/search_category_picker_view.dart b/lib/searchComponent/views/search_category_picker_view.dart similarity index 75% rename from lib/searchComponent/views/appWideSearch/search_category_picker_view.dart rename to lib/searchComponent/views/search_category_picker_view.dart index 00ac50a7..dc717bcb 100644 --- a/lib/searchComponent/views/appWideSearch/search_category_picker_view.dart +++ b/lib/searchComponent/views/search_category_picker_view.dart @@ -2,17 +2,19 @@ import 'package:campus_flutter/base/enums/credentials.dart'; import 'package:campus_flutter/base/util/horizontal_slider.dart'; import 'package:campus_flutter/onboardingComponent/viewModels/onboarding_viewmodel.dart'; import 'package:campus_flutter/base/enums/search_category.dart'; -import 'package:campus_flutter/searchComponent/viewModels/global_search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/viewModels/search_viewmodel.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; class SearchCategoryPickerView extends ConsumerWidget { - const SearchCategoryPickerView({super.key}); + const SearchCategoryPickerView({super.key, required this.searchVM}); + + final Provider searchVM; @override Widget build(BuildContext context, WidgetRef ref) { return StreamBuilder( - stream: ref.watch(searchViewModel).selectedCategories, + stream: ref.watch(searchVM).selectedCategories, builder: (context, snapshot) { return Padding( padding: const EdgeInsets.symmetric(vertical: 10.0), @@ -20,10 +22,8 @@ class SearchCategoryPickerView extends ConsumerWidget { data: _getData(snapshot.data ?? [], ref), height: 40, child: (searchCategory) => InkWell( - onLongPress: () { - ref.read(searchViewModel).selectSingleCategory(searchCategory); - ref.read(searchViewModel).triggerSearchAfterUpdate(null); - }, + onLongPress: () => + ref.read(searchVM).selectSingleCategory(searchCategory), child: FilterChip( label: Text( SearchCategoryExtension.localizedEnumTitle( @@ -31,10 +31,8 @@ class SearchCategoryPickerView extends ConsumerWidget { context, ), ), - onSelected: (selected) { - ref.read(searchViewModel).updateCategory(searchCategory); - ref.read(searchViewModel).triggerSearchAfterUpdate(null); - }, + onSelected: (selected) => + ref.read(searchVM).updateCategory(searchCategory), selected: (snapshot.data ?? []).isNotEmpty ? snapshot.data?.contains(searchCategory) ?? false : true, diff --git a/lib/searchComponent/views/appWideSearch/search_result_card_view.dart b/lib/searchComponent/views/search_result_card_view.dart similarity index 81% rename from lib/searchComponent/views/appWideSearch/search_result_card_view.dart rename to lib/searchComponent/views/search_result_card_view.dart index 81395493..af6ffc97 100644 --- a/lib/searchComponent/views/appWideSearch/search_result_card_view.dart +++ b/lib/searchComponent/views/search_result_card_view.dart @@ -5,24 +5,26 @@ import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/base/util/delayed_loading_indicator.dart'; import 'package:campus_flutter/base/util/padded_divider.dart'; import 'package:campus_flutter/homeComponent/view/widget/widget_frame_view.dart'; -import 'package:campus_flutter/searchComponent/protocols/search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/protocols/search_category_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:campus_flutter/searchComponent/viewModels/search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/views/search_result_details_view.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -class SearchResultCardView, S extends Searchable> - extends ConsumerWidget { +class SearchResultCardView, + S extends Searchable> extends ConsumerWidget { const SearchResultCardView({ super.key, + required this.searchVM, + required this.searchCategoryVM, required this.searchCategory, - required this.viewModel, required this.body, }); - final Provider> viewModel; + final Provider searchVM; + final Provider> searchCategoryVM; final SearchCategory searchCategory; final Widget Function(S searchable) body; @@ -33,7 +35,9 @@ class SearchResultCardView, S extends Searchable> SearchCategoryExtension.localizedEnumTitle(searchCategory, context), child: Card( child: StreamBuilder( - stream: ref.watch>(viewModel).searchResults, + stream: ref + .watch>(searchCategoryVM) + .searchResults, builder: (context, snapshot) { if (snapshot.hasData) { if (snapshot.data!.isEmpty) { @@ -88,10 +92,12 @@ class SearchResultCardView, S extends Searchable> ), ); } else { - return DelayedLoadingIndicator( - name: SearchCategoryExtension.localizedEnumTitle( - searchCategory, - context, + return ListTile( + title: DelayedLoadingIndicator( + name: SearchCategoryExtension.localizedEnumTitle( + searchCategory, + context, + ), ), ); } @@ -102,8 +108,7 @@ class SearchResultCardView, S extends Searchable> } int _calculateItemLength(List? data, WidgetRef ref) { - final selectedCategories = - ref.read(searchViewModel).selectedCategories.value; + final selectedCategories = ref.read(searchVM).selectedCategories.value; if (selectedCategories.contains(searchCategory) && selectedCategories.length == 1) { return (data!.length >= 9 ? 9 : data.length) + 1; @@ -121,7 +126,7 @@ class SearchResultCardView, S extends Searchable> style: Theme.of(context).textTheme.titleMedium, ), ), - // TODO: figure out for multiple attributes + // TODO(@jakobkoerber): figure out for multiple attributes onTap: () => Navigator.push( context, MaterialPageRoute( diff --git a/lib/searchComponent/views/appWideSearch/search_result_details_view.dart b/lib/searchComponent/views/search_result_details_view.dart similarity index 100% rename from lib/searchComponent/views/appWideSearch/search_result_details_view.dart rename to lib/searchComponent/views/search_result_details_view.dart diff --git a/lib/searchComponent/views/search_result_view_builder.dart b/lib/searchComponent/views/search_result_view_builder.dart new file mode 100644 index 00000000..60d1b43b --- /dev/null +++ b/lib/searchComponent/views/search_result_view_builder.dart @@ -0,0 +1,56 @@ +import 'package:campus_flutter/base/enums/search_category.dart'; +import 'package:campus_flutter/searchComponent/viewModels/search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/views/resultViews/cafeteria_search_result_view.dart'; +import 'package:campus_flutter/searchComponent/views/resultViews/calendar_search_result_view.dart'; +import 'package:campus_flutter/searchComponent/views/resultViews/grade_search_result_view.dart'; +import 'package:campus_flutter/searchComponent/views/resultViews/lecture_search_result_view.dart'; +import 'package:campus_flutter/searchComponent/views/resultViews/movie_search_result_view.dart'; +import 'package:campus_flutter/searchComponent/views/resultViews/navigatum_search_result_view.dart'; +import 'package:campus_flutter/searchComponent/views/resultViews/news_search_result_view.dart'; +import 'package:campus_flutter/searchComponent/views/resultViews/person_search_result_view.dart'; +import 'package:campus_flutter/searchComponent/views/resultViews/personal_lecture_search_result_view.dart'; +import 'package:campus_flutter/searchComponent/views/resultViews/student_club_search_result_view.dart'; +import 'package:campus_flutter/searchComponent/views/resultViews/study_room_search_result_view.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +class SearchResultViewBuilder extends StatelessWidget { + const SearchResultViewBuilder({ + super.key, + required this.searchVM, + required this.searchCategory, + }); + + final Provider searchVM; + final SearchCategory searchCategory; + + @override + Widget build(BuildContext context) { + switch (searchCategory) { + case SearchCategory.grade: + return GradeSearchResultView(searchVM: searchVM); + case SearchCategory.cafeterias: + return CafeteriasSearchResultView(searchVM: searchVM); + case SearchCategory.calendar: + return CalendarSearchResultView(searchVM: searchVM); + case SearchCategory.movie: + return MovieSearchResultView(searchVM: searchVM); + case SearchCategory.news: + return NewsSearchResultView(searchVM: searchVM); + case SearchCategory.studentClub: + return StudentClubSearchResultView(searchVM: searchVM); + case SearchCategory.studyRoom: + return StudyRoomSearchResultView(searchVM: searchVM); + case SearchCategory.lectures: + return LectureSearchResultView(searchVM: searchVM); + case SearchCategory.personalLectures: + return PersonalLectureSearchResultView(searchVM: searchVM); + case SearchCategory.persons: + return PersonSearchResultView(searchVM: searchVM); + case SearchCategory.rooms: + return NavigaTumSearchResultView(searchVM: searchVM); + default: + return Container(); + } + } +} diff --git a/lib/searchComponent/views/search_scaffold.dart b/lib/searchComponent/views/search_scaffold.dart new file mode 100644 index 00000000..0a7c6c93 --- /dev/null +++ b/lib/searchComponent/views/search_scaffold.dart @@ -0,0 +1,41 @@ +import 'package:campus_flutter/base/util/custom_back_button.dart'; +import 'package:campus_flutter/searchComponent/viewModels/search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/views/search_view.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +class SearchScaffold extends ConsumerStatefulWidget { + const SearchScaffold({ + super.key, + required this.searchVM, + this.searchString, + }); + + final Provider searchVM; + final String? searchString; + + @override + ConsumerState createState() => _SearchScaffoldState(); +} + +class _SearchScaffoldState extends ConsumerState { + @override + void initState() { + ref.read(widget.searchVM).search(searchString: widget.searchString); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text(context.tr("search")), + leading: CustomBackButton( + beforeOnPressed: ref.read(widget.searchVM).clear, + ), + ), + body: SearchView(searchVM: widget.searchVM), + ); + } +} diff --git a/lib/searchComponent/views/appWideSearch/search_textfield_view.dart b/lib/searchComponent/views/search_textfield_view.dart similarity index 68% rename from lib/searchComponent/views/appWideSearch/search_textfield_view.dart rename to lib/searchComponent/views/search_textfield_view.dart index 8a4d5379..619f51c4 100644 --- a/lib/searchComponent/views/appWideSearch/search_textfield_view.dart +++ b/lib/searchComponent/views/search_textfield_view.dart @@ -1,13 +1,16 @@ import 'package:campus_flutter/base/extensions/context.dart'; -import 'package:campus_flutter/searchComponent/viewModels/global_search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/viewModels/search_viewmodel.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; class SearchTextField extends ConsumerStatefulWidget { - const SearchTextField({super.key, required this.textEditingController}); + const SearchTextField({ + super.key, + required this.searchVM, + }); - final TextEditingController textEditingController; + final Provider searchVM; @override ConsumerState createState() => @@ -22,11 +25,16 @@ class _SearchTextFieldState extends ConsumerState { return Padding( padding: EdgeInsets.symmetric(horizontal: context.padding), child: TextField( - controller: widget.textEditingController, + controller: ref.watch(widget.searchVM).searchTextController, onChanged: (searchString) { - ref.read(searchViewModel).triggerSearchAfterUpdate(searchString); + ref.read(widget.searchVM).search(); setState(() { - showIcon = widget.textEditingController.value.text.isNotEmpty; + showIcon = ref + .read(widget.searchVM) + .searchTextController + .value + .text + .isNotEmpty; }); }, decoration: InputDecoration( @@ -34,8 +42,7 @@ class _SearchTextFieldState extends ConsumerState { suffixIcon: showIcon ? GestureDetector( onTap: () { - ref.read(searchViewModel).clear(); - widget.textEditingController.clear(); + ref.read(widget.searchVM).clear(); setState(() { showIcon = false; }); diff --git a/lib/searchComponent/views/appWideSearch/search_view.dart b/lib/searchComponent/views/search_view.dart similarity index 60% rename from lib/searchComponent/views/appWideSearch/search_view.dart rename to lib/searchComponent/views/search_view.dart index 03dc43dc..ceb86ae6 100644 --- a/lib/searchComponent/views/appWideSearch/search_view.dart +++ b/lib/searchComponent/views/search_view.dart @@ -1,18 +1,21 @@ import 'package:campus_flutter/base/enums/search_category.dart'; -import 'package:campus_flutter/searchComponent/viewModels/global_search_viewmodel.dart'; -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/searchComponent/viewModels/search_viewmodel.dart'; +import 'package:campus_flutter/searchComponent/views/search_category_picker_view.dart'; +import 'package:campus_flutter/searchComponent/views/search_result_view_builder.dart'; +import 'package:campus_flutter/searchComponent/views/search_textfield_view.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'; class SearchView extends ConsumerWidget { - SearchView({super.key, required this.showContent}); - - final TextEditingController textEditingController = TextEditingController(); + const SearchView({ + super.key, + required this.searchVM, + this.showContent = true, + }); + final Provider searchVM; final bool showContent; @override @@ -24,10 +27,10 @@ class SearchView extends ConsumerWidget { ? Column( mainAxisSize: MainAxisSize.min, children: [ - SearchTextField( - textEditingController: textEditingController, + SearchTextField(searchVM: searchVM), + SearchCategoryPickerView( + searchVM: searchVM, ), - const SearchCategoryPickerView(), _search(ref), ], ) //) @@ -39,9 +42,10 @@ class SearchView extends ConsumerWidget { Widget _search(WidgetRef ref) { return Expanded( child: StreamBuilder( - stream: ref.watch(searchViewModel).result, + stream: ref.watch(searchVM).results, builder: (context, snapshot) { - if (!snapshot.hasData && textEditingController.text.isEmpty) { + if (!snapshot.hasData && + ref.read(searchVM).searchTextController.text.isEmpty) { return Center( child: Text(context.tr("enterQueryStart")), ); @@ -51,8 +55,10 @@ class SearchView extends ConsumerWidget { return MasonryGridView.count( crossAxisCount: 2, itemCount: snapshot.data?.length ?? 0, - itemBuilder: (context, index) => - SearchResultViewBuilder(snapshot.data![index]), + itemBuilder: (context, index) => SearchResultViewBuilder( + searchVM: searchVM, + searchCategory: snapshot.data![index], + ), ); } else { return SingleChildScrollView( @@ -61,7 +67,10 @@ class SearchView extends ConsumerWidget { children: [ for (var result in snapshot.data ?? const Iterable.empty()) - SearchResultViewBuilder(result), + SearchResultViewBuilder( + searchVM: searchVM, + searchCategory: result, + ), ], ), ); diff --git a/lib/studiesComponent/screen/studies_screen.dart b/lib/studiesComponent/screen/studies_screen.dart index 8c9d4b18..fcb37a3a 100644 --- a/lib/studiesComponent/screen/studies_screen.dart +++ b/lib/studiesComponent/screen/studies_screen.dart @@ -11,8 +11,7 @@ class StudiesScreen extends StatefulWidget { State createState() => _StudiesScreenState(); } -class _StudiesScreenState extends State - with AutomaticKeepAliveClientMixin { +class _StudiesScreenState extends State { int selectedPage = 0; PageController pageController = PageController(); @@ -29,7 +28,6 @@ class _StudiesScreenState extends State @override Widget build(BuildContext context) { - super.build(context); return Column( children: [ Padding( @@ -72,7 +70,4 @@ class _StudiesScreenState extends State ], ); } - - @override - bool get wantKeepAlive => true; } diff --git a/lib/studiesComponent/view/grade/grades_view.dart b/lib/studiesComponent/view/grade/grades_view.dart index d289569b..1f90679c 100644 --- a/lib/studiesComponent/view/grade/grades_view.dart +++ b/lib/studiesComponent/view/grade/grades_view.dart @@ -17,8 +17,7 @@ class GradesView extends ConsumerStatefulWidget { ConsumerState createState() => _GradesViewState(); } -class _GradesViewState extends ConsumerState - with AutomaticKeepAliveClientMixin { +class _GradesViewState extends ConsumerState { late Provider gradeVM; @override @@ -30,7 +29,6 @@ class _GradesViewState extends ConsumerState @override Widget build(BuildContext context) { - super.build(context); return StreamBuilder( stream: ref.watch(gradeVM).studyProgramGrades, builder: (context, snapshot) { @@ -131,9 +129,6 @@ class _GradesViewState extends ConsumerState ], ); } - - @override - bool get wantKeepAlive => true; } class DegreeView extends StatelessWidget { diff --git a/lib/studiesComponent/view/lecture/lecture_view.dart b/lib/studiesComponent/view/lecture/lecture_view.dart index f65cc294..4b58d4c3 100644 --- a/lib/studiesComponent/view/lecture/lecture_view.dart +++ b/lib/studiesComponent/view/lecture/lecture_view.dart @@ -1,6 +1,7 @@ import 'package:campus_flutter/base/extensions/context.dart'; import 'package:campus_flutter/base/util/icon_text.dart'; import 'package:campus_flutter/base/routing/routes.dart'; +import 'package:campus_flutter/base/util/speaker.dart'; import 'package:campus_flutter/studiesComponent/model/lecture.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -35,7 +36,11 @@ class LectureView extends ConsumerWidget { ), const Padding(padding: EdgeInsets.symmetric(vertical: 2.0)), if (lecture.speaker != null) - _subtitle(lecture.speaker!, Icons.person, context), + _subtitle( + Speaker.getSpeakerName(lecture.speaker!), + Icons.person, + context, + ), ], ), onTap: () => context.push(lectureDetails, extra: lecture), diff --git a/lib/studiesComponent/view/lecture/lectures_view.dart b/lib/studiesComponent/view/lecture/lectures_view.dart index 1f679993..9b15eea2 100644 --- a/lib/studiesComponent/view/lecture/lectures_view.dart +++ b/lib/studiesComponent/view/lecture/lectures_view.dart @@ -16,8 +16,7 @@ class LecturesView extends ConsumerStatefulWidget { ConsumerState createState() => _LecturesViewState(); } -class _LecturesViewState extends ConsumerState - with AutomaticKeepAliveClientMixin { +class _LecturesViewState extends ConsumerState { final ScrollController scrollController = ScrollController(); @override @@ -28,7 +27,6 @@ class _LecturesViewState extends ConsumerState @override Widget build(BuildContext context) { - super.build(context); return StreamBuilder( stream: ref.watch(lectureViewModel).lectures, builder: (context, snapshot) { @@ -106,7 +104,4 @@ class _LecturesViewState extends ConsumerState ); } } - - @override - bool get wantKeepAlive => true; } diff --git a/lib/studiesComponent/view/lectureDetail/basic_lecture_info_view.dart b/lib/studiesComponent/view/lectureDetail/basic_lecture_info_view.dart index 59e16f9f..8d837d2e 100644 --- a/lib/studiesComponent/view/lectureDetail/basic_lecture_info_view.dart +++ b/lib/studiesComponent/view/lectureDetail/basic_lecture_info_view.dart @@ -1,4 +1,5 @@ import 'package:campus_flutter/base/routing/routes.dart'; +import 'package:campus_flutter/base/util/speaker.dart'; import 'package:campus_flutter/studiesComponent/model/lecture.dart'; import 'package:campus_flutter/studiesComponent/model/lecture_details.dart'; import 'package:campus_flutter/studiesComponent/view/lectureDetail/basic_lecture_info_row_view.dart'; @@ -37,17 +38,30 @@ class BasicLectureInfoView extends ConsumerWidget { information: lectureDetails.organisation, iconData: Icons.import_contacts, ), - if (lectureDetails.speaker != null) + if (lecture?.speaker != null) BasicLectureInfoRowView( - information: lectureDetails.speaker!, + information: Speaker.getSpeakerName(lecture!.speaker!), iconData: Icons.person, trailingWidget: IconButton( onPressed: () => context.push( - roomSearch, - extra: ( - lectureDetails.speaker?.split(",").first, - false, - ), + personSearch, + extra: Speaker.getSpeakerName(lecture!.speaker!), + ), + icon: Icon( + Icons.search, + size: 20, + color: context.theme.primaryColor, + ), + ), + ), + if (lecture?.speaker == null) + BasicLectureInfoRowView( + information: Speaker.getSpeakerName(lectureDetails.speaker!), + iconData: Icons.person, + trailingWidget: IconButton( + onPressed: () => context.push( + personSearch, + extra: Speaker.getSpeakerName(lectureDetails.speaker!), ), icon: Icon( Icons.search, diff --git a/lib/studiesComponent/view/lectureDetail/lecture_meeting_info_view.dart b/lib/studiesComponent/view/lectureDetail/lecture_meeting_info_view.dart index 77c9bf9c..0c72f180 100644 --- a/lib/studiesComponent/view/lectureDetail/lecture_meeting_info_view.dart +++ b/lib/studiesComponent/view/lectureDetail/lecture_meeting_info_view.dart @@ -30,10 +30,7 @@ class LectureMeetingInfoView extends ConsumerWidget { trailingWidget: IconButton( onPressed: () => context.push( roomSearch, - extra: ( - ref.read(viewModel).event!.location, - null, - ), + extra: ref.read(viewModel).event!.location, ), icon: Icon( Icons.search, diff --git a/pubspec.lock b/pubspec.lock index 9dcca061..41fda1d4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -616,10 +616,10 @@ packages: dependency: transitive description: name: geolocator_apple - sha256: bc2aca02423ad429cb0556121f56e60360a2b7d694c8570301d06ea0c00732fd + sha256: f47bca50d7f564bc342aac311a050ea0de7d0b6b7bbcf3948b22b1b61874ebd3 url: "https://pub.dev" source: hosted - version: "2.3.7" + version: "2.3.8" geolocator_platform_interface: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 76eaa513..ae9f6169 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: campus_flutter -description: "A new Flutter project." +description: "TUM Campus App" publish_to: 'none' version: 5.1.1+1