Add: More info on top of the screen

Fix: Show real size of apk
This commit is contained in:
LooKeR 2021-10-22 19:29:47 +05:30
parent 3ea6dab407
commit fd7746f8b3
6 changed files with 235 additions and 24 deletions

View File

@ -4,6 +4,7 @@ import android.annotation.SuppressLint
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.content.pm.PermissionGroupInfo
import android.content.pm.PermissionInfo
import android.content.res.Resources
@ -24,11 +25,17 @@ import android.view.ViewGroup
import android.widget.*
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.content.res.ResourcesCompat
import androidx.core.net.toUri
import androidx.core.text.HtmlCompat
import androidx.core.text.util.LinkifyCompat
import androidx.core.view.doOnPreDraw
import androidx.recyclerview.widget.RecyclerView
import coil.load
import com.google.android.material.card.MaterialCardView
import com.google.android.material.divider.MaterialDivider
import com.google.android.material.imageview.ShapeableImageView
import com.google.android.material.switchmaterial.SwitchMaterial
import com.google.android.material.textview.MaterialTextView
import com.looker.droidify.R
import com.looker.droidify.content.Preferences
import com.looker.droidify.content.ProductPreferences
@ -79,7 +86,7 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
data class Downloading(val read: Long, val total: Long?) : Status()
}
enum class ViewType { HEADER, SWITCH, SECTION, EXPAND, TEXT, LINK, PERMISSIONS, SCREENSHOT, RELEASE, EMPTY }
enum class ViewType { HEADER, RELEASE_INFO, SWITCH, SECTION, EXPAND, TEXT, LINK, PERMISSIONS, SCREENSHOT, RELEASE, EMPTY }
private enum class SwitchType(val titleResId: Int) {
IGNORE_ALL_UPDATES(R.string.ignore_all_updates),
@ -129,6 +136,14 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
get() = ViewType.HEADER
}
object ReleaseInfoItem : Item() {
override val descriptor: String
get() = "release_item"
override val viewType: ViewType
get() = ViewType.RELEASE_INFO
}
class SwitchItem(
val switchType: SwitchType,
val packageName: String,
@ -309,7 +324,6 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
private class HeaderViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val icon = itemView.findViewById<ShapeableImageView>(R.id.icon)!!
val name = itemView.findViewById<TextView>(R.id.name)!!
val version = itemView.findViewById<TextView>(R.id.version)!!
val packageName = itemView.findViewById<TextView>(R.id.package_name)!!
val action = itemView.findViewById<Button>(R.id.action)!!
val statusLayout = itemView.findViewById<View>(R.id.status_layout)!!
@ -334,6 +348,17 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
}
}
private class ReleaseInfoViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val targetBlock = itemView.findViewById<LinearLayout>(R.id.sdk_block)!!
val divider1 = itemView.findViewById<MaterialDivider>(R.id.divider1)!!
val targetSdk = itemView.findViewById<MaterialTextView>(R.id.sdk)!!
val version = itemView.findViewById<MaterialTextView>(R.id.version)!!
val size = itemView.findViewById<MaterialTextView>(R.id.size)!!
val devName = itemView.findViewById<MaterialTextView>(R.id.dev)!!
val devIcon = itemView.findViewById<ShapeableImageView>(R.id.dev_icon)!!
val dev = itemView.findViewById<MaterialCardView>(R.id.dev_block)!!
}
private class SwitchViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val enabled = itemView.findViewById<SwitchMaterial>(R.id.enabled)!!
@ -699,6 +724,7 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
return if (length >= 0) subSequence(0, length) else null
}
items.add(Item.ReleaseInfoItem)
val screenshotItems = productRepository.first.screenshots
.map { Item.ScreenshotItem(productRepository.second, packageName, it) }
if (screenshotItems.isNotEmpty()) {
@ -994,6 +1020,7 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
ViewType.HEADER -> HeaderViewHolder(parent.inflate(R.layout.product_header_item)).apply {
action.setOnClickListener { this@ProductAdapter.action?.let(callbacks::onActionClick) }
}
ViewType.RELEASE_INFO -> ReleaseInfoViewHolder(parent.inflate(R.layout.release_info))
ViewType.SWITCH -> SwitchViewHolder(parent.inflate(R.layout.switch_item)).apply {
itemView.setOnClickListener {
val switchItem = items[adapterPosition] as Item.SwitchItem
@ -1145,12 +1172,6 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
holder.name.text = item.product.name
val canUpdate = item.product.canUpdate(installedItem) &&
!ProductPreferences[item.product.packageName].shouldIgnoreUpdate(item.product.versionCode)
val version =
(if (canUpdate) item.product.version else installedItem?.version)?.nullIfEmpty()
?: item.product.version.nullIfEmpty()
holder.version.text =
version?.let { context.getString(R.string.version_FORMAT, it) }
?: context.getString(R.string.unknown)
holder.packageName.apply {
text = item.product.packageName
setTextSizeScaled(15)
@ -1196,6 +1217,31 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
}
Unit
}
ViewType.RELEASE_INFO -> {
holder as ReleaseInfoViewHolder
item as Item.ReleaseInfoItem
val imageSource = product?.source?.trimAfter('/', 4).plus(".png")
val sdk = product?.displayRelease?.targetSdkVersion
holder.version.doOnPreDraw {
if (it.measuredWidth > 70 || sdk == 0) {
holder.targetBlock.visibility = View.GONE
holder.divider1.visibility = View.GONE
}
}
holder.targetSdk.text = sdk.toString()
holder.version.text = product?.displayRelease?.version
holder.size.text = product?.displayRelease?.size?.formatSize()
holder.devName.text = product?.author?.name?.replaceFirstChar {
if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString()
}
holder.devIcon.load(imageSource)
holder.dev.setOnClickListener {
context.startActivity(Intent(Intent.ACTION_VIEW, product?.source?.toUri()))
}
}
ViewType.SWITCH -> {
holder as SwitchViewHolder
item as Item.SwitchItem

View File

@ -108,7 +108,6 @@ class ProductFragment() : ScreenFragment(), ProductAdapter.Callbacks {
val toolbar = view.findViewById<Toolbar>(R.id.toolbar)!!
screenActivity.onToolbarCreated(toolbar)
toolbar.title = getString(R.string.application)
this.toolbar = toolbar
toolbar.menu.apply {
@ -190,7 +189,6 @@ class ProductFragment() : ScreenFragment(), ProductAdapter.Callbacks {
layoutManagerState = null
if (firstChanged || productChanged) {
this.products = products
toolbar.title = products[0].first.name
}
if (firstChanged || installedItemChanged) {
installed = installedItem.value?.let {
@ -342,6 +340,15 @@ class ProductFragment() : ScreenFragment(), ProductAdapter.Callbacks {
updateToolbarButtons()
}
private fun updateToolbarTitle() {
val showPackageName = recyclerView?.let {
(it.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition() != 0
} == true
if (showPackageName) toolbar?.title = products[0].first.name
else toolbar?.title = getString(R.string.application)
}
private fun updateToolbarButtons() {
val (actions, primaryAction) = actions
val showPrimaryAction = recyclerView
@ -394,6 +401,7 @@ class ProductFragment() : ScreenFragment(), ProductAdapter.Callbacks {
val lastPosition = lastPosition
this.lastPosition = position
if ((lastPosition == 0) != (position == 0)) {
updateToolbarTitle()
updateToolbarButtons()
}
}

View File

@ -13,12 +13,23 @@ private val sizeFormats = listOf("%.0f B", "%.0f kB", "%.1f MB", "%.2f GB")
fun Long.formatSize(): String {
val (size, index) = generateSequence(Pair(this.toFloat(), 0)) { (size, index) ->
if (size >= 1000f)
Pair(size / 1000f, index + 1) else null
if (size >= 1024f)
Pair(size / 1024f, index + 1) else null
}.take(sizeFormats.size).last()
return sizeFormats[index].format(Locale.US, size)
}
fun String?.trimAfter(char: Char, repeated: Int): String? {
var count = 0
this?.let {
for (i in it.indices) {
if (it[i] == char) count++
if (repeated == count) return it.substring(0, i)
}
}
return null
}
fun Char.halfByte(): Int {
return when (this) {
in '0'..'9' -> this - '0'

View File

@ -47,16 +47,6 @@
android:singleLine="true"
android:textColor="?android:attr/textColor"
android:textSize="14sp" />
<TextView
android:id="@+id/version"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="2sp"
android:singleLine="true"
android:textColor="?attr/colorOnSurface"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>

View File

@ -5,11 +5,9 @@
android:layout_width="match_parent"
android:layout_height="72dp"
android:layout_marginHorizontal="10dp"
android:orientation="horizontal"
app:cardBackgroundColor="?android:attr/colorBackground"
app:cardCornerRadius="@dimen/shape_medium_corner"
app:cardElevation="0dp"
app:strokeColor="@null"
app:strokeWidth="0dp">
<LinearLayout

View File

@ -0,0 +1,158 @@
<?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_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:background="@drawable/background_border"
android:backgroundTint="?attr/colorSurface"
android:gravity="center">
<LinearLayout
android:id="@+id/sdk_block"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:padding="16dp"
app:layout_constraintEnd_toStartOf="@id/divider1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textview.MaterialTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Target"
android:textColor="?android:attr/textColorPrimary"
android:textSize="16sp" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/sdk"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?android:attr/textColor"
android:textSize="12sp" />
</LinearLayout>
<com.google.android.material.divider.MaterialDivider
android:id="@+id/divider1"
android:layout_width="2dp"
android:layout_height="0dp"
android:layout_marginVertical="12dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/version_block"
app:layout_constraintStart_toEndOf="@id/sdk_block"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:id="@+id/version_block"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:padding="16dp"
app:layout_constraintEnd_toStartOf="@id/divider2"
app:layout_constraintStart_toEndOf="@id/divider1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textview.MaterialTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Version"
android:textColor="?android:attr/textColorPrimary"
android:textSize="16sp" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/version"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?android:attr/textColor"
android:textSize="12sp" />
</LinearLayout>
<com.google.android.material.divider.MaterialDivider
android:id="@+id/divider2"
android:layout_width="2dp"
android:layout_height="0dp"
android:layout_marginVertical="12dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/size_block"
app:layout_constraintStart_toEndOf="@id/version_block"
app:layout_constraintTop_toTopOf="parent" />
<LinearLayout
android:id="@+id/size_block"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:padding="16dp"
app:layout_constraintEnd_toStartOf="@id/divider3"
app:layout_constraintStart_toEndOf="@id/divider2"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textview.MaterialTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Size"
android:textColor="?android:attr/textColorPrimary"
android:textSize="16sp" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?android:attr/textColor"
android:textSize="12sp" />
</LinearLayout>
<com.google.android.material.divider.MaterialDivider
android:id="@+id/divider3"
android:layout_width="2dp"
android:layout_height="0dp"
android:layout_marginVertical="12dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/dev_block"
app:layout_constraintStart_toEndOf="@id/size_block"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.card.MaterialCardView
android:id="@+id/dev_block"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:cardBackgroundColor="?attr/colorSurface"
app:cardCornerRadius="@dimen/shape_medium_corner"
app:cardElevation="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/divider3"
app:layout_constraintTop_toTopOf="parent"
app:strokeWidth="0dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:padding="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/divider2">
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/dev_icon"
android:layout_width="35dp"
android:layout_height="35dp"
app:shapeAppearanceOverlay="@style/Shape.Small" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/dev"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="?android:attr/textColor"
android:textSize="12sp" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</androidx.constraintlayout.widget.ConstraintLayout>