2022-09-24 16:05:21 +08:00
|
|
|
package com.huanchengfly.tieba.post
|
|
|
|
|
|
2022-10-16 12:06:27 +08:00
|
|
|
import android.annotation.SuppressLint
|
|
|
|
|
import android.app.job.JobInfo
|
|
|
|
|
import android.app.job.JobScheduler
|
|
|
|
|
import android.content.BroadcastReceiver
|
|
|
|
|
import android.content.ComponentName
|
|
|
|
|
import android.content.Context
|
|
|
|
|
import android.content.Intent
|
2022-09-24 16:05:21 +08:00
|
|
|
import android.os.Build
|
|
|
|
|
import android.os.Bundle
|
|
|
|
|
import android.os.Handler
|
|
|
|
|
import android.os.Looper
|
|
|
|
|
import androidx.compose.animation.AnimatedContentScope
|
|
|
|
|
import androidx.compose.animation.ExperimentalAnimationApi
|
2023-01-26 13:10:20 +08:00
|
|
|
import androidx.compose.animation.core.Spring
|
|
|
|
|
import androidx.compose.animation.core.VisibilityThreshold
|
|
|
|
|
import androidx.compose.animation.core.spring
|
2023-01-25 22:26:23 +08:00
|
|
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
2022-09-24 16:05:21 +08:00
|
|
|
import androidx.compose.material.Surface
|
|
|
|
|
import androidx.compose.runtime.Composable
|
2023-01-25 22:26:23 +08:00
|
|
|
import androidx.compose.runtime.CompositionLocalProvider
|
|
|
|
|
import androidx.compose.runtime.staticCompositionLocalOf
|
2022-09-24 16:05:21 +08:00
|
|
|
import androidx.compose.ui.Alignment
|
2023-01-26 13:10:20 +08:00
|
|
|
import androidx.compose.ui.unit.IntOffset
|
2023-01-25 22:26:23 +08:00
|
|
|
import androidx.compose.ui.unit.dp
|
2023-01-01 21:26:46 +08:00
|
|
|
import androidx.core.content.ContextCompat
|
2022-09-24 16:05:21 +08:00
|
|
|
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
2023-01-07 16:00:39 +08:00
|
|
|
import androidx.lifecycle.flowWithLifecycle
|
2022-09-24 16:05:21 +08:00
|
|
|
import androidx.lifecycle.lifecycleScope
|
2023-01-25 22:26:23 +08:00
|
|
|
import androidx.navigation.plusAssign
|
2023-01-07 16:00:39 +08:00
|
|
|
import androidx.window.layout.FoldingFeature
|
|
|
|
|
import androidx.window.layout.WindowInfoTracker
|
2023-01-25 22:26:23 +08:00
|
|
|
import com.google.accompanist.navigation.animation.rememberAnimatedNavController
|
2022-09-24 16:05:21 +08:00
|
|
|
import com.google.accompanist.navigation.material.ExperimentalMaterialNavigationApi
|
2023-01-25 22:26:23 +08:00
|
|
|
import com.google.accompanist.navigation.material.ModalBottomSheetLayout
|
|
|
|
|
import com.google.accompanist.navigation.material.rememberBottomSheetNavigator
|
2022-09-24 16:05:21 +08:00
|
|
|
import com.google.accompanist.systemuicontroller.SystemUiController
|
|
|
|
|
import com.huanchengfly.tieba.post.api.retrofit.exception.getErrorMessage
|
|
|
|
|
import com.huanchengfly.tieba.post.arch.BaseComposeActivity
|
2022-10-16 12:06:27 +08:00
|
|
|
import com.huanchengfly.tieba.post.services.NotifyJobService
|
2022-09-24 16:05:21 +08:00
|
|
|
import com.huanchengfly.tieba.post.ui.common.theme.compose.ExtendedTheme
|
|
|
|
|
import com.huanchengfly.tieba.post.ui.page.NavGraphs
|
|
|
|
|
import com.huanchengfly.tieba.post.ui.page.destinations.MainPageDestination
|
2023-01-07 16:00:39 +08:00
|
|
|
import com.huanchengfly.tieba.post.ui.utils.DevicePosture
|
|
|
|
|
import com.huanchengfly.tieba.post.ui.utils.isBookPosture
|
|
|
|
|
import com.huanchengfly.tieba.post.ui.utils.isSeparating
|
2022-09-24 16:05:21 +08:00
|
|
|
import com.huanchengfly.tieba.post.utils.AccountUtil
|
2022-10-16 12:06:27 +08:00
|
|
|
import com.huanchengfly.tieba.post.utils.JobServiceUtil
|
2022-09-24 16:05:21 +08:00
|
|
|
import com.huanchengfly.tieba.post.utils.PermissionUtils
|
|
|
|
|
import com.huanchengfly.tieba.post.utils.TiebaUtil
|
2023-01-26 12:30:41 +08:00
|
|
|
import com.huanchengfly.tieba.post.utils.newIntentFilter
|
2022-09-24 16:05:21 +08:00
|
|
|
import com.huanchengfly.tieba.post.utils.requestPermission
|
|
|
|
|
import com.ramcosta.composedestinations.DestinationsNavHost
|
|
|
|
|
import com.ramcosta.composedestinations.animations.defaults.RootNavGraphDefaultAnimations
|
|
|
|
|
import com.ramcosta.composedestinations.animations.rememberAnimatedNavHostEngine
|
|
|
|
|
import com.ramcosta.composedestinations.navigation.dependency
|
|
|
|
|
import dagger.hilt.android.AndroidEntryPoint
|
|
|
|
|
import kotlinx.coroutines.Dispatchers
|
2023-01-25 22:26:23 +08:00
|
|
|
import kotlinx.coroutines.channels.BufferOverflow
|
|
|
|
|
import kotlinx.coroutines.flow.Flow
|
|
|
|
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
2023-01-07 16:00:39 +08:00
|
|
|
import kotlinx.coroutines.flow.SharingStarted
|
|
|
|
|
import kotlinx.coroutines.flow.StateFlow
|
2022-09-24 16:05:21 +08:00
|
|
|
import kotlinx.coroutines.flow.catch
|
|
|
|
|
import kotlinx.coroutines.flow.collect
|
|
|
|
|
import kotlinx.coroutines.flow.flowOn
|
2023-01-07 16:00:39 +08:00
|
|
|
import kotlinx.coroutines.flow.map
|
|
|
|
|
import kotlinx.coroutines.flow.stateIn
|
2022-09-24 16:05:21 +08:00
|
|
|
import kotlinx.coroutines.launch
|
|
|
|
|
|
2023-01-25 22:26:23 +08:00
|
|
|
val LocalNotificationCountFlow =
|
|
|
|
|
staticCompositionLocalOf<Flow<Int>> { throw IllegalStateException("not allowed here!") }
|
|
|
|
|
|
2022-09-24 16:05:21 +08:00
|
|
|
@AndroidEntryPoint
|
|
|
|
|
class MainActivityV2 : BaseComposeActivity() {
|
|
|
|
|
private val handler = Handler(Looper.getMainLooper())
|
2022-10-16 12:06:27 +08:00
|
|
|
private val newMessageReceiver: BroadcastReceiver = NewMessageReceiver()
|
2022-09-24 16:05:21 +08:00
|
|
|
|
2023-01-25 22:26:23 +08:00
|
|
|
private val notificationCountFlow: MutableSharedFlow<Int> =
|
|
|
|
|
MutableSharedFlow(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
|
|
|
|
|
|
2023-01-07 16:00:39 +08:00
|
|
|
private val devicePostureFlow: StateFlow<DevicePosture> by lazy {
|
|
|
|
|
WindowInfoTracker.getOrCreate(this)
|
|
|
|
|
.windowLayoutInfo(this)
|
|
|
|
|
.flowWithLifecycle(lifecycle)
|
|
|
|
|
.map { layoutInfo ->
|
|
|
|
|
val foldingFeature =
|
|
|
|
|
layoutInfo.displayFeatures
|
|
|
|
|
.filterIsInstance<FoldingFeature>()
|
|
|
|
|
.firstOrNull()
|
|
|
|
|
when {
|
|
|
|
|
isBookPosture(foldingFeature) ->
|
|
|
|
|
DevicePosture.BookPosture(foldingFeature.bounds)
|
|
|
|
|
|
|
|
|
|
isSeparating(foldingFeature) ->
|
|
|
|
|
DevicePosture.Separating(foldingFeature.bounds, foldingFeature.orientation)
|
|
|
|
|
|
|
|
|
|
else -> DevicePosture.NormalPosture
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.stateIn(
|
|
|
|
|
scope = lifecycleScope,
|
|
|
|
|
started = SharingStarted.Eagerly,
|
|
|
|
|
initialValue = DevicePosture.NormalPosture
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-24 16:05:21 +08:00
|
|
|
private fun fetchAccount() {
|
|
|
|
|
lifecycleScope.launch(Dispatchers.Main) {
|
|
|
|
|
if (AccountUtil.isLoggedIn()) {
|
|
|
|
|
AccountUtil.fetchAccountFlow()
|
|
|
|
|
.flowOn(Dispatchers.IO)
|
|
|
|
|
.catch { e ->
|
|
|
|
|
toastShort(e.getErrorMessage())
|
|
|
|
|
e.printStackTrace()
|
|
|
|
|
}
|
|
|
|
|
.collect()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun requestNotificationPermission() {
|
|
|
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && AccountUtil.isLoggedIn()) {
|
|
|
|
|
requestPermission {
|
|
|
|
|
permissions = listOf(PermissionUtils.POST_NOTIFICATIONS)
|
|
|
|
|
description = getString(R.string.desc_permission_post_notifications)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private fun initAutoSign() {
|
|
|
|
|
runCatching {
|
|
|
|
|
TiebaUtil.initAutoSign(this)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override fun onStart() {
|
|
|
|
|
super.onStart()
|
2022-10-16 12:06:27 +08:00
|
|
|
runCatching {
|
2023-01-01 21:26:46 +08:00
|
|
|
ContextCompat.registerReceiver(
|
|
|
|
|
this,
|
2022-10-16 12:06:27 +08:00
|
|
|
newMessageReceiver,
|
2023-01-26 12:30:41 +08:00
|
|
|
newIntentFilter(NotifyJobService.ACTION_NEW_MESSAGE),
|
2023-01-01 21:26:46 +08:00
|
|
|
ContextCompat.RECEIVER_NOT_EXPORTED
|
2022-10-16 12:06:27 +08:00
|
|
|
)
|
|
|
|
|
startService(Intent(this, NotifyJobService::class.java))
|
|
|
|
|
val builder = JobInfo.Builder(
|
|
|
|
|
JobServiceUtil.getJobId(this),
|
|
|
|
|
ComponentName(this, NotifyJobService::class.java)
|
|
|
|
|
)
|
|
|
|
|
.setPersisted(true)
|
|
|
|
|
.setPeriodic(30 * 60 * 1000L)
|
|
|
|
|
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
|
|
|
|
|
val jobScheduler = getSystemService(Context.JOB_SCHEDULER_SERVICE) as JobScheduler
|
|
|
|
|
jobScheduler.schedule(builder.build())
|
|
|
|
|
}
|
2022-09-24 16:05:21 +08:00
|
|
|
handler.postDelayed({
|
|
|
|
|
requestNotificationPermission()
|
|
|
|
|
}, 100)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
|
|
|
installSplashScreen()
|
|
|
|
|
super.onCreate(savedInstanceState)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override fun onCreateContent(systemUiController: SystemUiController) {
|
|
|
|
|
super.onCreateContent(systemUiController)
|
|
|
|
|
fetchAccount()
|
|
|
|
|
initAutoSign()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@OptIn(ExperimentalAnimationApi::class, ExperimentalMaterialNavigationApi::class)
|
|
|
|
|
@Composable
|
|
|
|
|
override fun createContent() {
|
2023-01-25 22:26:23 +08:00
|
|
|
CompositionLocalProvider(LocalNotificationCountFlow provides notificationCountFlow) {
|
|
|
|
|
Surface(
|
|
|
|
|
color = ExtendedTheme.colors.background
|
|
|
|
|
) {
|
2023-01-26 13:10:20 +08:00
|
|
|
val animationSpec = spring(
|
|
|
|
|
stiffness = Spring.StiffnessMediumLow,
|
|
|
|
|
visibilityThreshold = IntOffset.VisibilityThreshold
|
|
|
|
|
)
|
2023-01-25 22:26:23 +08:00
|
|
|
val engine = rememberAnimatedNavHostEngine(
|
|
|
|
|
navHostContentAlignment = Alignment.TopStart,
|
|
|
|
|
rootDefaultAnimations = RootNavGraphDefaultAnimations(
|
|
|
|
|
enterTransition = {
|
|
|
|
|
slideIntoContainer(
|
|
|
|
|
AnimatedContentScope.SlideDirection.Start,
|
2023-01-26 13:10:20 +08:00
|
|
|
animationSpec = animationSpec,
|
|
|
|
|
initialOffset = { it }
|
|
|
|
|
)
|
2023-01-25 22:26:23 +08:00
|
|
|
},
|
|
|
|
|
exitTransition = {
|
|
|
|
|
slideOutOfContainer(
|
|
|
|
|
AnimatedContentScope.SlideDirection.End,
|
2023-01-26 13:10:20 +08:00
|
|
|
animationSpec = animationSpec,
|
|
|
|
|
targetOffset = { -it }
|
|
|
|
|
)
|
2023-01-25 22:26:23 +08:00
|
|
|
},
|
|
|
|
|
popEnterTransition = {
|
|
|
|
|
slideIntoContainer(
|
|
|
|
|
AnimatedContentScope.SlideDirection.Start,
|
2023-01-26 13:10:20 +08:00
|
|
|
animationSpec = animationSpec,
|
|
|
|
|
initialOffset = { -it }
|
|
|
|
|
)
|
2023-01-25 22:26:23 +08:00
|
|
|
},
|
|
|
|
|
popExitTransition = {
|
|
|
|
|
slideOutOfContainer(
|
|
|
|
|
AnimatedContentScope.SlideDirection.End,
|
2023-01-26 13:10:20 +08:00
|
|
|
animationSpec = animationSpec,
|
|
|
|
|
targetOffset = { it }
|
|
|
|
|
)
|
2023-01-25 22:26:23 +08:00
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
val navController = rememberAnimatedNavController()
|
2023-01-26 13:10:20 +08:00
|
|
|
val bottomSheetNavigator =
|
|
|
|
|
rememberBottomSheetNavigator(animationSpec = spring(stiffness = Spring.StiffnessMediumLow))
|
2023-01-25 22:26:23 +08:00
|
|
|
navController.navigatorProvider += bottomSheetNavigator
|
|
|
|
|
ModalBottomSheetLayout(
|
|
|
|
|
bottomSheetNavigator = bottomSheetNavigator,
|
2023-01-26 14:53:03 +08:00
|
|
|
sheetShape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp)
|
2023-01-25 22:26:23 +08:00
|
|
|
) {
|
|
|
|
|
DestinationsNavHost(
|
|
|
|
|
navController = navController,
|
|
|
|
|
navGraph = NavGraphs.root,
|
|
|
|
|
engine = engine,
|
|
|
|
|
dependenciesContainerBuilder = {
|
|
|
|
|
dependency(MainPageDestination) { this@MainActivityV2 }
|
|
|
|
|
dependency(devicePostureFlow)
|
|
|
|
|
}
|
|
|
|
|
)
|
2022-09-24 16:05:21 +08:00
|
|
|
}
|
2023-01-25 22:26:23 +08:00
|
|
|
}
|
2022-09-24 16:05:21 +08:00
|
|
|
}
|
|
|
|
|
}
|
2022-10-16 12:06:27 +08:00
|
|
|
|
|
|
|
|
private inner class NewMessageReceiver : BroadcastReceiver() {
|
|
|
|
|
@SuppressLint("RestrictedApi")
|
|
|
|
|
override fun onReceive(context: Context, intent: Intent) {
|
|
|
|
|
if (intent.action == NotifyJobService.ACTION_NEW_MESSAGE) {
|
|
|
|
|
val channel = intent.getStringExtra("channel")
|
|
|
|
|
val count = intent.getIntExtra("count", 0)
|
|
|
|
|
if (channel != null && channel == NotifyJobService.CHANNEL_TOTAL) {
|
2023-01-25 22:26:23 +08:00
|
|
|
lifecycleScope.launch {
|
|
|
|
|
notificationCountFlow.emit(count)
|
|
|
|
|
}
|
2022-10-16 12:06:27 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-09-24 16:05:21 +08:00
|
|
|
}
|