diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 0164e11e..69c4d0fb 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -12,6 +12,8 @@
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28"
tools:ignore="ScopedStorage" />
+
+
Unit = {},
onBookmarkClick: () -> Unit = {},
onDeleteClick: () -> Unit = {},
+ onMoreClick: () -> Unit = {},
) {
var boxSize by remember { mutableStateOf(IntSize.Zero) }
var expanded by remember { mutableStateOf(false) }
@@ -128,6 +129,14 @@ fun RecordyVideoText(
style = RecordyTheme.typography.body2M,
color = RecordyTheme.colors.gray01,
)
+ Spacer(modifier = Modifier.height(8.dp))
+ Icon(
+ modifier = Modifier
+ .customClickable { onMoreClick() },
+ painter = painterResource(id = R.drawable.ic_seemore),
+ contentDescription = "see more",
+ tint = RecordyTheme.colors.gray01,
+ )
Spacer(modifier = Modifier.height(if (isMyVideo) 16.dp else 20.dp))
if (isMyVideo) {
Icon(
diff --git a/core/designsystem/src/main/res/drawable/ic_seemore.xml b/core/designsystem/src/main/res/drawable/ic_seemore.xml
new file mode 100644
index 00000000..6261dcb5
--- /dev/null
+++ b/core/designsystem/src/main/res/drawable/ic_seemore.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
diff --git a/core/designsystem/src/main/res/drawable/ic_viskit_logo.xml b/core/designsystem/src/main/res/drawable/ic_viskit_logo.xml
new file mode 100644
index 00000000..08e2a383
--- /dev/null
+++ b/core/designsystem/src/main/res/drawable/ic_viskit_logo.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/feature/home/build.gradle.kts b/feature/home/build.gradle.kts
index 141c606f..1e5bd6cf 100644
--- a/feature/home/build.gradle.kts
+++ b/feature/home/build.gradle.kts
@@ -11,4 +11,5 @@ dependencies {
implementation(projects.domain.keyword)
implementation(libs.lottie.compose)
implementation(libs.collapsing.toolbar)
+ implementation(libs.google.location)
}
diff --git a/feature/home/src/main/AndroidManifest.xml b/feature/home/src/main/AndroidManifest.xml
index a5918e68..769b825c 100644
--- a/feature/home/src/main/AndroidManifest.xml
+++ b/feature/home/src/main/AndroidManifest.xml
@@ -1,4 +1,5 @@
-
\ No newline at end of file
+
+
diff --git a/feature/home/src/main/java/com/record/home/Exhibition.kt b/feature/home/src/main/java/com/record/home/Exhibition.kt
new file mode 100644
index 00000000..c1378fa2
--- /dev/null
+++ b/feature/home/src/main/java/com/record/home/Exhibition.kt
@@ -0,0 +1,12 @@
+package com.record.home
+
+import com.record.video.model.VideoData
+import kotlinx.collections.immutable.ImmutableList
+import kotlinx.collections.immutable.toImmutableList
+
+data class Exhibition(
+ val location: String,
+ val name: String,
+ val exhibitionCount: Int,
+ val userVideo: ImmutableList = emptyList().toImmutableList(),
+)
diff --git a/feature/home/src/main/java/com/record/home/HomeContract.kt b/feature/home/src/main/java/com/record/home/HomeContract.kt
index 5da09f9c..d4e54b50 100644
--- a/feature/home/src/main/java/com/record/home/HomeContract.kt
+++ b/feature/home/src/main/java/com/record/home/HomeContract.kt
@@ -1,22 +1,20 @@
package com.record.home
-import com.record.model.VideoType
import com.record.ui.base.SideEffect
import com.record.ui.base.UiState
-import com.record.video.model.VideoData
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
data class HomeState(
- val chipList: ImmutableList = listOf("전체").toImmutableList(),
- val popularList: ImmutableList = emptyList().toImmutableList(),
- val recentList: ImmutableList = emptyList().toImmutableList(),
- val selectedChipIndex: Int? = 0,
+ val exhibitionList: ImmutableList = emptyList().toImmutableList(),
val isLoading: Boolean = false,
+ val location: Location = Location(0.0, 0.0),
+ val showLocationPermissionDialog: Boolean = true,
) : UiState
sealed interface HomeSideEffect : SideEffect {
data object navigateToUpload : HomeSideEffect
- data class navigateToVideo(val id: Long, val type: VideoType, val keyword: String?) : HomeSideEffect
- data object collapseToolbar : HomeSideEffect
+ data class navigateToVideo(val id: Long, val location: String) : HomeSideEffect
+ data class navigateToDetail(val id: Long) : HomeSideEffect
+ data object launchSettingIntent : HomeSideEffect
}
diff --git a/feature/home/src/main/java/com/record/home/HomeScreen.kt b/feature/home/src/main/java/com/record/home/HomeScreen.kt
index c4e509b9..03f3a148 100644
--- a/feature/home/src/main/java/com/record/home/HomeScreen.kt
+++ b/feature/home/src/main/java/com/record/home/HomeScreen.kt
@@ -1,67 +1,54 @@
package com.record.home
-import androidx.compose.foundation.Image
+import android.Manifest
+import android.content.pm.PackageManager
+import android.location.Location
+import android.util.Log
+import androidx.activity.compose.rememberLauncherForActivityResult
+import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
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.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow
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.rememberCoroutineScope
-import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.alpha
-import androidx.compose.ui.graphics.Brush
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalConfiguration
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
-import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
+import androidx.core.app.ActivityCompat
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
-import com.airbnb.lottie.compose.LottieAnimation
-import com.airbnb.lottie.compose.LottieCompositionSpec
-import com.airbnb.lottie.compose.LottieConstants
-import com.airbnb.lottie.compose.animateLottieCompositionAsState
-import com.airbnb.lottie.compose.rememberLottieComposition
+import com.google.android.gms.location.FusedLocationProviderClient
+import com.google.android.gms.location.LocationServices
import com.record.designsystem.R
import com.record.designsystem.component.RecordyVideoThumbnail
-import com.record.designsystem.component.button.RecordyChipButton
+import com.record.designsystem.component.dialog.RecordyDialog
import com.record.designsystem.theme.RecordyTheme
-import com.record.home.component.UploadFloatingButton
import com.record.model.VideoType
-import com.record.ui.extension.customClickable
import com.record.ui.lifecycle.LaunchedEffectWithLifecycle
import com.record.video.model.VideoData
+import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.collectLatest
-import kotlinx.coroutines.launch
-import me.onebone.toolbar.CollapsingToolbarScaffold
-import me.onebone.toolbar.CollapsingToolbarScaffoldState
-import me.onebone.toolbar.CollapsingToolbarScope
-import me.onebone.toolbar.ExperimentalToolbarApi
-import me.onebone.toolbar.ScrollStrategy
-import me.onebone.toolbar.rememberCollapsingToolbarScaffoldState
-@OptIn(ExperimentalToolbarApi::class)
@Composable
fun HomeRoute(
padding: PaddingValues,
@@ -71,283 +58,158 @@ fun HomeRoute(
navigateToUpload: () -> Unit = {},
) {
val state by viewModel.uiState.collectAsStateWithLifecycle()
- val toolbarScaffoldState = rememberCollapsingToolbarScaffoldState()
val coroutineScope = rememberCoroutineScope()
+
LaunchedEffectWithLifecycle {
- viewModel.getVideos()
viewModel.sideEffect.collectLatest { sideEffect ->
when (sideEffect) {
HomeSideEffect.navigateToUpload -> navigateToUpload()
is HomeSideEffect.navigateToVideo -> {
- navigateToVideoDetail(sideEffect.type, sideEffect.id, sideEffect.keyword, 0)
+ // navigateToVideoDetail(sideEffect.type, sideEffect.id, sideEffect.keyword, 0)
}
- HomeSideEffect.collapseToolbar -> {
- coroutineScope.launch {
- toolbarScaffoldState.toolbarState.collapse(500)
- }
- }
+ HomeSideEffect.launchSettingIntent -> TODO()
+ is HomeSideEffect.navigateToDetail -> TODO()
}
}
}
HomeScreen(
modifier = modifier.padding(bottom = padding.calculateBottomPadding()),
state = state,
- toolbarState = toolbarScaffoldState,
- onUploadButtonClick = viewModel::navigateToUpload,
- onChipButtonClick = viewModel::selectCategory,
- onVideoClick = viewModel::navigateToVideo,
- onBookmarkClick = viewModel::bookmark,
+ showLocationPermissionDialog = viewModel::showLocationPermissionDialog,
+ updateLocation = viewModel::updateLocation,
)
}
@Composable
fun HomeScreen(
modifier: Modifier = Modifier,
- toolbarState: CollapsingToolbarScaffoldState,
state: HomeState,
- onUploadButtonClick: () -> Unit,
- onChipButtonClick: (Int) -> Unit,
- onVideoClick: (Long, VideoType) -> Unit,
- onBookmarkClick: (Long) -> Unit,
+ showLocationPermissionDialog: (Boolean) -> Unit,
+ updateLocation: (Double, Double) -> Unit,
) {
- var boxSize by remember {
- mutableStateOf(IntSize.Zero)
- }
- Box(
- modifier = modifier
- .fillMaxSize()
- .onGloballyPositioned { layoutCoordinates ->
- boxSize = layoutCoordinates.size
+ val configuration = LocalConfiguration.current
+ val screenWidth = configuration.screenWidthDp.dp
+ val context = LocalContext.current
+ val launcher = rememberLauncherForActivityResult(
+ contract = ActivityResultContracts.RequestPermission(),
+ ) { isGranted ->
+ if (isGranted) {
+ val fusedLocationClient: FusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(context)
+
+ // 위치 정보 요청
+ if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
+ return@rememberLauncherForActivityResult
}
- .background(
- brush = Brush.verticalGradient(
- listOf(Color(0x339babfb), Color(0x00000000)),
- startY = boxSize.height.toFloat() * 0.0f,
- endY = boxSize.height.toFloat() * 0.3f,
- ),
- ),
- ) {
- BackgroundAnimation()
- CollapsingToolbar(
- toolbarState = toolbarState,
- state = state,
- onChipButtonClick = onChipButtonClick,
- onVideoClick = onVideoClick,
- onBookmarkClick = onBookmarkClick,
- )
- UploadFloatingButton(
- modifier = Modifier
- .align(Alignment.BottomEnd)
- .padding(bottom = 15.dp, end = 16.dp),
- onClick = onUploadButtonClick,
- )
- if (state.isLoading) {
- LoadingLottie()
+ fusedLocationClient.lastLocation.addOnSuccessListener { location: Location? ->
+ location?.let {
+ updateLocation(it.latitude, it.longitude)
+ Log.e("위치", "${it.latitude} ${it.longitude}")
+ }
+ }
+ showLocationPermissionDialog(false)
+ } else {
+ showLocationPermissionDialog(true)
}
}
-}
-
-@Composable
-fun BoxScope.BackgroundAnimation() {
- val composition by rememberLottieComposition(spec = LottieCompositionSpec.RawRes(R.raw.bubble))
- val progress by animateLottieCompositionAsState(
- composition,
- iterations = LottieConstants.IterateForever,
- speed = 1.0f,
- )
- LottieAnimation(
- composition,
- { progress },
- modifier = Modifier
- .align(Alignment.TopCenter),
- )
-}
-
-@Composable
-fun LoadingLottie() {
- val composition by rememberLottieComposition(spec = LottieCompositionSpec.RawRes(R.raw.loading_lotties))
- val progress by animateLottieCompositionAsState(
- composition,
- iterations = LottieConstants.IterateForever,
- speed = 4.0f,
- )
- Box(
- modifier = Modifier
- .fillMaxSize()
- .customClickable(rippleEnabled = false) {}
- .background(color = RecordyTheme.colors.black50),
- ) {
- LottieAnimation(
- composition,
- { progress },
- modifier = Modifier
- .align(Alignment.Center),
- )
- }
-}
-@Composable
-fun CollapsingToolbar(
- toolbarState: CollapsingToolbarScaffoldState,
- state: HomeState,
- onChipButtonClick: (Int) -> Unit,
- onVideoClick: (Long, VideoType) -> Unit,
- onBookmarkClick: (Long) -> Unit,
-) {
- CollapsingToolbarScaffold(
- modifier = Modifier
- .fillMaxSize(),
- state = toolbarState,
- scrollStrategy = ScrollStrategy.ExitUntilCollapsed,
- enabled = true,
- toolbar = {
- ToolbarContent(toolbarState)
- },
- ) {
- ChipRow(toolbarState, state.chipList, state.selectedChipIndex, onChipButtonClick)
- Content(
- state = state,
- onVideoClick = onVideoClick,
- onBookmarkClick = onBookmarkClick,
+ LaunchedEffectWithLifecycle {
+ launcher.launch(
+ Manifest.permission.ACCESS_FINE_LOCATION,
)
}
-}
-@Composable
-fun CollapsingToolbarScope.ToolbarContent(toolbarState: CollapsingToolbarScaffoldState) {
- val topPadding = (32 + 12 * toolbarState.toolbarState.progress).dp
- val alpha = toolbarState.toolbarState.progress * 2 - 0.5f
- Image(
- painter = painterResource(R.drawable.ic_recordy_logo),
- contentDescription = "logo",
- modifier = Modifier
- .padding(start = 16.dp, top = topPadding, bottom = 12.dp)
- .pin(),
- )
Box(
- modifier = Modifier
- .fillMaxWidth()
- .height(246.dp)
- .road(Alignment.CenterEnd, Alignment.BottomStart)
- .alpha(alpha)
- .padding(start = 16.dp),
+ modifier = modifier
+ .fillMaxSize(),
) {
- Row(
+ LazyColumn(
modifier = Modifier
- .fillMaxWidth()
- .align(Alignment.BottomCenter),
- horizontalArrangement = Arrangement.SpaceBetween,
- verticalAlignment = Alignment.Bottom,
+ .fillMaxSize(),
) {
- Text(
- text = "오늘은 어떤 키워드로\n공간을 둘러볼까요?",
- modifier = Modifier
- .weight(192f)
- .padding(bottom = 28.dp),
- style = RecordyTheme.typography.title1,
- color = RecordyTheme.colors.white,
- )
-
- Image(
- modifier = Modifier
- .weight(140f)
- .padding(end = 12.dp),
- painter = painterResource(R.drawable.img_home_graphic),
- contentDescription = "home",
- )
+ item {
+ Box {
+ Icon(
+ modifier = Modifier
+ .align(Alignment.CenterStart)
+ .padding(start = 16.dp)
+ .padding(top = 66.dp, bottom = 32.dp),
+ painter = painterResource(id = R.drawable.ic_viskit_logo),
+ tint = RecordyTheme.colors.viskitYellow500,
+ contentDescription = "logo",
+ )
+ }
+ }
+ itemsIndexed(state.exhibitionList) { i, exhibition ->
+ ExhibitionContatiner(exhibition, screenWidth)
+ }
}
- }
-}
-@OptIn(ExperimentalToolbarApi::class)
-@Composable
-fun ChipRow(
- state: CollapsingToolbarScaffoldState,
- chipList: List,
- selectedChip: Int?,
- onChipButtonClick: (Int) -> Unit,
-) {
- LazyRow(
- modifier = Modifier
- .padding(bottom = 12.dp),
- horizontalArrangement = Arrangement.spacedBy(8.dp),
- ) {
- item { Spacer(modifier = Modifier.width(8.dp)) }
- itemsIndexed(chipList) { i, item ->
- RecordyChipButton(
- text = item,
- isActive = selectedChip == i,
- onClick = {
- onChipButtonClick(i)
- },
+ if (state.showLocationPermissionDialog) {
+ RecordyDialog(
+ graphicAsset = R.drawable.img_trashcan,
+ title = "필수 권한 허용해 주세요",
+ subTitle = "내 위치 기반 공간 추천을 위해\n사용자의 위치에 접근하도록 허용해 주세요.",
+ negativeButtonLabel = "취소",
+ positiveButtonLabel = "삭제",
+ onDismissRequest = { },
+ onPositiveButtonClick = { },
)
}
- item { Spacer(modifier = Modifier.width(8.dp)) }
}
}
@Composable
-fun Content(
- state: HomeState,
- onVideoClick: (Long, VideoType) -> Unit,
- onBookmarkClick: (Long) -> Unit,
+private fun ExhibitionContatiner(
+ exhibition: Exhibition,
+ screenWidth: Dp,
+ onVideoClick: (Long, VideoType) -> Unit = { i, j -> },
+ onBookmarkClick: (Long) -> Unit = {},
+ videoType: VideoType = VideoType.RECENT,
) {
- val configuration = LocalConfiguration.current
- val screenWidth = configuration.screenWidthDp.dp
- LazyColumn(
- modifier = Modifier
- .fillMaxWidth()
- .padding(top = 44.dp),
- ) {
- item {
- Section(
- title = "이번 주 인기 기록",
- videoList = state.popularList,
- screenWidth = screenWidth,
- onVideoClick = onVideoClick,
- onBookmarkClick = onBookmarkClick,
- videoType = VideoType.POPULAR,
- )
- Section(
- title = "방금 막 올라왔어요",
- videoList = state.recentList,
- screenWidth = screenWidth,
- onVideoClick = onVideoClick,
- onBookmarkClick = onBookmarkClick,
- videoType = VideoType.RECENT,
+ Column {
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(horizontal = 16.dp, vertical = 16.dp)
+ .background(color = RecordyTheme.colors.gray10, shape = RoundedCornerShape(8.dp)),
+ horizontalArrangement = Arrangement.SpaceBetween,
+ ) {
+ Column(
+ modifier = Modifier.padding(16.dp),
+ verticalArrangement = Arrangement.spacedBy(4.dp),
+ ) {
+ Text(
+ text = exhibition.location,
+ style = RecordyTheme.typography.caption1M,
+ color = RecordyTheme.colors.gray05,
+ )
+ Text(
+ text = exhibition.name,
+ style = RecordyTheme.typography.title3,
+ color = RecordyTheme.colors.gray01,
+ )
+ Text(
+ text = exhibition.exhibitionCount.toString(),
+ style = RecordyTheme.typography.body2SB,
+ color = RecordyTheme.colors.viskitYellow500,
+ )
+ }
+ Icon(
+ modifier = Modifier
+ .align(Alignment.CenterVertically)
+ .padding(16.dp),
+ tint = RecordyTheme.colors.gray01,
+ painter = painterResource(id = R.drawable.ic_angle_right_24),
+ contentDescription = "next",
)
- Spacer(modifier = Modifier.height(56.dp))
}
- }
-}
-@Composable
-fun Section(
- title: String,
- videoList: List,
- screenWidth: Dp,
- onVideoClick: (Long, VideoType) -> Unit,
- onBookmarkClick: (Long) -> Unit,
- videoType: VideoType,
-) {
- Column(
- modifier = Modifier
- .fillMaxWidth(),
- ) {
- Text(
- text = title,
- style = RecordyTheme.typography.subtitle,
- color = RecordyTheme.colors.white,
- modifier = Modifier
- .padding(horizontal = 16.dp)
- .padding(top = 16.dp, bottom = 12.dp),
- )
LazyRow(
horizontalArrangement = Arrangement.spacedBy(12.dp),
) {
item { Spacer(modifier = Modifier.width(4.dp)) }
- itemsIndexed(videoList) { index, videoData ->
+ itemsIndexed(exhibition.userVideo) { index, videoData ->
RecordyVideoThumbnail(
modifier = Modifier.width(screenWidth / 8 * 3),
imageUri = videoData.previewUrl,
@@ -367,5 +229,34 @@ fun Section(
@Composable
fun PreviewHome() {
RecordyTheme {
+ HomeScreen(
+ state = HomeState(
+ exhibitionList =
+ listOf(
+ Exhibition(
+ "서울 종로구",
+ "국립현대미술관",
+ 7,
+ userVideo = listOf(
+ VideoData(
+ bookmarkId = 1,
+ id = 1,
+ isBookmark = false,
+ bookmarkCount = 7,
+ content = "ㅎㅇ",
+ videoUrl = "ggg",
+ previewUrl = "ggg",
+ location = "korea",
+ uploaderId = 1,
+ nickname = "안녕",
+ isMine = false,
+ ),
+ ).toImmutableList(),
+ ),
+ ).toImmutableList(),
+ ),
+ showLocationPermissionDialog = {},
+ updateLocation = { i, j -> },
+ )
}
}
diff --git a/feature/home/src/main/java/com/record/home/HomeViewModel.kt b/feature/home/src/main/java/com/record/home/HomeViewModel.kt
index 965cb915..f6270daa 100644
--- a/feature/home/src/main/java/com/record/home/HomeViewModel.kt
+++ b/feature/home/src/main/java/com/record/home/HomeViewModel.kt
@@ -1,10 +1,6 @@
package com.record.home
-import android.util.Log
import androidx.lifecycle.viewModelScope
-import com.record.keyword.repository.KeywordRepository
-import com.record.model.VideoType
-import com.record.model.exception.ApiError
import com.record.ui.base.BaseViewModel
import com.record.video.repository.VideoRepository
import dagger.hilt.android.lifecycle.HiltViewModel
@@ -15,139 +11,59 @@ import javax.inject.Inject
@HiltViewModel
class HomeViewModel @Inject constructor(
private val videoRepository: VideoRepository,
- private val keywordRepository: KeywordRepository,
) : BaseViewModel(HomeState()) {
- fun navigateToUpload() {
- postSideEffect(HomeSideEffect.navigateToUpload)
+ fun navigateToVideo(videoId: Long, location: String) {
+ postSideEffect(HomeSideEffect.navigateToVideo(videoId, location))
}
- fun selectCategory(categoryIndex: Int) {
- intent {
- copy(selectedChipIndex = categoryIndex)
- }
- postSideEffect(HomeSideEffect.collapseToolbar)
- getPopularVideos()
- getRecentVideos()
- }
-
- fun getVideos() {
- getPreferenceKeywords()
- getPopularVideos()
- getRecentVideos()
- }
-
- private fun getPreferenceKeywords() {
- viewModelScope.launch {
- val newList = listOf("전체")
- keywordRepository.getKeywords().onSuccess {
- intent {
- copy(chipList = (newList + it.keywords).toImmutableList())
- }
- }.onFailure {
- when (it) {
- is ApiError -> {
- Log.e("error", it.message)
- }
- }
- }
- }
+ fun showLocationPermissionDialog(isShow: Boolean) = intent {
+ copy(showLocationPermissionDialog = isShow)
}
- private fun getRecentVideos() {
- viewModelScope.launch {
- val keyIndex = uiState.value.selectedChipIndex
- val keyword = if (keyIndex != null) listOf(uiState.value.chipList[keyIndex]) else null
- videoRepository.getRecentVideos(
- keywords = keyword,
- cursor = 0,
- pageSize = 10,
- ).onSuccess {
- intent {
- copy(recentList = it.data.toImmutableList())
- }
- }.onFailure {
- when (it) {
- is ApiError -> {
- Log.e("error", it.message)
- }
- }
- }
- }
- }
-
- private fun getPopularVideos() {
- viewModelScope.launch {
- val keyIndex = uiState.value.selectedChipIndex
- val keyword = if (keyIndex != null) listOf(uiState.value.chipList[keyIndex]) else null
- videoRepository.getPopularVideos(
- keywords = keyword,
- pageNumber = 0,
- pageSize = 10,
- ).onSuccess {
- intent {
- copy(popularList = it.data.toImmutableList())
- }
- }.onFailure {
- when (it) {
- is ApiError -> {
- Log.e("error", it.message)
- }
- }
- }
- }
- }
-
- fun navigateToVideo(videoId: Long, type: VideoType) {
- val selectedIndex = uiState.value.selectedChipIndex
- val selectedKeyword = if (selectedIndex != null) uiState.value.chipList[selectedIndex] else null
- postSideEffect(HomeSideEffect.navigateToVideo(videoId, type, selectedKeyword))
+ fun updateLocation(latitude: Double, longitude: Double) = intent {
+ copy(location = Location(latitude, longitude))
}
fun bookmark(id: Long) {
intent {
- val updatedRecentList = uiState.value.recentList.map { video ->
- if (video.id == id) {
- video.copy(isBookmark = !video.isBookmark)
- } else {
- video
- }
- }
-
- val updatedPopularList = uiState.value.popularList.map { video ->
- if (video.id == id) {
- video.copy(isBookmark = !video.isBookmark)
- } else {
- video
- }
+ val updatedList = uiState.value.exhibitionList.map { exhibition ->
+ Exhibition(
+ location = exhibition.location,
+ name = exhibition.name,
+ exhibitionCount = exhibition.exhibitionCount,
+ userVideo = exhibition.userVideo.map { video ->
+ if (video.id == id) {
+ video.copy(isBookmark = !video.isBookmark)
+ } else {
+ video
+ }
+ }.toImmutableList(),
+ )
}
copy(
- recentList = updatedRecentList.toImmutableList(),
- popularList = updatedPopularList.toImmutableList(),
+ exhibitionList = updatedList.toImmutableList(),
)
}
viewModelScope.launch {
videoRepository.bookmark(id).onSuccess {
- val updatedRecentList1 = uiState.value.recentList.map { video ->
- if (video.id == id) {
- video.copy(isBookmark = it)
- } else {
- video
- }
- }
-
- val updatedPopularList1 = uiState.value.popularList.map { video ->
- if (video.id == id) {
- video.copy(isBookmark = it)
- } else {
- video
- }
+ val updatedList = uiState.value.exhibitionList.map { exhibition ->
+ Exhibition(
+ location = exhibition.location,
+ name = exhibition.name,
+ exhibitionCount = exhibition.exhibitionCount,
+ userVideo = exhibition.userVideo.map { video ->
+ if (video.id == id) {
+ video.copy(isBookmark = !video.isBookmark)
+ } else {
+ video
+ }
+ }.toImmutableList(),
+ )
}
-
intent {
copy(
- recentList = updatedRecentList1.toImmutableList(),
- popularList = updatedPopularList1.toImmutableList(),
+ exhibitionList = updatedList.toImmutableList(),
)
}
}.onFailure {
diff --git a/feature/home/src/main/java/com/record/home/Location.kt b/feature/home/src/main/java/com/record/home/Location.kt
new file mode 100644
index 00000000..02e15874
--- /dev/null
+++ b/feature/home/src/main/java/com/record/home/Location.kt
@@ -0,0 +1,6 @@
+package com.record.home
+
+data class Location(
+ val latitude: Double,
+ val longitude: Double,
+)
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 71518883..1b3c8753 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -61,6 +61,7 @@ google-service = "4.4.2"
material = "1.12.0"
firebase-bom = "33.1.1"
crashlytics = "3.0.2"
+google-location = "21.3.0"
# Compose Versions
compose-compiler = "1.5.1"
@@ -219,6 +220,7 @@ firebase-database = { group = "com.google.firebase", name = "firebase-database-k
accompanist-insets = { module = "com.google.accompanist:accompanist-insets", version.ref = "accompanistInsets" }
accompanist-permissions = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanistPermissions" }
accompanist-systemuicontroller = { module = "com.google.accompanist:accompanist-systemuicontroller", version.ref = "accompanistPermissions" }
+google-location = { group = "com.google.android.gms", name = "play-services-location", version.ref = "google-location"}
# AWS
aws-android-sdk-cognito = { module = "com.amazonaws:aws-android-sdk-cognito", version.ref = "awsAndroidSdkMobileClient" }