feat(chat-character): 신규 캐릭터 전체보기 화면 및 API 연동 추가
This commit is contained in:
		@@ -191,6 +191,7 @@
 | 
				
			|||||||
                <category android:name="android.intent.category.DEFAULT" />
 | 
					                <category android:name="android.intent.category.DEFAULT" />
 | 
				
			||||||
            </intent-filter>
 | 
					            </intent-filter>
 | 
				
			||||||
        </activity>
 | 
					        </activity>
 | 
				
			||||||
 | 
					        <activity android:name=".chat.character.newcharacters.NewCharactersAllActivity" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <activity
 | 
					        <activity
 | 
				
			||||||
            android:name="com.google.android.gms.oss.licenses.OssLicensesMenuActivity"
 | 
					            android:name="com.google.android.gms.oss.licenses.OssLicensesMenuActivity"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -43,6 +43,14 @@ interface CharacterApi {
 | 
				
			|||||||
        @Query("size") size: Int
 | 
					        @Query("size") size: Int
 | 
				
			||||||
    ): Single<ApiResponse<CharacterImageListResponse>>
 | 
					    ): Single<ApiResponse<CharacterImageListResponse>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 신규 캐릭터 전체보기
 | 
				
			||||||
 | 
					    @GET("/api/chat/character/recent")
 | 
				
			||||||
 | 
					    fun getRecentCharacters(
 | 
				
			||||||
 | 
					        @Header("Authorization") authHeader: String,
 | 
				
			||||||
 | 
					        @Query("page") page: Int,
 | 
				
			||||||
 | 
					        @Query("size") size: Int
 | 
				
			||||||
 | 
					    ): Single<ApiResponse<kr.co.vividnext.sodalive.chat.character.newcharacters.RecentCharactersResponse>>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @POST("/api/chat/character/image/purchase")
 | 
					    @POST("/api/chat/character/image/purchase")
 | 
				
			||||||
    fun purchaseCharacterImage(
 | 
					    fun purchaseCharacterImage(
 | 
				
			||||||
        @Header("Authorization") authHeader: String,
 | 
					        @Header("Authorization") authHeader: String,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,6 +22,7 @@ import kr.co.vividnext.sodalive.base.SodaDialog
 | 
				
			|||||||
import kr.co.vividnext.sodalive.chat.character.curation.CurationSectionAdapter
 | 
					import kr.co.vividnext.sodalive.chat.character.curation.CurationSectionAdapter
 | 
				
			||||||
import kr.co.vividnext.sodalive.chat.character.detail.CharacterDetailActivity
 | 
					import kr.co.vividnext.sodalive.chat.character.detail.CharacterDetailActivity
 | 
				
			||||||
import kr.co.vividnext.sodalive.chat.character.detail.CharacterDetailActivity.Companion.EXTRA_CHARACTER_ID
 | 
					import kr.co.vividnext.sodalive.chat.character.detail.CharacterDetailActivity.Companion.EXTRA_CHARACTER_ID
 | 
				
			||||||
 | 
					import kr.co.vividnext.sodalive.chat.character.newcharacters.NewCharactersAllActivity
 | 
				
			||||||
import kr.co.vividnext.sodalive.chat.character.recent.RecentCharacterAdapter
 | 
					import kr.co.vividnext.sodalive.chat.character.recent.RecentCharacterAdapter
 | 
				
			||||||
import kr.co.vividnext.sodalive.common.LoadingDialog
 | 
					import kr.co.vividnext.sodalive.common.LoadingDialog
 | 
				
			||||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
 | 
					import kr.co.vividnext.sodalive.common.SharedPreferenceManager
 | 
				
			||||||
@@ -289,6 +290,14 @@ class CharacterTabFragment : BaseFragment<FragmentCharacterTabBinding>(
 | 
				
			|||||||
        recyclerView.adapter = newCharacterAdapter
 | 
					        recyclerView.adapter = newCharacterAdapter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        binding.tvNewCharacterAll.setOnClickListener {
 | 
					        binding.tvNewCharacterAll.setOnClickListener {
 | 
				
			||||||
 | 
					            ensureLoginAndAuth {
 | 
				
			||||||
 | 
					                startActivity(
 | 
				
			||||||
 | 
					                    Intent(
 | 
				
			||||||
 | 
					                        requireContext(),
 | 
				
			||||||
 | 
					                        NewCharactersAllActivity::class.java
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // 신규 캐릭터 LiveData 구독
 | 
					        // 신규 캐릭터 LiveData 구독
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,92 @@
 | 
				
			|||||||
 | 
					package kr.co.vividnext.sodalive.chat.character.newcharacters
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import android.content.Intent
 | 
				
			||||||
 | 
					import android.os.Bundle
 | 
				
			||||||
 | 
					import android.view.View
 | 
				
			||||||
 | 
					import androidx.recyclerview.widget.GridLayoutManager
 | 
				
			||||||
 | 
					import androidx.recyclerview.widget.LinearLayoutManager
 | 
				
			||||||
 | 
					import androidx.recyclerview.widget.RecyclerView
 | 
				
			||||||
 | 
					import kr.co.vividnext.sodalive.base.BaseActivity
 | 
				
			||||||
 | 
					import kr.co.vividnext.sodalive.chat.character.detail.CharacterDetailActivity
 | 
				
			||||||
 | 
					import kr.co.vividnext.sodalive.chat.character.detail.CharacterDetailActivity.Companion.EXTRA_CHARACTER_ID
 | 
				
			||||||
 | 
					import kr.co.vividnext.sodalive.common.GridSpacingItemDecoration
 | 
				
			||||||
 | 
					import kr.co.vividnext.sodalive.common.LoadingDialog
 | 
				
			||||||
 | 
					import kr.co.vividnext.sodalive.databinding.ActivityNewCharactersAllBinding
 | 
				
			||||||
 | 
					import kr.co.vividnext.sodalive.extensions.dpToPx
 | 
				
			||||||
 | 
					import org.koin.android.ext.android.inject
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class NewCharactersAllActivity : BaseActivity<ActivityNewCharactersAllBinding>(
 | 
				
			||||||
 | 
					    ActivityNewCharactersAllBinding::inflate
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    private val viewModel: NewCharactersAllViewModel by inject()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private lateinit var adapter: NewCharactersAllAdapter
 | 
				
			||||||
 | 
					    private lateinit var loadingDialog: LoadingDialog
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override fun onCreate(savedInstanceState: Bundle?) {
 | 
				
			||||||
 | 
					        super.onCreate(savedInstanceState)
 | 
				
			||||||
 | 
					        setupView()
 | 
				
			||||||
 | 
					        bindData()
 | 
				
			||||||
 | 
					        viewModel.loadMore()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override fun setupView() {
 | 
				
			||||||
 | 
					        loadingDialog = LoadingDialog(this, layoutInflater)
 | 
				
			||||||
 | 
					        binding.toolbar.tvBack.text = "신규 캐릭터 전체보기"
 | 
				
			||||||
 | 
					        binding.toolbar.tvBack.setOnClickListener { finish() }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val spanCount = 3
 | 
				
			||||||
 | 
					        val spacingPx = 8f.dpToPx().toInt()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        adapter = NewCharactersAllAdapter { characterId ->
 | 
				
			||||||
 | 
					            startActivity(
 | 
				
			||||||
 | 
					                Intent(this, CharacterDetailActivity::class.java).apply {
 | 
				
			||||||
 | 
					                    putExtra(EXTRA_CHARACTER_ID, characterId)
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        binding.rvCharacters.layoutManager = GridLayoutManager(this, spanCount)
 | 
				
			||||||
 | 
					        binding.rvCharacters.addItemDecoration(
 | 
				
			||||||
 | 
					            GridSpacingItemDecoration(
 | 
				
			||||||
 | 
					                spanCount,
 | 
				
			||||||
 | 
					                spacingPx,
 | 
				
			||||||
 | 
					                false
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        binding.rvCharacters.addOnScrollListener(object : RecyclerView.OnScrollListener() {
 | 
				
			||||||
 | 
					            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
 | 
				
			||||||
 | 
					                super.onScrolled(recyclerView, dx, dy)
 | 
				
			||||||
 | 
					                val lastVisibleItemPosition = (recyclerView.layoutManager as LinearLayoutManager)
 | 
				
			||||||
 | 
					                    .findLastVisibleItemPosition()
 | 
				
			||||||
 | 
					                val totalItemCount = recyclerView.adapter?.itemCount ?: 0
 | 
				
			||||||
 | 
					                if (
 | 
				
			||||||
 | 
					                    !recyclerView.canScrollVertically(1) &&
 | 
				
			||||||
 | 
					                    lastVisibleItemPosition >= totalItemCount - 1
 | 
				
			||||||
 | 
					                ) {
 | 
				
			||||||
 | 
					                    viewModel.loadMore()
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					        binding.rvCharacters.adapter = adapter
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun bindData() {
 | 
				
			||||||
 | 
					        viewModel.isLoading.observe(this) { isLoading ->
 | 
				
			||||||
 | 
					            if (isLoading) loadingDialog.show(screenWidth) else loadingDialog.dismiss()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        viewModel.totalCount.observe(this) { count ->
 | 
				
			||||||
 | 
					            binding.tvTotalCount.text = "$count"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        viewModel.items.observe(this) { list ->
 | 
				
			||||||
 | 
					            adapter.addItems(list.drop(adapter.itemCount))
 | 
				
			||||||
 | 
					            binding.rvCharacters.visibility = if (list.isEmpty()) View.GONE else View.VISIBLE
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        viewModel.toastLiveData.observe(this) { message ->
 | 
				
			||||||
 | 
					            message?.let { showToast(it) }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					package kr.co.vividnext.sodalive.chat.character.newcharacters
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import android.annotation.SuppressLint
 | 
				
			||||||
 | 
					import android.view.LayoutInflater
 | 
				
			||||||
 | 
					import android.view.ViewGroup
 | 
				
			||||||
 | 
					import androidx.recyclerview.widget.RecyclerView
 | 
				
			||||||
 | 
					import coil.load
 | 
				
			||||||
 | 
					import coil.transform.RoundedCornersTransformation
 | 
				
			||||||
 | 
					import kr.co.vividnext.sodalive.R
 | 
				
			||||||
 | 
					import kr.co.vividnext.sodalive.chat.character.Character
 | 
				
			||||||
 | 
					import kr.co.vividnext.sodalive.databinding.ItemNewCharacterAllBinding
 | 
				
			||||||
 | 
					import kr.co.vividnext.sodalive.extensions.dpToPx
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class NewCharactersAllAdapter(
 | 
				
			||||||
 | 
					    private val onClick: (Long) -> Unit
 | 
				
			||||||
 | 
					) : RecyclerView.Adapter<NewCharactersAllAdapter.VH>() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private val items = mutableListOf<Character>()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inner class VH(val binding: ItemNewCharacterAllBinding) : RecyclerView.ViewHolder(binding.root) {
 | 
				
			||||||
 | 
					        fun bind(item: Character) {
 | 
				
			||||||
 | 
					            binding.tvCharacterName.text = item.name
 | 
				
			||||||
 | 
					            binding.tvCharacterDescription.text = item.description
 | 
				
			||||||
 | 
					            binding.ivCharacter.load(item.imageUrl) {
 | 
				
			||||||
 | 
					                crossfade(true)
 | 
				
			||||||
 | 
					                placeholder(R.drawable.ic_logo_service_center)
 | 
				
			||||||
 | 
					                transformations(RoundedCornersTransformation(16f.dpToPx()))
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            binding.root.setOnClickListener { onClick(item.characterId) }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH {
 | 
				
			||||||
 | 
					        val binding = ItemNewCharacterAllBinding.inflate(LayoutInflater.from(parent.context), parent, false)
 | 
				
			||||||
 | 
					        return VH(binding)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override fun getItemCount(): Int = items.size
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override fun onBindViewHolder(holder: VH, position: Int) {
 | 
				
			||||||
 | 
					        holder.bind(items[position])
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun addItems(newItems: List<Character>) {
 | 
				
			||||||
 | 
					        val start = items.size
 | 
				
			||||||
 | 
					        items.addAll(newItems)
 | 
				
			||||||
 | 
					        notifyItemRangeInserted(start, newItems.size)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @SuppressLint("NotifyDataSetChanged")
 | 
				
			||||||
 | 
					    fun clear() {
 | 
				
			||||||
 | 
					        items.clear()
 | 
				
			||||||
 | 
					        notifyDataSetChanged()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,68 @@
 | 
				
			|||||||
 | 
					package kr.co.vividnext.sodalive.chat.character.newcharacters
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import androidx.lifecycle.LiveData
 | 
				
			||||||
 | 
					import androidx.lifecycle.MutableLiveData
 | 
				
			||||||
 | 
					import com.orhanobut.logger.Logger
 | 
				
			||||||
 | 
					import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
 | 
				
			||||||
 | 
					import io.reactivex.rxjava3.schedulers.Schedulers
 | 
				
			||||||
 | 
					import kr.co.vividnext.sodalive.base.BaseViewModel
 | 
				
			||||||
 | 
					import kr.co.vividnext.sodalive.chat.character.Character
 | 
				
			||||||
 | 
					import kr.co.vividnext.sodalive.common.SharedPreferenceManager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class NewCharactersAllViewModel(
 | 
				
			||||||
 | 
					    private val repository: NewCharactersRepository
 | 
				
			||||||
 | 
					) : BaseViewModel() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private val _toastLiveData = MutableLiveData<String?>()
 | 
				
			||||||
 | 
					    val toastLiveData: LiveData<String?> get() = _toastLiveData
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private val _isLoading = MutableLiveData(false)
 | 
				
			||||||
 | 
					    val isLoading: LiveData<Boolean> get() = _isLoading
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private val _totalCount = MutableLiveData<Long>(0)
 | 
				
			||||||
 | 
					    val totalCount: LiveData<Long> get() = _totalCount
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private val _items = MutableLiveData<List<Character>>(emptyList())
 | 
				
			||||||
 | 
					    val items: LiveData<List<Character>> get() = _items
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private var page = 0
 | 
				
			||||||
 | 
					    private val size = 20
 | 
				
			||||||
 | 
					    private var isLast = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun loadMore() {
 | 
				
			||||||
 | 
					        if (_isLoading.value == true || isLast) return
 | 
				
			||||||
 | 
					        _isLoading.value = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        compositeDisposable.add(
 | 
				
			||||||
 | 
					            repository.getRecentCharacters(
 | 
				
			||||||
 | 
					                token = "Bearer ${SharedPreferenceManager.token}",
 | 
				
			||||||
 | 
					                page = page,
 | 
				
			||||||
 | 
					                size = size
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					                .subscribeOn(Schedulers.io())
 | 
				
			||||||
 | 
					                .observeOn(AndroidSchedulers.mainThread())
 | 
				
			||||||
 | 
					                .subscribe({ response ->
 | 
				
			||||||
 | 
					                    val data = response.data
 | 
				
			||||||
 | 
					                    if (response.success && data != null) {
 | 
				
			||||||
 | 
					                        val current = _items.value ?: emptyList()
 | 
				
			||||||
 | 
					                        val next = current + data.content
 | 
				
			||||||
 | 
					                        _items.value = next
 | 
				
			||||||
 | 
					                        _totalCount.value = data.totalCount
 | 
				
			||||||
 | 
					                        if (data.content.isNotEmpty()) {
 | 
				
			||||||
 | 
					                            page += 1
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            isLast = true
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        _toastLiveData.value = response.message
 | 
				
			||||||
 | 
					                            ?: "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    _isLoading.value = false
 | 
				
			||||||
 | 
					                }, { e ->
 | 
				
			||||||
 | 
					                    _isLoading.value = false
 | 
				
			||||||
 | 
					                    e.message?.let { Logger.e(it) }
 | 
				
			||||||
 | 
					                    _toastLiveData.value = "알 수 없는 오류가 발생했습니다. 다시 시도해 주세요."
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					package kr.co.vividnext.sodalive.chat.character.newcharacters
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import io.reactivex.rxjava3.core.Single
 | 
				
			||||||
 | 
					import kr.co.vividnext.sodalive.chat.character.CharacterApi
 | 
				
			||||||
 | 
					import kr.co.vividnext.sodalive.common.ApiResponse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class NewCharactersRepository(
 | 
				
			||||||
 | 
					    private val api: CharacterApi
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    fun getRecentCharacters(
 | 
				
			||||||
 | 
					        token: String,
 | 
				
			||||||
 | 
					        page: Int,
 | 
				
			||||||
 | 
					        size: Int
 | 
				
			||||||
 | 
					    ): Single<ApiResponse<RecentCharactersResponse>> {
 | 
				
			||||||
 | 
					        return api.getRecentCharacters(
 | 
				
			||||||
 | 
					            authHeader = token,
 | 
				
			||||||
 | 
					            page = page,
 | 
				
			||||||
 | 
					            size = size
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					package kr.co.vividnext.sodalive.chat.character.newcharacters
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import androidx.annotation.Keep
 | 
				
			||||||
 | 
					import com.google.gson.annotations.SerializedName
 | 
				
			||||||
 | 
					import kr.co.vividnext.sodalive.chat.character.Character
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Keep
 | 
				
			||||||
 | 
					data class RecentCharactersResponse(
 | 
				
			||||||
 | 
					    @SerializedName("totalCount") val totalCount: Long,
 | 
				
			||||||
 | 
					    @SerializedName("content") val content: List<Character>
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
@@ -67,6 +67,8 @@ import kr.co.vividnext.sodalive.audition.role.AuditionRoleDetailViewModel
 | 
				
			|||||||
import kr.co.vividnext.sodalive.chat.character.CharacterApi
 | 
					import kr.co.vividnext.sodalive.chat.character.CharacterApi
 | 
				
			||||||
import kr.co.vividnext.sodalive.chat.character.CharacterTabRepository
 | 
					import kr.co.vividnext.sodalive.chat.character.CharacterTabRepository
 | 
				
			||||||
import kr.co.vividnext.sodalive.chat.character.CharacterTabViewModel
 | 
					import kr.co.vividnext.sodalive.chat.character.CharacterTabViewModel
 | 
				
			||||||
 | 
					import kr.co.vividnext.sodalive.chat.character.newcharacters.NewCharactersAllViewModel
 | 
				
			||||||
 | 
					import kr.co.vividnext.sodalive.chat.character.newcharacters.NewCharactersRepository
 | 
				
			||||||
import kr.co.vividnext.sodalive.chat.character.comment.CharacterCommentApi
 | 
					import kr.co.vividnext.sodalive.chat.character.comment.CharacterCommentApi
 | 
				
			||||||
import kr.co.vividnext.sodalive.chat.character.comment.CharacterCommentRepository
 | 
					import kr.co.vividnext.sodalive.chat.character.comment.CharacterCommentRepository
 | 
				
			||||||
import kr.co.vividnext.sodalive.chat.character.detail.detail.CharacterDetailRepository
 | 
					import kr.co.vividnext.sodalive.chat.character.detail.detail.CharacterDetailRepository
 | 
				
			||||||
@@ -364,6 +366,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) {
 | 
				
			|||||||
        viewModel { TalkTabViewModel(get()) }
 | 
					        viewModel { TalkTabViewModel(get()) }
 | 
				
			||||||
        viewModel { kr.co.vividnext.sodalive.chat.character.comment.CharacterCommentListViewModel(get()) }
 | 
					        viewModel { kr.co.vividnext.sodalive.chat.character.comment.CharacterCommentListViewModel(get()) }
 | 
				
			||||||
        viewModel { kr.co.vividnext.sodalive.chat.character.comment.CharacterCommentReplyViewModel(get()) }
 | 
					        viewModel { kr.co.vividnext.sodalive.chat.character.comment.CharacterCommentReplyViewModel(get()) }
 | 
				
			||||||
 | 
					        viewModel { NewCharactersAllViewModel(get()) }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private val repositoryModule = module {
 | 
					    private val repositoryModule = module {
 | 
				
			||||||
@@ -413,6 +416,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) {
 | 
				
			|||||||
        factory { CharacterGalleryRepository(get()) }
 | 
					        factory { CharacterGalleryRepository(get()) }
 | 
				
			||||||
        factory { TalkTabRepository(get()) }
 | 
					        factory { TalkTabRepository(get()) }
 | 
				
			||||||
        factory { CharacterCommentRepository(get()) }
 | 
					        factory { CharacterCommentRepository(get()) }
 | 
				
			||||||
 | 
					        factory { NewCharactersRepository(get()) }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										61
									
								
								app/src/main/res/layout/activity_new_characters_all.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								app/src/main/res/layout/activity_new_characters_all.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 | 
				
			||||||
 | 
					    xmlns:tools="http://schemas.android.com/tools"
 | 
				
			||||||
 | 
					    android:layout_width="match_parent"
 | 
				
			||||||
 | 
					    android:layout_height="match_parent"
 | 
				
			||||||
 | 
					    android:background="@color/black"
 | 
				
			||||||
 | 
					    android:orientation="vertical">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <include
 | 
				
			||||||
 | 
					        android:id="@+id/toolbar"
 | 
				
			||||||
 | 
					        layout="@layout/detail_toolbar" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <LinearLayout
 | 
				
			||||||
 | 
					        android:layout_width="match_parent"
 | 
				
			||||||
 | 
					        android:layout_height="wrap_content"
 | 
				
			||||||
 | 
					        android:layout_gravity="center_vertical"
 | 
				
			||||||
 | 
					        android:layout_marginTop="13.3dp"
 | 
				
			||||||
 | 
					        android:orientation="horizontal"
 | 
				
			||||||
 | 
					        android:paddingHorizontal="24dp"
 | 
				
			||||||
 | 
					        android:paddingVertical="6.7dp">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <TextView
 | 
				
			||||||
 | 
					            android:layout_width="wrap_content"
 | 
				
			||||||
 | 
					            android:layout_height="wrap_content"
 | 
				
			||||||
 | 
					            android:fontFamily="@font/gmarket_sans_medium"
 | 
				
			||||||
 | 
					            android:gravity="center"
 | 
				
			||||||
 | 
					            android:text="전체"
 | 
				
			||||||
 | 
					            android:textColor="@color/color_e2e2e2"
 | 
				
			||||||
 | 
					            android:textSize="13.3sp" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <TextView
 | 
				
			||||||
 | 
					            android:id="@+id/tv_total_count"
 | 
				
			||||||
 | 
					            android:layout_width="wrap_content"
 | 
				
			||||||
 | 
					            android:layout_height="wrap_content"
 | 
				
			||||||
 | 
					            android:layout_marginStart="8dp"
 | 
				
			||||||
 | 
					            android:fontFamily="@font/gmarket_sans_medium"
 | 
				
			||||||
 | 
					            android:gravity="center"
 | 
				
			||||||
 | 
					            android:text="0"
 | 
				
			||||||
 | 
					            android:textColor="@color/color_ff5c49"
 | 
				
			||||||
 | 
					            android:textSize="13.3sp" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <TextView
 | 
				
			||||||
 | 
					            android:layout_width="wrap_content"
 | 
				
			||||||
 | 
					            android:layout_height="wrap_content"
 | 
				
			||||||
 | 
					            android:layout_marginStart="2dp"
 | 
				
			||||||
 | 
					            android:fontFamily="@font/gmarket_sans_medium"
 | 
				
			||||||
 | 
					            android:gravity="center"
 | 
				
			||||||
 | 
					            android:text="개"
 | 
				
			||||||
 | 
					            android:textColor="@color/color_e2e2e2"
 | 
				
			||||||
 | 
					            android:textSize="13.3sp" />
 | 
				
			||||||
 | 
					    </LinearLayout>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <androidx.recyclerview.widget.RecyclerView
 | 
				
			||||||
 | 
					        android:id="@+id/rv_characters"
 | 
				
			||||||
 | 
					        android:layout_width="match_parent"
 | 
				
			||||||
 | 
					        android:layout_height="match_parent"
 | 
				
			||||||
 | 
					        android:clipToPadding="false"
 | 
				
			||||||
 | 
					        android:padding="12dp"
 | 
				
			||||||
 | 
					        tools:listitem="@layout/item_new_character_all" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</LinearLayout>
 | 
				
			||||||
@@ -160,8 +160,7 @@
 | 
				
			|||||||
                    android:fontFamily="@font/pretendard_regular"
 | 
					                    android:fontFamily="@font/pretendard_regular"
 | 
				
			||||||
                    android:text="전체보기"
 | 
					                    android:text="전체보기"
 | 
				
			||||||
                    android:textColor="#90A4AE"
 | 
					                    android:textColor="#90A4AE"
 | 
				
			||||||
                    android:textSize="14sp"
 | 
					                    android:textSize="14sp" />
 | 
				
			||||||
                    android:visibility="gone" />
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            </LinearLayout>
 | 
					            </LinearLayout>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										52
									
								
								app/src/main/res/layout/item_new_character_all.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								app/src/main/res/layout/item_new_character_all.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
 | 
				
			||||||
 | 
					    xmlns:app="http://schemas.android.com/apk/res-auto"
 | 
				
			||||||
 | 
					    xmlns:tools="http://schemas.android.com/tools"
 | 
				
			||||||
 | 
					    android:layout_width="match_parent"
 | 
				
			||||||
 | 
					    android:layout_height="wrap_content"
 | 
				
			||||||
 | 
					    android:paddingStart="0dp"
 | 
				
			||||||
 | 
					    android:paddingEnd="0dp">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <ImageView
 | 
				
			||||||
 | 
					        android:id="@+id/iv_character"
 | 
				
			||||||
 | 
					        android:layout_width="0dp"
 | 
				
			||||||
 | 
					        android:layout_height="0dp"
 | 
				
			||||||
 | 
					        android:scaleType="centerCrop"
 | 
				
			||||||
 | 
					        android:contentDescription="@null"
 | 
				
			||||||
 | 
					        app:layout_constraintTop_toTopOf="parent"
 | 
				
			||||||
 | 
					        app:layout_constraintStart_toStartOf="parent"
 | 
				
			||||||
 | 
					        app:layout_constraintEnd_toEndOf="parent"
 | 
				
			||||||
 | 
					        app:layout_constraintDimensionRatio="1:1"
 | 
				
			||||||
 | 
					        tools:src="@drawable/ic_logo_service_center" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <TextView
 | 
				
			||||||
 | 
					        android:id="@+id/tv_character_name"
 | 
				
			||||||
 | 
					        android:layout_width="0dp"
 | 
				
			||||||
 | 
					        android:layout_height="wrap_content"
 | 
				
			||||||
 | 
					        android:layout_marginStart="6dp"
 | 
				
			||||||
 | 
					        android:layout_marginTop="4dp"
 | 
				
			||||||
 | 
					        android:ellipsize="end"
 | 
				
			||||||
 | 
					        android:maxLines="1"
 | 
				
			||||||
 | 
					        android:textColor="@color/color_b0bec5"
 | 
				
			||||||
 | 
					        android:textSize="18sp"
 | 
				
			||||||
 | 
					        app:layout_constraintTop_toBottomOf="@id/iv_character"
 | 
				
			||||||
 | 
					        app:layout_constraintStart_toStartOf="parent"
 | 
				
			||||||
 | 
					        app:layout_constraintEnd_toEndOf="parent"
 | 
				
			||||||
 | 
					        tools:text="캐릭터 이름" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <TextView
 | 
				
			||||||
 | 
					        android:id="@+id/tv_character_description"
 | 
				
			||||||
 | 
					        android:layout_width="0dp"
 | 
				
			||||||
 | 
					        android:layout_height="wrap_content"
 | 
				
			||||||
 | 
					        android:layout_marginStart="6dp"
 | 
				
			||||||
 | 
					        android:layout_marginTop="4dp"
 | 
				
			||||||
 | 
					        android:ellipsize="end"
 | 
				
			||||||
 | 
					        android:maxLines="1"
 | 
				
			||||||
 | 
					        android:textColor="#78909C"
 | 
				
			||||||
 | 
					        android:textSize="14sp"
 | 
				
			||||||
 | 
					        app:layout_constraintTop_toBottomOf="@id/tv_character_name"
 | 
				
			||||||
 | 
					        app:layout_constraintStart_toStartOf="parent"
 | 
				
			||||||
 | 
					        app:layout_constraintEnd_toEndOf="parent"
 | 
				
			||||||
 | 
					        tools:text="설명 텍스트" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</androidx.constraintlayout.widget.ConstraintLayout>
 | 
				
			||||||
		Reference in New Issue
	
	Block a user