Add: Repository sheet

This commit is contained in:
machiav3lli 2022-01-25 02:41:38 +01:00
parent e672710e14
commit c3282d4c98
6 changed files with 360 additions and 1 deletions

View File

@ -51,6 +51,9 @@ interface RepositoryDao : BaseDao<Repository> {
@Query("SELECT * FROM repository WHERE _id = :id and deleted == 0") @Query("SELECT * FROM repository WHERE _id = :id and deleted == 0")
fun get(id: Long): Repository? fun get(id: Long): Repository?
@Query("SELECT * FROM repository WHERE _id = :id and deleted == 0")
fun getLive(id: Long): LiveData<Repository?>
@get:Query("SELECT * FROM repository WHERE deleted == 0 ORDER BY _id ASC") @get:Query("SELECT * FROM repository WHERE deleted == 0 ORDER BY _id ASC")
val allCursor: Cursor val allCursor: Cursor
@ -81,6 +84,9 @@ interface ProductDao : BaseDao<Product> {
@Query("SELECT COUNT(*) FROM product WHERE repository_id = :id") @Query("SELECT COUNT(*) FROM product WHERE repository_id = :id")
fun countForRepository(id: Long): Long fun countForRepository(id: Long): Long
@Query("SELECT COUNT(*) FROM product WHERE repository_id = :id")
fun countForRepositoryLive(id: Long): LiveData<Long>
@Query("SELECT * FROM product WHERE package_name = :packageName") @Query("SELECT * FROM product WHERE package_name = :packageName")
fun get(packageName: String): List<Product?> fun get(packageName: String): List<Product?>

View File

@ -9,7 +9,7 @@ import java.net.URL
data class Repository( data class Repository(
var id: Long, val address: String, val mirrors: List<String>, var id: Long, val address: String, val mirrors: List<String>,
val name: String, val description: String, val version: Int, val enabled: Boolean, val name: String, val description: String, val version: Int, var enabled: Boolean,
val fingerprint: String, val lastModified: String, val entityTag: String, val fingerprint: String, val lastModified: String, val entityTag: String,
val updated: Long, val timestamp: Long, val authentication: String, val updated: Long, val timestamp: Long, val authentication: String,
) { ) {

View File

@ -60,6 +60,16 @@ class PrefsRepositoriesFragment : BaseNavFragment() {
} }
false false
} }
reposFastAdapter?.onLongClickListener =
{ _: View?, _: IAdapter<RepoItem>?, item: RepoItem?, _: Int? ->
item?.item?.let {
RepositorySheetX(it.id).showNow(
parentFragmentManager,
"Repository ${it.id}"
)
}
false
}
binding.recyclerView.apply { binding.recyclerView.apply {
layoutManager = LinearLayoutManager(context) layoutManager = LinearLayoutManager(context)

View File

@ -0,0 +1,135 @@
package com.looker.droidify.ui.fragments
import android.app.Dialog
import android.os.Bundle
import android.text.SpannableStringBuilder
import android.text.format.DateUtils
import android.text.style.ForegroundColorSpan
import android.text.style.TypefaceSpan
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.viewModels
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.looker.droidify.R
import com.looker.droidify.databinding.SheetRepositoryBinding
import com.looker.droidify.service.Connection
import com.looker.droidify.service.SyncService
import com.looker.droidify.ui.activities.PrefsActivityX
import com.looker.droidify.ui.viewmodels.RepositoryViewModelX
import com.looker.droidify.utility.extension.resources.getColorFromAttr
import java.util.*
class RepositorySheetX() : BottomSheetDialogFragment() {
private lateinit var binding: SheetRepositoryBinding
val viewModel: RepositoryViewModelX by viewModels {
RepositoryViewModelX.Factory((requireActivity() as PrefsActivityX).db, repositoryId)
}
companion object {
private const val EXTRA_REPOSITORY_ID = "repositoryId"
}
constructor(repositoryId: Long = 0) : this() {
arguments = Bundle().apply {
putLong(EXTRA_REPOSITORY_ID, repositoryId)
}
}
private val repositoryId: Long
get() = requireArguments().getLong(EXTRA_REPOSITORY_ID)
private val syncConnection = Connection(SyncService::class.java)
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val sheet = super.onCreateDialog(savedInstanceState) as BottomSheetDialog
sheet.behavior.state = BottomSheetBehavior.STATE_EXPANDED
return sheet
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = SheetRepositoryBinding.inflate(layoutInflater)
syncConnection.bind(requireContext())
viewModel.repo.observe(viewLifecycleOwner) { updateRepositoryView() }
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
syncConnection.unbind(requireContext())
}
private fun updateRepositoryView() {
val repository = viewModel.repo.value?.trueData
if (repository == null) {
binding.address.text = getString(R.string.unknown)
binding.nameBlock.visibility = View.GONE
binding.descriptionBlock.visibility = View.GONE
binding.updatedBlock.visibility = View.GONE
binding.appsBlock.visibility = View.GONE
} else {
binding.address.text = repository.address
binding.descriptionBlock.visibility = View.VISIBLE
if (repository.updated > 0L) {
binding.nameBlock.visibility = View.VISIBLE
binding.updatedBlock.visibility = View.VISIBLE
binding.name.text = repository.name
binding.description.text = repository.description.replace('\n', ' ')
binding.updated.text = run {
val lastUpdated = repository.updated
if (lastUpdated > 0L) {
val date = Date(repository.updated)
val format =
if (DateUtils.isToday(date.time)) DateUtils.FORMAT_SHOW_TIME else
DateUtils.FORMAT_SHOW_TIME or DateUtils.FORMAT_SHOW_DATE
DateUtils.formatDateTime(binding.root.context, date.time, format)
} else {
getString(R.string.unknown)
}
}
if (repository.enabled && (repository.lastModified.isNotEmpty() || repository.entityTag.isNotEmpty())) {
binding.appsBlock.visibility = View.VISIBLE
binding.apps.text = viewModel.appsCount.value.toString()
} else {
binding.appsBlock.visibility = View.GONE
}
} else {
binding.description.text = getString(R.string.repository_not_used_DESC)
binding.nameBlock.visibility = View.GONE
binding.updatedBlock.visibility = View.GONE
binding.appsBlock.visibility = View.GONE
}
if (repository.fingerprint.isEmpty()) {
if (repository.updated > 0L) {
val builder =
SpannableStringBuilder(getString(R.string.repository_unsigned_DESC))
builder.setSpan(
ForegroundColorSpan(binding.root.context.getColorFromAttr(R.attr.colorError).defaultColor),
0, builder.length, SpannableStringBuilder.SPAN_EXCLUSIVE_EXCLUSIVE
)
binding.fingerprint.text = builder
binding.fingerprintBlock.visibility = View.VISIBLE
} else
binding.fingerprintBlock.visibility = View.GONE
} else {
val fingerprint =
SpannableStringBuilder(repository.fingerprint.windowed(2, 2, false)
.take(32).joinToString(separator = " ") { it.uppercase(Locale.US) })
fingerprint.setSpan(
TypefaceSpan("monospace"), 0, fingerprint.length,
SpannableStringBuilder.SPAN_EXCLUSIVE_EXCLUSIVE
)
binding.fingerprint.text = fingerprint
binding.fingerprintBlock.visibility = View.VISIBLE
}
}
}
}

View File

@ -0,0 +1,28 @@
package com.looker.droidify.ui.viewmodels
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.looker.droidify.database.DatabaseX
import com.looker.droidify.database.entity.Repository
class RepositoryViewModelX(val db: DatabaseX, val repositoryId: Long) : ViewModel() {
val repo = MediatorLiveData<Repository>()
val appsCount = MediatorLiveData<Long>()
init {
repo.addSource(db.repositoryDao.getLive(repositoryId), repo::setValue)
appsCount.addSource(db.productDao.countForRepositoryLive(repositoryId), appsCount::setValue)
}
class Factory(val db: DatabaseX, val repositoryId: Long) : ViewModelProvider.Factory {
@Suppress("unchecked_cast")
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(RepositoryViewModelX::class.java)) {
return RepositoryViewModelX(db, repositoryId) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
}

View File

@ -0,0 +1,180 @@
<?xml version="1.0" encoding="UTF-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true">
<androidx.core.widget.NestedScrollView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<com.google.android.material.circularreveal.CircularRevealFrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginBottom="12dp"
android:paddingHorizontal="12dp">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/address_block"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingHorizontal="16dp"
android:paddingVertical="8dp">
<com.google.android.material.textview.MaterialTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/address"
android:textColor="?android:attr/textColorPrimary"
android:textSize="12sp" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/address"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textSize="16sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/name_block"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingHorizontal="16dp"
android:paddingVertical="8dp">
<com.google.android.material.textview.MaterialTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/name"
android:textColor="?android:attr/textColorPrimary"
android:textSize="12sp" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textSize="16sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/description_block"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingHorizontal="16dp"
android:paddingVertical="8dp">
<com.google.android.material.textview.MaterialTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/description"
android:textColor="?android:attr/textColorPrimary"
android:textSize="12sp" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textSize="16sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/updated_block"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingHorizontal="16dp"
android:paddingVertical="8dp">
<com.google.android.material.textview.MaterialTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/recently_updated"
android:textColor="?android:attr/textColorPrimary"
android:textSize="12sp" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/updated"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textSize="16sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/apps_block"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingHorizontal="16dp"
android:paddingVertical="8dp">
<com.google.android.material.textview.MaterialTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/number_of_applications"
android:textColor="?android:attr/textColorPrimary"
android:textSize="12sp" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/apps"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textSize="16sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/fingerprint_block"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingHorizontal="16dp"
android:paddingVertical="8dp">
<com.google.android.material.textview.MaterialTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/fingerprint"
android:textColor="?android:attr/textColorPrimary"
android:textSize="12sp" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/fingerprint"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textSize="16sp" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content">
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</com.google.android.material.circularreveal.CircularRevealFrameLayout>
</androidx.core.widget.NestedScrollView>
</FrameLayout>
</layout>