diff --git a/applications/src/main/java/de/mm20/launcher2/search/data/AppSerialization.kt b/applications/src/main/java/de/mm20/launcher2/search/data/AppSerialization.kt index 1beb8e65..feb77fbd 100644 --- a/applications/src/main/java/de/mm20/launcher2/search/data/AppSerialization.kt +++ b/applications/src/main/java/de/mm20/launcher2/search/data/AppSerialization.kt @@ -7,14 +7,13 @@ import android.content.pm.LauncherApps import android.os.Process import android.os.UserManager import androidx.core.content.getSystemService -import de.mm20.launcher2.search.PinnableSearchable -import de.mm20.launcher2.search.Searchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.search.SearchableDeserializer import de.mm20.launcher2.search.SearchableSerializer import org.json.JSONObject class LauncherAppSerializer : SearchableSerializer { - override fun serialize(searchable: PinnableSearchable): String { + override fun serialize(searchable: SavableSearchable): String { searchable as LauncherApp val json = JSONObject() json.put("package", searchable.`package`) @@ -28,7 +27,7 @@ class LauncherAppSerializer : SearchableSerializer { } class LauncherAppDeserializer(val context: Context) : SearchableDeserializer { - override fun deserialize(serialized: String): PinnableSearchable? { + override fun deserialize(serialized: String): SavableSearchable? { val json = JSONObject(serialized) val launcherApps = context.getSystemService()!! val userManager = context.getSystemService()!! diff --git a/applications/src/main/java/de/mm20/launcher2/search/data/LauncherApp.kt b/applications/src/main/java/de/mm20/launcher2/search/data/LauncherApp.kt index dde7b778..0fd92fb0 100644 --- a/applications/src/main/java/de/mm20/launcher2/search/data/LauncherApp.kt +++ b/applications/src/main/java/de/mm20/launcher2/search/data/LauncherApp.kt @@ -17,7 +17,7 @@ import de.mm20.launcher2.compat.PackageManagerCompat import de.mm20.launcher2.icons.* import de.mm20.launcher2.ktx.getSerialNumber import de.mm20.launcher2.ktx.isAtLeastApiLevel -import de.mm20.launcher2.search.PinnableSearchable +import de.mm20.launcher2.search.SavableSearchable import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -30,7 +30,7 @@ data class LauncherApp( val version: String?, internal val userSerialNumber: Long, override val labelOverride: String? = null, -) : PinnableSearchable { +) : SavableSearchable { constructor(context: Context, launcherActivityInfo: LauncherActivityInfo): this( launcherActivityInfo, diff --git a/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/AppShortcutSerialization.kt b/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/AppShortcutSerialization.kt index a2ee772a..7b118101 100644 --- a/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/AppShortcutSerialization.kt +++ b/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/AppShortcutSerialization.kt @@ -9,18 +9,17 @@ import android.os.Process import android.os.UserManager import androidx.core.content.getSystemService import de.mm20.launcher2.ktx.jsonObjectOf -import de.mm20.launcher2.search.PinnableSearchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.search.SearchableDeserializer import de.mm20.launcher2.search.SearchableSerializer import de.mm20.launcher2.search.data.LauncherShortcut import de.mm20.launcher2.search.data.LegacyShortcut -import de.mm20.launcher2.search.Searchable import org.json.JSONObject import org.koin.core.component.KoinComponent class LauncherShortcutSerializer : SearchableSerializer { - override fun serialize(searchable: PinnableSearchable): String { + override fun serialize(searchable: SavableSearchable): String { searchable as LauncherShortcut return jsonObjectOf( "packagename" to searchable.launcherShortcut.`package`, @@ -38,7 +37,7 @@ class LauncherShortcutDeserializer( val context: Context ) : SearchableDeserializer, KoinComponent { - override fun deserialize(serialized: String): PinnableSearchable? { + override fun deserialize(serialized: String): SavableSearchable? { val launcherApps = context.getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps if (!launcherApps.hasShortcutHostPermission()) return null else { @@ -82,7 +81,7 @@ class LauncherShortcutDeserializer( } class LegacyShortcutSerializer: SearchableSerializer { - override fun serialize(searchable: PinnableSearchable): String { + override fun serialize(searchable: SavableSearchable): String { searchable as LegacyShortcut return jsonObjectOf( "label" to searchable.label, @@ -103,7 +102,7 @@ class LegacyShortcutSerializer: SearchableSerializer { class LegacyShortcutDeserializer( val context: Context ): SearchableDeserializer { - override fun deserialize(serialized: String): PinnableSearchable { + override fun deserialize(serialized: String): SavableSearchable { val json = JSONObject(serialized) val label = json.getString("label") val intent = Intent.parseUri(json.getString("intent"), 0) diff --git a/appshortcuts/src/main/java/de/mm20/launcher2/search/data/AppShortcut.kt b/appshortcuts/src/main/java/de/mm20/launcher2/search/data/AppShortcut.kt index 023cf122..b3c89595 100644 --- a/appshortcuts/src/main/java/de/mm20/launcher2/search/data/AppShortcut.kt +++ b/appshortcuts/src/main/java/de/mm20/launcher2/search/data/AppShortcut.kt @@ -7,10 +7,9 @@ import de.mm20.launcher2.appshortcuts.R import de.mm20.launcher2.icons.ColorLayer import de.mm20.launcher2.icons.StaticLauncherIcon import de.mm20.launcher2.icons.TintedIconLayer -import de.mm20.launcher2.search.PinnableSearchable -import de.mm20.launcher2.search.Searchable +import de.mm20.launcher2.search.SavableSearchable -interface AppShortcut: PinnableSearchable { +interface AppShortcut: SavableSearchable { val appName: String? diff --git a/appshortcuts/src/main/java/de/mm20/launcher2/search/data/LauncherShortcut.kt b/appshortcuts/src/main/java/de/mm20/launcher2/search/data/LauncherShortcut.kt index 2bacc93f..4f233637 100644 --- a/appshortcuts/src/main/java/de/mm20/launcher2/search/data/LauncherShortcut.kt +++ b/appshortcuts/src/main/java/de/mm20/launcher2/search/data/LauncherShortcut.kt @@ -15,7 +15,6 @@ import de.mm20.launcher2.appshortcuts.R import de.mm20.launcher2.icons.* import de.mm20.launcher2.ktx.getSerialNumber import de.mm20.launcher2.ktx.isAtLeastApiLevel -import de.mm20.launcher2.search.PinnableSearchable import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext diff --git a/appshortcuts/src/main/java/de/mm20/launcher2/search/data/LegacyShortcut.kt b/appshortcuts/src/main/java/de/mm20/launcher2/search/data/LegacyShortcut.kt index 07fa919e..349a69c9 100644 --- a/appshortcuts/src/main/java/de/mm20/launcher2/search/data/LegacyShortcut.kt +++ b/appshortcuts/src/main/java/de/mm20/launcher2/search/data/LegacyShortcut.kt @@ -5,12 +5,10 @@ import android.content.Intent import android.content.Intent.ShortcutIconResource import android.graphics.drawable.AdaptiveIconDrawable import android.os.Bundle -import android.util.Log import de.mm20.launcher2.icons.* import de.mm20.launcher2.ktx.getDrawableOrNull import de.mm20.launcher2.ktx.isAtLeastApiLevel import de.mm20.launcher2.ktx.tryStartActivity -import de.mm20.launcher2.search.PinnableSearchable data class LegacyShortcut( val intent: Intent, diff --git a/backup/src/main/java/de/mm20/launcher2/backup/BackupManager.kt b/backup/src/main/java/de/mm20/launcher2/backup/BackupManager.kt index c0cf16f5..ec2e670a 100644 --- a/backup/src/main/java/de/mm20/launcher2/backup/BackupManager.kt +++ b/backup/src/main/java/de/mm20/launcher2/backup/BackupManager.kt @@ -183,7 +183,7 @@ class BackupManager( companion object { private const val BackupFormatMajor = 1 - private const val BackupFormatMinor = 2 + private const val BackupFormatMinor = 3 internal const val BackupFormat = "$BackupFormatMajor.$BackupFormatMinor" } } diff --git a/base/src/main/java/de/mm20/launcher2/search/PinnableSearchable.kt b/base/src/main/java/de/mm20/launcher2/search/SavableSearchable.kt similarity index 83% rename from base/src/main/java/de/mm20/launcher2/search/PinnableSearchable.kt rename to base/src/main/java/de/mm20/launcher2/search/SavableSearchable.kt index 9faba0f4..8495d66c 100644 --- a/base/src/main/java/de/mm20/launcher2/search/PinnableSearchable.kt +++ b/base/src/main/java/de/mm20/launcher2/search/SavableSearchable.kt @@ -7,7 +7,7 @@ import de.mm20.launcher2.icons.StaticLauncherIcon import de.mm20.launcher2.ktx.romanize import java.text.Collator -interface PinnableSearchable : Searchable, Comparable { +interface SavableSearchable : Searchable, Comparable { val domain: String val key: String @@ -16,7 +16,7 @@ interface PinnableSearchable : Searchable, Comparable { val labelOverride: String? get() = null - fun overrideLabel(label: String): PinnableSearchable + fun overrideLabel(label: String): SavableSearchable fun launch(context: Context, options: Bundle?): Boolean @@ -34,7 +34,7 @@ interface PinnableSearchable : Searchable, Comparable { ): LauncherIcon? = null - override fun compareTo(other: PinnableSearchable): Int { + override fun compareTo(other: SavableSearchable): Int { val label1 = labelOverride ?: label val label2 = other.labelOverride ?: other.label return Collator.getInstance().apply { strength = Collator.SECONDARY } diff --git a/base/src/main/java/de/mm20/launcher2/search/SearchableDeserializer.kt b/base/src/main/java/de/mm20/launcher2/search/SearchableDeserializer.kt index eb288ef8..0cc44198 100644 --- a/base/src/main/java/de/mm20/launcher2/search/SearchableDeserializer.kt +++ b/base/src/main/java/de/mm20/launcher2/search/SearchableDeserializer.kt @@ -1,11 +1,11 @@ package de.mm20.launcher2.search interface SearchableDeserializer { - fun deserialize(serialized: String): PinnableSearchable? + fun deserialize(serialized: String): SavableSearchable? } class NullDeserializer: SearchableDeserializer { - override fun deserialize(serialized: String): PinnableSearchable? { + override fun deserialize(serialized: String): SavableSearchable? { return null } diff --git a/base/src/main/java/de/mm20/launcher2/search/SearchableSerializer.kt b/base/src/main/java/de/mm20/launcher2/search/SearchableSerializer.kt index e8e814ac..165f1919 100644 --- a/base/src/main/java/de/mm20/launcher2/search/SearchableSerializer.kt +++ b/base/src/main/java/de/mm20/launcher2/search/SearchableSerializer.kt @@ -1,12 +1,12 @@ package de.mm20.launcher2.search interface SearchableSerializer { - fun serialize(searchable: PinnableSearchable): String? + fun serialize(searchable: SavableSearchable): String? val typePrefix: String } class NullSerializer : SearchableSerializer { - override fun serialize(searchable: PinnableSearchable): String? { + override fun serialize(searchable: SavableSearchable): String? { return null } diff --git a/calendar/src/main/java/de/mm20/launcher2/calendar/CalendarSerialization.kt b/calendar/src/main/java/de/mm20/launcher2/calendar/CalendarSerialization.kt index 6f8f8801..7b3642ed 100644 --- a/calendar/src/main/java/de/mm20/launcher2/calendar/CalendarSerialization.kt +++ b/calendar/src/main/java/de/mm20/launcher2/calendar/CalendarSerialization.kt @@ -7,16 +7,15 @@ import android.content.pm.PackageManager import android.provider.CalendarContract import androidx.core.content.ContextCompat import androidx.core.database.getStringOrNull -import de.mm20.launcher2.search.PinnableSearchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.search.SearchableDeserializer import de.mm20.launcher2.search.SearchableSerializer import de.mm20.launcher2.search.data.CalendarEvent -import de.mm20.launcher2.search.Searchable import org.json.JSONObject import java.util.* class CalendarEventSerializer: SearchableSerializer { - override fun serialize(searchable: PinnableSearchable): String { + override fun serialize(searchable: SavableSearchable): String { searchable as CalendarEvent val json = JSONObject() json.put("id", searchable.id) @@ -28,7 +27,7 @@ class CalendarEventSerializer: SearchableSerializer { } class CalendarEventDeserializer(val context: Context): SearchableDeserializer { - override fun deserialize(serialized: String): PinnableSearchable? { + override fun deserialize(serialized: String): SavableSearchable? { if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CALENDAR) != PackageManager.PERMISSION_GRANTED) return null val json = JSONObject(serialized) val id = json.getLong("id") diff --git a/calendar/src/main/java/de/mm20/launcher2/search/data/CalendarEvent.kt b/calendar/src/main/java/de/mm20/launcher2/search/data/CalendarEvent.kt index 421de09d..3e399fff 100644 --- a/calendar/src/main/java/de/mm20/launcher2/search/data/CalendarEvent.kt +++ b/calendar/src/main/java/de/mm20/launcher2/search/data/CalendarEvent.kt @@ -9,8 +9,7 @@ import de.mm20.launcher2.icons.ColorLayer import de.mm20.launcher2.icons.StaticLauncherIcon import de.mm20.launcher2.icons.TextLayer import de.mm20.launcher2.ktx.tryStartActivity -import de.mm20.launcher2.search.PinnableSearchable -import de.mm20.launcher2.search.Searchable +import de.mm20.launcher2.search.SavableSearchable import java.text.SimpleDateFormat data class CalendarEvent( @@ -25,7 +24,7 @@ data class CalendarEvent( val description: String, val calendar: Long, override val labelOverride: String? = null, -) : PinnableSearchable { +) : SavableSearchable { override val domain: String = Domain diff --git a/contacts/src/main/java/de/mm20/launcher2/contacts/ContactSerialization.kt b/contacts/src/main/java/de/mm20/launcher2/contacts/ContactSerialization.kt index 8806b55f..684ada52 100644 --- a/contacts/src/main/java/de/mm20/launcher2/contacts/ContactSerialization.kt +++ b/contacts/src/main/java/de/mm20/launcher2/contacts/ContactSerialization.kt @@ -6,15 +6,14 @@ import android.content.pm.PackageManager import android.provider.ContactsContract import androidx.core.content.ContextCompat import de.mm20.launcher2.ktx.jsonObjectOf -import de.mm20.launcher2.search.PinnableSearchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.search.SearchableDeserializer import de.mm20.launcher2.search.SearchableSerializer import de.mm20.launcher2.search.data.Contact -import de.mm20.launcher2.search.Searchable import org.json.JSONObject class ContactSerializer : SearchableSerializer { - override fun serialize(searchable: PinnableSearchable): String { + override fun serialize(searchable: SavableSearchable): String { searchable as Contact return jsonObjectOf( "id" to searchable.id @@ -26,7 +25,7 @@ class ContactSerializer : SearchableSerializer { } class ContactDeserializer(val context: Context) : SearchableDeserializer { - override fun deserialize(serialized: String): PinnableSearchable? { + override fun deserialize(serialized: String): SavableSearchable? { if (ContextCompat.checkSelfPermission( context, Manifest.permission.READ_CONTACTS diff --git a/contacts/src/main/java/de/mm20/launcher2/search/data/Contact.kt b/contacts/src/main/java/de/mm20/launcher2/search/data/Contact.kt index e3b5e084..8f6963e4 100644 --- a/contacts/src/main/java/de/mm20/launcher2/search/data/Contact.kt +++ b/contacts/src/main/java/de/mm20/launcher2/search/data/Contact.kt @@ -11,7 +11,7 @@ import androidx.core.graphics.drawable.toDrawable import de.mm20.launcher2.icons.* import de.mm20.launcher2.ktx.asBitmap import de.mm20.launcher2.ktx.tryStartActivity -import de.mm20.launcher2.search.PinnableSearchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.search.Searchable import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -29,7 +29,7 @@ data class Contact( val whatsapp: Set, val postals: Set, override val labelOverride: String? = null -) : Searchable, PinnableSearchable { +) : Searchable, SavableSearchable { override val domain: String = Domain override val key: String diff --git a/customattrs/src/main/java/de/mm20/launcher2/customattrs/CustomAttributesRepository.kt b/customattrs/src/main/java/de/mm20/launcher2/customattrs/CustomAttributesRepository.kt index e14d692b..b286e933 100644 --- a/customattrs/src/main/java/de/mm20/launcher2/customattrs/CustomAttributesRepository.kt +++ b/customattrs/src/main/java/de/mm20/launcher2/customattrs/CustomAttributesRepository.kt @@ -5,7 +5,7 @@ import de.mm20.launcher2.database.AppDatabase import de.mm20.launcher2.database.entities.CustomAttributeEntity import de.mm20.launcher2.favorites.FavoritesRepository import de.mm20.launcher2.ktx.jsonObjectOf -import de.mm20.launcher2.search.PinnableSearchable +import de.mm20.launcher2.search.SavableSearchable import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList @@ -19,24 +19,24 @@ import java.io.File interface CustomAttributesRepository { - fun search(query: String): Flow> + fun search(query: String): Flow> - fun getCustomIcon(searchable: PinnableSearchable): Flow - fun setCustomIcon(searchable: PinnableSearchable, icon: CustomIcon?) + fun getCustomIcon(searchable: SavableSearchable): Flow + fun setCustomIcon(searchable: SavableSearchable, icon: CustomIcon?) - fun getCustomLabels(items: List): Flow> - fun setCustomLabel(searchable: PinnableSearchable, label: String) - fun clearCustomLabel(searchable: PinnableSearchable) + fun getCustomLabels(items: List): Flow> + fun setCustomLabel(searchable: SavableSearchable, label: String) + fun clearCustomLabel(searchable: SavableSearchable) - fun setTags(searchable: PinnableSearchable, tags: List) - fun getTags(searchable: PinnableSearchable): Flow> + fun setTags(searchable: SavableSearchable, tags: List) + fun getTags(searchable: SavableSearchable): Flow> suspend fun export(toDir: File) suspend fun import(fromDir: File) suspend fun getAllTags(startsWith: String? = null): List - fun getItemsForTag(tag: String): Flow> - fun addTag(item: PinnableSearchable, tag: String) + fun getItemsForTag(tag: String): Flow> + fun addTag(item: SavableSearchable, tag: String) suspend fun cleanupDatabase(): Int } @@ -46,7 +46,7 @@ internal class CustomAttributesRepositoryImpl( ) : CustomAttributesRepository { private val scope = CoroutineScope(Job() + Dispatchers.Default) - override fun getCustomIcon(searchable: PinnableSearchable): Flow { + override fun getCustomIcon(searchable: SavableSearchable): Flow { val dao = appDatabase.customAttrsDao() return dao.getCustomAttribute(searchable.key, CustomAttributeType.Icon.value) .map { @@ -54,7 +54,7 @@ internal class CustomAttributesRepositoryImpl( } } - override fun setCustomIcon(searchable: PinnableSearchable, icon: CustomIcon?) { + override fun setCustomIcon(searchable: SavableSearchable, icon: CustomIcon?) { val dao = appDatabase.customAttrsDao() scope.launch { dao.clearCustomAttribute(searchable.key, CustomAttributeType.Icon.value) @@ -64,7 +64,7 @@ internal class CustomAttributesRepositoryImpl( } } - override fun getCustomLabels(items: List): Flow> { + override fun getCustomLabels(items: List): Flow> { val dao = appDatabase.customAttrsDao() return dao.getCustomAttributes(items.map { it.key }, CustomAttributeType.Label.value) .map { list -> @@ -72,7 +72,7 @@ internal class CustomAttributesRepositoryImpl( } } - override fun setCustomLabel(searchable: PinnableSearchable, label: String) { + override fun setCustomLabel(searchable: SavableSearchable, label: String) { val dao = appDatabase.customAttrsDao() scope.launch { favoritesRepository.save(searchable) @@ -88,14 +88,14 @@ internal class CustomAttributesRepositoryImpl( } } - override fun clearCustomLabel(searchable: PinnableSearchable) { + override fun clearCustomLabel(searchable: SavableSearchable) { val dao = appDatabase.customAttrsDao() scope.launch { dao.clearCustomAttribute(searchable.key, CustomAttributeType.Label.value) } } - override fun setTags(searchable: PinnableSearchable, tags: List) { + override fun setTags(searchable: SavableSearchable, tags: List) { val dao = appDatabase.customAttrsDao() scope.launch { favoritesRepository.save(searchable) @@ -105,7 +105,7 @@ internal class CustomAttributesRepositoryImpl( } } - override fun getTags(searchable: PinnableSearchable): Flow> { + override fun getTags(searchable: SavableSearchable): Flow> { val dao = appDatabase.customAttrsDao() return dao.getCustomAttributes(listOf(searchable.key), CustomAttributeType.Tag.value).map { it.map { it.value } @@ -121,21 +121,21 @@ internal class CustomAttributesRepositoryImpl( } } - override fun getItemsForTag(tag: String): Flow> { + override fun getItemsForTag(tag: String): Flow> { val dao = appDatabase.customAttrsDao() return dao.getItemsWithTag(tag).map { favoritesRepository.getFromKeys(it) } } - override fun addTag(item: PinnableSearchable, tag: String) { + override fun addTag(item: SavableSearchable, tag: String) { val dao = appDatabase.customAttrsDao() scope.launch { dao.addTag(item.key, tag) } } - override fun search(query: String): Flow> { + override fun search(query: String): Flow> { if (query.isBlank()) { return flow { emit(persistentListOf()) diff --git a/customattrs/src/main/java/de/mm20/launcher2/customattrs/utils/Utils.kt b/customattrs/src/main/java/de/mm20/launcher2/customattrs/utils/Utils.kt index 14ef4cdb..f4f011e5 100644 --- a/customattrs/src/main/java/de/mm20/launcher2/customattrs/utils/Utils.kt +++ b/customattrs/src/main/java/de/mm20/launcher2/customattrs/utils/Utils.kt @@ -1,12 +1,12 @@ package de.mm20.launcher2.customattrs.utils import de.mm20.launcher2.customattrs.CustomAttributesRepository -import de.mm20.launcher2.search.PinnableSearchable +import de.mm20.launcher2.search.SavableSearchable import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.channelFlow import kotlinx.coroutines.flow.collectLatest -fun Flow>.withCustomLabels( +fun Flow>.withCustomLabels( customAttributesRepository: CustomAttributesRepository, ): Flow> = channelFlow { this@withCustomLabels.collectLatest { items -> diff --git a/database/schemas/de.mm20.launcher2.database.AppDatabase/18.json b/database/schemas/de.mm20.launcher2.database.AppDatabase/18.json new file mode 100644 index 00000000..6ce94204 --- /dev/null +++ b/database/schemas/de.mm20.launcher2.database.AppDatabase/18.json @@ -0,0 +1,456 @@ +{ + "formatVersion": 1, + "database": { + "version": 18, + "identityHash": "4ae30e68d30e179ef6d30b562bbc3011", + "entities": [ + { + "tableName": "forecasts", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`timestamp` INTEGER NOT NULL, `temperature` REAL NOT NULL, `minTemp` REAL NOT NULL, `maxTemp` REAL NOT NULL, `pressure` REAL NOT NULL, `humidity` REAL NOT NULL, `icon` INTEGER NOT NULL, `condition` TEXT NOT NULL, `clouds` INTEGER NOT NULL, `windSpeed` REAL NOT NULL, `windDirection` REAL NOT NULL, `rain` REAL NOT NULL, `snow` REAL NOT NULL, `night` INTEGER NOT NULL, `location` TEXT NOT NULL, `provider` TEXT NOT NULL, `providerUrl` TEXT NOT NULL, `rainProbability` INTEGER NOT NULL, `snowProbability` INTEGER NOT NULL, `updateTime` INTEGER NOT NULL, PRIMARY KEY(`timestamp`))", + "fields": [ + { + "fieldPath": "timestamp", + "columnName": "timestamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "temperature", + "columnName": "temperature", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "minTemp", + "columnName": "minTemp", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "maxTemp", + "columnName": "maxTemp", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "pressure", + "columnName": "pressure", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "humidity", + "columnName": "humidity", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "icon", + "columnName": "icon", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "condition", + "columnName": "condition", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "clouds", + "columnName": "clouds", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "windSpeed", + "columnName": "windSpeed", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "windDirection", + "columnName": "windDirection", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "precipitation", + "columnName": "rain", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "snow", + "columnName": "snow", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "night", + "columnName": "night", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "location", + "columnName": "location", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "provider", + "columnName": "provider", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "providerUrl", + "columnName": "providerUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "precipProbability", + "columnName": "rainProbability", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "snowProbability", + "columnName": "snowProbability", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "updateTime", + "columnName": "updateTime", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "timestamp" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Searchable", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`key` TEXT NOT NULL, `type` TEXT NOT NULL, `searchable` TEXT NOT NULL, `launchCount` INTEGER NOT NULL, `pinned` INTEGER NOT NULL, `hidden` INTEGER NOT NULL, PRIMARY KEY(`key`))", + "fields": [ + { + "fieldPath": "key", + "columnName": "key", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "serializedSearchable", + "columnName": "searchable", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "launchCount", + "columnName": "launchCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "pinPosition", + "columnName": "pinned", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "hidden", + "columnName": "hidden", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "key" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Websearch", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`urlTemplate` TEXT NOT NULL, `label` TEXT NOT NULL, `color` INTEGER NOT NULL, `icon` TEXT, `encoding` INTEGER, `id` INTEGER PRIMARY KEY AUTOINCREMENT)", + "fields": [ + { + "fieldPath": "urlTemplate", + "columnName": "urlTemplate", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "label", + "columnName": "label", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "color", + "columnName": "color", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "icon", + "columnName": "icon", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "encoding", + "columnName": "encoding", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Currency", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`symbol` TEXT NOT NULL, `value` REAL NOT NULL, `lastUpdate` INTEGER NOT NULL, PRIMARY KEY(`symbol`))", + "fields": [ + { + "fieldPath": "symbol", + "columnName": "symbol", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "value", + "columnName": "value", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "lastUpdate", + "columnName": "lastUpdate", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "symbol" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Icons", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`type` TEXT NOT NULL, `componentName` TEXT, `drawable` TEXT, `iconPack` TEXT NOT NULL, `scale` REAL, `id` INTEGER PRIMARY KEY AUTOINCREMENT)", + "fields": [ + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "componentName", + "columnName": "componentName", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "drawable", + "columnName": "drawable", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "iconPack", + "columnName": "iconPack", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "scale", + "columnName": "scale", + "affinity": "REAL", + "notNull": false + }, + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "IconPack", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`name` TEXT NOT NULL, `packageName` TEXT NOT NULL, `version` TEXT NOT NULL, `scale` REAL NOT NULL, PRIMARY KEY(`packageName`))", + "fields": [ + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "packageName", + "columnName": "packageName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "version", + "columnName": "version", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "scale", + "columnName": "scale", + "affinity": "REAL", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "packageName" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "Widget", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`type` TEXT NOT NULL, `data` TEXT NOT NULL, `height` INTEGER NOT NULL, `position` INTEGER NOT NULL, `label` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT)", + "fields": [ + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "data", + "columnName": "data", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "height", + "columnName": "height", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "position", + "columnName": "position", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "label", + "columnName": "label", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + }, + { + "tableName": "CustomAttributes", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`key` TEXT NOT NULL, `type` TEXT NOT NULL, `value` TEXT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT)", + "fields": [ + { + "fieldPath": "key", + "columnName": "key", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "value", + "columnName": "value", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": false + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "indices": [], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '4ae30e68d30e179ef6d30b562bbc3011')" + ] + } +} \ No newline at end of file diff --git a/database/src/main/java/de/mm20/launcher2/database/AppDatabase.kt b/database/src/main/java/de/mm20/launcher2/database/AppDatabase.kt index 40a99c39..5a9c72d6 100644 --- a/database/src/main/java/de/mm20/launcher2/database/AppDatabase.kt +++ b/database/src/main/java/de/mm20/launcher2/database/AppDatabase.kt @@ -12,13 +12,13 @@ import androidx.sqlite.db.SupportSQLiteDatabase import de.mm20.launcher2.database.entities.* @Database(entities = [ForecastEntity::class, - FavoritesItemEntity::class, + SavedSearchableEntity::class, WebsearchEntity::class, CurrencyEntity::class, IconEntity::class, IconPackEntity::class, WidgetEntity::class, - CustomAttributeEntity::class], version = 17, exportSchema = true) + CustomAttributeEntity::class], version = 18, exportSchema = true) @TypeConverters(ComponentNameConverter::class, StringListConverter::class) abstract class AppDatabase : RoomDatabase() { @@ -62,6 +62,7 @@ abstract class AppDatabase : RoomDatabase() { Migration_14_15(), Migration_15_16(), Migration_16_17(), + Migration_17_18(), ).build() if (_instance == null) _instance = instance return instance @@ -172,5 +173,15 @@ class Migration_16_17 : Migration(16, 17) { override fun migrate(database: SupportSQLiteDatabase) { database.execSQL("ALTER TABLE Websearch ADD COLUMN encoding INTEGER") } +} +class Migration_17_18: Migration(17, 18) { + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("ALTER TABLE Searchable ADD COLUMN type TEXT NOT NULL DEFAULT ''") + database.execSQL(""" + UPDATE Searchable + SET type = SUBSTR(`key`, 0, INSTR(`key`, '://')), + searchable = SUBSTR(`searchable`, INSTR(`searchable`, '#') + 1) + """.trimIndent()) + } } \ No newline at end of file diff --git a/database/src/main/java/de/mm20/launcher2/database/BackupRestoreDao.kt b/database/src/main/java/de/mm20/launcher2/database/BackupRestoreDao.kt index 6d6f9bae..506de4c4 100644 --- a/database/src/main/java/de/mm20/launcher2/database/BackupRestoreDao.kt +++ b/database/src/main/java/de/mm20/launcher2/database/BackupRestoreDao.kt @@ -5,7 +5,7 @@ import androidx.room.Insert import androidx.room.OnConflictStrategy import androidx.room.Query import de.mm20.launcher2.database.entities.CustomAttributeEntity -import de.mm20.launcher2.database.entities.FavoritesItemEntity +import de.mm20.launcher2.database.entities.SavedSearchableEntity import de.mm20.launcher2.database.entities.WebsearchEntity import de.mm20.launcher2.database.entities.WidgetEntity @@ -16,10 +16,10 @@ interface BackupRestoreDao { suspend fun wipeFavorites() @Query("SELECT * FROM Searchable LIMIT :limit OFFSET :offset") - suspend fun exportFavorites(limit: Int, offset: Int): List + suspend fun exportFavorites(limit: Int, offset: Int): List @Insert(onConflict = OnConflictStrategy.REPLACE) - suspend fun importFavorites(items: List) + suspend fun importFavorites(items: List) @Query("DELETE FROM Widget") suspend fun wipeWidgets() diff --git a/database/src/main/java/de/mm20/launcher2/database/SearchDao.kt b/database/src/main/java/de/mm20/launcher2/database/SearchDao.kt index 7797cca4..e0b1bc1b 100644 --- a/database/src/main/java/de/mm20/launcher2/database/SearchDao.kt +++ b/database/src/main/java/de/mm20/launcher2/database/SearchDao.kt @@ -1,7 +1,7 @@ package de.mm20.launcher2.database import androidx.room.* -import de.mm20.launcher2.database.entities.FavoritesItemEntity +import de.mm20.launcher2.database.entities.SavedSearchableEntity import de.mm20.launcher2.database.entities.WebsearchEntity import kotlinx.coroutines.flow.Flow @@ -9,16 +9,16 @@ import kotlinx.coroutines.flow.Flow interface SearchDao { @Insert() - fun insertAll(items: List) + fun insertAll(items: List) @Insert(onConflict = OnConflictStrategy.IGNORE) - fun insertAllSkipExisting(items: List) + fun insertAllSkipExisting(items: List) @Insert(onConflict = OnConflictStrategy.IGNORE) - fun insertSkipExisting(items: FavoritesItemEntity) + fun insertSkipExisting(items: SavedSearchableEntity) @Insert(onConflict = OnConflictStrategy.REPLACE) - fun insertAllReplaceExisting(items: List) + fun insertAllReplaceExisting(items: List) @Query("SELECT * FROM Searchable " + @@ -31,7 +31,7 @@ interface SearchDao { automaticallySorted: Boolean = false, frequentlyUsed: Boolean = false, limit: Int, - ): Flow> + ): Flow> @Query("SELECT * FROM Searchable " + "WHERE SUBSTR(`key`, 0, INSTR(`key`, '://')) IN (:includeTypes) AND (" + @@ -45,10 +45,10 @@ interface SearchDao { automaticallySorted: Boolean = false, frequentlyUsed: Boolean = false, limit: Int, - ): Flow> + ): Flow> @Query("SELECT * FROM Searchable " + - "WHERE SUBSTR(`key`, 0, INSTR(`key`, '://')) NOT IN (:excludeTypes) AND (" + + "WHERE `type` NOT IN (:excludeTypes) AND (" + "(:manuallySorted AND pinned > 1) OR " + "(:automaticallySorted AND pinned = 1) OR" + "(:frequentlyUsed AND pinned = 0 AND launchCount > 0)" + @@ -59,7 +59,7 @@ interface SearchDao { automaticallySorted: Boolean = false, frequentlyUsed: Boolean = false, limit: Int, - ): Flow> + ): Flow> @Query("SELECT `key` FROM Searchable WHERE hidden = 1 AND `key` LIKE 'calendar://%'") fun getHiddenCalendarEventKeys(): Flow> @@ -69,7 +69,7 @@ interface SearchDao { fun getPinCount(): Int @Query("SELECT * FROM Searchable WHERE pinned = 0 AND launchCount > 0 AND hidden = 0 AND NOT `key` LIKE 'calendar://%' ORDER BY launchCount DESC LIMIT :count") - fun getAutoFavorites(count: Int): List + fun getAutoFavorites(count: Int): List @Query("DELETE FROM Searchable WHERE `key` IN (:keys)") fun deleteAll(keys: List) @@ -79,7 +79,7 @@ interface SearchDao { fun pinExistingItem(key: String) @Transaction - fun pinToFavorites(item: FavoritesItemEntity) { + fun pinToFavorites(item: SavedSearchableEntity) { pinExistingItem(item.key) insertSkipExisting(item) } @@ -102,7 +102,7 @@ interface SearchDao { fun hideExistingItem(key: String) @Transaction - fun hideItem(item: FavoritesItemEntity) { + fun hideItem(item: SavedSearchableEntity) { hideExistingItem(item.key) insertSkipExisting(item) } @@ -117,7 +117,7 @@ interface SearchDao { fun getHiddenItemKeys(): Flow> @Query("SELECT * FROM SEARCHABLE WHERE hidden = 1") - fun getHiddenItems(): Flow> + fun getHiddenItems(): Flow> @Query("SELECT * FROM Websearch ORDER BY label ASC") fun getWebSearches(): Flow> @@ -135,22 +135,22 @@ interface SearchDao { fun incrementExistingLaunchCount(key: String) @Transaction - fun incrementLaunchCount(item: FavoritesItemEntity) { + fun incrementLaunchCount(item: SavedSearchableEntity) { incrementExistingLaunchCount(item.key) insertSkipExisting(item) } @Query("SELECT * FROM Searchable WHERE `key` = :key") - fun getFavorite(key: String): FavoritesItemEntity? + fun getFavorite(key: String): SavedSearchableEntity? @Query("SELECT * FROM Searchable WHERE `key` IN (:keys)") - suspend fun getFromKeys(keys: List): List + suspend fun getFromKeys(keys: List): List @Insert(onConflict = OnConflictStrategy.REPLACE) - fun insertReplaceExisting(toDatabaseEntity: FavoritesItemEntity) + fun insertReplaceExisting(toDatabaseEntity: SavedSearchableEntity) @Transaction - fun saveFavorites(favorites: List) { + fun saveFavorites(favorites: List) { deleteAllFavorites() insertAll(favorites) } diff --git a/database/src/main/java/de/mm20/launcher2/database/entities/FavoritesItemEntity.kt b/database/src/main/java/de/mm20/launcher2/database/entities/SavedSearchableEntity.kt similarity index 87% rename from database/src/main/java/de/mm20/launcher2/database/entities/FavoritesItemEntity.kt rename to database/src/main/java/de/mm20/launcher2/database/entities/SavedSearchableEntity.kt index 03a54ca7..9af986f7 100644 --- a/database/src/main/java/de/mm20/launcher2/database/entities/FavoritesItemEntity.kt +++ b/database/src/main/java/de/mm20/launcher2/database/entities/SavedSearchableEntity.kt @@ -5,8 +5,9 @@ import androidx.room.Entity import androidx.room.PrimaryKey @Entity(tableName = "Searchable") -data class FavoritesItemEntity( +data class SavedSearchableEntity( @PrimaryKey val key: String, + val type: String, @ColumnInfo(name = "searchable") val serializedSearchable: String, var launchCount: Int, @ColumnInfo(name = "pinned") var pinPosition: Int, diff --git a/favorites/src/main/java/de/mm20/launcher2/favorites/FavoritesRepository.kt b/favorites/src/main/java/de/mm20/launcher2/favorites/FavoritesRepository.kt index 5a653fec..3c7fcf88 100644 --- a/favorites/src/main/java/de/mm20/launcher2/favorites/FavoritesRepository.kt +++ b/favorites/src/main/java/de/mm20/launcher2/favorites/FavoritesRepository.kt @@ -4,11 +4,10 @@ import android.content.Context import android.util.Log import de.mm20.launcher2.crashreporter.CrashReporter import de.mm20.launcher2.database.AppDatabase -import de.mm20.launcher2.database.entities.FavoritesItemEntity +import de.mm20.launcher2.database.entities.SavedSearchableEntity import de.mm20.launcher2.ktx.jsonObjectOf -import de.mm20.launcher2.search.PinnableSearchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.search.SearchableDeserializer -import de.mm20.launcher2.search.data.CalendarEvent import kotlinx.coroutines.* import kotlinx.coroutines.flow.* import org.json.JSONArray @@ -33,46 +32,46 @@ interface FavoritesRepository { automaticallySorted: Boolean = false, frequentlyUsed: Boolean = false, limit: Int = 100 - ): Flow> + ): Flow> fun getHiddenCalendarEventKeys(): Flow> - fun isPinned(searchable: PinnableSearchable): Flow - fun pinItem(searchable: PinnableSearchable) - fun unpinItem(searchable: PinnableSearchable) - fun isHidden(searchable: PinnableSearchable): Flow - fun hideItem(searchable: PinnableSearchable) - fun unhideItem(searchable: PinnableSearchable) - fun incrementLaunchCounter(searchable: PinnableSearchable) + fun isPinned(searchable: SavableSearchable): Flow + fun pinItem(searchable: SavableSearchable) + fun unpinItem(searchable: SavableSearchable) + fun isHidden(searchable: SavableSearchable): Flow + fun hideItem(searchable: SavableSearchable) + fun unhideItem(searchable: SavableSearchable) + fun incrementLaunchCounter(searchable: SavableSearchable) fun updateFavorites( - manuallySorted: List, - automaticallySorted: List, + manuallySorted: List, + automaticallySorted: List, ) - fun getHiddenItems(): Flow> + fun getHiddenItems(): Flow> fun getHiddenItemKeys(): Flow> /** * Remove this item from the Searchable database */ - fun remove(searchable: PinnableSearchable) + fun remove(searchable: SavableSearchable) /** * Remove this item from favorites and reset launch counter */ - fun removeFromFavorites(searchable: PinnableSearchable) + fun removeFromFavorites(searchable: SavableSearchable) /** * Ensure that this searchable exists in the Favorites table. * If it doesn't exist, insert it with 0 launch count, not pinned and not hidden */ - fun save(searchable: PinnableSearchable) + fun save(searchable: SavableSearchable) /** * Get items with the given keys from the favorites database. * Items that don't exist in the database will not be returned. */ - suspend fun getFromKeys(keys: List): List + suspend fun getFromKeys(keys: List): List suspend fun export(toDir: File) suspend fun import(fromDir: File) @@ -99,7 +98,7 @@ internal class FavoritesRepositoryImpl( automaticallySorted: Boolean, frequentlyUsed: Boolean, limit: Int - ): Flow> { + ): Flow> { val dao = database.searchDao() val entities = when { includeTypes == null && excludeTypes == null -> dao.getFavorites( @@ -137,28 +136,28 @@ internal class FavoritesRepositoryImpl( return database.searchDao().getHiddenCalendarEventKeys() } - override fun isPinned(searchable: PinnableSearchable): Flow { + override fun isPinned(searchable: SavableSearchable): Flow { return AppDatabase.getInstance(context).searchDao().isPinned(searchable.key) } - override fun pinItem(searchable: PinnableSearchable) { + override fun pinItem(searchable: SavableSearchable) { scope.launch { withContext(Dispatchers.IO) { val dao = AppDatabase.getInstance(context).searchDao() val databaseItem = dao.getFavorite(searchable.key) - val favoritesItem = FavoritesItem( + val savedSearchable = SavedSearchable( key = searchable.key, searchable = searchable, launchCount = databaseItem?.launchCount ?: 0, pinPosition = 1, hidden = false ) - favoritesItem.toDatabaseEntity()?.let { dao.insertReplaceExisting(it) } + savedSearchable.toDatabaseEntity()?.let { dao.insertReplaceExisting(it) } } } } - override fun unpinItem(searchable: PinnableSearchable) { + override fun unpinItem(searchable: SavableSearchable) { scope.launch { withContext(Dispatchers.IO) { AppDatabase.getInstance(context).searchDao().unpinFavorite(searchable.key) @@ -166,28 +165,28 @@ internal class FavoritesRepositoryImpl( } } - override fun isHidden(searchable: PinnableSearchable): Flow { + override fun isHidden(searchable: SavableSearchable): Flow { return AppDatabase.getInstance(context).searchDao().isHidden(searchable.key) } - override fun hideItem(searchable: PinnableSearchable) { + override fun hideItem(searchable: SavableSearchable) { scope.launch { withContext(Dispatchers.IO) { val dao = AppDatabase.getInstance(context).searchDao() val databaseItem = dao.getFavorite(searchable.key) - val favoritesItem = FavoritesItem( + val savedSearchable = SavedSearchable( key = searchable.key, searchable = searchable, launchCount = databaseItem?.launchCount ?: 0, pinPosition = 0, hidden = true ) - favoritesItem.toDatabaseEntity()?.let { dao.insertReplaceExisting(it) } + savedSearchable.toDatabaseEntity()?.let { dao.insertReplaceExisting(it) } } } } - override fun unhideItem(searchable: PinnableSearchable) { + override fun unhideItem(searchable: SavableSearchable) { scope.launch { withContext(Dispatchers.IO) { AppDatabase.getInstance(context).searchDao().unhideItem(searchable.key) @@ -195,10 +194,10 @@ internal class FavoritesRepositoryImpl( } } - override fun incrementLaunchCounter(searchable: PinnableSearchable) { + override fun incrementLaunchCounter(searchable: SavableSearchable) { scope.launch { withContext(Dispatchers.IO) { - val item = FavoritesItem(searchable.key, searchable, 0, 0, false) + val item = SavedSearchable(searchable.key, searchable, 0, 0, false) item.toDatabaseEntity()?.let { AppDatabase.getInstance(context).searchDao() .incrementLaunchCount(it) @@ -207,7 +206,7 @@ internal class FavoritesRepositoryImpl( } } - override fun getHiddenItems(): Flow> { + override fun getHiddenItems(): Flow> { return database.searchDao().getHiddenItems().map { it.mapNotNull { fromDatabaseEntity(it).searchable } } @@ -217,7 +216,7 @@ internal class FavoritesRepositoryImpl( return database.searchDao().getHiddenItemKeys() } - override fun remove(searchable: PinnableSearchable) { + override fun remove(searchable: SavableSearchable) { scope.launch { withContext(Dispatchers.IO) { database.searchDao().deleteByKey(searchable.key) @@ -225,16 +224,16 @@ internal class FavoritesRepositoryImpl( } } - override fun removeFromFavorites(searchable: PinnableSearchable) { + override fun removeFromFavorites(searchable: SavableSearchable) { scope.launch { database.searchDao().resetPinStatusAndLaunchCounter(searchable.key) } } - override fun save(searchable: PinnableSearchable) { + override fun save(searchable: SavableSearchable) { scope.launch { withContext(Dispatchers.IO) { - val entity = FavoritesItem( + val entity = SavedSearchable( key = searchable.key, searchable = searchable, launchCount = 0, @@ -247,8 +246,8 @@ internal class FavoritesRepositoryImpl( } override fun updateFavorites( - manuallySorted: List, - automaticallySorted: List + manuallySorted: List, + automaticallySorted: List ) { val dao = database.searchDao() scope.launch { @@ -256,7 +255,7 @@ internal class FavoritesRepositoryImpl( val keys = manuallySorted.map { it.key } + automaticallySorted.map { it.key } val entities = dao.getFromKeys(keys) val updatedManuallySorted = manuallySorted.mapIndexedNotNull { index, searchable -> - val entity = entities.find { searchable.key == it.key } ?: FavoritesItem( + val entity = entities.find { searchable.key == it.key } ?: SavedSearchable( key = searchable.key, searchable = searchable, launchCount = 0, @@ -268,7 +267,7 @@ internal class FavoritesRepositoryImpl( } val updatedAutomaticallySorted = automaticallySorted.mapIndexedNotNull { index, searchable -> - val entity = entities.find { searchable.key == it.key } ?: FavoritesItem( + val entity = entities.find { searchable.key == it.key } ?: SavedSearchable( key = searchable.key, searchable = searchable, launchCount = 0, @@ -288,12 +287,12 @@ internal class FavoritesRepositoryImpl( } - private fun fromDatabaseEntity(entity: FavoritesItemEntity): FavoritesItem { + private fun fromDatabaseEntity(entity: SavedSearchableEntity): SavedSearchable { val deserializer: SearchableDeserializer = - getDeserializer(context, entity.serializedSearchable) - val searchable = deserializer.deserialize(entity.serializedSearchable.substringAfter("#")) + getDeserializer(context, entity.type) + val searchable = deserializer.deserialize(entity.serializedSearchable) if (searchable == null) removeInvalidItem(entity.key) - return FavoritesItem( + return SavedSearchable( key = entity.key, searchable = searchable, launchCount = entity.launchCount, @@ -308,7 +307,7 @@ internal class FavoritesRepositoryImpl( } } - override suspend fun getFromKeys(keys: List): List { + override suspend fun getFromKeys(keys: List): List { val dao = database.searchDao() return dao.getFromKeys(keys) .mapNotNull { fromDatabaseEntity(it).searchable } @@ -324,6 +323,7 @@ internal class FavoritesRepositoryImpl( jsonArray.put( jsonObjectOf( "key" to fav.key, + "type" to fav.type, "hidden" to fav.hidden, "launchCount" to fav.launchCount, "pinPosition" to fav.pinPosition, @@ -348,14 +348,15 @@ internal class FavoritesRepositoryImpl( fromDir.listFiles { _, name -> name.startsWith("favorites.") } ?: return@withContext for (file in files) { - val favorites = mutableListOf() + val favorites = mutableListOf() try { val jsonArray = JSONArray(file.inputStream().reader().readText()) for (i in 0 until jsonArray.length()) { val json = jsonArray.getJSONObject(i) - val entity = FavoritesItemEntity( + val entity = SavedSearchableEntity( key = json.getString("key"), + type = json.optString("type").takeIf { it.isNotEmpty() } ?: continue, serializedSearchable = json.getString("searchable"), launchCount = json.getInt("launchCount"), hidden = json.getBoolean("hidden"), diff --git a/favorites/src/main/java/de/mm20/launcher2/favorites/FavoritesItem.kt b/favorites/src/main/java/de/mm20/launcher2/favorites/SavedSearchable.kt similarity index 51% rename from favorites/src/main/java/de/mm20/launcher2/favorites/FavoritesItem.kt rename to favorites/src/main/java/de/mm20/launcher2/favorites/SavedSearchable.kt index 9c7bf96f..8de5b07d 100644 --- a/favorites/src/main/java/de/mm20/launcher2/favorites/FavoritesItem.kt +++ b/favorites/src/main/java/de/mm20/launcher2/favorites/SavedSearchable.kt @@ -1,30 +1,28 @@ package de.mm20.launcher2.favorites -import de.mm20.launcher2.database.entities.FavoritesItemEntity -import de.mm20.launcher2.search.PinnableSearchable +import de.mm20.launcher2.database.entities.SavedSearchableEntity +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.search.SearchableSerializer -import de.mm20.launcher2.search.Searchable -data class FavoritesItem( +data class SavedSearchable( val key: String, /** * null if searchable could not be deserialized (i.e. the app has been uninstalled) */ - val searchable: PinnableSearchable?, + val searchable: SavableSearchable?, var launchCount: Int, var pinPosition: Int, var hidden: Boolean ) { - private val serializer: SearchableSerializer = getSerializer(searchable) - - fun toDatabaseEntity(): FavoritesItemEntity? { - val serializer = serializer + fun toDatabaseEntity(): SavedSearchableEntity? { + val serializer = getSerializer(searchable) val data = searchable?.let { serializer.serialize(it) } ?: return null - return FavoritesItemEntity( + return SavedSearchableEntity( key = key, - serializedSearchable = "${serializer.typePrefix}#${data}", + type = searchable.domain, + serializedSearchable = data, hidden = hidden, pinPosition = pinPosition, launchCount = launchCount diff --git a/favorites/src/main/java/de/mm20/launcher2/favorites/Serialization.kt b/favorites/src/main/java/de/mm20/launcher2/favorites/Serialization.kt index 3e441461..50bd179d 100644 --- a/favorites/src/main/java/de/mm20/launcher2/favorites/Serialization.kt +++ b/favorites/src/main/java/de/mm20/launcher2/favorites/Serialization.kt @@ -65,45 +65,44 @@ internal fun getSerializer(searchable: Searchable?): SearchableSerializer { return NullSerializer() } -internal fun getDeserializer(context: Context, serialized: String): SearchableDeserializer { - val type = serialized.substringBefore("#") - if (type == "app") { +internal fun getDeserializer(context: Context, type: String): SearchableDeserializer { + if (type == LauncherApp.Domain) { return LauncherAppDeserializer(context) } - if (type == "shortcut") { + if (type == LauncherShortcut.Domain) { return LauncherShortcutDeserializer(context) } - if (type == "legacyshortcut") { + if (type == LegacyShortcut.Domain) { return LegacyShortcutDeserializer(context) } - if (type == "calendar") { + if (type == CalendarEvent.Domain) { return CalendarEventDeserializer(context) } - if (type == "contact") { + if (type == Contact.Domain) { return ContactDeserializer(context) } - if (type == "wikipedia") { + if (type == Wikipedia.Domain) { return WikipediaDeserializer(context) } - if (type == "gdrive") { + if (type == GDriveFile.Domain) { return GDriveFileDeserializer() } - if (type == "onedrive") { + if (type == OneDriveFile.Domain) { return OneDriveFileDeserializer() } - if (type == "nextcloud") { + if (type == NextcloudFile.Domain) { return NextcloudFileDeserializer() } - if (type == "owncloud") { + if (type == OwncloudFile.Domain) { return OwncloudFileDeserializer() } - if (type == "file") { + if (type == LocalFile.Domain) { return LocalFileDeserializer(context) } - if (type == "website") { + if (type == Website.Domain) { return WebsiteDeserializer() } - if (type == "tag") { + if (type == Tag.Domain) { return TagDeserializer() } return NullDeserializer() diff --git a/favorites/src/main/java/de/mm20/launcher2/favorites/TagSerialization.kt b/favorites/src/main/java/de/mm20/launcher2/favorites/TagSerialization.kt index fd2b7209..7b92dc91 100644 --- a/favorites/src/main/java/de/mm20/launcher2/favorites/TagSerialization.kt +++ b/favorites/src/main/java/de/mm20/launcher2/favorites/TagSerialization.kt @@ -1,14 +1,13 @@ package de.mm20.launcher2.favorites -import de.mm20.launcher2.search.PinnableSearchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.search.SearchableDeserializer import de.mm20.launcher2.search.SearchableSerializer -import de.mm20.launcher2.search.Searchable import de.mm20.launcher2.search.data.Tag import org.json.JSONObject class TagSerializer: SearchableSerializer { - override fun serialize(searchable: PinnableSearchable): String { + override fun serialize(searchable: SavableSearchable): String { searchable as Tag val json = JSONObject() json.put("tag", searchable.tag) @@ -20,7 +19,7 @@ class TagSerializer: SearchableSerializer { } class TagDeserializer: SearchableDeserializer { - override fun deserialize(serialized: String): PinnableSearchable { + override fun deserialize(serialized: String): SavableSearchable { val json = JSONObject(serialized) return Tag(json.getString("tag")) diff --git a/favorites/src/main/java/de/mm20/launcher2/search/data/Tag.kt b/favorites/src/main/java/de/mm20/launcher2/search/data/Tag.kt index eea2f66c..8e3c363a 100644 --- a/favorites/src/main/java/de/mm20/launcher2/search/data/Tag.kt +++ b/favorites/src/main/java/de/mm20/launcher2/search/data/Tag.kt @@ -5,13 +5,12 @@ import android.os.Bundle import de.mm20.launcher2.icons.ColorLayer import de.mm20.launcher2.icons.StaticLauncherIcon import de.mm20.launcher2.icons.TextLayer -import de.mm20.launcher2.search.PinnableSearchable -import de.mm20.launcher2.search.Searchable +import de.mm20.launcher2.search.SavableSearchable data class Tag( val tag: String, override val labelOverride: String? = null -): PinnableSearchable { +): SavableSearchable { override val domain: String = Domain @@ -23,7 +22,7 @@ data class Tag( override fun launch(context: Context, options: Bundle?): Boolean { return false } - override fun overrideLabel(label: String): PinnableSearchable { + override fun overrideLabel(label: String): SavableSearchable { return this.copy(labelOverride = label) } diff --git a/files/src/main/java/de/mm20/launcher2/files/FileSerialization.kt b/files/src/main/java/de/mm20/launcher2/files/FileSerialization.kt index c2d03661..f660d6b5 100644 --- a/files/src/main/java/de/mm20/launcher2/files/FileSerialization.kt +++ b/files/src/main/java/de/mm20/launcher2/files/FileSerialization.kt @@ -6,8 +6,7 @@ import androidx.core.database.getStringOrNull import de.mm20.launcher2.ktx.jsonObjectOf import de.mm20.launcher2.permissions.PermissionGroup import de.mm20.launcher2.permissions.PermissionsManager -import de.mm20.launcher2.search.PinnableSearchable -import de.mm20.launcher2.search.Searchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.search.SearchableDeserializer import de.mm20.launcher2.search.SearchableSerializer import de.mm20.launcher2.search.data.* @@ -16,7 +15,7 @@ import org.koin.core.component.KoinComponent import org.koin.core.component.get class LocalFileSerializer : SearchableSerializer { - override fun serialize(searchable: PinnableSearchable): String { + override fun serialize(searchable: SavableSearchable): String { searchable as LocalFile return jsonObjectOf( "id" to searchable.id @@ -30,7 +29,7 @@ class LocalFileSerializer : SearchableSerializer { class LocalFileDeserializer( val context: Context ) : SearchableDeserializer, KoinComponent { - override fun deserialize(serialized: String): PinnableSearchable? { + override fun deserialize(serialized: String): SavableSearchable? { val permissionsManager: PermissionsManager = get() if (!permissionsManager.checkPermissionOnce( PermissionGroup.ExternalStorage @@ -75,7 +74,7 @@ class LocalFileDeserializer( } class GDriveFileSerializer : SearchableSerializer { - override fun serialize(searchable: PinnableSearchable): String { + override fun serialize(searchable: SavableSearchable): String { searchable as GDriveFile return jsonObjectOf( "id" to searchable.fileId, @@ -104,7 +103,7 @@ class GDriveFileSerializer : SearchableSerializer { } class GDriveFileDeserializer : SearchableDeserializer { - override fun deserialize(serialized: String): PinnableSearchable { + override fun deserialize(serialized: String): SavableSearchable { val json = JSONObject(serialized) val id = json.getString("id") val label = json.getString("label") @@ -135,7 +134,7 @@ class GDriveFileDeserializer : SearchableDeserializer { } class OneDriveFileSerializer : SearchableSerializer { - override fun serialize(searchable: PinnableSearchable): String { + override fun serialize(searchable: SavableSearchable): String { searchable as OneDriveFile return jsonObjectOf( "id" to searchable.fileId, @@ -162,7 +161,7 @@ class OneDriveFileSerializer : SearchableSerializer { } class OneDriveFileDeserializer : SearchableDeserializer { - override fun deserialize(serialized: String): PinnableSearchable { + override fun deserialize(serialized: String): SavableSearchable { val json = JSONObject(serialized) val fileId = json.getString("id") val label = json.getString("label") @@ -190,7 +189,7 @@ class OneDriveFileDeserializer : SearchableDeserializer { } class NextcloudFileSerializer : SearchableSerializer { - override fun serialize(searchable: PinnableSearchable): String { + override fun serialize(searchable: SavableSearchable): String { searchable as NextcloudFile return jsonObjectOf( "id" to searchable.fileId, @@ -217,7 +216,7 @@ class NextcloudFileSerializer : SearchableSerializer { } class NextcloudFileDeserializer : SearchableDeserializer { - override fun deserialize(serialized: String): PinnableSearchable { + override fun deserialize(serialized: String): SavableSearchable { val json = JSONObject(serialized) val id = json.getLong("id") val label = json.getString("label") @@ -243,7 +242,7 @@ class NextcloudFileDeserializer : SearchableDeserializer { } class OwncloudFileSerializer : SearchableSerializer { - override fun serialize(searchable: PinnableSearchable): String { + override fun serialize(searchable: SavableSearchable): String { searchable as OwncloudFile return jsonObjectOf( "id" to searchable.fileId, @@ -270,7 +269,7 @@ class OwncloudFileSerializer : SearchableSerializer { } class OwncloudFileDeserializer : SearchableDeserializer { - override fun deserialize(serialized: String): PinnableSearchable { + override fun deserialize(serialized: String): SavableSearchable { val json = JSONObject(serialized) val id = json.getLong("id") val label = json.getString("label") diff --git a/files/src/main/java/de/mm20/launcher2/search/data/File.kt b/files/src/main/java/de/mm20/launcher2/search/data/File.kt index ddea7e23..6b0d06e1 100644 --- a/files/src/main/java/de/mm20/launcher2/search/data/File.kt +++ b/files/src/main/java/de/mm20/launcher2/search/data/File.kt @@ -6,11 +6,10 @@ import de.mm20.launcher2.files.R import de.mm20.launcher2.icons.ColorLayer import de.mm20.launcher2.icons.StaticLauncherIcon import de.mm20.launcher2.icons.TintedIconLayer -import de.mm20.launcher2.search.PinnableSearchable -import de.mm20.launcher2.search.Searchable +import de.mm20.launcher2.search.SavableSearchable import java.util.* -interface File : PinnableSearchable { +interface File : SavableSearchable { val path: String val mimeType: String val size: Long diff --git a/files/src/main/java/de/mm20/launcher2/search/data/LocalFile.kt b/files/src/main/java/de/mm20/launcher2/search/data/LocalFile.kt index 8a5d882d..a593eb42 100644 --- a/files/src/main/java/de/mm20/launcher2/search/data/LocalFile.kt +++ b/files/src/main/java/de/mm20/launcher2/search/data/LocalFile.kt @@ -20,10 +20,8 @@ import de.mm20.launcher2.icons.* import de.mm20.launcher2.ktx.formatToString import de.mm20.launcher2.ktx.tryStartActivity import de.mm20.launcher2.media.ThumbnailUtilsCompat -import de.mm20.launcher2.search.PinnableSearchable import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -import org.koin.core.component.KoinComponent import java.io.IOException import java.io.File as JavaIOFile diff --git a/icons/src/main/java/de/mm20/launcher2/icons/IconRepository.kt b/icons/src/main/java/de/mm20/launcher2/icons/IconRepository.kt index db852bae..c444fec6 100644 --- a/icons/src/main/java/de/mm20/launcher2/icons/IconRepository.kt +++ b/icons/src/main/java/de/mm20/launcher2/icons/IconRepository.kt @@ -13,9 +13,8 @@ import de.mm20.launcher2.icons.transformations.LauncherIconTransformation import de.mm20.launcher2.icons.transformations.LegacyToAdaptiveTransformation import de.mm20.launcher2.icons.transformations.transform import de.mm20.launcher2.preferences.LauncherDataStore -import de.mm20.launcher2.search.PinnableSearchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.search.data.LauncherApp -import de.mm20.launcher2.search.Searchable import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -99,7 +98,7 @@ class IconRepository( } - fun getIcon(searchable: PinnableSearchable, size: Int): Flow = channelFlow { + fun getIcon(searchable: SavableSearchable, size: Int): Flow = channelFlow { iconProviders.collectLatest { providers -> transformations.collectLatest { transformations -> customAttributesRepository.getCustomIcon(searchable).collectLatest { customIcon -> @@ -190,7 +189,7 @@ class IconRepository( } suspend fun getCustomIconSuggestions( - searchable: PinnableSearchable, + searchable: SavableSearchable, size: Int ): List { val suggestions = mutableListOf() @@ -302,7 +301,7 @@ class IconRepository( } - suspend fun getUncustomizedDefaultIcon(searchable: PinnableSearchable, size: Int): CustomIconWithPreview? { + suspend fun getUncustomizedDefaultIcon(searchable: SavableSearchable, size: Int): CustomIconWithPreview? { val icon = iconProviders.first().getFirstIcon(searchable, size) ?.transform(transformations.first()) ?: return null return CustomIconWithPreview( @@ -339,7 +338,7 @@ class IconRepository( return iconPackIcons + themedIcons } - fun setCustomIcon(searchable: PinnableSearchable, icon: CustomIcon?) { + fun setCustomIcon(searchable: SavableSearchable, icon: CustomIcon?) { customAttributesRepository.setCustomIcon(searchable, icon) } diff --git a/icons/src/main/java/de/mm20/launcher2/icons/providers/CalendarIconProvider.kt b/icons/src/main/java/de/mm20/launcher2/icons/providers/CalendarIconProvider.kt index d75c8a98..a2eb46e9 100644 --- a/icons/src/main/java/de/mm20/launcher2/icons/providers/CalendarIconProvider.kt +++ b/icons/src/main/java/de/mm20/launcher2/icons/providers/CalendarIconProvider.kt @@ -6,12 +6,11 @@ import android.content.pm.PackageManager import de.mm20.launcher2.icons.DynamicCalendarIcon import de.mm20.launcher2.icons.LauncherIcon import de.mm20.launcher2.ktx.obtainTypedArrayOrNull -import de.mm20.launcher2.search.PinnableSearchable -import de.mm20.launcher2.search.Searchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.search.data.LauncherApp class CalendarIconProvider(val context: Context): IconProvider { - override suspend fun getIcon(searchable: PinnableSearchable, size: Int): LauncherIcon? { + override suspend fun getIcon(searchable: SavableSearchable, size: Int): LauncherIcon? { if(searchable !is LauncherApp) return null val component = ComponentName(searchable.`package`, searchable.activity) val pm = context.packageManager diff --git a/icons/src/main/java/de/mm20/launcher2/icons/providers/CustomIconPackIconProvider.kt b/icons/src/main/java/de/mm20/launcher2/icons/providers/CustomIconPackIconProvider.kt index 7c4be7d4..8194d398 100644 --- a/icons/src/main/java/de/mm20/launcher2/icons/providers/CustomIconPackIconProvider.kt +++ b/icons/src/main/java/de/mm20/launcher2/icons/providers/CustomIconPackIconProvider.kt @@ -4,14 +4,13 @@ import android.content.ComponentName import de.mm20.launcher2.customattrs.CustomIconPackIcon import de.mm20.launcher2.icons.IconPackManager import de.mm20.launcher2.icons.LauncherIcon -import de.mm20.launcher2.search.PinnableSearchable -import de.mm20.launcher2.search.Searchable +import de.mm20.launcher2.search.SavableSearchable class CustomIconPackIconProvider( private val customIcon: CustomIconPackIcon, private val iconPackManager: IconPackManager, ) : IconProvider { - override suspend fun getIcon(searchable: PinnableSearchable, size: Int): LauncherIcon? { + override suspend fun getIcon(searchable: SavableSearchable, size: Int): LauncherIcon? { return iconPackManager.getIcon( customIcon.iconPackPackage, ComponentName.unflattenFromString(customIcon.iconComponentName) ?: return null diff --git a/icons/src/main/java/de/mm20/launcher2/icons/providers/CustomThemedIconProvider.kt b/icons/src/main/java/de/mm20/launcher2/icons/providers/CustomThemedIconProvider.kt index a0178f77..c727962e 100644 --- a/icons/src/main/java/de/mm20/launcher2/icons/providers/CustomThemedIconProvider.kt +++ b/icons/src/main/java/de/mm20/launcher2/icons/providers/CustomThemedIconProvider.kt @@ -3,14 +3,13 @@ package de.mm20.launcher2.icons.providers import de.mm20.launcher2.customattrs.CustomThemedIcon import de.mm20.launcher2.icons.IconPackManager import de.mm20.launcher2.icons.LauncherIcon -import de.mm20.launcher2.search.PinnableSearchable -import de.mm20.launcher2.search.Searchable +import de.mm20.launcher2.search.SavableSearchable class CustomThemedIconProvider( private val customIcon: CustomThemedIcon, private val iconPackManager: IconPackManager, ): IconProvider { - override suspend fun getIcon(searchable: PinnableSearchable, size: Int): LauncherIcon? { + override suspend fun getIcon(searchable: SavableSearchable, size: Int): LauncherIcon? { return iconPackManager.getThemedIcon(customIcon.iconPackageName) } } \ No newline at end of file diff --git a/icons/src/main/java/de/mm20/launcher2/icons/providers/GoogleClockIconProvider.kt b/icons/src/main/java/de/mm20/launcher2/icons/providers/GoogleClockIconProvider.kt index c86e9177..5debdae2 100644 --- a/icons/src/main/java/de/mm20/launcher2/icons/providers/GoogleClockIconProvider.kt +++ b/icons/src/main/java/de/mm20/launcher2/icons/providers/GoogleClockIconProvider.kt @@ -8,12 +8,11 @@ import android.graphics.drawable.LayerDrawable import android.graphics.drawable.RotateDrawable import androidx.core.content.res.ResourcesCompat import de.mm20.launcher2.icons.* -import de.mm20.launcher2.search.PinnableSearchable -import de.mm20.launcher2.search.Searchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.search.data.LauncherApp class GoogleClockIconProvider(val context: Context) : IconProvider { - override suspend fun getIcon(searchable: PinnableSearchable, size: Int): LauncherIcon? { + override suspend fun getIcon(searchable: SavableSearchable, size: Int): LauncherIcon? { if (searchable !is LauncherApp) return null if (searchable.`package` != "com.google.android.deskclock") return null val pm = context.packageManager diff --git a/icons/src/main/java/de/mm20/launcher2/icons/providers/IconPackIconProvider.kt b/icons/src/main/java/de/mm20/launcher2/icons/providers/IconPackIconProvider.kt index d722025e..9215204b 100644 --- a/icons/src/main/java/de/mm20/launcher2/icons/providers/IconPackIconProvider.kt +++ b/icons/src/main/java/de/mm20/launcher2/icons/providers/IconPackIconProvider.kt @@ -3,9 +3,8 @@ package de.mm20.launcher2.icons.providers import android.content.ComponentName import android.content.Context import de.mm20.launcher2.icons.* -import de.mm20.launcher2.search.PinnableSearchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.search.data.LauncherApp -import de.mm20.launcher2.search.Searchable import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -14,7 +13,7 @@ class IconPackIconProvider( private val iconPack: String, private val iconPackManager: IconPackManager, ): IconProvider { - override suspend fun getIcon(searchable: PinnableSearchable, size: Int): LauncherIcon? { + override suspend fun getIcon(searchable: SavableSearchable, size: Int): LauncherIcon? { if (searchable !is LauncherApp) return null val component = ComponentName(searchable.`package`, searchable.activity) diff --git a/icons/src/main/java/de/mm20/launcher2/icons/providers/IconProvider.kt b/icons/src/main/java/de/mm20/launcher2/icons/providers/IconProvider.kt index 9c31ca01..a7a37fa5 100644 --- a/icons/src/main/java/de/mm20/launcher2/icons/providers/IconProvider.kt +++ b/icons/src/main/java/de/mm20/launcher2/icons/providers/IconProvider.kt @@ -1,15 +1,14 @@ package de.mm20.launcher2.icons.providers import de.mm20.launcher2.icons.LauncherIcon -import de.mm20.launcher2.search.PinnableSearchable -import de.mm20.launcher2.search.Searchable +import de.mm20.launcher2.search.SavableSearchable interface IconProvider { - suspend fun getIcon(searchable: PinnableSearchable, size: Int): LauncherIcon? + suspend fun getIcon(searchable: SavableSearchable, size: Int): LauncherIcon? } internal suspend fun Iterable.getFirstIcon( - searchable: PinnableSearchable, + searchable: SavableSearchable, size: Int ): LauncherIcon? { for (provider in this) { diff --git a/icons/src/main/java/de/mm20/launcher2/icons/providers/PlaceholderIconProvider.kt b/icons/src/main/java/de/mm20/launcher2/icons/providers/PlaceholderIconProvider.kt index fd27b717..7e1c92a8 100644 --- a/icons/src/main/java/de/mm20/launcher2/icons/providers/PlaceholderIconProvider.kt +++ b/icons/src/main/java/de/mm20/launcher2/icons/providers/PlaceholderIconProvider.kt @@ -2,11 +2,10 @@ package de.mm20.launcher2.icons.providers import android.content.Context import de.mm20.launcher2.icons.LauncherIcon -import de.mm20.launcher2.search.PinnableSearchable -import de.mm20.launcher2.search.Searchable +import de.mm20.launcher2.search.SavableSearchable class PlaceholderIconProvider(val context: Context) : IconProvider { - override suspend fun getIcon(searchable: PinnableSearchable, size: Int): LauncherIcon { + override suspend fun getIcon(searchable: SavableSearchable, size: Int): LauncherIcon { return searchable.getPlaceholderIcon(context) } } \ No newline at end of file diff --git a/icons/src/main/java/de/mm20/launcher2/icons/providers/SystemIconProvider.kt b/icons/src/main/java/de/mm20/launcher2/icons/providers/SystemIconProvider.kt index 56381ab1..5d1ec016 100644 --- a/icons/src/main/java/de/mm20/launcher2/icons/providers/SystemIconProvider.kt +++ b/icons/src/main/java/de/mm20/launcher2/icons/providers/SystemIconProvider.kt @@ -2,14 +2,13 @@ package de.mm20.launcher2.icons.providers import android.content.Context import de.mm20.launcher2.icons.LauncherIcon -import de.mm20.launcher2.search.PinnableSearchable -import de.mm20.launcher2.search.Searchable +import de.mm20.launcher2.search.SavableSearchable class SystemIconProvider( private val context: Context, private val themedIcons: Boolean, ) : IconProvider { - override suspend fun getIcon(searchable: PinnableSearchable, size: Int): LauncherIcon? { + override suspend fun getIcon(searchable: SavableSearchable, size: Int): LauncherIcon? { return searchable.loadIcon(context, size, themedIcons) } } \ No newline at end of file diff --git a/icons/src/main/java/de/mm20/launcher2/icons/providers/ThemedIconProvider.kt b/icons/src/main/java/de/mm20/launcher2/icons/providers/ThemedIconProvider.kt index dbb05553..15758af0 100644 --- a/icons/src/main/java/de/mm20/launcher2/icons/providers/ThemedIconProvider.kt +++ b/icons/src/main/java/de/mm20/launcher2/icons/providers/ThemedIconProvider.kt @@ -1,15 +1,14 @@ package de.mm20.launcher2.icons.providers import de.mm20.launcher2.icons.* -import de.mm20.launcher2.search.PinnableSearchable -import de.mm20.launcher2.search.Searchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.search.data.LauncherApp internal class ThemedIconProvider( private val iconPackManager: IconPackManager, ) : IconProvider { - override suspend fun getIcon(searchable: PinnableSearchable, size: Int): LauncherIcon? { + override suspend fun getIcon(searchable: SavableSearchable, size: Int): LauncherIcon? { if (searchable !is LauncherApp) return null return iconPackManager.getThemedIcon(searchable.`package`) } diff --git a/icons/src/main/java/de/mm20/launcher2/icons/providers/ThemedPlaceholderIconProvider.kt b/icons/src/main/java/de/mm20/launcher2/icons/providers/ThemedPlaceholderIconProvider.kt index 7798f447..c09521e1 100644 --- a/icons/src/main/java/de/mm20/launcher2/icons/providers/ThemedPlaceholderIconProvider.kt +++ b/icons/src/main/java/de/mm20/launcher2/icons/providers/ThemedPlaceholderIconProvider.kt @@ -2,14 +2,13 @@ package de.mm20.launcher2.icons.providers import android.content.Context import de.mm20.launcher2.icons.* -import de.mm20.launcher2.search.PinnableSearchable -import de.mm20.launcher2.search.Searchable +import de.mm20.launcher2.search.SavableSearchable internal class ThemedPlaceholderIconProvider( private val context: Context, ) : IconProvider { - override suspend fun getIcon(searchable: PinnableSearchable, size: Int): LauncherIcon { + override suspend fun getIcon(searchable: SavableSearchable, size: Int): LauncherIcon { val icon = searchable.getPlaceholderIcon(context) return StaticLauncherIcon( diff --git a/search/src/main/java/de/mm20/launcher2/search/SearchService.kt b/search/src/main/java/de/mm20/launcher2/search/SearchService.kt index 5fe001b5..fe4b3b77 100644 --- a/search/src/main/java/de/mm20/launcher2/search/SearchService.kt +++ b/search/src/main/java/de/mm20/launcher2/search/SearchService.kt @@ -36,7 +36,6 @@ import de.mm20.launcher2.wikipedia.WikipediaRepository import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList -import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.channelFlow @@ -216,7 +215,7 @@ internal class SearchServiceImpl( } launch { results - .map { it.toList().sortedBy { it as? PinnableSearchable }.toImmutableList() } + .map { it.toList().sortedBy { it as? SavableSearchable }.toImmutableList() } .collectLatest { send(it) } @@ -235,7 +234,7 @@ internal data class SearchResults( val unitConverters: List = emptyList(), val websites: List = emptyList(), val wikipedia: List = emptyList(), - val other: List = emptyList(), + val other: List = emptyList(), ) { fun toList(): List { return (apps + shortcuts + contacts + calendars + websites + wikipedia + other).distinctBy { it.key } + calculators+ unitConverters diff --git a/ui/src/main/java/de/mm20/launcher2/ui/common/FavoritesVM.kt b/ui/src/main/java/de/mm20/launcher2/ui/common/FavoritesVM.kt index 5312f3b8..f9477057 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/common/FavoritesVM.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/common/FavoritesVM.kt @@ -6,7 +6,7 @@ import de.mm20.launcher2.customattrs.CustomAttributesRepository import de.mm20.launcher2.customattrs.utils.withCustomLabels import de.mm20.launcher2.favorites.FavoritesRepository import de.mm20.launcher2.preferences.LauncherDataStore -import de.mm20.launcher2.search.PinnableSearchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.search.data.Tag import de.mm20.launcher2.widgets.WidgetRepository import kotlinx.coroutines.flow.* @@ -32,7 +32,7 @@ open class FavoritesVM : ViewModel(), KoinComponent { it.filterIsInstance() } - val favorites: Flow> = selectedTag.flatMapLatest { tag -> + val favorites: Flow> = selectedTag.flatMapLatest { tag -> if (tag == null) { val columns = dataStore.data.map { it.grid.columnCount } val excludeCalendar = widgetRepository.isCalendarWidgetEnabled() diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/modals/EditFavoritesSheet.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/modals/EditFavoritesSheet.kt index 310198fa..362d54bb 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/modals/EditFavoritesSheet.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/modals/EditFavoritesSheet.kt @@ -89,8 +89,7 @@ import androidx.compose.ui.unit.toSize import androidx.lifecycle.viewmodel.compose.viewModel import de.mm20.launcher2.badges.Badge import de.mm20.launcher2.icons.LauncherIcon -import de.mm20.launcher2.search.PinnableSearchable -import de.mm20.launcher2.search.Searchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.component.BottomSheetDialog import de.mm20.launcher2.ui.component.MissingPermissionBanner @@ -739,7 +738,7 @@ fun ShortcutPicker(viewModel: EditFavoritesSheetVM) { } sealed interface FavoritesSheetGridItem { - class Favorite(val item: PinnableSearchable) : FavoritesSheetGridItem + class Favorite(val item: SavableSearchable) : FavoritesSheetGridItem class Divider(val section: FavoritesSheetSection) : FavoritesSheetGridItem class Spacer(val span: Int = 1) : FavoritesSheetGridItem object EmptySection : FavoritesSheetGridItem diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/modals/EditFavoritesSheetVM.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/modals/EditFavoritesSheetVM.kt index dfe1cb9e..c55a2381 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/modals/EditFavoritesSheetVM.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/modals/EditFavoritesSheetVM.kt @@ -20,7 +20,7 @@ import de.mm20.launcher2.ktx.normalize import de.mm20.launcher2.permissions.PermissionGroup import de.mm20.launcher2.permissions.PermissionsManager import de.mm20.launcher2.preferences.LauncherDataStore -import de.mm20.launcher2.search.PinnableSearchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.search.data.AppShortcut import de.mm20.launcher2.search.Searchable import de.mm20.launcher2.search.data.Tag @@ -48,9 +48,9 @@ class EditFavoritesSheetVM : ViewModel(), KoinComponent { val createShortcutTarget = MutableLiveData(null) - private var manuallySorted: MutableList = mutableListOf() - private var automaticallySorted: MutableList = mutableListOf() - private var frequentlyUsed: MutableList = mutableListOf() + private var manuallySorted: MutableList = mutableListOf() + private var automaticallySorted: MutableList = mutableListOf() + private var frequentlyUsed: MutableList = mutableListOf() val pinnedTags = MutableLiveData>(emptyList()) val availableTags = MutableLiveData>(emptyList()) @@ -179,7 +179,7 @@ class EditFavoritesSheetVM : ViewModel(), KoinComponent { ) } - fun getIcon(searchable: PinnableSearchable, size: Int): Flow { + fun getIcon(searchable: SavableSearchable, size: Int): Flow { return iconRepository.getIcon(searchable, size) } diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/modals/HiddenItemsSheet.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/modals/HiddenItemsSheet.kt index 8d214c11..79d62fb9 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/modals/HiddenItemsSheet.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/modals/HiddenItemsSheet.kt @@ -16,15 +16,14 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel -import de.mm20.launcher2.search.PinnableSearchable -import de.mm20.launcher2.search.Searchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.component.BottomSheetDialog import de.mm20.launcher2.ui.launcher.search.common.grid.SearchResultGrid @Composable fun HiddenItemsSheet( - items: List, + items: List, onDismiss: () -> Unit ) { val viewModel: HiddenItemsSheetVM = viewModel() diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/SearchColumn.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/SearchColumn.kt index b4b40f19..d0abc0fa 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/SearchColumn.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/SearchColumn.kt @@ -43,8 +43,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel -import de.mm20.launcher2.search.PinnableSearchable -import de.mm20.launcher2.search.Searchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.component.LauncherCard import de.mm20.launcher2.ui.component.MissingPermissionBanner @@ -378,7 +377,7 @@ fun SearchColumn( } fun LazyListScope.GridResults( - items: ImmutableList, + items: ImmutableList, columns: Int, reverse: Boolean, showLabels: Boolean, @@ -443,7 +442,7 @@ fun LazyListScope.GridResults( @Composable fun GridRow( modifier: Modifier = Modifier, - items: ImmutableList, + items: ImmutableList, columns: Int, showLabels: Boolean, ) { @@ -467,7 +466,7 @@ fun GridRow( } fun LazyListScope.ListResults( - items: ImmutableList, + items: ImmutableList, reverse: Boolean, key: String, before: (@Composable () -> Unit)? = null, @@ -520,7 +519,7 @@ fun LazyListScope.ListResults( @Composable fun ListRow( modifier: Modifier = Modifier, - item: PinnableSearchable, + item: SavableSearchable, ) { Box( modifier = modifier.padding( diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/SearchVM.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/SearchVM.kt index 5a754f33..15447d15 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/SearchVM.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/SearchVM.kt @@ -1,17 +1,15 @@ package de.mm20.launcher2.ui.launcher.search -import android.util.Log import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.asLiveData import androidx.lifecycle.viewModelScope -import de.mm20.launcher2.customattrs.CustomAttributesRepository import de.mm20.launcher2.favorites.FavoritesRepository import de.mm20.launcher2.permissions.PermissionGroup import de.mm20.launcher2.permissions.PermissionsManager import de.mm20.launcher2.preferences.LauncherDataStore -import de.mm20.launcher2.search.PinnableSearchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.search.SearchService import de.mm20.launcher2.search.WebsearchRepository import de.mm20.launcher2.search.data.* @@ -47,7 +45,7 @@ class SearchVM : ViewModel(), KoinComponent { val unitConverterResults = MutableLiveData>(emptyList()) val websearchResults = MutableLiveData>(emptyList()) - val hiddenResults = MutableLiveData>(emptyList()) + val hiddenResults = MutableLiveData>(emptyList()) val favoritesEnabled = dataStore.data.map { it.favorites.enabled } val hideFavorites = MutableLiveData(false) @@ -90,7 +88,7 @@ class SearchVM : ViewModel(), KoinComponent { wikipedia = it.wikipediaSearch, ).collectLatest { results -> hiddenItemKeys.collectLatest { hiddenKeys -> - val hidden = mutableListOf() + val hidden = mutableListOf() val apps = mutableListOf() val workApps = mutableListOf() val shortcuts = mutableListOf() @@ -103,7 +101,7 @@ class SearchVM : ViewModel(), KoinComponent { val website = mutableListOf() for (r in results) { when { - r is PinnableSearchable && hiddenKeys.contains(r.key) -> { + r is SavableSearchable && hiddenKeys.contains(r.key) -> { hidden.add(r) } r is LauncherApp && !r.isMainProfile -> workApps.add(r) diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/SearchableItemVM.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/SearchableItemVM.kt index 7e3482bf..d64bf43a 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/SearchableItemVM.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/SearchableItemVM.kt @@ -10,7 +10,7 @@ import de.mm20.launcher2.favorites.FavoritesRepository import de.mm20.launcher2.icons.IconRepository import de.mm20.launcher2.icons.LauncherIcon import de.mm20.launcher2.ktx.isAtLeastApiLevel -import de.mm20.launcher2.search.PinnableSearchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.search.data.AppShortcut import de.mm20.launcher2.search.data.LauncherApp import kotlinx.coroutines.flow.Flow @@ -18,7 +18,7 @@ import org.koin.core.component.KoinComponent import org.koin.core.component.inject abstract class SearchableItemVM( - private val searchable: PinnableSearchable + private val searchable: SavableSearchable ) : KoinComponent { protected val favoritesRepository: FavoritesRepository by inject() protected val badgeRepository: BadgeRepository by inject() diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/customattrs/CustomizeSearchableSheet.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/customattrs/CustomizeSearchableSheet.kt index d17f63aa..eb963653 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/customattrs/CustomizeSearchableSheet.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/customattrs/CustomizeSearchableSheet.kt @@ -23,8 +23,7 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import de.mm20.launcher2.badges.Badge import de.mm20.launcher2.icons.CustomIconWithPreview -import de.mm20.launcher2.search.PinnableSearchable -import de.mm20.launcher2.search.Searchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.component.BottomSheetDialog import de.mm20.launcher2.ui.component.ShapedLauncherIcon @@ -36,7 +35,7 @@ import kotlinx.coroutines.launch @Composable fun CustomizeSearchableSheet( - searchable: PinnableSearchable, + searchable: SavableSearchable, onDismiss: () -> Unit, ) { val viewModel: CustomizeSearchableSheetVM = diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/customattrs/CustomizeSearchableSheetVM.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/customattrs/CustomizeSearchableSheetVM.kt index 9fc47dc3..0b3190a1 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/customattrs/CustomizeSearchableSheetVM.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/customattrs/CustomizeSearchableSheetVM.kt @@ -7,8 +7,7 @@ import de.mm20.launcher2.customattrs.CustomIcon import de.mm20.launcher2.icons.CustomIconWithPreview import de.mm20.launcher2.icons.IconRepository import de.mm20.launcher2.icons.LauncherIcon -import de.mm20.launcher2.search.PinnableSearchable -import de.mm20.launcher2.search.Searchable +import de.mm20.launcher2.search.SavableSearchable import kotlinx.coroutines.* import kotlinx.coroutines.flow.Flow import org.koin.core.component.KoinComponent @@ -16,7 +15,7 @@ import org.koin.core.component.inject import kotlin.coroutines.coroutineContext class CustomizeSearchableSheetVM( - private val searchable: PinnableSearchable + private val searchable: SavableSearchable ) : KoinComponent { private val iconRepository: IconRepository by inject() private val customAttributesRepository: CustomAttributesRepository by inject() diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/grid/GridItem.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/grid/GridItem.kt index 9e7c90d8..9036a8ba 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/grid/GridItem.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/grid/GridItem.kt @@ -22,7 +22,7 @@ import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Popup import androidx.compose.ui.window.PopupProperties -import de.mm20.launcher2.search.PinnableSearchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.search.Searchable import de.mm20.launcher2.search.data.* import de.mm20.launcher2.ui.component.LauncherCard @@ -45,7 +45,7 @@ import kotlinx.coroutines.delay @Composable -fun GridItem(modifier: Modifier = Modifier, item: PinnableSearchable, showLabels: Boolean = true) { +fun GridItem(modifier: Modifier = Modifier, item: SavableSearchable, showLabels: Boolean = true) { val viewModel = remember(item.key) { GridItemVM(item) } val context = LocalContext.current diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/grid/GridItemVM.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/grid/GridItemVM.kt index bf5913ac..15aa6108 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/grid/GridItemVM.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/grid/GridItemVM.kt @@ -1,9 +1,8 @@ package de.mm20.launcher2.ui.launcher.search.common.grid -import de.mm20.launcher2.search.PinnableSearchable -import de.mm20.launcher2.search.Searchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.ui.launcher.search.common.SearchableItemVM class GridItemVM( - searchable: PinnableSearchable + searchable: SavableSearchable ): SearchableItemVM(searchable) \ No newline at end of file diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/grid/SearchResultGrid.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/grid/SearchResultGrid.kt index 94277ac7..dc237c81 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/grid/SearchResultGrid.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/grid/SearchResultGrid.kt @@ -5,15 +5,14 @@ import androidx.compose.foundation.layout.* import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import de.mm20.launcher2.search.PinnableSearchable -import de.mm20.launcher2.search.Searchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.ui.layout.BottomReversed import de.mm20.launcher2.ui.locals.LocalGridColumns import kotlin.math.ceil @Composable fun SearchResultGrid( - items: List, + items: List, modifier: Modifier = Modifier, showLabels: Boolean = true, columns: Int = LocalGridColumns.current, diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/list/ListItem.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/list/ListItem.kt index c929895c..3f30592f 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/list/ListItem.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/list/ListItem.kt @@ -8,8 +8,7 @@ import androidx.compose.ui.geometry.Rect import androidx.compose.ui.layout.boundsInWindow import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.platform.LocalContext -import de.mm20.launcher2.search.PinnableSearchable -import de.mm20.launcher2.search.Searchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.search.data.* import de.mm20.launcher2.ui.component.InnerCard import de.mm20.launcher2.ui.launcher.search.calendar.CalendarItem @@ -18,7 +17,7 @@ import de.mm20.launcher2.ui.launcher.search.files.FileItem import de.mm20.launcher2.ui.launcher.search.shortcut.AppShortcutItem @Composable -fun ListItem(modifier: Modifier = Modifier, item: PinnableSearchable) { +fun ListItem(modifier: Modifier = Modifier, item: SavableSearchable) { var showDetails by remember { mutableStateOf(false) } val context = LocalContext.current diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/list/ListItemVM.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/list/ListItemVM.kt index 0b511671..87b92a5e 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/list/ListItemVM.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/list/ListItemVM.kt @@ -1,9 +1,8 @@ package de.mm20.launcher2.ui.launcher.search.common.list -import de.mm20.launcher2.search.PinnableSearchable -import de.mm20.launcher2.search.Searchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.ui.launcher.search.common.SearchableItemVM class ListItemVM( - searchable: PinnableSearchable + searchable: SavableSearchable ): SearchableItemVM(searchable) \ No newline at end of file diff --git a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/list/SearchResultList.kt b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/list/SearchResultList.kt index 5a2cc1d9..9c3613f4 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/list/SearchResultList.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/common/list/SearchResultList.kt @@ -8,13 +8,12 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.key import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import de.mm20.launcher2.search.PinnableSearchable -import de.mm20.launcher2.search.Searchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.ui.layout.BottomReversed @Composable fun SearchResultList( - items: List, + items: List, modifier: Modifier = Modifier, reverse: Boolean = false ) { diff --git a/ui/src/main/java/de/mm20/launcher2/ui/settings/hiddenitems/HiddenItemsSettingsScreenVM.kt b/ui/src/main/java/de/mm20/launcher2/ui/settings/hiddenitems/HiddenItemsSettingsScreenVM.kt index 650cc2be..f6502a90 100644 --- a/ui/src/main/java/de/mm20/launcher2/ui/settings/hiddenitems/HiddenItemsSettingsScreenVM.kt +++ b/ui/src/main/java/de/mm20/launcher2/ui/settings/hiddenitems/HiddenItemsSettingsScreenVM.kt @@ -14,9 +14,8 @@ import de.mm20.launcher2.favorites.FavoritesRepository import de.mm20.launcher2.icons.IconRepository import de.mm20.launcher2.icons.LauncherIcon import de.mm20.launcher2.ktx.isAtLeastApiLevel -import de.mm20.launcher2.search.PinnableSearchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.search.data.LauncherApp -import de.mm20.launcher2.search.Searchable import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.first @@ -33,18 +32,18 @@ class HiddenItemsSettingsScreenVM : ViewModel(), KoinComponent { val allApps = appRepository.getAllInstalledApps().map { withContext(Dispatchers.Default) { it.sorted() } }.asLiveData() - val hiddenItems: LiveData> = liveData { + val hiddenItems: LiveData> = liveData { val hidden = withContext(Dispatchers.Default) { favoritesRepository.getHiddenItems().first().filter { it !is LauncherApp }.sorted() } emit(hidden) } - fun isHidden(searchable: PinnableSearchable): Flow { + fun isHidden(searchable: SavableSearchable): Flow { return favoritesRepository.isHidden(searchable) } - fun setHidden(searchable: PinnableSearchable, hidden: Boolean) { + fun setHidden(searchable: SavableSearchable, hidden: Boolean) { if(hidden) { favoritesRepository.hideItem(searchable) } else { @@ -52,11 +51,11 @@ class HiddenItemsSettingsScreenVM : ViewModel(), KoinComponent { } } - fun getIcon(searchable: PinnableSearchable, size: Int): Flow { + fun getIcon(searchable: SavableSearchable, size: Int): Flow { return iconRepository.getIcon(searchable, size) } - fun launch(context: Context, searchable: PinnableSearchable) { + fun launch(context: Context, searchable: SavableSearchable) { val bundle = Bundle() if (isAtLeastApiLevel(31)) { bundle.putInt("android.activity.splashScreenStyle", 1) diff --git a/websites/src/main/java/de/mm20/launcher2/search/data/Website.kt b/websites/src/main/java/de/mm20/launcher2/search/data/Website.kt index 9fdb1ca1..d5cadddb 100644 --- a/websites/src/main/java/de/mm20/launcher2/search/data/Website.kt +++ b/websites/src/main/java/de/mm20/launcher2/search/data/Website.kt @@ -9,8 +9,7 @@ import coil.imageLoader import coil.request.ImageRequest import de.mm20.launcher2.icons.* import de.mm20.launcher2.ktx.tryStartActivity -import de.mm20.launcher2.search.PinnableSearchable -import de.mm20.launcher2.search.Searchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.websites.R import java.util.concurrent.ExecutionException @@ -22,7 +21,7 @@ data class Website( val favicon: String, val color: Int, override val labelOverride: String? = null, -) : PinnableSearchable { +) : SavableSearchable { override val domain: String = Domain diff --git a/websites/src/main/java/de/mm20/launcher2/websites/WebsiteSerialization.kt b/websites/src/main/java/de/mm20/launcher2/websites/WebsiteSerialization.kt index a4ed2a56..002a998b 100644 --- a/websites/src/main/java/de/mm20/launcher2/websites/WebsiteSerialization.kt +++ b/websites/src/main/java/de/mm20/launcher2/websites/WebsiteSerialization.kt @@ -1,15 +1,14 @@ package de.mm20.launcher2.websites import de.mm20.launcher2.ktx.jsonObjectOf -import de.mm20.launcher2.search.PinnableSearchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.search.SearchableDeserializer import de.mm20.launcher2.search.SearchableSerializer -import de.mm20.launcher2.search.Searchable import de.mm20.launcher2.search.data.Website import org.json.JSONObject class WebsiteSerializer : SearchableSerializer { - override fun serialize(searchable: PinnableSearchable): String { + override fun serialize(searchable: SavableSearchable): String { searchable as Website return jsonObjectOf( "label" to searchable.label, @@ -26,7 +25,7 @@ class WebsiteSerializer : SearchableSerializer { } class WebsiteDeserializer: SearchableDeserializer { - override fun deserialize(serialized: String): PinnableSearchable? { + override fun deserialize(serialized: String): SavableSearchable? { val json = JSONObject(serialized) return Website( label = json.getString("label"), diff --git a/wikipedia/src/main/java/de/mm20/launcher2/search/data/Wikipedia.kt b/wikipedia/src/main/java/de/mm20/launcher2/search/data/Wikipedia.kt index 656e6024..a47c8d76 100644 --- a/wikipedia/src/main/java/de/mm20/launcher2/search/data/Wikipedia.kt +++ b/wikipedia/src/main/java/de/mm20/launcher2/search/data/Wikipedia.kt @@ -11,8 +11,7 @@ import de.mm20.launcher2.icons.ColorLayer import de.mm20.launcher2.icons.StaticLauncherIcon import de.mm20.launcher2.icons.TintedIconLayer import de.mm20.launcher2.ktx.tryStartActivity -import de.mm20.launcher2.search.PinnableSearchable -import de.mm20.launcher2.search.Searchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.wikipedia.R data class Wikipedia( @@ -22,7 +21,7 @@ data class Wikipedia( val image: String?, val wikipediaUrl: String, override val labelOverride: String? = null, -) : PinnableSearchable { +) : SavableSearchable { override val domain: String = Domain diff --git a/wikipedia/src/main/java/de/mm20/launcher2/wikipedia/WikipediaSerialization.kt b/wikipedia/src/main/java/de/mm20/launcher2/wikipedia/WikipediaSerialization.kt index 5aa78e63..af32a436 100644 --- a/wikipedia/src/main/java/de/mm20/launcher2/wikipedia/WikipediaSerialization.kt +++ b/wikipedia/src/main/java/de/mm20/launcher2/wikipedia/WikipediaSerialization.kt @@ -1,15 +1,14 @@ package de.mm20.launcher2.wikipedia import android.content.Context -import de.mm20.launcher2.search.PinnableSearchable +import de.mm20.launcher2.search.SavableSearchable import de.mm20.launcher2.search.SearchableDeserializer import de.mm20.launcher2.search.SearchableSerializer -import de.mm20.launcher2.search.Searchable import de.mm20.launcher2.search.data.Wikipedia import org.json.JSONObject class WikipediaSerializer : SearchableSerializer { - override fun serialize(searchable: PinnableSearchable): String { + override fun serialize(searchable: SavableSearchable): String { searchable as Wikipedia val json = JSONObject() json.put("label", searchable.label) @@ -25,7 +24,7 @@ class WikipediaSerializer : SearchableSerializer { } class WikipediaDeserializer(val context: Context) : SearchableDeserializer { - override fun deserialize(serialized: String): PinnableSearchable? { + override fun deserialize(serialized: String): SavableSearchable? { val json = JSONObject(serialized) return Wikipedia( label = json.getString("label"),