diff --git a/app/src/main/java/kr/co/vividnext/sodalive/common/Constants.kt b/app/src/main/java/kr/co/vividnext/sodalive/common/Constants.kt index 709f06e..f71e64b 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/common/Constants.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/common/Constants.kt @@ -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" diff --git a/app/src/main/java/kr/co/vividnext/sodalive/common/SharedPreferenceManager.kt b/app/src/main/java/kr/co/vividnext/sodalive/common/SharedPreferenceManager.kt index 0a22dd0..7d1e00c 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/common/SharedPreferenceManager.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/common/SharedPreferenceManager.kt @@ -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 + } } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt b/app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt index d87429c..8e37ae9 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/di/AppDI.kt @@ -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 { diff --git a/app/src/main/java/kr/co/vividnext/sodalive/main/MainActivity.kt b/app/src/main/java/kr/co/vividnext/sodalive/main/MainActivity.kt index c8adc9a..c9be4e4 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/main/MainActivity.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/main/MainActivity.kt @@ -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::inflate) { @@ -22,16 +23,30 @@ class MainActivity : BaseActivity(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::infl fragmentTransaction.setReorderingAllowed(true) fragmentTransaction.commitNow() } + + private fun getMemberInfo() { + viewModel.getMemberInfo { + notificationSettingsDialog.show(screenWidth) + } + } } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/main/MainViewModel.kt b/app/src/main/java/kr/co/vividnext/sodalive/main/MainViewModel.kt index fb5c774..5824a03 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/main/MainViewModel.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/main/MainViewModel.kt @@ -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() + } + } + }, + {} + ) + ) + } } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/settings/notification/GetMemberInfoResponse.kt b/app/src/main/java/kr/co/vividnext/sodalive/settings/notification/GetMemberInfoResponse.kt new file mode 100644 index 0000000..02e0149 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/settings/notification/GetMemberInfoResponse.kt @@ -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, +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/settings/notification/NotificationSettingsDialog.kt b/app/src/main/java/kr/co/vividnext/sodalive/settings/notification/NotificationSettingsDialog.kt new file mode 100644 index 0000000..1e542cf --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/settings/notification/NotificationSettingsDialog.kt @@ -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 + } +} diff --git a/app/src/main/java/kr/co/vividnext/sodalive/settings/notification/UpdateNotificationSettingRequest.kt b/app/src/main/java/kr/co/vividnext/sodalive/settings/notification/UpdateNotificationSettingRequest.kt new file mode 100644 index 0000000..5cf9689 --- /dev/null +++ b/app/src/main/java/kr/co/vividnext/sodalive/settings/notification/UpdateNotificationSettingRequest.kt @@ -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 +) diff --git a/app/src/main/java/kr/co/vividnext/sodalive/user/UserApi.kt b/app/src/main/java/kr/co/vividnext/sodalive/user/UserApi.kt index bd6bddc..e340a08 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/user/UserApi.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/user/UserApi.kt @@ -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> + + @GET("/member/info") + fun getMemberInfo( + @Header("Authorization") authHeader: String + ): Single> + + @POST("/member/notification") + fun updateNotificationSettings( + @Body request: UpdateNotificationSettingRequest, + @Header("Authorization") authHeader: String + ): Single> } diff --git a/app/src/main/java/kr/co/vividnext/sodalive/user/UserRepository.kt b/app/src/main/java/kr/co/vividnext/sodalive/user/UserRepository.kt index e7508df..19d15f3 100644 --- a/app/src/main/java/kr/co/vividnext/sodalive/user/UserRepository.kt +++ b/app/src/main/java/kr/co/vividnext/sodalive/user/UserRepository.kt @@ -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) } diff --git a/app/src/main/res/drawable-xxhdpi/btn_toggle_off_big.png b/app/src/main/res/drawable-xxhdpi/btn_toggle_off_big.png new file mode 100644 index 0000000..ee6af1d Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/btn_toggle_off_big.png differ diff --git a/app/src/main/res/drawable-xxhdpi/btn_toggle_on_big.png b/app/src/main/res/drawable-xxhdpi/btn_toggle_on_big.png new file mode 100644 index 0000000..6898f8d Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/btn_toggle_on_big.png differ diff --git a/app/src/main/res/drawable/bg_round_corner_10_222222.xml b/app/src/main/res/drawable/bg_round_corner_10_222222.xml new file mode 100644 index 0000000..db787fc --- /dev/null +++ b/app/src/main/res/drawable/bg_round_corner_10_222222.xml @@ -0,0 +1,8 @@ + + + + + + diff --git a/app/src/main/res/layout/dialog_notification_settings.xml b/app/src/main/res/layout/dialog_notification_settings.xml new file mode 100644 index 0000000..3fead35 --- /dev/null +++ b/app/src/main/res/layout/dialog_notification_settings.xml @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 5cfc8c2..528c59b 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -15,4 +15,5 @@ #111111 #B3909090 + #88909090