Skip to content
Open
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ class StudyRepository {
studyService.addRegistrationId(sid, mapOf(registrationId to true))
}

suspend fun getRegistrationIdList(sid: String): Map<String, Boolean> {
return studyService.getRegistrationIdList(sid)
}

fun getMessageList(sid: String): Flow<Map<String, Message>> = flow {
while (true) {
kotlin.runCatching {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,11 @@ interface StudyService {
@Body registrationId: Map<String, Boolean>
)

@GET("studies/{sid}/registrationIds.json")
suspend fun getRegistrationIdList(
@Path("sid") sid: String
): Map<String, Boolean>

companion object {
private const val BASE_URL = BuildConfig.FIREBASE_BASE_URL
private val contentType = "application/json".toMediaType()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package com.sesac.developer_study_platform.ui.common

import android.Manifest
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import com.sesac.developer_study_platform.EventObserver
import com.sesac.developer_study_platform.R
import com.sesac.developer_study_platform.data.source.local.FcmTokenRepository
import com.sesac.developer_study_platform.databinding.DialogNotificationPermissionBinding

class NotificationPermissionDialogFragment : DialogFragment() {

private var _binding: DialogNotificationPermissionBinding? = null
private val binding get() = _binding!!
private val viewModel by viewModels<NotificationPermissionDialogViewModel> {
NotificationPermissionDialogViewModel.create(FcmTokenRepository(requireContext()))
}
private val args by navArgs<NotificationPermissionDialogFragmentArgs>()
private val requestPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
if (isGranted) {
checkNotificationKey()
} else {
Toast.makeText(context, getString(R.string.all_notification_info), Toast.LENGTH_SHORT).show()
viewModel.moveToMessage(args.studyId)
}
}

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = DialogNotificationPermissionBinding.inflate(inflater, container, false)
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

setYesButton()
binding.btnNo.setOnClickListener {
viewModel.moveToMessage(args.studyId)
}
setNavigation()
}

private fun setYesButton() {
binding.btnYes.setOnClickListener {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
} else {
checkNotificationKey()
}
}
}

private fun checkNotificationKey() {
viewModel.checkNotificationKey(args.studyId)
viewModel.checkNotificationKeyEvent.observe(
viewLifecycleOwner,
EventObserver {
viewModel.moveToMessage(args.studyId)
}
)
}

private fun setNavigation() {
viewModel.moveToMessageEvent.observe(
viewLifecycleOwner,
EventObserver {
val action = NotificationPermissionDialogFragmentDirections.actionGlobalToMessage(it)
findNavController().navigate(action)
}
)
}

override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package com.sesac.developer_study_platform.ui.common

import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
import com.sesac.developer_study_platform.Event
import com.sesac.developer_study_platform.StudyApplication.Companion.fcmRepository
import com.sesac.developer_study_platform.StudyApplication.Companion.studyRepository
import com.sesac.developer_study_platform.data.StudyGroup
import com.sesac.developer_study_platform.data.source.local.FcmTokenRepository
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch

class NotificationPermissionDialogViewModel(private val fcmTokenRepository: FcmTokenRepository) :
ViewModel() {

private val _checkNotificationKeyEvent: MutableLiveData<Event<Unit>> = MutableLiveData()
val checkNotificationKeyEvent: LiveData<Event<Unit>> = _checkNotificationKeyEvent

private val _moveToMessageEvent: MutableLiveData<Event<String>> = MutableLiveData()
val moveToMessageEvent: LiveData<Event<String>> = _moveToMessageEvent

fun checkNotificationKey(sid: String) {
viewModelScope.launch {
if (getNotificationKey(sid).isNullOrEmpty()) {
createNotificationKey(sid)
} else if (isRegistrationId(sid, fcmTokenRepository.getToken().first())) {
updateStudyGroup(sid)
}
}
}

private fun createNotificationKey(sid: String) {
viewModelScope.launch {
val token = fcmTokenRepository.getToken().first()
kotlin.runCatching {
fcmRepository.updateStudyGroup(StudyGroup("create", sid, listOf(token)))
}.onSuccess {
addNotificationKey(sid, it.values.first())
}.onFailure {
Log.e(
"NotificationPermissionDialogViewModel-createNotificationKey",
it.message ?: "error occurred."
)
}
}
}

private fun addNotificationKey(sid: String, notificationKey: String) {
viewModelScope.launch {
kotlin.runCatching {
studyRepository.addNotificationKey(sid, notificationKey)
}.onSuccess {
addRegistrationId(sid, fcmTokenRepository.getToken().first())
}.onFailure {
Log.e(
"NotificationPermissionDialogViewModel-addNotificationKey",
it.message ?: "error occurred."
)
}
}
}

private fun updateStudyGroup(sid: String) {
viewModelScope.launch {
val token = fcmTokenRepository.getToken().first()
kotlin.runCatching {
val notificationKey = getNotificationKey(sid)
if (!notificationKey.isNullOrEmpty()) {
fcmRepository.updateStudyGroup(StudyGroup("add", sid, listOf(token), notificationKey))
}
}.onSuccess {
addRegistrationId(sid, token)
}.onFailure {
Log.e(
"NotificationPermissionDialogViewModel-updateStudyGroup",
it.message ?: "error occurred."
)
}
}
}

private suspend fun getNotificationKey(sid: String): String? {
return viewModelScope.async {
kotlin.runCatching {
studyRepository.getNotificationKey(sid)
}.onFailure {
Log.e(
"NotificationPermissionDialogViewModel-getNotificationKey",
it.message ?: "error occurred."
)
}.getOrNull()
}.await()
}

private fun addRegistrationId(sid: String, registrationId: String) {
viewModelScope.launch {
kotlin.runCatching {
studyRepository.addRegistrationId(sid, registrationId)
}.onSuccess {
_checkNotificationKeyEvent.value = Event(Unit)
}.onFailure {
Log.e(
"NotificationPermissionDialogViewModel-addRegistrationId",
it.message ?: "error occurred."
)
}
}
}

private suspend fun isRegistrationId(sid: String, registrationId: String): Boolean {
return viewModelScope.async {
kotlin.runCatching {
studyRepository.getRegistrationIdList(sid)
}.map {
it.containsKey(registrationId)
}.onFailure {
Log.e(
"NotificationPermissionDialogViewModel-isRegistrationId",
it.message ?: "error occurred."
)
}.getOrDefault(false)
}.await()
}

fun moveToMessage(sid: String) {
_moveToMessageEvent.value = Event(sid)
}

companion object {
fun create(fcmTokenRepository: FcmTokenRepository) = viewModelFactory {
initializer {
NotificationPermissionDialogViewModel(fcmTokenRepository)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat
Expand Down Expand Up @@ -51,24 +50,13 @@ class JoinStudyDialogFragment : DialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

setDialog()
setNavigation()
setYesButton()
binding.btnNo.setOnClickListener {
dismiss()
}
}

private fun setDialog() {
val displayMetrics = resources.displayMetrics
val widthPixels = displayMetrics.widthPixels

val params = dialog?.window?.attributes
params?.width = (widthPixels * 0.9).toInt()
dialog?.window?.attributes = params as WindowManager.LayoutParams
dialog?.window?.setBackgroundDrawableResource(R.drawable.bg_white_radius_18dp)
}

private fun setYesButton() {
binding.btnYes.setOnClickListener {
viewModel.addUserStudy(
Expand All @@ -87,6 +75,11 @@ class JoinStudyDialogFragment : DialogFragment() {
}

private fun setNavigation() {
moveToMessage()
moveToNotificationPermissionDialog()
}

private fun moveToMessage() {
viewModel.moveToMessageEvent.observe(
viewLifecycleOwner,
EventObserver {
Expand All @@ -96,6 +89,16 @@ class JoinStudyDialogFragment : DialogFragment() {
)
}

private fun moveToNotificationPermissionDialog() {
viewModel.moveToNotificationPermissionDialogEvent.observe(
viewLifecycleOwner,
EventObserver {
val action = JoinStudyDialogFragmentDirections.actionGlobalToNotificationPermissionDialog(it)
findNavController().navigate(action)
}
)
}

private fun askNotificationPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
when {
Expand All @@ -107,7 +110,7 @@ class JoinStudyDialogFragment : DialogFragment() {
}

shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS) -> {
// TODO 권한 이유 다이얼로그
viewModel.moveToNotificationPermissionDialog(args.study.sid)
}

else -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ class JoinStudyDialogViewModel(private val fcmTokenRepository: FcmTokenRepositor
private val _moveToMessageEvent: MutableLiveData<Event<String>> = MutableLiveData()
val moveToMessageEvent: LiveData<Event<String>> = _moveToMessageEvent

private val _moveToNotificationPermissionDialogEvent: MutableLiveData<Event<String>> = MutableLiveData()
val moveToNotificationPermissionDialogEvent: LiveData<Event<String>> =
_moveToNotificationPermissionDialogEvent

fun addUserStudy(sid: String, study: UserStudy) {
viewModelScope.launch {
kotlin.runCatching {
Expand Down Expand Up @@ -102,6 +106,10 @@ class JoinStudyDialogViewModel(private val fcmTokenRepository: FcmTokenRepositor
_moveToMessageEvent.value = Event(sid)
}

fun moveToNotificationPermissionDialog(sid: String) {
_moveToNotificationPermissionDialogEvent.value = Event(sid)
}

companion object {
fun create(fcmTokenRepository: FcmTokenRepository) = viewModelFactory {
initializer {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class MainActivity : AppCompatActivity() {
R.id.dest_exit_dialog -> View.GONE
R.id.dest_ban_dialog -> View.GONE
R.id.dest_join_study_dialog -> View.GONE
R.id.dest_notification_permission_dialog -> View.GONE
else -> View.VISIBLE
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
Expand Down Expand Up @@ -32,7 +31,6 @@ class ExitDialogFragment : DialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

setDialog()
setNavigation()
binding.btnNo.setOnClickListener {
dismiss()
Expand All @@ -42,16 +40,6 @@ class ExitDialogFragment : DialogFragment() {
}
}

private fun setDialog() {
val displayMetrics = resources.displayMetrics
val widthPixels = displayMetrics.widthPixels

val params = dialog?.window?.attributes
params?.width = (widthPixels * 0.9).toInt()
dialog?.window?.attributes = params as WindowManager.LayoutParams
dialog?.window?.setBackgroundDrawableResource(R.drawable.bg_white_radius_18dp)
}

private fun setNavigation() {
viewModel.moveToHomeEvent.observe(
viewLifecycleOwner,
Expand Down
Loading