feat: 커뮤니티 글쓰기/수정
- 이미지 gif 등록 기능 추가
This commit is contained in:
		
							
								
								
									
										35
									
								
								.idea/codeStyles/Project.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										35
									
								
								.idea/codeStyles/Project.xml
									
									
									
										generated
									
									
									
								
							@@ -1,5 +1,40 @@
 | 
				
			|||||||
<component name="ProjectCodeStyleConfiguration">
 | 
					<component name="ProjectCodeStyleConfiguration">
 | 
				
			||||||
  <code_scheme name="Project" version="173">
 | 
					  <code_scheme name="Project" version="173">
 | 
				
			||||||
 | 
					    <JavaCodeStyleSettings>
 | 
				
			||||||
 | 
					      <option name="IMPORT_LAYOUT_TABLE">
 | 
				
			||||||
 | 
					        <value>
 | 
				
			||||||
 | 
					          <package name="" withSubpackages="true" static="false" module="true" />
 | 
				
			||||||
 | 
					          <package name="android" withSubpackages="true" static="true" />
 | 
				
			||||||
 | 
					          <package name="androidx" withSubpackages="true" static="true" />
 | 
				
			||||||
 | 
					          <package name="com" withSubpackages="true" static="true" />
 | 
				
			||||||
 | 
					          <package name="junit" withSubpackages="true" static="true" />
 | 
				
			||||||
 | 
					          <package name="net" withSubpackages="true" static="true" />
 | 
				
			||||||
 | 
					          <package name="org" withSubpackages="true" static="true" />
 | 
				
			||||||
 | 
					          <package name="java" withSubpackages="true" static="true" />
 | 
				
			||||||
 | 
					          <package name="javax" withSubpackages="true" static="true" />
 | 
				
			||||||
 | 
					          <package name="" withSubpackages="true" static="true" />
 | 
				
			||||||
 | 
					          <emptyLine />
 | 
				
			||||||
 | 
					          <package name="android" withSubpackages="true" static="false" />
 | 
				
			||||||
 | 
					          <emptyLine />
 | 
				
			||||||
 | 
					          <package name="androidx" withSubpackages="true" static="false" />
 | 
				
			||||||
 | 
					          <emptyLine />
 | 
				
			||||||
 | 
					          <package name="com" withSubpackages="true" static="false" />
 | 
				
			||||||
 | 
					          <emptyLine />
 | 
				
			||||||
 | 
					          <package name="junit" withSubpackages="true" static="false" />
 | 
				
			||||||
 | 
					          <emptyLine />
 | 
				
			||||||
 | 
					          <package name="net" withSubpackages="true" static="false" />
 | 
				
			||||||
 | 
					          <emptyLine />
 | 
				
			||||||
 | 
					          <package name="org" withSubpackages="true" static="false" />
 | 
				
			||||||
 | 
					          <emptyLine />
 | 
				
			||||||
 | 
					          <package name="java" withSubpackages="true" static="false" />
 | 
				
			||||||
 | 
					          <emptyLine />
 | 
				
			||||||
 | 
					          <package name="javax" withSubpackages="true" static="false" />
 | 
				
			||||||
 | 
					          <emptyLine />
 | 
				
			||||||
 | 
					          <package name="" withSubpackages="true" static="false" />
 | 
				
			||||||
 | 
					          <emptyLine />
 | 
				
			||||||
 | 
					        </value>
 | 
				
			||||||
 | 
					      </option>
 | 
				
			||||||
 | 
					    </JavaCodeStyleSettings>
 | 
				
			||||||
    <JetCodeStyleSettings>
 | 
					    <JetCodeStyleSettings>
 | 
				
			||||||
      <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
 | 
					      <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
 | 
				
			||||||
    </JetCodeStyleSettings>
 | 
					    </JetCodeStyleSettings>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -149,6 +149,7 @@ dependencies {
 | 
				
			|||||||
    implementation "io.github.ParkSangGwon:tedpermission-normal:3.3.0"
 | 
					    implementation "io.github.ParkSangGwon:tedpermission-normal:3.3.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    implementation 'com.github.dhaval2404:imagepicker:2.1'
 | 
					    implementation 'com.github.dhaval2404:imagepicker:2.1'
 | 
				
			||||||
 | 
					    implementation 'com.github.yalantis:ucrop:2.2.10'
 | 
				
			||||||
    implementation 'com.github.zhpanvip:bannerviewpager:3.5.7'
 | 
					    implementation 'com.github.zhpanvip:bannerviewpager:3.5.7'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    implementation 'com.google.android.gms:play-services-oss-licenses:17.1.0'
 | 
					    implementation 'com.google.android.gms:play-services-oss-licenses:17.1.0'
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,18 +2,24 @@ package kr.co.vividnext.sodalive.explorer.profile.creator_community.modify
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import android.Manifest
 | 
					import android.Manifest
 | 
				
			||||||
import android.annotation.SuppressLint
 | 
					import android.annotation.SuppressLint
 | 
				
			||||||
 | 
					import android.content.Intent
 | 
				
			||||||
 | 
					import android.net.Uri
 | 
				
			||||||
import android.os.Build
 | 
					import android.os.Build
 | 
				
			||||||
import android.os.Bundle
 | 
					import android.os.Bundle
 | 
				
			||||||
import android.view.View
 | 
					import android.view.View
 | 
				
			||||||
import android.widget.Toast
 | 
					import android.widget.Toast
 | 
				
			||||||
import androidx.activity.result.contract.ActivityResultContracts
 | 
					import androidx.activity.result.contract.ActivityResultContracts
 | 
				
			||||||
import androidx.core.content.ContextCompat
 | 
					import androidx.core.content.ContextCompat
 | 
				
			||||||
import coil.load
 | 
					 | 
				
			||||||
import coil.transform.RoundedCornersTransformation
 | 
					import coil.transform.RoundedCornersTransformation
 | 
				
			||||||
 | 
					import com.bumptech.glide.Glide
 | 
				
			||||||
 | 
					import com.bumptech.glide.load.resource.bitmap.RoundedCorners
 | 
				
			||||||
 | 
					import com.bumptech.glide.request.RequestOptions
 | 
				
			||||||
import com.github.dhaval2404.imagepicker.ImagePicker
 | 
					import com.github.dhaval2404.imagepicker.ImagePicker
 | 
				
			||||||
import com.gun0912.tedpermission.PermissionListener
 | 
					import com.gun0912.tedpermission.PermissionListener
 | 
				
			||||||
import com.gun0912.tedpermission.normal.TedPermission
 | 
					import com.gun0912.tedpermission.normal.TedPermission
 | 
				
			||||||
import com.jakewharton.rxbinding4.widget.textChanges
 | 
					import com.jakewharton.rxbinding4.widget.textChanges
 | 
				
			||||||
 | 
					import com.orhanobut.logger.Logger
 | 
				
			||||||
 | 
					import com.yalantis.ucrop.UCrop
 | 
				
			||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
 | 
					import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
 | 
				
			||||||
import io.reactivex.rxjava3.schedulers.Schedulers
 | 
					import io.reactivex.rxjava3.schedulers.Schedulers
 | 
				
			||||||
import kr.co.vividnext.sodalive.R
 | 
					import kr.co.vividnext.sodalive.R
 | 
				
			||||||
@@ -26,6 +32,7 @@ import kr.co.vividnext.sodalive.databinding.ActivityCreatorCommunityModifyBindin
 | 
				
			|||||||
import kr.co.vividnext.sodalive.extensions.dpToPx
 | 
					import kr.co.vividnext.sodalive.extensions.dpToPx
 | 
				
			||||||
import kr.co.vividnext.sodalive.extensions.loadUrl
 | 
					import kr.co.vividnext.sodalive.extensions.loadUrl
 | 
				
			||||||
import org.koin.android.ext.android.inject
 | 
					import org.koin.android.ext.android.inject
 | 
				
			||||||
 | 
					import java.io.File
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class CreatorCommunityModifyActivity : BaseActivity<ActivityCreatorCommunityModifyBinding>(
 | 
					class CreatorCommunityModifyActivity : BaseActivity<ActivityCreatorCommunityModifyBinding>(
 | 
				
			||||||
    ActivityCreatorCommunityModifyBinding::inflate
 | 
					    ActivityCreatorCommunityModifyBinding::inflate
 | 
				
			||||||
@@ -34,8 +41,9 @@ class CreatorCommunityModifyActivity : BaseActivity<ActivityCreatorCommunityModi
 | 
				
			|||||||
    private val viewModel: CreatorCommunityModifyViewModel by inject()
 | 
					    private val viewModel: CreatorCommunityModifyViewModel by inject()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private lateinit var loadingDialog: LoadingDialog
 | 
					    private lateinit var loadingDialog: LoadingDialog
 | 
				
			||||||
 | 
					    private lateinit var croppedTempFile: File
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private val imageResult = registerForActivityResult(
 | 
					    private val imageCropResult = registerForActivityResult(
 | 
				
			||||||
        ActivityResultContracts.StartActivityForResult()
 | 
					        ActivityResultContracts.StartActivityForResult()
 | 
				
			||||||
    ) { result ->
 | 
					    ) { result ->
 | 
				
			||||||
        val resultCode = result.resultCode
 | 
					        val resultCode = result.resultCode
 | 
				
			||||||
@@ -45,23 +53,114 @@ class CreatorCommunityModifyActivity : BaseActivity<ActivityCreatorCommunityModi
 | 
				
			|||||||
            val fileUri = data?.data
 | 
					            val fileUri = data?.data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (fileUri != null) {
 | 
					            if (fileUri != null) {
 | 
				
			||||||
                binding.ivContent.background = null
 | 
					                handleCroppedImage(fileUri)
 | 
				
			||||||
                binding.ivContent.load(fileUri) {
 | 
					 | 
				
			||||||
                    crossfade(true)
 | 
					 | 
				
			||||||
                    placeholder(R.drawable.ic_place_holder)
 | 
					 | 
				
			||||||
                    transformations(RoundedCornersTransformation(8f.dpToPx()))
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                viewModel.imageUri = fileUri
 | 
					 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
 | 
					                showWrongImageFile()
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else if (resultCode == ImagePicker.RESULT_ERROR) {
 | 
				
			||||||
 | 
					            showImagePickerError(data = data)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private val imageSelectResult = registerForActivityResult(
 | 
				
			||||||
 | 
					        ActivityResultContracts.StartActivityForResult()
 | 
				
			||||||
 | 
					    ) { result ->
 | 
				
			||||||
 | 
					        val resultCode = result.resultCode
 | 
				
			||||||
 | 
					        val data = result.data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (resultCode == RESULT_OK) {
 | 
				
			||||||
 | 
					            val fileUri = data?.data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (fileUri != null) {
 | 
				
			||||||
 | 
					                val mime = contentResolver.getType(fileUri)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (mime.equals("image/gif", ignoreCase = true)) {
 | 
				
			||||||
 | 
					                    handleGifImage(fileUri)
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    launchCrop(fileUri)
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                showWrongImageFile()
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else if (resultCode == ImagePicker.RESULT_ERROR) {
 | 
				
			||||||
 | 
					            showImagePickerError(data = data)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun launchImagePicker() {
 | 
				
			||||||
 | 
					        ImagePicker.with(this)
 | 
				
			||||||
 | 
					            .galleryOnly()
 | 
				
			||||||
 | 
					            .createIntent { imageSelectResult.launch(it) }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun launchCrop(fileUri: Uri) {
 | 
				
			||||||
 | 
					        croppedTempFile = File.createTempFile("cropped_", ".jpg", cacheDir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val destinationUri = Uri.fromFile(croppedTempFile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val options = UCrop.Options().apply {
 | 
				
			||||||
 | 
					            setFreeStyleCropEnabled(true)
 | 
				
			||||||
 | 
					            setToolbarTitle("이미지 자르기")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val uCrop = UCrop.of(fileUri, destinationUri)
 | 
				
			||||||
 | 
					            .withOptions(options)
 | 
				
			||||||
 | 
					            .withMaxResultSize(1080, 1080)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        imageCropResult.launch(uCrop.getIntent(this))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun handleGifImage(fileUri: Uri) {
 | 
				
			||||||
 | 
					        binding.ivContent.background = null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Glide.with(this)
 | 
				
			||||||
 | 
					            .asGif()
 | 
				
			||||||
 | 
					            .load(fileUri)
 | 
				
			||||||
 | 
					            .placeholder(R.drawable.ic_place_holder)
 | 
				
			||||||
 | 
					            .apply(
 | 
				
			||||||
 | 
					                RequestOptions().transform(
 | 
				
			||||||
 | 
					                    RoundedCorners(
 | 
				
			||||||
 | 
					                        8f.dpToPx().toInt()
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .into(binding.ivContent)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        viewModel.imageUri = fileUri
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun handleCroppedImage(fileUri: Uri) {
 | 
				
			||||||
 | 
					        binding.ivContent.background = null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Glide.with(this)
 | 
				
			||||||
 | 
					            .load(fileUri)
 | 
				
			||||||
 | 
					            .placeholder(R.drawable.ic_place_holder)
 | 
				
			||||||
 | 
					            .apply(
 | 
				
			||||||
 | 
					                RequestOptions().transform(
 | 
				
			||||||
 | 
					                    RoundedCorners(
 | 
				
			||||||
 | 
					                        8f.dpToPx().toInt()
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .into(binding.ivContent)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        viewModel.imageUri = fileUri
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun showWrongImageFile() {
 | 
				
			||||||
        Toast.makeText(
 | 
					        Toast.makeText(
 | 
				
			||||||
            this,
 | 
					            this,
 | 
				
			||||||
            "잘못된 파일입니다.\n다시 선택해 주세요.",
 | 
					            "잘못된 파일입니다.\n다시 선택해 주세요.",
 | 
				
			||||||
            Toast.LENGTH_SHORT
 | 
					            Toast.LENGTH_SHORT
 | 
				
			||||||
        ).show()
 | 
					        ).show()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
        } else if (resultCode == ImagePicker.RESULT_ERROR) {
 | 
					
 | 
				
			||||||
            Toast.makeText(this, ImagePicker.getError(data), Toast.LENGTH_SHORT).show()
 | 
					    private fun showImagePickerError(data: Intent?) {
 | 
				
			||||||
        }
 | 
					        Toast.makeText(
 | 
				
			||||||
 | 
					            this,
 | 
				
			||||||
 | 
					            ImagePicker.getError(data),
 | 
				
			||||||
 | 
					            Toast.LENGTH_SHORT
 | 
				
			||||||
 | 
					        ).show()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun onCreate(savedInstanceState: Bundle?) {
 | 
					    override fun onCreate(savedInstanceState: Bundle?) {
 | 
				
			||||||
@@ -89,25 +188,32 @@ class CreatorCommunityModifyActivity : BaseActivity<ActivityCreatorCommunityModi
 | 
				
			|||||||
        )
 | 
					        )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    override fun onDestroy() {
 | 
				
			||||||
 | 
					        deleteCroppedTempFile()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        super.onDestroy()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun deleteCroppedTempFile() {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            if (::croppedTempFile.isInitialized && croppedTempFile.exists()) {
 | 
				
			||||||
 | 
					                val deleted = croppedTempFile.delete()
 | 
				
			||||||
 | 
					                if (!deleted) {
 | 
				
			||||||
 | 
					                    Logger.w("임시 파일 삭제 실패: ${croppedTempFile.absolutePath}")
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (e: Exception) {
 | 
				
			||||||
 | 
					            e.printStackTrace()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun setupView() {
 | 
					    override fun setupView() {
 | 
				
			||||||
        loadingDialog = LoadingDialog(this, layoutInflater)
 | 
					        loadingDialog = LoadingDialog(this, layoutInflater)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        binding.toolbar.tvBack.text = "게시글 등록"
 | 
					        binding.toolbar.tvBack.text = "게시글 등록"
 | 
				
			||||||
        binding.toolbar.tvBack.setOnClickListener { finish() }
 | 
					        binding.toolbar.tvBack.setOnClickListener { finish() }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        binding.ivPhotoPicker.setOnClickListener {
 | 
					        binding.ivPhotoPicker.setOnClickListener { launchImagePicker() }
 | 
				
			||||||
            ImagePicker.with(this)
 | 
					 | 
				
			||||||
                .crop()
 | 
					 | 
				
			||||||
                .galleryOnly()
 | 
					 | 
				
			||||||
                .galleryMimeTypes( // Exclude gif images
 | 
					 | 
				
			||||||
                    mimeTypes = arrayOf(
 | 
					 | 
				
			||||||
                        "image/png",
 | 
					 | 
				
			||||||
                        "image/jpg",
 | 
					 | 
				
			||||||
                        "image/jpeg"
 | 
					 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
                .createIntent { imageResult.launch(it) }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (SharedPreferenceManager.isAuth) {
 | 
					        if (SharedPreferenceManager.isAuth) {
 | 
				
			||||||
            binding.llSetAdult.visibility = View.VISIBLE
 | 
					            binding.llSetAdult.visibility = View.VISIBLE
 | 
				
			||||||
@@ -174,11 +280,17 @@ class CreatorCommunityModifyActivity : BaseActivity<ActivityCreatorCommunityModi
 | 
				
			|||||||
        viewModel.imageUrlLiveData.observe(this) {
 | 
					        viewModel.imageUrlLiveData.observe(this) {
 | 
				
			||||||
            if (!it.isNullOrBlank()) {
 | 
					            if (!it.isNullOrBlank()) {
 | 
				
			||||||
                binding.ivContent.background = null
 | 
					                binding.ivContent.background = null
 | 
				
			||||||
                binding.ivContent.loadUrl(it) {
 | 
					                Glide.with(this)
 | 
				
			||||||
                    crossfade(true)
 | 
					                    .load(it)
 | 
				
			||||||
                    placeholder(R.drawable.ic_place_holder)
 | 
					                    .placeholder(R.drawable.ic_place_holder)
 | 
				
			||||||
                    transformations(RoundedCornersTransformation(8f.dpToPx()))
 | 
					                    .apply(
 | 
				
			||||||
                }
 | 
					                        RequestOptions().transform(
 | 
				
			||||||
 | 
					                            RoundedCorners(
 | 
				
			||||||
 | 
					                                8f.dpToPx().toInt()
 | 
				
			||||||
 | 
					                            )
 | 
				
			||||||
 | 
					                        )
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .into(binding.ivContent)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,18 +2,23 @@ package kr.co.vividnext.sodalive.explorer.profile.creator_community.write
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import android.Manifest
 | 
					import android.Manifest
 | 
				
			||||||
import android.annotation.SuppressLint
 | 
					import android.annotation.SuppressLint
 | 
				
			||||||
 | 
					import android.content.Intent
 | 
				
			||||||
 | 
					import android.net.Uri
 | 
				
			||||||
import android.os.Build
 | 
					import android.os.Build
 | 
				
			||||||
import android.os.Bundle
 | 
					import android.os.Bundle
 | 
				
			||||||
import android.view.View
 | 
					import android.view.View
 | 
				
			||||||
import android.widget.Toast
 | 
					import android.widget.Toast
 | 
				
			||||||
import androidx.activity.result.contract.ActivityResultContracts
 | 
					import androidx.activity.result.contract.ActivityResultContracts
 | 
				
			||||||
import androidx.core.content.ContextCompat
 | 
					import androidx.core.content.ContextCompat
 | 
				
			||||||
import coil.load
 | 
					import com.bumptech.glide.Glide
 | 
				
			||||||
import coil.transform.RoundedCornersTransformation
 | 
					import com.bumptech.glide.load.resource.bitmap.RoundedCorners
 | 
				
			||||||
 | 
					import com.bumptech.glide.request.RequestOptions
 | 
				
			||||||
import com.github.dhaval2404.imagepicker.ImagePicker
 | 
					import com.github.dhaval2404.imagepicker.ImagePicker
 | 
				
			||||||
import com.gun0912.tedpermission.PermissionListener
 | 
					import com.gun0912.tedpermission.PermissionListener
 | 
				
			||||||
import com.gun0912.tedpermission.normal.TedPermission
 | 
					import com.gun0912.tedpermission.normal.TedPermission
 | 
				
			||||||
import com.jakewharton.rxbinding4.widget.textChanges
 | 
					import com.jakewharton.rxbinding4.widget.textChanges
 | 
				
			||||||
 | 
					import com.orhanobut.logger.Logger
 | 
				
			||||||
 | 
					import com.yalantis.ucrop.UCrop
 | 
				
			||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
 | 
					import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
 | 
				
			||||||
import io.reactivex.rxjava3.schedulers.Schedulers
 | 
					import io.reactivex.rxjava3.schedulers.Schedulers
 | 
				
			||||||
import kr.co.vividnext.sodalive.R
 | 
					import kr.co.vividnext.sodalive.R
 | 
				
			||||||
@@ -33,8 +38,9 @@ class CreatorCommunityWriteActivity : BaseActivity<ActivityCreatorCommunityWrite
 | 
				
			|||||||
    private val viewModel: CreatorCommunityWriteViewModel by inject()
 | 
					    private val viewModel: CreatorCommunityWriteViewModel by inject()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private lateinit var loadingDialog: LoadingDialog
 | 
					    private lateinit var loadingDialog: LoadingDialog
 | 
				
			||||||
 | 
					    private lateinit var croppedTempFile: File
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private val imageResult = registerForActivityResult(
 | 
					    private val imageCropResult = registerForActivityResult(
 | 
				
			||||||
        ActivityResultContracts.StartActivityForResult()
 | 
					        ActivityResultContracts.StartActivityForResult()
 | 
				
			||||||
    ) { result ->
 | 
					    ) { result ->
 | 
				
			||||||
        val resultCode = result.resultCode
 | 
					        val resultCode = result.resultCode
 | 
				
			||||||
@@ -44,17 +50,103 @@ class CreatorCommunityWriteActivity : BaseActivity<ActivityCreatorCommunityWrite
 | 
				
			|||||||
            val fileUri = data?.data
 | 
					            val fileUri = data?.data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (fileUri != null) {
 | 
					            if (fileUri != null) {
 | 
				
			||||||
                binding.ivContent.background = null
 | 
					                handleCroppedImage(fileUri)
 | 
				
			||||||
                binding.ivContent.load(fileUri) {
 | 
					            } else {
 | 
				
			||||||
                    crossfade(true)
 | 
					                showWrongImageFile()
 | 
				
			||||||
                    placeholder(R.drawable.ic_place_holder)
 | 
					            }
 | 
				
			||||||
                    transformations(RoundedCornersTransformation(8f.dpToPx()))
 | 
					        } else if (resultCode == ImagePicker.RESULT_ERROR) {
 | 
				
			||||||
 | 
					            showImagePickerError(data = data)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                viewModel.setImageUri(fileUri)
 | 
					    private val imageSelectResult = registerForActivityResult(
 | 
				
			||||||
 | 
					        ActivityResultContracts.StartActivityForResult()
 | 
				
			||||||
 | 
					    ) { result ->
 | 
				
			||||||
 | 
					        val resultCode = result.resultCode
 | 
				
			||||||
 | 
					        val data = result.data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                binding.llRecordAudio.visibility = View.VISIBLE
 | 
					        if (resultCode == RESULT_OK) {
 | 
				
			||||||
 | 
					            val fileUri = data?.data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (fileUri != null) {
 | 
				
			||||||
 | 
					                val mime = contentResolver.getType(fileUri)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (mime.equals("image/gif", ignoreCase = true)) {
 | 
				
			||||||
 | 
					                    handleGifImage(fileUri)
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
 | 
					                    launchCrop(fileUri)
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                showWrongImageFile()
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else if (resultCode == ImagePicker.RESULT_ERROR) {
 | 
				
			||||||
 | 
					            showImagePickerError(data = data)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun launchImagePicker() {
 | 
				
			||||||
 | 
					        ImagePicker.with(this)
 | 
				
			||||||
 | 
					            .galleryOnly()
 | 
				
			||||||
 | 
					            .createIntent { imageSelectResult.launch(it) }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun launchCrop(fileUri: Uri) {
 | 
				
			||||||
 | 
					        croppedTempFile = File.createTempFile("cropped_", ".jpg", cacheDir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val destinationUri = Uri.fromFile(croppedTempFile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val options = UCrop.Options().apply {
 | 
				
			||||||
 | 
					            setFreeStyleCropEnabled(true)
 | 
				
			||||||
 | 
					            setToolbarTitle("이미지 자르기")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        val uCrop = UCrop.of(fileUri, destinationUri)
 | 
				
			||||||
 | 
					            .withOptions(options)
 | 
				
			||||||
 | 
					            .withMaxResultSize(1080, 1080)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        imageCropResult.launch(uCrop.getIntent(this))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun handleGifImage(fileUri: Uri) {
 | 
				
			||||||
 | 
					        binding.llRecordAudio.visibility = View.VISIBLE
 | 
				
			||||||
 | 
					        binding.ivContent.background = null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Glide.with(this)
 | 
				
			||||||
 | 
					            .asGif()
 | 
				
			||||||
 | 
					            .load(fileUri)
 | 
				
			||||||
 | 
					            .placeholder(R.drawable.ic_place_holder)
 | 
				
			||||||
 | 
					            .apply(
 | 
				
			||||||
 | 
					                RequestOptions().transform(
 | 
				
			||||||
 | 
					                    RoundedCorners(
 | 
				
			||||||
 | 
					                        8f.dpToPx().toInt()
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .into(binding.ivContent)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        viewModel.setImageUri(fileUri)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun handleCroppedImage(fileUri: Uri) {
 | 
				
			||||||
 | 
					        binding.llRecordAudio.visibility = View.VISIBLE
 | 
				
			||||||
 | 
					        binding.ivContent.background = null
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Glide.with(this)
 | 
				
			||||||
 | 
					            .load(fileUri)
 | 
				
			||||||
 | 
					            .placeholder(R.drawable.ic_place_holder)
 | 
				
			||||||
 | 
					            .apply(
 | 
				
			||||||
 | 
					                RequestOptions().transform(
 | 
				
			||||||
 | 
					                    RoundedCorners(
 | 
				
			||||||
 | 
					                        8f.dpToPx().toInt()
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .into(binding.ivContent)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        viewModel.setImageUri(fileUri)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun showWrongImageFile() {
 | 
				
			||||||
        binding.llRecordAudio.visibility = View.GONE
 | 
					        binding.llRecordAudio.visibility = View.GONE
 | 
				
			||||||
        Toast.makeText(
 | 
					        Toast.makeText(
 | 
				
			||||||
            this,
 | 
					            this,
 | 
				
			||||||
@@ -62,10 +154,14 @@ class CreatorCommunityWriteActivity : BaseActivity<ActivityCreatorCommunityWrite
 | 
				
			|||||||
            Toast.LENGTH_SHORT
 | 
					            Toast.LENGTH_SHORT
 | 
				
			||||||
        ).show()
 | 
					        ).show()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
        } else if (resultCode == ImagePicker.RESULT_ERROR) {
 | 
					
 | 
				
			||||||
 | 
					    private fun showImagePickerError(data: Intent?) {
 | 
				
			||||||
        binding.llRecordAudio.visibility = View.GONE
 | 
					        binding.llRecordAudio.visibility = View.GONE
 | 
				
			||||||
            Toast.makeText(this, ImagePicker.getError(data), Toast.LENGTH_SHORT).show()
 | 
					        Toast.makeText(
 | 
				
			||||||
        }
 | 
					            this,
 | 
				
			||||||
 | 
					            ImagePicker.getError(data),
 | 
				
			||||||
 | 
					            Toast.LENGTH_SHORT
 | 
				
			||||||
 | 
					        ).show()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun onCreate(savedInstanceState: Bundle?) {
 | 
					    override fun onCreate(savedInstanceState: Bundle?) {
 | 
				
			||||||
@@ -81,6 +177,9 @@ class CreatorCommunityWriteActivity : BaseActivity<ActivityCreatorCommunityWrite
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    override fun onDestroy() {
 | 
					    override fun onDestroy() {
 | 
				
			||||||
        deleteAudioFile()
 | 
					        deleteAudioFile()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        deleteCroppedTempFile()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        super.onDestroy()
 | 
					        super.onDestroy()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -90,6 +189,19 @@ class CreatorCommunityWriteActivity : BaseActivity<ActivityCreatorCommunityWrite
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun deleteCroppedTempFile() {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            if (::croppedTempFile.isInitialized && croppedTempFile.exists()) {
 | 
				
			||||||
 | 
					                val deleted = croppedTempFile.delete()
 | 
				
			||||||
 | 
					                if (!deleted) {
 | 
				
			||||||
 | 
					                    Logger.w("임시 파일 삭제 실패: ${croppedTempFile.absolutePath}")
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (e: Exception) {
 | 
				
			||||||
 | 
					            e.printStackTrace()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    override fun setupView() {
 | 
					    override fun setupView() {
 | 
				
			||||||
        loadingDialog = LoadingDialog(this, layoutInflater)
 | 
					        loadingDialog = LoadingDialog(this, layoutInflater)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -102,19 +214,7 @@ class CreatorCommunityWriteActivity : BaseActivity<ActivityCreatorCommunityWrite
 | 
				
			|||||||
            fragment.show(supportFragmentManager, fragment.tag)
 | 
					            fragment.show(supportFragmentManager, fragment.tag)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        binding.ivPhotoPicker.setOnClickListener {
 | 
					        binding.ivPhotoPicker.setOnClickListener { launchImagePicker() }
 | 
				
			||||||
            ImagePicker.with(this)
 | 
					 | 
				
			||||||
                .crop()
 | 
					 | 
				
			||||||
                .galleryOnly()
 | 
					 | 
				
			||||||
                .galleryMimeTypes( // Exclude gif images
 | 
					 | 
				
			||||||
                    mimeTypes = arrayOf(
 | 
					 | 
				
			||||||
                        "image/png",
 | 
					 | 
				
			||||||
                        "image/jpg",
 | 
					 | 
				
			||||||
                        "image/jpeg"
 | 
					 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
                .createIntent { imageResult.launch(it) }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (SharedPreferenceManager.isAuth) {
 | 
					        if (SharedPreferenceManager.isAuth) {
 | 
				
			||||||
            binding.llSetAdult.visibility = View.VISIBLE
 | 
					            binding.llSetAdult.visibility = View.VISIBLE
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,20 +41,28 @@
 | 
				
			|||||||
                    android:textColor="@color/color_eeeeee"
 | 
					                    android:textColor="@color/color_eeeeee"
 | 
				
			||||||
                    android:textSize="16.7sp" />
 | 
					                    android:textSize="16.7sp" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <RelativeLayout
 | 
					                <androidx.constraintlayout.widget.ConstraintLayout
 | 
				
			||||||
                    android:layout_width="121.3dp"
 | 
					                    android:layout_width="wrap_content"
 | 
				
			||||||
                    android:layout_height="106.7dp"
 | 
					                    android:layout_height="wrap_content"
 | 
				
			||||||
                    android:layout_marginTop="13.3dp">
 | 
					                    android:layout_marginTop="13.3dp">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    <ImageView
 | 
					                    <ImageView
 | 
				
			||||||
                        android:id="@+id/iv_content"
 | 
					                        android:id="@+id/iv_content"
 | 
				
			||||||
                        android:layout_width="106.7dp"
 | 
					                        android:layout_width="wrap_content"
 | 
				
			||||||
                        android:layout_height="106.7dp"
 | 
					                        android:layout_height="wrap_content"
 | 
				
			||||||
                        android:adjustViewBounds="true"
 | 
					                        android:adjustViewBounds="true"
 | 
				
			||||||
                        android:background="@drawable/bg_round_corner_8_13181b"
 | 
					                        android:background="@drawable/bg_round_corner_8_13181b"
 | 
				
			||||||
                        android:contentDescription="@null"
 | 
					                        android:contentDescription="@null"
 | 
				
			||||||
 | 
					                        android:maxWidth="300dp"
 | 
				
			||||||
 | 
					                        android:maxHeight="300dp"
 | 
				
			||||||
 | 
					                        android:minWidth="106.7dp"
 | 
				
			||||||
 | 
					                        android:minHeight="106.7dp"
 | 
				
			||||||
                        android:padding="13.3dp"
 | 
					                        android:padding="13.3dp"
 | 
				
			||||||
                        android:src="@drawable/ic_logo2" />
 | 
					                        android:src="@drawable/ic_logo2"
 | 
				
			||||||
 | 
					                        app:layout_constraintBottom_toBottomOf="parent"
 | 
				
			||||||
 | 
					                        app:layout_constraintEnd_toEndOf="parent"
 | 
				
			||||||
 | 
					                        app:layout_constraintStart_toStartOf="parent"
 | 
				
			||||||
 | 
					                        app:layout_constraintTop_toTopOf="parent" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    <ImageView
 | 
					                    <ImageView
 | 
				
			||||||
                        android:id="@+id/iv_photo_picker"
 | 
					                        android:id="@+id/iv_photo_picker"
 | 
				
			||||||
@@ -62,11 +70,15 @@
 | 
				
			|||||||
                        android:layout_height="wrap_content"
 | 
					                        android:layout_height="wrap_content"
 | 
				
			||||||
                        android:layout_alignParentEnd="true"
 | 
					                        android:layout_alignParentEnd="true"
 | 
				
			||||||
                        android:layout_alignParentBottom="true"
 | 
					                        android:layout_alignParentBottom="true"
 | 
				
			||||||
 | 
					                        android:layout_marginStart="-20dp"
 | 
				
			||||||
                        android:background="@drawable/bg_round_corner_33_3_3bb9f1"
 | 
					                        android:background="@drawable/bg_round_corner_33_3_3bb9f1"
 | 
				
			||||||
                        android:contentDescription="@null"
 | 
					                        android:contentDescription="@null"
 | 
				
			||||||
                        android:padding="10dp"
 | 
					                        android:padding="10dp"
 | 
				
			||||||
                        android:src="@drawable/ic_camera" />
 | 
					                        android:src="@drawable/ic_camera"
 | 
				
			||||||
                </RelativeLayout>
 | 
					                        app:layout_constraintBottom_toBottomOf="@+id/iv_content"
 | 
				
			||||||
 | 
					                        app:layout_constraintStart_toEndOf="@+id/iv_content" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                </androidx.constraintlayout.widget.ConstraintLayout>
 | 
				
			||||||
            </LinearLayout>
 | 
					            </LinearLayout>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            <LinearLayout
 | 
					            <LinearLayout
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,20 +41,28 @@
 | 
				
			|||||||
                    android:textColor="@color/color_eeeeee"
 | 
					                    android:textColor="@color/color_eeeeee"
 | 
				
			||||||
                    android:textSize="16.7sp" />
 | 
					                    android:textSize="16.7sp" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <RelativeLayout
 | 
					                <androidx.constraintlayout.widget.ConstraintLayout
 | 
				
			||||||
                    android:layout_width="121.3dp"
 | 
					                    android:layout_width="wrap_content"
 | 
				
			||||||
                    android:layout_height="106.7dp"
 | 
					                    android:layout_height="wrap_content"
 | 
				
			||||||
                    android:layout_marginTop="13.3dp">
 | 
					                    android:layout_marginTop="13.3dp">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    <ImageView
 | 
					                    <ImageView
 | 
				
			||||||
                        android:id="@+id/iv_content"
 | 
					                        android:id="@+id/iv_content"
 | 
				
			||||||
                        android:layout_width="106.7dp"
 | 
					                        android:layout_width="wrap_content"
 | 
				
			||||||
                        android:layout_height="106.7dp"
 | 
					                        android:layout_height="wrap_content"
 | 
				
			||||||
                        android:adjustViewBounds="true"
 | 
					                        android:adjustViewBounds="true"
 | 
				
			||||||
                        android:background="@drawable/bg_round_corner_8_13181b"
 | 
					                        android:background="@drawable/bg_round_corner_8_13181b"
 | 
				
			||||||
                        android:contentDescription="@null"
 | 
					                        android:contentDescription="@null"
 | 
				
			||||||
 | 
					                        android:maxWidth="300dp"
 | 
				
			||||||
 | 
					                        android:maxHeight="300dp"
 | 
				
			||||||
 | 
					                        android:minWidth="106.7dp"
 | 
				
			||||||
 | 
					                        android:minHeight="106.7dp"
 | 
				
			||||||
                        android:padding="13.3dp"
 | 
					                        android:padding="13.3dp"
 | 
				
			||||||
                        android:src="@drawable/ic_logo2" />
 | 
					                        android:src="@drawable/ic_logo2"
 | 
				
			||||||
 | 
					                        app:layout_constraintBottom_toBottomOf="parent"
 | 
				
			||||||
 | 
					                        app:layout_constraintEnd_toEndOf="parent"
 | 
				
			||||||
 | 
					                        app:layout_constraintStart_toStartOf="parent"
 | 
				
			||||||
 | 
					                        app:layout_constraintTop_toTopOf="parent" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    <ImageView
 | 
					                    <ImageView
 | 
				
			||||||
                        android:id="@+id/iv_photo_picker"
 | 
					                        android:id="@+id/iv_photo_picker"
 | 
				
			||||||
@@ -62,11 +70,15 @@
 | 
				
			|||||||
                        android:layout_height="wrap_content"
 | 
					                        android:layout_height="wrap_content"
 | 
				
			||||||
                        android:layout_alignParentEnd="true"
 | 
					                        android:layout_alignParentEnd="true"
 | 
				
			||||||
                        android:layout_alignParentBottom="true"
 | 
					                        android:layout_alignParentBottom="true"
 | 
				
			||||||
 | 
					                        android:layout_marginStart="-20dp"
 | 
				
			||||||
                        android:background="@drawable/bg_round_corner_33_3_3bb9f1"
 | 
					                        android:background="@drawable/bg_round_corner_33_3_3bb9f1"
 | 
				
			||||||
                        android:contentDescription="@null"
 | 
					                        android:contentDescription="@null"
 | 
				
			||||||
                        android:padding="10dp"
 | 
					                        android:padding="10dp"
 | 
				
			||||||
                        android:src="@drawable/ic_camera" />
 | 
					                        android:src="@drawable/ic_camera"
 | 
				
			||||||
                </RelativeLayout>
 | 
					                        app:layout_constraintBottom_toBottomOf="@+id/iv_content"
 | 
				
			||||||
 | 
					                        app:layout_constraintStart_toEndOf="@+id/iv_content" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                </androidx.constraintlayout.widget.ConstraintLayout>
 | 
				
			||||||
            </LinearLayout>
 | 
					            </LinearLayout>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            <LinearLayout
 | 
					            <LinearLayout
 | 
				
			||||||
@@ -98,8 +110,8 @@
 | 
				
			|||||||
                android:id="@+id/ll_record_audio"
 | 
					                android:id="@+id/ll_record_audio"
 | 
				
			||||||
                android:layout_width="match_parent"
 | 
					                android:layout_width="match_parent"
 | 
				
			||||||
                android:layout_height="wrap_content"
 | 
					                android:layout_height="wrap_content"
 | 
				
			||||||
                android:gravity="center"
 | 
					 | 
				
			||||||
                android:layout_marginTop="24dp"
 | 
					                android:layout_marginTop="24dp"
 | 
				
			||||||
 | 
					                android:gravity="center"
 | 
				
			||||||
                android:orientation="vertical"
 | 
					                android:orientation="vertical"
 | 
				
			||||||
                android:visibility="gone">
 | 
					                android:visibility="gone">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -129,8 +141,8 @@
 | 
				
			|||||||
                <LinearLayout
 | 
					                <LinearLayout
 | 
				
			||||||
                    android:layout_width="match_parent"
 | 
					                    android:layout_width="match_parent"
 | 
				
			||||||
                    android:layout_height="wrap_content"
 | 
					                    android:layout_height="wrap_content"
 | 
				
			||||||
                    android:gravity="center_horizontal"
 | 
					 | 
				
			||||||
                    android:layout_marginTop="13.3dp"
 | 
					                    android:layout_marginTop="13.3dp"
 | 
				
			||||||
 | 
					                    android:gravity="center_horizontal"
 | 
				
			||||||
                    android:orientation="horizontal">
 | 
					                    android:orientation="horizontal">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    <TextView
 | 
					                    <TextView
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user