Skip to content

Commit

Permalink
Optimize Search and Merge General, Person and Room Search
Browse files Browse the repository at this point in the history
  • Loading branch information
jakobkoerber committed Oct 9, 2024
1 parent f5b145c commit 89b6400
Show file tree
Hide file tree
Showing 41 changed files with 360 additions and 486 deletions.
5 changes: 5 additions & 0 deletions lib/base/enums/search_type.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
enum SearchType {
general,
room,
person;
}
32 changes: 19 additions & 13 deletions lib/base/routing/router.dart
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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';
Expand Down Expand Up @@ -220,7 +221,22 @@ final _router = GoRouter(
),
GoRoute(
path: search,
builder: (context, state) => const SearchScaffold(),
builder: (context, state) => SearchScaffold(
viewModel:
searchViewModel((SearchType.general, state.extra as String?)),
),
),
GoRoute(
path: roomSearch,
builder: (context, state) => SearchScaffold(
viewModel: searchViewModel((SearchType.room, state.extra as String?)),
),
),
GoRoute(
path: personSearch,
builder: (context, state) => SearchScaffold(
viewModel: searchViewModel((SearchType.person, state.extra as String?)),
),
),
GoRoute(
path: studyRoom,
Expand All @@ -244,16 +260,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(
Expand Down
7 changes: 5 additions & 2 deletions lib/base/routing/routes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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";
14 changes: 13 additions & 1 deletion lib/base/util/custom_back_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
},
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
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/category_search_viewmodel.dart';
import 'package:collection/collection.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:rxdart/rxdart.dart';

final navigaTumSearchViewModel = Provider((ref) => NavigaTumSearchViewModel());

class NavigaTumSearchViewModel
implements SearchViewModel<NavigaTumNavigationEntity> {
implements CategorySearchViewModel<NavigaTumNavigationEntity> {
@override
BehaviorSubject<List<NavigaTumNavigationEntity>?> searchResults =
BehaviorSubject.seeded(null);
Expand Down
7 changes: 5 additions & 2 deletions lib/navigation_service.dart
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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, null)))
.setSearchCategories(currentIndex);
context.push(search);
},
icon: const Icon(Icons.search),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'package:campus_flutter/searchComponent/protocols/searchable.dart';
import 'package:rxdart/rxdart.dart';

abstract class SearchViewModel<T extends Searchable> {
abstract class CategorySearchViewModel<T extends Searchable> {
late BehaviorSubject<List<T>?> searchResults;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
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:campus_flutter/navigaTumComponent/viewModels/navigatum_search_viewmodel.dart';
import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/person_search_viewmodel.dart';
Expand All @@ -12,30 +13,55 @@ import 'package:campus_flutter/searchComponent/viewModels/searchableViewModels/n
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/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:rxdart/rxdart.dart';

final searchViewModel = Provider((ref) => GlobalSearchViewModel(ref));
final searchViewModel = Provider.family<SearchViewModel, (SearchType, String?)>(
(ref, data) => data.$2 != null
? SearchViewModel(ref, searchType: data.$1, searchString: data.$2!)
: SearchViewModel(ref, searchType: data.$1),
);

class GlobalSearchViewModel {
class SearchViewModel {
BehaviorSubject<List<SearchCategory>?> result = BehaviorSubject.seeded(null);
BehaviorSubject<List<SearchCategory>> selectedCategories =
BehaviorSubject.seeded([]);

String searchString = "";
late final TextEditingController searchTextController;
final SearchType searchType;
final Ref ref;

bool isAuthorized = false;

final Ref ref;
SearchViewModel(
this.ref, {
required this.searchType,
String? searchString,
}) {
searchTextController = TextEditingController(text: searchString);
selectedCategories.add(_initialSearchCategories());
triggerSearchAfterUpdate();
}

GlobalSearchViewModel(this.ref);
_initialSearchCategories() {
switch (searchType) {
case SearchType.general:
return <SearchCategory>[];
case SearchType.room:
return [SearchCategory.rooms, SearchCategory.studyRoom];
case SearchType.person:
return [SearchCategory.persons];
}
}

void search(String searchString) async {
void _search() async {
final searchString = searchTextController.text;
if (searchString.isEmpty) {
clear();
return;
}
this.searchString = searchString;
searchTextController.text = searchString;
if (selectedCategories.value.isEmpty) {
if (ref.read(onboardingViewModel).credentials.value ==
Credentials.tumId) {
Expand Down Expand Up @@ -63,29 +89,26 @@ class GlobalSearchViewModel {
}

void clear() {
searchString = "";
searchTextController.clear();
result.add(null);
}

void triggerSearchAfterUpdate(String? searchString) {
if (searchString != null) {
this.searchString = searchString;
}
search(this.searchString);
void triggerSearchAfterUpdate() {
_search();
if (selectedCategories.value.isEmpty) {
for (var category in SearchCategory.values) {
if (isAuthorized) {
_authorizedSearchTriggerBuilder(searchString, category);
_authorizedSearchTriggerBuilder(category);
} else {
_unauthorizedSearchTriggerBuilder(searchString, category);
_unauthorizedSearchTriggerBuilder(category);
}
}
} else {
for (var selectedCategory in selectedCategories.value) {
if (isAuthorized) {
_authorizedSearchTriggerBuilder(searchString, selectedCategory);
_authorizedSearchTriggerBuilder(selectedCategory);
} else {
_unauthorizedSearchTriggerBuilder(searchString, selectedCategory);
_unauthorizedSearchTriggerBuilder(selectedCategory);
}
}
}
Expand Down Expand Up @@ -130,77 +153,57 @@ class GlobalSearchViewModel {
}
}

void _authorizedSearchTriggerBuilder(
String? searchString,
SearchCategory searchCategory,
) {
void _authorizedSearchTriggerBuilder(SearchCategory searchCategory) {
final searchString = searchTextController.text;
switch (searchCategory) {
case SearchCategory.grade:
ref.read(gradesSearchViewModel).gradesSearch(query: this.searchString);
ref.read(gradesSearchViewModel).gradesSearch(query: searchString);
case SearchCategory.cafeterias:
ref
.read(cafeteriaSearchViewModel)
.cafeteriaSearch(query: this.searchString);
ref.read(cafeteriaSearchViewModel).cafeteriaSearch(query: searchString);
case SearchCategory.calendar:
ref
.read(calendarSearchViewModel)
.calendarSearch(query: this.searchString);
ref.read(calendarSearchViewModel).calendarSearch(query: searchString);
case SearchCategory.movie:
ref.read(movieSearchViewModel).movieSearch(query: this.searchString);
ref.read(movieSearchViewModel).movieSearch(query: searchString);
case SearchCategory.news:
ref.read(newsSearchViewModel).newsSearch(query: this.searchString);
ref.read(newsSearchViewModel).newsSearch(query: searchString);
case SearchCategory.studentClub:
ref
.read(studentClubSearchViewModel)
.studentClubSearch(query: this.searchString);
.studentClubSearch(query: searchString);
case SearchCategory.studyRoom:
ref
.read(studyRoomSearchViewModel)
.studyRoomSearch(query: this.searchString);
ref.read(studyRoomSearchViewModel).studyRoomSearch(query: searchString);
case SearchCategory.lectures:
ref
.read(lectureSearchViewModel)
.lectureSearch(query: this.searchString);
ref.read(lectureSearchViewModel).lectureSearch(query: searchString);
case SearchCategory.personalLectures:
ref
.read(personalLectureSearchViewModel)
.personalLectureSearch(query: this.searchString);
.personalLectureSearch(query: searchString);
case SearchCategory.persons:
ref.read(personSearchViewModel).personSearch(query: this.searchString);
ref.read(personSearchViewModel).personSearch(query: searchString);
case SearchCategory.rooms:
ref
.read(navigaTumSearchViewModel)
.navigaTumSearch(query: this.searchString);
ref.read(navigaTumSearchViewModel).navigaTumSearch(query: searchString);
default:
return;
}
}

void _unauthorizedSearchTriggerBuilder(
String? searchString,
SearchCategory searchCategory,
) {
void _unauthorizedSearchTriggerBuilder(SearchCategory searchCategory) {
final searchString = searchTextController.text;
switch (searchCategory) {
case SearchCategory.cafeterias:
ref
.read(cafeteriaSearchViewModel)
.cafeteriaSearch(query: this.searchString);
ref.read(cafeteriaSearchViewModel).cafeteriaSearch(query: searchString);
case SearchCategory.movie:
ref.read(movieSearchViewModel).movieSearch(query: this.searchString);
ref.read(movieSearchViewModel).movieSearch(query: searchString);
case SearchCategory.news:
ref.read(newsSearchViewModel).newsSearch(query: this.searchString);
ref.read(newsSearchViewModel).newsSearch(query: searchString);
case SearchCategory.studentClub:
ref
.read(studentClubSearchViewModel)
.studentClubSearch(query: this.searchString);
.studentClubSearch(query: searchString);
case SearchCategory.studyRoom:
ref
.read(studyRoomSearchViewModel)
.studyRoomSearch(query: this.searchString);
ref.read(studyRoomSearchViewModel).studyRoomSearch(query: searchString);
case SearchCategory.rooms:
ref
.read(navigaTumSearchViewModel)
.navigaTumSearch(query: this.searchString);
ref.read(navigaTumSearchViewModel).navigaTumSearch(query: searchString);
default:
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ 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/category_search_viewmodel.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:rxdart/rxdart.dart';

final cafeteriaSearchViewModel = Provider((ref) => CafeteriaSearchViewModel());

class CafeteriaSearchViewModel implements SearchViewModel<Cafeteria> {
class CafeteriaSearchViewModel implements CategorySearchViewModel<Cafeteria> {
@override
BehaviorSubject<List<Cafeteria>?> searchResults =
BehaviorSubject.seeded(null);
Expand Down
Loading

0 comments on commit 89b6400

Please sign in to comment.