Skip to content

Commit

Permalink
Merge pull request #339 from boostcampwm2023/android/hotfix/338
Browse files Browse the repository at this point in the history
QA에서 발견한 버그 개선 및 MyPage -> Player 이동
  • Loading branch information
2taezeat authored Dec 14, 2023
2 parents cb03639 + baaf753 commit 72c421b
Show file tree
Hide file tree
Showing 16 changed files with 119 additions and 29 deletions.
6 changes: 4 additions & 2 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
android:usesCleartextTraffic="true">
<activity
android:name=".feature.login.LoginActivity"
android:exported="true">
android:exported="true"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

Expand All @@ -25,7 +26,8 @@

<activity
android:name=".MainActivity"
android:exported="true" />
android:exported="true"
android:screenOrientation="portrait" />

<service
android:name=".mediasession.PlaybackService"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.ohdodok.catchytape.core.domain.utils

import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow

fun <T> Flow<T>.throttleFirst(windowDuration: Long): Flow<T> = flow {
var lastEmissionTime = 0L
collect { upstream ->
val currentTime = System.currentTimeMillis()
if (currentTime - lastEmissionTime > windowDuration) {
lastEmissionTime = currentTime
emit(upstream)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ abstract class BaseFragment<VB : ViewDataBinding>(
_binding = null
}

protected fun setupBackStack(toolbar: MaterialToolbar){
protected fun setupBackStack(toolbar: MaterialToolbar) {
toolbar.setNavigationOnClickListener {
findNavController().popBackStack()
}
Expand All @@ -56,5 +56,4 @@ abstract class BaseFragment<VB : ViewDataBinding>(
protected fun showMessage(@StringRes messageId: Int) {
Snackbar.make(this.requireView(), messageId, Snackbar.LENGTH_LONG).show()
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.ohdodok.catchytape.core.ui

import android.view.View
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow

fun View.clicksFlow(): Flow<Unit> = callbackFlow {
setOnClickListener { trySend(Unit) }
awaitClose { setOnClickListener(null) }
}
5 changes: 2 additions & 3 deletions android/core/ui/src/main/res/layout/bottom_sheet_playlist.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@
xmlns:tools="http://schemas.android.com/tools">

<data>

<variable
name="viewModel"
type="com.ohdodok.catchytape.core.ui.PlaylistBottomSheetViewModel" />
</data>

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="match_parent"
android:background="@color/surface_bright">

<TextView
Expand Down Expand Up @@ -43,11 +44,9 @@
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:maxHeight="400dp"
android:orientation="vertical"
android:paddingHorizontal="@dimen/margin_horizontal"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/divider"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,5 @@ private fun NavController.navigateToPlayerScreen() {
NavDeepLinkRequest.Builder.fromUri("android-app://com.ohdodok.catchytape/player_fragment".toUri())
.build()

this.navigate(request)
navigate(request)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ package com.ohdodok.catchytape.feature.mypage

import android.os.Bundle
import android.view.View
import androidx.core.net.toUri
import androidx.core.view.ViewCompat
import androidx.fragment.app.viewModels
import androidx.navigation.NavController
import androidx.navigation.NavDeepLinkRequest
import androidx.navigation.fragment.findNavController
import com.ohdodok.catchytape.core.ui.BaseFragment
import com.ohdodok.catchytape.core.ui.MusicAdapter
import com.ohdodok.catchytape.core.ui.Orientation
Expand All @@ -28,7 +32,10 @@ class MyMusicsFragment : BaseFragment<FragmentMyMusicsBinding>(R.layout.fragment
}

private fun setupRecyclerView() {
binding.rvMyMusics.adapter = MusicAdapter(Orientation.VERTICAL)
binding.rvMyMusics.adapter = MusicAdapter(
musicItemOrientation = Orientation.VERTICAL,
listener = viewModel
)
}

private fun observeEvents() {
Expand All @@ -38,8 +45,17 @@ class MyMusicsFragment : BaseFragment<FragmentMyMusicsBinding>(R.layout.fragment
is MyMusicsEvent.ShowMessage -> {
showMessage(event.error.toMessageId())
}
is MyMusicsEvent.NavigateToPlayerScreen -> {
findNavController().navigateToPlayerScreen()
}
}
}
}
}
}

private fun NavController.navigateToPlayerScreen() {
val request =
NavDeepLinkRequest.Builder.fromUri("android-app://com.ohdodok.catchytape/player_fragment".toUri()).build()
navigate(request)
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import com.ohdodok.catchytape.core.domain.model.CtErrorType
import com.ohdodok.catchytape.core.domain.model.CtException
import com.ohdodok.catchytape.core.domain.model.Music
import com.ohdodok.catchytape.core.domain.repository.MusicRepository
import com.ohdodok.catchytape.core.domain.usecase.player.CurrentPlaylistUseCase
import com.ohdodok.catchytape.core.ui.MusicAdapter
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.flow.MutableSharedFlow
Expand All @@ -29,12 +31,14 @@ sealed interface MyMusicsEvent {
data class ShowMessage(
val error: CtErrorType
) : MyMusicsEvent
data object NavigateToPlayerScreen : MyMusicsEvent
}

@HiltViewModel
class MyMusicsViewModel @Inject constructor(
private val musicRepository: MusicRepository,
) : ViewModel() {
private val currentPlaylistUseCase: CurrentPlaylistUseCase,
) : ViewModel(), MusicAdapter.Listener {

private val _uiState = MutableStateFlow(MyMusicsUiState())
val uiState: StateFlow<MyMusicsUiState> = _uiState.asStateFlow()
Expand Down Expand Up @@ -67,4 +71,11 @@ class MyMusicsViewModel @Inject constructor(
}
.launchIn(viewModelScopeWithExceptionHandler)
}

override fun onClick(music: Music) {
currentPlaylistUseCase.playMusic(music)
viewModelScope.launch {
_events.emit(MyMusicsEvent.NavigateToPlayerScreen)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.view.View
import androidx.core.net.toUri
import androidx.core.view.ViewCompat
import androidx.fragment.app.viewModels
import androidx.navigation.NavController
import androidx.navigation.NavDeepLinkRequest
import androidx.navigation.fragment.findNavController
import com.ohdodok.catchytape.core.ui.BaseFragment
Expand Down Expand Up @@ -37,6 +38,9 @@ class MyPageFragment : BaseFragment<FragmentMyPageBinding>(R.layout.fragment_my_
is MyPageEvent.ShowMessage -> {
showMessage(event.error.toMessageId())
}
is MyPageEvent.NavigateToPlayerScreen -> {
findNavController().navigateToPlayerScreen()
}
}
}
}
Expand All @@ -56,11 +60,20 @@ class MyPageFragment : BaseFragment<FragmentMyPageBinding>(R.layout.fragment_my_
}

private fun setupRecyclerView() {
binding.rvMusics.adapter = MusicAdapter(Orientation.VERTICAL)
binding.rvMusics.adapter = MusicAdapter(
musicItemOrientation = Orientation.VERTICAL,
listener = viewModel
)
}

override fun onStart() {
super.onStart()
viewModel.fetchMyMusics(count = 3)
}
}

private fun NavController.navigateToPlayerScreen() {
val request =
NavDeepLinkRequest.Builder.fromUri("android-app://com.ohdodok.catchytape/player_fragment".toUri()).build()
navigate(request)
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import com.ohdodok.catchytape.core.domain.model.CtErrorType
import com.ohdodok.catchytape.core.domain.model.CtException
import com.ohdodok.catchytape.core.domain.model.Music
import com.ohdodok.catchytape.core.domain.repository.MusicRepository
import com.ohdodok.catchytape.core.domain.usecase.player.CurrentPlaylistUseCase
import com.ohdodok.catchytape.core.ui.MusicAdapter
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.flow.MutableSharedFlow
Expand All @@ -28,7 +30,8 @@ data class MyPageUiState(
@HiltViewModel
class MyPageViewModel @Inject constructor(
private val musicRepository: MusicRepository,
) : ViewModel() {
private val currentPlaylistUseCase: CurrentPlaylistUseCase,
) : ViewModel(), MusicAdapter.Listener {

private val _uiState = MutableStateFlow(MyPageUiState())
val uiState: StateFlow<MyPageUiState> = _uiState.asStateFlow()
Expand All @@ -55,8 +58,16 @@ class MyPageViewModel @Inject constructor(
}
.launchIn(viewModelScopeWithExceptionHandler)
}

override fun onClick(music: Music) {
currentPlaylistUseCase.playMusic(music)
viewModelScope.launch {
_events.emit(MyPageEvent.NavigateToPlayerScreen)
}
}
}

sealed interface MyPageEvent {
data class ShowMessage(val error: CtErrorType) : MyPageEvent
data object NavigateToPlayerScreen : MyPageEvent
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@ import android.view.View
import android.widget.SeekBar
import androidx.core.view.ViewCompat
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.lifecycleScope
import androidx.media3.exoplayer.ExoPlayer
import androidx.navigation.NavController
import androidx.navigation.fragment.findNavController
import com.ohdodok.catchytape.core.domain.utils.throttleFirst
import com.ohdodok.catchytape.core.ui.BaseFragment
import com.ohdodok.catchytape.core.ui.RootViewInsetsCallback
import com.ohdodok.catchytape.core.ui.clicksFlow
import com.ohdodok.catchytape.feature.player.databinding.FragmentPlayerBinding
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import javax.inject.Inject

const val millisecondsPerSecond = 1000
Expand Down Expand Up @@ -67,19 +72,20 @@ class PlayerFragment : BaseFragment<FragmentPlayerBinding>(R.layout.fragment_pla
player.onPreviousBtnClick()
}

binding.btnAddToPlaylist.setOnClickListener {
findNavController().showPlaylistBottomSheet()
}
binding.btnAddToPlaylist.clicksFlow()
.throttleFirst(500)
.onEach { findNavController().showPlaylistBottomSheet() }
.launchIn(viewLifecycleOwner.lifecycleScope)
}

private fun NavController.showPlaylistBottomSheet() {
val musicId = viewModel.uiState.value.currentMusic?.id ?: return

val action = PlayerFragmentDirections.actionPlayerFragmentToPlaylistBottomSheet(musicId = musicId)
this.navigate(action)
navigate(action)
}
}

fun NavController.navigateToPlayer() {
this.navigate(R.id.player_nav_graph)
navigate(R.id.player_nav_graph)
}

Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.ohdodok.catchytape.feature.player

import androidx.lifecycle.ViewModel

import androidx.lifecycle.viewModelScope
import com.ohdodok.catchytape.core.domain.model.CtErrorType
import com.ohdodok.catchytape.core.domain.model.CtException
Expand Down Expand Up @@ -28,7 +29,6 @@ data class PlayerState(
val duration: Int = 0,
val isNextEnable: Boolean = false,
val isPreviousEnable: Boolean = false

) {
val isPlayEnable: Boolean
get() = currentMusic != null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,5 @@ private fun NavController.navigateToPlayerScreen() {
val targetUri = "android-app://com.ohdodok.catchytape/player_fragment".toUri()
val request = NavDeepLinkRequest.Builder.fromUri(targetUri).build()

this.navigate(request)
navigate(request)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,19 @@ import android.view.View
import androidx.core.view.ViewCompat
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavController
import androidx.navigation.fragment.findNavController
import com.ohdodok.catchytape.core.domain.utils.throttleFirst
import com.ohdodok.catchytape.core.ui.BaseFragment
import com.ohdodok.catchytape.core.ui.PlaylistAdapter
import com.ohdodok.catchytape.core.ui.RootViewInsetsCallback
import com.ohdodok.catchytape.core.ui.clicksFlow
import com.ohdodok.catchytape.core.ui.cterror.toMessageId
import com.ohdodok.catchytape.feature.playlist.databinding.FragmentPlaylistsBinding
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach

@AndroidEntryPoint
class PlaylistsFragment : BaseFragment<FragmentPlaylistsBinding>(R.layout.fragment_playlists),
Expand All @@ -28,11 +33,15 @@ class PlaylistsFragment : BaseFragment<FragmentPlaylistsBinding>(R.layout.fragme
viewModel.fetchPlaylists()

observeEvents()
val newPlaylistDialog = NewPlaylistDialog()
binding.fabNewPlaylist.setOnClickListener {
newPlaylistDialog.show(childFragmentManager, NewPlaylistDialog.TAG)
}
setupButton()
}

private fun setupButton() {
val newPlaylistDialog = NewPlaylistDialog()
binding.fabNewPlaylist.clicksFlow()
.throttleFirst(500)
.onEach { newPlaylistDialog.show(childFragmentManager, NewPlaylistDialog.TAG) }
.launchIn(viewLifecycleOwner.lifecycleScope)
}

private fun observeEvents() {
Expand Down
Loading

0 comments on commit 72c421b

Please sign in to comment.