Skip to content

Commit

Permalink
Merge pull request #242 from mash-up-kr/feature/home_cache
Browse files Browse the repository at this point in the history
홈 화면 Post 캐싱 추가
  • Loading branch information
fbghgus123 authored Oct 2, 2024
2 parents 5fa1f98 + 3d911dd commit 454fdfc
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 67 deletions.
1 change: 1 addition & 0 deletions core/designsystem/src/main/res/raw/dot_loading.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"v":"4.8.0","meta":{"g":"LottieFiles AE 3.5.7","a":"","k":"","d":"","tc":""},"fr":30,"ip":0,"op":46,"w":240,"h":240,"nm":"Comp 2","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"dot1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[118.75,118.4,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":6,"s":[118.75,98.4,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[118.75,128.4,0],"to":[0,0,0],"ti":[0,0,0]},{"t":26,"s":[118.75,118.4,0]}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[25,25],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.901960784314,0.905882352941,0.921568627451,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-53.348,2.152],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":46,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"dot2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":10,"s":[173.375,118.4,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":16,"s":[173.375,98.4,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":30,"s":[173.375,128.4,0],"to":[0,0,0],"ti":[0,0,0]},{"t":36,"s":[173.375,118.4,0]}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[25,25],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.901960784314,0.905882352941,0.921568627451,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-53.348,2.152],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":46,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"dot3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[228.75,118.4,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":26,"s":[228.75,98.4,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":40,"s":[228.75,128.4,0],"to":[0,0,0],"ti":[0,0,0]},{"t":46,"s":[228.75,118.4,0]}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[25,25],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"fl","c":{"a":0,"k":[0.901960784314,0.905882352941,0.921568627451,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-53.348,2.152],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":46,"st":0,"bm":0}],"markers":[]}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ interface PostDao {
@Query("SELECT * FROM localPostItemEntity")
suspend fun getPostByPage(): List<LocalPostItemEntity>

@Query("SELECT * FROM localPostItemEntity ORDER BY createdAt DESC LIMIT :limit")
suspend fun getRecentPosts(limit: Int = 10): List<LocalPostItemEntity>

@Query(
"""
SELECT * FROM localPostItemEntity
Expand All @@ -37,6 +40,9 @@ interface PostDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertAll(posts: List<LocalPostItemEntity>)

@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertPost(post: LocalPostItemEntity)

/**
* Post 아이템 삭제
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ import com.mashup.dorabangs.data.model.toDomain
import com.mashup.dorabangs.data.pagingsource.PostRemoteMediator
import com.mashup.dorabangs.data.utils.PAGING_SIZE
import com.mashup.dorabangs.data.utils.doraPager
import com.mashup.dorabangs.domain.model.AIStatus
import com.mashup.dorabangs.domain.model.DoraSampleResponse
import com.mashup.dorabangs.domain.model.Link
import com.mashup.dorabangs.domain.model.Post
import com.mashup.dorabangs.domain.model.PostInfo
import com.mashup.dorabangs.domain.model.Posts
import com.mashup.dorabangs.domain.model.PostsMetaData
import com.mashup.dorabangs.domain.repository.PostsRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
Expand Down Expand Up @@ -52,7 +54,14 @@ class PostsRepositoryImpl @Inject constructor(
postsRemoteDataSource.saveLink(link)

override suspend fun getPost(postId: String) =
postsRemoteDataSource.getPost(postId).toDomain()
postsRemoteDataSource
.getPost(postId)
.toDomain()
.apply {
if (aiStatus == AIStatus.SUCCESS) {
database.postDao().insertPost(toLocalEntity())
}
}

override suspend fun patchPostInfo(postId: String, postInfo: PostInfo): DoraSampleResponse =
runCatching {
Expand Down Expand Up @@ -139,5 +148,15 @@ class PostsRepositoryImpl @Inject constructor(
order = order,
favorite = favorite,
isRead = isRead,
).toDomain()
)
.toDomain()
.apply {
val localPostItems = items.map { it.toLocalEntity() }
database.postDao().insertAll(localPostItems)
}

override suspend fun getLocalPosts(limit: Int) = Posts(
items = database.postDao().getRecentPosts(limit).map { it.toPost() },
metaData = PostsMetaData(),
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,6 @@ interface PostsRepository {
favorite: Boolean?,
isRead: Boolean?,
): Posts

suspend fun getLocalPosts(limit: Int): Posts
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.mashup.dorabangs.domain.usecase.posts

import com.mashup.dorabangs.domain.repository.PostsRepository
import javax.inject.Inject

class GetLocalPostsUseCase @Inject constructor(
private val postsRepository: PostsRepository,
) {

suspend operator fun invoke(limit: Int) = postsRepository.getLocalPosts(limit)
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ fun HomeRoute(
scrollCache = viewModel.scrollCache,
)

LifecycleEventEffect(Lifecycle.Event.ON_CREATE) {
viewModel.loadCachedPosts()
}

LifecycleEventEffect(Lifecycle.Event.ON_START) {
if (state.isNeedToRefreshOnStart) {
viewModel.setAIClassificationCount()
Expand Down Expand Up @@ -167,20 +171,18 @@ fun BoxScope.HomeSideEffectUI(
state: HomeState,
snackBarHostState: SnackbarHostState,
toastSnackBarHostState: SnackbarHostState,
navigateToSaveScreenWithLink: (String) -> Unit,

setLocalCopiedUrl: (String) -> Unit,
getLocalCopiedUrl: suspend () -> String?,
showSnackBar: (String) -> Unit,
navigateToSaveScreenWithLink: (String) -> Unit,
hideSnackBar: () -> Unit,
getLocalCopiedUrl: suspend () -> String?,
getCustomFolderList: () -> Unit,
setLocalCopiedUrl: (String) -> Unit,
setVisibleMoreButtonBottomSheet: (Boolean) -> Unit,
setVisibleMovingFolderBottomSheet: (Boolean, Boolean) -> Unit,
setVisibleDialog: (Boolean) -> Unit,
getCustomFolderList: () -> Unit,
updateSelectFolderId: (String, String) -> Unit,
deletePost: (String) -> Unit,
moveFolder: (String, String, String) -> Unit,

view: View = LocalView.current,
clipboardManager: ClipboardManager = LocalClipboardManager.current,
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,60 +77,62 @@ fun HomeScreen(
Box(
modifier = modifier.fillMaxSize(),
) {
if (state.isLoading) {
Box(
modifier = Modifier
.fillMaxSize()
.padding(top = 104.dp)
.align(Alignment.Center),
) {
LottieLoader(
lottieRes = R.raw.spinner,
iterations = Int.MAX_VALUE,
if (state.postList.isEmpty()) {
if (state.isLoading) {
Box(
modifier = Modifier
.size(54.dp)
.fillMaxSize()
.padding(top = 104.dp)
.align(Alignment.Center),
)
}
} else if (state.postList.isEmpty()) {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Spacer(modifier = Modifier.height(104.dp))

if (state.selectedIndex == 0) {
HomeCarousel(
) {
LottieLoader(
lottieRes = R.raw.spinner,
iterations = Int.MAX_VALUE,
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 16.dp, horizontal = 20.dp)
.clip(DoraRoundTokens.Round20),
homeCarouselItems = listOf(
HomeCarouselItem(
lottieRes = R.raw.unread,
description = stringResource(id = R.string.home_carousel_save_introduce),
onClickButton = navigateToHomeTutorial,
),
),
.size(54.dp)
.align(Alignment.Center),
)
}

} else {
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Icon(
painter = painterResource(id = R.drawable.ic_empty),
contentDescription = "",
tint = Color.Unspecified,
)
Text(
modifier = Modifier.padding(top = 12.dp),
text = stringResource(id = R.string.home_empty_feed),
style = DoraTypoTokens.caption3Medium,
color = DoraColorTokens.G3,
)
Spacer(modifier = Modifier.height(104.dp))

if (state.selectedIndex == 0) {
HomeCarousel(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 16.dp, horizontal = 20.dp)
.clip(DoraRoundTokens.Round20),
homeCarouselItems = listOf(
HomeCarouselItem(
lottieRes = R.raw.unread,
description = stringResource(id = R.string.home_carousel_save_introduce),
onClickButton = navigateToHomeTutorial,
),
),
)
}

Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxSize(),
) {
Icon(
painter = painterResource(id = R.drawable.ic_empty),
contentDescription = "",
tint = Color.Unspecified,
)
Text(
modifier = Modifier.padding(top = 12.dp),
text = stringResource(id = R.string.home_empty_feed),
style = DoraTypoTokens.caption3Medium,
color = DoraColorTokens.G3,
)
}
}
}
} else {
Expand Down Expand Up @@ -226,21 +228,49 @@ fun HomeScreen(
)
}

Box(
Column(
modifier = Modifier
.padding(bottom = 20.dp, end = 20.dp)
.size(60.dp)
.clip(DoraRoundTokens.Round99)
.background(DoraColorTokens.SurfaceBlack)
.align(Alignment.BottomEnd)
.clickable(onClick = navigateSaveScreenWithoutLink),
contentAlignment = Alignment.Center,
.fillMaxWidth()
.align(Alignment.BottomCenter),
) {
Icon(
tint = DoraColorTokens.G3,
painter = painterResource(id = R.drawable.ic_fab_add),
contentDescription = "",
)
Box(
modifier = Modifier
.padding(bottom = 20.dp, end = 20.dp)
.size(60.dp)
.clip(DoraRoundTokens.Round99)
.background(DoraColorTokens.SurfaceBlack)
.clickable(onClick = navigateSaveScreenWithoutLink)
.align(Alignment.End),
contentAlignment = Alignment.Center,
) {
Icon(
tint = DoraColorTokens.G3,
painter = painterResource(id = R.drawable.ic_fab_add),
contentDescription = "",
)
}

if (state.isLoading && state.postList.isNotEmpty()) {
Row(
modifier = Modifier
.fillMaxWidth()
.height(36.dp)
.background(DoraColorTokens.SurfaceBlack),
verticalAlignment = Alignment.CenterVertically,
) {
Text(
modifier = Modifier.padding(start = 20.dp),
text = "링크 불러오는 중",
color = DoraColorTokens.G3,
style = DoraTypoTokens.caption1Normal,
)
LottieLoader(
modifier = Modifier.size(24.dp),
lottieRes = R.raw.dot_loading,
iterations = Int.MAX_VALUE,
)
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import com.mashup.dorabangs.domain.usecase.folder.GetFolderListUseCase
import com.mashup.dorabangs.domain.usecase.folder.GetPostsFromFolderUseCase
import com.mashup.dorabangs.domain.usecase.posts.ChangePostFolder
import com.mashup.dorabangs.domain.usecase.posts.DeletePostUseCase
import com.mashup.dorabangs.domain.usecase.posts.GetLocalPostsUseCase
import com.mashup.dorabangs.domain.usecase.posts.GetPostUseCase
import com.mashup.dorabangs.domain.usecase.posts.GetPostsPageUseCase
import com.mashup.dorabangs.domain.usecase.posts.GetUnReadPostsCountUseCase
Expand Down Expand Up @@ -63,6 +64,7 @@ class HomeViewModel @Inject constructor(
private val changePostFolderUseCase: ChangePostFolder,
private val patchPostInfoUseCase: PatchPostInfoUseCase,
private val getPostUseCase: GetPostUseCase,
private val getLocalPostsUseCase: GetLocalPostsUseCase,
) : ViewModel(), ContainerHost<HomeState, HomeSideEffect> {
override val container = container<HomeState, HomeSideEffect>(HomeState())

Expand Down Expand Up @@ -559,9 +561,25 @@ class HomeViewModel @Inject constructor(
return feedCardList
}

fun loadCachedPosts() = viewModelScope.doraLaunch {
intent {
val posts = getLocalPostsUseCase(LOCAL_CACHED_POSTS_COUNT)

if (state.folderList.isEmpty()) {
initFolderList()
}

reduce { state.copy(postList = posts.items.toUIModel(state.folderList)) }
}
}

private fun List<Post>.toUIModel(folderList: List<Folder>) = this.map { post ->
val category =
folderList.firstOrNull { folder -> folder.id == post.folderId }?.name.orEmpty()
post.toUiModel(category)
}

companion object {
private const val LOCAL_CACHED_POSTS_COUNT = 10
}
}

0 comments on commit 454fdfc

Please sign in to comment.