Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[UI] #47 세부 UI 수정 #50

Merged
merged 16 commits into from
Aug 25, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
052fc41
[UI] #47-회원가입 성공화면 이미지 추가
l5x5l Aug 24, 2024
318abdb
[FIX] #47-링크/포킷 추가시 관련 화면에서 이벤트 수신 및 처리부분 추가
l5x5l Aug 24, 2024
b91246c
Merge branch 'refs/heads/develop' into ui/#47-detail_ui
l5x5l Aug 24, 2024
fa9e3d2
[FIX] #47-response가 없는 api의 경우 리턴값을 Response<Unit>으로 설정 및 이에 따른 dataS…
l5x5l Aug 24, 2024
3e05292
[BASE] #47-로딩, 에러, 빈 리스트시 표시할 component 추가
l5x5l Aug 24, 2024
5ade270
[FEATURE] #47-홈, 검색, 포킷 상세 화면에서 로딩/에러/빈 리스트 표시 UI 적용
l5x5l Aug 24, 2024
47e2cec
[BASE] #47-커스텀 토스트 UI component 추가
l5x5l Aug 24, 2024
5828d92
[FIX] #47-홈 화면에 누락된 포킷 제거 이벤트 추가
l5x5l Aug 24, 2024
023621e
[CHORE] #47-ktlint 적용
l5x5l Aug 24, 2024
6df90e3
[FIX] #47-검색 API에서 isRead와 favorites를 Nullable하게 변경
l5x5l Aug 25, 2024
f21db32
[FIX] #47-검색 화면에서 링크 이미지가 구글 로고로 표시되던 문제 수정
l5x5l Aug 25, 2024
49799bf
[FIX] #47-LinkCard의 badgeText를 Nullable하게 수정 및 리마인드 화면에서 링크 url이 badg…
l5x5l Aug 25, 2024
18488b5
[FIX] #47-검색 화면에서 안읽은 표시가 정 반대로 표시되는 문제 수정
l5x5l Aug 25, 2024
5ea9cb4
[FEATURE] #47-홈 화면, 링크 추가 화면에 PokitToast 적용
l5x5l Aug 25, 2024
57bffe0
Merge branch 'develop' into ui/#47-detail_ui
l5x5l Aug 25, 2024
22a6a13
[CHORE] #47-ktlint 적용
l5x5l Aug 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package pokitmons.pokit.core.feature.flow

import android.annotation.SuppressLint
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext

@SuppressLint("ComposableNaming")
@Composable
fun <T> Flow<T>.collectAsEffect(
context: CoroutineContext = EmptyCoroutineContext,
block: (T) -> Unit,
) {
LaunchedEffect(Unit) {
onEach(block).flowOn(context).launchIn(this)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package pokitmons.pokit.core.feature.flow

import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.MutableSharedFlow
import java.util.concurrent.atomic.AtomicBoolean

interface EventFlow<out T> : Flow<T> {
companion object {
const val DEFAULT_REPLAY: Int = 1
}
}

interface MutableEventFlow<T> : EventFlow<T>, FlowCollector<T>

fun <T> MutableEventFlow(
replay: Int = EventFlow.DEFAULT_REPLAY,
): MutableEventFlow<T> = EventFlowImpl(replay)

fun <T> MutableEventFlow<T>.asEventFlow(): EventFlow<T> = ReadOnlyEventFlow(this)

private class ReadOnlyEventFlow<T>(flow: EventFlow<T>) : EventFlow<T> by flow

private class EventFlowImpl<T>(
replay: Int,
) : MutableEventFlow<T> {

private val flow: MutableSharedFlow<EventFlowSlot<T>> = MutableSharedFlow(replay = replay)

@InternalCoroutinesApi
override suspend fun collect(collector: FlowCollector<T>) = flow
.collect { slot ->
if (!slot.markConsumed()) {
collector.emit(slot.value)
}
}

override suspend fun emit(value: T) {
flow.emit(EventFlowSlot(value))
}
}

private class EventFlowSlot<T>(val value: T) {
private val consumed: AtomicBoolean = AtomicBoolean(false)
fun markConsumed(): Boolean = consumed.getAndSet(true)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package pokitmons.pokit.core.feature.model

enum class NetworkState {
IDLE, LOADING, ERROR
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ data class LinkArg(
val thumbnail: String,
val createdAt: String,
val domain: String,
val pokitId: Int,
) : Parcelable
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ object LinkUpdateEvent {
private val _removedLink = MutableSharedFlow<Int>()
val removedLink = _removedLink.asSharedFlow()

private val _addedLink = MutableSharedFlow<LinkArg>()
val addedLink = _addedLink.asSharedFlow()

fun modifySuccess(link: LinkArg) {
CoroutineScope(Dispatchers.Default).launch {
_updatedLink.emit(link)
Expand All @@ -24,4 +27,10 @@ object LinkUpdateEvent {
_removedLink.emit(linkId)
}
}

fun createSuccess(link: LinkArg) {
CoroutineScope(Dispatchers.Default).launch {
_addedLink.emit(link)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ object PokitUpdateEvent {
private val _removedPokitId = MutableSharedFlow<Int>()
val removedPokitId = _removedPokitId.asSharedFlow()

private val _addedPokit = MutableSharedFlow<PokitArg>()
val addedPokit = _addedPokit.asSharedFlow()

fun updatePokit(pokitArg: PokitArg) {
CoroutineScope(Dispatchers.Default).launch {
_updatedPokit.emit(pokitArg)
Expand All @@ -24,4 +27,10 @@ object PokitUpdateEvent {
_removedPokitId.emit(pokitId)
}
}

fun createPokit(pokitArg: PokitArg) {
CoroutineScope(Dispatchers.Default).launch {
_addedPokit.emit(pokitArg)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package pokitmons.pokit.core.ui.components.atom.loading

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.width
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import pokitmons.pokit.core.ui.theme.PokitTheme

@Composable
fun LoadingProgress(modifier: Modifier = Modifier) {
Box(
modifier = modifier,
contentAlignment = Alignment.Center
) {
CircularProgressIndicator(
modifier = Modifier.width(64.dp),
color = PokitTheme.colors.brand,
trackColor = PokitTheme.colors.borderTertiary
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package pokitmons.pokit.core.ui.components.block.pokittoast

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
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.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import pokitmons.pokit.core.ui.R
import pokitmons.pokit.core.ui.theme.PokitTheme

@Composable
fun PokitToast(
modifier: Modifier = Modifier,
text: String,
onClick: (() -> Unit)? = null,
onClickClose: () -> Unit = {},
) {
Row(
modifier = modifier
.clip(RoundedCornerShape(9999.dp))
.background(PokitTheme.colors.backgroundTertiary)
.clickable(
enabled = onClick != null,
onClick = onClick ?: {}
)
.padding(start = 20.dp, end = 14.dp, top = 12.dp, bottom = 12.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = text,
style = PokitTheme.typography.body2Bold.copy(color = PokitTheme.colors.inverseWh),
modifier = Modifier.weight(1f)
)

Spacer(modifier = Modifier.width(12.dp))

IconButton(
onClick = onClickClose,
modifier = Modifier.size(36.dp)
) {
Icon(
painter = painterResource(id = R.drawable.icon_24_x),
contentDescription = null,
tint = PokitTheme.colors.inverseWh
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package pokitmons.pokit.core.ui.components.block.pokittoast

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import pokitmons.pokit.core.ui.theme.PokitTheme

@Preview(showBackground = true)
@Composable
private fun Preview() {
PokitTheme {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
PokitToast(
modifier = Modifier.padding(20.dp),
text = "최대 30개의 포킷을 생성할 수 있습니다.\n포킷을 삭제한 뒤에 추가해주세요.",
onClick = {}
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package pokitmons.pokit.core.ui.components.template.pokkiempty

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
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.res.painterResource
import androidx.compose.ui.unit.dp
import pokitmons.pokit.core.ui.R
import pokitmons.pokit.core.ui.theme.PokitTheme

@Composable
fun EmptyPokki(
modifier: Modifier = Modifier,
title: String,
sub: String,
) {
Box(
modifier = modifier,
contentAlignment = Alignment.Center
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Image(
modifier = Modifier
.height(180.dp)
.width(180.dp),
painter = painterResource(id = R.drawable.empty_pokki),
contentDescription = "empty"
)

Spacer(modifier = Modifier.height(16.dp))

Text(text = title, style = PokitTheme.typography.title2.copy(color = PokitTheme.colors.textPrimary))

Spacer(modifier = Modifier.height(8.dp))

Text(text = sub, style = PokitTheme.typography.body2Medium.copy(color = PokitTheme.colors.textSecondary))
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package pokitmons.pokit.core.ui.components.template.pokkiempty

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import pokitmons.pokit.core.ui.theme.PokitTheme

@Preview(showBackground = true)
@Composable
private fun Preview() {
PokitTheme {
Surface(modifier = Modifier.fillMaxSize()) {
EmptyPokki(title = "저장된 포킷이 없어요!", sub = "포킷을 생성해 링크를 저장해보세요")
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package pokitmons.pokit.core.ui.components.template.pokkierror

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
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.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import pokitmons.pokit.core.ui.R
import pokitmons.pokit.core.ui.components.atom.button.PokitButton
import pokitmons.pokit.core.ui.components.atom.button.attributes.PokitButtonSize
import pokitmons.pokit.core.ui.components.atom.button.attributes.PokitButtonStyle
import pokitmons.pokit.core.ui.components.atom.button.attributes.PokitButtonType
import pokitmons.pokit.core.ui.theme.PokitTheme

@Composable
fun ErrorPokki(
modifier: Modifier = Modifier,
pokkiSize: Dp = 180.dp,
title: String,
sub: String,
onClickRetry: (() -> Unit)? = null,
) {
Box(
modifier = modifier,
contentAlignment = Alignment.Center
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Image(
modifier = Modifier
.height(pokkiSize)
.width(pokkiSize),
painter = painterResource(id = R.drawable.cry_pokki),
contentDescription = "empty"
)

Spacer(modifier = Modifier.height(16.dp))

Text(text = title, style = PokitTheme.typography.title2.copy(color = PokitTheme.colors.textPrimary))

Spacer(modifier = Modifier.height(8.dp))

Text(text = sub, style = PokitTheme.typography.body2Medium.copy(color = PokitTheme.colors.textSecondary))

onClickRetry?.let { onClick ->
Spacer(modifier = Modifier.height(16.dp))

PokitButton(
type = PokitButtonType.SECONDARY,
size = PokitButtonSize.SMALL,
style = PokitButtonStyle.DEFAULT,
text = stringResource(id = R.string.retry),
icon = null,
onClick = onClick
)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package pokitmons.pokit.core.ui.components.template.pokkierror

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import pokitmons.pokit.core.ui.theme.PokitTheme

@Preview(showBackground = true)
@Composable
private fun Preview() {
PokitTheme {
Surface(modifier = Modifier.fillMaxSize()) {
ErrorPokki(title = "오류가 발생했어요", sub = "조금 뒤 다시 접속해주세요", onClickRetry = null)
// ErrorPokki(title = "오류가 발생했어요", sub = "조금 뒤 다시 접속해주세요", onClickRetry = {})
}
}
}
Binary file added core/ui/src/main/res/drawable-hdpi/big_pokki.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added core/ui/src/main/res/drawable-hdpi/cry_pokki.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added core/ui/src/main/res/drawable-mdpi/big_pokki.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added core/ui/src/main/res/drawable-mdpi/cry_pokki.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading