Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Feature/#72 others profile #78

Merged
merged 10 commits into from
Jul 15, 2024
Merged
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.record.mypage
package com.record.designsystem.component.container

import androidx.compose.foundation.Image
import androidx.compose.foundation.background
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class RecordyTypography internal constructor(
body1M: TextStyle,
body1R: TextStyle,
body2M: TextStyle,
body2B: TextStyle,
body2L: TextStyle,
caption1: TextStyle,
caption1U: TextStyle,
Expand Down Expand Up @@ -60,6 +61,8 @@ class RecordyTypography internal constructor(
private set
var body2M: TextStyle by mutableStateOf(body2M)
private set
var body2B: TextStyle by mutableStateOf(body2B)
private set
var body2L: TextStyle by mutableStateOf(body2L)
private set
var caption1: TextStyle by mutableStateOf(caption1)
Expand Down Expand Up @@ -97,6 +100,7 @@ class RecordyTypography internal constructor(
body1M: TextStyle = this.body1M,
body1R: TextStyle = this.body1R,
body2M: TextStyle = this.body2M,
body2B: TextStyle = this.body2B,
body2L: TextStyle = this.body2L,
caption1: TextStyle = this.caption1,
caption1U: TextStyle = this.caption1U,
Expand All @@ -120,6 +124,7 @@ class RecordyTypography internal constructor(
body1M,
body1R,
body2M,
body2B,
body2L,
caption1,
caption1U,
Expand All @@ -145,6 +150,7 @@ class RecordyTypography internal constructor(
body1M = other.body1M
body1R = other.body1R
body2M = other.body2M
body2B = other.body2B
body2L = other.body2L
caption1 = other.caption1
caption1U = other.caption1U
Expand Down Expand Up @@ -208,6 +214,12 @@ fun RecordyTypography(): RecordyTypography {
lineHeight = 20.sp,
letterSpacing = (-0.5).sp,
),
body2B = TextStyle(
fontFamily = PretendardBold,
fontSize = 14.sp,
lineHeight = 20.sp,
letterSpacing = (-0.5).sp,
),
body2L = TextStyle(
fontFamily = PretendardMedium,
fontSize = 14.sp,
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package com.record.mypage
package com.record.mypage.follow

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.record.designsystem.component.container.UserDataContainer
import com.record.designsystem.theme.RecordyTheme
import com.record.model.UserData
import kotlinx.collections.immutable.ImmutableList
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.record.mypage
package com.record.mypage.follow

import com.record.model.UserData
import com.record.ui.base.SideEffect
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.record.mypage
package com.record.mypage.follow

import androidx.lifecycle.viewModelScope
import com.record.model.UserData
Expand All @@ -10,7 +10,9 @@ import kotlinx.coroutines.launch
import javax.inject.Inject

@HiltViewModel
class FollowViewModel @Inject constructor() : BaseViewModel<FollowState, FollowSideEffect>(FollowState()) {
class FollowViewModel @Inject constructor() : BaseViewModel<FollowState, FollowSideEffect>(
FollowState(),
) {

fun toggleFollow(user: UserData) {
intent {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.record.mypage
package com.record.mypage.follow

import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
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.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
Expand All @@ -14,10 +16,11 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import coil.compose.rememberAsyncImagePainter
import com.record.designsystem.theme.RecordyTheme
import com.record.ui.lifecycle.LaunchedEffectWithLifecycle
import kotlinx.coroutines.flow.collectLatest
Expand Down Expand Up @@ -71,17 +74,32 @@ fun EmptyFollowerScreen() {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
) {
Image(
painter = rememberAsyncImagePainter("https://picsum.photos/id/200/200"),
contentDescription = null,
modifier = Modifier.size(120.dp),
)
Row() {
Spacer(modifier = Modifier.weight(13f))
Image(
painter = painterResource(com.record.designsystem.R.drawable.img_no_follower),
contentDescription = null,
modifier = Modifier
.weight(10f)
.aspectRatio(1f),
)
Spacer(modifier = Modifier.weight(13f))
}

Spacer(modifier = Modifier.size(32.dp))
Text(
text = "์•„์ง ํŒ”๋กœ์šฐํ•˜๋Š” ์‚ฌ๋žŒ์ด ์—†์–ด์š”",
style = RecordyTheme.typography.body2M,
text = "์•„์ง ํŒ”๋กœ์›Œ๊ฐ€ ์—†์–ด์š”",
style = RecordyTheme.typography.emptybody,
color = RecordyTheme.colors.white,
)
}
}
}

@Preview
@Composable
fun PreviewEmptyFollowerScreen() {
RecordyTheme {
EmptyFollowerScreen()
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
package com.record.mypage
package com.record.mypage.follow

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.record.designsystem.component.container.UserDataContainer
import com.record.designsystem.theme.RecordyTheme
import com.record.model.UserData
import com.record.ui.lifecycle.LaunchedEffectWithLifecycle
Expand All @@ -21,7 +25,7 @@ fun FollowingRoute(
modifier: Modifier = Modifier,
viewModel: FollowViewModel = hiltViewModel(),
) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
val followState by viewModel.uiState.collectAsStateWithLifecycle()

LaunchedEffectWithLifecycle(Unit) {
viewModel.sideEffect.collectLatest { sideEffect ->
Expand All @@ -41,27 +45,37 @@ fun FollowingRoute(
.background(RecordyTheme.colors.background)
.padding(padding),
) {
if (uiState.followingList.isEmpty()) {
EmptyFollowingScreen()
} else {
FollowScreen(
followingList = uiState.followingList,
onClick = { user -> viewModel.toggleFollow(user) },
)
}
DefaultProfileScreen(followState, viewModel::toggleFollow)
}
}

@Composable
fun EmptyFollowingScreen() {
UserDataContainer(
user = UserData(
fun DefaultProfileScreen(followState: FollowState, onclickEvent: (UserData) -> Unit) {
val defaultUser =
UserData(
id = 0,
profileImageResId = com.record.designsystem.R.drawable.img_profile,
name = "์œ ์˜",
isFollowing = false,
),
onClick = {},
showFollowButton = false,
)
)

val sortedList = listOf(defaultUser) + followState.followingList

LazyColumn {
items(sortedList) { user ->
UserDataContainer(
user = user,
onClick = { onclickEvent(user) },
showFollowButton = user.name != "์œ ์˜",
)
}
}
}

@Preview
@Composable
fun DefaultProfileScreenPreview() {
RecordyTheme {
DefaultProfileScreen(FollowState(), onclickEvent = {})
}
}
4 changes: 4 additions & 0 deletions feature/profile/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@ plugins {
android {
namespace = "com.record.profile"
}

dependencies {
implementation(projects.feature.video)
}
67 changes: 63 additions & 4 deletions feature/profile/src/main/java/com/record/profile/ProfileScreen.kt
Original file line number Diff line number Diff line change
@@ -1,18 +1,77 @@
package com.record.profile

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Text
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.record.designsystem.component.RecordyVideoThumbnail
import com.record.designsystem.component.container.UserDataContainer
import com.record.designsystem.theme.RecordyTheme
import com.record.video.SampleData

@Composable
fun ProfileRoute(
padding: PaddingValues,
modifier: Modifier = Modifier,
) {
Box(modifier = modifier.fillMaxSize()) {
Text("profile")
ProfileScreen(
padding = padding,
modifier = modifier,
)
}

@Composable
fun ProfileScreen(
padding: PaddingValues,
modifier: Modifier = Modifier,
viewModel: ProfileViewModel = hiltViewModel(),
) {
val uiState by viewModel.uiState.collectAsState()

Column(modifier = modifier.fillMaxSize()) {
UserDataContainer(
user = uiState.user,
onClick = { user ->
viewModel.toggleFollow(user)
},
)

LazyVerticalGrid(
modifier = Modifier
.fillMaxHeight()
.padding(horizontal = 16.dp)
.padding(bottom = padding.calculateBottomPadding()),
columns = GridCells.Fixed(2),
verticalArrangement = Arrangement.spacedBy(12.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
items(SampleData.sampleVideos) { item ->
RecordyVideoThumbnail(
imageUri = item.previewUri,
isBookmarkable = true,
isBookmark = false,
)
}
}
}
}

@Preview(showBackground = true)
@Composable
fun ProfileScreenPreview() {
RecordyTheme {
ProfileScreen(padding = PaddingValues(0.dp))
}
}
19 changes: 19 additions & 0 deletions feature/profile/src/main/java/com/record/profile/ProfileState.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.record.profile

import com.record.model.UserData
import com.record.ui.base.SideEffect
import com.record.ui.base.UiState

data class ProfileState(
val user: UserData = UserData(
id = 1,
profileImage = "https://picsum.photos/id/200/60",
name = "John Doe",
isFollowing = true,
),
) : UiState

sealed class ProfileSideEffect : SideEffect {
data object Following : ProfileSideEffect()
data object Unfollowing : ProfileSideEffect()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.record.profile

import androidx.lifecycle.viewModelScope
import com.record.model.UserData
import com.record.ui.base.BaseViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject

@HiltViewModel
class ProfileViewModel @Inject constructor() : BaseViewModel<ProfileState, ProfileSideEffect>(ProfileState()) {

fun toggleFollow(user: UserData) {
viewModelScope.launch {
val updatedUser = user.copy(isFollowing = !user.isFollowing)
intent {
copy(user = updatedUser)
}
postSideEffect(
if (updatedUser.isFollowing) {
ProfileSideEffect.Following
} else {
ProfileSideEffect.Unfollowing
},
)
}
}
}