sforkowany z mirror/meshtastic-android
rodzic
87cc382416
commit
07cc8ce701
|
@ -0,0 +1,3 @@
|
||||||
|
package com.geeksville.mesh.model.map
|
||||||
|
|
||||||
|
data class ChildData(val childTitle: String)
|
|
@ -0,0 +1,6 @@
|
||||||
|
package com.geeksville.mesh.model.map
|
||||||
|
|
||||||
|
object Constants {
|
||||||
|
const val PARENT = 0
|
||||||
|
const val CHILD = 1
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package com.geeksville.mesh.model.map
|
||||||
|
|
||||||
|
data class MapParentData(
|
||||||
|
val title: String? = null,
|
||||||
|
var type:Int = Constants.PARENT,
|
||||||
|
var subList: MutableList<ChildData> = ArrayList(),
|
||||||
|
var isExpanded: Boolean = false
|
||||||
|
)
|
|
@ -15,19 +15,20 @@ import android.widget.*
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.geeksville.mesh.BuildConfig
|
import com.geeksville.mesh.BuildConfig
|
||||||
import com.geeksville.mesh.NodeInfo
|
import com.geeksville.mesh.NodeInfo
|
||||||
import com.geeksville.mesh.R
|
import com.geeksville.mesh.R
|
||||||
import com.geeksville.mesh.android.Logging
|
import com.geeksville.mesh.android.Logging
|
||||||
import com.geeksville.mesh.database.entity.Packet
|
import com.geeksville.mesh.database.entity.Packet
|
||||||
import com.geeksville.mesh.databinding.AdapterMapMenuSelectionBinding
|
import com.geeksville.mesh.databinding.MapMenuLayoutBinding
|
||||||
import com.geeksville.mesh.databinding.MapMenuBinding
|
|
||||||
import com.geeksville.mesh.databinding.MapViewBinding
|
import com.geeksville.mesh.databinding.MapViewBinding
|
||||||
import com.geeksville.mesh.model.UIViewModel
|
import com.geeksville.mesh.model.UIViewModel
|
||||||
|
import com.geeksville.mesh.model.map.ChildData
|
||||||
import com.geeksville.mesh.model.map.CustomOverlayManager
|
import com.geeksville.mesh.model.map.CustomOverlayManager
|
||||||
import com.geeksville.mesh.model.map.CustomTileSource
|
import com.geeksville.mesh.model.map.CustomTileSource
|
||||||
|
import com.geeksville.mesh.model.map.MapParentData
|
||||||
import com.geeksville.mesh.util.SqlTileWriterExt
|
import com.geeksville.mesh.util.SqlTileWriterExt
|
||||||
import com.geeksville.mesh.util.SqlTileWriterExt.SourceCount
|
|
||||||
import com.geeksville.mesh.util.formatAgo
|
import com.geeksville.mesh.util.formatAgo
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
@ -93,7 +94,6 @@ class MapFragment : ScreenFragment("Map"), Logging, View.OnClickListener {
|
||||||
private lateinit var cacheManager: CacheManager
|
private lateinit var cacheManager: CacheManager
|
||||||
private lateinit var downloadRegionBoundingBox: BoundingBox
|
private lateinit var downloadRegionBoundingBox: BoundingBox
|
||||||
|
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||||
): View {
|
): View {
|
||||||
|
@ -185,18 +185,6 @@ class MapFragment : ScreenFragment("Map"), Logging, View.OnClickListener {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears active tile source cache
|
|
||||||
*/
|
|
||||||
private fun clearCache() {
|
|
||||||
val b: Boolean = SqlTileWriter().purgeCache()
|
|
||||||
SqlTileWriter().onDetach()
|
|
||||||
val title = if (b) "SQL Cache purged" else "SQL Cache purge failed, see logcat for details"
|
|
||||||
val length = if (b) Toast.LENGTH_SHORT else Toast.LENGTH_LONG
|
|
||||||
Toast.makeText(activity, title, length).show()
|
|
||||||
alertDialog!!.dismiss()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun purgeTileSource() {
|
private fun purgeTileSource() {
|
||||||
cache = SqlTileWriterExt()
|
cache = SqlTileWriterExt()
|
||||||
val builder = AlertDialog.Builder(context)
|
val builder = AlertDialog.Builder(context)
|
||||||
|
@ -408,26 +396,31 @@ class MapFragment : ScreenFragment("Map"), Logging, View.OnClickListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun chooseMapStyle() {
|
private fun chooseMapStyle() {
|
||||||
val mapMenu = MapMenuBinding.inflate(layoutInflater, view as ViewGroup, true)
|
/// Prepare dialog and its items
|
||||||
val layoutManager = LinearLayoutManager(requireContext())
|
val mapStyles by lazy { resources.getStringArray(R.array.map_styles) }
|
||||||
val adapterMenuSelection = AdapterMapMenuSelectionBinding.inflate(layoutInflater)
|
|
||||||
val adapter = MapStyleAdapter(adapterMenuSelection)
|
|
||||||
mapMenu.mapLayerRecyclerView.adapter =
|
|
||||||
adapter.mapStyleAdapater
|
|
||||||
mapMenu.mapTypeRecyclerView.layoutManager = layoutManager
|
|
||||||
mapMenu.mapTypeRecyclerView.adapter = adapter.mapLayerAdapater
|
|
||||||
|
|
||||||
|
val builder = MaterialAlertDialogBuilder(context!!)
|
||||||
|
val listData: MutableList<MapParentData> = ArrayList()
|
||||||
|
val parentData: Array<String> = arrayOf("Map Source", "Map Layer")
|
||||||
|
val mapStyleData: MutableList<ChildData> = mutableListOf()
|
||||||
|
mapStyles.forEach { style ->
|
||||||
|
mapStyleData.add(ChildData(style))
|
||||||
|
}
|
||||||
|
val mapLayerData: MutableList<ChildData> = mutableListOf(ChildData("test"))
|
||||||
|
|
||||||
// /// Prepare dialog and its items
|
val mapStyleObj = MapParentData(title = parentData[0], subList = mapStyleData)
|
||||||
// val builder = MaterialAlertDialogBuilder(context!!)
|
val mapLayerObj = MapParentData(title = parentData[1], subList = mapLayerData)
|
||||||
// builder.setTitle(getString(R.string.preferences_map_style))
|
listData.add(mapStyleObj)
|
||||||
// val mapStyles by lazy { resources.getStringArray(R.array.map_styles) }
|
listData.add(mapLayerObj)
|
||||||
//
|
val exRecycleView = MapMenuLayoutBinding.inflate(layoutInflater)
|
||||||
// /// Load preferences and its value
|
exRecycleView.exRecycle.layoutManager = LinearLayoutManager(context)
|
||||||
// val editor: SharedPreferences.Editor = mPrefs.edit()
|
exRecycleView.exRecycle.adapter = MapMenuRecyclerAdapter(context!!, listData)
|
||||||
// val mapStyleInt = mPrefs.getInt(mapStyleId, 1)
|
|
||||||
// debug("mapStyleId from prefs: $mapStyleInt")
|
builder.setView(exRecycleView.root)
|
||||||
//
|
/// Load preferences and its value
|
||||||
|
val editor: SharedPreferences.Editor = mPrefs.edit()
|
||||||
|
val mapStyleInt = mPrefs.getInt(mapStyleId, 1)
|
||||||
|
debug("mapStyleId from prefs: $mapStyleInt")
|
||||||
// builder.setSingleChoiceItems(mapStyles, mapStyleInt) { dialog, which ->
|
// builder.setSingleChoiceItems(mapStyles, mapStyleInt) { dialog, which ->
|
||||||
// debug("Set mapStyleId pref to $which")
|
// debug("Set mapStyleId pref to $which")
|
||||||
// editor.putInt(mapStyleId, which)
|
// editor.putInt(mapStyleId, which)
|
||||||
|
@ -437,8 +430,8 @@ class MapFragment : ScreenFragment("Map"), Logging, View.OnClickListener {
|
||||||
// renderDownloadButton()
|
// renderDownloadButton()
|
||||||
// drawOverlays()
|
// drawOverlays()
|
||||||
// }
|
// }
|
||||||
// val dialog = builder.create()
|
val dialog = builder.create()
|
||||||
// dialog.show()
|
dialog.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun renderDownloadButton() {
|
private fun renderDownloadButton() {
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
package com.geeksville.mesh.ui
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.geeksville.mesh.R
|
||||||
|
import com.geeksville.mesh.model.map.ChildData
|
||||||
|
import com.geeksville.mesh.model.map.Constants
|
||||||
|
import com.geeksville.mesh.model.map.MapParentData
|
||||||
|
|
||||||
|
class MapMenuRecyclerAdapter(var mContext: Context, val list: MutableList<MapParentData>) :
|
||||||
|
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
|
|
||||||
|
return if (viewType == Constants.PARENT) {
|
||||||
|
val rowView: View =
|
||||||
|
LayoutInflater.from(parent.context).inflate(R.layout.parent_row, parent, false)
|
||||||
|
GroupViewHolder(rowView)
|
||||||
|
} else {
|
||||||
|
val rowView: View =
|
||||||
|
LayoutInflater.from(parent.context).inflate(R.layout.child_row, parent, false)
|
||||||
|
ChildViewHolder(rowView)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int = list.size
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||||
|
|
||||||
|
val dataList = list[position]
|
||||||
|
if (dataList.type == Constants.PARENT) {
|
||||||
|
holder as GroupViewHolder
|
||||||
|
holder.apply {
|
||||||
|
parentTV?.text = dataList.title
|
||||||
|
downIV?.setOnClickListener {
|
||||||
|
expandOrCollapseParentItem(dataList, position)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
holder as ChildViewHolder
|
||||||
|
|
||||||
|
holder.apply {
|
||||||
|
val singleService = dataList.subList.first()
|
||||||
|
childTV?.text = singleService.childTitle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun expandOrCollapseParentItem(singleBoarding: MapParentData, position: Int) {
|
||||||
|
|
||||||
|
if (singleBoarding.isExpanded) {
|
||||||
|
collapseParentRow(position)
|
||||||
|
} else {
|
||||||
|
expandParentRow(position)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun expandParentRow(position: Int) {
|
||||||
|
val currentBoardingRow = list[position]
|
||||||
|
val services = currentBoardingRow.subList
|
||||||
|
currentBoardingRow.isExpanded = true
|
||||||
|
var nextPosition = position
|
||||||
|
if (currentBoardingRow.type == Constants.PARENT) {
|
||||||
|
|
||||||
|
services.forEach { service ->
|
||||||
|
val parentModel = MapParentData()
|
||||||
|
parentModel.type = Constants.CHILD
|
||||||
|
val subList: ArrayList<ChildData> = ArrayList()
|
||||||
|
subList.add(service)
|
||||||
|
parentModel.subList = subList
|
||||||
|
list.add(++nextPosition, parentModel)
|
||||||
|
}
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun collapseParentRow(position: Int) {
|
||||||
|
val currentBoardingRow = list[position]
|
||||||
|
val services = currentBoardingRow.subList
|
||||||
|
list[position].isExpanded = false
|
||||||
|
if (list[position].type == Constants.PARENT) {
|
||||||
|
services.forEach { _ ->
|
||||||
|
list.removeAt(position + 1)
|
||||||
|
}
|
||||||
|
notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemViewType(position: Int): Int = list[position].type
|
||||||
|
|
||||||
|
override fun getItemId(position: Int): Long {
|
||||||
|
return position.toLong()
|
||||||
|
}
|
||||||
|
|
||||||
|
class GroupViewHolder(row: View) : RecyclerView.ViewHolder(row) {
|
||||||
|
val parentTV = row.findViewById(R.id.parent_Title) as TextView?
|
||||||
|
val downIV = row.findViewById(R.id.down_iv) as ImageView?
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChildViewHolder(row: View) : RecyclerView.ViewHolder(row) {
|
||||||
|
val childTV = row.findViewById(R.id.child_Title) as TextView?
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,43 +0,0 @@
|
||||||
package com.geeksville.mesh.ui
|
|
||||||
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import com.geeksville.mesh.databinding.AdapterMapMenuSelectionBinding
|
|
||||||
|
|
||||||
class MapStyleAdapter(itemView: AdapterMapMenuSelectionBinding) :
|
|
||||||
RecyclerView.ViewHolder(itemView.root) {
|
|
||||||
val card = itemView.cardview
|
|
||||||
val text = itemView.textview1
|
|
||||||
|
|
||||||
val mapStyleAdapater = object : RecyclerView.Adapter<MapStyleAdapter>() {
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MapStyleAdapter {
|
|
||||||
val inflater = LayoutInflater.from(parent.context)
|
|
||||||
val mapMenuBinding = AdapterMapMenuSelectionBinding.inflate(inflater, parent, false)
|
|
||||||
return MapStyleAdapter(mapMenuBinding)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: MapStyleAdapter, position: Int) {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
val list = listOf<String>()
|
|
||||||
override fun getItemCount() = list.size
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
val mapLayerAdapater = object : RecyclerView.Adapter<MapStyleAdapter>() {
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MapStyleAdapter {
|
|
||||||
val inflater = LayoutInflater.from(parent.context)
|
|
||||||
val mapMenuBinding = AdapterMapMenuSelectionBinding.inflate(inflater, parent, false)
|
|
||||||
return MapStyleAdapter(mapMenuBinding)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: MapStyleAdapter, position: Int) {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
val list = listOf<String>()
|
|
||||||
override fun getItemCount() = list.size
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
<androidx.cardview.widget.CardView
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:card_view="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:id="@+id/cardview"
|
|
||||||
android:layout_width="100dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="1dp"
|
|
||||||
card_view:cardBackgroundColor="#FF9800"
|
|
||||||
card_view:cardCornerRadius="7dp"
|
|
||||||
card_view:cardElevation="7dp"
|
|
||||||
card_view:contentPadding="7dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textview1"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_marginTop="3dp"
|
|
||||||
android:layout_marginBottom="3dp"
|
|
||||||
android:textColor="#fff"
|
|
||||||
android:textSize="20dp"
|
|
||||||
android:textStyle="bold" />
|
|
||||||
|
|
||||||
</androidx.cardview.widget.CardView>
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout 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_marginBottom="4dp"
|
||||||
|
android:background="@color/colorPrimary"
|
||||||
|
android:layout_height="30dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/child_Title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="14sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.099"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintVertical_bias="0.036" />
|
||||||
|
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,40 +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"
|
|
||||||
app:layout_constraintBaseline_toTopOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="Map Type"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
|
||||||
android:textColor="@color/colourGrey" />
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/mapTypeRecyclerView"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:scrollbars="horizontal" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="Map Layer"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
|
||||||
android:textColor="@color/colourGrey" />
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/mapLayerRecyclerView"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/exRecycle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_marginBottom="4dp"
|
||||||
|
android:background="@color/colourGrey"
|
||||||
|
android:layout_height="50dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/parent_Title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="20sp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.099"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintVertical_bias="0.419" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/down_iv"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@android:drawable/arrow_down_float"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintHorizontal_bias="0.896"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/parent_Title"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
Ładowanie…
Reference in New Issue