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

플레이리스트 상세 UI #269

Merged
merged 8 commits into from
Dec 6, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import android.view.View
import android.widget.Toast
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.WindowCompat
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
Expand Down Expand Up @@ -44,9 +45,12 @@ class MainActivity : AppCompatActivity() {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)

binding.viewModel = playViewModel
binding.lifecycleOwner = this

WindowCompat.setDecorFitsSystemWindows(window, false)

setupBottomNav()
setUpPlayerController()
connectivityManager = getSystemService(ConnectivityManager::class.java)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@color/on_surface" />
</shape>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient
android:angle="90"
android:endColor="@android:color/transparent"
android:startColor="@color/surface"
android:type="linear" />
</shape>
6 changes: 3 additions & 3 deletions android/core/ui/src/main/res/drawable/ic_play.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M22.5,12C22.501,12.255 22.435,12.505 22.31,12.727C22.186,12.949 22.006,13.135 21.788,13.267L8.28,21.53C8.052,21.669 7.791,21.745 7.524,21.75C7.257,21.755 6.994,21.689 6.761,21.558C6.531,21.429 6.339,21.241 6.205,21.013C6.071,20.785 6,20.526 6,20.262V3.738C6,3.474 6.071,3.214 6.205,2.987C6.339,2.759 6.531,2.571 6.761,2.442C6.994,2.311 7.257,2.245 7.524,2.25C7.791,2.255 8.052,2.331 8.28,2.47L21.788,10.733C22.006,10.865 22.186,11.051 22.31,11.273C22.435,11.495 22.501,11.745 22.5,12Z"
android:fillColor="@color/on_surface"/>
<path
android:fillColor="@color/surface"
android:pathData="M22.5,12C22.501,12.255 22.435,12.505 22.31,12.727C22.186,12.949 22.006,13.135 21.788,13.267L8.28,21.53C8.052,21.669 7.791,21.745 7.524,21.75C7.257,21.755 6.994,21.689 6.761,21.558C6.531,21.429 6.339,21.241 6.205,21.013C6.071,20.785 6,20.526 6,20.262V3.738C6,3.474 6.071,3.214 6.205,2.987C6.339,2.759 6.531,2.571 6.761,2.442C6.994,2.311 7.257,2.245 7.524,2.25C7.791,2.255 8.052,2.331 8.28,2.47L21.788,10.733C22.006,10.865 22.186,11.051 22.31,11.273C22.435,11.495 22.501,11.745 22.5,12Z" />
</vector>
2 changes: 1 addition & 1 deletion android/core/ui/src/main/res/values-night/themes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<style name="Base.Theme.CatchyTape" parent="Theme.Material3.DayNight.NoActionBar">
<item name="colorPrimary">@color/primary</item>
<item name="colorAccent">@color/primary</item>
<item name="android:statusBarColor">@color/surface</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:windowLightStatusBar">false</item>
<item name="android:windowBackground">@color/surface</item>
<item name="android:textColor">@color/on_surface</item>
Expand Down
2 changes: 0 additions & 2 deletions android/core/ui/src/main/res/values/dimens.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,4 @@
<dimen name="btn_radius">4dp</dimen>

<dimen name="et_height">50dp</dimen>

<dimen name="appbar_height">48dp</dimen>
</resources>
2 changes: 1 addition & 1 deletion android/core/ui/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<string name="confirm">확인</string>
<string name="complete">완료</string>
<string name="save">저장</string>
<string name="play">썸네일 이미지</string>
<string name="play">재생하기</string>

<string name="recently_played_song">최근 재생한 노래</string>
<string name="recently_added_song">최근 추가된 노래</string>
Expand Down
9 changes: 6 additions & 3 deletions android/core/ui/src/main/res/values/themes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<style name="Base.Theme.CatchyTape" parent="Theme.Material3.DayNight.NoActionBar">
<item name="colorPrimary">@color/primary</item>
<item name="colorAccent">@color/primary</item>
<item name="android:statusBarColor">@color/white</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:windowLightStatusBar">true</item>
<item name="android:windowBackground">@color/white</item>
<item name="android:textColor">@color/on_surface</item>
Expand Down Expand Up @@ -35,6 +35,11 @@
<item name="android:textSize">12sp</item>
</style>

<style name="AppBarLayout" parent="Widget.Material3.AppBarLayout">
<item name="android:background">@android:color/transparent</item>
<item name="android:fitsSystemWindows">true</item>
</style>

<style name="ToolBar" parent="Widget.Material3.Toolbar">
<item name="titleTextColor">@color/on_surface</item>
<item name="navigationIconTint">@color/on_surface</item>
Expand All @@ -59,7 +64,6 @@
<item name="android:textColorHighlight">@color/key_variant</item>
</style>


<style name="CompleteButton" parent="Widget.AppCompat.Button">
<item name="android:textSize">22sp</item>
<item name="android:layout_height">wrap_content</item>
Expand All @@ -70,5 +74,4 @@
<item name="android:textColor">@drawable/btn_complete_selector</item>
</style>


</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:paddingBottom="32dp">

<com.google.android.material.appbar.MaterialToolbar
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:fitsSystemWindows="true">

<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/tb_my_musics"
style="@style/ToolBar"
android:layout_width="0dp"
android:layout_height="@dimen/appbar_height"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:fitsSystemWindows="true">

<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/tb_my_page"
style="@style/ToolBar"
android:layout_width="0dp"
android:layout_height="@dimen/appbar_height"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
android:fitsSystemWindows="true">

<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/tb_player"
Expand Down
2 changes: 1 addition & 1 deletion android/feature/player/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="minutes_and_seconds_format">%d:%02d</string>
<string name="play">재생하기</string>

<string name="previous_music">이전 곡</string>
<string name="next_music">다음 곡</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.ohdodok.catchytape.core.domain.model.Playlist
import com.ohdodok.catchytape.feature.playlist.databinding.ItemPlaylistBinding
import com.ohdodok.catchytape.feature.playlist.model.PlaylistUiModel

class PlaylistAdapter :
ListAdapter<Playlist, PlaylistAdapter.PlaylistViewHolder>(PlaylistItemDiffUtil) {
ListAdapter<PlaylistUiModel, PlaylistAdapter.PlaylistViewHolder>(PlaylistItemDiffUtil) {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PlaylistViewHolder {
return PlaylistViewHolder.from(parent)
Expand All @@ -22,7 +22,7 @@ class PlaylistAdapter :
class PlaylistViewHolder private constructor(private val binding: ItemPlaylistBinding) :
RecyclerView.ViewHolder(binding.root) {

fun bind(item: Playlist) {
fun bind(item: PlaylistUiModel) {
binding.playlist = item
}

Expand All @@ -37,12 +37,12 @@ class PlaylistAdapter :
}
}

object PlaylistItemDiffUtil : DiffUtil.ItemCallback<Playlist>() {
override fun areItemsTheSame(oldItem: Playlist, newItem: Playlist): Boolean {
object PlaylistItemDiffUtil : DiffUtil.ItemCallback<PlaylistUiModel>() {
override fun areItemsTheSame(oldItem: PlaylistUiModel, newItem: PlaylistUiModel): Boolean {
return oldItem.id == newItem.id
}

override fun areContentsTheSame(oldItem: Playlist, newItem: Playlist): Boolean {
override fun areContentsTheSame(oldItem: PlaylistUiModel, newItem: PlaylistUiModel): Boolean {
return oldItem == newItem
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.ohdodok.catchytape.feature.playlist

import android.os.Bundle
import android.view.View
import androidx.fragment.app.viewModels
import com.ohdodok.catchytape.core.ui.BaseFragment
import com.ohdodok.catchytape.core.ui.MusicAdapter
import com.ohdodok.catchytape.core.ui.Orientation
import com.ohdodok.catchytape.feature.playlist.databinding.FragmentPlaylistDetailBinding

class PlaylistDetailFragment :
BaseFragment<FragmentPlaylistDetailBinding>(R.layout.fragment_playlist_detail) {

private val viewModel: PlaylistDetailViewModel by viewModels()

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

binding.viewModel = viewModel
setupBackStack(binding.tbPlaylistDetail)
binding.rvPlaylist.adapter = MusicAdapter(Orientation.VERTICAL)
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.ohdodok.catchytape.feature.playlist

import androidx.lifecycle.ViewModel
import com.ohdodok.catchytape.core.domain.model.Music
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import javax.inject.Inject

data class PlaylistDetailUiState(
val musics: List<Music> = listOf(
Music(
id = "1",
title = "title",
artist = "artist",
imageUrl = "https://i.pinimg.com/736x/6a/be/29/6abe2929274d6459c815ac752fb0c057.jpg"
)
)
)

@HiltViewModel
class PlaylistDetailViewModel @Inject constructor(

) : ViewModel() {

private val _uiState = MutableStateFlow(PlaylistDetailUiState())
val uiState: StateFlow<PlaylistDetailUiState> = _uiState.asStateFlow()
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import android.os.Bundle
import android.view.View
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.viewModels
import androidx.navigation.NavController
import androidx.navigation.fragment.findNavController
import com.ohdodok.catchytape.core.ui.BaseFragment
import com.ohdodok.catchytape.core.ui.toMessageId
import com.ohdodok.catchytape.feature.playlist.databinding.FragmentPlaylistsBinding
Expand All @@ -29,14 +31,17 @@ class PlaylistsFragment : BaseFragment<FragmentPlaylistsBinding>(R.layout.fragme

}


private fun observeEvents() {
repeatOnStarted {
viewModel.events.collect { event ->
when (event) {
is PlaylistsEvent.ShowMessage -> {
showMessage(event.error.toMessageId())
}

is PlaylistsEvent.NavigateToPlaylistDetail -> {
findNavController().navigateToPlaylistDetail(event.playlistId)
}
}
}
}
Expand All @@ -45,4 +50,13 @@ class PlaylistsFragment : BaseFragment<FragmentPlaylistsBinding>(R.layout.fragme
override fun onPositiveButtonClicked(dialog: DialogFragment, title: String) {
viewModel.createPlaylist(title)
}

}

private fun NavController.navigateToPlaylistDetail(playlistId: Int) {
navigate(
PlaylistsFragmentDirections.actionPlaylistsFragmentToPlaylistDetailFragment(
playlistId = playlistId
)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.ohdodok.catchytape.core.domain.model.CtErrorType
import com.ohdodok.catchytape.core.domain.model.CtException
import com.ohdodok.catchytape.core.domain.model.Playlist
import com.ohdodok.catchytape.core.domain.repository.PlaylistRepository
import com.ohdodok.catchytape.feature.playlist.model.PlaylistUiModel
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.flow.MutableSharedFlow
Expand All @@ -21,7 +21,7 @@ import kotlinx.coroutines.plus
import javax.inject.Inject

data class PlaylistsUiState(
val playlists: List<Playlist> = emptyList()
val playlists: List<PlaylistUiModel> = emptyList()
)

@HiltViewModel
Expand All @@ -48,7 +48,19 @@ class PlaylistViewModel @Inject constructor(

fun fetchPlaylists() {
playlistRepository.getPlaylists().onEach { playlists ->
_uiState.update { it.copy(playlists = playlists) }
_uiState.update {
it.copy(
playlists = playlists.map { playlist ->
PlaylistUiModel(
id = playlist.id,
title = playlist.title,
thumbnailUrl = playlist.thumbnailUrl,
trackSize = playlist.trackSize,
onClick = { onPlaylistClick(playlist.id) },
)
}
)
}
}.launchIn(viewModelScopeWithExceptionHandler)
}

Expand All @@ -57,9 +69,16 @@ class PlaylistViewModel @Inject constructor(
playlistRepository.postPlaylist(playlistTitle)
}
}
}

private fun onPlaylistClick(playlistId: Int) {
viewModelScope.launch {
_events.emit(PlaylistsEvent.NavigateToPlaylistDetail(playlistId))
}
}
}

sealed interface PlaylistsEvent {

data class NavigateToPlaylistDetail(val playlistId: Int) : PlaylistsEvent
data class ShowMessage(val error: CtErrorType) : PlaylistsEvent
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.ohdodok.catchytape.feature.playlist.model

data class PlaylistUiModel(
val id: Int,
val title: String,
val thumbnailUrl: String,
val trackSize: Int,
val onClick: () -> Unit,
)
Loading