10 Commits

Author SHA1 Message Date
Michachatz fb06922278 Remove version badge from README
Removed a version badge from the README.
2026-03-30 00:22:31 +02:00
Michachatz 821d847ce2 Update license link in README.md 2026-03-30 00:22:19 +02:00
Michachatz 5a76773ae3 Enhance README with project badges
Added badges for version, downloads, issues, contributors, and license.
2026-03-29 23:55:39 +02:00
Michachatz f303844e28 Add warning about Google identity requirements
Added a warning about upcoming Google requirements for apps on certified Android devices.
2026-03-25 07:37:58 +01:00
Michatec 9e32fe3871 - Move FreeDroidWarn initialization from MainApplication to ScreenActivity 2026-03-24 17:43:21 +01:00
Michatec 6b2ac6d740 - Removed old changelogs
- Removed launcher SVG and build script
2026-03-24 17:33:47 +01:00
Michatec 2c9af08e8c - Refactor code to use idiomatic Kotlin functions like isNullOrEmpty(), associateBy, and appendRange
- Increase `DiffUtil` threshold in `CursorRecyclerAdapter` to 500 and optimize equality checks
- Simplify locale configuration by removing legacy Android SDK version checks
- Remove unnecessary `@SuppressLint` annotations and `@Volatile` modifiers
- Improve performance of collection operations in `ProductFragment` and `Preferences` using `associateBy` and `firstOrNull`
- Suppress deprecation warnings for `getOpacity` in `DrawableWrapper` and `TabsFragment`
- Clean up service binding logic in `Connection.kt` with better type casting
2026-03-24 17:31:51 +01:00
Michatec bdd204d9de - Migrate dependencies to Version Catalog (libs.versions.toml)
- Update Kotlin to 2.3.20 and Jackson Core to 2.21.2
- Update Gradle Wrapper to 9.4.1
- Bump version code to 17 and version name to 1.7
- Remove unused `percentTranslationY` property from `FragmentLinearLayout`
- Clean up semicolons in `MainApplication.kt`
- Update `.gitignore` to include `gradle-daemon-jvm.properties`
2026-03-24 13:07:06 +01:00
Michachatz 112d4bdb62 Integrate FreeDroidWarn for upgrade warnings 2026-03-24 08:43:37 +01:00
Michachatz ebb54fd19b Add JitPack repository and FreeDroidWarn dependency 2026-03-24 08:25:38 +01:00
25 changed files with 101 additions and 179 deletions
+1
View File
@@ -12,3 +12,4 @@
!/proguard.pro
!/README.md
!/src
/gradle/gradle-daemon-jvm.properties
+13
View File
@@ -1,9 +1,22 @@
# Michas Droid
<p align="center">
<a href="https://github.com/michatec/michas-droid/releases"><img src="https://img.shields.io/github/downloads/michatec/michas-droid/total.svg?style=flat-square" /></a>
<a href="https://github.com/michatec/michas-droid/issues"><img src="https://img.shields.io/github/issues-raw/michatec/michas-droid.svg?style=flat-square&label=issues" /></a>
<a href="https://github.com/michatec/michas-droid/graphs/contributors"><img src="https://img.shields.io/github/contributors/michatec/michas-droid?style=flat-square" /></a>
<a href="https://github.com/michatec/michas-droid/blob/master/COPYING"><img src="https://img.shields.io/github/license/michatec/michas-droid?style=flat-square" /></a>
</p>
Yet another F-Droid client.
[![Release](https://img.shields.io/github/v/release/michatec/michas-droid)](https://github.com/michatec/michas-droid/releases/latest)
## Warning ⚠️
Google has announced that, starting in 2026/2027, all apps on certified Android devices will require the developer to submit personal identity details directly to Google.
Since the developers of this app do not agree to this requirement, this app will no longer work on certified Android devices after that time.
## Description
Unofficial F-Droid client in the style of the classic one.
+16 -13
View File
@@ -2,11 +2,12 @@ buildscript {
repositories {
google()
mavenCentral()
maven { url 'https://jitpack.io' }
}
dependencies {
classpath 'com.android.tools.build:gradle:9.1.0'
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:2.3.10'
classpath libs.gradle
classpath libs.kotlin.gradle.plugin
}
}
@@ -20,8 +21,8 @@ android {
applicationId 'com.michatec.store'
minSdk 30
targetSdk 36
versionCode 16
versionName '1.6'
versionCode 17
versionName '1.7'
def languages = [ 'en' ]
buildConfigField 'String[]', 'LANGUAGES', '{ "' + languages.join('", "') + '" }'
@@ -95,16 +96,18 @@ android {
repositories {
google()
mavenCentral()
maven { url 'https://jitpack.io' }
}
dependencies {
implementation 'org.jetbrains.kotlin:kotlin-stdlib:2.3.10'
implementation 'androidx.fragment:fragment-ktx:1.8.9'
implementation 'androidx.viewpager2:viewpager2:1.1.0'
implementation 'androidx.vectordrawable:vectordrawable:1.2.0'
implementation 'com.squareup.okhttp3:okhttp:5.3.2'
implementation 'io.reactivex.rxjava3:rxjava:3.1.12'
implementation 'io.reactivex.rxjava3:rxandroid:3.0.2'
implementation 'com.fasterxml.jackson.core:jackson-core:2.21.1'
implementation 'com.squareup.picasso:picasso:2.71828'
implementation libs.kotlin.stdlib
implementation libs.fragment.ktx
implementation libs.viewpager2
implementation libs.vectordrawable
implementation libs.okhttp
implementation libs.rxjava
implementation libs.rxandroid
implementation libs.jackson.core
implementation libs.picasso
implementation libs.freedroidwarn
}
-27
View File
@@ -1,27 +0,0 @@
#!/bin/bash
set -e
cd "`dirname "$0"`"
dimensions=(mdpi:1 hdpi:1.5 xhdpi:2 xxhdpi:3 xxxhdpi:4)
res='../src/main/res'
cp 'launcher.svg' 'launcher-foreground.svg'
inkscape --select circle --verb EditDelete --verb=FileSave --verb=FileQuit \
'launcher-foreground.svg'
for dimension in ${dimensions[@]}; do
resource="${dimension%:*}"
scale="${dimension#*:}"
mkdir -p "$res/mipmap-$resource" "$res/drawable-$resource"
size="`bc <<< "48 * $scale"`"
inkscape 'launcher.svg' -a 15:15:93:93 -w "$size" -h "$size" \
-e "$res/mipmap-$resource/ic_launcher.png"
optipng "$res/mipmap-$resource/ic_launcher.png"
size="`bc <<< "108 * $scale"`"
inkscape 'launcher-foreground.svg' -w "$size" -h "$size" \
-e "$res/drawable-$resource/ic_launcher_foreground.png"
optipng "$res/drawable-$resource/ic_launcher_foreground.png"
done
rm 'launcher-foreground.svg'
-87
View File
@@ -1,87 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/2000/svg" style="enable-background:new" id="svg3" version="1.1" viewBox="0 0 108 108"
height="108" width="108" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://purl.org/dc/elements/1.1/">
<metadata id="metadata55">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>-</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs id="defs17">
<clipPath id="paper-clip" clipPathUnits="userSpaceOnUse">
<path id="paper-clip-path" d="m 67.759585,28.469613 -18.355472,18.146485 -21.453125,-4.732422 9.087891,24.064453 25.894536,12.974609 12.37695,-23.86914 -1.93359,-0.66211 z" />
</clipPath>
<filter id="paper-inner-shadow">
<feFlood id="feFlood6" result="flood" flood-color="rgb(0,0,0)" flood-opacity="0.2" />
<feComposite id="feComposite8" result="composite1" operator="in" in2="SourceGraphic" in="flood" />
<feGaussianBlur id="feGaussianBlur10" result="blur" stdDeviation="2" in="composite1" />
<feOffset id="feOffset12" result="offset" dy="0" dx="0" />
<feComposite id="feComposite14" result="composite2" operator="over" in2="offset" in="SourceGraphic" />
</filter>
<filter id="paper-edge-1" style="color-interpolation-filters:sRGB">
<feFlood id="feFlood958" result="flood" flood-color="rgb(0,0,0)" flood-opacity="0.2" />
<feComposite id="feComposite960" result="composite1" operator="out" in2="SourceGraphic"
in="flood" />
<feGaussianBlur id="feGaussianBlur962" result="blur" stdDeviation="0" in="composite1" />
<feOffset id="feOffset964" result="offset" dy="0.2" dx="0.2" />
<feComposite id="feComposite966" result="composite2" operator="atop" in2="SourceGraphic"
in="offset" />
</filter>
<filter id="paper-edge-2" style="color-interpolation-filters:sRGB">
<feFlood id="feFlood1388" result="flood" flood-color="rgb(255,255,255)" flood-opacity="0.2" />
<feComposite id="feComposite1390" result="composite1" operator="out" in2="SourceGraphic"
in="flood" />
<feGaussianBlur id="feGaussianBlur1392" result="blur" stdDeviation="0" in="composite1" />
<feOffset id="feOffset1394" result="offset" dy="-0.1" dx="0.3" />
<feComposite id="feComposite1396" result="composite2" operator="atop" in2="SourceGraphic"
in="offset" />
</filter>
<filter id="paper-shadow" style="color-interpolation-filters:sRGB">
<feFlood id="feFlood1506" result="flood" flood-color="rgb(0,0,0)" flood-opacity="0.4" />
<feComposite id="feComposite1508" result="composite1" operator="in" in2="SourceGraphic"
in="flood" />
<feGaussianBlur id="feGaussianBlur1510" result="blur" stdDeviation="2" in="composite1" />
<feOffset id="feOffset1512" result="offset" dy="0" dx="0" />
<feComposite id="feComposite1514" result="composite2" operator="over" in2="offset" in="SourceGraphic" />
</filter>
<filter id="circle-shadow" style="color-interpolation-filters:sRGB">
<feFlood id="feFlood1626" result="flood" flood-color="rgb(255,255,255)" flood-opacity="0.2" />
<feComposite id="feComposite1628" result="composite1" operator="out" in2="SourceGraphic"
in="flood" />
<feGaussianBlur id="feGaussianBlur1630" result="blur" stdDeviation="0" in="composite1" />
<feOffset id="feOffset1632" result="offset" dy="0.5" dx="0" />
<feComposite id="feComposite1634" result="fbSourceGraphic" operator="atop" in2="SourceGraphic"
in="offset" />
<feFlood in="fbSourceGraphic" result="flood" flood-color="rgb(0,0,0)" flood-opacity="0.2"
id="feFlood1640" />
<feComposite result="composite1" operator="out" in="flood" id="feComposite1642" in2="fbSourceGraphic" />
<feGaussianBlur result="blur" stdDeviation="0" in="composite1" id="feGaussianBlur1644" />
<feOffset result="offset" dy="-0.5" dx="0" id="feOffset1646" />
<feComposite result="fbSourceGraphic" operator="atop" in="offset" id="feComposite1648"
in2="fbSourceGraphic" />
<feFlood in="fbSourceGraphic" result="flood" flood-color="rgb(0,0,0)" flood-opacity="0.2"
id="feFlood1664" />
<feComposite result="composite1" operator="in" in="flood" id="feComposite1666" in2="fbSourceGraphic" />
<feGaussianBlur result="blur" stdDeviation="1" in="composite1" id="feGaussianBlur1668" />
<feOffset result="offset" dy="1" dx="0" id="feOffset1670" />
<feComposite result="composite2" operator="over" in="fbSourceGraphic" id="feComposite1672"
in2="offset" />
</filter>
</defs>
<circle r="36" cy="54" cx="54" id="circle" style="fill:#262c38;filter:url(#circle-shadow)" />
<g style="filter:url(#paper-shadow)" id="paper-group">
<path d="m 67.75836,28.470764 -23.382292,23.115602 -0.0887,1.254642 29.189963,2.017946 z"
style="fill:#1976d2" id="paper-4" />
<path style="fill:#47a2fc;filter:url(#paper-inner-shadow)" d="m 27.949219,41.884766 9.08789,24.064453 25.894532,12.974609 12.376953,-23.86914 -22.298828,-7.638672 v -0.002 z"
clip-path="url(#paper-clip)" id="paper-3" />
<path d="m 53.009473,47.414648 -15.970174,18.53113 25.894116,12.97696 z" style="fill:#1976d2;filter:url(#paper-edge-1)"
id="paper-2" />
<path style="fill:#47a2fc;filter:url(#paper-edge-2)" d="m 53.009766,47.414016 9.923828,31.503906 12.375,-23.865234 z"
id="paper-1" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.0 KiB

+30
View File
@@ -0,0 +1,30 @@
[versions]
fragment-ktx = "1.8.9"
freedroidwarn = "V1.10"
gradle = "9.1.0"
gradle-toolchains-foojay-resolver-convention = "1.0.0"
jackson-core = "2.21.2"
kotlin = "2.3.20"
okhttp = "5.3.2"
picasso = "2.71828"
rxandroid = "3.0.2"
rxjava = "3.1.12"
vectordrawable = "1.2.0"
viewpager2 = "1.1.0"
[libraries]
fragment-ktx = { group = "androidx.fragment", name = "fragment-ktx", version.ref = "fragment-ktx" }
freedroidwarn = { group = "com.github.woheller69", name = "FreeDroidWarn", version.ref = "freedroidwarn" }
gradle = { group = "com.android.tools.build", name = "gradle", version.ref = "gradle" }
jackson-core = { group = "com.fasterxml.jackson.core", name = "jackson-core", version.ref = "jackson-core" }
kotlin-gradle-plugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" }
kotlin-stdlib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib", version.ref = "kotlin" }
okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" }
picasso = { group = "com.squareup.picasso", name = "picasso", version.ref = "picasso" }
rxandroid = { group = "io.reactivex.rxjava3", name = "rxandroid", version.ref = "rxandroid" }
rxjava = { group = "io.reactivex.rxjava3", name = "rxjava", version.ref = "rxjava" }
vectordrawable = { group = "androidx.vectordrawable", name = "vectordrawable", version.ref = "vectordrawable" }
viewpager2 = { group = "androidx.viewpager2", name = "viewpager2", version.ref = "viewpager2" }
[plugins]
foojay = { id = "org.gradle.toolchains.foojay-resolver-convention", version.ref = "gradle-toolchains-foojay-resolver-convention" }
+1 -1
View File
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-3
View File
@@ -1,3 +0,0 @@
* Allow to sort by date added and last update
* Display more compatibility information for packages
* Drop AppCompat and reduce APK file size
-3
View File
@@ -1,3 +0,0 @@
* Persist sorting order across application restarts
* Display Open Collective donation links
* Rework text strings
-4
View File
@@ -1,4 +0,0 @@
* Full text search
* Search results ranking
* Allow to view packages per repository
* Automatic day/night theme for Android 10
+1 -1
View File
@@ -1,5 +1,5 @@
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '1.0.0'
id "org.gradle.toolchains.foojay-resolver-convention" version "1.0.0"
}
rootProject.name = "michas-droid"
include ':'
@@ -16,8 +16,10 @@ object Preferences {
private val subject = PublishSubject.create<Key<*>>()
private val keys = sequenceOf(Key.AutoSync, Key.IncompatibleVersions, Key.ProxyHost, Key.ProxyPort, Key.ProxyType,
Key.SortOrder, Key.Theme, Key.UpdateNotify, Key.UpdateUnstable).map { Pair(it.name, it) }.toMap()
private val keys = sequenceOf(
Key.AutoSync, Key.IncompatibleVersions, Key.ProxyHost, Key.ProxyPort, Key.ProxyType,
Key.SortOrder, Key.Theme, Key.UpdateNotify, Key.UpdateUnstable
).associateBy { it.name }
private val listener = SharedPreferences.OnSharedPreferenceChangeListener { _, keyString ->
keys[keyString]?.let(subject::onNext)
@@ -74,5 +74,6 @@ open class DrawableWrapper(val drawable: Drawable): Drawable() {
DrawableCompat.setHotspotBounds(drawable, left, top, right, bottom)
}
@Suppress("DEPRECATION", "OVERRIDE_DEPRECATION")
override fun getOpacity(): Int = drawable.opacity
}
@@ -260,6 +260,6 @@ class IndexHandler(private val repositoryId: Long, private val callback: Callbac
override fun characters(ch: CharArray, start: Int, length: Int) {
super.characters(ch, start, length)
contentBuilder.append(ch, start, length)
contentBuilder.appendRange(ch, start, start + length)
}
}
@@ -362,10 +362,10 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
}
}
@SuppressLint("ClickableViewAccessibility")
private open class OverlappingViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
init {
// Block touch events if touched above negative margin
@SuppressLint("ClickableViewAccessibility")
itemView.setOnTouchListener { v, event ->
val top = (v.layoutParams as ViewGroup.MarginLayoutParams).topMargin
event.action == MotionEvent.ACTION_DOWN && top < 0 && event.y < -top
@@ -373,6 +373,7 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
}
}
@SuppressLint("SetTextI18n")
private class LinkViewHolder(itemView: View): OverlappingViewHolder(itemView) {
companion object {
private val measurement = Measurement<Int>()
@@ -384,7 +385,6 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
init {
val margin = measurement.invalidate(itemView.resources) {
@SuppressLint("SetTextI18n")
text.text = "measure"
link.visibility = View.GONE
measurement.measure(itemView)
@@ -397,6 +397,7 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
}
}
@SuppressLint("SetTextI18n")
private class PermissionsViewHolder(itemView: View): OverlappingViewHolder(itemView) {
companion object {
private val measurement = Measurement<Int>()
@@ -407,7 +408,6 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
init {
val margin = measurement.invalidate(itemView.resources) {
@SuppressLint("SetTextI18n")
text.text = "measure"
measurement.measure(itemView)
((itemView.measuredHeight - icon.measuredHeight) / 2f).roundToInt()
@@ -148,7 +148,7 @@ class ProductFragment(): ScreenFragment(), ProductAdapter.Callbacks {
.flatMapSingle { products -> RxUtils
.querySingle { signal -> Database.RepositoryAdapter.getAll(signal) }
.map { result ->
result.asSequence().map { Pair(it.id, it) }.toMap()
result.associateBy { it.id }
.let { map -> products.mapNotNull { product -> map[product.repositoryId]?.let { Pair(product, it) } } } } }
.flatMapSingle { products -> RxUtils
.querySingle { signal -> Nullable(Database.InstalledAdapter.get(packageName, signal)) }
@@ -397,7 +397,7 @@ class ProductFragment(): ScreenFragment(), ProductAdapter.Callbacks {
override fun onScreenshotClick(screenshot: Product.Screenshot) {
val pair = products.asSequence()
.map { it -> Pair(it.second, it.first.screenshots.find { it === screenshot }?.identifier) }
.filter { it.second != null }.firstOrNull()
.firstOrNull { it.second != null }
if (pair != null) {
val (repository, identifier) = pair
if (identifier != null) {
@@ -420,7 +420,8 @@ class ProductFragment(): ScreenFragment(), ProductAdapter.Callbacks {
MessageDialog(MessageDialog.Message.ReleaseSignatureMismatch).show(childFragmentManager)
}
else -> {
val productRepository = products.asSequence().filter { it -> it.first.releases.any { it === release } }.firstOrNull()
val productRepository =
products.firstOrNull { it -> it.first.releases.any { it === release } }
if (productRepository != null) {
downloadConnection.binder?.enqueue(packageName, productRepository.first.name,
productRepository.second, release)
@@ -196,6 +196,12 @@ class ProductsAdapter(private val onClick: (ProductItem) -> Unit):
}
}
override fun areContentsTheSame(oldCursor: Cursor, newCursor: Cursor): Boolean {
val oldItem = Database.ProductAdapter.transformItem(oldCursor)
val newItem = Database.ProductAdapter.transformItem(newCursor)
return oldItem == newItem
}
@SuppressLint("NotifyDataSetChanged")
override fun onCursorChanged(oldCursor: Cursor?, newCursor: Cursor?) {
val oldSize = oldCursor?.count ?: 0
@@ -14,6 +14,7 @@ import androidx.core.os.BundleCompat
import androidx.core.view.WindowCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import com.michatec.store.BuildConfig
import com.michatec.store.R
import com.michatec.store.content.Cache
import com.michatec.store.content.Preferences
@@ -23,6 +24,7 @@ import com.michatec.store.utility.Utils
import com.michatec.store.utility.extension.android.*
import com.michatec.store.utility.extension.resources.*
import com.michatec.store.utility.extension.text.*
import org.woheller69.freeDroidWarn.FreeDroidWarn
abstract class ScreenActivity: FragmentActivity() {
companion object {
@@ -74,6 +76,8 @@ abstract class ScreenActivity: FragmentActivity() {
setTheme(Preferences[Preferences.Key.Theme].getResId(resources.configuration))
super.onCreate(savedInstanceState)
FreeDroidWarn.showWarningOnUpgrade(this, BuildConfig.VERSION_CODE)
WindowCompat.setDecorFitsSystemWindows(window, false)
addContentView(FrameLayout(this).apply { id = R.id.main_content },
ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT))
@@ -561,6 +561,7 @@ class TabsFragment: ScreenFragment() {
override fun setAlpha(alpha: Int) = Unit
override fun setColorFilter(colorFilter: ColorFilter?) = Unit
@Deprecated("Deprecated in Java")
override fun getOpacity(): Int = PixelFormat.TRANSLUCENT
}
@@ -19,11 +19,11 @@ class Connection<B: IBinder, S: ConnectionService<B>>(private val serviceClass:
}
}
override fun onServiceConnected(componentName: ComponentName, binder: IBinder) {
@Suppress("UNCHECKED_CAST")
binder as B
this.binder = binder
onBind?.invoke(this, binder)
override fun onServiceConnected(componentName: ComponentName, binder: IBinder) {
val b = binder as B
this.binder = b
onBind?.invoke(this, b)
}
override fun onServiceDisconnected(componentName: ComponentName) {
@@ -331,7 +331,7 @@ class SyncService: ConnectionService<SyncService.Binder>() {
currentTask = null
handleNextTask(false)
val blocked = updateNotificationBlockerFragment?.get()?.isAdded == true
if (!blocked && result != null && result.isNotEmpty()) {
if (!blocked && !result.isNullOrEmpty()) {
displayUpdatesNotification(result)
}
}
@@ -12,7 +12,7 @@ import okhttp3.Response
object RxUtils {
private class ManagedDisposable(private val cancel: () -> Unit): Disposable {
@Volatile var disposed = false
var disposed = false
override fun isDisposed(): Boolean = disposed
override fun dispose() {
@@ -1,7 +1,6 @@
package com.michatec.store.utility
import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.content.pm.Signature
import android.content.res.Configuration
@@ -67,17 +66,11 @@ object Utils {
}
}
@SuppressLint("SuspiciousIndentation")
fun configureLocale(context: Context): Context {
val supportedLanguages = BuildConfig.LANGUAGES.toSet()
val configuration = context.resources.configuration
val currentLocales = if (Android.sdk(24)) {
val localesList = configuration.locales
(0 until localesList.size()).map(localesList::get)
} else {
@Suppress("DEPRECATION")
listOf(configuration.locale)
}
val currentLocales = (0 until localesList.size()).map(localesList::get)
val compatibleLocales = currentLocales
.filter { it.language in supportedLanguages }
.let { it.ifEmpty { listOf(Locale.US) } }
@@ -33,9 +33,8 @@ abstract class CursorRecyclerAdapter<VT: Enum<VT>, VH: RecyclerView.ViewHolder>:
return
}
// Further reduced threshold to 100 for DiffUtil to avoid any noticeable frame drops on the main thread.
// JSON parsing and DB access during diffing are slow.
if (oldSize > 100 || newSize > 100) {
// Increased threshold for DiffUtil and optimized callback
if (oldSize > 500 || newSize > 500) {
notifyDataSetChanged()
return
}
@@ -60,7 +59,6 @@ abstract class CursorRecyclerAdapter<VT: Enum<VT>, VH: RecyclerView.ViewHolder>:
})
diffResult.dispatchUpdatesTo(this)
} catch (_: Exception) {
// Fallback in case of cursor issues during diffing
notifyDataSetChanged()
}
}
@@ -12,11 +12,4 @@ class FragmentLinearLayout: LinearLayout {
init {
fitsSystemWindows = true
}
@Suppress("unused")
var percentTranslationY: Float
get() = height.let { if (it > 0) translationY / it else 0f }
set(value) {
translationY = value * height
}
}