Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QA에서 발견한 버그 개선 및 MyPage -> Player 이동 #339

Merged
merged 14 commits into from
Dec 14, 2023
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,21 @@
package com.ohdodok.catchytape.core.domain.utils

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

fun <T> Flow<T>.throttleFist(windowDuration: Long): Flow<T> = flow {
HamBP marked this conversation as resolved.
Show resolved Hide resolved
var windowStartTime = System.currentTimeMillis()
var emitted = false
collect { value ->
val currentTime = System.currentTimeMillis()
val delta = currentTime - windowStartTime
if (delta >= windowDuration) {
windowStartTime += delta / windowDuration * windowDuration
emitted = false
}
if (!emitted) {
emit(value)
emitted = true
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import androidx.navigation.fragment.findNavController
import com.google.android.material.appbar.MaterialToolbar
import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.launch

abstract class BaseFragment<VB : ViewDataBinding>(
Expand All @@ -41,7 +44,7 @@ abstract class BaseFragment<VB : ViewDataBinding>(
_binding = null
}

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

protected fun clicksFlow(view: View): Flow<Unit> = callbackFlow {
view.setOnClickListener { trySend(Unit) }
awaitClose { view.setOnClickListener(null) }
}

}
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 @@ -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,17 @@ 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.throttleFist
import com.ohdodok.catchytape.core.ui.BaseFragment
import com.ohdodok.catchytape.core.ui.RootViewInsetsCallback
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 @@ -68,18 +72,21 @@ class PlayerFragment : BaseFragment<FragmentPlayerBinding>(R.layout.fragment_pla
}

binding.btnAddToPlaylist.setOnClickListener {
findNavController().showPlaylistBottomSheet()
clicksFlow(view = it).throttleFist(500)
.onEach {
findNavController().showPlaylistBottomSheet()
}.launchIn(viewLifecycleOwner.lifecycleScope)
Copy link
Member

@HamBP HamBP Dec 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 로직을 테스트한 방법이 궁금해
내 생각엔 각 클릭마다 개별 flow가 생기기 때문에 연속 클릭을 방지할 수 없을 것 같아

Copy link
Collaborator Author

@2taezeat 2taezeat Dec 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

한 번더 확인해보겠습니다~

Copy link
Collaborator Author

@2taezeat 2taezeat Dec 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

View 확장 함수로 변경 및 개선하였습니다!

}
}

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,18 @@ 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.throttleFist
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.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 +32,16 @@ class PlaylistsFragment : BaseFragment<FragmentPlaylistsBinding>(R.layout.fragme
viewModel.fetchPlaylists()

observeEvents()
val newPlaylistDialog = NewPlaylistDialog()
setupButton(NewPlaylistDialog())
}

private fun setupButton(newPlaylistDialog: NewPlaylistDialog) {
binding.fabNewPlaylist.setOnClickListener {
newPlaylistDialog.show(childFragmentManager, NewPlaylistDialog.TAG)
clicksFlow(view = it).throttleFist(500)
.onEach {
newPlaylistDialog.show(childFragmentManager, NewPlaylistDialog.TAG)
}.launchIn(viewLifecycleOwner.lifecycleScope)
}

}

private fun observeEvents() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,15 @@ import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class SearchFragment : BaseFragment<FragmentSearchBinding>(R.layout.fragment_search) {

private val viewModel: SearchViewModel by viewModels()

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

ViewCompat.setOnApplyWindowInsetsListener(binding.root, RootViewInsetsCallback())

binding.viewModel = viewModel

observeEvents()
setupRecyclerView()

}

private fun setupRecyclerView() {
Expand Down Expand Up @@ -65,5 +61,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 @@ -113,6 +113,8 @@
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionDone"
android:inputType="text"
android:onTextChanged="@{(text, start, before, count) -> viewModel.updateMusicTitle(text)}" />

</com.google.android.material.textfield.TextInputLayout>
Expand Down