Merge remote-tracking branch 'origin/master'

This commit is contained in:
Iamlooker 2022-04-11 09:08:36 +05:30
commit 5543c78987
22 changed files with 204 additions and 144 deletions

View File

@ -17,8 +17,8 @@ android {
applicationId = 'com.looker.droidify'
minSdk = 23
targetSdk = 32
versionCode = 43
versionName = "0.4.3"
versionCode = 903
versionName = "0.9.0"
vectorDrawables.useSupportLibrary = true
javaCompileOptions {
@ -58,7 +58,7 @@ android {
minifyEnabled = false
shrinkResources = false
applicationIdSuffix = ".debug"
versionNameSuffix = "-alpha2"
versionNameSuffix = "-alpha3"
resValue "string", "application_name", "Neo Store-Debug"
manifestPlaceholders = [
appIcon : "@mipmap/ic_launcher_debug",
@ -69,7 +69,7 @@ android {
minifyEnabled = false
shrinkResources = false
applicationIdSuffix = ".neo"
versionNameSuffix = "-alpha2"
versionNameSuffix = "-alpha3"
resValue "string", "application_name", "Neo Store-alpha"
manifestPlaceholders = [
appIcon : "@mipmap/ic_launcher_debug",

View File

@ -9,6 +9,7 @@
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
tools:ignore="QueryAllPackagesPermission" />
<uses-permission android:name="android.permission.UPDATE_PACKAGES_WITHOUT_USER_ACTION" />

View File

@ -15,8 +15,8 @@ const val TABLE_CATEGORY_NAME = "category"
const val TABLE_CATEGORY_TEMP_NAME = "temporary_category"
const val TABLE_INSTALLED = "installed"
const val TABLE_INSTALLED_NAME = "memory_installed"
const val TABLE_LOCK = "lock"
const val TABLE_LOCK_NAME = "memory_lock"
const val TABLE_IGNORED = "lock"
const val TABLE_IGNORED_NAME = "memory_lock"
const val TABLE_PRODUCT = "product"
const val TABLE_PRODUCT_NAME = "product"
const val TABLE_PRODUCT_TEMP_NAME = "temporary_product"
@ -43,7 +43,6 @@ const val ROW_ANTIFEATURES = "antiFeatures"
const val ROW_LICENSES = "licenses"
const val ROW_DONATES = "donates"
const val ROW_SCREENSHOTS = "screenshots"
const val ROW_VERSION = "version"
const val ROW_SIGNATURE = "signature"
const val ROW_ID = "_id"
const val ROW_ENABLED = "enabled"

View File

@ -37,7 +37,8 @@ object Preferences {
Key.Theme,
Key.DefaultTab,
Key.UpdateNotify,
Key.UpdateUnstable
Key.UpdateUnstable,
Key.IgnoreIgnoreBatteryOptimization
).map { Pair(it.name, it) }.toMap()
fun init(context: Context) {
@ -178,6 +179,9 @@ object Preferences {
object UpdateNotify : Key<Boolean>("update_notify", Value.BooleanValue(true))
object UpdateUnstable : Key<Boolean>("update_unstable", Value.BooleanValue(false))
object IgnoreIgnoreBatteryOptimization :
Key<Boolean>("ignore_ignore_battery_optimization", Value.BooleanValue(false))
}
sealed class AutoSync(override val valueString: String) : Enumeration<AutoSync> {

View File

@ -3,7 +3,7 @@ package com.looker.droidify.content
import android.content.Context
import android.content.SharedPreferences
import com.looker.droidify.database.DatabaseX
import com.looker.droidify.database.entity.Lock
import com.looker.droidify.database.entity.Ignored
import com.looker.droidify.entity.ProductPreference
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@ -27,13 +27,13 @@ object ProductPreferences {
db.lockDao.insert(*preferences.all.keys
.mapNotNull { pName ->
this@ProductPreferences[pName].databaseVersionCode?.let {
Lock(pName, it)
Ignored(pName, it)
}
}
.toTypedArray()
)
subject.collect { (packageName, versionCode) ->
if (versionCode != null) db.lockDao.insert(Lock(packageName, versionCode))
if (versionCode != null) db.lockDao.insert(Ignored(packageName, versionCode))
else db.lockDao.delete(packageName)
}
}

View File

@ -144,7 +144,7 @@ interface ProductDao : BaseDao<Product> {
builder += """SELECT $TABLE_PRODUCT.rowid AS $ROW_ID, $TABLE_PRODUCT.$ROW_REPOSITORY_ID,
$TABLE_PRODUCT.$ROW_PACKAGE_NAME, $TABLE_PRODUCT.$ROW_LABEL,
$TABLE_PRODUCT.$ROW_SUMMARY, $TABLE_PRODUCT.$ROW_DESCRIPTION,
(COALESCE($TABLE_LOCK.$ROW_VERSION_CODE, -1) NOT IN (0, $TABLE_PRODUCT.$ROW_VERSION_CODE) AND
(COALESCE($TABLE_IGNORED.$ROW_VERSION_CODE, -1) NOT IN (0, $TABLE_PRODUCT.$ROW_VERSION_CODE) AND
$TABLE_PRODUCT.$ROW_COMPATIBLE != 0 AND
$TABLE_PRODUCT.$ROW_VERSION_CODE > COALESCE($TABLE_INSTALLED.$ROW_VERSION_CODE, 0xffffffff) AND
$signatureMatches) AS $ROW_CAN_UPDATE, $TABLE_PRODUCT.$ROW_ICON,
@ -173,8 +173,8 @@ interface ProductDao : BaseDao<Product> {
ON $TABLE_PRODUCT.$ROW_REPOSITORY_ID = $TABLE_REPOSITORY.$ROW_ID"""
// Merge the matching locks
builder += """LEFT JOIN $TABLE_LOCK_NAME AS $TABLE_LOCK
ON $TABLE_PRODUCT.$ROW_PACKAGE_NAME = $TABLE_LOCK.$ROW_PACKAGE_NAME"""
builder += """LEFT JOIN $TABLE_IGNORED_NAME AS $TABLE_IGNORED
ON $TABLE_PRODUCT.$ROW_PACKAGE_NAME = $TABLE_IGNORED.$ROW_PACKAGE_NAME"""
// Merge the matching installed
if (!installed && !updates) builder += "LEFT"
@ -291,7 +291,7 @@ interface InstalledDao : BaseDao<Installed> {
}
@Dao
interface LockDao : BaseDao<Lock> {
interface LockDao : BaseDao<Ignored> {
@Query("DELETE FROM memory_lock WHERE packageName = :packageName")
fun delete(packageName: String)
}

View File

@ -20,7 +20,7 @@ import kotlinx.coroutines.launch
Category::class,
CategoryTemp::class,
Installed::class,
Lock::class
Ignored::class
], version = 6
)
@TypeConverters(Converters::class)

View File

@ -2,10 +2,11 @@ package com.looker.droidify.database.entity
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.looker.droidify.TABLE_LOCK_NAME
import com.looker.droidify.TABLE_IGNORED_NAME
@Entity(tableName = TABLE_LOCK_NAME)
data class Lock(
// TODO complete renaming to Ignored
@Entity(tableName = TABLE_IGNORED_NAME)
data class Ignored(
@PrimaryKey
var packageName: String = "",
var versionCode: Long = 0L

View File

@ -37,6 +37,7 @@ import java.io.File
import java.security.MessageDigest
import kotlin.math.roundToInt
// TODO maybe replace by using WorkManager instead?
class DownloadService : ConnectionService<DownloadService.Binder>() {
companion object {
private const val ACTION_CANCEL = "${BuildConfig.APPLICATION_ID}.intent.action.CANCEL"

View File

@ -3,6 +3,7 @@ package com.looker.droidify.ui.activities
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.os.PowerManager
import android.view.Menu
import android.view.MenuItem
import android.view.inputmethod.InputMethodManager
@ -31,6 +32,7 @@ import com.looker.droidify.ui.fragments.Source
import com.looker.droidify.ui.viewmodels.MainActivityViewModelX
import com.looker.droidify.utility.extension.android.Android
import com.looker.droidify.utility.extension.text.nullIfEmpty
import com.looker.droidify.utility.showBatteryOptimizationDialog
import kotlinx.coroutines.launch
import kotlin.properties.Delegates
@ -52,6 +54,7 @@ class MainActivityX : AppCompatActivity() {
lateinit var appBarConfiguration: AppBarConfiguration
private lateinit var navController: NavController
private val viewModel: MainActivityViewModelX by viewModels()
private lateinit var powerManager: PowerManager
val menuSetup = MutableLiveData<Boolean>()
val syncConnection = Connection(SyncService::class.java, onBind = { _, _ ->
@ -95,6 +98,7 @@ class MainActivityX : AppCompatActivity() {
setupActionBarWithNavController(navController, appBarConfiguration)
binding.bottomNavigation.selectedItemId = currentTab
powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
if (savedInstanceState == null && (intent.flags and Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0) {
handleIntent(intent)
}
@ -117,6 +121,8 @@ class MainActivityX : AppCompatActivity() {
super.onResume()
if (currentTheme != Preferences[Preferences.Key.Theme].getResId(resources.configuration))
recreate()
if (!powerManager.isIgnoringBatteryOptimizations(this.packageName) && !Preferences[Preferences.Key.IgnoreIgnoreBatteryOptimization])
showBatteryOptimizationDialog()
}
override fun onSupportNavigateUp(): Boolean {

View File

@ -30,11 +30,12 @@ import com.looker.droidify.ui.compose.components.RepositoryItem
fun ProductsVerticalRecycler(
productsList: List<Product>?,
repositories: Map<Long, Repository>,
modifier: Modifier = Modifier.fillMaxSize(),
onUserClick: (ProductItem) -> Unit = {},
onFavouriteClick: (ProductItem) -> Unit = {},
onInstallClick: (ProductItem) -> Unit = {}
) {
VerticalItemList(list = productsList) {
VerticalItemList(list = productsList, modifier = modifier) {
it.toItem().let { item ->
ProductsListItem(
item,
@ -84,7 +85,7 @@ fun RepositoriesRecycler(
@Composable
fun <T> VerticalItemList(
modifier: Modifier = Modifier,
modifier: Modifier = Modifier.fillMaxSize(),
backgroundColor: Color = MaterialTheme.colorScheme.background,
list: List<T>?,
itemKey: ((T) -> Any)? = null,
@ -92,7 +93,6 @@ fun <T> VerticalItemList(
) {
Box(
modifier = modifier
.fillMaxSize()
.background(backgroundColor),
contentAlignment = if (list.isNullOrEmpty()) Alignment.Center else Alignment.TopStart
) {

View File

@ -28,12 +28,13 @@ fun ProductCard(
onUserClick: (ProductItem) -> Unit = {}
) {
val imageData by remember(item, repo) {
val product by remember(item) { mutableStateOf(item) }
val imageData by remember(product, repo) {
mutableStateOf(
CoilDownloader.createIconUri(
item.packageName,
item.icon,
item.metadataIcon,
product.packageName,
product.icon,
product.metadataIcon,
repo?.address,
repo?.authentication
).toString()
@ -46,7 +47,7 @@ fun ProductCard(
.requiredSize(80.dp, 116.dp)
.clip(shape = RoundedCornerShape(8.dp))
.background(color = MaterialTheme.colorScheme.surface)
.clickable(onClick = { onUserClick(item) }),
.clickable(onClick = { onUserClick(product) }),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
@ -57,7 +58,7 @@ fun ProductCard(
Text(
modifier = Modifier.padding(4.dp, 2.dp),
text = item.name,
text = product.name,
style = MaterialTheme.typography.bodySmall,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
@ -65,7 +66,7 @@ fun ProductCard(
)
Text(
modifier = Modifier.padding(4.dp, 1.dp),
text = item.version,
text = product.version,
style = MaterialTheme.typography.labelSmall,
overflow = TextOverflow.Ellipsis,
maxLines = 1,

View File

@ -32,12 +32,13 @@ fun ProductsListItem(
onFavouriteClick: (ProductItem) -> Unit = {},
onInstallClick: (ProductItem) -> Unit = {}
) {
val imageData by remember(item, repo) {
val product by remember(item) { mutableStateOf(item) }
val imageData by remember(product, repo) {
mutableStateOf(
CoilDownloader.createIconUri(
item.packageName,
item.icon,
item.metadataIcon,
product.packageName,
product.icon,
product.metadataIcon,
repo?.address,
repo?.authentication
).toString()
@ -46,10 +47,10 @@ fun ProductsListItem(
ExpandableCard(
modifier = Modifier.padding(horizontal = 8.dp, vertical = 8.dp),
onClick = { onUserClick(item) },
onClick = { onUserClick(product) },
expandedContent = {
ExpandedItemContent(
item = item,
item = product,
onFavourite = onFavouriteClick,
onInstallClicked = onInstallClick
)
@ -74,7 +75,7 @@ fun ProductsListItem(
.fillMaxHeight(0.4f),
) {
Text(
text = item.name,
text = product.name,
modifier = Modifier
.align(Alignment.CenterVertically)
.weight(1f),
@ -84,8 +85,8 @@ fun ProductsListItem(
style = MaterialTheme.typography.titleMedium
)
Text(
text = item.version,
modifier = Modifier.align(Alignment.CenterVertically),
text = product.version,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
style = MaterialTheme.typography.bodySmall,
@ -95,7 +96,7 @@ fun ProductsListItem(
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth(),
text = item.summary,
text = product.summary,
style = MaterialTheme.typography.bodySmall,
overflow = TextOverflow.Ellipsis,
maxLines = 2,

View File

@ -1,16 +1,14 @@
package com.looker.droidify.ui.compose.utils
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Chip
import androidx.compose.material.ChipColors
import androidx.compose.material.ChipDefaults
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.*
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.unit.dp
@ -29,7 +27,8 @@ fun ChipRow(
) {
LazyRow(
modifier = modifier,
horizontalArrangement = Arrangement.spacedBy(8.dp)
horizontalArrangement = Arrangement.spacedBy(8.dp),
contentPadding = PaddingValues(horizontal = 8.dp)
) {
items(list) {
Chip(
@ -40,7 +39,47 @@ fun ChipRow(
Text(
text = it,
style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.primary.copy(alpha = ChipDefaults.ContentOpacity)
color = chipColors.contentColor(enabled = true).value
)
}
}
}
}
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun SelectableChipRow(
modifier: Modifier = Modifier,
list: List<String>,
chipColors: SelectableChipColors = ChipDefaults.filterChipColors(
backgroundColor = MaterialTheme.colorScheme.surface,
contentColor = MaterialTheme.colorScheme.onSurface,
selectedBackgroundColor = MaterialTheme.colorScheme.primary,
selectedContentColor = MaterialTheme.colorScheme.onPrimary
),
shapes: Shape = RoundedCornerShape(50),
onClick: (String) -> Unit
) {
var selected by remember { mutableStateOf(list[0]) }
LazyRow(
modifier = modifier,
horizontalArrangement = Arrangement.spacedBy(8.dp),
contentPadding = PaddingValues(horizontal = 8.dp)
) {
items(list) {
FilterChip(
shape = shapes,
colors = chipColors,
selected = it == selected,
onClick = {
onClick(it)
selected = it
}
) {
Text(
text = it,
color = chipColors.contentColor(enabled = true, selected = it == selected).value
)
}
}

View File

@ -7,10 +7,8 @@ import androidx.fragment.app.Fragment
abstract class BaseNavFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupAdapters()
setupLayout()
}
abstract fun setupAdapters()
abstract fun setupLayout()
}

View File

@ -5,18 +5,26 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.SearchView
import androidx.compose.foundation.background
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material.Scaffold
import androidx.core.view.children
import com.google.android.material.chip.Chip
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import com.looker.droidify.R
import com.looker.droidify.content.Preferences
import com.looker.droidify.database.entity.Category
import com.looker.droidify.database.entity.Product
import com.looker.droidify.database.entity.Repository
import com.looker.droidify.databinding.FragmentExploreXBinding
import com.looker.droidify.entity.Section
import com.looker.droidify.ui.compose.ProductsVerticalRecycler
import com.looker.droidify.ui.compose.theme.AppTheme
import com.looker.droidify.ui.compose.utils.SelectableChipRow
import com.looker.droidify.utility.isDarkTheme
import com.looker.droidify.widget.FocusSearchView
@ -40,67 +48,15 @@ class ExploreFragment : MainNavFragmentX() {
return binding.root
}
override fun setupAdapters() {
}
override fun setupLayout() {
viewModel.repositories.observe(viewLifecycleOwner) {
repositories = it.associateBy { repo -> repo.id }
}
viewModel.primaryProducts.observe(viewLifecycleOwner) {
binding.primaryComposeRecycler.setContent {
AppTheme(
darkTheme = when (Preferences[Preferences.Key.Theme]) {
is Preferences.Theme.System -> isSystemInDarkTheme()
is Preferences.Theme.AmoledSystem -> isSystemInDarkTheme()
else -> isDarkTheme
}
) {
Scaffold { _ ->
ProductsVerticalRecycler(it, repositories,
onUserClick = { item ->
AppSheetX(item.packageName)
.showNow(parentFragmentManager, "Product ${item.packageName}")
},
onFavouriteClick = {},
onInstallClick = {
mainActivityX.syncConnection.binder?.installApps(listOf(it))
}
)
}
}
}
redrawPage(it, viewModel.categories.value ?: emptyList())
}
viewModel.categories.observe(viewLifecycleOwner) {
binding.categories.apply {
removeAllViews()
addView(Chip(requireContext(), null, R.attr.categoryChipStyle).apply {
setText(R.string.all_applications)
id = R.id.SHOW_ALL
})
it.sorted().forEach {
addView(Chip(requireContext(), null, R.attr.categoryChipStyle).apply {
text = it
})
}
val selectedSection = viewModel.sections.value
check(
children.filterNotNull()
.find { child ->
child is Chip && selectedSection is Category && child.text == selectedSection.label
}?.id ?: R.id.SHOW_ALL
)
}
}
binding.categories.setOnCheckedStateChangeListener { group, checkedIds ->
group.findViewById<Chip>(checkedIds[0]).let {
viewModel.setSection(
if (it.text.equals(getString(R.string.all_applications)))
Section.All
else
Section.Category(it.text.toString())
)
}
redrawPage(viewModel.primaryProducts.value, it)
}
mainActivityX.menuSetup.observe(viewLifecycleOwner) {
if (it != null) {
@ -122,4 +78,53 @@ class ExploreFragment : MainNavFragmentX() {
}
}
}
@OptIn(ExperimentalMaterialApi::class, ExperimentalMaterial3Api::class)
private fun redrawPage(products: List<Product>?, categories: List<String> = emptyList()) {
binding.primaryComposeRecycler.setContent {
AppTheme(
darkTheme = when (Preferences[Preferences.Key.Theme]) {
is Preferences.Theme.System -> isSystemInDarkTheme()
is Preferences.Theme.AmoledSystem -> isSystemInDarkTheme()
else -> isDarkTheme
}
) {
Scaffold { _ ->
Column(
Modifier
.background(MaterialTheme.colorScheme.background)
.fillMaxSize()
) {
SelectableChipRow(
list = listOf(
stringResource(id = R.string.all_applications),
*categories.sorted().toTypedArray()
)
) {
viewModel.setSection(
when (it) {
getString(R.string.all_applications) -> Section.All
else -> Section.Category(it)
}
)
}
ProductsVerticalRecycler(products,
repositories,
Modifier
.fillMaxWidth()
.weight(1f),
onUserClick = { item ->
AppSheetX(item.packageName)
.showNow(parentFragmentManager, "Product ${item.packageName}")
},
onFavouriteClick = {},
onInstallClick = {
mainActivityX.syncConnection.binder?.installApps(listOf(it))
}
)
}
}
}
}
}
}

View File

@ -39,9 +39,6 @@ class InstalledFragment : MainNavFragmentX() {
return binding.root
}
override fun setupAdapters() {
}
override fun setupLayout() {
viewModel.repositories.observe(viewLifecycleOwner) {
repositories = it.associateBy { repo -> repo.id }

View File

@ -39,9 +39,6 @@ class LatestFragment : MainNavFragmentX() {
return binding.root
}
override fun setupAdapters() {
}
override fun setupLayout() {
viewModel.repositories.observe(viewLifecycleOwner) {
repositories = it.associateBy { repo -> repo.id }

View File

@ -43,12 +43,9 @@ class PrefsRepositoriesFragment : BaseNavFragment() {
return binding.root
}
override fun setupAdapters() {
override fun setupLayout() {
syncConnection.bind(requireContext())
binding.addRepository.setOnClickListener { viewModel.addRepository() }
}
override fun setupLayout() {
viewModel.repositories.observe(requireActivity()) {
binding.reposRecycler.setContent {
AppTheme(

View File

@ -3,11 +3,19 @@ package com.looker.droidify.utility
import android.app.ActivityManager
import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.content.pm.PackageInfo
import android.content.pm.Signature
import android.content.res.Configuration
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.PowerManager
import android.provider.Settings
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import com.looker.droidify.BuildConfig
import com.looker.droidify.PREFS_LANGUAGE_DEFAULT
import com.looker.droidify.R
@ -193,4 +201,28 @@ val isBlackTheme: Boolean
is Preferences.Theme.Amoled -> true
is Preferences.Theme.AmoledSystem -> true
else -> false
}
}
fun Context.showBatteryOptimizationDialog() {
AlertDialog.Builder(this)
.setTitle(R.string.ignore_battery_optimization_title)
.setMessage(R.string.ignore_battery_optimization_message)
.setPositiveButton(R.string.dialog_approve) { dialog: DialogInterface?, _: Int ->
val intent = Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
intent.data = Uri.parse("package:" + this.packageName)
try {
startActivity(intent)
} catch (e: ActivityNotFoundException) {
Toast.makeText(
this,
R.string.ignore_battery_optimization_not_supported,
Toast.LENGTH_LONG
).show()
Preferences[Preferences.Key.IgnoreIgnoreBatteryOptimization] = true
}
}
.setNeutralButton(R.string.dialog_refuse) { _: DialogInterface?, _: Int ->
Preferences[Preferences.Key.IgnoreIgnoreBatteryOptimization] = true
}
.show()
}

View File

@ -15,8 +15,7 @@
~ You should have received a copy of the GNU Affero General Public License
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
@ -26,33 +25,10 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
<androidx.compose.ui.platform.ComposeView
android:id="@+id/primaryComposeRecycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:nestedScrollingEnabled="true"
android:orientation="vertical">
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none">
<com.google.android.material.chip.ChipGroup
android:id="@+id/categories"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="true"
android:paddingHorizontal="@dimen/shape_margin_medium"
app:selectionRequired="true"
app:singleSelection="true" />
</HorizontalScrollView>
<androidx.compose.ui.platform.ComposeView
android:id="@+id/primaryComposeRecycler"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
android:layout_height="match_parent" />
</com.google.android.material.circularreveal.CircularRevealFrameLayout>
</layout>

View File

@ -189,4 +189,9 @@
<string name="default_tab">Default Tab</string>
<string name="pending">Pending</string>
<string name="installing">Installing</string>
<string name="ignore_battery_optimization_title">Ignore Battery Optimization</string>
<string name="ignore_battery_optimization_message">Starting Android 12 there\'s restrictions on running foreground services causing the app to crash on downloads. To prevent this, you should turn off the battery optimization</string>
<string name="ignore_battery_optimization_not_supported">The device doesn\'t support ignoring battery optimizations!</string>
<string name="dialog_refuse">Don\'t need it</string>
<string name="dialog_approve">Let\'s do it!</string>
</resources>