diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml new file mode 100644 index 0000000..a3ee486 --- /dev/null +++ b/.idea/deploymentTargetSelector.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..6806f5a --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,53 @@ + + + + \ No newline at end of file diff --git a/.idea/migrations.xml b/.idea/migrations.xml new file mode 100644 index 0000000..f8051a6 --- /dev/null +++ b/.idea/migrations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index f188970..874cba3 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,10 +1,13 @@ +// app 모듈의 build.gradle.kts 파일 plugins { - alias(libs.plugins.android.application) - alias(libs.plugins.jetbrains.kotlin.android) + id("com.android.application") + id("org.jetbrains.kotlin.android") + id("kotlin-kapt") id("com.google.devtools.ksp") id("dagger.hilt.android.plugin") id("androidx.navigation.safeargs.kotlin") - id("org.jetbrains.kotlin.kapt") + id("kotlin-android") + id("kotlin-parcelize") } android { @@ -17,7 +20,6 @@ android { targetSdk = 34 versionCode = 1 versionName = "1.0" - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { useSupportLibrary = true @@ -33,19 +35,24 @@ android { ) } } + compileOptions { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } + kotlinOptions { jvmTarget = "1.8" } + buildFeatures { compose = true } + composeOptions { kotlinCompilerExtensionVersion = "1.5.1" } + packaging { resources { excludes += "/META-INF/{AL2.0,LGPL2.1}" @@ -61,8 +68,9 @@ dependencies { implementation(libs.androidx.ui) implementation(libs.androidx.ui.graphics) implementation(libs.androidx.ui.tooling.preview) - implementation(libs.androidx.material3) // 이미 추가됨 - implementation("androidx.compose.material3:material3:1.0.0") // 추가된 부분 + implementation(libs.androidx.material3) + implementation(libs.androidx.navigation.compose) + implementation(libs.androidx.runtime.livedata) testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) @@ -76,12 +84,7 @@ dependencies { implementation(libs.androidx.constraintlayout) implementation(libs.androidx.constraintlayout.compose) implementation(libs.androidx.lifecycle.livedata.ktx) - implementation(libs.androidx.lifecycle.viewmodel.ktx) // 추가된 부분 - implementation(libs.androidx.navigation.fragment.ktx) - implementation(libs.androidx.navigation.ui.ktx) - - // Paging 라이브러리 추가 - implementation("androidx.paging:paging-runtime:3.1.1") + implementation(libs.androidx.lifecycle.viewmodel.ktx) // Hilt Dependency Injection implementation("com.google.dagger:hilt-android:2.49") @@ -99,10 +102,7 @@ dependencies { implementation("com.squareup.okhttp3:okhttp:5.0.0-alpha.2") implementation("com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.2") - // Lifecycle - implementation("androidx.lifecycle:lifecycle-extensions:2.2.0") - - // ViewModel + // ViewModel and Lifecycle implementation("androidx.activity:activity-ktx:1.9.0") implementation("androidx.fragment:fragment-ktx:1.6.2") @@ -117,13 +117,35 @@ dependencies { implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") - // Safe Args + // Safe args implementation("androidx.navigation:navigation-fragment-ktx:2.7.3") implementation("androidx.navigation:navigation-ui-ktx:2.7.3") // ROOM Database implementation("androidx.room:room-runtime:2.6.1") - annotationProcessor("androidx.room:room-compiler:2.6.1") kapt("androidx.room:room-compiler:2.6.1") implementation("androidx.room:room-ktx:2.6.1") -} \ No newline at end of file + + // Navigation Compose + implementation("androidx.navigation:navigation-compose:2.8.1") + + // Parcelize + implementation("androidx.core:core-ktx:1.13.1") + + // ViewPager implementation + implementation("com.google.accompanist:accompanist-pager:0.30.0") + implementation("com.google.accompanist:accompanist-pager-indicators:0.30.0") + + implementation("com.google.accompanist:accompanist-pager:") + implementation("com.google.accompanist:accompanist-pager-indicators:") + + implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2") + implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.6.2") + implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2") + +} + + + + + diff --git a/app/src/androidTest/java/umc/study/umc_7th/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/example/umc_7th/ExampleInstrumentedTest.kt similarity index 85% rename from app/src/androidTest/java/umc/study/umc_7th/ExampleInstrumentedTest.kt rename to app/src/androidTest/java/com/example/umc_7th/ExampleInstrumentedTest.kt index 8315371..c890911 100644 --- a/app/src/androidTest/java/umc/study/umc_7th/ExampleInstrumentedTest.kt +++ b/app/src/androidTest/java/com/example/umc_7th/ExampleInstrumentedTest.kt @@ -1,4 +1,4 @@ -package umc.study.umc_7th +package com.example.umc_7th import androidx.test.platform.app.InstrumentationRegistry import androidx.test.ext.junit.runners.AndroidJUnit4 @@ -19,6 +19,6 @@ class ExampleInstrumentedTest { fun useAppContext() { // Context of the app under test. val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("umc.study.umc_7th", appContext.packageName) + assertEquals("com.example.umc_7th", appContext.packageName) } } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b099ba3..ac36b0b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,9 +1,6 @@ \ - - - + xmlns:tools="http://schemas.android.com/tools"> diff --git a/app/src/main/java/com/example/umc_7th/album1/AlbumFragment.kt b/app/src/main/java/com/example/umc_7th/album1/AlbumFragment.kt new file mode 100644 index 0000000..c43d57f --- /dev/null +++ b/app/src/main/java/com/example/umc_7th/album1/AlbumFragment.kt @@ -0,0 +1,91 @@ +package com.example.umc_7th.album1 + +import android.annotation.SuppressLint +import androidx.compose.foundation.layout.Column +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.navigation.NavController +import java.time.LocalDate + +// AlbumData 데이터 클래스 정의 +data class AlbumData( + val albumTitle: String, + val date: LocalDate, + val author: String, + val albumImage: Int, + val trackList: List, + val titleTrackList: List +) + +@Composable +fun AlbumInfo() { + Text(text = "앨범 정보") +} + +@Composable +fun AlbumVideo() { + Text(text = "앨범 영상") +} + +@SuppressLint("NewApi") +@Composable +fun albumFragment( + navController: NavController, + albumTitle: String, + albumImage: Int, + author: String, + date: LocalDate, + trackList: List, + titleTrackList: List +) { + // AlbumData 객체 생성 + val album = AlbumData( + albumTitle = albumTitle, + date = date, + author = author, + albumImage = albumImage, + trackList = trackList, + titleTrackList = titleTrackList + ) + + Column { + // AlbumFragmentTop 호출 + AlbumFragmentTop( + album = album, + albumFgtoMain = { navController.navigate("homeFragment") }, + likeButtonClick = { /* TODO: 좋아요 버튼 기능 추가 */ }, + playerMoreButtonClick = { /* TODO: 더보기 버튼 기능 추가 */ } + ) + + // TabLayout 호출 + TabLayout(album = album) + } +} + +// AlbumFragmentTop 함수 정의 +@Composable +fun AlbumFragmentTop( + album: AlbumData, + albumFgtoMain: () -> Unit, + likeButtonClick: () -> Unit, + playerMoreButtonClick: () -> Unit +) { + Column { + Text(text = "Album Title: ${album.albumTitle}") + Text(text = "Author: ${album.author}") + Text(text = "Date: ${album.date}") + // 버튼 클릭 이벤트 추가 + } +} + +// TabLayout 함수 정의 +@Composable +fun TabLayout(album: AlbumData) { + Column { + Text(text = "TabLayout for ${album.albumTitle}") + // Tab 항목 구성 + } +} + + + diff --git a/app/src/main/java/com/example/umc_7th/album1/AlbumFragmentTop.kt b/app/src/main/java/com/example/umc_7th/album1/AlbumFragmentTop.kt new file mode 100644 index 0000000..0a07421 --- /dev/null +++ b/app/src/main/java/com/example/umc_7th/album1/AlbumFragmentTop.kt @@ -0,0 +1,157 @@ +// AlbumFragmentTop.kt 파일 +package com.example.umc_7th.album1 + +import android.annotation.SuppressLint +import android.os.Build +import androidx.annotation.RequiresApi +import androidx.compose.foundation.Image +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ImageBitmap +import androidx.compose.ui.res.imageResource +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.example.umc_7th.R +import java.time.LocalDate +import java.time.format.DateTimeFormatter + +@SuppressLint("NewApi") +@Composable +fun AlbumFragmentTop( + album: Album, + albumFgtoMain: () -> Unit, + likeButtonClick: () -> Unit, + playerMoreButtonClick: () -> Unit, + playAlbumButtonClick: () -> Unit +) { + Column( + verticalArrangement = Arrangement.spacedBy(16.dp), + modifier = Modifier.padding(10.dp) + ) { + Row( + horizontalArrangement = Arrangement.spacedBy(16.dp), + modifier = Modifier.fillMaxWidth() + ) { + IconButton(onClick = albumFgtoMain) { + Icon( + bitmap = ImageBitmap.imageResource(id = R.drawable.btn_arrow_black), + contentDescription = null, + modifier = Modifier.size(50.dp) + ) + } + Row( + horizontalArrangement = Arrangement.End, + modifier = Modifier.fillMaxWidth() + ) { + var like by remember { mutableStateOf(false) } + IconButton(onClick = likeButtonClick) { + Icon( + bitmap = if (like) ImageBitmap.imageResource(id = R.drawable.ic_my_like_on) + else ImageBitmap.imageResource(id = R.drawable.ic_my_like_off), + contentDescription = null, + modifier = Modifier + .size(50.dp) + .clickable { like = !like }, + tint = Color.Unspecified + ) + } + + Icon( + bitmap = ImageBitmap.imageResource(id = R.drawable.btn_player_more), + contentDescription = null, + modifier = Modifier.clickable { playerMoreButtonClick() } + ) + } + } + + Column( + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier.fillMaxWidth() + ) { + Text( + text = album.albumTitle, + fontWeight = FontWeight.Bold, + fontSize = 16.sp + ) + Text( + text = album.author, + style = TextStyle( + color = Color.Black.copy(alpha = 0.5f) + ), + fontSize = 12.sp + ) + val dateString = album.date.format(DateTimeFormatter.ofPattern("yyyy.MM.dd")) + val genre = "댄스 팝" + val regular = "정규" + Text(text = "$dateString | $regular | $genre") + } + + Row( + modifier = Modifier.padding(start = 70.dp) + ) { + Box( + contentAlignment = Alignment.Center + ) { + Image( + bitmap = ImageBitmap.imageResource(id = album.albumImage), + contentDescription = null, + modifier = Modifier + .size(210.dp) + .align(Alignment.Center) + .clip(RoundedCornerShape(20.dp)) + ) + IconButton(onClick = playAlbumButtonClick, modifier = Modifier.align(Alignment.BottomEnd)) { + Icon( + bitmap = ImageBitmap.imageResource(id = R.drawable.widget_black_play), + contentDescription = null, + tint = Color.Unspecified + ) + } + } + Image( + painter = painterResource(id = R.drawable.img_album_lp), + contentDescription = null + ) + } + } +} + +@RequiresApi(Build.VERSION_CODES.P) +@Composable +@Preview(showBackground = true) +fun previewAlbumFragmentTop() { + AlbumFragmentTop( + album = Album( + albumTitle = "IU 5th Album 'LILAC'", + date = LocalDate.parse("2023-03-27"), + author = "IU(아이유)", + albumImage = R.drawable.img_album_exp2, + trackList = listOf("LILAC", "Coin", "Flu", "Troll", "Lovesick"), + titleTrackList = listOf("LILAC", "Flu") + ), + albumFgtoMain = { /* TODO: 메인 화면으로 이동하는 함수 구현 */ }, + likeButtonClick = { /* TODO: 좋아요 클릭 처리 함수 구현 */ }, + playerMoreButtonClick = { /* TODO: 플레이어 더보기 클릭 처리 함수 구현 */ }, + playAlbumButtonClick = { /* TODO: 앨범 재생 클릭 처리 함수 구현 */ } + ) +} + + diff --git a/app/src/main/java/com/example/umc_7th/album1/AlbumItem.kt b/app/src/main/java/com/example/umc_7th/album1/AlbumItem.kt new file mode 100644 index 0000000..0a2dd3b --- /dev/null +++ b/app/src/main/java/com/example/umc_7th/album1/AlbumItem.kt @@ -0,0 +1,110 @@ +package com.example.umc_7th.album1 + +import android.os.Build +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.annotation.RequiresApi +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.lazy.grid.items +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ImageBitmap +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.imageResource +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import umc.study.umc_7th.R + +// Album 데이터 클래스 정의 +data class Album( + val albumTitle: String, + val author: String, + val albumImage: Int +) + +// 샘플 albumData 리스트 생성 +val albumData = listOf( + com.example.umc_7th.etc.Album("Album 1", "Author 1", R.drawable.sample_image1), + com.example.umc_7th.etc.Album("Album 2", "Author 2", R.drawable.sample_image2), + // 필요한 만큼 Album 객체 추가 +) + +class AlbumItemActivity : ComponentActivity() { + @RequiresApi(Build.VERSION_CODES.P) + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + AlbumItem() + } + } +} + +@RequiresApi(Build.VERSION_CODES.P) +@Composable +fun AlbumItem() { + LazyVerticalGrid( + columns = GridCells.Fixed(2), + modifier = Modifier.padding(horizontal = 8.dp) + ) { + items(albumData) { content -> + Column(modifier = Modifier.padding(vertical = 0.dp)) { + Box( + contentAlignment = Alignment.Center, + modifier = Modifier + .wrapContentSize() + .padding(vertical = 20.dp) + ) { + Image( + bitmap = ImageBitmap.imageResource(id = content.albumImage), + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier + .size(180.dp) + .clip(RoundedCornerShape(8.dp)) + ) + + Icon( + painter = painterResource(id = R.drawable.btn_miniplayer_play), + contentDescription = null, + tint = Color.White, + modifier = Modifier + .size(48.dp) + .align(Alignment.BottomEnd) + ) + } + Column(modifier = Modifier.padding(5.dp)) { + Text( + text = content.albumTitle, + fontSize = 20.sp, + fontWeight = FontWeight.Bold + ) + Text(text = content.author) + } + } + } + } +} + +@RequiresApi(Build.VERSION_CODES.P) +@Preview(showBackground = true) +@Composable +fun PreviewAlbumItem() { + AlbumItem() +} diff --git a/app/src/main/java/com/example/umc_7th/album1/AlbumMusicList.kt b/app/src/main/java/com/example/umc_7th/album1/AlbumMusicList.kt new file mode 100644 index 0000000..d1f403c --- /dev/null +++ b/app/src/main/java/com/example/umc_7th/album1/AlbumMusicList.kt @@ -0,0 +1,240 @@ +package com.example.umc_7th.album1 + +import android.os.Build +import androidx.annotation.RequiresApi +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import umc.study.umc_7th.R +import java.time.LocalDate + +@RequiresApi(Build.VERSION_CODES.P) +@Composable +fun AlbumMusicList( + album : Album, + playButtonClick : () -> Unit, + playAllButtonClick : () -> Unit, + selectAllButtonClick : () -> Unit, + moreInfoButtonClick :() -> Unit, + mixButtonClick : () -> Unit, +) { + LazyColumn( + verticalArrangement = Arrangement.spacedBy(8.dp), + modifier = Modifier.fillMaxHeight() + ) { + item { + Column( + verticalArrangement = Arrangement.spacedBy(4.dp), + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier.padding(10.dp) + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.background(Color.Black.copy(0.05f), + shape= RoundedCornerShape(percent= 50) + ).padding(vertical =6.dp, horizontal = 10.dp) + ) { +// + Text(text = "내 취향 MIX", fontSize = 15.sp) + + var checked by remember { mutableStateOf(false) } + Icon(painter = painterResource( + id = if (checked == false) R.drawable.btn_toggle_off + else R.drawable.btn_toggle_on + ), contentDescription = null, + modifier = Modifier + .clickable { checked = !checked } + .size(30.dp), + tint = Color.Unspecified) +// } + + } + Box(modifier = Modifier.fillMaxWidth()) { + var selected by remember { mutableStateOf(false) } + Row( + modifier = Modifier + .clickable { selectAllButtonClick() } + .align(Alignment.CenterStart) + + ) { + Icon( + painter = painterResource( + id = if (selected == false) R.drawable.btn_playlist_select_off + else R.drawable.btn_playlist_select_on + ), + contentDescription = null, + modifier = Modifier.size(16.dp) + ) + Text( + text = "전체 선택", + fontSize = 12.sp, + color = if (selected == false) Color.Black else Color.Blue + ) + } + Row( + modifier = Modifier + .clickable { playAllButtonClick() } + .align(Alignment.CenterEnd), + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + painter = painterResource(id = R.drawable.icon_browse_arrow_right), + contentDescription = null, + modifier = Modifier.size(16.dp) + ) + Text( + text = "전체 듣기", color = Color.Black, + fontSize = 12.sp + ) + } + + + } + } + + } + + itemsIndexed(album.trackList) { index, track -> + if(track in album.titleTrackList) + Row( + modifier = Modifier + .fillMaxWidth() + .padding(start = 10.dp), + verticalAlignment = Alignment.Top){ + Text( + text = "${index + 1}", Modifier.padding(horizontal = 4.dp), + fontSize = 12.sp, fontWeight = FontWeight.Bold + ) + Column { + Row( + verticalAlignment = Alignment.CenterVertically + ){ + Text(text="title", fontSize= 10.sp, color = Color.White, + modifier= Modifier.background(Color.Blue, shape = RoundedCornerShape(percent=30)) + .padding(horizontal =4.dp, vertical = 0.dp)) + + Spacer(modifier = Modifier.size(4.dp)) + Text(text = track) + + } + + Text( + text = album.author, + color = Color.Black.copy(0.5f), + fontSize = 12.sp) + } + Row( + modifier = Modifier + .padding(4.dp) + .fillMaxSize(), + horizontalArrangement = Arrangement.End, + verticalAlignment = Alignment.Top + ) { + Icon(painter = painterResource(id = R.drawable.btn_player_play), + contentDescription = null, + modifier = Modifier + .size(24.dp) + .clickable { playButtonClick() }) + Icon(painter = painterResource(id = R.drawable.btn_player_more), + contentDescription = null, + modifier = Modifier + .size(24.dp) + .clickable { moreInfoButtonClick() }) + } + + } + else + Row( + modifier = Modifier + .fillMaxWidth() + .padding(start = 10.dp), + verticalAlignment = Alignment.Top + ) { + Text( + text = "${index + 1}", Modifier.padding(horizontal = 4.dp), + fontSize = 12.sp, fontWeight = FontWeight.Bold + ) + Column { + Text(text = track) + Text( + text = album.author, + color = Color.Black.copy(0.5f), + fontSize = 12.sp + ) + } + + Row( + modifier = Modifier + .padding(4.dp) + .fillMaxSize(), + horizontalArrangement = Arrangement.End, + verticalAlignment = Alignment.Top + ) { + Icon(painter = painterResource(id = R.drawable.btn_player_play), + contentDescription = null, + modifier = Modifier + .size(24.dp) + .clickable { playButtonClick() }) + Icon(painter = painterResource(id = R.drawable.btn_player_more), + contentDescription = null, + modifier = Modifier + .size(24.dp) + .clickable { moreInfoButtonClick() }) + } + } + + + } + + + } +} + + +@RequiresApi(Build.VERSION_CODES.P) +@Preview(showBackground = true) +@Composable +fun PreviewAlbumMusicList(){ + AlbumMusicList( + album = Album( + albumTitle = "IU 5th Album 'LILAC'", + date = LocalDate.parse("2023-03-27"), + author = "IU(아이유)", + albumImage = R.drawable.img_album_exp2, + trackList = listOf("LILAC", "Coin", "Flu", "Troll", "Lovesick"), + titleTrackList = listOf("LILAC", "Flu") + ), + playButtonClick = { /*TODO*/ }, + playAllButtonClick = { /*TODO*/ }, + selectAllButtonClick = { /*TODO*/ }, + mixButtonClick = {}, + moreInfoButtonClick = {} + ) +} diff --git a/app/src/main/java/com/example/umc_7th/etc/AroundFragment.kt b/app/src/main/java/com/example/umc_7th/etc/AroundFragment.kt new file mode 100644 index 0000000..56522e8 --- /dev/null +++ b/app/src/main/java/com/example/umc_7th/etc/AroundFragment.kt @@ -0,0 +1,16 @@ +package com.example.umc_7th.etc + +import android.annotation.SuppressLint +import androidx.compose.foundation.content.MediaType.Companion.Text +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.navigation.NavController + +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@Composable +fun aroundFragment(navController: NavController){ + Scaffold { + Text(text = "around") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/umc_7th/etc/Content.kt b/app/src/main/java/com/example/umc_7th/etc/Content.kt new file mode 100644 index 0000000..207e244 --- /dev/null +++ b/app/src/main/java/com/example/umc_7th/etc/Content.kt @@ -0,0 +1,154 @@ +// 파일 경로: com.example.umc_7th.etc + +package com.example.umc_7th.etc + +import android.os.Build +import androidx.compose.ui.graphics.Color +import androidx.annotation.RequiresApi +import kotlinx.parcelize.Parcelize +import android.os.Parcelable +import java.time.LocalDate + +@Parcelize +data class Content( + val title: String, + val author: String, + val image: Int? = null, + val length: Int +) : Parcelable + +@Parcelize +data class Album( + val albumTitle: String, + val date: LocalDate, + val author: String, + val albumImage: Int, + val trackList: List, + val titleTrackList: List +) : Parcelable + +@Parcelize +data class BannerData( + val title1: String, + val date: LocalDate, + val contentList: List, + val backgroundImage: Int, + val textColor: Long +) : Parcelable + +@RequiresApi(Build.VERSION_CODES.P) +val bannerDataList = listOf( + BannerData( + title1 = "포근하게 덮어주는 꿈의 목소리2", + date = LocalDate.parse("2024-03-06"), + contentList = listOf( + Content( + title = "Butter", + author = "BTS", + image = R.drawable.img_album_exp, + length = 245 + ), + Content( + title = "Next Level", + author = "aespa", + image = R.drawable.img_album_exp3, + length = 199 + ) + ), + backgroundImage = R.drawable.img_default_4_x_1, + textColor = 0xFFFFFFFF + ), + BannerData( + title1 = "포근하게 덮어주는 꿈의 목소리 3", + date = LocalDate.parse("2024-03-06"), + contentList = List(15) { + Content( + title = "작은 것들을 위한 시", + author = "BTS", + image = R.drawable.img_album_exp4, + length = 220 + ) + }, + backgroundImage = R.drawable.img_default_4_x_1, + textColor = 0xFFFFFFFF + ), + BannerData( + title1 = "포근하게 덮어주는 꿈의 목소리 4", + date = LocalDate.parse("2024-03-06"), + contentList = List(15) { + Content( + title = "해야", + author = "IVE(아이브)", + image = R.drawable.img_album_heya, + length = 200 + ) + }, + backgroundImage = R.drawable.img_default_4_x_1, + textColor = 0xFFFFFFFF + ) +) + +@RequiresApi(Build.VERSION_CODES.P) +val albumData = listOf( + Album( + albumTitle = "IU 5th Album 'LILAC'", + date = LocalDate.parse("2023-03-27"), + author = "IU(아이유)", + albumImage = R.drawable.img_album_exp2, + trackList = listOf("LILAC", "Coin", "Flu", "Troll", "Lovesick"), + titleTrackList = listOf("LILAC", "Flu") + ), + Album( + albumTitle = "BTS 'Map of the Soul: Persona'", + date = LocalDate.parse("2019-04-12"), + author = "BTS(방탄소년단)", + albumImage = R.drawable.img_album_exp4, + trackList = listOf("Intro: Persona", "Boy With Luv", "Mikrokosmos", "Make It Right", "Home"), + titleTrackList = listOf("Boy With Luv") + ), + Album( + albumTitle = "Next Level", + date = LocalDate.parse("2019-04-12"), + author = "aespa", + albumImage = R.drawable.img_album_exp3, + trackList = listOf("Next Level"), + titleTrackList = listOf("Next Level") + ), + Album( + albumTitle = "MOMOLAND 'BAAM'", + date = LocalDate.parse("2018-06-26"), + author = "MOMOLAND", + albumImage = R.drawable.img_album_exp5, + trackList = listOf("BAAM", "Veryvery", "Bingo Game", "Only one you", "Falling U"), + titleTrackList = listOf("BAAM") + ), + Album( + albumTitle = "Taeyeon 'Weekend'", + date = LocalDate.parse("2021-07-06"), + author = "Taeyeon(태연)", + albumImage = R.drawable.img_album_exp6, + trackList = listOf("Weekend"), + titleTrackList = listOf("Weekend") + ), + Album( + albumTitle = "aespa 'Next Level: Drama'", + date = LocalDate.parse("2023-06-15"), + author = "aespa(에스파)", + albumImage = R.drawable.img_album_drama, + trackList = listOf("Next Level", "Drama", "Black Mamba", "Forever", "Savage"), + titleTrackList = listOf("Drama", "Next Level") + ), + Album( + albumTitle = "IVE 'I've HAEYA'", + date = LocalDate.parse("2023-08-10"), + author = "IVE(아이브)", + albumImage = R.drawable.img_album_heya, + trackList = listOf("HAEYA", "After LIKE", "ELEVEN", "LOVE DIVE", "ROYAL"), + titleTrackList = listOf("HAEYA", "After LIKE") + ) +) + + + + + diff --git a/app/src/main/java/com/example/umc_7th/etc/SearchFragment.kt b/app/src/main/java/com/example/umc_7th/etc/SearchFragment.kt new file mode 100644 index 0000000..3a84dc3 --- /dev/null +++ b/app/src/main/java/com/example/umc_7th/etc/SearchFragment.kt @@ -0,0 +1,16 @@ +package com.example.umc_7th.etc + +import android.annotation.SuppressLint +import androidx.compose.foundation.content.MediaType.Companion.Text +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.navigation.NavController + +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@Composable +fun searchFragment(navController: NavController){ + Scaffold { + Text(text = "search") + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/umc_7th/etc/Service.kt b/app/src/main/java/com/example/umc_7th/etc/Service.kt new file mode 100644 index 0000000..706ca69 --- /dev/null +++ b/app/src/main/java/com/example/umc_7th/etc/Service.kt @@ -0,0 +1,75 @@ +package com.example.umc_7th.etc + +import android.app.Service +import android.content.Intent +import android.app.Notification +import android.app.NotificationChannel +import android.app.NotificationManager +import android.app.PendingIntent +import android.content.Context +import android.os.IBinder +import android.os.Build +import androidx.core.app.NotificationCompat +import android.graphics.BitmapFactory + +import com.example.umc_7th.home.MainActivity + +class MusicPlayerService : Service() { + override fun onCreate() { + super.onCreate() + } + + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + startForeground(1, createNotification()) + return START_STICKY + } + + override fun onDestroy() { + super.onDestroy() + } + + override fun onBind(intent: Intent?): IBinder? { + return null + } + + private fun createNotification(): Notification { + val notificationChannelId = "MUSIC_PLAYER_CHANNEL" + val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val channel = NotificationChannel( + notificationChannelId, + "Music Player", + NotificationManager.IMPORTANCE_LOW + ) + notificationManager.createNotificationChannel(channel) + } + + // 알림 클릭 시 앱의 MainActivity를 여는 Intent와 PendingIntent + val notificationIntent = Intent(this, MainActivity::class.java) + val pendingIntent = PendingIntent.getActivity( + this, + 0, + notificationIntent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE // FLAG_IMMUTABLE은 API 23 이상 필요 + ) + + return NotificationCompat.Builder(this, notificationChannelId) + .setContentTitle("Now Playing") + .setContentText("Your favorite song is playing") + .setSmallIcon(R.drawable.icon_browse_arrow_right) // 작은 아이콘 + .setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.img_album_exp)) // 큰 아이콘 + .setContentIntent(pendingIntent) // 클릭 시 MainActivity로 이동 + .setPriority(NotificationCompat.PRIORITY_LOW) + .setOngoing(true) // 사용자가 수동으로만 제거할 수 있도록 설정 + .build() + } +} +fun startMusicService(context: Context) { + val intent = Intent(context, MusicPlayerService::class.java) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + context.startForegroundService(intent) + } else { + context.startService(intent) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/umc_7th/etc/TabLayout.kt b/app/src/main/java/com/example/umc_7th/etc/TabLayout.kt new file mode 100644 index 0000000..36779f3 --- /dev/null +++ b/app/src/main/java/com/example/umc_7th/etc/TabLayout.kt @@ -0,0 +1,98 @@ +package com.example.umc_7th.etc + +import android.os.Build +import androidx.annotation.RequiresApi +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.material3.Tab +import androidx.compose.material3.TabRow +import androidx.compose.material3.TabRowDefaults +import androidx.compose.material3.TabRowDefaults.tabIndicatorOffset +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import kotlinx.coroutines.launch +import umc.study.umc_7th.album.AlbumMusicList +import java.time.LocalDate + +@RequiresApi(Build.VERSION_CODES.P) +@Composable +fun TabLayout( + album : Album, +) { + val tabs = listOf("수록곡", "상세정보", "영상") + val pagerState = rememberPagerState{ tabs.size } + val coroutineScope = rememberCoroutineScope() + + Column { + TabRow( + selectedTabIndex = pagerState.currentPage, + indicator = { tabPositions -> + TabRowDefaults.Indicator( + Modifier + .tabIndicatorOffset(tabPositions[pagerState.currentPage]) + .padding(horizontal = tabPositions[pagerState.currentPage].width / 4), + color = Color.Blue, + height = 4.dp, + + ) + } + ) { + tabs.forEachIndexed { index, title -> + Tab( + text = { Text(text = title, fontSize = 16.sp, + color = if(pagerState.currentPage ==index) Color.Blue + else Color.Black) + }, + selected = pagerState.currentPage == index, + onClick = { + coroutineScope.launch { + pagerState.animateScrollToPage(index) + } + } + ) + } + } + HorizontalPager( + state = pagerState, + modifier = Modifier.fillMaxSize() + ) { page -> + when (page) { + 0 -> AlbumMusicList( + album = album, + playButtonClick = { /*TODO*/ }, + playAllButtonClick = { /*TODO*/ }, + selectAllButtonClick = { /*TODO*/ }, + mixButtonClick = {}, + moreInfoButtonClick = {}) + 1 -> Text("상세정보 내용", modifier = Modifier.padding(16.dp)) + 2 -> Text("영상 내용", modifier = Modifier.padding(16.dp)) + } + } + } +} + + + +@RequiresApi(Build.VERSION_CODES.P) +@Preview(showBackground = true) +@Composable +fun PreviewTabLayout(){ + TabLayout(album =Album( + albumTitle = "IU 5th Album 'LILAC'", + date = LocalDate.parse("2023-03-27"), + author = "IU(아이유)", + albumImage = R.drawable.img_album_exp2, + trackList = listOf("LILAC", "Coin", "Flu", "Troll", "Lovesick"), + titleTrackList = listOf("LILAC", "Flu") + ) + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/umc_7th/etc/ViewModel.kt b/app/src/main/java/com/example/umc_7th/etc/ViewModel.kt new file mode 100644 index 0000000..c63d061 --- /dev/null +++ b/app/src/main/java/com/example/umc_7th/etc/ViewModel.kt @@ -0,0 +1,126 @@ +package com.example.umc_7th.etc + +import android.app.Application +import androidx.lifecycle.AndroidViewModel +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch + +open class SongViewModel(application: Application) : AndroidViewModel(application) { + + private val _like = MutableLiveData(false) + open val like : LiveData = _like + + private val _unLike = MutableLiveData(false) + open val unLike : LiveData = _unLike + + fun toggleLike(){ + _like.value = _like.value != true + } + + fun toggleUnLike(){ + _unLike.value = _unLike.value != true + } + + + + private val _replay = MutableLiveData(false) + open val replay : LiveData = _replay + + private val _played = MutableLiveData(false) + open val played : LiveData = _played + + private val _duration = MutableLiveData(200f) + open val duration : LiveData = _duration + + private val _currentPosition = MutableLiveData(0f) + open val currentPosition : LiveData = _currentPosition + + private val _shuffle = MutableLiveData(false) + open val shuffle : LiveData = _shuffle + + private var playbackJob : Job? = null + + open fun toggleReplay() { + _replay.value = _replay.value != true + } + open fun togglePlayed() { + _played.value = _played.value != true + + if (_played.value == true) { + startPlayback() + }else { + stopPlayedback() + } + } + + private fun startPlayback(){ + playbackJob?.cancel() + playbackJob = viewModelScope.launch { + while (_played.value == true && _currentPosition.value!! < _duration.value!!){ + delay(1000L) + _currentPosition.value = _currentPosition.value!! + 1f + } + } + } + private fun stopPlayedback(){ + playbackJob?.cancel() + } + + open fun toggleShuffle() { + _shuffle.value = _shuffle.value != true + } + open fun updatePosition(position: Float){ + _currentPosition.value = position + } + fun setDuration(duration: Float){ + _duration.value = duration + } + fun resetProgress(){ // 그 .. beforeSongPlayClick() 에 넣어줄 것 + _currentPosition.value = 0f + } + + private val _currentSong = MutableLiveData(null) + open val currentSong : LiveData = _currentSong + + fun setCurrentSong(content:Content){ + _currentSong.value = content + resetProgress() + togglePlayed() + } + +} + +class MyApplication : Application() { + val songViewModel : SongViewModel by lazy { SongViewModel(this) } + +} + +//가짜 뷰 모델 +class FakeSongViewModel(application: Application) : SongViewModel(application) { + override val replay = MutableLiveData(false) + override val played = MutableLiveData(true) + override val shuffle = MutableLiveData(false) + override val currentPosition = MutableLiveData(0f) + override val duration = MutableLiveData(200f) + + override fun updatePosition(newPosition: Float) { + currentPosition.value = newPosition + } + + override fun toggleReplay() { + replay.value = replay.value?.not() + } + + override fun togglePlayed() { + played.value = played.value?.not() + } + + override fun toggleShuffle() { + shuffle.value = shuffle.value?.not() + } +} \ No newline at end of file diff --git a/app/src/main/java/umc/study/umc_7th/BottomBar.kt b/app/src/main/java/com/example/umc_7th/home/BottomNavigationBar.kt similarity index 79% rename from app/src/main/java/umc/study/umc_7th/BottomBar.kt rename to app/src/main/java/com/example/umc_7th/home/BottomNavigationBar.kt index 58fa583..e5da6b7 100644 --- a/app/src/main/java/umc/study/umc_7th/BottomBar.kt +++ b/app/src/main/java/com/example/umc_7th/home/BottomNavigationBar.kt @@ -1,23 +1,17 @@ -package umc.study.umc_7th +package com.example.umc_7th.home import android.os.Build +import androidx.activity.ComponentActivity import androidx.annotation.RequiresApi -import androidx.compose.foundation.Image import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column //import androidx.compose.foundation.layout.FlowRowScopeInstance.weight import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material3.Icon -import androidx.compose.material3.NavigationBarItemDefaults import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -26,15 +20,12 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.style.LineBreak import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import androidx.compose.runtime.setValue import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.res.imageResource +import com.example.umc_7th.R enum class DestinationClass( val mean : String, @@ -86,13 +77,15 @@ fun BottomNavigationBar( } } } - -@RequiresApi(Build.VERSION_CODES.P) -@Preview(showBackground = true) -@Composable -fun PreiviewBottomNavigationBar(){ - BottomNavigationBar( - onClick = { } - ) +class BottomNavigationBar : ComponentActivity() { + @RequiresApi(Build.VERSION_CODES.P) + @Preview(showBackground = true) + @Composable + fun PreiviewBottomNavigationBar() { + BottomNavigationBar( + onClick = { } + ) + } } + diff --git a/app/src/main/java/com/example/umc_7th/home/Horizontal.kt b/app/src/main/java/com/example/umc_7th/home/Horizontal.kt new file mode 100644 index 0000000..39bcceb --- /dev/null +++ b/app/src/main/java/com/example/umc_7th/home/Horizontal.kt @@ -0,0 +1,229 @@ +package com.example.umc_7th.home + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.ClickableText +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.items + +enum class BaseLocationCategory(val mean: String) { + GLOBAL(mean = "종합"), + DOMESTIC(mean = "국내"), + FOREIGN(mean = "해외"), +} + +@Composable +fun horizontalScrollContentView( + contentList: List, + titleBar: @Composable () -> Unit, + thumbnail: @Composable (Content) -> Unit, + contentClick: (Content) -> Unit +) { + Column { + titleBar() + LazyRow { + items(contentList) { content -> + Box( + modifier = Modifier + .padding(8.dp) + .clickable { contentClick(content) } + ) { + thumbnail(content) + } + } + } + } +} + +@Composable +fun LocationMusicContentView( + title: String, + contentList: List, + baseLocationCategory: BaseLocationCategory, + viewTitleClick: () -> Unit, + contentClick: (Content) -> Unit, + categoryClick: (BaseLocationCategory) -> Unit, +) { + horizontalScrollContentView( + contentList = contentList, + titleBar = { + Row( + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .padding(horizontal = 16.dp, vertical = 5.dp) + .fillMaxWidth() + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(4.dp), + modifier = Modifier.clickable { viewTitleClick() } + ) { + Text( + text = title, + style = TextStyle( + fontSize = 18.sp, + fontWeight = FontWeight.Bold, + ) + ) + Icon( + painter = painterResource(id = R.drawable.btn_main_arrow_more), + contentDescription = null, + modifier = Modifier.size(16.dp) + ) + } + Row( + horizontalArrangement = Arrangement.spacedBy(16.dp) + ) { + BaseLocationCategory.entries.forEach { category -> + ClickableText( + text = AnnotatedString(category.mean), + onClick = { categoryClick(category) }, + style = TextStyle( + color = if (category == baseLocationCategory) Color.Blue else Color.Unspecified + ) + ) + } + } + } + }, + thumbnail = { content -> + Box(contentAlignment = Alignment.BottomEnd) { + content.image?.let { + Image( + painter = painterResource(id = it), + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier + .size(128.dp) + .clip(RoundedCornerShape(8.dp)) + ) + } + Icon( + painter = painterResource(id = R.drawable.btn_miniplayer_play), + contentDescription = null, + tint = Color.White, + modifier = Modifier.size(48.dp) + ) + } + }, + contentClick = contentClick, + ) +} + +@Composable +fun PodcastCollectionView( + title: String, + contentList: List, + contentClick: (Content) -> Unit, +) { + horizontalScrollContentView( + contentList = contentList, + titleBar = { + Row( + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.padding(horizontal = 16.dp) + ) { + Text( + text = title, + style = TextStyle( + fontSize = 18.sp, + fontWeight = FontWeight.Bold, + ) + ) + } + }, + thumbnail = { content -> + content.image?.let { + Image( + painter = painterResource(id = it), + contentScale = ContentScale.Crop, + contentDescription = null, + modifier = Modifier + .size(128.dp) + .clip(RoundedCornerShape(8.dp)) + ) + } + }, + contentClick = contentClick, + ) +} + +@Composable +fun VideoCollectionView( + title: String, + contentList: List, + contentClick: (Content) -> Unit, +) { + horizontalScrollContentView( + contentList = contentList, + titleBar = { + Row( + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.padding(horizontal = 16.dp) + ) { + Text( + text = title, + style = TextStyle( + fontSize = 18.sp, + fontWeight = FontWeight.Bold, + ) + ) + } + }, + thumbnail = { content -> + Box(contentAlignment = Alignment.BottomEnd) { + content.image?.let { + Image( + painter = painterResource(id = it), + contentDescription = null, + contentScale = ContentScale.FillHeight, + modifier = Modifier + .width(228.dp) + .height(128.dp) + .clip(RoundedCornerShape(8.dp)) + ) + } + Box( + modifier = Modifier + .padding(8.dp) + .background(color = Color.Black.copy(alpha = 0.5f)) + ) { + Text( + text = "${"%02d".format(content.length / 60)}:${content.length % 60}", + style = TextStyle( + fontSize = 10.sp, + color = Color.White, + ), + modifier = Modifier.padding(4.dp), + ) + } + } + }, + contentClick = contentClick + ) +} + + + + + diff --git a/app/src/main/java/umc/study/umc_7th/MainActivity.kt b/app/src/main/java/com/example/umc_7th/home/MainActivity.kt similarity index 69% rename from app/src/main/java/umc/study/umc_7th/MainActivity.kt rename to app/src/main/java/com/example/umc_7th/home/MainActivity.kt index dd57dae..8f1197f 100644 --- a/app/src/main/java/umc/study/umc_7th/MainActivity.kt +++ b/app/src/main/java/com/example/umc_7th/home/MainActivity.kt @@ -1,6 +1,9 @@ -package umc.study.umc_7th +package com.example.umc_7th.home import android.os.Build +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent import androidx.annotation.RequiresApi import androidx.compose.foundation.Image import androidx.compose.foundation.clickable @@ -8,14 +11,12 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.verticalScroll +import androidx.compose.foundation.lazy.items import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.Text @@ -23,39 +24,38 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.ImageBitmap import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.res.imageResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.LineBreak -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import com.example.umc_7th.R import java.time.LocalDate import java.time.format.DateTimeFormatter - @RequiresApi(Build.VERSION_CODES.P) @Composable fun MainBanner( - title1 : String, - title2 : String, - date : LocalDate, - contentList : List, - backgroundImage: ImageBitmap, - textColor : Color, - MikeButtonClick : ()-> Unit, - TicketButtonClick : ()-> Unit, - SettingButtonClick : ()-> Unit, - PlayButtonClick : () -> Unit -){ - Box{ - Image(bitmap = backgroundImage, - contentDescription =null, + title1: String, + title2: String, + date: LocalDate, + contentList: List, + backgroundImage: Int, + textColor: Color, + MikeButtonClick: () -> Unit, + TicketButtonClick: () -> Unit, + SettingButtonClick: () -> Unit, + PlayButtonClick: () -> Unit +) { + Box { + Image( + painter = painterResource(id = backgroundImage), + contentDescription = null, contentScale = ContentScale.Crop, - modifier = Modifier.matchParentSize()) + modifier = Modifier.matchParentSize() + ) Column( modifier = Modifier.padding(14.dp), verticalArrangement = Arrangement.spacedBy(16.dp) @@ -63,7 +63,7 @@ fun MainBanner( Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.End - ){ + ) { listOf( MikeButtonClick to R.drawable.btn_main_mike, TicketButtonClick to R.drawable.btn_main_ticket, @@ -105,7 +105,7 @@ fun MainBanner( .fillMaxWidth() .padding(end = 16.dp), horizontalArrangement = Arrangement.End - ){ + ) { IconButton(onClick = PlayButtonClick, modifier = Modifier.size(60.dp) ) { @@ -119,9 +119,10 @@ fun MainBanner( Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(10.dp) - ){ - Text(text = "총 ${contentList.size}곡",color =textColor) - Text(text = date.format(DateTimeFormatter.ofPattern("yyyy.MM.dd")), + ) { + Text(text = "총 ${contentList.size}곡", color = textColor) + Text( + text = date.format(DateTimeFormatter.ofPattern("yyyy.MM.dd")), color = textColor, ) } @@ -129,16 +130,15 @@ fun MainBanner( verticalArrangement = Arrangement.spacedBy(16.dp), modifier = Modifier.height(100.dp) ) { - items(count = contentList.size) {index -> - val content = contentList[index] + items(contentList) { content -> Row( verticalAlignment = Alignment.Top, horizontalArrangement = Arrangement.spacedBy(16.dp), - modifier = Modifier.clickable { } - ){ + modifier = Modifier.clickable { /* Handle click */ } + ) { content.image?.let { Image( - bitmap = it, + painter = painterResource(id = it), contentDescription = null, modifier = Modifier.size(40.dp) ) @@ -148,42 +148,46 @@ fun MainBanner( ) { Text(text = content.title, color = textColor) Text(text = content.author, color = textColor) - } } } } } } - - } -@RequiresApi(Build.VERSION_CODES.P) -@Preview -@Composable -fun PreviewBanner(){ - MainBanner( - title1 = "포근하게 덮어주는 꿈의", - title2 = "목소리", - date = LocalDate.parse("2019-11-11"), - contentList = List(15){ - Content( - title = "Butter", - author = "BTS", - image = ImageBitmap.imageResource(id = R.drawable.img_album_exp), - length = 200, +class MainActivity : ComponentActivity() { + @RequiresApi(Build.VERSION_CODES.P) + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + MainBanner( + title1 = "포근하게 덮어주는 꿈의", + title2 = "목소리", + date = LocalDate.parse("2019-11-11"), + contentList = List(15) { + Content( + title = "Butter", + author = "BTS", + image = R.drawable.img_album_exp, + length = 200, + ) + }, + backgroundImage = R.drawable.img_default_4_x_1, + textColor = Color.White, + MikeButtonClick = { /*TODO*/ }, + TicketButtonClick = { /*TODO*/ }, + SettingButtonClick = { /*TODO*/ }, + PlayButtonClick = { /*TODO*/ } ) - }, - backgroundImage = ImageBitmap.imageResource(id = R.drawable.img_default_4_x_1) , - textColor =Color.White , - MikeButtonClick = { /*TODO*/ }, - TicketButtonClick = { /*TODO*/ }, - SettingButtonClick = { /*TODO*/ }) { - + } } } + + + + diff --git a/app/src/main/java/com/example/umc_7th/home/MainBanner.kt b/app/src/main/java/com/example/umc_7th/home/MainBanner.kt new file mode 100644 index 0000000..30fcefb --- /dev/null +++ b/app/src/main/java/com/example/umc_7th/home/MainBanner.kt @@ -0,0 +1,175 @@ +package com.example.umc_7th.home + +import android.os.Build +import androidx.annotation.RequiresApi +import androidx.compose.foundation.Image +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.example.umc_7th.etc.Content +import com.example.umc_7th.R +import java.time.LocalDate +import java.time.format.DateTimeFormatter + +data class Content( + val title: String, + val author: String, + val image: Int, + val length: Int +) + +@RequiresApi(Build.VERSION_CODES.P) +@Composable +fun MainBanner( + title1: String, + date: LocalDate, + contentList: List, + backgroundImage: Painter, + textColor: Color, + MikeButtonClick: () -> Unit, + TicketButtonClick: () -> Unit, + SettingButtonClick: () -> Unit, + PlayButtonClick: () -> Unit +) { + Box { + Image( + painter = backgroundImage, + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier.fillMaxWidth() + ) + Column( + modifier = Modifier.padding(14.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.End + ) { + listOf( + MikeButtonClick to R.drawable.btn_main_mike, + TicketButtonClick to R.drawable.btn_main_ticket, + SettingButtonClick to R.drawable.btn_main_setting + ).forEach { (onClick, icon) -> + Icon( + painter = painterResource(id = icon), + contentDescription = null, + tint = textColor, + modifier = Modifier + .size(40.dp) + .padding(end = 8.dp) + .clickable { onClick() } + ) + } + } + Column { + Text( + text = title1, + style = TextStyle( + color = textColor, + fontSize = 29.sp, + fontWeight = FontWeight.Bold + ) + ) + } + Row( + modifier = Modifier + .fillMaxWidth() + .padding(end = 16.dp), + horizontalArrangement = Arrangement.End + ) { + IconButton( + onClick = PlayButtonClick, + modifier = Modifier.size(60.dp) + ) { + Icon( + painter = painterResource(id = R.drawable.btn_panel_play_large), + contentDescription = null, + tint = textColor + ) + } + } + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(10.dp) + ) { + Text(text = "총 ${contentList.size}곡", color = textColor) + Text( + text = date.format(DateTimeFormatter.ofPattern("yyyy.MM.dd")), + color = textColor + ) + } + LazyColumn( + verticalArrangement = Arrangement.spacedBy(16.dp), + modifier = Modifier.height(100.dp) + ) { + items(count = contentList.size) { index -> + val content = contentList[index] + Row( + verticalAlignment = Alignment.Top, + horizontalArrangement = Arrangement.spacedBy(16.dp), + modifier = Modifier.clickable { } + ) { + Image( + painter = painterResource(id = content.image), + contentDescription = null, + modifier = Modifier.size(40.dp) + ) + Column( + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + Text(text = content.title, color = textColor) + Text(text = content.author, color = textColor) + } + } + } + } + } + } +} + +@RequiresApi(Build.VERSION_CODES.P) +@Preview +@Composable +fun PreviewBanner() { + MainBanner( + title1 = "포근하게 덮어주는 꿈의 목소리", + date = LocalDate.parse("2019-11-11"), + contentList = List(15) { + Content( + title = "Butter", + author = "BTS", + image = R.drawable.img_album_exp, + length = 200 + ) + }, + backgroundImage = painterResource(id = R.drawable.img_default_4_x_1), + textColor = Color.White, + MikeButtonClick = { /* TODO */ }, + TicketButtonClick = { /* TODO */ }, + SettingButtonClick = { /* TODO */ }, + PlayButtonClick = { /* TODO */ } + ) +} diff --git a/app/src/main/java/com/example/umc_7th/home/Promotion.kt b/app/src/main/java/com/example/umc_7th/home/Promotion.kt new file mode 100644 index 0000000..a36d6b0 --- /dev/null +++ b/app/src/main/java/com/example/umc_7th/home/Promotion.kt @@ -0,0 +1,41 @@ +package com.example.umc_7th.home + +import androidx.compose.foundation.Image +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import com.example.umc_7th.R + +@Composable +fun Promotion( + image: Painter, + padding: Dp = 0.dp, + onClicked: () -> Unit +) { + Box(modifier = Modifier.padding(padding)) { + Image( + painter = image, + contentDescription = null, + modifier = Modifier.clickable { onClicked() } + ) + } +} + +@Preview(showBackground = true) +@Composable +fun PreviewPromotion() { + val image = painterResource(id = R.drawable.img_home_viewpager_exp2) + Promotion( + image = image, + padding = 8.dp, + onClicked = {} + ) +} + diff --git a/app/src/main/java/umc/study/umc_7th/sns.kt b/app/src/main/java/com/example/umc_7th/home/snsSharebar.kt similarity index 65% rename from app/src/main/java/umc/study/umc_7th/sns.kt rename to app/src/main/java/com/example/umc_7th/home/snsSharebar.kt index 39e9f31..1eecc4c 100644 --- a/app/src/main/java/umc/study/umc_7th/sns.kt +++ b/app/src/main/java/com/example/umc_7th/home/snsSharebar.kt @@ -1,40 +1,21 @@ -package umc.study.umc_7th +package com.example.umc_7th.home import android.os.Build import androidx.annotation.RequiresApi -import androidx.compose.foundation.Image import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.ImageBitmap -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.res.imageResource import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.LineBreak import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import java.time.LocalDate -import java.time.format.DateTimeFormatter +import com.example.umc_7th.R + @RequiresApi(Build.VERSION_CODES.P) @Composable fun snsSharebar( @@ -76,3 +57,5 @@ fun PreviewsnsSharebar(){ twitterClick = { /* */}) } + + diff --git a/app/src/main/java/com/example/umc_7th/locker/LockerFragement.kt b/app/src/main/java/com/example/umc_7th/locker/LockerFragement.kt new file mode 100644 index 0000000..33fd5c2 --- /dev/null +++ b/app/src/main/java/com/example/umc_7th/locker/LockerFragement.kt @@ -0,0 +1,171 @@ +// 파일 경로: com.example.umc_7th.locker + +package com.example.umc_7th.locker + +import android.annotation.SuppressLint +import androidx.compose.runtime.Composable +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Icon +import androidx.compose.material3.Tab +import androidx.compose.material3.TabRowDefaults +import androidx.compose.material3.TabRowDefaults.tabIndicatorOffset +import androidx.compose.material3.Text +import androidx.compose.material3.Scaffold +import androidx.compose.material3.ScrollableTabRow +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ImageBitmap +import androidx.compose.ui.res.imageResource +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.navigation.NavController +import kotlinx.coroutines.launch +import com.example.umc_7th.etc.Content +import com.example.umc_7th.R + +@Composable +fun LockerFragment1(){ + Column( + verticalArrangement = Arrangement.spacedBy(16.dp), + modifier = Modifier + .padding(16.dp) + .background(color = Color.White) + + ){ + Box( + modifier = Modifier.fillMaxWidth() + ){ + Row( + modifier = Modifier.align(Alignment.CenterStart) + ){ + Text(text = "보관함", fontWeight = FontWeight.Bold, color = Color.Black, fontSize = 24.sp) + } + Row( + modifier = Modifier.align(Alignment.CenterEnd) + ){ + Text(text = "로그인", color = Color.Blue) + } + } + } +} + +@Composable +fun LockerTab(){ + val pages= listOf("저장한 곡", "음악파일") + val pagerState= rememberPagerState { pages.size } + val coroutineScope = rememberCoroutineScope() + Column { + ScrollableTabRow( + selectedTabIndex = pagerState.currentPage, + containerColor = Color.White, + edgePadding = 0.dp, + indicator = { tabPositions -> + TabRowDefaults.Indicator( + modifier = Modifier + .tabIndicatorOffset(tabPositions[pagerState.currentPage]) + .padding(horizontal = tabPositions[pagerState.currentPage].width / 4), + color = Color.Blue, + height = 2.dp + ) + } + ) { + pages.forEachIndexed { index, title -> + Tab( + text = { Text(text = title, fontSize = 16.sp, color = if (pagerState.currentPage == index) Color.Blue else Color.Black) }, + selected = pagerState.currentPage == index, + onClick = { + coroutineScope.launch { pagerState.animateScrollToPage(index) } + } + ) + } + } + HorizontalPager(state = pagerState, modifier = Modifier.fillMaxWidth()) { page -> + when (page) { + 0 -> LockerMusic( + selectAllButtonClick = {}, + playAllButtonClick = {}, + contentList = listOf( + Content("Butter", "BTS", R.drawable.img_album_exp, 200), + Content("Next Level", "aespa", R.drawable.img_album_exp3, 210), + ) + ) + 1 -> Text("음악 파일") // Placeholder for music files page + } + } + } +} + +@Composable +fun LockerMusic( + selectAllButtonClick: () -> Unit, + playAllButtonClick: () -> Unit, + contentList: List +) { + Column( + modifier = Modifier + .fillMaxSize() + .padding(16.dp) + ) { + Row( + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxWidth() + ) { + Text( + text = "저장한 곡", + fontWeight = FontWeight.Bold, + fontSize = 20.sp, + color = Color.Black + ) + Row { + Text( + text = "전체 선택", + color = Color.Blue, + modifier = Modifier.clickable { selectAllButtonClick() } + ) + Spacer(modifier = Modifier.width(8.dp)) + Text( + text = "모두 재생", + color = Color.Blue, + modifier = Modifier.clickable { playAllButtonClick() } + ) + } + } + + LazyColumn { + items(contentList) { content -> + Row( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 8.dp) + ) { + content.image?.let { + Image( + painter = painterResource(id = it), + contentDescription = null, + modifier = Modifier.size(64.dp) + ) + } + Spacer(modifier = Modifier.width(8.dp)) + Column { + Text(text = content.title, fontWeight = FontWeight.Bold) + Text(text = content.author, color = Color.Gray) + } + } + } + } + } +} diff --git a/app/src/main/java/com/example/umc_7th/locker/LockerMusic.kt b/app/src/main/java/com/example/umc_7th/locker/LockerMusic.kt new file mode 100644 index 0000000..2209470 --- /dev/null +++ b/app/src/main/java/com/example/umc_7th/locker/LockerMusic.kt @@ -0,0 +1,178 @@ +package com.example.umc_7th.locker + +import android.annotation.SuppressLint +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateMapOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp + +import com.example.umc_7th.R + +// Content 클래스 정의 +data class Content( + val title: String, + val author: String, + val image: Int? // 이미지 리소스 ID (nullable) +) + +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@Composable +fun LockerMusic( + selectAllButtonClick: () -> Unit, + playAllButtonClick: () -> Unit, + contentList: List, +) { + var contentList by remember { mutableStateOf(contentList.toMutableList()) } + + Column( + modifier = Modifier + .fillMaxSize() + ) { + Box( + modifier = Modifier + .fillMaxWidth() + .padding(8.dp, vertical = 12.dp) + ) { + var selected by remember { mutableStateOf(false) } + Row { + Row( + modifier = Modifier + .clickable { selectAllButtonClick() } + ) { + Icon( + painter = painterResource( + id = if (!selected) R.drawable.btn_playlist_select_off + else R.drawable.btn_playlist_select_on + ), + contentDescription = null, + modifier = Modifier.size(23.dp) + ) + Text( + text = "전체 선택", + fontSize = 16.sp, + color = if (!selected) Color.Black.copy(0.5f) else Color.Blue + ) + } + Spacer(modifier = Modifier.width(16.dp)) + Row( + modifier = Modifier.clickable { playAllButtonClick() }, + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + painter = painterResource(id = R.drawable.icon_browse_arrow_right), + contentDescription = null, + modifier = Modifier.size(23.dp) + ) + Text( + text = "전체 듣기", + color = Color.Black.copy(0.5f), + fontSize = 16.sp + ) + } + } + + Row( + modifier = Modifier.align(Alignment.CenterEnd), + verticalAlignment = Alignment.CenterVertically + ) { + Text(text = "편집", fontSize = 16.sp, color = Color.Black.copy(0.5f)) + Spacer(modifier = Modifier.width(8.dp)) + } + } + + val itemStates = remember { mutableStateMapOf().apply { contentList.forEach { put(it, false) } } } + + LazyColumn( + verticalArrangement = Arrangement.spacedBy(8.dp), + modifier = Modifier.fillMaxWidth() + ) { + items(contentList) { content -> + val isSelected = itemStates[content] ?: false + Box( + modifier = Modifier + .fillMaxWidth() + .background(if (!isSelected) Color.Unspecified else Color.Blue.copy(0.05f)) + .clickable { itemStates[content] = !isSelected } + ) { + Row( + modifier = Modifier.padding(horizontal = 8.dp) + ) { + content.image?.let { + Image( + painter = painterResource(id = it), + contentDescription = null, + modifier = Modifier + .size(50.dp) + .clip(RoundedCornerShape(3.dp)) + ) + } + Column( + modifier = Modifier + .align(Alignment.CenterVertically) + .padding(horizontal = 8.dp) + ) { + Text( + text = content.title, + modifier = Modifier.padding(bottom = 2.dp), + fontWeight = FontWeight.Bold, + fontSize = 16.sp + ) + Text( + text = content.author, + color = Color.Black.copy(0.5f), + fontSize = 14.sp + ) + } + } + Row( + modifier = Modifier.align(Alignment.CenterEnd).padding(8.dp) + ) { + Icon( + painter = painterResource(id = R.drawable.btn_player_play), + contentDescription = null, + modifier = Modifier.size(30.dp) + ) + Icon( + painter = painterResource(id = R.drawable.btn_player_more), + contentDescription = null, + modifier = Modifier.size(30.dp).clickable { + contentList = contentList.filter { it != content }.toMutableList() + } + ) + } + } + Spacer(modifier = Modifier.padding(5.dp)) + } + } + } +} + + diff --git a/app/src/main/java/com/example/umc_7th/song/ContentFrame.kt b/app/src/main/java/com/example/umc_7th/song/ContentFrame.kt new file mode 100644 index 0000000..54b36ee --- /dev/null +++ b/app/src/main/java/com/example/umc_7th/song/ContentFrame.kt @@ -0,0 +1,108 @@ +package com.example.umc_7th.song + +import android.app.Application +import androidx.compose.foundation.Image +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.painterResource +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.example.umc_7th.R +import com.example.umc_7th.etc.FakeSongViewModel +import com.example.umc_7th.etc.SongViewModel + +@Composable +fun ContentFrame( + viewModel: SongViewModel, + toSingerinfoClick: () -> Unit, +) { + // LiveData 관찰 + val currentSong by viewModel.currentSong.observeAsState() + val like by viewModel.like.observeAsState(false) + val unLike by viewModel.unLike.observeAsState(false) + + currentSong?.let { content -> + Column(horizontalAlignment = Alignment.CenterHorizontally) { + Text( + text = content.title, + fontSize = 24.sp, + fontWeight = FontWeight.Bold + ) + + Row { + Text(text = content.author, fontSize = 18.sp) + Icon( + painter = painterResource(id = R.drawable.btn_arrow_more), + contentDescription = null, + modifier = Modifier.clickable { toSingerinfoClick() } + ) + } + Spacer(modifier = Modifier.height(18.dp)) + + content.image?.let { imageId -> + Image( + painter = painterResource(id = imageId), // 수정된 부분 + contentDescription = null, + modifier = Modifier + .size(220.dp) + .clip(RoundedCornerShape(20.dp)), + contentScale = ContentScale.Crop + ) + } + Spacer(modifier = Modifier.height(18.dp)) + + Row( + modifier = Modifier + .fillMaxWidth() + .size(36.dp), + horizontalArrangement = Arrangement.Center + ) { + IconButton(onClick = { viewModel.toggleLike() }) { + Image( + painter = painterResource(id = if (like) R.drawable.ic_my_like_on else R.drawable.ic_my_like_off), + contentDescription = null, + contentScale = ContentScale.Crop + ) + } + Spacer(modifier = Modifier.padding(10.dp)) + IconButton(onClick = { viewModel.toggleUnLike() }) { + Icon( + painter = painterResource(id = if (unLike) R.drawable.btn_player_unlike_off else R.drawable.btn_player_unlike_on), + contentDescription = null + ) + } + } + } + } ?: run { + Text( + text = "곡 정보가 없습니다.", + fontSize = 16.sp, + color = Color.Gray + ) + } +} + +@Composable +@Preview(showBackground = true) +fun PreviewContentFrame() { + // FakeSongViewModel을 사용하여 Preview에서 테스트 + ContentFrame( + viewModel = FakeSongViewModel(Application()), + toSingerinfoClick = {}, + ) +} + + + diff --git a/app/src/main/java/com/example/umc_7th/song/Lyric.kt b/app/src/main/java/com/example/umc_7th/song/Lyric.kt new file mode 100644 index 0000000..2e252ed --- /dev/null +++ b/app/src/main/java/com/example/umc_7th/song/Lyric.kt @@ -0,0 +1,39 @@ +package com.example.umc_7th.song + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.width +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp + +@Composable +fun Lyric( + lyric1 : String, + lyric2 : String, +){ + Column( + modifier = Modifier + .width(120.dp) + .height(50.dp), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally + + + ) { + Text(text = lyric1, textAlign = TextAlign.Center) + Text(text = lyric2, textAlign =TextAlign.Center) + } +} + +@Preview(showBackground = true) +@Composable +fun PreviewLyric(){ + Lyric(lyric1 = "내리는 꽃가루에", lyric2 = "눈이 따끔해 아야") + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/umc_7th/song/MiniPlayer.kt b/app/src/main/java/com/example/umc_7th/song/MiniPlayer.kt new file mode 100644 index 0000000..fc8fe25 --- /dev/null +++ b/app/src/main/java/com/example/umc_7th/song/MiniPlayer.kt @@ -0,0 +1,154 @@ +package com.example.umc_7th.song + +import android.os.Build +import androidx.annotation.RequiresApi +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.material3.Slider +import umc.study.umc_7th.Content +import umc.study.umc_7th.R +import umc.study.umc_7th.SongViewModel + + +@OptIn(ExperimentalMaterial3Api::class) +@RequiresApi(Build.VERSION_CODES.P) +@Composable +fun MiniPlayer( + viewModel: SongViewModel, + + beforeSongPlayButtonClick: () -> Unit, + playSongButtonClick: () -> Unit, + nextSongPlayButtonClick: () -> Unit, + musicQueueClick: () -> Unit, + toSongActivity: (Content) -> Unit, +){ + val currentSong by viewModel.currentSong.observeAsState() + + currentSong?.let{ content -> + Column { + val currentPosition by viewModel.currentPosition.observeAsState(0f) + val duration by viewModel.duration.observeAsState(1f) + + val progress = currentPosition / duration + + Slider( + value = progress, + onValueChange = { newProgress -> + viewModel.updatePosition(newProgress * duration) + }, + modifier = Modifier + .fillMaxWidth().height(3.dp), + thumb = {}, + ) + Box(modifier = Modifier.clickable {toSongActivity(content) } + ) + { + Row( + modifier = Modifier + .background(color = Color.White) + .fillMaxWidth() + .padding(horizontal = 15.dp, vertical = 8.dp), + horizontalArrangement = Arrangement.spacedBy(120.dp), + verticalAlignment = Alignment.CenterVertically + ){ + Column( + verticalArrangement = Arrangement.spacedBy(1.dp) + ){ + Text(text = content.title, + fontSize = 18.sp, + maxLines = 1, + overflow = TextOverflow.Ellipsis) + Text( + text = content.author, + fontSize = 15.sp, + style = TextStyle( + color = TextStyle.Default.color.copy(alpha = 0.5f) + ), + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + Row( + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ){ val played by viewModel.played.observeAsState(true) + Icon(painter = painterResource(id = R.drawable.btn_miniplayer_previous), + contentDescription = null, + modifier = Modifier + .size(50.dp) + .clickable { beforeSongPlayButtonClick() }) + Icon(painter = painterResource(id = if(played) R.drawable.btn_miniplay_pause + else R.drawable.btn_miniplayer_play + ), + contentDescription = null, + modifier = Modifier + .size(40.dp) + .clickable { + viewModel.togglePlayed() + playSongButtonClick() + }) + Icon(painter = painterResource(id = R.drawable.btn_miniplayer_next), + contentDescription = null, + modifier = Modifier + .size(50.dp) + .clickable { nextSongPlayButtonClick() }) + Icon(painter = painterResource(id = R.drawable.btn_miniplayer_go_list), + contentDescription = null, + modifier = Modifier + .size(45.dp) + .clickable { musicQueueClick() }) + } + } + } + } + }?:run { + Box(modifier = Modifier.fillMaxWidth() + .padding(16.dp).background(Color.LightGray)){ + Text(text="현재 재생 중인 곡이 없습니다.", + fontSize = 18.sp, + color= Color.Gray, + modifier = Modifier.align(Alignment.Center)) + } + } + + + + + +} + +//@RequiresApi(Build.VERSION_CODES.P) +//@Preview(showBackground = true) +//@Composable +//fun PreviewMiniPlayer(){ +// val fakeSongViewModel = FakeSongViewModel(application = Application()) +// MiniPlayer( +// viewModel = fakeSongViewModel, +// beforeSongPlayButtonClick = { /*TODO*/ }, +// playSongButtonClick = { /*TODO*/ }, +// nextSongPlayButtonClick = { /*TODO*/ }, +// musicQueueClick = { /*TODO*/ }, +// toSongActivity = {}) +//} \ No newline at end of file diff --git a/app/src/main/java/com/example/umc_7th/song/PlayProgreeBar.kt b/app/src/main/java/com/example/umc_7th/song/PlayProgreeBar.kt new file mode 100644 index 0000000..3d38829 --- /dev/null +++ b/app/src/main/java/com/example/umc_7th/song/PlayProgreeBar.kt @@ -0,0 +1,156 @@ +package com.example.umc_7th.song + +import android.app.Application +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.Slider +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import umc.study.umc_7th.FakeSongViewModel +import umc.study.umc_7th.R +import umc.study.umc_7th.SongViewModel + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun PlayProgressBar( + viewModel : SongViewModel, + beforeSongPlayClick : () -> Unit, + songPlayButtonClick: () -> Unit, + nextSongPlayClick : ()-> Unit, + + ){ + val replay by viewModel.replay.observeAsState(false) + val shuffle by viewModel.shuffle.observeAsState(false) + + val played by viewModel.played.observeAsState(false) + val currentPosition by viewModel.currentPosition.observeAsState(0f) + val duration by viewModel.duration.observeAsState(1f) + + var progress by remember { mutableStateOf(0f) } + +// LaunchedEffect(played){ +// if(played){ +// while ( played && currentPosition < duration){ +// delay(1000L) +// viewModel.updatePosition(currentPosition+1f) +// } +// } +// } + progress = currentPosition / duration + Slider( + value = progress, + onValueChange = { newProgress -> + viewModel.updatePosition(newProgress * duration) + }, + modifier = Modifier + .fillMaxWidth() + .height(3.dp), + thumb = { + + }, + ) + Row( + + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 5.dp, horizontal = 10.dp) + ){ + Text(text = formatTime(currentPosition), fontSize = 12.sp, color= Color.Blue) + Text(text = formatTime(duration), fontSize = 12.sp) + } + + Row( + modifier = Modifier + .fillMaxWidth() + .padding(top = 20.dp), + horizontalArrangement = Arrangement.Center, + ){ + + Icon( + painter = painterResource(id = R.drawable.nugu_btn_repeat_inactive), + contentDescription = null, + modifier = Modifier + .size(65.dp) + .padding(10.dp) + .clickable { viewModel.toggleReplay() } + , tint = if (replay) Color.Blue else Color.Black + ) + Spacer(modifier = Modifier.padding(10.dp)) + Icon( + painter = painterResource(id = R.drawable.nugu_btn_skip_previous_32), + contentDescription = null, + modifier = Modifier + .size(65.dp) + .padding(10.dp) + .clickable { beforeSongPlayClick() + } + + ) + + Icon( + painter = painterResource(id = if(played) R.drawable.nugu_btn_pause_32 + else R.drawable.nugu_btn_play_32 + ), + contentDescription = null, + modifier = Modifier + .size(65.dp) + .padding(10.dp) + .clickable { + viewModel.togglePlayed() + songPlayButtonClick() + } + ) + + Icon( + painter = painterResource(id = R.drawable.nugu_btn_skip_next_32), + contentDescription = null, + modifier = Modifier + .size(65.dp) + .padding(10.dp) + .clickable { nextSongPlayClick() } + ) + Spacer(modifier = Modifier.padding(10.dp)) + Icon( + painter = painterResource(id = R.drawable.nugu_btn_random_inactive), + contentDescription = null, + modifier = Modifier + .size(65.dp) + .padding(10.dp) + .clickable { viewModel.toggleShuffle() }, + tint = if (shuffle) Color.Blue else Color.Black + ) + + } +} + +@Preview(showBackground = true) +@Composable +fun PreviewPlayProgressBar(){ + val fakeSongViewModel = FakeSongViewModel(application = Application()) + PlayProgressBar( + viewModel = fakeSongViewModel, + beforeSongPlayClick = { /*TODO*/ }, + songPlayButtonClick = { /*TODO*/ }, + nextSongPlayClick = {} + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/umc_7th/song/SongActivity.kt b/app/src/main/java/com/example/umc_7th/song/SongActivity.kt new file mode 100644 index 0000000..da41e0b --- /dev/null +++ b/app/src/main/java/com/example/umc_7th/song/SongActivity.kt @@ -0,0 +1,120 @@ +package com.example.umc_7th.song + +import android.app.Application +import android.content.Intent +import android.os.Build +import android.os.Bundle +import androidx.activity.compose.setContent +import androidx.annotation.RequiresApi +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.verticalScroll +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import umc.study.umc_7th.ui.theme.Umc_7thTheme +import androidx.activity.ComponentActivity +import androidx.compose.foundation.rememberScrollState +import umc.study.umc_7th.FakeSongViewModel +import umc.study.umc_7th.MyApplication +import umc.study.umc_7th.SongViewModel +import umc.study.umc_7th.main.home.MainActivity +import umc.study.umc_7th.main.home.SongSnsBar + +class SongActivity : ComponentActivity() { + + @RequiresApi(Build.VERSION_CODES.P) + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val viewModel = (application as MyApplication).songViewModel + + setContent { + + Umc_7thTheme { + Box(){ + SongPlayerScreen( + viewModel= viewModel, + toMainActivity = { + val intent = Intent(this@SongActivity, MainActivity::class.java) + startActivity(intent) + finish() + },) + } + + + + + } + + } + } +} + + +@RequiresApi(Build.VERSION_CODES.P) +@Composable +fun SongPlayerScreen( + viewModel: SongViewModel, + toMainActivity : () -> Unit, +){ + Column (modifier = Modifier + .verticalScroll(rememberScrollState()) + .fillMaxHeight() + .padding(8.dp) + , + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(10.dp) + ){ + SongTopButton( + SettingButtonClick = {}, + eqButtonClick = {}, + songActivityToMainActivity = { toMainActivity() } + ) + + ContentFrame( + + toSingerinfoClick={}, + likeClick ={}, + unLikeButtonClick={}, + viewModel = viewModel + ) + + Lyric(lyric1 = "내리는 꽃가루에", lyric2 = "눈이 따끔해 아야") + + PlayProgressBar( + viewModel = viewModel, + beforeSongPlayClick = { /*TODO*/ }, + songPlayButtonClick = { /*TODO*/ }, + nextSongPlayClick = {} + ) + SongSnsBar( + instagramShareClick = { /*TODO*/ }, + similarSongButtonClick = { /*TODO*/ }, + musicQueueClick ={} + ) + } +} + + +fun formatTime(timeInSeconds:Float) : String{ + val minutes = (timeInSeconds / 60).toInt() + val seconds = (timeInSeconds % 60).toInt() + return String.format("%02d:%02d", minutes, seconds) +} + + +@RequiresApi(Build.VERSION_CODES.P) +@Preview(showBackground = true) +@Composable +fun PreviewSongPlayerScreen(){ + val fakeviewModel = FakeSongViewModel(application = Application()) + SongPlayerScreen( + viewModel = fakeviewModel, + toMainActivity = {}, + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/example/umc_7th/song/SongTopButton.kt b/app/src/main/java/com/example/umc_7th/song/SongTopButton.kt new file mode 100644 index 0000000..ef69a08 --- /dev/null +++ b/app/src/main/java/com/example/umc_7th/song/SongTopButton.kt @@ -0,0 +1,56 @@ +package com.example.umc_7th.song + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.size +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import umc.study.umc_7th.R + +@Composable +fun SongTopButton( + SettingButtonClick: () -> Unit, + eqButtonClick: () -> Unit, + songActivityToMainActivity: () -> Unit +){ + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween + ){ + Row( + horizontalArrangement = Arrangement.spacedBy(16.dp) + ) { + IconButton(onClick = SettingButtonClick, + modifier = Modifier.size(36.dp) + ) { + Icon( + painter = painterResource(id = R.drawable.btn_player_setting), + contentDescription = null, + + ) + } + IconButton(onClick = eqButtonClick, + modifier = Modifier.size(36.dp) + ) { + Icon( + painter = painterResource(id = R.drawable.btn_player_eq_off), + contentDescription = null, + modifier = Modifier + ) + } + } + IconButton(onClick = songActivityToMainActivity, + modifier = Modifier.size(36.dp) + ) { + Icon( + painter = painterResource(id = R.drawable.nugu_btn_down), + contentDescription = null, + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/umc/study/umc_7th/ui/theme/Color.kt b/app/src/main/java/com/example/umc_7th/ui/theme/Color.kt similarity index 59% rename from app/src/main/java/umc/study/umc_7th/ui/theme/Color.kt rename to app/src/main/java/com/example/umc_7th/ui/theme/Color.kt index 3f2460a..b7de884 100644 --- a/app/src/main/java/umc/study/umc_7th/ui/theme/Color.kt +++ b/app/src/main/java/com/example/umc_7th/ui/theme/Color.kt @@ -1,4 +1,4 @@ -package umc.study.umc_7th.ui.theme +package com.example.umc_7th.ui.theme import androidx.compose.ui.graphics.Color @@ -8,4 +8,7 @@ val Pink80 = Color(0xFFEFB8C8) val Purple40 = Color(0xFF6650a4) val PurpleGrey40 = Color(0xFF625b71) -val Pink40 = Color(0xFF7D5260) \ No newline at end of file +val Pink40 = Color(0xFF7D5260) + +// 추가할 파란색 정의 +val Flo = Color(0xFF004AD) // 색상 코드 추가 diff --git a/app/src/main/java/umc/study/umc_7th/ui/theme/Theme.kt b/app/src/main/java/com/example/umc_7th/ui/theme/Theme.kt similarity index 97% rename from app/src/main/java/umc/study/umc_7th/ui/theme/Theme.kt rename to app/src/main/java/com/example/umc_7th/ui/theme/Theme.kt index c62117a..106792a 100644 --- a/app/src/main/java/umc/study/umc_7th/ui/theme/Theme.kt +++ b/app/src/main/java/com/example/umc_7th/ui/theme/Theme.kt @@ -1,4 +1,4 @@ -package umc.study.umc_7th.ui.theme +package com.example.umc_7th.ui.theme import android.app.Activity import android.os.Build diff --git a/app/src/main/java/umc/study/umc_7th/ui/theme/Type.kt b/app/src/main/java/com/example/umc_7th/ui/theme/Type.kt similarity index 96% rename from app/src/main/java/umc/study/umc_7th/ui/theme/Type.kt rename to app/src/main/java/com/example/umc_7th/ui/theme/Type.kt index 0242850..1f4399a 100644 --- a/app/src/main/java/umc/study/umc_7th/ui/theme/Type.kt +++ b/app/src/main/java/com/example/umc_7th/ui/theme/Type.kt @@ -1,4 +1,4 @@ -package umc.study.umc_7th.ui.theme +package com.example.umc_7th.ui.theme import androidx.compose.material3.Typography import androidx.compose.ui.text.TextStyle diff --git a/app/src/main/java/umc/study/umc_7th/Content.kt b/app/src/main/java/umc/study/umc_7th/Content.kt deleted file mode 100644 index ed4fa5a..0000000 --- a/app/src/main/java/umc/study/umc_7th/Content.kt +++ /dev/null @@ -1,22 +0,0 @@ -package umc.study.umc_7th - -import androidx.compose.ui.graphics.ImageBitmap -import java.time.LocalDate -import java.util.Date -import java.util.Dictionary - -data class Content( - val title: String, - val author : String, - val image: ImageBitmap?= null, - val length: Int, -) - -data class Album ( - val albumTitle : String, - val date : LocalDate, - val author : String, - val albumImage: ImageBitmap, - val trackList : List, - val titleTrackList : List -) \ No newline at end of file diff --git a/app/src/main/java/umc/study/umc_7th/HorizontalCollection.kt b/app/src/main/java/umc/study/umc_7th/HorizontalCollection.kt deleted file mode 100644 index 490dbe9..0000000 --- a/app/src/main/java/umc/study/umc_7th/HorizontalCollection.kt +++ /dev/null @@ -1,341 +0,0 @@ -package umc.study.umc_7th - -import android.icu.text.UnicodeSetSpanner.CountMethod -import android.os.Build -import androidx.annotation.RequiresApi -import androidx.compose.foundation.Image -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.lazy.LazyRow -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.text.ClickableText -import androidx.compose.material3.Icon -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.ImageBitmap -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.layout.onGloballyPositioned -import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.res.imageResource -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.AnnotatedString -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp - - -enum class BaseLocationCategory( - val mean : String -){ - GLOABAL(mean = "종합"), - DOMESTIC(mean = "국내"), - FOREIGN(mean = "해외"), -} -@RequiresApi(Build.VERSION_CODES.P) -@Composable -fun LocationMusicContentView( - title : String, - contentList : List, - baseLocationCategory: BaseLocationCategory, - viewTitleClick : () -> Unit, - contentClick : (Content) -> Unit, - categoryClick : (BaseLocationCategory) -> Unit, -){ - horizontalScrollContentView( - contentList = contentList, - titleBar = { - Row ( - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .padding(horizontal = 16.dp, vertical = 5.dp) - .fillMaxWidth() - ){ - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(4.dp), - modifier = Modifier.clickable { viewTitleClick() } - ){ - Text( - text = title, - style = TextStyle( - fontSize = 18.sp, - fontWeight = FontWeight.Bold, - ) - ) - Icon( - painter = painterResource(id = R.drawable.btn_main_arrow_more), - contentDescription = null, - modifier = Modifier.size(16.dp) - ) - } - Row( - horizontalArrangement = Arrangement.spacedBy(16.dp) - ){ - BaseLocationCategory.entries.forEach{ category -> - ClickableText( - text = AnnotatedString(category.mean), - onClick = { categoryClick(category)}, - style = TextStyle( - color = if(category == baseLocationCategory) Color.Blue else Color.Unspecified - ) - ) - } - } - } - }, - thumbnail = { content -> - Box( - contentAlignment = Alignment.BottomEnd, - ){ - content.image?.let { - Image(bitmap = it, - contentDescription = null, - contentScale = ContentScale.Crop, - modifier = Modifier - .size(128.dp) - .clip(RoundedCornerShape(8.dp)) - ) - } - Icon( - painter = painterResource(id = R.drawable.btn_miniplayer_play), - contentDescription = null, - tint = Color.White, - modifier = Modifier.size(48.dp) - ) - } - }, - contentClick = contentClick, - ) -} - -@RequiresApi(Build.VERSION_CODES.P) -@Composable -fun PodcastCollectionView( - title : String, - contentList: List, - contentClick: (Content) -> Unit, -){ - horizontalScrollContentView(contentList = contentList , - titleBar = { - Row( - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.padding(horizontal = 16.dp) - ){ - Text( - text = title, - style = TextStyle( - fontSize = 18.sp, - fontWeight = FontWeight.Bold, - ) - ) - } - }, - thumbnail = { content -> - content.image?.let { - Image(bitmap = it, - contentScale = ContentScale.Crop, - contentDescription =null, - modifier = Modifier - .size(128.dp) - .clip(RoundedCornerShape(8.dp)) - ) - } - }, - contentClick = contentClick, - ) -} - -@RequiresApi(Build.VERSION_CODES.P) -@Composable -fun VideoCollectionView( - title : String, - contentList : List, - contentClick: (Content) -> Unit, -){ - horizontalScrollContentView(contentList =contentList , - titleBar = { - Row( - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.padding(horizontal = 16.dp) - ){ - Text( - text = title, - style = TextStyle( - fontSize = 18.sp, - fontWeight = FontWeight.Bold, - ) - ) - } - }, - thumbnail = { content -> - Box(contentAlignment = Alignment.BottomEnd){ - content.image?.let { - Image(bitmap = it, - contentDescription = null, - contentScale = ContentScale.FillHeight, - modifier = Modifier - .width(228.dp) - .height(128.dp) - .clip(RoundedCornerShape(8.dp)) - ) - } - Box( - modifier = Modifier - .padding(8.dp) - .background(color = Color.Black.copy(alpha = 0.5f)) - ){ - Text( - text = "${"%02d".format(content.length/60)}:${content.length%60}", - style = TextStyle( - fontSize = 10.sp, - color = Color.White, - ), - modifier = Modifier.padding(4.dp), - ) - } - } - }, - contentClick= contentClick - ) -} - -@RequiresApi(Build.VERSION_CODES.P) -@Composable -private fun horizontalScrollContentView( - contentList: List, - titleBar : @Composable () -> Unit, - thumbnail : @Composable (Content) -> Unit, - contentClick: (Content) -> Unit -) { - val density = LocalDensity.current - var contentWidth by remember { mutableStateOf(0.dp) } - - Column( - verticalArrangement = Arrangement.spacedBy(4.dp), - modifier = Modifier.padding(vertical = 18.dp) - ) { - titleBar() - LazyRow( - horizontalArrangement = Arrangement.spacedBy(16.dp), - ){ - item { Spacer(modifier = Modifier.width(0.dp))} - items(count = contentList.size){ index -> - val content = contentList[index] - Column( - verticalArrangement = Arrangement.spacedBy(8.dp), - modifier = Modifier.clickable { contentClick(content) } - ) { - Box( - modifier = Modifier.onGloballyPositioned { - with(density) { contentWidth = it.size.width.toDp() } - } - ){ - thumbnail(content) - } - Column (verticalArrangement = Arrangement.spacedBy(4.dp), - modifier = Modifier.width(contentWidth) - ) { - Text( - text = content.title, - style = TextStyle( - fontSize = 18.sp, - ), - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) - Text( - text = content.author, - style = TextStyle( - color = TextStyle.Default.color.copy(alpha = 0.5f) - ), - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) - } - } - } - item { Spacer(modifier = Modifier.width(0.dp))} - } - } -} - -@RequiresApi(Build.VERSION_CODES.P) -@Preview(showBackground = true) -@Composable -fun PreviewLocationMusicContentView(){ - LocationMusicContentView( - title = "오늘 발매 음악", - contentList = List(15){ - Content( - title = "LILAC", - author = "아이유(IU)", - image = ImageBitmap.imageResource(id = R.drawable.img_album_exp2), - length = 200 - ) - }, - baseLocationCategory = BaseLocationCategory.GLOABAL , - viewTitleClick = { }, - contentClick ={}, - categoryClick = {} - ) -} - -@RequiresApi(Build.VERSION_CODES.P) -@Preview(showBackground = true) -@Composable -fun PreviewPodcastCollectionView(){ - PodcastCollectionView( - title = "매일 들어도 좋은 팟캐스트" , - contentList = List(15){ - Content( - title = "김시선의 귀책사유 FLO X 윌라", - author= "김시선", - image = ImageBitmap.imageResource(id = R.drawable.img_potcast_exp), - length = 200, - ) - }, - contentClick = {} - ) -} -@RequiresApi(Build.VERSION_CODES.P) -@Preview(showBackground = true) -@Composable -fun PreviewVideoCollectionView(){ - VideoCollectionView( - title ="비디오 콜렉션" , - contentList =List(15){ - Content( - title = "제목", - author = "가수", - image = ImageBitmap.imageResource(id = R.drawable.img_video_exp), - length = 200, - ) - } , - contentClick = {} - ) -} - diff --git a/app/src/main/java/umc/study/umc_7th/Promo.kt b/app/src/main/java/umc/study/umc_7th/Promo.kt deleted file mode 100644 index 677443f..0000000 --- a/app/src/main/java/umc/study/umc_7th/Promo.kt +++ /dev/null @@ -1,41 +0,0 @@ -package umc.study.umc_7th - -import android.os.Build -import android.provider.ContactsContract.CommonDataKinds.Im -import androidx.annotation.RequiresApi -import androidx.compose.foundation.Image -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.padding -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.ImageBitmap -import androidx.compose.ui.res.imageResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.dp - -@RequiresApi(Build.VERSION_CODES.P) -@Composable -fun Promotion( - image : ImageBitmap, - padding: Dp = 0.dp, - onClicked: ()-> Unit -) { - Box(modifier = Modifier - ) - { - Image( - bitmap = image, - contentDescription =null, - modifier = Modifier.clickable { onClicked() } - ) - } -} -@RequiresApi(Build.VERSION_CODES.P) -@Preview(showBackground = true) -@Composable -fun PreviewPromotion(){ - Promotion(image = ImageBitmap.imageResource(id = R.drawable.img_home_viewpager_exp2), - onClicked = {},) -} \ No newline at end of file diff --git a/app/src/main/res/drawable/textview_background_select_color_radius.xml b/app/src/main/res/drawable/textview_background_select_color_radius.xml index 70a0481..5f8e3d1 100644 --- a/app/src/main/res/drawable/textview_background_select_color_radius.xml +++ b/app/src/main/res/drawable/textview_background_select_color_radius.xml @@ -4,10 +4,10 @@ - + + diff --git a/app/src/main/res/layout/_7th.xml b/app/src/main/res/layout/_7th.xml deleted file mode 100644 index 77d9ef6..0000000 --- a/app/src/main/res/layout/_7th.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index d60b4b8..dbf9837 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -1,7 +1,5 @@ - #3f3fff - #FFBB86FC #FF6200EE #FF3700B3 @@ -9,17 +7,5 @@ #FF018786 #FF000000 #FFFFFFFF - - #9cbee2 - #062342 - #424242 - #6bb2ff - - #00ff0000 - #3f3fff - #a8a8a8 - #3f3fff - #a8a8a8 - - #F11818 + #004AAD \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9ac5010..42d1852 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,3 +1,3 @@ - FLO + umc_7th \ No newline at end of file diff --git a/app/src/test/java/umc/study/umc_7th/ExampleUnitTest.kt b/app/src/test/java/com/example/umc_7th/ExampleUnitTest.kt similarity index 91% rename from app/src/test/java/umc/study/umc_7th/ExampleUnitTest.kt rename to app/src/test/java/com/example/umc_7th/ExampleUnitTest.kt index 43256d8..e154618 100644 --- a/app/src/test/java/umc/study/umc_7th/ExampleUnitTest.kt +++ b/app/src/test/java/com/example/umc_7th/ExampleUnitTest.kt @@ -1,4 +1,4 @@ -package umc.study.umc_7th +package com.example.umc_7th import org.junit.Test diff --git a/build.gradle.kts b/build.gradle.kts index 8adda76..da307e6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { alias(libs.plugins.android.application) apply false - alias(libs.plugins.jetbrains.kotlin.android) apply false + alias(libs.plugins.kotlin.android) apply false // 수정된 부분 id("com.google.dagger.hilt.android") version "2.49" apply false id("com.google.devtools.ksp") version "1.9.0-1.0.13" apply false } @@ -9,11 +9,11 @@ plugins { buildscript { repositories { google() + mavenCentral() // mavenCentral()도 추가하면 좋습니다. } dependencies { val nav_version = "2.7.7" classpath("androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version") - // - classpath("androidx.navigation:navigation-safe-args-gradle-plugin:2.7.3") } -} \ No newline at end of file +} + diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 823db7d..d84dca5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,22 +1,24 @@ [versions] -agp = "8.5.1" +agp = "8.6.0" kotlin = "1.9.0" -coreKtx = "1.13.1" +coreKtx = "1.10.1" junit = "4.13.2" -junitVersion = "1.2.1" -espressoCore = "3.6.1" -lifecycleRuntimeKtx = "2.8.6" -activityCompose = "1.9.2" +junitVersion = "1.1.5" +espressoCore = "3.5.1" +lifecycleRuntimeKtx = "2.6.1" +activityCompose = "1.8.0" composeBom = "2024.04.01" -appcompat = "1.7.0" -material = "1.12.0" -constraintlayout = "2.1.4" -lifecycleLivedataKtx = "2.8.3" -lifecycleViewmodelKtx = "2.8.3" -navigationFragmentKtx = "2.7.7" -navigationUiKtx = "2.7.7" -activity = "1.8.0" -constraintlayoutCompose = "1.0.1" +appcompat = "1.6.1" # 추가: appcompat 버전 +material = "1.9.0" # 추가: material 버전 +constraintlayout = "2.1.4" # 추가: constraintlayout 버전 +lifecycleLivedataKtx = "2.6.1" # 추가: lifecycle-livedata-ktx 버전 +lifecycleViewmodelKtx = "2.6.1" # 추가: lifecycle-viewmodel-ktx 버전 +navigationFragmentKtx = "2.7.2" # 추가: navigation-fragment-ktx 버전 +navigationUiKtx = "2.7.2" # 추가: navigation-ui-ktx 버전 +activity = "1.8.0" # 추가: activity 버전 +constraintlayoutCompose = "1.0.1" # 추가: constraintlayout-compose 버전 +navigationCompose = "2.7.2" # 추가: navigation-compose 버전 +runtimeLivedata = "2.6.1" # 추가: runtime-livedata 버전 [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } @@ -42,8 +44,10 @@ androidx-navigation-fragment-ktx = { group = "androidx.navigation", name = "navi androidx-navigation-ui-ktx = { group = "androidx.navigation", name = "navigation-ui-ktx", version.ref = "navigationUiKtx" } androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" } androidx-constraintlayout-compose = { group = "androidx.constraintlayout", name = "constraintlayout-compose", version.ref = "constraintlayoutCompose" } +androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" } +androidx-runtime-livedata = { group = "androidx.compose.runtime", name = "runtime-livedata", version.ref = "runtimeLivedata" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" } -jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } - +kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } +kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c10190b..cc83aaa 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,4 +1,4 @@ -#Tue Sep 24 20:15:58 KST 2024 +#Tue Oct 29 16:40:55 KST 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/gradlew.bat b/gradlew.bat index 107acd3..ac1b06f 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,89 +1,89 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega