회원가입 후 초기 알림설정 기능 추가

This commit is contained in:
klaus 2023-07-24 14:54:15 +09:00
parent 6c8183b12f
commit edbaceba0b
15 changed files with 371 additions and 2 deletions

View File

@ -1,10 +1,13 @@
package kr.co.vividnext.sodalive.common
object Constants {
const val PREF_CAN = "pref_can"
const val PREF_TOKEN = "pref_token"
const val PREF_EMAIL = "pref_email"
const val PREF_USER_ID = "pref_user_id"
const val PREF_IS_ADULT = "pref_is_adult"
const val PREF_NICKNAME = "pref_nickname"
const val PREF_USER_ROLE = "pref_user_role"
const val PREF_PROFILE_IMAGE = "pref_profile_image"
const val EXTRA_DATA = "extra_data"

View File

@ -3,6 +3,7 @@ package kr.co.vividnext.sodalive.common
import android.content.Context
import android.content.SharedPreferences
import androidx.preference.PreferenceManager
import kr.co.vividnext.sodalive.settings.notification.MemberRole
object SharedPreferenceManager {
private lateinit var sharedPreferences: SharedPreferences
@ -73,4 +74,22 @@ object SharedPreferenceManager {
set(value) {
sharedPreferences[Constants.PREF_PROFILE_IMAGE] = value
}
var can: Int
get() = sharedPreferences[Constants.PREF_CAN, 0]
set(value) {
sharedPreferences[Constants.PREF_CAN] = value
}
var role: String
get() = sharedPreferences[Constants.PREF_USER_ROLE, MemberRole.USER.name]
set(value) {
sharedPreferences[Constants.PREF_USER_ROLE] = value
}
var isAuth: Boolean
get() = sharedPreferences[Constants.PREF_IS_ADULT, false]
set(value) {
sharedPreferences[Constants.PREF_IS_ADULT] = value
}
}

View File

@ -65,7 +65,7 @@ class AppDI(private val context: Context, isDebugMode: Boolean) {
viewModel { SignUpViewModel(get()) }
viewModel { TermsViewModel(get()) }
viewModel { FindPasswordViewModel(get()) }
viewModel { MainViewModel() }
viewModel { MainViewModel(get()) }
}
private val repositoryModule = module {

View File

@ -14,6 +14,7 @@ import kr.co.vividnext.sodalive.explorer.ExplorerFragment
import kr.co.vividnext.sodalive.live.LiveFragment
import kr.co.vividnext.sodalive.message.MessageFragment
import kr.co.vividnext.sodalive.mypage.MyPageFragment
import kr.co.vividnext.sodalive.settings.notification.NotificationSettingsDialog
import org.koin.android.ext.android.inject
class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::inflate) {
@ -22,16 +23,30 @@ class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::infl
private lateinit var liveFragment: LiveFragment
private lateinit var loadingDialog: LoadingDialog
private lateinit var notificationSettingsDialog: NotificationSettingsDialog
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setupBottomTabLayout()
getMemberInfo()
}
override fun setupView() {
loadingDialog = LoadingDialog(this, layoutInflater)
liveFragment = LiveFragment()
notificationSettingsDialog = NotificationSettingsDialog(
this,
layoutInflater
) { isNotifiedLive, isNotifiedUploadContent, isNotifiedMessage ->
viewModel.updateNotificationSettings(
isNotifiedLive,
isNotifiedUploadContent,
isNotifiedMessage
)
}
}
private fun setupBottomTabLayout() {
@ -180,4 +195,10 @@ class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::infl
fragmentTransaction.setReorderingAllowed(true)
fragmentTransaction.commitNow()
}
private fun getMemberInfo() {
viewModel.getMemberInfo {
notificationSettingsDialog.show(screenWidth)
}
}
}

View File

@ -3,9 +3,16 @@ package kr.co.vividnext.sodalive.main
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.google.gson.annotations.SerializedName
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.schedulers.Schedulers
import kr.co.vividnext.sodalive.base.BaseViewModel
import kr.co.vividnext.sodalive.common.SharedPreferenceManager
import kr.co.vividnext.sodalive.settings.notification.UpdateNotificationSettingRequest
import kr.co.vividnext.sodalive.user.UserRepository
class MainViewModel : BaseViewModel() {
class MainViewModel(
private val userRepository: UserRepository,
) : BaseViewModel() {
enum class CurrentTab {
@SerializedName("CONTENT")
CONTENT,
@ -32,4 +39,50 @@ class MainViewModel : BaseViewModel() {
_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 getMemberInfo(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.role = data.role.name
SharedPreferenceManager.isAuth = data.isAuth
if (
data.followingChannelUploadContentNotice == null &&
data.followingChannelLiveNotice == null &&
data.messageNotice == null
) {
showNotificationSettingsDialog()
}
}
},
{}
)
)
}
}

View File

@ -0,0 +1,22 @@
package kr.co.vividnext.sodalive.settings.notification
import com.google.gson.annotations.SerializedName
data class GetMemberInfoResponse(
@SerializedName("can") val can: Int,
@SerializedName("isAuth") val isAuth: Boolean,
@SerializedName("role") val role: MemberRole,
@SerializedName("messageNotice") val messageNotice: Boolean?,
@SerializedName("followingChannelLiveNotice")
val followingChannelLiveNotice: Boolean?,
@SerializedName("followingChannelUploadContentNotice")
val followingChannelUploadContentNotice: Boolean?
)
enum class MemberRole {
@SerializedName("USER")
USER,
@SerializedName("CREATOR")
CREATOR,
}

View File

@ -0,0 +1,83 @@
package kr.co.vividnext.sodalive.settings.notification
import android.app.Activity
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.view.LayoutInflater
import android.view.WindowManager
import androidx.appcompat.app.AlertDialog
import kr.co.vividnext.sodalive.R
import kr.co.vividnext.sodalive.databinding.DialogNotificationSettingsBinding
import kr.co.vividnext.sodalive.extensions.dpToPx
class NotificationSettingsDialog(
activity: Activity,
layoutInflater: LayoutInflater,
confirmAction: (Boolean, Boolean, Boolean) -> Unit
) {
private val alertDialog: AlertDialog
val dialogView = DialogNotificationSettingsBinding.inflate(layoutInflater)
private var isNewChannelLive = true
private var isNotifiedChannel = true
private var isMessage = true
init {
val dialogBuilder = AlertDialog.Builder(activity)
dialogBuilder.setView(dialogView.root)
alertDialog = dialogBuilder.create()
alertDialog.setCancelable(false)
alertDialog.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
dialogView.ivNewChannelLive.setOnClickListener {
isNewChannelLive = !isNewChannelLive
dialogView.ivNewChannelLive.setImageResource(
if (isNewChannelLive) {
R.drawable.btn_toggle_on_big
} else {
R.drawable.btn_toggle_off_big
}
)
}
dialogView.ivNotifiedChannel.setOnClickListener {
isNotifiedChannel = !isNotifiedChannel
dialogView.ivNotifiedChannel.setImageResource(
if (isNotifiedChannel) {
R.drawable.btn_toggle_on_big
} else {
R.drawable.btn_toggle_off_big
}
)
}
dialogView.ivMessage.setOnClickListener {
isMessage = !isMessage
dialogView.ivMessage.setImageResource(
if (isMessage) {
R.drawable.btn_toggle_on_big
} else {
R.drawable.btn_toggle_off_big
}
)
}
dialogView.tvConfirm.setOnClickListener {
confirmAction(isNewChannelLive, isNotifiedChannel, isMessage)
alertDialog.dismiss()
}
}
fun show(width: Int) {
alertDialog.show()
val lp = WindowManager.LayoutParams()
lp.copyFrom(alertDialog.window?.attributes)
lp.width = width - (26.7f.dpToPx()).toInt()
lp.height = WindowManager.LayoutParams.WRAP_CONTENT
alertDialog.window?.attributes = lp
}
}

View File

@ -0,0 +1,9 @@
package kr.co.vividnext.sodalive.settings.notification
import com.google.gson.annotations.SerializedName
data class UpdateNotificationSettingRequest(
@SerializedName("live") var live: Boolean? = null,
@SerializedName("uploadContent") var uploadContent: Boolean? = null,
@SerializedName("message") var message: Boolean? = null
)

View File

@ -2,12 +2,16 @@ package kr.co.vividnext.sodalive.user
import io.reactivex.rxjava3.core.Single
import kr.co.vividnext.sodalive.common.ApiResponse
import kr.co.vividnext.sodalive.settings.notification.GetMemberInfoResponse
import kr.co.vividnext.sodalive.settings.notification.UpdateNotificationSettingRequest
import kr.co.vividnext.sodalive.user.find_password.ForgotPasswordRequest
import kr.co.vividnext.sodalive.user.login.LoginRequest
import kr.co.vividnext.sodalive.user.login.LoginResponse
import okhttp3.MultipartBody
import okhttp3.RequestBody
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.Multipart
import retrofit2.http.POST
import retrofit2.http.Part
@ -25,4 +29,15 @@ interface UserApi {
@POST("/member/forgot-password")
fun findPassword(@Body request: ForgotPasswordRequest): Single<ApiResponse<Any>>
@GET("/member/info")
fun getMemberInfo(
@Header("Authorization") authHeader: String
): Single<ApiResponse<GetMemberInfoResponse>>
@POST("/member/notification")
fun updateNotificationSettings(
@Body request: UpdateNotificationSettingRequest,
@Header("Authorization") authHeader: String
): Single<ApiResponse<Any>>
}

View File

@ -1,5 +1,6 @@
package kr.co.vividnext.sodalive.user
import kr.co.vividnext.sodalive.settings.notification.UpdateNotificationSettingRequest
import kr.co.vividnext.sodalive.user.find_password.ForgotPasswordRequest
import kr.co.vividnext.sodalive.user.login.LoginRequest
import okhttp3.MultipartBody
@ -14,4 +15,11 @@ class UserRepository(private val userApi: UserApi) {
)
fun findPassword(request: ForgotPasswordRequest) = userApi.findPassword(request = request)
fun updateNotificationSettings(
request: UpdateNotificationSettingRequest,
token: String
) = userApi.updateNotificationSettings(request, authHeader = token)
fun getMemberInfo(token: String) = userApi.getMemberInfo(authHeader = token)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 845 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 927 B

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/color_222222" />
<corners android:radius="10dp" />
<stroke
android:width="1dp"
android:color="@color/color_222222" />
</shape>

View File

@ -0,0 +1,127 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/bg_round_corner_10_222222"
android:orientation="vertical"
android:paddingVertical="20dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="13.3dp"
android:fontFamily="@font/gmarket_sans_bold"
android:gravity="center"
android:text="알림 설정"
android:textColor="@color/color_eeeeee"
android:textSize="18sp" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="16.7dp"
android:paddingStart="16.7dp"
android:paddingEnd="13.3dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:fontFamily="@font/gmarket_sans_bold"
android:text="라이브 알림"
android:textColor="@color/color_eeeeee"
android:textSize="14.7sp" />
<ImageView
android:id="@+id/iv_new_channel_live"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:contentDescription="@null"
android:src="@drawable/btn_toggle_on_big" />
</RelativeLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginHorizontal="13.3dp"
android:background="@color/color_88909090" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="16.7dp"
android:paddingStart="16.7dp"
android:paddingEnd="13.3dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:fontFamily="@font/gmarket_sans_bold"
android:text="콘텐츠 업로드 알림"
android:textColor="@color/color_eeeeee"
android:textSize="14.7sp" />
<ImageView
android:id="@+id/iv_notified_channel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:contentDescription="@null"
android:src="@drawable/btn_toggle_on_big" />
</RelativeLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginHorizontal="13.3dp"
android:background="@color/color_88909090" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingVertical="16.7dp"
android:paddingStart="16.7dp"
android:paddingEnd="13.3dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:fontFamily="@font/gmarket_sans_bold"
android:text="메시지 알림"
android:textColor="@color/color_eeeeee"
android:textSize="14.7sp" />
<ImageView
android:id="@+id/iv_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:contentDescription="@null"
android:src="@drawable/btn_toggle_on_big" />
</RelativeLayout>
<TextView
android:id="@+id/tv_confirm"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="13.3dp"
android:layout_marginTop="26.7dp"
android:background="@drawable/bg_round_corner_10_9970ff"
android:fontFamily="@font/gmarket_sans_bold"
android:gravity="center"
android:paddingVertical="16dp"
android:text="설정하기"
android:textColor="@color/white"
android:textSize="18.3sp" />
</LinearLayout>

View File

@ -15,4 +15,5 @@
<color name="color_111111">#111111</color>
<color name="color_b3909090">#B3909090</color>
<color name="color_88909090">#88909090</color>
</resources>