회원가입 후 초기 알림설정 기능 추가
This commit is contained in:
		| @@ -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" | ||||
|   | ||||
| @@ -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 | ||||
|         } | ||||
| } | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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() | ||||
|                             } | ||||
|                         } | ||||
|                     }, | ||||
|                     {} | ||||
|                 ) | ||||
|         ) | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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, | ||||
| } | ||||
| @@ -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 | ||||
|     } | ||||
| } | ||||
| @@ -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 | ||||
| ) | ||||
| @@ -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>> | ||||
| } | ||||
|   | ||||
| @@ -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) | ||||
| } | ||||
|   | ||||
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/drawable-xxhdpi/btn_toggle_off_big.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/src/main/res/drawable-xxhdpi/btn_toggle_off_big.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 845 B | 
							
								
								
									
										
											BIN
										
									
								
								app/src/main/res/drawable-xxhdpi/btn_toggle_on_big.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								app/src/main/res/drawable-xxhdpi/btn_toggle_on_big.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 927 B | 
							
								
								
									
										8
									
								
								app/src/main/res/drawable/bg_round_corner_10_222222.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								app/src/main/res/drawable/bg_round_corner_10_222222.xml
									
									
									
									
									
										Normal 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> | ||||
							
								
								
									
										127
									
								
								app/src/main/res/layout/dialog_notification_settings.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								app/src/main/res/layout/dialog_notification_settings.xml
									
									
									
									
									
										Normal 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> | ||||
| @@ -15,4 +15,5 @@ | ||||
|     <color name="color_111111">#111111</color> | ||||
|  | ||||
|     <color name="color_b3909090">#B3909090</color> | ||||
|     <color name="color_88909090">#88909090</color> | ||||
| </resources> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user