diff --git a/app/build.gradle b/app/build.gradle
index c10c2e0c8..b840f7b09 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -211,9 +211,6 @@ dependencies {
// indicator
implementation libs.pageindicatorview
- // sendbird sdk
- implementation libs.sendbird.chat
-
// google play-auth
implementation libs.play.services.auth
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 19fff39b7..41f0c8349 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -82,11 +82,6 @@
android:exported="true"
android:screenOrientation="portrait" />
-
-
-
{
-
- private val appId = BuildConfig.SENDBIRD_APP_ID
-
- override fun create(context: Context) {
- SendbirdChat.init(
- InitParams(
- appId = appId,
- context = context.applicationContext,
- useCaching = false
- ),
- object : InitResultHandler {
- override fun onMigrationStarted() {
- // This won't be called if useLocalCaching is set to false.
- Timber.e("Sendbird migration started")
- }
-
- override fun onInitSucceed() {
- // This won't be called if useLocalCaching is set to false.
- Timber.e("Sendbird init succeed")
- }
-
- override fun onInitFailed(e: SendbirdException) {
- Timber.e("Sendbird init failed : [${e.code}] ${e.message}")
- }
- }
- )
- }
-
- override fun dependencies(): List>> {
- return listOf(TimberInitializer::class.java)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/ku_stacks/ku_ring/navigator/KuringNavigator.kt b/app/src/main/java/com/ku_stacks/ku_ring/navigator/KuringNavigator.kt
index 618bb0b63..f243ddc65 100644
--- a/app/src/main/java/com/ku_stacks/ku_ring/navigator/KuringNavigator.kt
+++ b/app/src/main/java/com/ku_stacks/ku_ring/navigator/KuringNavigator.kt
@@ -7,7 +7,6 @@ import com.ku_stacks.ku_ring.data.model.Notice
import com.ku_stacks.ku_ring.data.model.WebViewNotice
interface KuringNavigator {
- fun navigateToChat(activity: Activity)
fun createEditSubscriptionIntent(context: Context, isFirstRun: Boolean = false): Intent
fun navigateToEditSubscription(activity: Activity, isFirstRun: Boolean = false)
fun navigateToFeedback(activity: Activity)
diff --git a/app/src/main/java/com/ku_stacks/ku_ring/navigator/KuringNavigatorImpl.kt b/app/src/main/java/com/ku_stacks/ku_ring/navigator/KuringNavigatorImpl.kt
index daef25ab8..0231dcde7 100644
--- a/app/src/main/java/com/ku_stacks/ku_ring/navigator/KuringNavigatorImpl.kt
+++ b/app/src/main/java/com/ku_stacks/ku_ring/navigator/KuringNavigatorImpl.kt
@@ -7,7 +7,6 @@ import com.google.android.gms.oss.licenses.OssLicensesMenuActivity
import com.ku_stacks.ku_ring.R
import com.ku_stacks.ku_ring.data.model.Notice
import com.ku_stacks.ku_ring.data.model.WebViewNotice
-import com.ku_stacks.ku_ring.ui.chat.ChatActivity
import com.ku_stacks.ku_ring.ui.edit_subscription.EditSubscriptionActivity
import com.ku_stacks.ku_ring.ui.feedback.FeedbackActivity
import com.ku_stacks.ku_ring.ui.main.MainActivity
@@ -19,10 +18,7 @@ import com.ku_stacks.ku_ring.ui.onboarding.OnboardingActivity
import com.ku_stacks.ku_ring.ui.splash.SplashActivity
import javax.inject.Inject
-class KuringNavigatorImpl @Inject constructor(): KuringNavigator {
- override fun navigateToChat(activity: Activity) {
- ChatActivity.start(activity)
- }
+class KuringNavigatorImpl @Inject constructor() : KuringNavigator {
override fun createEditSubscriptionIntent(context: Context, isFirstRun: Boolean): Intent {
return Intent(context, EditSubscriptionActivity::class.java).apply {
diff --git a/app/src/main/java/com/ku_stacks/ku_ring/repository/SendbirdRepository.kt b/app/src/main/java/com/ku_stacks/ku_ring/repository/SendbirdRepository.kt
deleted file mode 100644
index 16a45ba0a..000000000
--- a/app/src/main/java/com/ku_stacks/ku_ring/repository/SendbirdRepository.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.ku_stacks.ku_ring.repository
-
-import io.reactivex.rxjava3.core.Single
-
-interface SendbirdRepository {
- fun hasDuplicateNickname(nickname: String, userId: String): Single
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/ku_stacks/ku_ring/repository/SendbirdRepositoryImpl.kt b/app/src/main/java/com/ku_stacks/ku_ring/repository/SendbirdRepositoryImpl.kt
deleted file mode 100644
index fe982874e..000000000
--- a/app/src/main/java/com/ku_stacks/ku_ring/repository/SendbirdRepositoryImpl.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.ku_stacks.ku_ring.repository
-
-import com.ku_stacks.ku_ring.data.api.SendbirdClient
-import io.reactivex.rxjava3.core.Single
-import io.reactivex.rxjava3.schedulers.Schedulers
-import javax.inject.Inject
-
-class SendbirdRepositoryImpl @Inject constructor(
- private val sendbirdClient: SendbirdClient
-) : SendbirdRepository {
-
- override fun hasDuplicateNickname(nickname: String, userId: String): Single {
- return sendbirdClient.fetchNicknameList(nickname)
- .subscribeOn(Schedulers.io())
- .map {
- it.users.any { userResponse -> userResponse.userId != userId }
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/ChatActivity.kt b/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/ChatActivity.kt
deleted file mode 100644
index 96750fe73..000000000
--- a/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/ChatActivity.kt
+++ /dev/null
@@ -1,190 +0,0 @@
-package com.ku_stacks.ku_ring.ui.chat
-
-import android.app.Activity
-import android.content.ClipData
-import android.content.ClipboardManager
-import android.content.Intent
-import android.content.res.ColorStateList
-import android.os.Bundle
-import android.text.Editable
-import android.text.TextWatcher
-import androidx.activity.viewModels
-import androidx.appcompat.app.AppCompatActivity
-import androidx.core.widget.ImageViewCompat
-import androidx.databinding.DataBindingUtil
-import com.ku_stacks.ku_ring.R
-import com.ku_stacks.ku_ring.databinding.ActivityChatBinding
-import com.ku_stacks.ku_ring.ui.chat.ui_model.ReceivedMessageUiModel
-import com.ku_stacks.ku_ring.ui.chat.ui_model.SentMessageUiModel
-import com.ku_stacks.ku_ring.ui.dialogs.ChatActionDialog
-import com.ku_stacks.ku_ring.util.makeDialog
-import com.ku_stacks.ku_ring.util.modified_external_library.RecyclerViewPager
-import com.ku_stacks.ku_ring.util.showToast
-import dagger.hilt.android.AndroidEntryPoint
-
-@AndroidEntryPoint
-class ChatActivity : AppCompatActivity() {
-
- private lateinit var binding: ActivityChatBinding
- private val viewModel by viewModels()
-
- private lateinit var chatMessageAdapter: ChatMessageAdapter
- private lateinit var recyclerObserver: ChatRecyclerDataObserver
- private lateinit var pager: RecyclerViewPager
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
-
- setupBinding()
- setupView()
- setupRecyclerView()
- observeData()
- observeEvent()
- }
-
- private fun setupBinding() {
- binding = DataBindingUtil.setContentView(this, R.layout.activity_chat)
- binding.lifecycleOwner = this
- binding.viewModel = viewModel
- }
-
- private fun setupView() {
- binding.chatBackBt.setOnClickListener {
- finish()
- overridePendingTransition(R.anim.anim_slide_left_enter, R.anim.anim_slide_left_exit)
- }
-
- binding.chatSendBt.setOnClickListener {
- val message = binding.chatMessageEt.text.toString()
- binding.chatMessageEt.text.clear()
- viewModel.sendMessage(message)
- }
- binding.chatMessageEt.addTextChangedListener(object : TextWatcher {
- override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) =
- Unit
-
- override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) = Unit
- override fun afterTextChanged(s: Editable?) {
- val textTintColor = if (s.isNullOrEmpty()) {
- R.color.kus_green_50
- } else {
- R.color.kus_green
- }
- ImageViewCompat.setImageTintList(
- binding.chatSendBt,
- ColorStateList.valueOf(getColor(textTintColor))
- )
-
- s?.length?.let { len ->
- val maxLen = 300
- if (len > maxLen) {
- showToast(getString(R.string.chat_max_message_length, maxLen.toString()))
- binding.chatMessageEt.setText(s.substring(0, maxLen))
- binding.chatMessageEt.setSelection(binding.chatMessageEt.length())
- }
- }
- }
- })
- }
-
- private fun setupRecyclerView() {
- chatMessageAdapter = ChatMessageAdapter(
- onErrorClick = { sentMessageUiModel -> makeResendDialog(sentMessageUiModel) },
- onMessageLongClick = { receivedMessageUiModel ->
- makeChatActionDialog(
- receivedMessageUiModel
- )
- }
- )
-
- binding.chatRecyclerview.apply {
- adapter = chatMessageAdapter
- pager = RecyclerViewPager(
- recyclerView = this,
- isReversed = true,
- isLoading = { viewModel.isLoading.value == true },
- loadNext = { viewModel.fetchPreviousMessageList(chatMessageAdapter.currentList.first().timeStamp) },
- isEnd = { viewModel.hasPrevious.value == false }
- )
- pager.prefetchDistance = 30
- }
-
- recyclerObserver = ChatRecyclerDataObserver(
- recyclerView = binding.chatRecyclerview
- )
- chatMessageAdapter.registerAdapterDataObserver(recyclerObserver)
- }
-
- private fun observeData() {
- viewModel.chatUiModelList.observe(this) {
- chatMessageAdapter.submitList(it.toList()) {
- viewModel.isLoading.postValue(false)
- }
- }
- }
-
- private fun observeEvent() {
- viewModel.dialogEvent.observe(this) {
- makeDialog(description = getString(it))
- }
-
- viewModel.toastEvent.observe(this) {
- showToast(getString(it))
- }
-
- viewModel.readyToBottomScrollEvent.observe(this) {
- recyclerObserver.readyToBottomScroll(true)
- }
- }
-
- private fun makeResendDialog(sentMessageUiModel: SentMessageUiModel) {
- makeDialog(
- description = getString(R.string.chat_resend_message),
- leftText = getString(R.string.chat_delete),
- rightText = getString(R.string.chat_resend)
- ).setOnCancelClickListener {
- viewModel.deletePendingMessage(sentMessageUiModel)
- }.setOnConfirmClickListener {
- viewModel.deletePendingMessage(sentMessageUiModel)
- viewModel.sendMessage(sentMessageUiModel.message)
- }
- }
-
- private fun makeChatActionDialog(messageUiModel: ReceivedMessageUiModel) {
- ChatActionDialog(this).apply {
- show()
- }.setOnCopyMessageClickListener {
- val clipboardManager = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
- val clipData = ClipData.newPlainText("message", messageUiModel.message)
- clipboardManager.setPrimaryClip(clipData)
- showToast(getString(R.string.chat_copied_message))
- }.setOnCopyNicknameClickListener {
- val clipboardManager = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
- val clipData = ClipData.newPlainText("nickname", messageUiModel.nickname)
- clipboardManager.setPrimaryClip(clipData)
- showToast(getString(R.string.chat_copied_nickname))
- }.setOnReportClickListener {
- makeDialog(description = getString(R.string.report_ask_again))
- .setOnConfirmClickListener {
- viewModel.reportMessage(messageUiModel)
- }
- }.setOnBlockClickListener {
- makeDialog(description = getString(R.string.block_ask_again))
- .setOnConfirmClickListener {
- viewModel.blockUser(messageUiModel)
- }
- }
- }
-
- override fun onBackPressed() {
- super.onBackPressed()
- overridePendingTransition(R.anim.anim_slide_left_enter, R.anim.anim_slide_left_exit)
- }
-
- companion object {
- fun start(activity: Activity) {
- val intent = Intent(activity, ChatActivity::class.java)
- activity.startActivity(intent)
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/ChatMessageAdapter.kt b/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/ChatMessageAdapter.kt
deleted file mode 100644
index 74a6bf566..000000000
--- a/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/ChatMessageAdapter.kt
+++ /dev/null
@@ -1,150 +0,0 @@
-package com.ku_stacks.ku_ring.ui.chat
-
-import android.view.LayoutInflater
-import android.view.ViewGroup
-import androidx.recyclerview.widget.DiffUtil
-import androidx.recyclerview.widget.ListAdapter
-import androidx.recyclerview.widget.RecyclerView.NO_POSITION
-import com.ku_stacks.ku_ring.R
-import com.ku_stacks.ku_ring.databinding.ItemChatAdminBinding
-import com.ku_stacks.ku_ring.databinding.ItemChatReceiveBinding
-import com.ku_stacks.ku_ring.databinding.ItemChatSendBinding
-import com.ku_stacks.ku_ring.ui.chat.ui_model.AdminMessageUiModel
-import com.ku_stacks.ku_ring.ui.chat.ui_model.ChatUiModel
-import com.ku_stacks.ku_ring.ui.chat.ui_model.ReceivedMessageUiModel
-import com.ku_stacks.ku_ring.ui.chat.ui_model.SentMessageUiModel
-import com.ku_stacks.ku_ring.ui.chat.viewholder.AdminViewHolder
-import com.ku_stacks.ku_ring.ui.chat.viewholder.ReceiveViewHolder
-import com.ku_stacks.ku_ring.ui.chat.viewholder.SealedChatViewHolder
-import com.ku_stacks.ku_ring.ui.chat.viewholder.SendViewHolder
-import com.ku_stacks.ku_ring.util.DateUtil.areSameDate
-
-class ChatMessageAdapter(
- private val onErrorClick: (SentMessageUiModel) -> Unit,
- private val onMessageLongClick: (ReceivedMessageUiModel) -> Unit
-) : ListAdapter(MessageDiffCallback) {
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SealedChatViewHolder {
- return when (viewType) {
- CHAT_RECEIVED -> {
- createReceivedViewHolder(parent)
- }
-
- CHAT_SENT -> {
- createSendViewHolder(parent)
- }
-
- CHAT_ADMIN -> {
- createAdminViewHolder(parent)
- }
-
- else -> {
- throw IllegalStateException("no such viewType : $viewType")
- }
- }
- }
-
- private fun createAdminViewHolder(parent: ViewGroup): AdminViewHolder {
- val view = LayoutInflater.from(parent.context)
- .inflate(R.layout.item_chat_admin, parent, false)
- val binding = ItemChatAdminBinding.bind(view)
- return AdminViewHolder(binding)
- }
-
- private fun createSendViewHolder(parent: ViewGroup): SendViewHolder {
- val view = LayoutInflater.from(parent.context)
- .inflate(R.layout.item_chat_send, parent, false)
- val binding = ItemChatSendBinding.bind(view)
- return SendViewHolder(binding).apply {
- binding.chatSendErrorIv.setOnClickListener {
- val position = absoluteAdapterPosition.takeIf { it != NO_POSITION }
- ?: return@setOnClickListener
- onErrorClick(getItem(position) as SentMessageUiModel)
- }
- }
- }
-
- private fun createReceivedViewHolder(parent: ViewGroup): ReceiveViewHolder {
- val view = LayoutInflater.from(parent.context)
- .inflate(R.layout.item_chat_receive, parent, false)
- val binding = ItemChatReceiveBinding.bind(view)
- return ReceiveViewHolder(binding).apply {
- binding.chatMessageLayout.setOnLongClickListener {
- val position = absoluteAdapterPosition.takeIf { it != NO_POSITION }
- ?: return@setOnLongClickListener false
- onMessageLongClick(getItem(position) as ReceivedMessageUiModel)
- return@setOnLongClickListener true
- }
- }
- }
-
- override fun onBindViewHolder(holder: SealedChatViewHolder, position: Int) {
- val showDate = if (position > 0) {
- val cur = currentList[position].timeStamp
- val prev = currentList[position - 1].timeStamp
- !areSameDate(cur, prev)
- } else {
- true
- }
-
- val item = getItem(position)
- when (holder) {
- is ReceiveViewHolder -> {
- holder.bind(item as ReceivedMessageUiModel, showDate)
- }
-
- is SendViewHolder -> {
- holder.bind(item as SentMessageUiModel, showDate)
- }
-
- is AdminViewHolder -> {
- holder.bind(item as AdminMessageUiModel, showDate)
- }
- }
- }
-
- override fun getItemViewType(position: Int): Int {
- return when (getItem(position)) {
- is ReceivedMessageUiModel -> CHAT_RECEIVED
- is SentMessageUiModel -> CHAT_SENT
- is AdminMessageUiModel -> CHAT_ADMIN
- }
- }
-
- companion object {
- const val CHAT_RECEIVED = 1
- const val CHAT_SENT = 2
- const val CHAT_ADMIN = 3
- }
-
- private object MessageDiffCallback : DiffUtil.ItemCallback() {
- override fun areItemsTheSame(oldItem: ChatUiModel, newItem: ChatUiModel): Boolean {
- // SentMessageUiModel 은 같은 말풍선에 대해서 messageId 가 (전송 시작) : 0, (전송 후) > 0 로 변하기 때문에 분기처리
- return if (oldItem is SentMessageUiModel && newItem is SentMessageUiModel) {
- if (oldItem.messageId > 0 && newItem.messageId > 0) {
- oldItem.messageId == newItem.messageId
- } else {
- oldItem.requestId == newItem.requestId
- }
- } else {
- oldItem.messageId == newItem.messageId
- }
-
- }
-
- override fun areContentsTheSame(oldItem: ChatUiModel, newItem: ChatUiModel): Boolean {
- return if (oldItem is ReceivedMessageUiModel && newItem is ReceivedMessageUiModel) {
- oldItem.messageId == newItem.messageId
- && oldItem.message == newItem.message
- } else if (oldItem is SentMessageUiModel && newItem is SentMessageUiModel) {
- oldItem.messageId == newItem.messageId
- && oldItem.message == newItem.message
- && oldItem.isPending == newItem.isPending
- } else if (oldItem is AdminMessageUiModel && newItem is AdminMessageUiModel) {
- oldItem.messageId == newItem.messageId
- && oldItem.message == newItem.message
- } else {
- false
- }
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/ChatRecyclerDataObserver.kt b/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/ChatRecyclerDataObserver.kt
deleted file mode 100644
index 9dca39e3b..000000000
--- a/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/ChatRecyclerDataObserver.kt
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.ku_stacks.ku_ring.ui.chat
-
-import androidx.recyclerview.widget.LinearLayoutManager
-import androidx.recyclerview.widget.RecyclerView
-
-// Reference : https://github.com/sendbird/sendbird-chat-sample-android/blob/main/commonmodule/src/main/java/com/sendbird/chat/module/utils/ChatRecyclerDataObserver.kt
-
-class ChatRecyclerDataObserver(
- private val recyclerView: RecyclerView
-) : RecyclerView.AdapterDataObserver() {
-
- private var scrollToBottom: Boolean = false
- private var adapter: RecyclerView.Adapter
- private var layoutManager: LinearLayoutManager
-
- init {
- if (recyclerView.adapter == null) {
- throw IllegalStateException("recyclerViewAdapter must be set")
- }
- adapter = recyclerView.adapter!!
- layoutManager = recyclerView.layoutManager as LinearLayoutManager
- }
-
- override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
- // 이미 가장 하단 메세지를 보고 있던 경우
- if (layoutManager.findLastCompletelyVisibleItemPosition() == adapter.itemCount - 2) {
- notifyUpdate()
- } else {
- // 스크롤을 강제로 내려야 하는 경우(메세지 전송 등)
- if (scrollToBottom) {
- notifyUpdate()
- }
- }
- super.onItemRangeInserted(positionStart, itemCount)
- }
-
- private fun notifyUpdate() {
- recyclerView.scrollToPosition(adapter.itemCount - 1)
- scrollToBottom = false
- }
-
- fun readyToBottomScroll(value: Boolean) {
- scrollToBottom = value
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/ChatViewModel.kt b/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/ChatViewModel.kt
deleted file mode 100644
index f117fad81..000000000
--- a/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/ChatViewModel.kt
+++ /dev/null
@@ -1,350 +0,0 @@
-package com.ku_stacks.ku_ring.ui.chat
-
-import androidx.lifecycle.LiveData
-import androidx.lifecycle.MutableLiveData
-import androidx.lifecycle.ViewModel
-import com.ku_stacks.ku_ring.BuildConfig
-import com.ku_stacks.ku_ring.R
-import com.ku_stacks.ku_ring.data.api.FeedbackClient
-import com.ku_stacks.ku_ring.data.api.request.FeedbackRequest
-import com.ku_stacks.ku_ring.repository.UserRepository
-import com.ku_stacks.ku_ring.ui.SingleLiveEvent
-import com.ku_stacks.ku_ring.ui.chat.ui_model.ChatUiModel
-import com.ku_stacks.ku_ring.ui.chat.ui_model.ReceivedMessageUiModel
-import com.ku_stacks.ku_ring.ui.chat.ui_model.SentMessageUiModel
-import com.ku_stacks.ku_ring.ui.chat.ui_model.toAdminMessageUiModel
-import com.ku_stacks.ku_ring.ui.chat.ui_model.toChatUiModelList
-import com.ku_stacks.ku_ring.ui.chat.ui_model.toReceivedMessageUiModel
-import com.ku_stacks.ku_ring.ui.chat.ui_model.toSentMessageUiModel
-import com.ku_stacks.ku_ring.util.PreferenceUtil
-import com.sendbird.android.SendbirdChat
-import com.sendbird.android.channel.BaseChannel
-import com.sendbird.android.channel.OpenChannel
-import com.sendbird.android.handler.ConnectionHandler
-import com.sendbird.android.handler.OpenChannelHandler
-import com.sendbird.android.message.AdminMessage
-import com.sendbird.android.message.BaseMessage
-import com.sendbird.android.message.UserMessage
-import com.sendbird.android.params.MessageListParams
-import com.sendbird.android.params.UserMessageCreateParams
-import dagger.hilt.android.lifecycle.HiltViewModel
-import io.reactivex.rxjava3.disposables.CompositeDisposable
-import io.reactivex.rxjava3.schedulers.Schedulers
-import timber.log.Timber
-import javax.inject.Inject
-
-@HiltViewModel
-class ChatViewModel @Inject constructor(
- private val pref: PreferenceUtil,
- private val feedbackClient: FeedbackClient,
- private val repository: UserRepository
-) : ViewModel() {
-
- private val disposable = CompositeDisposable()
-
- private val _dialogEvent = SingleLiveEvent()
- val dialogEvent: LiveData
- get() = _dialogEvent
-
- private val _toastEvent = SingleLiveEvent()
- val toastEvent: LiveData
- get() = _toastEvent
-
- private val normalMessageList = mutableListOf()
- private val pendingMessageList = mutableListOf()
- private val _chatUiModelList = MutableLiveData>()
- val chatUiModelList: LiveData>
- get() = _chatUiModelList
-
- private lateinit var blackUserList: List
-
- private val _hasPrevious = MutableLiveData()
- val hasPrevious: LiveData
- get() = _hasPrevious
-
- val isLoading = MutableLiveData(false)
-
- private val _readyToBottomScrollEvent = SingleLiveEvent()
- val readyToBottomScrollEvent: LiveData
- get() = _readyToBottomScrollEvent
-
- private var kuringChannel: OpenChannel? = null
-
- init {
- updateBlackUserList()
- enterChannel()
- addSendbirdHandler()
- }
-
- private fun updateBlackUserList() {
- disposable.add(
- repository.getBlackUserList()
- .subscribeOn(Schedulers.io())
- .subscribe({
- blackUserList = it
- }, {
- Timber.e("getBlackUserList error $it")
- })
- )
- }
-
- private fun enterChannel() {
- val channelUrl = BuildConfig.KURING_CAMPUS_OPEN_CHANNEL_URL
- OpenChannel.getChannel(channelUrl) { channel, e1 ->
- if (e1 != null) {
- Timber.e("Sendbird getChannel error [${e1.code}] : ${e1.message}")
- _dialogEvent.postValue(R.string.chat_get_channel_error)
- return@getChannel
- }
- channel?.enter { e2 ->
- if (e2 != null) {
- Timber.e("Sendbird enterChannel error [${e2.code}] : ${e2.message}")
- _dialogEvent.postValue(R.string.chat_enter_channel_error)
- return@enter
- }
- kuringChannel = channel
- Timber.e("Sendbird openChannel enter success")
-
- fetchPreviousMessageList(Long.MAX_VALUE)
- }
- }
- }
-
- fun sendMessage(text: String) {
- if (text.isEmpty()) {
- return
- }
- val params = UserMessageCreateParams(text)
- val pendingMessage = kuringChannel?.sendUserMessage(params) { message, e ->
- if (e != null) {
- Timber.e("Sendbird sendMessage error [${e.code}] : ${e.message}")
- updateErrorMessage(message)
- return@sendUserMessage
- }
- updateSucceedMessage(message)
- }
- _readyToBottomScrollEvent.call()
- addPendingMessage(pendingMessage)
- }
-
- fun deletePendingMessage(sentMessageUiModel: SentMessageUiModel) {
- pendingMessageList.removeIf { it.requestId == sentMessageUiModel.requestId }
- _chatUiModelList.postValue(normalMessageList + pendingMessageList)
- }
-
- private fun addPendingMessage(message: UserMessage?) {
- message?.let {
- pendingMessageList.add(it.toSentMessageUiModel(isPending = true))
- _chatUiModelList.postValue(normalMessageList + pendingMessageList)
- }
- }
-
- private fun updateErrorMessage(message: UserMessage?) {
- message?.let { msg ->
- pendingMessageList.forEachIndexed { index, pendingMessage ->
- if (pendingMessage.requestId == msg.requestId) {
- pendingMessageList[index] = msg.toSentMessageUiModel(null)
- return@forEachIndexed
- }
- }
- _chatUiModelList.postValue(normalMessageList + pendingMessageList)
- }
- }
-
- private fun updateSucceedMessage(message: UserMessage?) {
- message?.let { msg ->
- pendingMessageList.removeIf { it.requestId == msg.requestId }
- normalMessageList.add(msg.toSentMessageUiModel(isPending = false))
- _chatUiModelList.postValue(normalMessageList + pendingMessageList)
- }
- }
-
- fun fetchPreviousMessageList(timeStamp: Long) {
- isLoading.value = true
-
- val params = MessageListParams().apply {
- previousResultSize = 100
- }
- kuringChannel?.getMessagesByTimestamp(timeStamp, params) { messageList, e ->
- if (e != null) {
- isLoading.postValue(false)
- Timber.e("fetchPreviousMessageList error [${e.code}] : ${e.message}")
- return@getMessagesByTimestamp
- }
-
- if (messageList == null) {
- isLoading.postValue(false)
- Timber.e("fetchPreviousMessageList is null")
- return@getMessagesByTimestamp
- }
-
- if (messageList.isEmpty()) {
- _hasPrevious.value = false
- isLoading.postValue(false)
- } else {
- _hasPrevious.value = messageList.size >= params.previousResultSize
- normalMessageList.addAll(0, messageList.toChatUiModelList(blackUserList))
- _chatUiModelList.postValue(normalMessageList + pendingMessageList)
- }
- }
- }
-
- fun fetchLatestMessageList(timeStamp: Long) {
- isLoading.value = true
-
- val params = MessageListParams().apply {
- nextResultSize = 100
- }
- kuringChannel?.getMessagesByTimestamp(timeStamp, params) { messageList, e ->
- if (e != null) {
- isLoading.postValue(false)
- Timber.e("fetchLatestMessageList error [${e.code}] : ${e.message}")
- return@getMessagesByTimestamp
- }
-
- if (messageList.isNullOrEmpty()) {
- isLoading.postValue(false)
- return@getMessagesByTimestamp
- }
-
- normalMessageList.addAll(messageList.toChatUiModelList(blackUserList))
- _chatUiModelList.postValue(normalMessageList + pendingMessageList)
- val hasNext = messageList.size >= params.nextResultSize
- if (hasNext) {
- fetchLatestMessageList(messageList.last().createdAt)
- }
- }
- }
-
- private fun addSendbirdHandler() {
- SendbirdChat.addConnectionHandler(
- CONNECTION_HANDLER_ID,
- object : ConnectionHandler {
- override fun onConnected(userId: String) {
- Timber.e("Sendbird connection connected")
- }
-
- override fun onDisconnected(userId: String) {
- Timber.e("Sendbird connection disconnected")
- }
-
- override fun onReconnectFailed() {
- Timber.e("Sendbird reconnection failed")
- }
-
- override fun onReconnectStarted() {
- Timber.e("Sendbird reconnection started")
- }
-
- override fun onReconnectSucceeded() {
- Timber.e("Sendbird reconnection succeed")
-
- val lastMessageTime = normalMessageList.lastOrNull()?.timeStamp
- lastMessageTime?.let { timeStamp ->
- fetchLatestMessageList(timeStamp)
- }
- }
- })
-
- SendbirdChat.addChannelHandler(
- CHANNEL_HANDLER_ID,
- object : OpenChannelHandler() {
- override fun onMessageReceived(channel: BaseChannel, message: BaseMessage) {
- Timber.e("onMessageReceived")
- when (message) {
- is UserMessage -> normalMessageList.add(message.toReceivedMessageUiModel())
- is AdminMessage -> normalMessageList.add(message.toAdminMessageUiModel())
- }
- _chatUiModelList.postValue(normalMessageList + pendingMessageList)
- }
- }
- )
- }
-
- fun reportMessage(messageUiModel: ReceivedMessageUiModel) {
- val reporter = SendbirdChat.currentUser?.userId ?: ""
- val feedbackContent =
- "🤬 $reporter 가 ${messageUiModel.userId} 를 신고했습니다 - 메세지 내용 : ${messageUiModel.message}"
-
- // send to Kuring server
- disposable.add(
- feedbackClient.sendFeedback(
- token = pref.fcmToken ?: "",
- feedbackRequest = FeedbackRequest(content = feedbackContent),
- )
- .subscribeOn(Schedulers.io())
- .subscribe({
- if (it.isSuccess) {
- _toastEvent.postValue(R.string.report_success)
- } else {
- _toastEvent.postValue(R.string.report_fail)
- }
- }, {
- _toastEvent.postValue(R.string.report_error)
- })
- )
-
- // send to sendbird server
- reportToSendbirdServer(messageUiModel)
- }
-
- private fun reportToSendbirdServer(messageUiModel: ReceivedMessageUiModel) {
- val params = MessageListParams().apply {
- isInclusive = true
- previousResultSize = 0
- nextResultSize = 0
- }
- kuringChannel?.getMessagesByMessageId(messageUiModel.messageId, params) { messages, e1 ->
- if (e1 != null) {
- Timber.e("getMessagesByMessageId error [${e1.code}] ${e1.message}")
- return@getMessagesByMessageId
- }
- if (messages?.size == 1) {
- kuringChannel?.reportMessage(
- message = messages[0],
- reportCategory = BaseChannel.ReportCategory.INAPPROPRIATE,
- reportDescription = "",
- ) { e2 ->
- if (e2 != null) {
- Timber.e("reportToSendbirdServer error [${e2.code}] : ${e2.message}")
- return@reportMessage
- }
- Timber.e("reportToSendbirdServer success")
- }
- }
- }
- }
-
- fun blockUser(messageUiModel: ReceivedMessageUiModel) {
- val userId = messageUiModel.userId
- val nickname = messageUiModel.nickname
-
- disposable.add(
- repository.blockUser(userId, nickname)
- .subscribeOn(Schedulers.io())
- .subscribe({
- Timber.e("blockUser success")
- _toastEvent.postValue(R.string.block_success)
- updateBlackUserList()
- }, {
- Timber.e("blockUser error $it")
- _toastEvent.postValue(R.string.block_fail)
- })
- )
- }
-
- override fun onCleared() {
- super.onCleared()
- SendbirdChat.removeConnectionHandler(CONNECTION_HANDLER_ID)
- SendbirdChat.removeChannelHandler(CHANNEL_HANDLER_ID)
-
- if (!disposable.isDisposed) {
- disposable.dispose()
- }
- }
-
- companion object {
- const val CONNECTION_HANDLER_ID = "KURING_CONNECTION_ID"
- const val CHANNEL_HANDLER_ID = "KURING_CHANNEL_ID"
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/ui_model/ChatUiModel.kt b/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/ui_model/ChatUiModel.kt
deleted file mode 100644
index 0a698baa3..000000000
--- a/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/ui_model/ChatUiModel.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.ku_stacks.ku_ring.ui.chat.ui_model
-
-sealed class ChatUiModel(
- open val timeStamp: Long,
- open val messageId: Long
-)
-
-data class ReceivedMessageUiModel(
- override val timeStamp: Long,
- override val messageId: Long,
- val userId: String,
- val nickname: String,
- val message: String
-) : ChatUiModel(timeStamp, messageId)
-
-data class SentMessageUiModel(
- override val timeStamp: Long,
- override val messageId: Long,
- val message: String,
- val requestId: String,
- val isPending: Boolean?
-) : ChatUiModel(timeStamp, messageId)
-
-data class AdminMessageUiModel(
- override val timeStamp: Long,
- override val messageId: Long,
- val message: String
-) : ChatUiModel(timeStamp, messageId)
\ No newline at end of file
diff --git a/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/ui_model/ChatUiModelMapper.kt b/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/ui_model/ChatUiModelMapper.kt
deleted file mode 100644
index a5949aae1..000000000
--- a/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/ui_model/ChatUiModelMapper.kt
+++ /dev/null
@@ -1,61 +0,0 @@
-package com.ku_stacks.ku_ring.ui.chat.ui_model
-
-import com.sendbird.android.SendbirdChat
-import com.sendbird.android.message.AdminMessage
-import com.sendbird.android.message.BaseMessage
-import com.sendbird.android.message.UserMessage
-import timber.log.Timber
-
-fun List.toChatUiModelList(blackUserList: List): List {
- val currentUser = SendbirdChat.currentUser
- val chatUiModelList = mutableListOf()
-
- if (currentUser == null) {
- Timber.e("currentUser is null!")
- }
-
- for (message in this) {
- if (message is AdminMessage) {
- chatUiModelList.add(message.toAdminMessageUiModel())
- } else if (message is UserMessage) {
- if (message.sender?.userId == currentUser?.userId) {
- chatUiModelList.add(message.toSentMessageUiModel(isPending = false))
- } else {
- if (!blackUserList.contains(message.sender?.userId)) {
- chatUiModelList.add(message.toReceivedMessageUiModel())
- }
- }
- } else {
- Timber.e("message type is strange! ${message.messageId}")
- }
- }
- return chatUiModelList
-}
-
-fun UserMessage.toReceivedMessageUiModel(): ReceivedMessageUiModel {
- return ReceivedMessageUiModel(
- userId = this.sender?.userId ?: "",
- nickname = this.sender?.nickname ?: "",
- messageId = this.messageId,
- message = this.message,
- timeStamp = this.createdAt
- )
-}
-
-fun UserMessage.toSentMessageUiModel(isPending: Boolean?): SentMessageUiModel {
- return SentMessageUiModel(
- messageId = this.messageId,
- message = this.message,
- timeStamp = this.createdAt,
- requestId = this.requestId,
- isPending = isPending
- )
-}
-
-fun AdminMessage.toAdminMessageUiModel(): AdminMessageUiModel {
- return AdminMessageUiModel(
- messageId = this.messageId,
- message = this.message,
- timeStamp = this.createdAt
- )
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/viewholder/AdminViewHolder.kt b/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/viewholder/AdminViewHolder.kt
deleted file mode 100644
index c659367c5..000000000
--- a/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/viewholder/AdminViewHolder.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.ku_stacks.ku_ring.ui.chat.viewholder
-
-import com.ku_stacks.ku_ring.adapter.visibleIf
-import com.ku_stacks.ku_ring.databinding.ItemChatAdminBinding
-import com.ku_stacks.ku_ring.ui.chat.ui_model.AdminMessageUiModel
-
-class AdminViewHolder(
- private val binding: ItemChatAdminBinding
-) : SealedChatViewHolder(binding.root) {
-
- fun bind(message: AdminMessageUiModel, showDate: Boolean) {
- binding.adminMessageUiModel = message
- binding.chatDateTv.visibleIf(showDate)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/viewholder/ReceiveViewHolder.kt b/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/viewholder/ReceiveViewHolder.kt
deleted file mode 100644
index 90421e73c..000000000
--- a/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/viewholder/ReceiveViewHolder.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.ku_stacks.ku_ring.ui.chat.viewholder
-
-import android.graphics.Typeface
-import android.text.SpannableStringBuilder
-import android.text.Spanned
-import android.text.style.BackgroundColorSpan
-import android.text.style.StyleSpan
-import com.ku_stacks.ku_ring.R
-import com.ku_stacks.ku_ring.adapter.visibleIf
-import com.ku_stacks.ku_ring.databinding.ItemChatReceiveBinding
-import com.ku_stacks.ku_ring.ui.chat.ui_model.ReceivedMessageUiModel
-import com.sendbird.android.SendbirdChat
-
-class ReceiveViewHolder(
- private val binding: ItemChatReceiveBinding
-) : SealedChatViewHolder(binding.root) {
-
- fun bind(receivedMessageUiModel: ReceivedMessageUiModel, showDate: Boolean) {
- binding.receivedMessageUiModel = receivedMessageUiModel
- binding.chatDateTv.visibleIf(showDate)
-
- binding.chatContentTv.text = spanNickname(
- message = receivedMessageUiModel.message,
- nickname = SendbirdChat.currentUser?.nickname ?: ""
- )
- }
-
- private fun spanNickname(message: String, nickname: String): SpannableStringBuilder {
- val spannableStringBuilder = SpannableStringBuilder(message)
-
- val nicknameIndexList = getNicknameStartPositionList(message, nickname)
- nicknameIndexList.forEach { index ->
- spannableStringBuilder.setSpan(
- StyleSpan(Typeface.BOLD),
- index,
- index + nickname.length,
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
- )
-
- spannableStringBuilder.setSpan(
- BackgroundColorSpan(binding.root.context.getColor(R.color.kus_green_50)),
- index,
- index + nickname.length,
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
- )
- }
-
- return spannableStringBuilder
- }
-
- private fun getNicknameStartPositionList(message: String, nickname: String): List {
- if (nickname.isEmpty()) {
- return emptyList()
- }
-
- val indexList = mutableListOf()
- var index = 0
- while (index <= message.length - nickname.length) {
- var isNickname = true
- nickname.forEachIndexed { i, char ->
- if (message[index + i] != char) {
- isNickname = false
- return@forEachIndexed
- }
- }
- if (isNickname) {
- indexList.add(index)
- index += nickname.length
- } else {
- index++
- }
- }
- return indexList
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/viewholder/SealedChatViewHolder.kt b/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/viewholder/SealedChatViewHolder.kt
deleted file mode 100644
index 61330a670..000000000
--- a/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/viewholder/SealedChatViewHolder.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.ku_stacks.ku_ring.ui.chat.viewholder
-
-import android.view.View
-import androidx.recyclerview.widget.RecyclerView
-
-sealed class SealedChatViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
\ No newline at end of file
diff --git a/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/viewholder/SendViewHolder.kt b/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/viewholder/SendViewHolder.kt
deleted file mode 100644
index bbecf04ad..000000000
--- a/app/src/main/java/com/ku_stacks/ku_ring/ui/chat/viewholder/SendViewHolder.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.ku_stacks.ku_ring.ui.chat.viewholder
-
-import com.ku_stacks.ku_ring.adapter.visibleIf
-import com.ku_stacks.ku_ring.databinding.ItemChatSendBinding
-import com.ku_stacks.ku_ring.ui.chat.ui_model.SentMessageUiModel
-
-class SendViewHolder(
- private val binding: ItemChatSendBinding
-) : SealedChatViewHolder(binding.root) {
-
- fun bind(message: SentMessageUiModel, showDate: Boolean) {
- binding.sentMessageUiModel = message
- binding.chatDateTv.visibleIf(showDate)
-
- message.isPending.let { isPending ->
- binding.chatTimeTv.visibleIf(isPending == false)
- binding.chatSendErrorIv.visibleIf(isPending == null)
- binding.chatPendingProgressbar.visibleIf(isPending == true)
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/ku_stacks/ku_ring/ui/dialogs/ChatActionDialog.kt b/app/src/main/java/com/ku_stacks/ku_ring/ui/dialogs/ChatActionDialog.kt
deleted file mode 100644
index 3b9f11636..000000000
--- a/app/src/main/java/com/ku_stacks/ku_ring/ui/dialogs/ChatActionDialog.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.ku_stacks.ku_ring.ui.dialogs
-
-import android.app.Dialog
-import android.content.Context
-import android.graphics.Color
-import android.graphics.drawable.ColorDrawable
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import com.ku_stacks.ku_ring.databinding.DialogChatActionBinding
-
-class ChatActionDialog(context: Context) : Dialog(context) {
-
- private lateinit var binding: DialogChatActionBinding
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
-
- binding = DialogChatActionBinding.inflate(LayoutInflater.from(context))
- setContentView(binding.root)
- }
-
- fun setOnCopyMessageClickListener(onClickListener: View.OnClickListener) = this.apply {
- binding.actionCopyContentTv.setOnClickListener { v ->
- onClickListener.onClick(v)
- dismiss()
- }
- }
-
- fun setOnCopyNicknameClickListener(onClickListener: View.OnClickListener) = this.apply {
- binding.actionCopyNicknameTv.setOnClickListener { v ->
- onClickListener.onClick(v)
- dismiss()
- }
- }
-
- fun setOnReportClickListener(onClickListener: View.OnClickListener) = this.apply {
- binding.actionReportTv.setOnClickListener { v ->
- onClickListener.onClick(v)
- dismiss()
- }
- }
-
- fun setOnBlockClickListener(onClickListener: View.OnClickListener) = this.apply {
- binding.actionBlockTv.setOnClickListener { v ->
- onClickListener.onClick(v)
- dismiss()
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/ku_stacks/ku_ring/ui/main/campus_onboarding/CampusFragment.kt b/app/src/main/java/com/ku_stacks/ku_ring/ui/main/campus_onboarding/CampusFragment.kt
index 74355152a..e52a9c0bf 100644
--- a/app/src/main/java/com/ku_stacks/ku_ring/ui/main/campus_onboarding/CampusFragment.kt
+++ b/app/src/main/java/com/ku_stacks/ku_ring/ui/main/campus_onboarding/CampusFragment.kt
@@ -1,26 +1,12 @@
package com.ku_stacks.ku_ring.ui.main.campus_onboarding
import android.os.Bundle
-import android.text.Editable
-import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import androidx.activity.result.contract.ActivityResultContracts
-import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
-import androidx.fragment.app.viewModels
-import com.google.android.gms.auth.api.signin.GoogleSignIn
-import com.google.android.gms.auth.api.signin.GoogleSignInOptions
-import com.google.android.gms.common.api.ApiException
-import com.ku_stacks.ku_ring.R
import com.ku_stacks.ku_ring.databinding.FragmentCampusBinding
-import com.ku_stacks.ku_ring.navigator.KuringNavigator
-import com.ku_stacks.ku_ring.util.PreferenceUtil
-import com.ku_stacks.ku_ring.util.makeDialog
import dagger.hilt.android.AndroidEntryPoint
-import timber.log.Timber
-import javax.inject.Inject
@AndroidEntryPoint
class CampusFragment : Fragment() {
@@ -29,34 +15,6 @@ class CampusFragment : Fragment() {
private val binding
get() = _binding!!
- private val viewModel by viewModels()
-
- @Inject
- lateinit var pref: PreferenceUtil
-
- @Inject
- lateinit var navigator: KuringNavigator
-
- private val loginFinishResult = registerForActivityResult(
- ActivityResultContracts.StartActivityForResult()
- ) {
- try {
- val task = GoogleSignIn.getSignedInAccountFromIntent(it.data)
- val account = task.getResult(ApiException::class.java)
- Timber.e("account email: ${account.email}")
- account.email?.let { userId ->
- viewModel.connectToSendbird(userId) {}
- changeState(CampusState.SET_NICKNAME_STATE)
- }
- } catch (e: ApiException) {
- Timber.e("signInResult failed [${e.statusCode}]")
- requireContext().makeDialog(description = "구글 로그인에 실패하였습니다. [${e.statusCode}]")
- } catch (e: Exception) {
- Timber.e("signInResult failed : $e")
- requireContext().makeDialog(description = "구글 로그인에 실패하였습니다. ${e.message}")
- }
- }
-
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@@ -66,132 +24,6 @@ class CampusFragment : Fragment() {
return binding.root
}
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
-
- setupView()
- observeEvent()
- }
-
- private fun setupView() {
- val campusUserId = pref.campusUserId
- if (campusUserId.isNotEmpty()) { // 저장된 ID 있음
- changeState(CampusState.AUTO_LOGIN_STATE)
-
- binding.campusAutoLoginLayout.campusNextBt.setOnClickListener {
- viewModel.connectToSendbird(campusUserId) { nickname ->
- if (nickname != null) { // 닉네임도 있다면
- startChatActivity()
- } else { // 닉네임 설정해야한다면
- changeState(CampusState.SET_NICKNAME_STATE)
- }
- }
- }
- } else { // 저장된 ID 없음. 처음인 경우
- changeState(CampusState.LOGIN_STATE)
- binding.campusLoginLayout.campusGoogleLoginBt.setOnClickListener {
- signInGoogle()
- }
- }
- }
-
- private fun observeEvent() {
- viewModel.dialogEvent.observe(viewLifecycleOwner) {
- requireContext().makeDialog(description = getString(it))
- }
-
- viewModel.finishEvent.observe(viewLifecycleOwner) {
- startChatActivity()
- }
- }
-
- private fun changeState(toNewState: CampusState) {
- Timber.e("changeState to $toNewState")
- when (toNewState) {
- CampusState.LOGIN_STATE -> {
- binding.campusLoginLayout.root.visibility = View.VISIBLE
- binding.campusSetNicknameLayout.root.visibility = View.GONE
- binding.campusAutoLoginLayout.root.visibility = View.GONE
- }
-
- CampusState.SET_NICKNAME_STATE -> {
- binding.campusLoginLayout.root.visibility = View.GONE
- binding.campusSetNicknameLayout.root.visibility = View.VISIBLE
- binding.campusAutoLoginLayout.root.visibility = View.GONE
-
- binding.campusSetNicknameLayout.nicknameEt.addTextChangedListener(object :
- TextWatcher {
- override fun beforeTextChanged(
- s: CharSequence?,
- start: Int,
- count: Int,
- after: Int
- ) = Unit
-
- override fun onTextChanged(
- s: CharSequence?,
- start: Int,
- before: Int,
- count: Int
- ) = Unit
-
- override fun afterTextChanged(s: Editable?) {
- val isValidFormat = viewModel.isValidNicknameFormat(s.toString())
- val formatText = if (isValidFormat) {
- R.string.nickname_valid_format
- } else {
- R.string.nickname_not_valid_format
- }
- val formatTextColor = if (isValidFormat) {
- R.color.kus_gray
- } else {
- R.color.kus_pink
- }
-
- binding.campusSetNicknameLayout.nicknameFormatDescTv.apply {
- text = getString(formatText)
- setTextColor(ContextCompat.getColor(requireContext(), formatTextColor))
- }
- }
- })
-
- binding.campusSetNicknameLayout.campusNextBt.setOnClickListener {
- val nickname = binding.campusSetNicknameLayout.nicknameEt.text.toString()
- viewModel.login(nickname)
- }
- }
-
- CampusState.AUTO_LOGIN_STATE -> {
- binding.campusLoginLayout.root.visibility = View.GONE
- binding.campusSetNicknameLayout.root.visibility = View.GONE
- binding.campusAutoLoginLayout.root.visibility = View.VISIBLE
- }
- }
- }
-
- private fun signInGoogle() {
- val googleSignInOptions = GoogleSignInOptions
- .Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
- .requestEmail()
- .build()
-
- val googleSignInClient =
- GoogleSignIn.getClient(requireContext().applicationContext, googleSignInOptions)
-
- val intent = googleSignInClient.signInIntent
- loginFinishResult.launch(intent)
- }
-
- private fun startChatActivity() {
- changeState(CampusState.AUTO_LOGIN_STATE)
-
- navigator.navigateToChat(requireActivity())
- requireActivity().overridePendingTransition(
- R.anim.anim_slide_right_enter,
- R.anim.anim_stay_exit
- )
- }
-
override fun onDestroyView() {
super.onDestroyView()
_binding = null
diff --git a/app/src/main/java/com/ku_stacks/ku_ring/ui/main/campus_onboarding/CampusState.kt b/app/src/main/java/com/ku_stacks/ku_ring/ui/main/campus_onboarding/CampusState.kt
deleted file mode 100644
index 6d72dca34..000000000
--- a/app/src/main/java/com/ku_stacks/ku_ring/ui/main/campus_onboarding/CampusState.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.ku_stacks.ku_ring.ui.main.campus_onboarding
-
-enum class CampusState {
- LOGIN_STATE,
- SET_NICKNAME_STATE,
- AUTO_LOGIN_STATE
-}
diff --git a/app/src/main/java/com/ku_stacks/ku_ring/ui/main/campus_onboarding/CampusViewModel.kt b/app/src/main/java/com/ku_stacks/ku_ring/ui/main/campus_onboarding/CampusViewModel.kt
deleted file mode 100644
index a1336ab4b..000000000
--- a/app/src/main/java/com/ku_stacks/ku_ring/ui/main/campus_onboarding/CampusViewModel.kt
+++ /dev/null
@@ -1,108 +0,0 @@
-package com.ku_stacks.ku_ring.ui.main.campus_onboarding
-
-import androidx.lifecycle.LiveData
-import androidx.lifecycle.ViewModel
-import com.ku_stacks.ku_ring.R
-import com.ku_stacks.ku_ring.repository.SendbirdRepository
-import com.ku_stacks.ku_ring.ui.SingleLiveEvent
-import com.ku_stacks.ku_ring.util.PreferenceUtil
-import com.sendbird.android.SendbirdChat
-import com.sendbird.android.params.UserUpdateParams
-import dagger.hilt.android.lifecycle.HiltViewModel
-import io.reactivex.rxjava3.disposables.CompositeDisposable
-import timber.log.Timber
-import java.util.regex.Pattern
-import javax.inject.Inject
-
-@HiltViewModel
-class CampusViewModel @Inject constructor(
- private val pref: PreferenceUtil,
- private val repository: SendbirdRepository
-) : ViewModel() {
-
- private val disposable = CompositeDisposable()
-
- private val _dialogEvent = SingleLiveEvent()
- val dialogEvent: LiveData
- get() = _dialogEvent
-
- private val _finishEvent = SingleLiveEvent()
- val finishEvent: LiveData
- get() = _finishEvent
-
- init {
- Timber.e("CampusViewModel init")
- }
-
- fun connectToSendbird(userId: String, nickname: (String?) -> Unit) {
- SendbirdChat.connect(userId) { user, e ->
- if (e != null) {
- Timber.e("Sendbird connect error [${e.code}] : ${e.message}")
- _dialogEvent.postValue(R.string.chat_connect_error)
- return@connect
- }
- Timber.e("Sendbird connect success. nickname : ${user?.nickname}")
-
- pref.campusUserId = userId
- nickname(user?.nickname)
- }
- }
-
- /*
- (?=.{5,15}$) // 5-15 characters long
- (?![_.]) // no _ or . at the beginning
- (?!.*[_.]{2}) // no __ or _. or ._ or .. inside
- [a-zA-Z0-9가-힣._] // allowed characters
- (? Unit) {
- if (!isValidNicknameFormat(nickname)) {
- Timber.e("nickname: $nickname")
- _dialogEvent.postValue(R.string.nickname_not_valid_format)
- return
- }
-
- val userId = pref.campusUserId
-
- disposable.add(
- repository.hasDuplicateNickname(nickname, userId)
- .subscribe({
- if (!it) {
- isAuthorized()
- } else {
- _dialogEvent.postValue(R.string.nickname_duplicated)
- }
- }, {
- Timber.e("authorizeNickname error : $it")
- _dialogEvent.postValue(R.string.nickname_check_error)
- })
- )
- }
-
- private fun setNickname(nickname: String, isDone: () -> Unit) {
- val params = UserUpdateParams()
- .setNickname(nickname)
-
- SendbirdChat.updateCurrentUserInfo(params) { e ->
- if (e != null) {
- Timber.e("updateCurrentUserInfo error [${e.code} : ${e.message}]")
- return@updateCurrentUserInfo
- }
- Timber.e("updateCurrentUserInfo success")
- isDone()
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_chat.xml b/app/src/main/res/layout/activity_chat.xml
deleted file mode 100644
index a9480fa28..000000000
--- a/app/src/main/res/layout/activity_chat.xml
+++ /dev/null
@@ -1,123 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/campus_auto_login.xml b/app/src/main/res/layout/campus_auto_login.xml
deleted file mode 100644
index 4847be5d4..000000000
--- a/app/src/main/res/layout/campus_auto_login.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/campus_login.xml b/app/src/main/res/layout/campus_main.xml
similarity index 70%
rename from app/src/main/res/layout/campus_login.xml
rename to app/src/main/res/layout/campus_main.xml
index 08241c095..295031af7 100644
--- a/app/src/main/res/layout/campus_login.xml
+++ b/app/src/main/res/layout/campus_main.xml
@@ -12,7 +12,7 @@
android:layout_marginEnd="60dp"
android:layout_marginBottom="60dp"
android:src="@drawable/ic_campus_man"
- app:layout_constraintBottom_toTopOf="@+id/campus_google_login_bt"
+ app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent" />
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/campus_set_nickname.xml b/app/src/main/res/layout/campus_set_nickname.xml
deleted file mode 100644
index 106fa60d8..000000000
--- a/app/src/main/res/layout/campus_set_nickname.xml
+++ /dev/null
@@ -1,78 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_chat_action.xml b/app/src/main/res/layout/dialog_chat_action.xml
deleted file mode 100644
index 0fdb99fb5..000000000
--- a/app/src/main/res/layout/dialog_chat_action.xml
+++ /dev/null
@@ -1,75 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_campus.xml b/app/src/main/res/layout/fragment_campus.xml
index d32f384e3..9ee795a45 100644
--- a/app/src/main/res/layout/fragment_campus.xml
+++ b/app/src/main/res/layout/fragment_campus.xml
@@ -20,26 +20,8 @@
app:layout_constraintTop_toTopOf="parent" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_chat_receive.xml b/app/src/main/res/layout/item_chat_receive.xml
deleted file mode 100644
index 966aeba18..000000000
--- a/app/src/main/res/layout/item_chat_receive.xml
+++ /dev/null
@@ -1,95 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_chat_send.xml b/app/src/main/res/layout/item_chat_send.xml
deleted file mode 100644
index 61e107a66..000000000
--- a/app/src/main/res/layout/item_chat_send.xml
+++ /dev/null
@@ -1,100 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index dbd9c60d1..5f645a3ea 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -129,6 +129,7 @@
쿠링 캠퍼스
쿠링청심대
+ 더 멋진 쿠링을 위해 잠시만 기다려 주세요!
쿠링 청심대에서 다같이 모여 메세지를 보내세요
상대에게 보여지는 이름을 설정해주세요
적절한 닉네임 형식이 아닙니다.
diff --git a/app/src/test/java/com/ku_stacks/ku_ring/repository/SendbirdRepositoryTest.kt b/app/src/test/java/com/ku_stacks/ku_ring/repository/SendbirdRepositoryTest.kt
deleted file mode 100644
index 21f5544ce..000000000
--- a/app/src/test/java/com/ku_stacks/ku_ring/repository/SendbirdRepositoryTest.kt
+++ /dev/null
@@ -1,77 +0,0 @@
-package com.ku_stacks.ku_ring.repository
-
-import androidx.arch.core.executor.testing.InstantTaskExecutorRule
-import com.ku_stacks.ku_ring.MockUtil
-import com.ku_stacks.ku_ring.data.api.SendbirdClient
-import com.ku_stacks.ku_ring.data.api.response.UserListResponse
-import io.reactivex.rxjava3.core.Single
-import io.reactivex.rxjava3.plugins.RxJavaPlugins
-import io.reactivex.rxjava3.schedulers.Schedulers
-import org.junit.After
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.mockito.Mockito
-
-class SendbirdRepositoryTest {
-
- private val sendbirdClient: SendbirdClient = Mockito.mock(SendbirdClient::class.java)
- private lateinit var sendbirdRepository: SendbirdRepository
-
- @get:Rule
- val instantTaskExecutorRule = InstantTaskExecutorRule()
-
- @Before
- fun setup() {
- RxJavaPlugins.setIoSchedulerHandler {
- Schedulers.trampoline()
- }
- sendbirdRepository = SendbirdRepositoryImpl(sendbirdClient)
- }
-
- @After
- fun tearDown() {
- RxJavaPlugins.reset()
- }
-
- @Test
- fun `given no user then false`() {
- val nickname = "kuring"
- val mockResponse = UserListResponse(emptyList())
- Mockito.`when`(sendbirdClient.fetchNicknameList(nickname))
- .thenReturn(Single.just(mockResponse))
-
- val userId = "someUserId"
- sendbirdRepository.hasDuplicateNickname(nickname, userId)
- .test()
- .assertComplete()
- .assertValue(false)
- }
-
- @Test
- fun `given no duplicates then false`() {
- val mockResponse = MockUtil.mockUserResponse()
- val (nickname, userId) = mockResponse
- Mockito.`when`(sendbirdClient.fetchNicknameList(nickname))
- .thenReturn(Single.just(UserListResponse(listOf(mockResponse))))
-
- sendbirdRepository.hasDuplicateNickname(nickname, userId)
- .test()
- .assertComplete()
- .assertValue(false)
- }
-
- @Test
- fun `given a duplicate then true`() {
- val mockResponse = MockUtil.mockUserListResponse()
- val (nickname, userId) = mockResponse.users[0]
- Mockito.`when`(sendbirdClient.fetchNicknameList(nickname))
- .thenReturn(Single.just(mockResponse))
-
- sendbirdRepository.hasDuplicateNickname(nickname, userId)
- .test()
- .assertComplete()
- .assertValue(true)
- }
-
-}
\ No newline at end of file
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index bb51036dc..549e711f6 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -145,7 +145,6 @@ androidtagview = 'com.github.yeon-kyu:AndroidTagView:v1.1.7-alpha1'
keyboardvisibilityevent = 'net.yslibrary.keyboardvisibilityevent:keyboardvisibilityevent:3.0.0-RC3'
leakcanary-android = 'com.squareup.leakcanary:leakcanary-android:2.8.1'
pageindicatorview = 'com.romandanylyk:pageindicatorview:1.0.3'
-sendbird-chat = 'com.sendbird.sdk:sendbird-chat:4.0.0-beta.2'
shimmer = 'com.facebook.shimmer:shimmer:0.5.0'
timber = 'com.jakewharton.timber:timber:4.7.1'
holdableswipehandler = 'com.github.yeon-kyu.HoldableSwipeHandler:HoldableSwipeHandler:1.2.2'