Modify badge API

Pass searchable as argument instead of badgeKey which is now obsolete
This commit is contained in:
MM20 2022-03-05 15:00:33 +01:00
parent 9100af75bf
commit 47e7591975
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
25 changed files with 60 additions and 66 deletions

BIN
app/release/app-release.zip Normal file

Binary file not shown.

View File

@ -26,9 +26,6 @@ class AppInstallation(
override val key: String
get() = "installer://${session.installerPackageName}:${session.appPackageName}"
override val badgeKey: String
get() = "app://${session.appPackageName}"
override fun getLaunchIntent(context: Context): Intent? {
return session.createDetailsIntent()
}

View File

@ -32,7 +32,7 @@ class AppShortcut(
internal val userSerialNumber: Long = launcherShortcut.userHandle.getSerialNumber(context)
private val isMainProfile = launcherShortcut.userHandle == Process.myUserHandle()
val isMainProfile = launcherShortcut.userHandle == Process.myUserHandle()
override val key: String
get() = if (isMainProfile) {
@ -41,11 +41,6 @@ class AppShortcut(
"shortcut://${launcherShortcut.`package`}/${launcherShortcut.id}:${userSerialNumber}"
}
override val badgeKey: String
get() {
return if (isMainProfile) "shortcut://${launcherShortcut.activity?.flattenToShortString()}" else "profile://$userSerialNumber"
}
override fun getLaunchIntent(context: Context): Intent? {
return launcherShortcut.intent
}

View File

@ -20,9 +20,6 @@ abstract class Application(
val shortcuts: List<AppShortcut> = emptyList()
) : Searchable() {
override val badgeKey: String
get() = "app://${`package`}"
override fun serialize(): String {
val json = JSONObject()
json.put("package", `package`)

View File

@ -57,10 +57,7 @@ class LauncherApp(
), KoinComponent {
internal val userSerialNumber: Long = launcherActivityInfo.user.getSerialNumber(context)
private val isMainProfile = launcherActivityInfo.user == Process.myUserHandle()
override val badgeKey: String =
if (isMainProfile) "app://${`package`}" else "profile://$userSerialNumber"
val isMainProfile = launcherActivityInfo.user == Process.myUserHandle()
override val key: String
get() = if (isMainProfile) "app://$`package`:$activity" else "app://$`package`:$activity:${userSerialNumber}"

View File

@ -47,5 +47,6 @@ dependencies {
implementation(project(":notifications"))
implementation(project(":preferences"))
implementation(project(":base"))
implementation(project(":search"))
implementation(project(":files"))
}

View File

@ -3,13 +3,14 @@ package de.mm20.launcher2.badges
import android.content.Context
import de.mm20.launcher2.badges.providers.*
import de.mm20.launcher2.preferences.LauncherDataStore
import de.mm20.launcher2.search.data.Searchable
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
interface BadgeRepository {
fun getBadge(badgeKey: String): Flow<Badge?>
fun getBadge(searchable: Searchable): Flow<Badge?>
}
internal class BadgeRepositoryImpl(private val context: Context) : BadgeRepository, KoinComponent {
@ -23,6 +24,7 @@ internal class BadgeRepositoryImpl(private val context: Context) : BadgeReposito
scope.launch {
dataStore.data.map { it.badges }.distinctUntilChanged().collectLatest {
val providers = mutableListOf<BadgeProvider>()
providers += WorkProfileBadgeProvider()
if (it.notifications) {
providers += NotificationBadgeProvider()
}
@ -35,20 +37,19 @@ internal class BadgeRepositoryImpl(private val context: Context) : BadgeReposito
if (it.suspendedApps) {
providers += SuspendedAppsBadgeProvider()
}
providers += WorkProfileBadgeProvider(context)
badgeProviders.value = providers
}
}
}
override fun getBadge(badgeKey: String): Flow<Badge?> = channelFlow {
override fun getBadge(searchable: Searchable): Flow<Badge?> = channelFlow {
withContext(Dispatchers.Default) {
badgeProviders.collectLatest { providers ->
if (providers.isEmpty()) {
send(null)
return@collectLatest
}
combine(providers.map { it.getBadge(badgeKey) }) { badges ->
combine(providers.map { it.getBadge(searchable) }) { badges ->
if (badges.all { it == null }) {
return@combine null
}

View File

@ -5,6 +5,8 @@ import android.content.Context
import android.content.pm.PackageManager
import de.mm20.launcher2.badges.Badge
import de.mm20.launcher2.graphics.BadgeDrawable
import de.mm20.launcher2.search.data.AppShortcut
import de.mm20.launcher2.search.data.Searchable
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.channelFlow
@ -13,9 +15,9 @@ import kotlinx.coroutines.withContext
class AppShortcutBadgeProvider(
private val context: Context
) : BadgeProvider {
override fun getBadge(badgeKey: String): Flow<Badge?> = channelFlow {
if (badgeKey.startsWith("shortcut://")) {
val componentName = ComponentName.unflattenFromString(badgeKey.substring(11))
override fun getBadge(searchable: Searchable): Flow<Badge?> = channelFlow {
if (searchable is AppShortcut) {
val componentName = searchable.launcherShortcut.activity
if (componentName == null) {
send(null)
return@channelFlow

View File

@ -1,6 +1,7 @@
package de.mm20.launcher2.badges.providers
import de.mm20.launcher2.badges.Badge
import de.mm20.launcher2.search.data.Searchable
import kotlinx.coroutines.flow.Flow
interface BadgeProvider {
@ -9,5 +10,5 @@ interface BadgeProvider {
* BadgeRepository is waiting for values from every provider.
* null must be emitted if no badge should be shown.
*/
fun getBadge(badgeKey: String): Flow<Badge?>
fun getBadge(searchable: Searchable): Flow<Badge?>
}

View File

@ -3,17 +3,20 @@ package de.mm20.launcher2.badges.providers
import android.util.Log
import de.mm20.launcher2.badges.Badge
import de.mm20.launcher2.badges.R
import de.mm20.launcher2.search.data.File
import de.mm20.launcher2.search.data.Searchable
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
class CloudBadgeProvider: BadgeProvider {
override fun getBadge(badgeKey: String): Flow<Badge?> = flow {
when(badgeKey) {
"gdrive://" -> emit(Badge(iconRes = R.drawable.ic_badge_gdrive))
"onedrive://" -> emit(Badge(iconRes = R.drawable.ic_badge_onedrive))
"owncloud://" -> emit(Badge(iconRes = R.drawable.ic_badge_owncloud))
"nextcloud://" -> emit(Badge(iconRes = R.drawable.ic_badge_nextcloud))
else -> emit(null)
override fun getBadge(searchable: Searchable): Flow<Badge?> = flow {
if (searchable is File) {
val iconResId = searchable.providerIconRes
if (iconResId != null) {
emit(Badge(iconRes = iconResId))
return@flow
}
}
emit(null)
}
}

View File

@ -3,6 +3,9 @@ package de.mm20.launcher2.badges.providers
import android.app.Notification
import de.mm20.launcher2.badges.Badge
import de.mm20.launcher2.notifications.NotificationRepository
import de.mm20.launcher2.search.data.Application
import de.mm20.launcher2.search.data.LauncherApp
import de.mm20.launcher2.search.data.Searchable
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.channelFlow
import kotlinx.coroutines.flow.collectLatest
@ -13,9 +16,9 @@ import org.koin.core.component.inject
class NotificationBadgeProvider : BadgeProvider, KoinComponent {
private val notificationRepository: NotificationRepository by inject()
override fun getBadge(badgeKey: String): Flow<Badge?> = channelFlow {
if (badgeKey.startsWith("app://")) {
val packageName = badgeKey.substring(6)
override fun getBadge(searchable: Searchable): Flow<Badge?> = channelFlow {
if (searchable is Application) {
val packageName = searchable.`package`
notificationRepository.notifications.map {
it.filter { it.packageName == packageName }
}.collectLatest {

View File

@ -3,6 +3,9 @@ package de.mm20.launcher2.badges.providers
import de.mm20.launcher2.applications.AppRepository
import de.mm20.launcher2.badges.Badge
import de.mm20.launcher2.badges.R
import de.mm20.launcher2.search.data.Application
import de.mm20.launcher2.search.data.LauncherApp
import de.mm20.launcher2.search.data.Searchable
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.channelFlow
import kotlinx.coroutines.flow.collectLatest
@ -12,9 +15,9 @@ import org.koin.core.component.inject
class SuspendedAppsBadgeProvider : BadgeProvider, KoinComponent {
private val appRepository: AppRepository by inject()
override fun getBadge(badgeKey: String): Flow<Badge?> = channelFlow {
if (badgeKey.startsWith("app://")) {
val packageName = badgeKey.substring(6)
override fun getBadge(searchable: Searchable): Flow<Badge?> = channelFlow {
if (searchable is Application) {
val packageName = searchable.`package`
appRepository.getSuspendedPackages().collectLatest {
if (it.contains(packageName)) {
send(

View File

@ -1,26 +1,21 @@
package de.mm20.launcher2.badges.providers
import android.content.Context
import android.os.Process
import de.mm20.launcher2.badges.Badge
import de.mm20.launcher2.badges.R
import de.mm20.launcher2.ktx.getSerialNumber
import de.mm20.launcher2.search.data.AppShortcut
import de.mm20.launcher2.search.data.LauncherApp
import de.mm20.launcher2.search.data.Searchable
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
class WorkProfileBadgeProvider(private val context: Context) : BadgeProvider {
override fun getBadge(badgeKey: String): Flow<Badge?> = flow {
if (badgeKey.startsWith("profile://")) {
val serialNumber = badgeKey.substring(10).toLong()
if (serialNumber != Process.myUserHandle().getSerialNumber(context)) {
emit(
Badge(
iconRes = R.drawable.ic_badge_workprofile
)
class WorkProfileBadgeProvider : BadgeProvider {
override fun getBadge(searchable: Searchable): Flow<Badge?> = flow {
if (searchable is LauncherApp && !searchable.isMainProfile || searchable is AppShortcut && !searchable.isMainProfile) {
emit(
Badge(
iconRes = R.drawable.ic_badge_workprofile
)
} else {
emit(null)
}
)
} else {
emit(null)
}

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -17,6 +17,8 @@ abstract class File(
) : Searchable() {
abstract val isStoredInCloud: Boolean
open val providerIconRes: Int? = null
override fun getPlaceholderIcon(context: Context): LauncherIcon {
val (resId, bgColor) = when {
isDirectory -> R.drawable.ic_file_folder to R.color.lightblue

View File

@ -23,11 +23,10 @@ class GDriveFile(
override val key: String = "gdrive://$fileId"
override val badgeKey: String
get() = "gdrive://"
override val isStoredInCloud = true
override val providerIconRes = R.drawable.ic_badge_gdrive
override fun getLaunchIntent(context: Context): Intent? {
return Intent(Intent.ACTION_VIEW).apply {
data = Uri.parse(viewUri)

View File

@ -4,6 +4,7 @@ import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import de.mm20.launcher2.files.R
class NextcloudFile(
fileId: Long,
@ -15,13 +16,13 @@ class NextcloudFile(
val server: String,
metaData: List<Pair<Int, String>>
) : File(fileId, path, mimeType, size, isDirectory, metaData) {
override val badgeKey: String = "nextcloud://"
override val key: String = "nextcloud://$server/$fileId"
override val isStoredInCloud: Boolean
get() = true
override val providerIconRes = R.drawable.ic_badge_nextcloud
override fun getLaunchIntent(context: Context): Intent? {
return Intent(Intent.ACTION_VIEW).apply {
data = Uri.parse("$server/f/$id")

View File

@ -19,10 +19,10 @@ class OneDriveFile(
val webUrl: String
) : File(0, path, mimeType, size, isDirectory, metaData) {
override val badgeKey: String = "onedrive://"
override val key: String = "onedrive://$fileId"
override val providerIconRes = R.drawable.ic_badge_onedrive
override val isStoredInCloud = true
override fun getLaunchIntent(context: Context): Intent? {

View File

@ -17,13 +17,13 @@ class OwncloudFile(
val server: String,
metaData: List<Pair<Int, String>>
) : File(fileId, path, mimeType, size, isDirectory, metaData) {
override val badgeKey: String = "owncloud://"
override val key: String = "owncloud://$server/$fileId"
override val isStoredInCloud: Boolean
get() = true
override val providerIconRes = R.drawable.ic_badge_owncloud
override fun getLaunchIntent(context: Context): Intent? {
return Intent(Intent.ACTION_VIEW).apply {
data = Uri.parse("$server/f/$id")

View File

@ -16,9 +16,6 @@ abstract class Searchable : Comparable<Searchable> {
abstract val key: String
abstract val label: String
open val badgeKey
get() = key
open fun serialize(): String = ""
open fun getLaunchIntent(context: Context): Intent? = null

View File

@ -38,7 +38,7 @@ abstract class SearchableItemVM(
favoritesRepository.unhideItem(searchable)
}
val badge = badgeRepository.getBadge(searchable.badgeKey)
val badge = badgeRepository.getBadge(searchable)
fun getIcon(size: Int): Flow<LauncherIcon> {
return iconRepository.getIcon(searchable, size)