You've already forked RekomenciMobile
fcm token sending
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
package com.prodhack.moscow2025.data.dto
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class FcmTokenDTO(
|
||||
@SerialName("device_id")
|
||||
val deviceId: String
|
||||
)
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package com.prodhack.moscow2025.data.repImplementations
|
||||
|
||||
import com.prodhack.moscow2025.data.base.BaseRepository
|
||||
import com.prodhack.moscow2025.data.data_providers.api.ApiKtorClient
|
||||
import com.prodhack.moscow2025.data.dto.FcmTokenDTO
|
||||
import com.prodhack.moscow2025.domain.interfaces.FCMRepository
|
||||
import io.ktor.client.request.setBody
|
||||
import io.ktor.client.request.url
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.http.HttpMethod
|
||||
import io.ktor.http.contentType
|
||||
import org.koin.core.annotation.Single
|
||||
|
||||
@Single
|
||||
class FCMRepositoryImpl(
|
||||
val ktorClient: ApiKtorClient
|
||||
) : FCMRepository, BaseRepository() {
|
||||
|
||||
override val defaultKtorClient = ktorClient.client
|
||||
|
||||
override suspend fun sendFCMToken(token: String) {
|
||||
networkRequest<String> {
|
||||
method = HttpMethod.Post
|
||||
url("/notifications/register_device")
|
||||
setBody(FcmTokenDTO(token))
|
||||
contentType(ContentType.Application.Json)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.prodhack.moscow2025.domain.interfaces
|
||||
|
||||
interface FCMRepository {
|
||||
|
||||
suspend fun sendFCMToken(token: String)
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.prodhack.moscow2025.domain.usecase.auth
|
||||
|
||||
import com.prodhack.moscow2025.domain.interfaces.FCMRepository
|
||||
import org.koin.core.annotation.Single
|
||||
|
||||
@Single
|
||||
class SendFCMTokenUseCase(private val fcmRepository: FCMRepository) {
|
||||
suspend operator fun invoke(token: String) = fcmRepository.sendFCMToken(token = token)
|
||||
}
|
||||
@@ -14,12 +14,15 @@ import androidx.compose.runtime.getValue
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.google.firebase.messaging.FirebaseMessaging
|
||||
import com.prodhack.moscow2025.domain.usecase.auth.CheckSessionUseCase
|
||||
import com.prodhack.moscow2025.domain.usecase.auth.SendFCMTokenUseCase
|
||||
import com.prodhack.moscow2025.domain.usecase.auth.SessionState
|
||||
import com.prodhack.moscow2025.presentation.navigation.AppDestination
|
||||
import com.prodhack.moscow2025.presentation.navigation.TTasksApp
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.koin.android.ext.android.inject
|
||||
import kotlin.getValue
|
||||
@@ -32,6 +35,7 @@ class MainActivity : ComponentActivity() {
|
||||
|
||||
private val checkSessionUseCase: CheckSessionUseCase by inject()
|
||||
|
||||
private val sendFCMTokenUseCase: SendFCMTokenUseCase by inject()
|
||||
private val sessionDestinationState = MutableStateFlow<AppDestination?>(null)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@@ -65,20 +69,13 @@ class MainActivity : ComponentActivity() {
|
||||
|
||||
setContent {
|
||||
val sessionDestination by sessionDestinationState.collectAsState()
|
||||
TTasksApp(sessionDestination = sessionDestination, context = this)
|
||||
LaunchedEffect(Unit) {
|
||||
requestPermissions(
|
||||
arrayOf(Manifest.permission.ACCESS_NOTIFICATION_POLICY), 123
|
||||
)
|
||||
FirebaseMessaging.getInstance().token
|
||||
.addOnCompleteListener { task ->
|
||||
if (task.isSuccessful) {
|
||||
val token = task.result
|
||||
}
|
||||
}
|
||||
|
||||
checkAndRequestNotificationPermission()
|
||||
}
|
||||
TTasksApp(
|
||||
sessionDestination = sessionDestination,
|
||||
context = this,
|
||||
requestNotifyPermissions = {
|
||||
checkAndRequestNotificationPermission()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,12 +86,10 @@ class MainActivity : ComponentActivity() {
|
||||
this,
|
||||
Manifest.permission.POST_NOTIFICATIONS
|
||||
) == PackageManager.PERMISSION_GRANTED -> {
|
||||
// Разрешение уже есть, получаем токен
|
||||
getFCMToken()
|
||||
}
|
||||
|
||||
else -> {
|
||||
// Запрашиваем разрешение
|
||||
requestPermissions(
|
||||
arrayOf(Manifest.permission.POST_NOTIFICATIONS),
|
||||
123
|
||||
@@ -102,17 +97,19 @@ class MainActivity : ComponentActivity() {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Для версий ниже Android 13 разрешение не требуется
|
||||
getFCMToken()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFCMToken() {
|
||||
fun getFCMToken() {
|
||||
FirebaseMessaging.getInstance().token
|
||||
.addOnCompleteListener { task ->
|
||||
if (task.isSuccessful) {
|
||||
val token = task.result
|
||||
Log.d("TOKEN", token)
|
||||
lifecycleScope.launch {
|
||||
sendFCMTokenUseCase(token)
|
||||
}
|
||||
} else {
|
||||
Log.e("TOKEN", "Failed to get token", task.exception)
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.prodhack.moscow2025.presentation.utils.ui.SnackbarStyle
|
||||
fun TTasksApp(
|
||||
appState: TTasksAppState = rememberTTasksAppState(),
|
||||
context: Context,
|
||||
requestNotifyPermissions: () -> Unit,
|
||||
sessionDestination: AppDestination? = null
|
||||
) {
|
||||
MoscowHackatonTemplateTheme {
|
||||
@@ -99,7 +100,8 @@ fun TTasksApp(
|
||||
modifier = Modifier.padding(padding),
|
||||
sessionDestination = sessionDestination,
|
||||
snackbarHostState = snackbarHostState,
|
||||
context = context
|
||||
context = context,
|
||||
requestNotifyPermissions = requestNotifyPermissions
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ fun TTasksNavHost(
|
||||
modifier: Modifier = Modifier,
|
||||
sessionDestination: AppDestination? = null,
|
||||
context: Context,
|
||||
requestNotifyPermissions: () -> Unit,
|
||||
snackbarHostState: SnackbarHostState
|
||||
) {
|
||||
val startDestination = sessionDestination?.route ?: AppDestination.Login.route
|
||||
@@ -100,7 +101,8 @@ fun TTasksNavHost(
|
||||
})
|
||||
}, openCreateResume = {
|
||||
navController.navigate(AppDestination.ResumeCreation.route)
|
||||
}
|
||||
},
|
||||
requestNotifyPermissions = requestNotifyPermissions
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.prodhack.moscow2025.presentation.screens.main
|
||||
|
||||
import android.Manifest
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
@@ -21,6 +22,7 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.pulltorefresh.PullToRefreshBox
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
@@ -30,6 +32,7 @@ import androidx.compose.ui.unit.sp
|
||||
import androidx.paging.LoadState
|
||||
import androidx.paging.compose.LazyPagingItems
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import com.google.firebase.messaging.FirebaseMessaging
|
||||
import com.prodhack.moscow2025.R
|
||||
import com.prodhack.moscow2025.presentation.components.standart.BigButton
|
||||
import com.prodhack.moscow2025.presentation.components.standart.TopLogo
|
||||
@@ -45,9 +48,14 @@ fun ErrorCollectorScope.MainScreen(
|
||||
modifier: Modifier = Modifier,
|
||||
openResumeDetails: (String) -> Unit,
|
||||
openCreateResume: () -> Unit,
|
||||
requestNotifyPermissions: () -> Unit,
|
||||
viewModel: MainScreenViewModel = koinViewModel()
|
||||
) {
|
||||
Box (modifier = modifier){
|
||||
LaunchedEffect(Unit) {
|
||||
requestNotifyPermissions()
|
||||
}
|
||||
|
||||
Box(modifier = modifier) {
|
||||
val items = viewModel.resumeList.collectAsLazyPagingItems()
|
||||
|
||||
MainScreenContent(
|
||||
@@ -162,7 +170,7 @@ private fun MainScreenContent(
|
||||
}
|
||||
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(Paddings.large*4.5f))
|
||||
Spacer(modifier = Modifier.height(Paddings.large * 4.5f))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user