Skip to content

Commit

Permalink
fix: 앨범 및 검색 페이징 처리
Browse files Browse the repository at this point in the history
  • Loading branch information
easyhz committed Apr 16, 2024
1 parent fef2db1 commit 2f38aa0
Show file tree
Hide file tree
Showing 13 changed files with 238 additions and 124 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.easyhz.picly.data.data_source.album

import androidx.paging.PagingSource
import androidx.paging.PagingState
import com.easyhz.picly.data.entity.album.Album
import com.easyhz.picly.data.mapper.toAlbumItem
import com.easyhz.picly.domain.model.album.AlbumItem
import com.easyhz.picly.domain.repository.album.AlbumRepository
import com.google.firebase.firestore.QuerySnapshot
import kotlinx.coroutines.tasks.await

class AlbumPagingSource(
private val albumRepository: AlbumRepository
): PagingSource<QuerySnapshot, AlbumItem>() {
override fun getRefreshKey(state: PagingState<QuerySnapshot, AlbumItem>): QuerySnapshot? = null

override suspend fun load(params: LoadParams<QuerySnapshot>): LoadResult<QuerySnapshot, AlbumItem> = try {
val current = params.key ?: albumRepository.fetchAlbums().get().await()
val data = current.toObjects(Album::class.java).toAlbumItem()
if (data.isEmpty()) {
LoadResult.Page(data = emptyList(), prevKey = null, nextKey = null)
} else {
val lastVisibleProduct = current.documents.last()
val nextPage = albumRepository.fetchAlbums().startAfter(lastVisibleProduct).get().await()

LoadResult.Page(data = data, prevKey = null, nextKey = nextPage)
}
} catch (e: Exception) {
LoadResult.Error(e)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.easyhz.picly.data.data_source.album

import androidx.paging.PagingSource
import androidx.paging.PagingState
import com.easyhz.picly.data.entity.album.Album
import com.easyhz.picly.data.mapper.toAlbumItem
import com.easyhz.picly.domain.model.album.AlbumItem
import com.easyhz.picly.domain.repository.album.AlbumRepository
import com.google.firebase.firestore.QuerySnapshot
import kotlinx.coroutines.tasks.await

class SearchAlbumPagingSource(
private val albumRepository: AlbumRepository,
private val searchText: String,
): PagingSource<QuerySnapshot, AlbumItem>() {
override fun getRefreshKey(state: PagingState<QuerySnapshot, AlbumItem>): QuerySnapshot? = null

override suspend fun load(params: LoadParams<QuerySnapshot>): LoadResult<QuerySnapshot, AlbumItem> = try {
val current = params.key ?: albumRepository.searchAlbums(searchText).get().await()
val data = current.toObjects(Album::class.java).toAlbumItem()
if (data.isEmpty()) {
LoadResult.Page(data = emptyList(), prevKey = null, nextKey = null)
} else {
val lastVisibleProduct = current.documents.last()
val nextPage = albumRepository.searchAlbums(searchText).startAfter(lastVisibleProduct).get().await()

LoadResult.Page(data = data, prevKey = null, nextKey = nextPage)
}
} catch (e: Exception) {
LoadResult.Error(e)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ object Constants {

const val OWNER_ID = "ownerID"
const val CREATION_TIME = "creationTime"
const val TAGS = "tags"

const val AUTH_PROVIDER_EMAIL = "Email"
const val AUTH_PROVIDER_GOOGLE = "Google"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import com.easyhz.picly.data.entity.album.ImageUrl
import com.easyhz.picly.data.firebase.Constants.ALBUMS
import com.easyhz.picly.data.firebase.Constants.CREATION_TIME
import com.easyhz.picly.data.firebase.Constants.OWNER_ID
import com.easyhz.picly.data.firebase.Constants.TAGS
import com.easyhz.picly.data.repository.user.UserManager
import com.easyhz.picly.domain.repository.album.AlbumRepository
import com.easyhz.picly.util.toPICLY
import com.google.firebase.firestore.DocumentReference
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.Query
import com.google.firebase.firestore.toObjects
import com.google.firebase.storage.FirebaseStorage
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
Expand All @@ -25,21 +25,16 @@ class AlbumRepositoryImpl
private val fireStore: FirebaseFirestore,
private val storage: FirebaseStorage,
): AlbumRepository {
override fun fetchAlbums() : Flow<List<Album>> = flow {
try {
val result = fireStore.collection(ALBUMS)
.whereEqualTo(OWNER_ID, UserManager.currentUser?.uid)
.orderBy(CREATION_TIME, Query.Direction.DESCENDING)
.get()
.await()
override suspend fun fetchAlbums(): Query = fireStore.collection(ALBUMS)
.whereEqualTo(OWNER_ID, UserManager.currentUser?.uid)
.orderBy(CREATION_TIME, Query.Direction.DESCENDING)
.limit(PAGE_SIZE)
override fun searchAlbums(searchText: String): Query = fireStore.collection(ALBUMS)
.whereEqualTo(OWNER_ID, UserManager.currentUser?.uid)
.whereArrayContains(TAGS, searchText)
.orderBy(CREATION_TIME, Query.Direction.DESCENDING)
.limit(PAGE_SIZE)

val albums = result.toObjects<Album>()
emit(albums)
} catch (e: Exception) {
// 예외 처리
Log.e(this.javaClass.simpleName, "Error fetching albums: ${e.message}")
}
}
override fun writeAlbums(album: Album): Flow<DocumentReference> = flow {
try {
val result = fireStore.collection(ALBUMS)
Expand Down Expand Up @@ -108,5 +103,6 @@ class AlbumRepositoryImpl

companion object {
const val THUMBNAIL = "thumbnail.jpeg"
const val PAGE_SIZE = 10L
}
}
13 changes: 10 additions & 3 deletions app/src/main/java/com/easyhz/picly/di/UseCaseModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import com.easyhz.picly.domain.repository.album.AlbumRepository
import com.easyhz.picly.domain.repository.data_store.AppSettingRepository
import com.easyhz.picly.domain.repository.gallery.GalleryRepository
import com.easyhz.picly.domain.repository.user.UserRepository
import com.easyhz.picly.domain.usecase.album.AlbumUseCase
import com.easyhz.picly.domain.usecase.album.FetchAlbumUseCase
import com.easyhz.picly.domain.usecase.album.DeleteAlbumUseCase
import com.easyhz.picly.domain.usecase.album.DownloadImageUseCase
import com.easyhz.picly.domain.usecase.album.SearchAlbumUseCase
import com.easyhz.picly.domain.usecase.album.upload.GalleryUseCase
import com.easyhz.picly.domain.usecase.album.upload.UploadUseCase
import com.easyhz.picly.domain.usecase.data_store.AppSettingDataStoreUseCase
Expand All @@ -25,9 +26,15 @@ object UseCaseModule {

@Provides
@Singleton
fun provideAlbumUseCase(
fun provideFetchAlbumUseCase(
albumRepository: AlbumRepository
): AlbumUseCase = AlbumUseCase(albumRepository)
): FetchAlbumUseCase = FetchAlbumUseCase(albumRepository)

@Provides
@Singleton
fun provideSearchAlbumUseCase(
albumRepository: AlbumRepository
): SearchAlbumUseCase = SearchAlbumUseCase(albumRepository)

@Provides
@Singleton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ import android.net.Uri
import com.easyhz.picly.data.entity.album.Album
import com.easyhz.picly.data.entity.album.ImageUrl
import com.google.firebase.firestore.DocumentReference
import com.google.firebase.firestore.Query
import kotlinx.coroutines.flow.Flow

interface AlbumRepository {
fun fetchAlbums() : Flow<List<Album>>
suspend fun fetchAlbums(): Query

fun searchAlbums(searchText: String): Query

fun writeAlbums(album: Album) : Flow<DocumentReference>

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.easyhz.picly.domain.usecase.album

import androidx.paging.Pager
import androidx.paging.PagingConfig
import com.easyhz.picly.data.data_source.album.AlbumPagingSource
import com.easyhz.picly.data.repository.album.AlbumRepositoryImpl.Companion.PAGE_SIZE
import com.easyhz.picly.domain.repository.album.AlbumRepository
import javax.inject.Inject

class FetchAlbumUseCase
@Inject constructor(
private val repository: AlbumRepository
) {
private var pagingSource: AlbumPagingSource? = null
get() {
if (field == null || field?.invalid == true) {
field = AlbumPagingSource(repository)
}
return field
}
operator fun invoke() = Pager(
config = PagingConfig(
pageSize = PAGE_SIZE.toInt()
),
pagingSourceFactory = {
pagingSource!!
}
)

fun setPagingSource() {
pagingSource?.invalidate()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.easyhz.picly.domain.usecase.album

import androidx.paging.Pager
import androidx.paging.PagingConfig
import com.easyhz.picly.data.data_source.album.SearchAlbumPagingSource
import com.easyhz.picly.data.repository.album.AlbumRepositoryImpl.Companion.PAGE_SIZE
import com.easyhz.picly.domain.repository.album.AlbumRepository
import javax.inject.Inject

class SearchAlbumUseCase
@Inject constructor(
private val repository: AlbumRepository
) {
var searchText: String = ""
private var pagingSource: SearchAlbumPagingSource? = null
get() {
if (field == null || field?.invalid == true) {
field = SearchAlbumPagingSource(repository, searchText)
}
return field
}
operator fun invoke() = Pager(
config = PagingConfig(
pageSize = PAGE_SIZE.toInt()
),
pagingSourceFactory = {
pagingSource!!
}
)

fun setPagingSource() {
pagingSource?.invalidate()
}
}
5 changes: 0 additions & 5 deletions app/src/main/java/com/easyhz/picly/view/MainFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ class MainFragment:Fragment() {
}

private fun setUp() {
fetchAlbums()
observeIsSwipe()
}

Expand Down Expand Up @@ -88,10 +87,6 @@ class MainFragment:Fragment() {
}
}

private fun fetchAlbums() {
viewModel.fetchAlbums()
}

private fun observeIsSwipe() {
viewModel.isSwipe.observe(viewLifecycleOwner) {
if (it) {
Expand Down
56 changes: 7 additions & 49 deletions app/src/main/java/com/easyhz/picly/view/album/AlbumAdapter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,27 @@ package com.easyhz.picly.view.album
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Filter
import android.widget.Filterable
import androidx.recyclerview.widget.AsyncListDiffer
import androidx.paging.PagingDataAdapter
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.easyhz.picly.databinding.ItemAlbumBinding
import com.easyhz.picly.domain.model.album.AlbumItem

class AlbumAdapter(
private val noResult: (Boolean , String) -> Unit,
private val onClickLinkButton: (AlbumItem) -> Unit,
private val onLongClick: (AlbumItem, View) -> Unit,
private val onClickListener: (AlbumItem) -> Unit,
):RecyclerView.Adapter<AlbumAdapter.AlbumViewHolder>(), Filterable {
var originalList: List<AlbumItem> = listOf()
private val postFiler = PostFilter()

): PagingDataAdapter<AlbumItem, AlbumAdapter.AlbumViewHolder>(differ) {
inner class AlbumViewHolder(val binding: ItemAlbumBinding) : RecyclerView.ViewHolder(binding.root)


private val differ = AsyncListDiffer(this, object : DiffUtil.ItemCallback<AlbumItem>() {
override fun areItemsTheSame(oldItem: AlbumItem, newItem: AlbumItem): Boolean {
return oldItem.thumbnailUrl == newItem.thumbnailUrl
}

override fun areContentsTheSame(oldItem: AlbumItem, newItem: AlbumItem): Boolean {
return oldItem == newItem
}
})

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AlbumViewHolder = AlbumViewHolder(
ItemAlbumBinding.inflate(
LayoutInflater.from(parent.context), parent, false
)
)

override fun getItemCount(): Int = differ.currentList.size

override fun onBindViewHolder(holder: AlbumViewHolder, position: Int) {
val currentItem = differ.currentList[position]
val currentItem = getItem(position) ?: return
holder.binding.apply {
data = currentItem
albumCardView.setOnClickListener {
Expand All @@ -61,35 +42,12 @@ class AlbumAdapter(
}
}

fun setAlbumList(albumList: List<AlbumItem>) {
differ.submitList(albumList)
}

override fun getFilter(): Filter = postFiler
inner class PostFilter: Filter() {
companion object {
private val differ = object : DiffUtil.ItemCallback<AlbumItem>() {
override fun areItemsTheSame(oldItem: AlbumItem, newItem: AlbumItem): Boolean = oldItem.documentId == newItem.documentId

override fun performFiltering(constraint: CharSequence?): FilterResults {
val filterString = constraint.toString().trim()
val results = FilterResults()

if (filterString.isEmpty()) {
results.values = originalList
} else {
val filterList = originalList.filter { album ->
val tags = listOf(album.mainTag) + album.tags
tags.any { tag -> tag.contains(filterString) }
}
results.values = filterList
}

results.count = (results.values as List<AlbumItem>).size
return results
}
override fun areContentsTheSame(oldItem: AlbumItem, newItem: AlbumItem): Boolean = oldItem == newItem

override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
val filteredList = results?.values as? List<AlbumItem> ?: emptyList()
noResult(filteredList.isEmpty(), constraint.toString())
differ.submitList(filteredList)
}
}
}
Loading

0 comments on commit 2f38aa0

Please sign in to comment.