import SwiftUI import SwiftUIFlux import Combine // MARK: - Movies List struct MoviesList: ConnectedView { struct Props { let searchedMovies: [Int]? let searchedKeywords: [Keyword]? let searcherdPeoples: [Int]? let recentSearches: [String] } enum SearchFilter: Int { case movies, peoples } // MARK: - binding @State private var searchFilter: Int = SearchFilter.movies.rawValue @State private var searchTextWrapper = MoviesSearchTextWrapper() @State private var isSearching = false // MARK: - Public var let movies: [Int] let displaySearch: Bool var pageListener: MoviesPagesListener? var headerView: AnyView? // MARK: - Computed Props func map(state: AppState, dispatch: @escaping DispatchFunction) -> Props { if isSearching { return Props(searchedMovies: state.moviesState.search[searchTextWrapper.searchText], searchedKeywords: state.moviesState.searchKeywords[searchTextWrapper.searchText]?.prefix(5).map{ $0 }, searcherdPeoples: state.peoplesState.search[searchTextWrapper.searchText], recentSearches: state.moviesState.recentSearches.map{ $0 }) } return Props(searchedMovies: nil, searchedKeywords: nil, searcherdPeoples: nil, recentSearches: []) } // MARK: - Computed views private func moviesRows(props: Props) -> some View { ForEach(isSearching ? props.searchedMovies ?? [] : movies, id: \.self) { id in NavigationLink(destination: MovieDetail(movieId: id)) { MovieRow(movieId: id) } } } private func movieSection(props: Props) -> some View { Group { if isSearching { Section(header: Text("Sonuçlar: \(searchTextWrapper.searchText)")) { if isSearching && props.searchedMovies == nil { Text("Filmler aranıyor...") } else if isSearching && props.searchedMovies?.isEmpty == true { Text("Sonuç yok") } else { moviesRows(props: props) } } } else { Section { moviesRows(props: props) } } } } private func peoplesSection(props: Props) -> some View { Section { if isSearching && props.searcherdPeoples == nil { Text("Kişiler aranıyor...") } else if isSearching && props.searcherdPeoples?.isEmpty == true { Text("Sonuç yok") } else { ForEach(props.searcherdPeoples ?? [], id: \.self) { id in NavigationLink(destination: PeopleDetail(peopleId: id)) { PeopleRow(peopleId: id) } } } } } private func keywordsSection(props: Props) -> some View { Section(header: Text("Anahtar kelimeler")) { ForEach(props.searchedKeywords ?? []) {keyword in NavigationLink(destination: MovieKeywordList(keyword: keyword)) { Text(keyword.name) } } } } private var searchField: some View { SearchField(searchTextWrapper: searchTextWrapper, placeholder: "Film veya kişi arayın", isSearching: $isSearching) .onPreferenceChange(OffsetTopPreferenceKey.self) { _ in UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) } } private var searchFilterView: some View { Picker(selection: $searchFilter, label: Text("")) { Text("Filmler").tag(SearchFilter.movies.rawValue) Text("Kişiler").tag(SearchFilter.peoples.rawValue) }.pickerStyle(SegmentedPickerStyle()) } // MARK: - Body func body(props: Props) -> some View { List { if displaySearch { Section { searchField } } if headerView != nil && !isSearching { Section { headerView! } } if isSearching { searchFilterView if props.searchedKeywords != nil && searchFilter == SearchFilter.movies.rawValue { keywordsSection(props: props) } } if isSearching && searchFilter == SearchFilter.peoples.rawValue { peoplesSection(props: props) } else { movieSection(props: props) } if !movies.isEmpty || props.searchedMovies?.isEmpty == false { Rectangle() .foregroundColor(.clear) .onAppear { if self.isSearching && props.searchedMovies?.isEmpty == false { self.searchTextWrapper.searchPageListener.currentPage += 1 } else if self.pageListener != nil && !self.isSearching && !self.movies.isEmpty { self.pageListener?.currentPage += 1 } } } } .listStyle(PlainListStyle()) .animation(.spring()) } }