Skip to content

Commit

Permalink
Merge pull request #35 from FakeDevelopers/feature/BDBD-240
Browse files Browse the repository at this point in the history
BDBD-240 상품 사진 등록
  • Loading branch information
minseonglove authored Jun 5, 2022
2 parents 1cd83b2 + c690dfd commit c93f85d
Show file tree
Hide file tree
Showing 33 changed files with 914 additions and 153 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/bidderbidderCI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.date.outputs.date }}
release_name: Release-${{ steps.date.outputs.date }}
release_name: Release-dev-${{ steps.date.outputs.date }}
- name: Upload Release APK
id: upload_release_asset
uses: actions/upload-release-asset@v1
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,21 @@ class MainActivity : AppCompatActivity() {
navController.addOnDestinationChangedListener { _, destination, _ ->
when (destination.id) {
R.id.productListFragment -> {
binding.bottomNavigationMain.visibility = View.VISIBLE
binding.bottomNavigationMain.run {
visibility = View.VISIBLE
selectedItemId = R.id.menu_product_list
}
}
R.id.productRegistrationFragment -> binding.bottomNavigationMain.visibility = View.GONE
}
}
binding.bottomNavigationMain.setOnItemSelectedListener { item ->
when (item.itemId) {
R.id.menu_product_registration -> navController.navigate(R.id.productRegistrationFragment)
}
true
}
// navController.navigate(R.id.productRegistrationFragment)
}

override fun onDestroy() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ class ProductListRepository @Inject constructor(
) {
suspend fun postProductList(
searchWord: String,
searchType: Int,
listCount: Int,
startNumber: Long
): Response<List<ProductListDto>> {
return service.postProductList(searchWord, listCount, startNumber)
return service.postProductList(searchWord, searchType, listCount, startNumber)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import retrofit2.http.GET
import retrofit2.http.Query

interface ProductListService {
@GET("board/getInfiniteProductList")
@GET("product/getInfiniteProductList")
suspend fun postProductList(
@Query("searchWord") searchWord: String?,
@Query("searchType") searchType: Int?,
@Query("listCount") listCount: Int,
@Query("startNumber") startNumber: Long
): Response<List<ProductListDto>>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ class LoginFragment : Fragment() {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.loginResponse.collect {
if (it.isSuccessful) {
Logger.t("Login").i(it.body().toString())
if (it.body().toString() == LOGIN_SUCCESS) {
findNavController().navigate(R.id.action_loginFragment_to_mainFragment)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,20 @@ import com.fakedevelopers.bidderbidder.R
import com.fakedevelopers.bidderbidder.api.data.Constants.Companion.BASE_URL
import com.fakedevelopers.bidderbidder.databinding.RecyclerProductListBinding
import com.fakedevelopers.bidderbidder.databinding.RecyclerProductListFooterBinding
import com.fakedevelopers.bidderbidder.ui.product_list.ProductListViewModel.Companion.LIST_COUNT
import java.text.DecimalFormat
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

class ProductListAdapter(
private val onClick: () -> Unit,
private val isReadMoreVisible: () -> Boolean,
private val getPriceInfo: (String) -> String
) : ListAdapter<ProductListDto, RecyclerView.ViewHolder>(diffUtil) {

private var listSize = 0
private val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.getDefault())

inner class ItemViewHolder(
private val binding: RecyclerProductListBinding,
Expand All @@ -34,7 +38,7 @@ class ProductListAdapter(
if (::timerTask.isInitialized) {
timerTask.cancel()
}
val timer = dateFormat.parse(item.expirationDate)!!.time - System.currentTimeMillis()
val timer = dateFormat.parse(item.expirationDate)!!.time - Date(System.currentTimeMillis()).time
timerTask = object : CountDownTimer(timer, 1000) {
override fun onTick(millisUntilFinished: Long) {
textviewProductListExpire.text = getRemainTimeString(millisUntilFinished)
Expand All @@ -47,9 +51,9 @@ class ProductListAdapter(
Glide.with(context)
.load(BASE_URL + item.thumbnail)
.placeholder(R.drawable.the_cat)
.error(R.drawable.the_cat)
.error(R.drawable.error_cat)
.into(imageProductList)
textviewProductListTitle.text = item.boardTitle
textviewProductListTitle.text = item.productTitle
if (item.hopePrice == 0L) {
hopePrice.visibility = View.GONE
textviewProductListHopePrice.visibility = View.GONE
Expand Down Expand Up @@ -93,9 +97,12 @@ class ProductListAdapter(
private val binding: RecyclerProductListFooterBinding
) : RecyclerView.ViewHolder(binding.root) {
fun bind() {
binding.buttonLoadMore.setOnClickListener {
binding.buttonLoadMore.visibility = View.GONE
onClick()
binding.buttonLoadMore.run {
visibility = if (isReadMoreVisible()) View.VISIBLE else View.GONE
setOnClickListener {
binding.buttonLoadMore.visibility = View.GONE
onClick()
}
}
}
}
Expand Down Expand Up @@ -127,9 +134,9 @@ class ProductListAdapter(
}

override fun getItemViewType(position: Int) =
if (position == itemCount - 1) TYPE_FOOTER else TYPE_ITEM
if (position <= LIST_COUNT && position == itemCount - 1) TYPE_FOOTER else TYPE_ITEM

override fun getItemCount() = if (listSize == 0) super.getItemCount() else listSize
override fun getItemCount() = if (listSize == 0 || listSize > LIST_COUNT) super.getItemCount() else listSize

override fun submitList(list: List<ProductListDto>?) {
if (!list.isNullOrEmpty()) {
Expand All @@ -143,11 +150,10 @@ class ProductListAdapter(
const val TYPE_FOOTER = 2

val dec = DecimalFormat("#,###")
val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.getDefault())

val diffUtil = object : DiffUtil.ItemCallback<ProductListDto>() {
override fun areItemsTheSame(oldItem: ProductListDto, newItem: ProductListDto) =
oldItem.boardId == newItem.boardId
oldItem.productId == newItem.productId

override fun areContentsTheSame(oldItem: ProductListDto, newItem: ProductListDto) =
oldItem == newItem
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.fakedevelopers.bidderbidder.ui.product_list

data class ProductListDto(
val boardId: Long,
val productId: Long,
val thumbnail: String,
val boardTitle: String,
val productTitle: String,
val hopePrice: Long,
val openingBid: Long,
val tick: Long,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,13 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.fakedevelopers.bidderbidder.R
import com.fakedevelopers.bidderbidder.databinding.FragmentProductListBinding
import com.orhanobut.logger.Logger
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch

@AndroidEntryPoint
class ProductListFragment : Fragment() {

private lateinit var productListAdapter: ProductListAdapter

private var _binding: FragmentProductListBinding? = null

private val binding get() = _binding!!
Expand Down Expand Up @@ -54,45 +51,24 @@ class ProductListFragment : Fragment() {
super.onViewCreated(view, savedInstanceState)
initListener()
viewModel.requestProductList(true)
binding.recyclerProductList.addItemDecoration(
DividerItemDecoration(requireContext(), LinearLayout.VERTICAL).apply {
setDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.divider_product_list)!!)
}
)
collectProductList()
}

private fun collectProductList() {
lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.productList.collectLatest {
updateRecyclerView(it)
binding.swipeProductList.isRefreshing = false
viewModel.isLoading.collectLatest {
binding.swipeProductList.isRefreshing = it
}
}
}
}

private fun updateRecyclerView(productList: List<ProductListDto>) {
if (!::productListAdapter.isInitialized) {
productListAdapter = ProductListAdapter(onClick = {
// 더보기 버튼이 애매하게 가려진 채로 누르면 크래쉬가 납니다.
// 그래서 우선 더보기를 누르면 스크롤을 가장 끝까지 내린다음 클릭 이벤트를 수행 합니다.
binding.recyclerProductList.scrollToPosition(productListAdapter.itemCount)
viewModel.clickReadMore()
}) {
getString(R.string.productlist_text_price, it)
}.apply {
submitList(productList)
}
val divider = DividerItemDecoration(requireContext(), LinearLayout.VERTICAL).apply {
setDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.divider_product_list)!!)
}
binding.recyclerProductList.apply {
layoutManager = LinearLayoutManager(activity)
addItemDecoration(divider)
adapter = productListAdapter
}
} else {
productListAdapter.submitList(productList.toList())
}
}

private fun initListener() {
binding.swipeProductList.setOnRefreshListener {
viewModel.requestProductList(true)
Expand All @@ -103,7 +79,6 @@ class ProductListFragment : Fragment() {
binding.recyclerProductList.layoutManager.let {
val lastVisibleItem = (it as LinearLayoutManager).findLastCompletelyVisibleItemPosition()
if (it.itemCount <= lastVisibleItem + REFRESH_COUNT) {
Logger.t("recycler").i("리스트 하나 더")
viewModel.getNextProductList()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,21 @@ class ProductListViewModel @Inject constructor(
private val repository: ProductListRepository
) : ViewModel() {

private val _productList = MutableStateFlow(mutableListOf<ProductListDto>())
private val productList = MutableStateFlow(listOf<ProductListDto>())
private val _isLoading = MutableStateFlow(false)
private val _isReadMoreVisible = MutableStateFlow(true)
private val isReadMoreVisible = MutableStateFlow(true)
private val isLastProduct = MutableStateFlow(false)
private val startNumber = MutableStateFlow(-1L)
private val searchWord = MutableStateFlow("")

val productList: StateFlow<List<ProductListDto>> get() = _productList
val isLoading: StateFlow<Boolean> get() = _isLoading
val isReadMoreVisible: StateFlow<Boolean> get() = _isReadMoreVisible

val adapter = ProductListAdapter(
onClick = { clickReadMore() },
isReadMoreVisible = { isReadMoreVisible.value }
) {
"${it}"
}

fun getNextProductList() {
// 이미 로딩 중일 때
Expand All @@ -46,14 +51,16 @@ class ProductListViewModel @Inject constructor(
viewModelScope.launch {
// 추가하기 전에 로딩 띄우기
setLoadingState(true)
repository.postProductList(searchWord.value, LIST_COUNT, startNumber.value).let {
repository.postProductList(searchWord.value, 0, LIST_COUNT, startNumber.value).let {
if (it.isSuccessful) {
val currentList = if (isInitialize) mutableListOf() else _productList.value.toMutableList()
val currentList = if (isInitialize) mutableListOf() else productList.value.toMutableList()
currentList.addAll(it.body()!!)
_productList.emit(currentList)
startNumber.emit(_productList.value[_productList.value.size - 1].boardId)
productList.emit(currentList)
startNumber.emit(productList.value[productList.value.size - 1].productId)
adapter.submitList(productList.value.toList())
// 요청한 것 보다 더 적게 받아오면 끝자락이라고 판단
if (it.body()!!.size < LIST_COUNT) {
isReadMoreVisible.value = false
isLastProduct.emit(true)
}
} else {
Expand All @@ -64,8 +71,8 @@ class ProductListViewModel @Inject constructor(
}
}

fun clickReadMore() {
_isReadMoreVisible.value = false
private fun clickReadMore() {
isReadMoreVisible.value = false
getNextProductList()
}

Expand Down
Loading

0 comments on commit c93f85d

Please sign in to comment.