Refactor permissions manager

This commit is contained in:
MM20 2022-01-03 21:41:44 +01:00
parent 5c0d142fd9
commit b5005ee4ea
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
15 changed files with 183 additions and 84 deletions

View File

@ -21,6 +21,7 @@ import de.mm20.launcher2.websites.websitesModule
import de.mm20.launcher2.widgets.widgetsModule import de.mm20.launcher2.widgets.widgetsModule
import de.mm20.launcher2.wikipedia.wikipediaModule import de.mm20.launcher2.wikipedia.wikipediaModule
import de.mm20.launcher2.database.databaseModule import de.mm20.launcher2.database.databaseModule
import de.mm20.launcher2.permissions.permissionsModule
import de.mm20.launcher2.preferences.preferencesModule import de.mm20.launcher2.preferences.preferencesModule
import de.mm20.launcher2.weather.weatherModule import de.mm20.launcher2.weather.weatherModule
import kotlinx.coroutines.* import kotlinx.coroutines.*
@ -67,6 +68,7 @@ class LauncherApplication : Application(), CoroutineScope {
hiddenItemsModule, hiddenItemsModule,
iconsModule, iconsModule,
musicModule, musicModule,
permissionsModule,
preferencesModule, preferencesModule,
searchModule, searchModule,
unitConverterModule, unitConverterModule,
@ -86,10 +88,4 @@ class LauncherApplication : Application(), CoroutineScope {
} }
} }
} }
object PermissionRequests {
const val CALENDAR = 309
const val LOCATION = 410
const val ALL = 666
}

View File

@ -20,8 +20,11 @@ import de.mm20.launcher2.graphics.TextDrawable
import de.mm20.launcher2.icons.LauncherIcon import de.mm20.launcher2.icons.LauncherIcon
import de.mm20.launcher2.ktx.checkPermission import de.mm20.launcher2.ktx.checkPermission
import de.mm20.launcher2.ktx.dp import de.mm20.launcher2.ktx.dp
import de.mm20.launcher2.permissions.PermissionGroup
import de.mm20.launcher2.permissions.PermissionsManager import de.mm20.launcher2.permissions.PermissionsManager
import de.mm20.launcher2.preferences.LauncherPreferences import de.mm20.launcher2.preferences.LauncherPreferences
import org.koin.core.component.KoinComponent
import org.koin.core.component.get
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
@ -76,7 +79,7 @@ class CalendarEvent(
return null return null
} }
companion object { companion object: KoinComponent {
fun search( fun search(
context: Context, context: Context,
query: String, query: String,
@ -87,10 +90,11 @@ class CalendarEvent(
unselectedCalendars: List<Long> = emptyList(), unselectedCalendars: List<Long> = emptyList(),
hiddenEvents: List<Long> = emptyList() hiddenEvents: List<Long> = emptyList()
): List<CalendarEvent> { ): List<CalendarEvent> {
val permissionsManager: PermissionsManager = get()
val results = mutableListOf<CalendarEvent>() val results = mutableListOf<CalendarEvent>()
if (!query.isEmpty() && query.length < 3) return results if (!query.isEmpty() && query.length < 3) return results
if (!LauncherPreferences.instance.searchCalendars) return listOf() if (!LauncherPreferences.instance.searchCalendars) return listOf()
if (!PermissionsManager.checkPermission(context, PermissionsManager.CALENDAR)) { if (!permissionsManager.checkPermission(PermissionGroup.Calendar)) {
return emptyList() return emptyList()
} }
val builder = CalendarContract.Instances.CONTENT_URI.buildUpon() val builder = CalendarContract.Instances.CONTENT_URI.buildUpon()

View File

@ -14,10 +14,13 @@ import de.mm20.launcher2.graphics.TextDrawable
import de.mm20.launcher2.icons.LauncherIcon import de.mm20.launcher2.icons.LauncherIcon
import de.mm20.launcher2.ktx.asBitmap import de.mm20.launcher2.ktx.asBitmap
import de.mm20.launcher2.ktx.sp import de.mm20.launcher2.ktx.sp
import de.mm20.launcher2.permissions.PermissionGroup
import de.mm20.launcher2.permissions.PermissionsManager import de.mm20.launcher2.permissions.PermissionsManager
import de.mm20.launcher2.preferences.LauncherPreferences import de.mm20.launcher2.preferences.LauncherPreferences
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.koin.core.component.KoinComponent
import org.koin.core.component.get
class Contact( class Contact(
val id: Long, val id: Long,
@ -71,13 +74,14 @@ class Contact(
return null return null
} }
companion object { companion object: KoinComponent {
fun search(context: Context, query: String): List<Contact> { fun search(context: Context, query: String): List<Contact> {
if (query.length < 3) return mutableListOf() if (query.length < 3) return mutableListOf()
if (!LauncherPreferences.instance.searchContacts) { if (!LauncherPreferences.instance.searchContacts) {
return mutableListOf() return mutableListOf()
} }
if (!PermissionsManager.checkPermission(context, PermissionsManager.CONTACTS)) { val permissionsManager: PermissionsManager = get()
if (!permissionsManager.checkPermission(PermissionGroup.Contacts)) {
return mutableListOf() return mutableListOf()
} }
val proj = arrayOf( val proj = arrayOf(

View File

@ -4,11 +4,14 @@ import android.content.Context
import android.provider.MediaStore import android.provider.MediaStore
import androidx.core.database.getStringOrNull import androidx.core.database.getStringOrNull
import de.mm20.launcher2.ktx.jsonObjectOf import de.mm20.launcher2.ktx.jsonObjectOf
import de.mm20.launcher2.permissions.PermissionGroup
import de.mm20.launcher2.permissions.PermissionsManager import de.mm20.launcher2.permissions.PermissionsManager
import de.mm20.launcher2.search.SearchableDeserializer import de.mm20.launcher2.search.SearchableDeserializer
import de.mm20.launcher2.search.SearchableSerializer import de.mm20.launcher2.search.SearchableSerializer
import de.mm20.launcher2.search.data.* import de.mm20.launcher2.search.data.*
import org.json.JSONObject import org.json.JSONObject
import org.koin.core.component.KoinComponent
import org.koin.core.component.get
class LocalFileSerializer : SearchableSerializer { class LocalFileSerializer : SearchableSerializer {
override fun serialize(searchable: Searchable): String { override fun serialize(searchable: Searchable): String {
@ -24,11 +27,11 @@ class LocalFileSerializer : SearchableSerializer {
class LocalFileDeserializer( class LocalFileDeserializer(
val context: Context val context: Context
) : SearchableDeserializer { ) : SearchableDeserializer, KoinComponent {
override fun deserialize(serialized: String): Searchable? { override fun deserialize(serialized: String): Searchable? {
if (!PermissionsManager.checkPermission( val permissionsManager: PermissionsManager = get()
context, if (!permissionsManager.checkPermission(
PermissionsManager.EXTERNAL_STORAGE PermissionGroup.ExternalStorage
) )
) return null ) return null
val json = JSONObject(serialized) val json = JSONObject(serialized)

View File

@ -21,10 +21,13 @@ import de.mm20.launcher2.files.R
import de.mm20.launcher2.icons.LauncherIcon import de.mm20.launcher2.icons.LauncherIcon
import de.mm20.launcher2.ktx.formatToString import de.mm20.launcher2.ktx.formatToString
import de.mm20.launcher2.media.ThumbnailUtilsCompat import de.mm20.launcher2.media.ThumbnailUtilsCompat
import de.mm20.launcher2.permissions.PermissionGroup
import de.mm20.launcher2.permissions.PermissionsManager import de.mm20.launcher2.permissions.PermissionsManager
import de.mm20.launcher2.preferences.LauncherPreferences import de.mm20.launcher2.preferences.LauncherPreferences
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.koin.core.component.KoinComponent
import org.koin.core.component.get
import java.io.IOException import java.io.IOException
import java.util.* import java.util.*
import java.io.File as JavaIOFile import java.io.File as JavaIOFile
@ -161,14 +164,14 @@ open class LocalFile(
companion object { companion object: KoinComponent {
fun search(context: Context, query: String): List<LocalFile> { fun search(context: Context, query: String): List<LocalFile> {
val results = mutableListOf<LocalFile>() val results = mutableListOf<LocalFile>()
if (!LauncherPreferences.instance.searchFiles) return results if (!LauncherPreferences.instance.searchFiles) return results
if (query.isBlank()) return results if (query.isBlank()) return results
if (!PermissionsManager.checkPermission( val permissionsManager: PermissionsManager = get()
context, if (!permissionsManager.checkPermission(
PermissionsManager.EXTERNAL_STORAGE PermissionGroup.ExternalStorage
) )
) return results ) return results
val uri = MediaStore.Files.getContentUri("external").buildUpon() val uri = MediaStore.Files.getContentUri("external").buildUpon()

View File

@ -39,6 +39,8 @@ dependencies {
implementation(libs.androidx.core) implementation(libs.androidx.core)
implementation(libs.androidx.appcompat) implementation(libs.androidx.appcompat)
implementation(libs.koin.android)
implementation(project(":ktx")) implementation(project(":ktx"))
implementation(project(":base")) implementation(project(":base"))
implementation(project(":icons")) implementation(project(":icons"))

View File

@ -4,11 +4,12 @@ import android.content.Context
import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import de.mm20.launcher2.icons.LauncherIcon import de.mm20.launcher2.icons.LauncherIcon
import de.mm20.launcher2.permissions.PermissionGroup
import de.mm20.launcher2.permissions.R import de.mm20.launcher2.permissions.R
class MissingPermission(override val label: String, val permissionGroup: Int): Searchable() { class MissingPermission(override val label: String, val permissionGroup: PermissionGroup): Searchable() {
override val key: String override val key: String
get() = "permission://${permissionGroup}" get() = "permission://${permissionGroup.ordinal}"
override fun getPlaceholderIcon(context: Context): LauncherIcon { override fun getPlaceholderIcon(context: Context): LauncherIcon {
return LauncherIcon( return LauncherIcon(

View File

@ -0,0 +1,8 @@
package de.mm20.launcher2.permissions
import org.koin.android.ext.koin.androidContext
import org.koin.dsl.module
val permissionsModule = module {
single<PermissionsManager> { PermissionsManagerImpl(androidContext()) }
}

View File

@ -1,55 +1,75 @@
package de.mm20.launcher2.permissions package de.mm20.launcher2.permissions
import android.Manifest import android.Manifest
import android.app.Activity
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Environment import android.os.Environment
import android.provider.Settings import android.provider.Settings
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import de.mm20.launcher2.ktx.checkPermission import de.mm20.launcher2.ktx.checkPermission
import de.mm20.launcher2.ktx.isAtLeastApiLevel import de.mm20.launcher2.ktx.isAtLeastApiLevel
object PermissionsManager { interface PermissionsManager {
fun requestPermission(context: AppCompatActivity, permissionGroup: PermissionGroup)
fun requestPermission(context: Activity, permissionGroup: Int) { fun checkPermission(permissionGroup: PermissionGroup): Boolean
}
enum class PermissionGroup {
Calendar,
Location,
Contacts,
ExternalStorage
}
class PermissionsManagerImpl(
private val context: Context
): PermissionsManager {
override fun requestPermission(activity: AppCompatActivity, permissionGroup: PermissionGroup) {
when (permissionGroup) { when (permissionGroup) {
CALENDAR -> { PermissionGroup.Calendar -> {
ActivityCompat.requestPermissions(context, calendarPermissions, permissionGroup) ActivityCompat.requestPermissions(activity, calendarPermissions, permissionGroup.ordinal)
} }
LOCATION -> { PermissionGroup.Location -> {
ActivityCompat.requestPermissions(context, locationPermissions, permissionGroup) ActivityCompat.requestPermissions(activity, locationPermissions, permissionGroup.ordinal)
} }
CONTACTS -> { PermissionGroup.Contacts -> {
ActivityCompat.requestPermissions(context, contactPermissions, permissionGroup) ActivityCompat.requestPermissions(activity, contactPermissions, permissionGroup.ordinal)
} }
EXTERNAL_STORAGE -> { PermissionGroup.ExternalStorage -> {
if (isAtLeastApiLevel(Build.VERSION_CODES.R)) { if (isAtLeastApiLevel(Build.VERSION_CODES.R)) {
val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION).also { val intent =
it.data = Uri.parse("package:${context.packageName}") Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION).also {
} it.data = Uri.parse("package:${activity.packageName}")
context.startActivity(intent) }
activity.startActivity(intent)
} else { } else {
ActivityCompat.requestPermissions(context, externalStoragePermissions, permissionGroup) ActivityCompat.requestPermissions(
activity,
externalStoragePermissions,
permissionGroup.ordinal
)
} }
} }
} }
} }
fun checkPermission(context: Context, permissionGroup: Int): Boolean { override fun checkPermission(permissionGroup: PermissionGroup): Boolean {
return when (permissionGroup) { return when (permissionGroup) {
CALENDAR -> { PermissionGroup.Calendar -> {
calendarPermissions.all { context.checkPermission(it) } calendarPermissions.all { context.checkPermission(it) }
} }
LOCATION -> { PermissionGroup.Location -> {
locationPermissions.all { context.checkPermission(it) } locationPermissions.all { context.checkPermission(it) }
} }
CONTACTS -> { PermissionGroup.Contacts -> {
contactPermissions.all { context.checkPermission(it) } contactPermissions.all { context.checkPermission(it) }
} }
EXTERNAL_STORAGE -> { PermissionGroup.ExternalStorage -> {
if (isAtLeastApiLevel(Build.VERSION_CODES.R)) { if (isAtLeastApiLevel(Build.VERSION_CODES.R)) {
Environment.isExternalStorageManager() Environment.isExternalStorageManager()
} else { } else {
@ -60,15 +80,14 @@ object PermissionsManager {
} }
} }
const val CALENDAR = 0x1
private val calendarPermissions = arrayOf(Manifest.permission.READ_CALENDAR) private val calendarPermissions = arrayOf(Manifest.permission.READ_CALENDAR)
const val LOCATION = 0x2 private val locationPermissions = arrayOf(
private val locationPermissions = arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION) Manifest.permission.ACCESS_COARSE_LOCATION,
const val CONTACTS = 0x4 Manifest.permission.ACCESS_FINE_LOCATION
)
private val contactPermissions = arrayOf(Manifest.permission.READ_CONTACTS) private val contactPermissions = arrayOf(Manifest.permission.READ_CONTACTS)
const val EXTERNAL_STORAGE = 0x8 private val externalStoragePermissions = arrayOf(
private val externalStoragePermissions = arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE) Manifest.permission.READ_EXTERNAL_STORAGE,
const val NOTIFICATIONS = 0x10 Manifest.permission.WRITE_EXTERNAL_STORAGE
)
const val ALL = 0x12
} }

View File

@ -0,0 +1,63 @@
package de.mm20.launcher2.ui.component
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Lock
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
@Composable
fun MissingPermissionBanner(
modifier: Modifier = Modifier,
text: String,
onClick: () -> Unit,
secondaryAction: @Composable () -> Unit = {}
) {
Surface(
modifier = modifier,
color = MaterialTheme.colorScheme.primaryContainer,
shape = RoundedCornerShape(8.dp)
) {
Column {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
Icon(
modifier = Modifier.padding(16.dp),
imageVector = Icons.Rounded.Lock,
contentDescription = null
)
Text(
text = text,
modifier = Modifier
.weight(1f)
.padding(vertical = 16.dp)
.padding(end = 16.dp),
style = MaterialTheme.typography.bodyMedium
)
}
Row(
Modifier
.align(Alignment.End)
.padding(8.dp)
) {
secondaryAction()
TextButton(
modifier = Modifier.padding(start = 8.dp),
onClick = onClick) {
Text("Grant", style = MaterialTheme.typography.labelLarge)
}
}
}
}
}

View File

@ -213,14 +213,6 @@ class LauncherActivity : AppCompatActivity() {
ThemeHelper.applyTheme(theme) ThemeHelper.applyTheme(theme)
if (LauncherPreferences.instance.firstRunVersion < 1) { if (LauncherPreferences.instance.firstRunVersion < 1) {
ActivityCompat.requestPermissions(
this, arrayOf(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
), PermissionsManager.ALL
)
LauncherPreferences.instance.firstRunVersion = 1 LauncherPreferences.instance.firstRunVersion = 1
} }
@ -646,15 +638,6 @@ class LauncherActivity : AppCompatActivity() {
) { ) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults) super.onRequestPermissionsResult(requestCode, permissions, grantResults)
search(binding.searchBar.getSearchQuery()) search(binding.searchBar.getSearchQuery())
when (requestCode) {
PermissionsManager.LOCATION -> {
ViewModelProvider(this).get(WeatherViewModel::class.java).requestUpdate(this)
}
PermissionsManager.ALL -> {
ViewModelProvider(this).get(WeatherViewModel::class.java).requestUpdate(this)
search(binding.searchBar.getSearchQuery())
}
}
} }
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {

View File

@ -9,6 +9,7 @@ import android.widget.FrameLayout
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import de.mm20.launcher2.permissions.PermissionGroup
import de.mm20.launcher2.permissions.PermissionsManager import de.mm20.launcher2.permissions.PermissionsManager
import de.mm20.launcher2.preferences.LauncherPreferences import de.mm20.launcher2.preferences.LauncherPreferences
import de.mm20.launcher2.search.data.CalendarEvent import de.mm20.launcher2.search.data.CalendarEvent
@ -16,8 +17,10 @@ import de.mm20.launcher2.search.data.MissingPermission
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.launcher.search.SearchViewModel import de.mm20.launcher2.ui.launcher.search.SearchViewModel
import de.mm20.launcher2.ui.legacy.search.SearchListView import de.mm20.launcher2.ui.legacy.search.SearchListView
import org.koin.core.component.KoinComponent
import org.koin.core.component.get
class CalendarView : FrameLayout { class CalendarView : FrameLayout, KoinComponent {
constructor(context: Context) : super(context) constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
@ -30,6 +33,7 @@ class CalendarView : FrameLayout {
private val calendarEvents: LiveData<List<CalendarEvent>?> private val calendarEvents: LiveData<List<CalendarEvent>?>
init { init {
val permissionsManager: PermissionsManager = get()
View.inflate(context, R.layout.view_search_category_list, this) View.inflate(context, R.layout.view_search_category_list, this)
layoutTransition = LayoutTransition() layoutTransition = LayoutTransition()
layoutTransition.enableTransitionType(LayoutTransition.CHANGING) layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
@ -43,9 +47,8 @@ class CalendarView : FrameLayout {
visibility = View.GONE visibility = View.GONE
return@observe return@observe
} }
if (it.isEmpty() && LauncherPreferences.instance.searchCalendars && !PermissionsManager.checkPermission( if (it.isEmpty() && LauncherPreferences.instance.searchCalendars && !permissionsManager.checkPermission(
context, PermissionGroup.Calendar
PermissionsManager.CALENDAR
) )
) { ) {
visibility = View.VISIBLE visibility = View.VISIBLE
@ -53,7 +56,7 @@ class CalendarView : FrameLayout {
listOf( listOf(
MissingPermission( MissingPermission(
context.getString(R.string.permission_calendar_search), context.getString(R.string.permission_calendar_search),
PermissionsManager.CALENDAR PermissionGroup.Calendar
) )
) )
) )

View File

@ -10,6 +10,7 @@ import android.widget.SearchView
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import de.mm20.launcher2.permissions.PermissionGroup
import de.mm20.launcher2.permissions.PermissionsManager import de.mm20.launcher2.permissions.PermissionsManager
import de.mm20.launcher2.preferences.LauncherPreferences import de.mm20.launcher2.preferences.LauncherPreferences
import de.mm20.launcher2.search.data.Contact import de.mm20.launcher2.search.data.Contact
@ -17,8 +18,10 @@ import de.mm20.launcher2.search.data.MissingPermission
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.launcher.search.SearchViewModel import de.mm20.launcher2.ui.launcher.search.SearchViewModel
import de.mm20.launcher2.ui.legacy.search.SearchListView import de.mm20.launcher2.ui.legacy.search.SearchListView
import org.koin.core.component.KoinComponent
import org.koin.core.component.get
class ContactView : FrameLayout { class ContactView : FrameLayout, KoinComponent {
private val contacts: LiveData<List<Contact>?> private val contacts: LiveData<List<Contact>?>
constructor(context: Context) : super(context) constructor(context: Context) : super(context)
@ -30,6 +33,7 @@ class ContactView : FrameLayout {
) )
init { init {
val permissionsManager: PermissionsManager = get()
View.inflate(context, R.layout.view_search_category_list, this) View.inflate(context, R.layout.view_search_category_list, this)
layoutTransition = LayoutTransition() layoutTransition = LayoutTransition()
layoutTransition.enableTransitionType(LayoutTransition.CHANGING) layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
@ -43,9 +47,8 @@ class ContactView : FrameLayout {
visibility = View.GONE visibility = View.GONE
return@observe return@observe
} }
if (it.isEmpty() && LauncherPreferences.instance.searchContacts && !PermissionsManager.checkPermission( if (it.isEmpty() && LauncherPreferences.instance.searchContacts && !permissionsManager.checkPermission(
context, PermissionGroup.Contacts
PermissionsManager.CONTACTS
) )
) { ) {
visibility = View.VISIBLE visibility = View.VISIBLE
@ -53,7 +56,7 @@ class ContactView : FrameLayout {
listOf( listOf(
MissingPermission( MissingPermission(
context.getString(R.string.permission_contact_search), context.getString(R.string.permission_contact_search),
PermissionsManager.CONTACTS PermissionGroup.Contacts
) )
) )
) )

View File

@ -9,14 +9,17 @@ import android.widget.FrameLayout
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import de.mm20.launcher2.permissions.PermissionGroup
import de.mm20.launcher2.permissions.PermissionsManager import de.mm20.launcher2.permissions.PermissionsManager
import de.mm20.launcher2.search.data.File import de.mm20.launcher2.search.data.File
import de.mm20.launcher2.search.data.MissingPermission import de.mm20.launcher2.search.data.MissingPermission
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.launcher.search.SearchViewModel import de.mm20.launcher2.ui.launcher.search.SearchViewModel
import de.mm20.launcher2.ui.legacy.search.SearchListView import de.mm20.launcher2.ui.legacy.search.SearchListView
import org.koin.core.component.KoinComponent
import org.koin.core.component.get
class FileView : FrameLayout { class FileView : FrameLayout, KoinComponent {
private val files: LiveData<List<File>?> private val files: LiveData<List<File>?>
constructor(context: Context) : super(context) constructor(context: Context) : super(context)
@ -28,6 +31,7 @@ class FileView : FrameLayout {
) )
init { init {
val permissionsManager: PermissionsManager = get()
View.inflate(context, R.layout.view_search_category_list, this) View.inflate(context, R.layout.view_search_category_list, this)
layoutTransition = LayoutTransition() layoutTransition = LayoutTransition()
layoutTransition.enableTransitionType(LayoutTransition.CHANGING) layoutTransition.enableTransitionType(LayoutTransition.CHANGING)
@ -41,9 +45,8 @@ class FileView : FrameLayout {
visibility = View.GONE visibility = View.GONE
return@observe return@observe
} }
if (it.isEmpty() && !PermissionsManager.checkPermission( if (it.isEmpty() && !permissionsManager.checkPermission(
context, PermissionGroup.ExternalStorage
PermissionsManager.EXTERNAL_STORAGE
) )
) { ) {
visibility = View.VISIBLE visibility = View.VISIBLE
@ -51,7 +54,7 @@ class FileView : FrameLayout {
listOf( listOf(
MissingPermission( MissingPermission(
context.getString(R.string.permission_files_search), context.getString(R.string.permission_files_search),
PermissionsManager.EXTERNAL_STORAGE PermissionGroup.ExternalStorage
) )
) )
) )

View File

@ -2,6 +2,7 @@ package de.mm20.launcher2.ui.legacy.search
import android.app.Activity import android.app.Activity
import android.widget.TextView import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.transition.Scene import androidx.transition.Scene
import de.mm20.launcher2.permissions.PermissionsManager import de.mm20.launcher2.permissions.PermissionsManager
import de.mm20.launcher2.search.data.MissingPermission import de.mm20.launcher2.search.data.MissingPermission
@ -10,17 +11,20 @@ import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.legacy.searchable.SearchableView import de.mm20.launcher2.ui.legacy.searchable.SearchableView
import de.mm20.launcher2.ui.legacy.view.InnerCardView import de.mm20.launcher2.ui.legacy.view.InnerCardView
import de.mm20.launcher2.ui.legacy.view.LauncherIconView import de.mm20.launcher2.ui.legacy.view.LauncherIconView
import org.koin.core.component.KoinComponent
import org.koin.core.component.get
class PermissionListRepresentation : Representation { class PermissionListRepresentation : Representation, KoinComponent {
override fun getScene(rootView: SearchableView, searchable: Searchable, previousRepresentation: Int?): Scene { override fun getScene(rootView: SearchableView, searchable: Searchable, previousRepresentation: Int?): Scene {
val missingPermission = searchable as MissingPermission val missingPermission = searchable as MissingPermission
val context = rootView.context val context = rootView.context
val scene = Scene.getSceneForLayout(rootView, R.layout.view_permission_list, rootView.context) val scene = Scene.getSceneForLayout(rootView, R.layout.view_permission_list, rootView.context)
scene.setEnterAction { scene.setEnterAction {
val permissionsManager: PermissionsManager = get()
rootView.findViewById<TextView>(R.id.permissionText).text = missingPermission.label rootView.findViewById<TextView>(R.id.permissionText).text = missingPermission.label
rootView.findViewById<LauncherIconView>(R.id.permissionIcon).icon = missingPermission.getPlaceholderIcon(context) rootView.findViewById<LauncherIconView>(R.id.permissionIcon).icon = missingPermission.getPlaceholderIcon(context)
rootView.findViewById<InnerCardView>(R.id.card).setOnClickListener { rootView.findViewById<InnerCardView>(R.id.card).setOnClickListener {
PermissionsManager.requestPermission(context as Activity, missingPermission.permissionGroup) permissionsManager.requestPermission(context as AppCompatActivity, missingPermission.permissionGroup)
} }
} }
return scene return scene