feat(main-v2): 메인 하단 내비게이션을 추가한다
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
package kr.co.vividnext.sodalive.v2.main
|
||||
|
||||
import kr.co.vividnext.sodalive.base.BaseFragment
|
||||
import kr.co.vividnext.sodalive.databinding.FragmentV2MainChatBinding
|
||||
|
||||
class ChatMainFragment : BaseFragment<FragmentV2MainChatBinding>(
|
||||
FragmentV2MainChatBinding::inflate
|
||||
)
|
||||
@@ -0,0 +1,8 @@
|
||||
package kr.co.vividnext.sodalive.v2.main
|
||||
|
||||
import kr.co.vividnext.sodalive.base.BaseFragment
|
||||
import kr.co.vividnext.sodalive.databinding.FragmentV2MainContentBinding
|
||||
|
||||
class ContentMainFragment : BaseFragment<FragmentV2MainContentBinding>(
|
||||
FragmentV2MainContentBinding::inflate
|
||||
)
|
||||
@@ -0,0 +1,8 @@
|
||||
package kr.co.vividnext.sodalive.v2.main
|
||||
|
||||
import kr.co.vividnext.sodalive.base.BaseFragment
|
||||
import kr.co.vividnext.sodalive.databinding.FragmentV2MainHomeBinding
|
||||
|
||||
class HomeMainFragment : BaseFragment<FragmentV2MainHomeBinding>(
|
||||
FragmentV2MainHomeBinding::inflate
|
||||
)
|
||||
@@ -0,0 +1,654 @@
|
||||
package kr.co.vividnext.sodalive.v2.main
|
||||
|
||||
import android.Manifest
|
||||
import android.content.ComponentName
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.View
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.net.toUri
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.media3.common.MediaItem
|
||||
import androidx.media3.common.MediaMetadata
|
||||
import androidx.media3.common.Player
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.session.MediaController
|
||||
import androidx.media3.session.SessionToken
|
||||
import coil.load
|
||||
import coil.transform.RoundedCornersTransformation
|
||||
import com.google.common.util.concurrent.ListenableFuture
|
||||
import com.google.firebase.messaging.FirebaseMessaging
|
||||
import com.gun0912.tedpermission.PermissionListener
|
||||
import com.gun0912.tedpermission.normal.TedPermission
|
||||
import com.orhanobut.logger.Logger
|
||||
import kr.co.vividnext.sodalive.R
|
||||
import kr.co.vividnext.sodalive.audio_content.AudioContentPlayService
|
||||
import kr.co.vividnext.sodalive.audio_content.detail.AudioContentDetailActivity
|
||||
import kr.co.vividnext.sodalive.audio_content.player.AudioContentPlayerFragment
|
||||
import kr.co.vividnext.sodalive.audio_content.player.AudioContentPlayerService
|
||||
import kr.co.vividnext.sodalive.audio_content.series.detail.SeriesDetailActivity
|
||||
import kr.co.vividnext.sodalive.audition.AuditionActivity
|
||||
import kr.co.vividnext.sodalive.base.BaseActivity
|
||||
import kr.co.vividnext.sodalive.common.Constants
|
||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||
import kr.co.vividnext.sodalive.databinding.ActivityMainV2Binding
|
||||
import kr.co.vividnext.sodalive.explorer.profile.UserProfileActivity
|
||||
import kr.co.vividnext.sodalive.explorer.profile.creator_community.all.CreatorCommunityAllActivity
|
||||
import kr.co.vividnext.sodalive.main.EventPopupDialogFragment
|
||||
import kr.co.vividnext.sodalive.message.MessageActivity
|
||||
import kr.co.vividnext.sodalive.mypage.MyPageFragment
|
||||
import kr.co.vividnext.sodalive.settings.event.EventDetailActivity
|
||||
import kr.co.vividnext.sodalive.settings.notification.NotificationSettingsDialog
|
||||
import kr.co.vividnext.sodalive.user.login.LoginActivity
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.android.ext.android.inject
|
||||
import java.util.Locale
|
||||
import kotlin.math.max
|
||||
|
||||
@UnstableApi
|
||||
class MainV2Activity : BaseActivity<ActivityMainV2Binding>(ActivityMainV2Binding::inflate) {
|
||||
|
||||
private val viewModel: MainV2ViewModel by inject()
|
||||
|
||||
private lateinit var notificationSettingsDialog: NotificationSettingsDialog
|
||||
private var mediaController: MediaController? = null
|
||||
private var mediaControllerFuture: ListenableFuture<MediaController>? = null
|
||||
private val handler = Handler(Looper.getMainLooper())
|
||||
private val showMiniPlayerRunnable = Runnable { initAndVisibleMiniPlayer() }
|
||||
private var playerStateJob: Job? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
overrideRootWindowInsets()
|
||||
|
||||
checkPermissions()
|
||||
trackAppLaunchIfNeeded()
|
||||
pushTokenUpdate()
|
||||
|
||||
if (isLoggedIn()) {
|
||||
updatePidAndGaid()
|
||||
getEventPopup()
|
||||
observePlayerState()
|
||||
handler.postDelayed({ executeDeeplink(intent) }, 1000)
|
||||
}
|
||||
}
|
||||
|
||||
private fun overrideRootWindowInsets() {
|
||||
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, insets ->
|
||||
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
val ime = insets.getInsets(WindowInsetsCompat.Type.ime())
|
||||
|
||||
val left = max(systemBars.left, ime.left)
|
||||
val top = systemBars.top
|
||||
val right = max(systemBars.right, ime.right)
|
||||
v.setPadding(left, top, right, 0)
|
||||
|
||||
insets
|
||||
}
|
||||
ViewCompat.requestApplyInsets(binding.root)
|
||||
}
|
||||
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
super.onNewIntent(intent)
|
||||
setIntent(intent)
|
||||
|
||||
if (isLoggedIn()) {
|
||||
executeDeeplink(intent)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
getMemberInfo()
|
||||
startService(
|
||||
Intent(this, AudioContentPlayService::class.java).apply {
|
||||
action = AudioContentPlayService.MusicAction.INIT.name
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
deInitMiniPlayer()
|
||||
playerStateJob?.cancel()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun setupView() {
|
||||
notificationSettingsDialog = NotificationSettingsDialog(
|
||||
this,
|
||||
layoutInflater
|
||||
) { isNotifiedLive, isNotifiedUploadContent, isNotifiedMessage ->
|
||||
viewModel.updateNotificationSettings(
|
||||
isNotifiedLive,
|
||||
isNotifiedUploadContent,
|
||||
isNotifiedMessage
|
||||
)
|
||||
}
|
||||
|
||||
setupBottomNavigation()
|
||||
}
|
||||
|
||||
fun showLoginActivity() {
|
||||
if (SharedPreferenceManager.token.isBlank()) {
|
||||
val extras = intent.extras
|
||||
startActivity(
|
||||
Intent(applicationContext, LoginActivity::class.java).apply {
|
||||
putExtra(Constants.EXTRA_DATA, extras)
|
||||
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun openChatTab() {
|
||||
viewModel.clickTab(MainV2Tab.CHAT)
|
||||
}
|
||||
|
||||
private fun setupBottomNavigation() {
|
||||
binding.bottomNavigation.setOnItemSelectedListener { item ->
|
||||
when (item.itemId) {
|
||||
R.id.menu_main_v2_home -> viewModel.clickTab(MainV2Tab.HOME)
|
||||
R.id.menu_main_v2_content -> viewModel.clickTab(MainV2Tab.CONTENT)
|
||||
R.id.menu_main_v2_chat -> viewModel.clickTab(MainV2Tab.CHAT)
|
||||
R.id.menu_main_v2_my -> viewModel.clickTab(MainV2Tab.MY)
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
binding.bottomNavigation.apply {
|
||||
itemIconTintList = null
|
||||
}
|
||||
|
||||
viewModel.currentTab.observe(this) { tab ->
|
||||
val itemId = when (tab) {
|
||||
MainV2Tab.HOME -> R.id.menu_main_v2_home
|
||||
MainV2Tab.CONTENT -> R.id.menu_main_v2_content
|
||||
MainV2Tab.CHAT -> R.id.menu_main_v2_chat
|
||||
MainV2Tab.MY -> R.id.menu_main_v2_my
|
||||
}
|
||||
|
||||
if (binding.bottomNavigation.selectedItemId != itemId) {
|
||||
binding.bottomNavigation.selectedItemId = itemId
|
||||
}
|
||||
|
||||
changeFragment(tab)
|
||||
}
|
||||
}
|
||||
|
||||
private fun changeFragment(currentTab: MainV2Tab) {
|
||||
val tag = currentTab.toString()
|
||||
val fragmentManager = supportFragmentManager
|
||||
val fragmentTransaction = fragmentManager.beginTransaction()
|
||||
|
||||
fragmentManager.primaryNavigationFragment?.let {
|
||||
fragmentTransaction.hide(it)
|
||||
}
|
||||
|
||||
var fragment = fragmentManager.findFragmentByTag(tag)
|
||||
if (fragment == null) {
|
||||
fragment = when (currentTab) {
|
||||
MainV2Tab.HOME -> HomeMainFragment()
|
||||
MainV2Tab.CONTENT -> ContentMainFragment()
|
||||
MainV2Tab.CHAT -> ChatMainFragment()
|
||||
MainV2Tab.MY -> MyPageFragment()
|
||||
}
|
||||
fragmentTransaction.add(R.id.fl_container, fragment, tag)
|
||||
} else {
|
||||
fragmentTransaction.show(fragment)
|
||||
}
|
||||
|
||||
fragmentTransaction.setPrimaryNavigationFragment(fragment)
|
||||
fragmentTransaction.setReorderingAllowed(true)
|
||||
fragmentTransaction.commitNow()
|
||||
}
|
||||
|
||||
private fun observePlayerState() {
|
||||
playerStateJob = lifecycleScope.launch {
|
||||
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
SharedPreferenceManager.isPlayerServiceRunningFlow.collect { isRunning ->
|
||||
if (isRunning) {
|
||||
handler.removeCallbacks(showMiniPlayerRunnable)
|
||||
handler.postDelayed(showMiniPlayerRunnable, 1500)
|
||||
} else {
|
||||
deInitMiniPlayer()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun initAndVisibleMiniPlayer() {
|
||||
binding.clMiniPlayer.visibility = View.VISIBLE
|
||||
binding.clMiniPlayer.setOnClickListener { showPlayerFragment() }
|
||||
binding.ivPlayerStop.setOnClickListener {
|
||||
startService(
|
||||
Intent(applicationContext, AudioContentPlayerService::class.java).apply {
|
||||
action = "STOP_SERVICE"
|
||||
}
|
||||
)
|
||||
}
|
||||
connectPlayerService()
|
||||
}
|
||||
|
||||
private fun connectPlayerService() {
|
||||
if (mediaController != null || mediaControllerFuture != null) {
|
||||
return
|
||||
}
|
||||
|
||||
val componentName = ComponentName(applicationContext, AudioContentPlayerService::class.java)
|
||||
val sessionToken = SessionToken(applicationContext, componentName)
|
||||
val controllerFuture =
|
||||
MediaController.Builder(applicationContext, sessionToken).buildAsync()
|
||||
mediaControllerFuture = controllerFuture
|
||||
controllerFuture.addListener(
|
||||
{
|
||||
try {
|
||||
if (mediaController != null) {
|
||||
controllerFuture.get().release()
|
||||
return@addListener
|
||||
}
|
||||
|
||||
mediaController = controllerFuture.get()
|
||||
setupMediaController()
|
||||
updateMediaMetadata(mediaController?.mediaMetadata)
|
||||
|
||||
binding.ivPlayerPlayOrPause.setImageResource(
|
||||
if (mediaController?.isPlaying == true) {
|
||||
R.drawable.ic_player_pause
|
||||
} else {
|
||||
R.drawable.ic_player_play
|
||||
}
|
||||
)
|
||||
|
||||
binding.ivPlayerPlayOrPause.setOnClickListener {
|
||||
mediaController?.let {
|
||||
if (it.playWhenReady) {
|
||||
it.pause()
|
||||
} else {
|
||||
it.play()
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (throwable: Throwable) {
|
||||
Logger.e(throwable, "Failed to connect player service")
|
||||
} finally {
|
||||
mediaControllerFuture = null
|
||||
}
|
||||
},
|
||||
ContextCompat.getMainExecutor(applicationContext)
|
||||
)
|
||||
}
|
||||
|
||||
private fun updateMediaMetadata(metadata: MediaMetadata?) {
|
||||
metadata?.let {
|
||||
binding.tvPlayerTitle.text = it.title
|
||||
binding.tvPlayerNickname.text = it.artist
|
||||
|
||||
binding.ivPlayerCover.load(it.artworkUri) {
|
||||
crossfade(true)
|
||||
placeholder(R.drawable.ic_place_holder)
|
||||
transformations(RoundedCornersTransformation(4f))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupMediaController() {
|
||||
if (mediaController == null) {
|
||||
deInitMiniPlayer()
|
||||
return
|
||||
}
|
||||
|
||||
mediaController!!.addListener(object : Player.Listener {
|
||||
override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
|
||||
updateMediaMetadata(mediaItem?.mediaMetadata)
|
||||
}
|
||||
|
||||
override fun onPlayWhenReadyChanged(playWhenReady: Boolean, reason: Int) {
|
||||
binding.ivPlayerPlayOrPause.setImageResource(
|
||||
if (playWhenReady) {
|
||||
R.drawable.ic_player_pause
|
||||
} else {
|
||||
R.drawable.ic_player_play
|
||||
}
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun deInitMiniPlayer() {
|
||||
handler.removeCallbacks(showMiniPlayerRunnable)
|
||||
binding.clMiniPlayer.visibility = View.GONE
|
||||
mediaControllerFuture?.cancel(true)
|
||||
mediaControllerFuture = null
|
||||
mediaController?.release()
|
||||
mediaController = null
|
||||
}
|
||||
|
||||
private fun showPlayerFragment() {
|
||||
val playerFragment = AudioContentPlayerFragment(screenWidth, arrayListOf())
|
||||
playerFragment.show(supportFragmentManager, playerFragment.tag)
|
||||
}
|
||||
|
||||
private fun checkPermissions() {
|
||||
val permissions = mutableListOf(Manifest.permission.RECORD_AUDIO)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
permissions.add(Manifest.permission.POST_NOTIFICATIONS)
|
||||
}
|
||||
|
||||
TedPermission.create()
|
||||
.setPermissionListener(object : PermissionListener {
|
||||
override fun onPermissionGranted() {
|
||||
}
|
||||
|
||||
override fun onPermissionDenied(deniedPermissions: MutableList<String>?) {
|
||||
}
|
||||
})
|
||||
.setDeniedMessage(R.string.record_audio_permission_denied_message)
|
||||
.setPermissions(*permissions.toTypedArray())
|
||||
.check()
|
||||
}
|
||||
|
||||
private fun trackAppLaunchIfNeeded() {
|
||||
handler.postDelayed({
|
||||
val alreadyTrackingAppLaunch = SharedPreferenceManager.alreadyTrackingAppLaunch
|
||||
val pid = SharedPreferenceManager.marketingPid
|
||||
|
||||
if (!alreadyTrackingAppLaunch && pid.isNotBlank()) {
|
||||
SharedPreferenceManager.alreadyTrackingAppLaunch = true
|
||||
viewModel.adTrackingAppLaunch(pid = pid)
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
private fun pushTokenUpdate() {
|
||||
FirebaseMessaging.getInstance().token.addOnCompleteListener {
|
||||
if (!it.isSuccessful) {
|
||||
Logger.v("Fetching FCM registration token failed", it.exception)
|
||||
return@addOnCompleteListener
|
||||
}
|
||||
|
||||
val pushToken = it.result
|
||||
if (pushToken != null) {
|
||||
SharedPreferenceManager.pushToken = pushToken
|
||||
if (isLoggedIn()) {
|
||||
viewModel.pushTokenUpdate(pushToken)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updatePidAndGaid() {
|
||||
handler.postDelayed({
|
||||
viewModel.fetchAndUpdateGaidAndPid(context = applicationContext)
|
||||
}, 3000)
|
||||
}
|
||||
|
||||
private fun getMemberInfo() {
|
||||
if (isLoggedIn()) {
|
||||
viewModel.getMemberInfo(context = applicationContext) {
|
||||
notificationSettingsDialog.show(screenWidth)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getEventPopup() {
|
||||
viewModel.getEventPopup {
|
||||
if (SharedPreferenceManager.notShowingEventPopupId != it.id) {
|
||||
EventPopupDialogFragment(
|
||||
screenWidth = screenWidth,
|
||||
eventItem = it
|
||||
) {
|
||||
startActivity(
|
||||
Intent(applicationContext, EventDetailActivity::class.java).apply {
|
||||
putExtra(Constants.EXTRA_EVENT, it)
|
||||
}
|
||||
)
|
||||
}.show(supportFragmentManager, EventPopupDialogFragment::class.java.simpleName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun executeDeeplink(intent: Intent) {
|
||||
val bundle = intent.getBundleExtra(Constants.EXTRA_DATA) ?: return
|
||||
val deepLinkUrl = bundle.getString("deep_link")
|
||||
val routeBundle = if (!deepLinkUrl.isNullOrBlank()) {
|
||||
buildBundleFromDeepLinkUrl(deepLinkUrl) ?: bundle
|
||||
} else {
|
||||
bundle
|
||||
}
|
||||
|
||||
if (executeBundleRoute(routeBundle)) {
|
||||
clearDeferredDeepLink()
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildBundleFromDeepLinkUrl(deepLinkUrl: String): Bundle? {
|
||||
val data = runCatching { deepLinkUrl.toUri() }.getOrNull() ?: return null
|
||||
val extras = Bundle().apply {
|
||||
putString("deep_link", deepLinkUrl)
|
||||
}
|
||||
|
||||
fun putQuery(key: String) {
|
||||
val value = data.getQueryParameter(key)
|
||||
if (!value.isNullOrBlank()) {
|
||||
extras.putString(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
putQuery("channel_id")
|
||||
putQuery("message_id")
|
||||
putQuery("audition_id")
|
||||
putQuery("content_id")
|
||||
putQuery("deep_link_value")
|
||||
putQuery("deep_link_sub5")
|
||||
putQuery(Constants.EXTRA_COMMUNITY_CREATOR_ID)
|
||||
putQuery(Constants.EXTRA_COMMUNITY_POST_ID)
|
||||
|
||||
applyPathDeepLink(data = data) { key, value ->
|
||||
if (!value.isNullOrBlank() && !extras.containsKey(key)) {
|
||||
extras.putString(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
return extras
|
||||
}
|
||||
|
||||
private fun applyPathDeepLink(
|
||||
data: android.net.Uri,
|
||||
putIfAbsent: (key: String, value: String?) -> Unit
|
||||
) {
|
||||
val host = data.host?.lowercase(Locale.ROOT).orEmpty()
|
||||
val pathSegments = data.pathSegments.filter { it.isNotBlank() }
|
||||
val pathType: String
|
||||
val pathId: String?
|
||||
|
||||
if (host.isNotBlank() && host != "payverse") {
|
||||
pathType = host
|
||||
pathId = pathSegments.firstOrNull()
|
||||
} else if (pathSegments.isNotEmpty()) {
|
||||
pathType = pathSegments[0].lowercase(Locale.ROOT)
|
||||
pathId = pathSegments.getOrNull(1)
|
||||
} else {
|
||||
return
|
||||
}
|
||||
|
||||
when (pathType) {
|
||||
"content" -> {
|
||||
putIfAbsent("content_id", pathId)
|
||||
putIfAbsent("deep_link_value", "content")
|
||||
putIfAbsent("deep_link_sub5", pathId)
|
||||
}
|
||||
|
||||
"series" -> {
|
||||
putIfAbsent("deep_link_value", "series")
|
||||
putIfAbsent("deep_link_sub5", pathId)
|
||||
}
|
||||
|
||||
"community" -> {
|
||||
putIfAbsent("deep_link_value", "community")
|
||||
putIfAbsent(Constants.EXTRA_COMMUNITY_CREATOR_ID, pathId)
|
||||
putIfAbsent("deep_link_sub5", pathId)
|
||||
}
|
||||
|
||||
"message" -> {
|
||||
putIfAbsent("deep_link_value", "message")
|
||||
putIfAbsent("message_id", pathId)
|
||||
putIfAbsent("deep_link_sub5", pathId)
|
||||
}
|
||||
|
||||
"audition" -> {
|
||||
putIfAbsent("deep_link_value", "audition")
|
||||
putIfAbsent("audition_id", pathId)
|
||||
putIfAbsent("deep_link_sub5", pathId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun executeBundleRoute(bundle: Bundle): Boolean {
|
||||
val channelId = bundle.getString("channel_id")?.toLongOrNull()
|
||||
?: bundle.getLong(Constants.EXTRA_USER_ID).takeIf { it > 0 }
|
||||
val messageId = bundle.getString("message_id")?.toLongOrNull()
|
||||
?: bundle.getLong(Constants.EXTRA_MESSAGE_ID).takeIf { it > 0 }
|
||||
val contentId = bundle.getString("content_id")?.toLongOrNull()
|
||||
?: bundle.getLong(Constants.EXTRA_AUDIO_CONTENT_ID).takeIf { it > 0 }
|
||||
val auditionId = bundle.getString("audition_id")?.toLongOrNull()
|
||||
?: bundle.getLong(Constants.EXTRA_AUDITION_ID).takeIf { it > 0 }
|
||||
val communityCreatorId = bundle.getString(Constants.EXTRA_COMMUNITY_CREATOR_ID)?.toLongOrNull()
|
||||
?: bundle.getLong(Constants.EXTRA_COMMUNITY_CREATOR_ID).takeIf { it > 0 }
|
||||
val communityPostId = bundle.getString(Constants.EXTRA_COMMUNITY_POST_ID)?.toLongOrNull()
|
||||
?: bundle.getLong(Constants.EXTRA_COMMUNITY_POST_ID).takeIf { it > 0 }
|
||||
|
||||
when {
|
||||
channelId != null && channelId > 0 -> {
|
||||
startActivity(
|
||||
Intent(applicationContext, UserProfileActivity::class.java).apply {
|
||||
putExtra(Constants.EXTRA_USER_ID, channelId)
|
||||
}
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
contentId != null && contentId > 0 -> {
|
||||
startActivity(
|
||||
Intent(applicationContext, AudioContentDetailActivity::class.java).apply {
|
||||
putExtra(Constants.EXTRA_AUDIO_CONTENT_ID, contentId)
|
||||
}
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
messageId != null && messageId > 0 -> {
|
||||
startActivity(Intent(applicationContext, MessageActivity::class.java))
|
||||
return true
|
||||
}
|
||||
|
||||
communityCreatorId != null && communityCreatorId > 0 -> {
|
||||
startActivity(
|
||||
Intent(applicationContext, CreatorCommunityAllActivity::class.java).apply {
|
||||
putExtra(Constants.EXTRA_COMMUNITY_CREATOR_ID, communityCreatorId)
|
||||
if (communityPostId != null && communityPostId > 0) {
|
||||
putExtra(Constants.EXTRA_COMMUNITY_POST_ID, communityPostId)
|
||||
}
|
||||
}
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
auditionId != null && auditionId > 0 -> {
|
||||
startActivity(Intent(applicationContext, AuditionActivity::class.java))
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
val deepLinkValue = bundle.getString("deep_link_value")
|
||||
val deepLinkValueId = bundle.getString("deep_link_sub5")?.toLongOrNull()
|
||||
return !deepLinkValue.isNullOrBlank() && routeByDeepLinkValue(deepLinkValue, deepLinkValueId)
|
||||
}
|
||||
|
||||
private fun routeByDeepLinkValue(deepLinkValue: String, deepLinkValueId: Long?): Boolean {
|
||||
return when (deepLinkValue.lowercase(Locale.ROOT)) {
|
||||
"series" -> {
|
||||
if (deepLinkValueId == null || deepLinkValueId <= 0) {
|
||||
return false
|
||||
}
|
||||
startActivity(
|
||||
Intent(applicationContext, SeriesDetailActivity::class.java).apply {
|
||||
putExtra(Constants.EXTRA_SERIES_ID, deepLinkValueId)
|
||||
}
|
||||
)
|
||||
true
|
||||
}
|
||||
|
||||
"content" -> {
|
||||
if (deepLinkValueId == null || deepLinkValueId <= 0) {
|
||||
return false
|
||||
}
|
||||
startActivity(
|
||||
Intent(applicationContext, AudioContentDetailActivity::class.java).apply {
|
||||
putExtra(Constants.EXTRA_AUDIO_CONTENT_ID, deepLinkValueId)
|
||||
}
|
||||
)
|
||||
true
|
||||
}
|
||||
|
||||
"channel" -> {
|
||||
if (deepLinkValueId == null || deepLinkValueId <= 0) {
|
||||
return false
|
||||
}
|
||||
startActivity(
|
||||
Intent(applicationContext, UserProfileActivity::class.java).apply {
|
||||
putExtra(Constants.EXTRA_USER_ID, deepLinkValueId)
|
||||
}
|
||||
)
|
||||
true
|
||||
}
|
||||
|
||||
"community" -> {
|
||||
if (deepLinkValueId == null || deepLinkValueId <= 0) {
|
||||
return false
|
||||
}
|
||||
startActivity(
|
||||
Intent(applicationContext, CreatorCommunityAllActivity::class.java).apply {
|
||||
putExtra(Constants.EXTRA_COMMUNITY_CREATOR_ID, deepLinkValueId)
|
||||
}
|
||||
)
|
||||
true
|
||||
}
|
||||
|
||||
"message" -> {
|
||||
startActivity(Intent(applicationContext, MessageActivity::class.java))
|
||||
true
|
||||
}
|
||||
|
||||
"audition" -> {
|
||||
startActivity(Intent(applicationContext, AuditionActivity::class.java))
|
||||
true
|
||||
}
|
||||
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
private fun clearDeferredDeepLink() {
|
||||
SharedPreferenceManager.marketingUtmSource = ""
|
||||
SharedPreferenceManager.marketingUtmMedium = ""
|
||||
SharedPreferenceManager.marketingUtmCampaign = ""
|
||||
SharedPreferenceManager.marketingLinkValue = ""
|
||||
SharedPreferenceManager.marketingLinkValueId = 0
|
||||
}
|
||||
|
||||
private fun isLoggedIn(): Boolean {
|
||||
return SharedPreferenceManager.token.isNotBlank() && SharedPreferenceManager.token.length > 10
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package kr.co.vividnext.sodalive.v2.main
|
||||
|
||||
enum class MainV2Tab {
|
||||
HOME,
|
||||
CONTENT,
|
||||
CHAT,
|
||||
MY
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
package kr.co.vividnext.sodalive.v2.main
|
||||
|
||||
import android.content.Context
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.google.android.gms.ads.identifier.AdvertisingIdClient
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import kr.co.vividnext.sodalive.audio_content.AddAllPlaybackTrackingRequest
|
||||
import kr.co.vividnext.sodalive.audio_content.AudioContentRepository
|
||||
import kr.co.vividnext.sodalive.audio_content.PlaybackTrackingData
|
||||
import kr.co.vividnext.sodalive.audio_content.PlaybackTrackingRepository
|
||||
import kr.co.vividnext.sodalive.base.BaseViewModel
|
||||
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
|
||||
import kr.co.vividnext.sodalive.main.MarketingInfoUpdateRequest
|
||||
import kr.co.vividnext.sodalive.main.PushTokenUpdateRequest
|
||||
import kr.co.vividnext.sodalive.settings.ContentType
|
||||
import kr.co.vividnext.sodalive.settings.event.EventItem
|
||||
import kr.co.vividnext.sodalive.settings.event.EventRepository
|
||||
import kr.co.vividnext.sodalive.settings.notification.UpdateNotificationSettingRequest
|
||||
import kr.co.vividnext.sodalive.tracking.AdTrackingRepository
|
||||
import kr.co.vividnext.sodalive.tracking.FirebaseTracking
|
||||
import kr.co.vividnext.sodalive.tracking.NotiflyClient
|
||||
import kr.co.vividnext.sodalive.user.UserRepository
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
class MainV2ViewModel(
|
||||
private val userRepository: UserRepository,
|
||||
private val eventRepository: EventRepository,
|
||||
private val adTrackingRepository: AdTrackingRepository,
|
||||
private val audioContentRepository: AudioContentRepository,
|
||||
private val playbackTrackingRepository: PlaybackTrackingRepository
|
||||
) : BaseViewModel() {
|
||||
|
||||
private val _currentTab = MutableLiveData(MainV2Tab.HOME)
|
||||
val currentTab: LiveData<MainV2Tab>
|
||||
get() = _currentTab
|
||||
|
||||
fun clickTab(tab: MainV2Tab) {
|
||||
if (_currentTab.value != tab) {
|
||||
_currentTab.postValue(tab)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateNotificationSettings(
|
||||
isNotifiedLive: Boolean,
|
||||
isNotifiedUploadContent: Boolean,
|
||||
isNotifiedMessage: Boolean
|
||||
) {
|
||||
compositeDisposable.add(
|
||||
userRepository.updateNotificationSettings(
|
||||
request = UpdateNotificationSettingRequest(
|
||||
isNotifiedLive,
|
||||
isNotifiedUploadContent,
|
||||
isNotifiedMessage
|
||||
),
|
||||
token = "Bearer ${SharedPreferenceManager.token}"
|
||||
)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({}, {})
|
||||
)
|
||||
}
|
||||
|
||||
fun pushTokenUpdate(pushToken: String) {
|
||||
compositeDisposable.add(
|
||||
userRepository
|
||||
.updatePushToken(
|
||||
PushTokenUpdateRequest(pushToken = pushToken),
|
||||
"Bearer ${SharedPreferenceManager.token}"
|
||||
)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({}, {})
|
||||
)
|
||||
}
|
||||
|
||||
fun getMemberInfo(context: Context, showNotificationSettingsDialog: () -> Unit) {
|
||||
compositeDisposable.add(
|
||||
userRepository.getMemberInfo(token = "Bearer ${SharedPreferenceManager.token}")
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
{
|
||||
if (it.success && it.data != null) {
|
||||
val data = it.data
|
||||
SharedPreferenceManager.can = data.can
|
||||
SharedPreferenceManager.point = data.point
|
||||
SharedPreferenceManager.role = data.role.name
|
||||
SharedPreferenceManager.isAuth = data.isAuth
|
||||
|
||||
val localCountryCode = SharedPreferenceManager.countryCode.ifBlank { "KR" }
|
||||
val resolvedCountryCode = data.countryCode?.ifBlank { "KR" } ?: localCountryCode
|
||||
val resolvedIsAdultContentVisible =
|
||||
data.isAdultContentVisible ?: SharedPreferenceManager.isAdultContentVisible
|
||||
val resolvedContentType =
|
||||
data.contentType
|
||||
?: ContentType.entries.getOrNull(SharedPreferenceManager.contentPreference)
|
||||
?: ContentType.ALL
|
||||
|
||||
SharedPreferenceManager.countryCode = resolvedCountryCode
|
||||
SharedPreferenceManager.isAdultContentVisible = resolvedIsAdultContentVisible
|
||||
SharedPreferenceManager.contentPreference = resolvedContentType.ordinal
|
||||
SharedPreferenceManager.isAuditionNotification =
|
||||
data.auditionNotice ?: false
|
||||
if (
|
||||
data.followingChannelUploadContentNotice == null &&
|
||||
data.followingChannelLiveNotice == null &&
|
||||
data.messageNotice == null
|
||||
) {
|
||||
showNotificationSettingsDialog()
|
||||
}
|
||||
|
||||
val dateFormat = SimpleDateFormat(
|
||||
"yyyy-MM-dd, HH:mm:ss",
|
||||
Locale.getDefault()
|
||||
)
|
||||
val lastActiveDate = dateFormat.format(Date())
|
||||
|
||||
val params = mutableMapOf(
|
||||
"nickname" to SharedPreferenceManager.nickname,
|
||||
"last_active_date" to lastActiveDate,
|
||||
"charge_count" to data.chargeCount,
|
||||
"signup_date" to data.signupDate,
|
||||
"is_auth" to data.isAuth,
|
||||
"gender" to data.gender,
|
||||
"can" to data.can
|
||||
)
|
||||
|
||||
NotiflyClient.setUser(
|
||||
context = context,
|
||||
userId = SharedPreferenceManager.userId,
|
||||
params = params
|
||||
)
|
||||
FirebaseTracking.login("email")
|
||||
}
|
||||
},
|
||||
{}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun addAllPlaybackTracking() {
|
||||
val trackingDataList = playbackTrackingRepository.getAllPlaybackTracking()
|
||||
.filter { it.endPosition != null }
|
||||
.filter { it.endPosition!! - it.startPosition >= 4000 }
|
||||
.map {
|
||||
PlaybackTrackingData(it.contentId, it.playDateTime, it.isPreview)
|
||||
}
|
||||
|
||||
if (trackingDataList.isNotEmpty()) {
|
||||
compositeDisposable.add(
|
||||
audioContentRepository.addAllPlaybackTracking(
|
||||
request = AddAllPlaybackTrackingRequest(trackingDataList = trackingDataList),
|
||||
token = "Bearer ${SharedPreferenceManager.token}"
|
||||
)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
{
|
||||
if (it.success) {
|
||||
playbackTrackingRepository.removeAllPlaybackTracking()
|
||||
}
|
||||
},
|
||||
{}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun getEventPopup(onSuccess: (EventItem) -> Unit) {
|
||||
compositeDisposable.add(
|
||||
eventRepository.getEventPopup(token = "Bearer ${SharedPreferenceManager.token}")
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
{
|
||||
if (it.success && it.data != null) {
|
||||
onSuccess(it.data)
|
||||
}
|
||||
},
|
||||
{}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun fetchAndUpdateGaidAndPid(context: Context) {
|
||||
Executors.newSingleThreadExecutor().execute {
|
||||
try {
|
||||
val adInfo = AdvertisingIdClient.getAdvertisingIdInfo(context)
|
||||
val request = MarketingInfoUpdateRequest(
|
||||
adid = adInfo.id.orEmpty(),
|
||||
pid = SharedPreferenceManager.marketingPid
|
||||
)
|
||||
updateMarketingInfo(request)
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
updateMarketingInfo(
|
||||
MarketingInfoUpdateRequest(
|
||||
adid = "",
|
||||
pid = SharedPreferenceManager.marketingPid
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun adTrackingAppLaunch(pid: String) {
|
||||
compositeDisposable.add(
|
||||
adTrackingRepository.appLaunch(pid)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({}, {})
|
||||
)
|
||||
}
|
||||
|
||||
private fun updateMarketingInfo(request: MarketingInfoUpdateRequest) {
|
||||
compositeDisposable.add(
|
||||
userRepository.updateMarketingInfo(
|
||||
request,
|
||||
token = "Bearer ${SharedPreferenceManager.token}"
|
||||
)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe({}, {})
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user