Skip to content

Commit

Permalink
Merge pull request #100 from snuhcs-course/feat/android-non-user-dialog
Browse files Browse the repository at this point in the history
Add dialog for Non-User mode
  • Loading branch information
yangchanhk98 authored Dec 5, 2023
2 parents f45db4b + 13470ce commit ae676eb
Show file tree
Hide file tree
Showing 9 changed files with 184 additions and 65 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,15 @@ class RootActivity : ComponentActivity() {
navController.getBackStackEntry(NavigationDestination.MainPage)
}
val emojiViewModel = hiltViewModel<EmojiViewModel>(parentEntry)
PlayEmojiView(emojiViewModel)
val userViewModel = hiltViewModel<UserViewModel>(parentEntry)
PlayEmojiView(emojiViewModel, userViewModel)
}

composable(NavigationDestination.CreatePost) {
val postViewModel = hiltViewModel<PostViewModel>()
val parentEntry = remember(it) {
navController.getBackStackEntry(NavigationDestination.MainPage)
}
val postViewModel = hiltViewModel<PostViewModel>(parentEntry)
CreatePostPage(postViewModel)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import javax.inject.Singleton

interface LocalStorage {
var accessToken: String?
val currentUser: String?
var currentUser: String?
}

@Singleton
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.goliath.emojihub.usecases

import android.util.Log
import com.goliath.emojihub.EmojiHubApplication
import com.goliath.emojihub.data_sources.ApiErrorController
import com.goliath.emojihub.models.LoginUserDto
Expand Down Expand Up @@ -62,6 +61,7 @@ class UserUseCaseImpl @Inject constructor(
_accessTokenState.update { accessToken }
_userState.update { User(UserDto(name)) }
EmojiHubApplication.preferences.accessToken = accessToken
EmojiHubApplication.preferences.currentUser = name
} else {
errorController.setErrorState(it.code())
}
Expand All @@ -73,6 +73,7 @@ class UserUseCaseImpl @Inject constructor(
response.let {
if (it.isSuccessful) {
EmojiHubApplication.preferences.accessToken = null
EmojiHubApplication.preferences.currentUser = null
_accessTokenState.update { null }
_userState.update { null }
} else {
Expand All @@ -87,6 +88,7 @@ class UserUseCaseImpl @Inject constructor(
response.let {
if (it.isSuccessful) {
EmojiHubApplication.preferences.accessToken = null
EmojiHubApplication.preferences.currentUser = null
_accessTokenState.update { null }
_userState.update { null }
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import kotlinx.coroutines.launch

@Composable
fun CreatePostPage(
viewModel: PostViewModel
postViewModel: PostViewModel
) {
val navController = LocalNavController.current

Expand All @@ -42,7 +42,7 @@ fun CreatePostPage(
) {
TextButton(onClick = {
coroutineScope.launch {
val success = viewModel.uploadPost(content.text)
val success = postViewModel.uploadPost(content.text)
if (success) {
showSuccessDialog = true
}
Expand Down
92 changes: 60 additions & 32 deletions android/app/src/main/java/com/goliath/emojihub/views/EmojiPage.kt
Original file line number Diff line number Diff line change
@@ -1,57 +1,69 @@
package com.goliath.emojihub.views

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import android.Manifest
import android.content.pm.PackageManager
import android.os.Build
import android.util.Log
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
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.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.material.Button
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
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.unit.dp
import com.goliath.emojihub.views.components.EmojiCell
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.content.ContextCompat
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.paging.compose.collectAsLazyPagingItems
import com.goliath.emojihub.LocalNavController
import com.goliath.emojihub.NavigationDestination
import com.goliath.emojihub.navigateAsOrigin
import com.goliath.emojihub.ui.theme.Color.Black
import com.goliath.emojihub.ui.theme.Color.LightGray
import com.goliath.emojihub.ui.theme.Color.White
import com.goliath.emojihub.viewmodels.EmojiViewModel
import com.goliath.emojihub.viewmodels.UserViewModel
import com.goliath.emojihub.views.components.CustomDialog
import com.goliath.emojihub.views.components.EmojiCell
import com.goliath.emojihub.views.components.EmojiCellDisplay
import com.goliath.emojihub.views.components.TopNavigationBar

@Composable
fun EmojiPage(
) {
fun EmojiPage() {
val context = LocalContext.current
val navController = LocalNavController.current

val viewModel = hiltViewModel<EmojiViewModel>()
val userViewModel = hiltViewModel<UserViewModel>()
val emojiViewModel = hiltViewModel<EmojiViewModel>()

val currentUser = userViewModel.userState.collectAsState().value
val emojiList = emojiViewModel.emojiList.collectAsLazyPagingItems()

var showNonUserDialog by remember { mutableStateOf(false) }

val permissionLauncher = rememberLauncherForActivityResult(
ActivityResultContracts.RequestPermission()
Expand All @@ -62,30 +74,32 @@ fun EmojiPage(
) { uri ->
if (uri != null) {
Log.d("PhotoPicker", "Selected URI: $uri")
viewModel.videoUri = uri
emojiViewModel.videoUri = uri
navController.navigate(NavigationDestination.TransformVideo)
}
}

val emojiList = viewModel.emojiList.collectAsLazyPagingItems()

LaunchedEffect(Unit) {
viewModel.fetchEmojiList()
emojiViewModel.fetchEmojiList()
}

Column(Modifier.background(White)) {
TopNavigationBar("Emoji", shouldNavigate = false) {
IconButton(onClick = {
when (PackageManager.PERMISSION_GRANTED) {
ContextCompat.checkSelfPermission(
context, Manifest.permission.READ_MEDIA_VIDEO
) -> {
pickMediaLauncher.launch(PickVisualMediaRequest(
ActivityResultContracts.PickVisualMedia.VideoOnly
))
}
else -> {
permissionLauncher.launch(Manifest.permission.READ_MEDIA_VIDEO)
if (currentUser == null) {
showNonUserDialog = true
} else {
when (PackageManager.PERMISSION_GRANTED) {
ContextCompat.checkSelfPermission(
context, Manifest.permission.READ_MEDIA_VIDEO
) -> {
pickMediaLauncher.launch(PickVisualMediaRequest(
ActivityResultContracts.PickVisualMedia.VideoOnly
))
}
else -> {
permissionLauncher.launch(Manifest.permission.READ_MEDIA_VIDEO)
}
}
}
}) {
Expand All @@ -107,13 +121,13 @@ fun EmojiPage(
Text("Trending 🔥", fontSize = 20.sp, fontWeight = FontWeight.Bold)

Button(
onClick = { viewModel.toggleSortingMode() },
onClick = { emojiViewModel.toggleSortingMode() },
colors = ButtonDefaults.buttonColors(
backgroundColor = if (viewModel.sortByDate == 0) Black else LightGray,
backgroundColor = if (emojiViewModel.sortByDate == 0) Black else LightGray,
contentColor = White
)
) {
Text(text = if (viewModel.sortByDate == 1) "Sort by Date" else "Sort by Save Count", fontSize = 12.sp)
Text(text = if (emojiViewModel.sortByDate == 1) "Sort by Date" else "Sort by Save Count", fontSize = 12.sp)
}
}

Expand All @@ -126,12 +140,26 @@ fun EmojiPage(
items(emojiList.itemCount) { index ->
emojiList[index]?.let{
EmojiCell(emoji = it, displayMode = EmojiCellDisplay.VERTICAL) { selectedEmoji ->
viewModel.currentEmoji = selectedEmoji
emojiViewModel.currentEmoji = selectedEmoji
navController.navigate(NavigationDestination.PlayEmojiVideo)
}
}
}
}
}

if (showNonUserDialog) {
CustomDialog(
title = "비회원 모드",
body = "회원만 이모지를 생성할 수 있습니다. 로그인 화면으로 이동할까요?",
confirmText = "이동",
needsCancelButton = true,
onDismissRequest = { showNonUserDialog = false },
dismiss = { showNonUserDialog = false },
confirm = {
navController.navigateAsOrigin(NavigationDestination.Onboard)
}
)
}
}
}
43 changes: 34 additions & 9 deletions android/app/src/main/java/com/goliath/emojihub/views/FeedPage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.Divider
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
Expand All @@ -21,13 +26,14 @@ import com.goliath.emojihub.LocalBottomSheetController
import com.goliath.emojihub.LocalNavController
import com.goliath.emojihub.NavigationDestination
import com.goliath.emojihub.models.createDummyEmoji
import com.goliath.emojihub.navigateAsOrigin
import com.goliath.emojihub.ui.theme.Color
import com.goliath.emojihub.ui.theme.Color.EmojiHubDividerColor
import com.goliath.emojihub.viewmodels.EmojiViewModel
import com.goliath.emojihub.viewmodels.PostViewModel
import com.goliath.emojihub.views.components.EmojiCell
import com.goliath.emojihub.views.components.EmojiCellDisplay
import com.goliath.emojihub.viewmodels.UserViewModel
import com.goliath.emojihub.views.components.CustomBottomSheet
import com.goliath.emojihub.views.components.CustomDialog
import com.goliath.emojihub.views.components.PostCell
import com.goliath.emojihub.views.components.TopNavigationBar

Expand All @@ -38,10 +44,15 @@ fun FeedPage() {

val emojiViewModel = hiltViewModel<EmojiViewModel>()
val postViewModel = hiltViewModel<PostViewModel>()
val userViewModel = hiltViewModel<UserViewModel>()

val currentUser = userViewModel.userState.collectAsState().value

val emojiList = (1..10).map { createDummyEmoji() }
val postList = postViewModel.postList.collectAsLazyPagingItems()

var showNonUserDialog by remember { mutableStateOf(false) }

LaunchedEffect(Unit) {
postViewModel.fetchPostList()
}
Expand All @@ -51,7 +62,11 @@ fun FeedPage() {
) {
TopNavigationBar("Feed", shouldNavigate = false) {
IconButton(onClick = {
navController.navigate(NavigationDestination.CreatePost)
if (currentUser == null) {
showNonUserDialog = true
} else {
navController.navigate(NavigationDestination.CreatePost)
}
}) {
Icon(
imageVector = Icons.Default.Add,
Expand All @@ -60,25 +75,35 @@ fun FeedPage() {
}
}

Box(
modifier = Modifier
.weight(1f)
.fillMaxWidth()
) {
Box(modifier = Modifier.weight(1f).fillMaxWidth()) {
LazyColumn(
modifier = Modifier.fillMaxWidth(),
contentPadding = PaddingValues(horizontal = 16.dp)
) {
items(postList.itemCount) { index ->
postList[index]?.let {
PostCell(post = it)
PostCell(post = it, isNonUser = currentUser == null)
Divider(color = EmojiHubDividerColor, thickness = 0.5.dp)
}
}
}
}
}

if (showNonUserDialog) {
CustomDialog(
title = "비회원 모드",
body = "회원만 글을 작성할 수 있습니다. 로그인 화면으로 이동할까요?",
confirmText = "이동",
needsCancelButton = true,
onDismissRequest = { showNonUserDialog = false },
dismiss = { showNonUserDialog = false },
confirm = {
navController.navigateAsOrigin(NavigationDestination.Onboard)
}
)
}

if (bottomSheetController.isVisible) {
CustomBottomSheet(
bottomSheetContent = emojiViewModel.bottomSheetContent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.material3.ButtonDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
Expand Down Expand Up @@ -48,6 +49,8 @@ fun LoginPage() {
var username by remember { mutableStateOf(TextFieldValue("")) }
var password by remember { mutableStateOf(TextFieldValue("")) }

val isLoginButtonDisabled by remember { derivedStateOf { username.text.isEmpty() || password.text.isEmpty() }}

val focusManager = LocalFocusManager.current
val interactionSource = remember { MutableInteractionSource() }

Expand Down Expand Up @@ -97,6 +100,7 @@ fun LoginPage() {
}
},
modifier = Modifier.padding(top = 24.dp).fillMaxWidth().height(44.dp),
enabled = !isLoginButtonDisabled,
shape = RoundedCornerShape(50),
colors = ButtonDefaults.buttonColors(
containerColor = Color.Black,
Expand Down
Loading

0 comments on commit ae676eb

Please sign in to comment.