diff --git a/app/build.gradle b/app/build.gradle index 87a5f6de5..94d8bd443 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -34,7 +34,7 @@ android { compileSdkVersion versions.compileSdk versionCode versions.versionCode versionName versions.versionName - resConfigs "en", "ar", "de", "es", "fi", "fr", "it", "pl", "pt", "ru", "tr", "zh", "uk", "vi" + resourceConfigurations += ['en', 'ar', 'de', 'es', 'fi', 'fr', 'it', 'pl', 'pt', 'ru', 'tr', 'zh', 'uk', 'vi'] testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } diff --git a/app/src/main/assets/release_notes.txt b/app/src/main/assets/release_notes.txt index f59976bc1..61ad30d80 100644 --- a/app/src/main/assets/release_notes.txt +++ b/app/src/main/assets/release_notes.txt @@ -1,5 +1,5 @@ -* UI/UX upgrades for tablets and foldable devices (can be changed via Settings) +* Fix issue where actors list of shows and movies would not return to its scrolled position * Other bugfixes -Do you enjoy Showly and want to support the developer? -Become a premium subscriber and gain access to cool bonus features! Check Settings to learn more! +Do you enjoy Showly and want to support the one and only developer? +Become a Premium user and gain access to cool bonus features! Check Settings to learn more! diff --git a/app/src/main/play/release-notes/en-GB/default.txt b/app/src/main/play/release-notes/en-GB/default.txt index 6818c26ac..86d0a1edb 100644 --- a/app/src/main/play/release-notes/en-GB/default.txt +++ b/app/src/main/play/release-notes/en-GB/default.txt @@ -1,2 +1,2 @@ -* UI/UX upgrades for tablets and foldable devices (can be changed via Settings) +* Fix issue where actors list of shows and movies would not return to its scrolled position * Other bugfixes \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c42526844..55a20a3c2 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,7 +12,7 @@ hiltWork = "1.0.0" [libraries] -gradle = { group = "com.android.tools.build", name = "gradle", version = "8.1.1" } +gradle = { group = "com.android.tools.build", name = "gradle", version = "8.2.0" } gradle-kotlin-plugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version = "1.9.0" } gradle-ktlint = { group = "org.jlleitschuh.gradle", name = "ktlint-gradle", version = "10.2.1" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 452f17e57..bafa2e150 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Tue Apr 11 21:13:54 CEST 2023 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/ui-base/src/main/java/com/michaldrabik/ui_base/BaseBottomSheetFragment.kt b/ui-base/src/main/java/com/michaldrabik/ui_base/BaseBottomSheetFragment.kt index 5bc9d7f93..8a9258bf3 100644 --- a/ui-base/src/main/java/com/michaldrabik/ui_base/BaseBottomSheetFragment.kt +++ b/ui-base/src/main/java/com/michaldrabik/ui_base/BaseBottomSheetFragment.kt @@ -25,13 +25,22 @@ abstract class BaseBottomSheetFragment(@LayoutRes val layoutResId: Int) : Bottom override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - val behavior: BottomSheetBehavior<*> = (dialog as BottomSheetDialog).behavior - behavior.state = BottomSheetBehavior.STATE_EXPANDED - behavior.skipCollapsed = true + expandSheet() } protected fun navigateTo(@IdRes destination: Int, bundle: Bundle? = null) = (requireActivity() as NavigationHost).findNavControl()?.navigate(destination, bundle) + protected fun isSheetExpanded(): Boolean { + val behavior: BottomSheetBehavior<*> = (dialog as BottomSheetDialog).behavior + return behavior.state == BottomSheetBehavior.STATE_EXPANDED + } + + protected fun expandSheet() { + val behavior: BottomSheetBehavior<*> = (dialog as BottomSheetDialog).behavior + behavior.state = BottomSheetBehavior.STATE_EXPANDED + behavior.skipCollapsed = true + } + protected fun closeSheet() = (requireActivity() as NavigationHost).findNavControl()?.navigateUp() } diff --git a/ui-movie/src/main/java/com/michaldrabik/ui_movie/MovieDetailsUiEvents.kt b/ui-movie/src/main/java/com/michaldrabik/ui_movie/MovieDetailsUiEvents.kt index bc3c96b25..b9ff0ac4c 100644 --- a/ui-movie/src/main/java/com/michaldrabik/ui_movie/MovieDetailsUiEvents.kt +++ b/ui-movie/src/main/java/com/michaldrabik/ui_movie/MovieDetailsUiEvents.kt @@ -6,12 +6,14 @@ import com.michaldrabik.ui_base.utilities.events.Event import com.michaldrabik.ui_model.Movie import com.michaldrabik.ui_model.MovieCollection import com.michaldrabik.ui_model.Person +import com.michaldrabik.ui_people.details.PersonDetailsArgs sealed class MovieDetailsEvent(action: T) : Event(action) { data class OpenPersonSheet( val movie: Movie, val person: Person, + val personArgs: PersonDetailsArgs?, ) : MovieDetailsEvent(movie) data class OpenPeopleSheet( diff --git a/ui-movie/src/main/java/com/michaldrabik/ui_movie/sections/people/MovieDetailsPeopleFragment.kt b/ui-movie/src/main/java/com/michaldrabik/ui_movie/sections/people/MovieDetailsPeopleFragment.kt index 58181bde2..43392e34c 100644 --- a/ui-movie/src/main/java/com/michaldrabik/ui_movie/sections/people/MovieDetailsPeopleFragment.kt +++ b/ui-movie/src/main/java/com/michaldrabik/ui_movie/sections/people/MovieDetailsPeopleFragment.kt @@ -28,7 +28,9 @@ import com.michaldrabik.ui_movie.R import com.michaldrabik.ui_movie.databinding.FragmentMovieDetailsPeopleBinding import com.michaldrabik.ui_movie.sections.people.recycler.ActorsAdapter import com.michaldrabik.ui_navigation.java.NavigationArgs.ARG_PERSON +import com.michaldrabik.ui_navigation.java.NavigationArgs.ARG_PERSON_ARGS import com.michaldrabik.ui_navigation.java.NavigationArgs.REQUEST_DETAILS +import com.michaldrabik.ui_people.details.PersonDetailsArgs import com.michaldrabik.ui_people.details.PersonDetailsBottomSheet import com.michaldrabik.ui_people.list.PeopleListBottomSheet import dagger.hilt.android.AndroidEntryPoint @@ -67,9 +69,9 @@ class MovieDetailsPeopleFragment : BaseFragment(R.l } } - private fun openPersonSheet(movie: Movie, person: Person) { + private fun openPersonSheet(movie: Movie, person: Person, personArgs: PersonDetailsArgs?) { handleSheetResult() - val bundle = PersonDetailsBottomSheet.createBundle(person, movie.ids.trakt) + val bundle = PersonDetailsBottomSheet.createBundle(person, movie.ids.trakt, personArgs) (requireParentFragment() as BaseFragment<*>) .navigateToSafe(R.id.actionMovieDetailsFragmentToPerson, bundle) } @@ -141,7 +143,7 @@ class MovieDetailsPeopleFragment : BaseFragment(R.l private fun handleEvent(event: Event<*>) { when (event) { - is OpenPersonSheet -> openPersonSheet(event.movie, event.person) + is OpenPersonSheet -> openPersonSheet(event.movie, event.person, event.personArgs) is OpenPeopleSheet -> openPeopleSheet(event) } } @@ -150,8 +152,10 @@ class MovieDetailsPeopleFragment : BaseFragment(R.l private fun handleSheetResult() { requireParentFragment() .setFragmentResultListener(REQUEST_DETAILS) { _, bundle -> - bundle.getParcelable(ARG_PERSON)?.let { - viewModel.saveLastPerson(it) + val person = bundle.getParcelable(ARG_PERSON) + val personArgs = bundle.getParcelable(ARG_PERSON_ARGS) + person?.let { + viewModel.saveLastPerson(it, personArgs) bundle.clear() } requireParentFragment().clearFragmentResultListener(REQUEST_DETAILS) diff --git a/ui-movie/src/main/java/com/michaldrabik/ui_movie/sections/people/MovieDetailsPeopleViewModel.kt b/ui-movie/src/main/java/com/michaldrabik/ui_movie/sections/people/MovieDetailsPeopleViewModel.kt index f0f792c95..d6687b983 100644 --- a/ui-movie/src/main/java/com/michaldrabik/ui_movie/sections/people/MovieDetailsPeopleViewModel.kt +++ b/ui-movie/src/main/java/com/michaldrabik/ui_movie/sections/people/MovieDetailsPeopleViewModel.kt @@ -12,6 +12,7 @@ import com.michaldrabik.ui_model.Person.Department import com.michaldrabik.ui_movie.MovieDetailsEvent.OpenPeopleSheet import com.michaldrabik.ui_movie.MovieDetailsEvent.OpenPersonSheet import com.michaldrabik.ui_movie.sections.people.cases.MovieDetailsPeopleCase +import com.michaldrabik.ui_people.details.PersonDetailsArgs import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted @@ -27,7 +28,9 @@ class MovieDetailsPeopleViewModel @Inject constructor( ) : ViewModel(), ChannelsDelegate by DefaultChannelsDelegate() { private lateinit var movie: Movie + private var lastOpenedPerson: Person? = null + private var lastOpenedPersonArgs: PersonDetailsArgs? = null private val loadingState = MutableStateFlow(true) private val actorsState = MutableStateFlow?>(null) @@ -59,9 +62,12 @@ class MovieDetailsPeopleViewModel @Inject constructor( Timber.d("Loading people...") } - fun loadPersonDetails(person: Person) { + fun loadPersonDetails( + person: Person, + personArgs: PersonDetailsArgs? = null, + ) { viewModelScope.launch { - eventChannel.send(OpenPersonSheet(movie, person)) + eventChannel.send(OpenPersonSheet(movie, person, personArgs)) } } @@ -73,13 +79,18 @@ class MovieDetailsPeopleViewModel @Inject constructor( fun loadLastPerson() { lastOpenedPerson?.let { - loadPersonDetails(it) + loadPersonDetails(it, lastOpenedPersonArgs) lastOpenedPerson = null + lastOpenedPersonArgs = null } } - fun saveLastPerson(person: Person) { + fun saveLastPerson( + person: Person, + personArgs: PersonDetailsArgs?, + ) { lastOpenedPerson = person + lastOpenedPersonArgs = personArgs } val uiState = combine( diff --git a/ui-navigation/src/main/java/com.michaldrabik.ui_navigation.java/NavigationArgs.kt b/ui-navigation/src/main/java/com.michaldrabik.ui_navigation.java/NavigationArgs.kt index 4046238da..4de1d982f 100644 --- a/ui-navigation/src/main/java/com.michaldrabik.ui_navigation.java/NavigationArgs.kt +++ b/ui-navigation/src/main/java/com.michaldrabik.ui_navigation.java/NavigationArgs.kt @@ -8,6 +8,7 @@ object NavigationArgs { const val ARG_COMMENT_ID = "ARG_COMMENT_ID" const val ARG_COLLECTION_ID = "ARG_COLLECTION_ID" const val ARG_PERSON = "ARG_PERSON" + const val ARG_PERSON_ARGS = "ARG_PERSON_ARGS" const val ARG_OPTIONS = "ARG_OPTIONS" const val ARG_TITLE = "ARG_TITLE" const val ARG_ITEM = "ARG_ITEM" diff --git a/ui-people/src/main/java/com/michaldrabik/ui_people/details/PersonDetailsArgs.kt b/ui-people/src/main/java/com/michaldrabik/ui_people/details/PersonDetailsArgs.kt new file mode 100644 index 000000000..14ddec069 --- /dev/null +++ b/ui-people/src/main/java/com/michaldrabik/ui_people/details/PersonDetailsArgs.kt @@ -0,0 +1,11 @@ +package com.michaldrabik.ui_people.details + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize +data class PersonDetailsArgs( + val isExpanded: Boolean = false, + val firstVisibleItemPosition: Int = 0, + val isUpButtonVisible: Boolean = false +) : Parcelable diff --git a/ui-people/src/main/java/com/michaldrabik/ui_people/details/PersonDetailsBottomSheet.kt b/ui-people/src/main/java/com/michaldrabik/ui_people/details/PersonDetailsBottomSheet.kt index e7fe8faff..54d81d1bf 100644 --- a/ui-people/src/main/java/com/michaldrabik/ui_people/details/PersonDetailsBottomSheet.kt +++ b/ui-people/src/main/java/com/michaldrabik/ui_people/details/PersonDetailsBottomSheet.kt @@ -4,6 +4,7 @@ import android.annotation.SuppressLint import android.os.Bundle import android.view.View import androidx.core.os.bundleOf +import androidx.core.view.isVisible import androidx.fragment.app.setFragmentResult import androidx.fragment.app.viewModels import androidx.navigation.fragment.findNavController @@ -16,6 +17,7 @@ import com.google.android.material.snackbar.Snackbar import com.michaldrabik.ui_base.BaseBottomSheetFragment import com.michaldrabik.ui_base.common.FastLinearLayoutManager import com.michaldrabik.ui_base.utilities.TipsHost +import com.michaldrabik.ui_base.utilities.events.Event import com.michaldrabik.ui_base.utilities.events.MessageEvent import com.michaldrabik.ui_base.utilities.extensions.fadeIn import com.michaldrabik.ui_base.utilities.extensions.fadeOut @@ -32,9 +34,11 @@ import com.michaldrabik.ui_model.Tip import com.michaldrabik.ui_navigation.java.NavigationArgs import com.michaldrabik.ui_navigation.java.NavigationArgs.ARG_ID import com.michaldrabik.ui_navigation.java.NavigationArgs.ARG_PERSON +import com.michaldrabik.ui_navigation.java.NavigationArgs.ARG_PERSON_ARGS import com.michaldrabik.ui_navigation.java.NavigationArgs.REQUEST_DETAILS import com.michaldrabik.ui_people.R import com.michaldrabik.ui_people.databinding.ViewPersonDetailsBinding +import com.michaldrabik.ui_people.details.PersonDetailsUiEvent.ScrollToPosition import com.michaldrabik.ui_people.details.links.PersonLinksBottomSheet import com.michaldrabik.ui_people.details.recycler.PersonDetailsAdapter import com.michaldrabik.ui_people.details.recycler.PersonDetailsItem @@ -47,16 +51,23 @@ class PersonDetailsBottomSheet : BaseBottomSheetFragment(R.layout.view_person_de companion object { const val SHOW_BACK_UP_BUTTON_THRESHOLD = 25 - fun createBundle(person: Person, sourceId: IdTrakt) = - bundleOf( + fun createBundle( + person: Person, + sourceId: IdTrakt, + personArgs: PersonDetailsArgs?, + ): Bundle { + return bundleOf( ARG_PERSON to person, + ARG_PERSON_ARGS to (personArgs ?: PersonDetailsArgs()), ARG_ID to sourceId ) + } } private val viewModel by viewModels() private val binding by viewBinding(ViewPersonDetailsBinding::bind) + private val personArgs by lazy { requireParcelable(ARG_PERSON_ARGS) } private val person by lazy { requireParcelable(ARG_PERSON) } private val sourceId by lazy { requireParcelable(ARG_ID) } @@ -72,8 +83,9 @@ class PersonDetailsBottomSheet : BaseBottomSheetFragment(R.layout.view_person_de launchAndRepeatStarted( { viewModel.uiState.collect { render(it) } }, + { viewModel.eventFlow.collect { handleEvent(it) } }, { viewModel.messageFlow.collect { renderSnackbar(it) } }, - doAfterLaunch = { viewModel.loadDetails(person) } + doAfterLaunch = { viewModel.loadDetails(person, personArgs) } ) } @@ -110,7 +122,7 @@ class PersonDetailsBottomSheet : BaseBottomSheetFragment(R.layout.view_person_de onImageClickListener = { openGallery() }, onImageMissingListener = { item, force -> viewModel.loadMissingImage(item, force) }, onTranslationMissingListener = { item -> viewModel.loadMissingTranslation(item) }, - onFiltersChangeListener = { filters -> viewModel.loadCredits(person, filters) } + onFiltersChangeListener = { filters -> viewModel.loadCredits(person, null, filters) } ) with(binding.personDetailsRecycler) { adapter = this@PersonDetailsBottomSheet.adapter @@ -122,7 +134,14 @@ class PersonDetailsBottomSheet : BaseBottomSheetFragment(R.layout.view_person_de } private fun openDetails(item: PersonDetailsItem) { - val personBundle = bundleOf(ARG_PERSON to person) + val personBundle = bundleOf( + ARG_PERSON to person, + ARG_PERSON_ARGS to PersonDetailsArgs( + isExpanded = isSheetExpanded(), + isUpButtonVisible = binding.personDetailsRecyclerFab.isVisible, + firstVisibleItemPosition = (layoutManager?.findLastVisibleItemPosition() ?: 0) + ), + ) if (item is PersonDetailsItem.CreditsShowItem && item.show.traktId != sourceId.id) { setFragmentResult(REQUEST_DETAILS, personBundle) val bundle = bundleOf(NavigationArgs.ARG_SHOW_ID to item.show.traktId) @@ -167,6 +186,20 @@ class PersonDetailsBottomSheet : BaseBottomSheetFragment(R.layout.view_person_de } } + private fun handleEvent(event: Event<*>) { + when (event) { + is ScrollToPosition -> { + if (event.isSheetExpanded) expandSheet() + with(binding) { + if (event.isUpButtonVisible) personDetailsRecyclerFab.fadeIn(150) + personDetailsRecycler.postDelayed({ + personDetailsRecycler.scrollToPosition(event.position) + }, 100) + } + } + } + } + override fun onDestroyView() { adapter = null layoutManager = null diff --git a/ui-people/src/main/java/com/michaldrabik/ui_people/details/PersonDetailsUiEvent.kt b/ui-people/src/main/java/com/michaldrabik/ui_people/details/PersonDetailsUiEvent.kt new file mode 100644 index 000000000..4fb8cf063 --- /dev/null +++ b/ui-people/src/main/java/com/michaldrabik/ui_people/details/PersonDetailsUiEvent.kt @@ -0,0 +1,12 @@ +// ktlint-disable filename +package com.michaldrabik.ui_people.details + +import com.michaldrabik.ui_base.utilities.events.Event + +internal sealed class PersonDetailsUiEvent(action: T) : Event(action) { + data class ScrollToPosition( + val position: Int, + val isSheetExpanded: Boolean, + val isUpButtonVisible: Boolean + ) : PersonDetailsUiEvent(position) +} diff --git a/ui-people/src/main/java/com/michaldrabik/ui_people/details/PersonDetailsViewModel.kt b/ui-people/src/main/java/com/michaldrabik/ui_people/details/PersonDetailsViewModel.kt index 6119ddbe1..32b006e88 100644 --- a/ui-people/src/main/java/com/michaldrabik/ui_people/details/PersonDetailsViewModel.kt +++ b/ui-people/src/main/java/com/michaldrabik/ui_people/details/PersonDetailsViewModel.kt @@ -48,7 +48,7 @@ class PersonDetailsViewModel @Inject constructor( private var imagesJobs = mutableMapOf() private var translationsJobs = mutableMapOf() - fun loadDetails(person: Person) { + fun loadDetails(person: Person, personArgs: PersonDetailsArgs) { viewModelScope.launch { mainProgressJob = launchDelayed(750) { setMainLoading(true) } try { @@ -67,7 +67,7 @@ class PersonDetailsViewModel @Inject constructor( } mainProgressJob?.cancelAndJoin() - loadCredits(details) + loadCredits(details, personArgs) } catch (error: Throwable) { messageChannel.send(MessageEvent.Error(R.string.errorGeneral)) Timber.e(error) @@ -78,7 +78,11 @@ class PersonDetailsViewModel @Inject constructor( } } - fun loadCredits(person: Person, filters: List = emptyList()) { + fun loadCredits( + person: Person, + personArgs: PersonDetailsArgs?, + filters: List = emptyList(), + ) { creditsJob?.cancel() creditsJob = viewModelScope.launch { creditsProgressJob = launchDelayed(500) { setCreditsLoading(true) } @@ -100,7 +104,18 @@ class PersonDetailsViewModel @Inject constructor( currentValue.add(PersonDetailsItem.CreditsHeader(year)) currentValue.addAll(credit) } + personDetailsItemsState.value = currentValue + + personArgs?.let { + eventChannel.send( + PersonDetailsUiEvent.ScrollToPosition( + position = it.firstVisibleItemPosition, + isSheetExpanded = it.isExpanded, + isUpButtonVisible = it.isUpButtonVisible + ) + ) + } } } catch (error: Throwable) { messageChannel.send(MessageEvent.Error(R.string.errorGeneral)) diff --git a/ui-people/src/main/java/com/michaldrabik/ui_people/list/PeopleListBottomSheet.kt b/ui-people/src/main/java/com/michaldrabik/ui_people/list/PeopleListBottomSheet.kt index a47d11fe5..b15d0982b 100644 --- a/ui-people/src/main/java/com/michaldrabik/ui_people/list/PeopleListBottomSheet.kt +++ b/ui-people/src/main/java/com/michaldrabik/ui_people/list/PeopleListBottomSheet.kt @@ -41,7 +41,7 @@ class PeopleListBottomSheet : BaseBottomSheetFragment(R.layout.view_people_list) mediaIdTrakt: IdTrakt, mediaTitle: String, mode: Mode, - department: Person.Department + department: Person.Department, ) = bundleOf( ARG_ID to mediaIdTrakt.id, ARG_TITLE to mediaTitle, @@ -103,7 +103,7 @@ class PeopleListBottomSheet : BaseBottomSheetFragment(R.layout.view_people_list) private fun openDetails(item: Person) { setFragmentResult(REQUEST_DETAILS, bundleOf(ARG_PERSON to item)) - val bundle = PersonDetailsBottomSheet.createBundle(item, mediaIdTrakt) + val bundle = PersonDetailsBottomSheet.createBundle(item, mediaIdTrakt, null) findNavController().navigate(R.id.actionPeopleListDialogToDetails, bundle) } diff --git a/ui-search/src/main/java/com/michaldrabik/ui_search/SearchFragment.kt b/ui-search/src/main/java/com/michaldrabik/ui_search/SearchFragment.kt index d7676da82..b47dfb952 100644 --- a/ui-search/src/main/java/com/michaldrabik/ui_search/SearchFragment.kt +++ b/ui-search/src/main/java/com/michaldrabik/ui_search/SearchFragment.kt @@ -3,6 +3,7 @@ package com.michaldrabik.ui_search import android.graphics.drawable.Animatable import android.os.Bundle import android.text.Editable +import android.view.KeyEvent import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -133,7 +134,9 @@ class SearchFragment : BaseFragment(R.layout.fragment_search), searchViewLayout.binding.searchViewText.gone() (searchViewLayout.binding.searchViewIcon.drawable as Animatable).start() searchViewLayout.settingsIconVisible = false + viewModel.preloadSuggestions() + if (!isInitialized) { searchViewLayout.binding.searchViewInput.showKeyboard() searchViewLayout.binding.searchViewInput.requestFocus() @@ -145,21 +148,24 @@ class SearchFragment : BaseFragment(R.layout.fragment_search), setOnEditorActionListener { textView, id, _ -> if (id == EditorInfo.IME_ACTION_SEARCH) { val query = textView.text.toString() - if (query.trim().isBlank()) { - searchViewLayout.shake() - return@setOnEditorActionListener true - } - viewModel.search(query) - searchViewLayout.binding.searchViewInput.hideKeyboard() - searchViewLayout.binding.searchViewInput.clearFocus() + return@setOnEditorActionListener onSearchQuery(query) } true } + setOnKeyListener { _, keyCode, keyEvent -> + if (keyEvent.action == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_ENTER) { + val query = text.toString() + return@setOnKeyListener onSearchQuery(query) + } + false + } } + searchViewLayout.binding.searchViewIcon.onClick { searchViewLayout.binding.searchViewInput.hideKeyboard() requireActivity().onBackPressed() } + with(searchFiltersView) { onChipsChangeListener = viewModel::setFilters onSortClickListener = ::openSortingDialog @@ -229,6 +235,19 @@ class SearchFragment : BaseFragment(R.layout.fragment_search), } } + private fun onSearchQuery(query: String): Boolean { + with(binding) { + if (query.trim().isBlank()) { + searchViewLayout.shake() + return true + } + viewModel.search(query) + searchViewLayout.binding.searchViewInput.hideKeyboard() + searchViewLayout.binding.searchViewInput.clearFocus() + return true + } + } + private fun openSortingDialog(order: SortOrder, type: SortType) { val options = listOf(SortOrder.RANK, SortOrder.NAME, SortOrder.NEWEST) val args = SortOrderBottomSheet.createBundle(options, order, type) diff --git a/ui-show/src/main/java/com/michaldrabik/ui_show/ShowDetailsUiEvents.kt b/ui-show/src/main/java/com/michaldrabik/ui_show/ShowDetailsUiEvents.kt index c8afafafd..3d320b8fc 100644 --- a/ui-show/src/main/java/com/michaldrabik/ui_show/ShowDetailsUiEvents.kt +++ b/ui-show/src/main/java/com/michaldrabik/ui_show/ShowDetailsUiEvents.kt @@ -7,31 +7,29 @@ import com.michaldrabik.ui_base.utilities.events.Event import com.michaldrabik.ui_model.IdTrakt import com.michaldrabik.ui_model.Person import com.michaldrabik.ui_model.Show +import com.michaldrabik.ui_people.details.PersonDetailsArgs sealed class ShowDetailsEvent(action: T) : Event(action) { data class OpenPersonSheet( val show: Show, - val person: Person + val person: Person, + val personArgs: PersonDetailsArgs?, ) : ShowDetailsEvent(show) data class OpenPeopleSheet( val show: Show, val people: List, - val department: Person.Department + val department: Person.Department, ) : ShowDetailsEvent(show) data class RemoveFromTrakt( @IdRes val actionId: Int, val mode: RemoveTraktBottomSheet.Mode, - val traktIds: List + val traktIds: List, ) : ShowDetailsEvent(actionId) - data class SaveOpenedPerson( - val person: Person - ) : ShowDetailsEvent(person) + data object RefreshSeasons : ShowDetailsEvent(Unit) - object RefreshSeasons : ShowDetailsEvent(Unit) - - object Finish : ShowDetailsEvent(Unit) + data object Finish : ShowDetailsEvent(Unit) } diff --git a/ui-show/src/main/java/com/michaldrabik/ui_show/sections/people/ShowDetailsPeopleFragment.kt b/ui-show/src/main/java/com/michaldrabik/ui_show/sections/people/ShowDetailsPeopleFragment.kt index 30c0080c9..82403662a 100644 --- a/ui-show/src/main/java/com/michaldrabik/ui_show/sections/people/ShowDetailsPeopleFragment.kt +++ b/ui-show/src/main/java/com/michaldrabik/ui_show/sections/people/ShowDetailsPeopleFragment.kt @@ -21,7 +21,9 @@ import com.michaldrabik.ui_model.Person import com.michaldrabik.ui_model.Person.Department import com.michaldrabik.ui_model.Show import com.michaldrabik.ui_navigation.java.NavigationArgs.ARG_PERSON +import com.michaldrabik.ui_navigation.java.NavigationArgs.ARG_PERSON_ARGS import com.michaldrabik.ui_navigation.java.NavigationArgs.REQUEST_DETAILS +import com.michaldrabik.ui_people.details.PersonDetailsArgs import com.michaldrabik.ui_people.details.PersonDetailsBottomSheet import com.michaldrabik.ui_people.list.PeopleListBottomSheet import com.michaldrabik.ui_show.R @@ -67,9 +69,9 @@ class ShowDetailsPeopleFragment : BaseFragment(R.lay } } - private fun openPersonSheet(show: Show, person: Person) { + private fun openPersonSheet(show: Show, person: Person, personArgs: PersonDetailsArgs?) { handleSheetResult() - val bundle = PersonDetailsBottomSheet.createBundle(person, show.ids.trakt) + val bundle = PersonDetailsBottomSheet.createBundle(person, show.ids.trakt, personArgs) (requireParentFragment() as BaseFragment<*>) .navigateToSafe(R.id.actionShowDetailsFragmentToPerson, bundle) } @@ -139,7 +141,7 @@ class ShowDetailsPeopleFragment : BaseFragment(R.lay private fun handleEvent(event: Event<*>) { when (event) { - is OpenPersonSheet -> openPersonSheet(event.show, event.person) + is OpenPersonSheet -> openPersonSheet(event.show, event.person, event.personArgs) is OpenPeopleSheet -> openPeopleSheet(event) } } @@ -148,8 +150,10 @@ class ShowDetailsPeopleFragment : BaseFragment(R.lay private fun handleSheetResult() { requireParentFragment() .setFragmentResultListener(REQUEST_DETAILS) { _, bundle -> - bundle.getParcelable(ARG_PERSON)?.let { - viewModel.saveLastPerson(it) + val person = bundle.getParcelable(ARG_PERSON) + val personArgs = bundle.getParcelable(ARG_PERSON_ARGS) + person?.let { + viewModel.saveLastPerson(it, personArgs) bundle.clear() } requireParentFragment().clearFragmentResultListener(REQUEST_DETAILS) diff --git a/ui-show/src/main/java/com/michaldrabik/ui_show/sections/people/ShowDetailsPeopleViewModel.kt b/ui-show/src/main/java/com/michaldrabik/ui_show/sections/people/ShowDetailsPeopleViewModel.kt index 57bb0a112..055a3a8bd 100644 --- a/ui-show/src/main/java/com/michaldrabik/ui_show/sections/people/ShowDetailsPeopleViewModel.kt +++ b/ui-show/src/main/java/com/michaldrabik/ui_show/sections/people/ShowDetailsPeopleViewModel.kt @@ -9,6 +9,7 @@ import com.michaldrabik.ui_base.viewmodel.DefaultChannelsDelegate import com.michaldrabik.ui_model.Person import com.michaldrabik.ui_model.Person.Department import com.michaldrabik.ui_model.Show +import com.michaldrabik.ui_people.details.PersonDetailsArgs import com.michaldrabik.ui_show.ShowDetailsEvent import com.michaldrabik.ui_show.sections.people.cases.ShowDetailsPeopleCase import dagger.hilt.android.lifecycle.HiltViewModel @@ -26,7 +27,9 @@ class ShowDetailsPeopleViewModel @Inject constructor( ) : ViewModel(), ChannelsDelegate by DefaultChannelsDelegate() { private lateinit var show: Show + private var lastOpenedPerson: Person? = null + private var lastOpenedPersonArgs: PersonDetailsArgs? = null private val loadingState = MutableStateFlow(true) private val actorsState = MutableStateFlow?>(null) @@ -58,9 +61,12 @@ class ShowDetailsPeopleViewModel @Inject constructor( Timber.d("Loading people...") } - fun loadPersonDetails(person: Person) { + fun loadPersonDetails( + person: Person, + personArgs: PersonDetailsArgs? = null, + ) { viewModelScope.launch { - eventChannel.send(ShowDetailsEvent.OpenPersonSheet(show, person)) + eventChannel.send(ShowDetailsEvent.OpenPersonSheet(show, person, personArgs)) } } @@ -72,13 +78,18 @@ class ShowDetailsPeopleViewModel @Inject constructor( fun loadLastPerson() { lastOpenedPerson?.let { - loadPersonDetails(it) + loadPersonDetails(it, lastOpenedPersonArgs) lastOpenedPerson = null + lastOpenedPersonArgs = null } } - fun saveLastPerson(person: Person) { + fun saveLastPerson( + person: Person, + personArgs: PersonDetailsArgs?, + ) { lastOpenedPerson = person + lastOpenedPersonArgs = personArgs } val uiState = combine( diff --git a/versions.gradle b/versions.gradle index cb2f32995..2d0780754 100644 --- a/versions.gradle +++ b/versions.gradle @@ -1,6 +1,6 @@ ext.versions = [ - versionCode: 623, - versionName: '3.27.1', + versionCode: 625, + versionName: '3.28.0', minSdk : 21, compileSdk : 33,