mirror of
https://github.com/libre-tube/LibreTube.git
synced 2024-12-13 22:00:30 +05:30
refactor: combine submitting and voting SponsorBlock segments into one dialog
This commit is contained in:
parent
a83620206c
commit
feea8ac795
@ -1,15 +1,17 @@
|
|||||||
package com.github.libretube.ui.dialogs
|
package com.github.libretube.ui.dialogs
|
||||||
|
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
import android.content.DialogInterface
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.text.format.DateUtils
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.core.os.bundleOf
|
import android.widget.Toast
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.github.libretube.BuildConfig
|
import com.github.libretube.BuildConfig
|
||||||
import com.github.libretube.R
|
import com.github.libretube.R
|
||||||
|
import com.github.libretube.api.JsonHelper
|
||||||
import com.github.libretube.api.RetrofitInstance
|
import com.github.libretube.api.RetrofitInstance
|
||||||
|
import com.github.libretube.api.obj.Segment
|
||||||
import com.github.libretube.constants.IntentData
|
import com.github.libretube.constants.IntentData
|
||||||
import com.github.libretube.databinding.DialogSubmitSegmentBinding
|
import com.github.libretube.databinding.DialogSubmitSegmentBinding
|
||||||
import com.github.libretube.extensions.TAG
|
import com.github.libretube.extensions.TAG
|
||||||
@ -20,11 +22,16 @@ import java.lang.Exception
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import kotlinx.serialization.encodeToString
|
||||||
|
|
||||||
class SubmitSegmentDialog : DialogFragment() {
|
class SubmitSegmentDialog : DialogFragment() {
|
||||||
private var videoId: String = ""
|
private var videoId: String = ""
|
||||||
private var currentPosition: Long = 0
|
private var currentPosition: Long = 0
|
||||||
private var duration: Long? = null
|
private var duration: Long? = null
|
||||||
|
private var segments: List<Segment> = emptyList()
|
||||||
|
|
||||||
|
private var _binding: DialogSubmitSegmentBinding? = null
|
||||||
|
private val binding: DialogSubmitSegmentBinding get() = _binding!!
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@ -36,37 +43,34 @@ class SubmitSegmentDialog : DialogFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
val binding = DialogSubmitSegmentBinding.inflate(layoutInflater)
|
_binding = DialogSubmitSegmentBinding.inflate(layoutInflater)
|
||||||
|
|
||||||
|
binding.createSegment.setOnClickListener {
|
||||||
|
lifecycleScope.launch { createSegment() }
|
||||||
|
}
|
||||||
|
binding.voteSegment.setOnClickListener {
|
||||||
|
lifecycleScope.launch { voteForSegment() }
|
||||||
|
}
|
||||||
|
|
||||||
binding.startTime.setText((currentPosition.toFloat() / 1000).toString())
|
binding.startTime.setText((currentPosition.toFloat() / 1000).toString())
|
||||||
|
|
||||||
binding.segmentCategory.items = resources.getStringArray(R.array.sponsorBlockSegmentNames).toList()
|
binding.segmentCategory.items = resources.getStringArray(R.array.sponsorBlockSegmentNames).toList()
|
||||||
|
|
||||||
return MaterialAlertDialogBuilder(requireContext())
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
.setTitle(getString(R.string.sb_create_segment))
|
fetchSegments()
|
||||||
.setView(binding.root)
|
}
|
||||||
.setPositiveButton(R.string.okay, null)
|
|
||||||
.setNegativeButton(R.string.cancel, null)
|
|
||||||
.setNeutralButton(R.string.vote_for_segment) { _, _ ->
|
|
||||||
VoteForSegmentDialog().apply {
|
|
||||||
arguments = bundleOf(IntentData.videoId to videoId)
|
|
||||||
}.show(parentFragmentManager, null)
|
|
||||||
}
|
|
||||||
.show()
|
|
||||||
.apply {
|
|
||||||
getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener {
|
|
||||||
requireDialog().hide()
|
|
||||||
|
|
||||||
lifecycleScope.launch {
|
return MaterialAlertDialogBuilder(requireContext())
|
||||||
submitSegment(binding)
|
.setView(binding.root)
|
||||||
dismiss()
|
.setNegativeButton(R.string.cancel, null)
|
||||||
}
|
.show()
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun submitSegment(binding: DialogSubmitSegmentBinding) {
|
private suspend fun createSegment() {
|
||||||
val context = requireContext().applicationContext
|
val context = requireContext().applicationContext
|
||||||
|
val binding = _binding ?: return
|
||||||
|
|
||||||
|
requireDialog().hide()
|
||||||
|
|
||||||
val startTime = binding.startTime.text.toString().toFloatOrNull()
|
val startTime = binding.startTime.text.toString().toFloatOrNull()
|
||||||
var endTime = binding.endTime.text.toString().toFloatOrNull()
|
var endTime = binding.endTime.text.toString().toFloatOrNull()
|
||||||
@ -96,5 +100,69 @@ class SubmitSegmentDialog : DialogFragment() {
|
|||||||
Log.e(TAG(), e.toString())
|
Log.e(TAG(), e.toString())
|
||||||
context.toastFromMainDispatcher(e.localizedMessage.orEmpty())
|
context.toastFromMainDispatcher(e.localizedMessage.orEmpty())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
requireDialog().dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun voteForSegment() {
|
||||||
|
val binding = _binding ?: return
|
||||||
|
val context = requireContext().applicationContext
|
||||||
|
|
||||||
|
val segmentID = segments.getOrNull(binding.segmentsDropdown.selectedItemPosition)
|
||||||
|
?.uuid ?: return
|
||||||
|
|
||||||
|
// see https://wiki.sponsor.ajay.app/w/API_Docs#POST_/api/voteOnSponsorTime
|
||||||
|
val score = when {
|
||||||
|
binding.upvote.isChecked -> 1
|
||||||
|
binding.downvote.isChecked -> 0
|
||||||
|
else -> 20
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog?.hide()
|
||||||
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
RetrofitInstance.externalApi.voteOnSponsorTime(
|
||||||
|
uuid = segmentID,
|
||||||
|
userID = PreferenceHelper.getSponsorBlockUserID(),
|
||||||
|
score = score
|
||||||
|
)
|
||||||
|
context.toastFromMainDispatcher(R.string.success)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
context.toastFromMainDispatcher(e.localizedMessage.orEmpty())
|
||||||
|
}
|
||||||
|
withContext(Dispatchers.Main) { dialog?.dismiss() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun fetchSegments() {
|
||||||
|
val categories = resources.getStringArray(R.array.sponsorBlockSegments).toList()
|
||||||
|
segments = try {
|
||||||
|
RetrofitInstance.api.getSegments(videoId, JsonHelper.json.encodeToString(categories)).segments
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG(), e.toString())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
val binding = _binding ?: return@withContext
|
||||||
|
|
||||||
|
if (segments.isEmpty()) {
|
||||||
|
dismiss()
|
||||||
|
Toast.makeText(context, R.string.no_segments_found, Toast.LENGTH_SHORT).show()
|
||||||
|
return@withContext
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.segmentsDropdown.items = segments.map {
|
||||||
|
val (start, end) = it.segmentStartAndEnd
|
||||||
|
val (startStr, endStr) = DateUtils.formatElapsedTime(start.toLong()) to
|
||||||
|
DateUtils.formatElapsedTime(end.toLong())
|
||||||
|
"${it.category} ($startStr - $endStr)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroyView() {
|
||||||
|
super.onDestroyView()
|
||||||
|
_binding = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,112 +0,0 @@
|
|||||||
package com.github.libretube.ui.dialogs
|
|
||||||
|
|
||||||
import android.app.Dialog
|
|
||||||
import android.content.DialogInterface
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.text.format.DateUtils
|
|
||||||
import android.util.Log
|
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.fragment.app.DialogFragment
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import com.github.libretube.R
|
|
||||||
import com.github.libretube.api.JsonHelper
|
|
||||||
import com.github.libretube.api.RetrofitInstance
|
|
||||||
import com.github.libretube.api.obj.Segment
|
|
||||||
import com.github.libretube.constants.IntentData
|
|
||||||
import com.github.libretube.databinding.DialogVoteSegmentBinding
|
|
||||||
import com.github.libretube.extensions.TAG
|
|
||||||
import com.github.libretube.extensions.toastFromMainDispatcher
|
|
||||||
import com.github.libretube.helpers.PreferenceHelper
|
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import kotlinx.serialization.encodeToString
|
|
||||||
|
|
||||||
class VoteForSegmentDialog : DialogFragment() {
|
|
||||||
private lateinit var videoId: String
|
|
||||||
private var _binding: DialogVoteSegmentBinding? = null
|
|
||||||
private var segments: List<Segment> = listOf()
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
videoId = arguments?.getString(IntentData.videoId, "")!!
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
|
||||||
_binding = DialogVoteSegmentBinding.inflate(layoutInflater)
|
|
||||||
|
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
|
||||||
fetchSegments()
|
|
||||||
}
|
|
||||||
|
|
||||||
return MaterialAlertDialogBuilder(requireContext())
|
|
||||||
.setTitle(R.string.vote_for_segment)
|
|
||||||
.setView(_binding?.root)
|
|
||||||
.setNegativeButton(R.string.cancel, null)
|
|
||||||
.setPositiveButton(R.string.okay, null)
|
|
||||||
.show()
|
|
||||||
.apply {
|
|
||||||
getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener {
|
|
||||||
val binding = _binding ?: return@setOnClickListener
|
|
||||||
|
|
||||||
val segmentID = segments.getOrNull(binding.segmentsDropdown.selectedItemPosition)
|
|
||||||
?.uuid ?: return@setOnClickListener
|
|
||||||
|
|
||||||
// see https://wiki.sponsor.ajay.app/w/API_Docs#POST_/api/voteOnSponsorTime
|
|
||||||
val score = when {
|
|
||||||
binding.upvote.isChecked -> 1
|
|
||||||
binding.downvote.isChecked -> 0
|
|
||||||
else -> 20
|
|
||||||
}
|
|
||||||
|
|
||||||
dialog?.hide()
|
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
|
||||||
try {
|
|
||||||
RetrofitInstance.externalApi.voteOnSponsorTime(
|
|
||||||
uuid = segmentID,
|
|
||||||
userID = PreferenceHelper.getSponsorBlockUserID(),
|
|
||||||
score = score
|
|
||||||
)
|
|
||||||
context.toastFromMainDispatcher(R.string.success)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
context.toastFromMainDispatcher(e.localizedMessage.orEmpty())
|
|
||||||
}
|
|
||||||
withContext(Dispatchers.Main) { dialog?.dismiss() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun fetchSegments() {
|
|
||||||
val categories = resources.getStringArray(R.array.sponsorBlockSegments).toList()
|
|
||||||
segments = try {
|
|
||||||
RetrofitInstance.api.getSegments(videoId, JsonHelper.json.encodeToString(categories)).segments
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e(TAG(), e.toString())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
|
||||||
val binding = _binding ?: return@withContext
|
|
||||||
|
|
||||||
if (segments.isEmpty()) {
|
|
||||||
dismiss()
|
|
||||||
Toast.makeText(context, R.string.no_segments_found, Toast.LENGTH_SHORT).show()
|
|
||||||
return@withContext
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.segmentsDropdown.items = segments.map {
|
|
||||||
val (start, end) = it.segmentStartAndEnd
|
|
||||||
val (startStr, endStr) = DateUtils.formatElapsedTime(start.toLong()) to
|
|
||||||
DateUtils.formatElapsedTime(end.toLong())
|
|
||||||
"${it.category} ($startStr - $endStr)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyView() {
|
|
||||||
super.onDestroyView()
|
|
||||||
_binding = null
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +1,29 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
android:orientation="vertical"
|
||||||
android:orientation="vertical">
|
android:paddingHorizontal="15dp"
|
||||||
|
android:paddingTop="15dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/sb_create_segment"
|
||||||
|
android:textSize="24sp" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:baselineAligned="false"
|
||||||
android:baselineAligned="false">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
style="@style/CustomDialogTextInputLayout"
|
|
||||||
android:hint="@string/start_time"
|
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_weight="1">
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:hint="@string/start_time">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
android:id="@+id/start_time"
|
android:id="@+id/start_time"
|
||||||
@ -25,10 +33,11 @@
|
|||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
style="@style/CustomDialogTextInputLayout"
|
|
||||||
android:hint="@string/end_time"
|
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_weight="1">
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:hint="@string/end_time">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
android:id="@+id/end_time"
|
android:id="@+id/end_time"
|
||||||
@ -43,8 +52,66 @@
|
|||||||
android:id="@+id/segment_category"
|
android:id="@+id/segment_category"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginHorizontal="15dp"
|
|
||||||
app:hint="@string/segment_type"
|
app:hint="@string/segment_type"
|
||||||
app:icon="@drawable/ic_frame" />
|
app:icon="@drawable/ic_frame" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/create_segment"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="end"
|
||||||
|
android:drawableStart="@drawable/ic_copy"
|
||||||
|
android:text="@string/sb_create_segment" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:text="@string/vote_for_segment"
|
||||||
|
android:textSize="24sp" />
|
||||||
|
|
||||||
|
<com.github.libretube.ui.views.DropdownMenu
|
||||||
|
android:id="@+id/segments_dropdown"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:hint="@string/segment"
|
||||||
|
app:icon="@drawable/ic_frame" />
|
||||||
|
|
||||||
|
<RadioGroup
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="end"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/upvote"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="5dp"
|
||||||
|
android:checked="true"
|
||||||
|
android:text="@string/upvote" />
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/downvote"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="5dp"
|
||||||
|
android:text="@string/downvote" />
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/undo"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/undo" />
|
||||||
|
|
||||||
|
</RadioGroup>
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/vote_segment"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="end"
|
||||||
|
android:drawableStart="@drawable/ic_copy"
|
||||||
|
android:text="@string/vote_for_segment" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
@ -1,45 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingHorizontal="12dp">
|
|
||||||
|
|
||||||
<com.github.libretube.ui.views.DropdownMenu
|
|
||||||
android:id="@+id/segments_dropdown"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:hint="@string/segment"
|
|
||||||
app:icon="@drawable/ic_frame" />
|
|
||||||
|
|
||||||
<RadioGroup
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="end"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<RadioButton
|
|
||||||
android:id="@+id/upvote"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="5dp"
|
|
||||||
android:checked="true"
|
|
||||||
android:text="@string/upvote" />
|
|
||||||
|
|
||||||
<RadioButton
|
|
||||||
android:id="@+id/downvote"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="5dp"
|
|
||||||
android:text="@string/downvote" />
|
|
||||||
|
|
||||||
<RadioButton
|
|
||||||
android:id="@+id/undo"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/undo" />
|
|
||||||
|
|
||||||
</RadioGroup>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
@ -47,8 +47,8 @@
|
|||||||
|
|
||||||
<item name="android:layout_width">match_parent</item>
|
<item name="android:layout_width">match_parent</item>
|
||||||
<item name="android:layout_height">wrap_content</item>
|
<item name="android:layout_height">wrap_content</item>
|
||||||
<item name="android:layout_marginLeft">15dp</item>
|
<item name="android:layout_marginStart">15dp</item>
|
||||||
<item name="android:layout_marginRight">15dp</item>
|
<item name="android:layout_marginEnd">15dp</item>
|
||||||
<item name="android:layout_marginTop">5dp</item>
|
<item name="android:layout_marginTop">5dp</item>
|
||||||
<item name="android:layout_marginBottom">10dp</item>
|
<item name="android:layout_marginBottom">10dp</item>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user