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

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 package kr.co.vividnext.sodalive.common
object Constants { object Constants {
const val PREF_CAN = "pref_can"
const val PREF_TOKEN = "pref_token" const val PREF_TOKEN = "pref_token"
const val PREF_EMAIL = "pref_email" const val PREF_EMAIL = "pref_email"
const val PREF_USER_ID = "pref_user_id" 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_NICKNAME = "pref_nickname"
const val PREF_USER_ROLE = "pref_user_role"
const val PREF_PROFILE_IMAGE = "pref_profile_image" const val PREF_PROFILE_IMAGE = "pref_profile_image"
const val EXTRA_DATA = "extra_data" 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.Context
import android.content.SharedPreferences import android.content.SharedPreferences
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import kr.co.vividnext.sodalive.settings.notification.MemberRole
object SharedPreferenceManager { object SharedPreferenceManager {
private lateinit var sharedPreferences: SharedPreferences private lateinit var sharedPreferences: SharedPreferences
@ -73,4 +74,22 @@ object SharedPreferenceManager {
set(value) { set(value) {
sharedPreferences[Constants.PREF_PROFILE_IMAGE] = 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 { SignUpViewModel(get()) }
viewModel { TermsViewModel(get()) } viewModel { TermsViewModel(get()) }
viewModel { FindPasswordViewModel(get()) } viewModel { FindPasswordViewModel(get()) }
viewModel { MainViewModel() } viewModel { MainViewModel(get()) }
} }
private val repositoryModule = module { 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.live.LiveFragment
import kr.co.vividnext.sodalive.message.MessageFragment import kr.co.vividnext.sodalive.message.MessageFragment
import kr.co.vividnext.sodalive.mypage.MyPageFragment import kr.co.vividnext.sodalive.mypage.MyPageFragment
import kr.co.vividnext.sodalive.settings.notification.NotificationSettingsDialog
import org.koin.android.ext.android.inject import org.koin.android.ext.android.inject
class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::inflate) { class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::inflate) {
@ -22,16 +23,30 @@ class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::infl
private lateinit var liveFragment: LiveFragment private lateinit var liveFragment: LiveFragment
private lateinit var loadingDialog: LoadingDialog private lateinit var loadingDialog: LoadingDialog
private lateinit var notificationSettingsDialog: NotificationSettingsDialog
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setupBottomTabLayout() setupBottomTabLayout()
getMemberInfo()
} }
override fun setupView() { override fun setupView() {
loadingDialog = LoadingDialog(this, layoutInflater) loadingDialog = LoadingDialog(this, layoutInflater)
liveFragment = LiveFragment() liveFragment = LiveFragment()
notificationSettingsDialog = NotificationSettingsDialog(
this,
layoutInflater
) { isNotifiedLive, isNotifiedUploadContent, isNotifiedMessage ->
viewModel.updateNotificationSettings(
isNotifiedLive,
isNotifiedUploadContent,
isNotifiedMessage
)
}
} }
private fun setupBottomTabLayout() { private fun setupBottomTabLayout() {
@ -180,4 +195,10 @@ class MainActivity : BaseActivity<ActivityMainBinding>(ActivityMainBinding::infl
fragmentTransaction.setReorderingAllowed(true) fragmentTransaction.setReorderingAllowed(true)
fragmentTransaction.commitNow() 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.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import com.google.gson.annotations.SerializedName 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.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 { enum class CurrentTab {
@SerializedName("CONTENT") @SerializedName("CONTENT")
CONTENT, CONTENT,
@ -32,4 +39,50 @@ class MainViewModel : BaseViewModel() {
_currentTab.postValue(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 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 io.reactivex.rxjava3.core.Single
import kr.co.vividnext.sodalive.common.ApiResponse 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.find_password.ForgotPasswordRequest
import kr.co.vividnext.sodalive.user.login.LoginRequest import kr.co.vividnext.sodalive.user.login.LoginRequest
import kr.co.vividnext.sodalive.user.login.LoginResponse import kr.co.vividnext.sodalive.user.login.LoginResponse
import okhttp3.MultipartBody import okhttp3.MultipartBody
import okhttp3.RequestBody import okhttp3.RequestBody
import retrofit2.http.Body import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.Multipart import retrofit2.http.Multipart
import retrofit2.http.POST import retrofit2.http.POST
import retrofit2.http.Part import retrofit2.http.Part
@ -25,4 +29,15 @@ interface UserApi {
@POST("/member/forgot-password") @POST("/member/forgot-password")
fun findPassword(@Body request: ForgotPasswordRequest): Single<ApiResponse<Any>> 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 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.find_password.ForgotPasswordRequest
import kr.co.vividnext.sodalive.user.login.LoginRequest import kr.co.vividnext.sodalive.user.login.LoginRequest
import okhttp3.MultipartBody import okhttp3.MultipartBody
@ -14,4 +15,11 @@ class UserRepository(private val userApi: UserApi) {
) )
fun findPassword(request: ForgotPasswordRequest) = userApi.findPassword(request = request) 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_111111">#111111</color>
<color name="color_b3909090">#B3909090</color> <color name="color_b3909090">#B3909090</color>
<color name="color_88909090">#88909090</color>
</resources> </resources>