package org.mosad.teapod.ui.activity.main.fragments import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.SearchView import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope import kotlinx.coroutines.Job import kotlinx.coroutines.async import org.mosad.teapod.databinding.FragmentSearchBinding import org.mosad.teapod.parser.crunchyroll.Crunchyroll import org.mosad.teapod.util.ItemMedia import org.mosad.teapod.util.adapter.MediaItemListAdapter import org.mosad.teapod.util.decoration.MediaItemDecoration import org.mosad.teapod.util.showFragment import org.mosad.teapod.util.toItemMediaList class SearchFragment : Fragment() { private lateinit var binding: FragmentSearchBinding private lateinit var adapter: MediaItemListAdapter private val itemList = arrayListOf() private var searchJob: Job? = null private var oldSearchQuery = "" override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { binding = FragmentSearchBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding.recyclerMediaSearch.addItemDecoration(MediaItemDecoration(9)) adapter = MediaItemListAdapter(MediaItemListAdapter.OnClickListener { binding.searchText.clearFocus() activity?.showFragment(MediaFragment(it.id)) }) binding.recyclerMediaSearch.adapter = adapter initActions() } private fun initActions() { binding.searchText.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextSubmit(query: String?): Boolean { query?.let { search(it) } return false } override fun onQueryTextChange(newText: String?): Boolean { newText?.let { search(it) } return false } }) } /** * Search for a query string at Crunchyroll and submit the results to the adapter. */ private fun search(query: String) { // if the query hasn't changed since the last successful search, return if (query == oldSearchQuery) return // cancel search job if one is already running if (searchJob?.isActive == true) searchJob?.cancel() searchJob = lifecycleScope.async { // TODO maybe wait a few ms (500ms?) before searching, if the user inputs any other chars val results = Crunchyroll.search(query, 50) itemList.clear() // TODO needs clean up // TODO add top results first heading adapter.submitList( results.items.firstOrNull()?.items?.toItemMediaList() ?: listOf() ) // TODO currently only tv shows are supported, hence only the first items array // should be always present // // TODO add tv shows heading // if (results.items.size >= 2) { // itemList.addAll(results.items[1].items.map { item -> // ItemMedia(item.id, item.title, item.images.poster_wide[0][0].source) // }) // } // // // TODO add movies heading // if (results.items.size >= 3) { // itemList.addAll(results.items[2].items.map { item -> // ItemMedia(item.id, item.title, item.images.poster_wide[0][0].source) // }) // } // // // TODO add episodes heading // if (results.items.size >= 4) { // itemList.addAll(results.items[3].items.map { item -> // ItemMedia(item.id, item.title, item.images.poster_wide[0][0].source) // }) // } // after successfully searching the query term, add it as old query, to make sure we // don't search again if the query hasn't changed oldSearchQuery = query } } }