diff --git a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/AudioContentMainFragment.kt b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/AudioContentMainFragment.kt index 277287d..171e6b7 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/AudioContentMainFragment.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/audio_content/main/AudioContentMainFragment.kt @@ -48,6 +48,7 @@ import kr.co.vividnext.sodalive.explorer.ExplorerSectionAdapter import kr.co.vividnext.sodalive.explorer.profile.UserProfileActivity import kr.co.vividnext.sodalive.explorer.profile.series.UserProfileSeriesListAdapter import kr.co.vividnext.sodalive.extensions.dpToPx +import kr.co.vividnext.sodalive.main.MainActivity import kr.co.vividnext.sodalive.mypage.alarm.AlarmListActivity import kr.co.vividnext.sodalive.settings.event.EventDetailActivity import kr.co.vividnext.sodalive.settings.notification.MemberRole @@ -149,6 +150,10 @@ class AudioContentMainFragment : BaseFragment( ) ) } + + binding.flSearchChannel.setOnClickListener { + (requireActivity() as MainActivity).showSearchBar() + } } private fun setupCreatorRank() { diff --git a/app/src/main/java/kr/co/vividnext/sodalive/main/MainActivity.kt b/app/src/main/java/kr/co/vividnext/sodalive/main/MainActivity.kt index 989d1e8..6f877ad 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/main/MainActivity.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/main/MainActivity.kt @@ -1,6 +1,7 @@ package kr.co.vividnext.sodalive.main import android.Manifest +import android.app.Service import android.content.BroadcastReceiver import android.content.ComponentName import android.content.Context @@ -8,11 +9,14 @@ import android.content.Intent import android.content.IntentFilter import android.content.SharedPreferences import android.content.res.ColorStateList +import android.graphics.Rect import android.os.Build import android.os.Bundle import android.os.Handler import android.os.Looper import android.view.View +import android.view.inputmethod.InputMethodManager +import androidx.activity.addCallback import androidx.core.content.ContextCompat import androidx.core.content.res.ResourcesCompat import androidx.media3.common.MediaItem @@ -21,12 +25,17 @@ import androidx.media3.common.Player import androidx.media3.common.util.UnstableApi import androidx.media3.session.MediaController import androidx.media3.session.SessionToken +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView import coil.load import coil.transform.RoundedCornersTransformation import com.google.firebase.messaging.FirebaseMessaging import com.gun0912.tedpermission.PermissionListener import com.gun0912.tedpermission.normal.TedPermission +import com.jakewharton.rxbinding4.widget.textChanges import com.orhanobut.logger.Logger +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers +import io.reactivex.rxjava3.schedulers.Schedulers import kr.co.vividnext.sodalive.R import kr.co.vividnext.sodalive.audio_content.AudioContentPlayService import kr.co.vividnext.sodalive.audio_content.detail.AudioContentDetailActivity @@ -40,19 +49,26 @@ import kr.co.vividnext.sodalive.common.LoadingDialog import kr.co.vividnext.sodalive.common.SharedPreferenceManager import kr.co.vividnext.sodalive.databinding.ActivityMainBinding import kr.co.vividnext.sodalive.databinding.ItemMainTabBinding +import kr.co.vividnext.sodalive.explorer.ExplorerViewModel import kr.co.vividnext.sodalive.explorer.profile.UserProfileActivity import kr.co.vividnext.sodalive.extensions.dpToPx import kr.co.vividnext.sodalive.live.LiveFragment import kr.co.vividnext.sodalive.message.MessageFragment +import kr.co.vividnext.sodalive.message.SelectMessageRecipientAdapter import kr.co.vividnext.sodalive.mypage.MyPageFragment import kr.co.vividnext.sodalive.settings.event.EventDetailActivity import kr.co.vividnext.sodalive.settings.notification.NotificationSettingsDialog import org.koin.android.ext.android.inject +import java.util.concurrent.TimeUnit @UnstableApi class MainActivity : BaseActivity(ActivityMainBinding::inflate) { private val viewModel: MainViewModel by inject() + private val explorerViewModel: ExplorerViewModel by inject() + + private lateinit var searchChannelAdapter: SelectMessageRecipientAdapter + private lateinit var imm: InputMethodManager private lateinit var liveFragment: LiveFragment private lateinit var loadingDialog: LoadingDialog @@ -61,6 +77,7 @@ class MainActivity : BaseActivity(ActivityMainBinding::infl private var mediaController: MediaController? = null private val handler = Handler(Looper.getMainLooper()) private val audioContentReceiver = AudioContentReceiver() + private var isShowSearchBar = false private val preferenceChangeListener = SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key -> @@ -174,6 +191,10 @@ class MainActivity : BaseActivity(ActivityMainBinding::infl override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + imm = getSystemService( + Service.INPUT_METHOD_SERVICE + ) as InputMethodManager + checkPermissions() pushTokenUpdate() gaidUpdate() @@ -189,6 +210,15 @@ class MainActivity : BaseActivity(ActivityMainBinding::infl } handler.postDelayed({ executeDeeplink(intent) }, 500) + + onBackPressedDispatcher.addCallback { + if (isShowSearchBar) { + hideSearchBar() + } else { + isEnabled = false + onBackPressedDispatcher.onBackPressed() + } + } } override fun onDestroy() { @@ -239,6 +269,7 @@ class MainActivity : BaseActivity(ActivityMainBinding::infl } setupBottomTabLayout() + setupSearchChannelView() } private fun executeDeeplink(intent: Intent) { @@ -497,6 +528,96 @@ class MainActivity : BaseActivity(ActivityMainBinding::infl } } + private fun setupSearchChannelView() { + searchChannelAdapter = SelectMessageRecipientAdapter { + hideKeyboard() + val intent = Intent(applicationContext, UserProfileActivity::class.java) + intent.putExtra(Constants.EXTRA_USER_ID, it.id) + startActivity(intent) + } + + binding.rvSearchChannel.layoutManager = LinearLayoutManager( + this, + LinearLayoutManager.VERTICAL, + false + ) + + binding.rvSearchChannel.addItemDecoration(object : RecyclerView.ItemDecoration() { + override fun getItemOffsets( + outRect: Rect, + view: View, + parent: RecyclerView, + state: RecyclerView.State + ) { + super.getItemOffsets(outRect, view, parent, state) + + outRect.left = 13.3f.dpToPx().toInt() + outRect.right = 13.3f.dpToPx().toInt() + outRect.top = 13.3f.dpToPx().toInt() + outRect.bottom = 13.3f.dpToPx().toInt() + } + }) + + binding.rvSearchChannel.adapter = searchChannelAdapter + + compositeDisposable.add( + binding.etSearchChannel.textChanges().skip(1) + .debounce(500, TimeUnit.MILLISECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .subscribeOn(Schedulers.io()) + .subscribe { + if (it.length >= 2) { + explorerViewModel.searchChannel(it.toString()) + binding.rvSearchChannel.visibility = View.VISIBLE + binding.tvResultX.visibility = View.GONE + } else { + binding.rvSearchChannel.visibility = View.GONE + binding.tvResultX.visibility = View.VISIBLE + } + } + ) + + explorerViewModel.searchChannelLiveData.observe(this) { + searchChannelAdapter.items.clear() + if (it.isNotEmpty()) { + searchChannelAdapter.items.addAll(it) + binding.rvSearchChannel.visibility = View.VISIBLE + binding.tvResultX.visibility = View.GONE + } else { + binding.rvSearchChannel.visibility = View.GONE + binding.tvResultX.visibility = View.VISIBLE + } + searchChannelAdapter.notifyDataSetChanged() + } + } + + private fun hideKeyboard() { + handler.postDelayed({ + imm.hideSoftInputFromWindow( + window.decorView.applicationWindowToken, + InputMethodManager.HIDE_NOT_ALWAYS + ) + }, 100) + } + + private fun hideSearchBar() { + isShowSearchBar = false + binding.nsSearch.visibility = View.GONE + binding.etSearchChannel.setText("") + } + + fun showSearchBar() { + isShowSearchBar = true + binding.nsSearch.visibility = View.VISIBLE + binding.etSearchChannel.setText("") + + binding.etSearchChannel.requestFocus() + binding.etSearchChannel.post { + val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager + imm.showSoftInput(binding.etSearchChannel, InputMethodManager.SHOW_IMPLICIT) + } + } + inner class AudioContentReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { val contentId = intent?.getLongExtra(Constants.EXTRA_AUDIO_CONTENT_ID, 0) diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index b2ae649..d4ecf87 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -197,4 +197,71 @@ android:layout_height="wrap_content" android:layout_weight="1" /> + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_audio_content_main.xml b/app/src/main/res/layout/fragment_audio_content_main.xml index 91ba792..1638daf 100644 --- a/app/src/main/res/layout/fragment_audio_content_main.xml +++ b/app/src/main/res/layout/fragment_audio_content_main.xml @@ -64,6 +64,38 @@ android:layout_marginTop="6.7dp" android:layout_marginBottom="26.7dp" /> + + + + + + +