Merge branch 'MM2-0:main' into french-launcher
This commit is contained in:
commit
d9ca048fa7
@ -26,7 +26,7 @@ android {
|
||||
minSdk = sdk.versions.minSdk.get().toInt()
|
||||
targetSdk = sdk.versions.targetSdk.get().toInt()
|
||||
versionCode = versionCodeDate()
|
||||
versionName = "1.4.2"
|
||||
versionName = "1.4.3"
|
||||
multiDexEnabled = true
|
||||
signingConfig = signingConfigs.getByName("debug")
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ buildscript {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath("com.android.tools.build:gradle:7.1.0")
|
||||
classpath("com.android.tools.build:gradle:7.1.1")
|
||||
classpath(libs.kotlin.gradle)
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10")
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
|
||||
@ -35,9 +35,9 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
override fun onCreate(db: SupportSQLiteDatabase) {
|
||||
super.onCreate(db)
|
||||
db.execSQL("INSERT INTO Websearch (urlTemplate, label, color, icon) VALUES " +
|
||||
"('${context.getString(R.string.websearch_google_url)}', '${context.getString(R.string.websearch_google)}', 0xFF4285F4, NULL )," +
|
||||
"('${context.getString(R.string.websearch_youtube_url)}', '${context.getString(R.string.websearch_youtube)}', 0xFFFF0000, NULL )," +
|
||||
"('${context.getString(R.string.websearch_playstore_url)}', '${context.getString(R.string.websearch_playstore)}', 0xFF00D3FF, NULL );")
|
||||
"('${context.getString(R.string.websearch_google_url)}', '${context.getString(R.string.websearch_google)}', 0, NULL )," +
|
||||
"('${context.getString(R.string.websearch_youtube_url)}', '${context.getString(R.string.websearch_youtube)}', 0, NULL )," +
|
||||
"('${context.getString(R.string.websearch_playstore_url)}', '${context.getString(R.string.websearch_playstore)}', 0, NULL );")
|
||||
|
||||
db.execSQL("INSERT INTO Widget (type, data, height, position, label) VALUES " +
|
||||
"('internal', 'weather', -1, 0, '${context.getString(R.string.widget_name_weather)}')," +
|
||||
|
||||
@ -3,11 +3,12 @@ package de.mm20.launcher2.database
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.room.*
|
||||
import de.mm20.launcher2.database.entities.WidgetEntity
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface WidgetDao {
|
||||
@Query("SELECT * FROM Widget ORDER BY position ASC")
|
||||
fun getWidgets(): List<WidgetEntity>
|
||||
fun getWidgets(): Flow<List<WidgetEntity>>
|
||||
|
||||
@Transaction
|
||||
fun updateWidgets(widgets: List<WidgetEntity>) {
|
||||
|
||||
@ -18,9 +18,10 @@ data class FavoritesItem(
|
||||
var pinPosition: Int,
|
||||
var hidden: Boolean
|
||||
) : KoinComponent {
|
||||
private val serializer: SearchableSerializer by inject { parametersOf(searchable) }
|
||||
private val serializer: SearchableSerializer? by inject { parametersOf(searchable) }
|
||||
|
||||
fun toDatabaseEntity(): FavoritesItemEntity {
|
||||
fun toDatabaseEntity(): FavoritesItemEntity? {
|
||||
val serializer = serializer ?: return null
|
||||
|
||||
return FavoritesItemEntity(
|
||||
key = key,
|
||||
|
||||
@ -103,7 +103,7 @@ internal class FavoritesRepositoryImpl(
|
||||
pinPosition = 1,
|
||||
hidden = false
|
||||
)
|
||||
dao.insertReplaceExisting(favoritesItem.toDatabaseEntity())
|
||||
favoritesItem.toDatabaseEntity()?.let { dao.insertReplaceExisting(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -132,7 +132,7 @@ internal class FavoritesRepositoryImpl(
|
||||
pinPosition = 0,
|
||||
hidden = true
|
||||
)
|
||||
dao.insertReplaceExisting(favoritesItem.toDatabaseEntity())
|
||||
favoritesItem.toDatabaseEntity()?.let { dao.insertReplaceExisting(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -149,8 +149,10 @@ internal class FavoritesRepositoryImpl(
|
||||
scope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
val item = FavoritesItem(searchable.key, searchable, 0, 0, false)
|
||||
AppDatabase.getInstance(context).searchDao()
|
||||
.incrementLaunchCount(item.toDatabaseEntity())
|
||||
item.toDatabaseEntity()?.let {
|
||||
AppDatabase.getInstance(context).searchDao()
|
||||
.incrementLaunchCount(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -167,7 +169,7 @@ internal class FavoritesRepositoryImpl(
|
||||
scope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
AppDatabase.getInstance(context).searchDao()
|
||||
.saveFavorites(favorites.map { it.toDatabaseEntity() })
|
||||
.saveFavorites(favorites.mapNotNull { it.toDatabaseEntity() })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ val favoritesModule = module {
|
||||
if (searchable is Website) {
|
||||
return@factory WebsiteSerializer()
|
||||
}
|
||||
throw IllegalArgumentException("No known serializer exists for type ${searchable.javaClass.canonicalName}")
|
||||
return@factory null
|
||||
}
|
||||
|
||||
factory { (serialized: String) ->
|
||||
|
||||
@ -2,20 +2,18 @@ package de.mm20.launcher2.search.data
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import de.mm20.launcher2.files.R
|
||||
import de.mm20.launcher2.helper.NetworkUtils
|
||||
import de.mm20.launcher2.nextcloud.NextcloudApiHelper
|
||||
|
||||
class NextcloudFile(
|
||||
fileId: Long,
|
||||
override val label: String,
|
||||
path: String,
|
||||
mimeType: String,
|
||||
size: Long,
|
||||
isDirectory: Boolean,
|
||||
val server: String,
|
||||
metaData: List<Pair<Int, String>>
|
||||
fileId: Long,
|
||||
override val label: String,
|
||||
path: String,
|
||||
mimeType: String,
|
||||
size: Long,
|
||||
isDirectory: Boolean,
|
||||
val server: String,
|
||||
metaData: List<Pair<Int, String>>
|
||||
) : File(fileId, path, mimeType, size, isDirectory, metaData) {
|
||||
override val badgeKey: String = "nextcloud://"
|
||||
|
||||
@ -28,6 +26,22 @@ class NextcloudFile(
|
||||
return Intent(Intent.ACTION_VIEW).apply {
|
||||
data = Uri.parse("$server/f/$id")
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
`package` = getNextcloudAppPackage(context)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private fun getNextcloudAppPackage(context: Context): String? {
|
||||
val candidates = listOf("com.nextcloud.client", "com.nextcloud.android.beta")
|
||||
|
||||
for (c in candidates) {
|
||||
try {
|
||||
context.packageManager.getPackageInfo(c, 0)
|
||||
return c
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -210,7 +210,7 @@
|
||||
<string name="preference_screen_badges_summary">Configure icon badges</string>
|
||||
<string name="preference_notification_badges">Notification badges</string>
|
||||
<string name="preference_notification_badges_summary">Show a badge for applications with unread notifications</string>
|
||||
<string name="preference_suspended_badges_summary">Show a badge for suspended applicatoins</string>
|
||||
<string name="preference_suspended_badges_summary">Show a badge for suspended applications</string>
|
||||
<string name="preference_suspended_badges">Suspended apps</string>
|
||||
<string name="preference_cloud_badges">Cloud badges</string>
|
||||
<string name="preference_cloud_badges_summary">Show a badge for files that are stored in a cloud</string>
|
||||
|
||||
@ -2,34 +2,29 @@ package de.mm20.launcher2.ui.launcher.widgets
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.asLiveData
|
||||
import androidx.lifecycle.liveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import de.mm20.launcher2.widgets.Widget
|
||||
import de.mm20.launcher2.widgets.WidgetRepository
|
||||
import kotlinx.coroutines.launch
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
|
||||
class WidgetsVM: ViewModel(), KoinComponent {
|
||||
class WidgetsVM : ViewModel(), KoinComponent {
|
||||
private val widgetRepository: WidgetRepository by inject()
|
||||
|
||||
val isEditMode = MutableLiveData(false)
|
||||
|
||||
val widgets = liveData<List<Widget>?> {
|
||||
emit(widgetRepository.getWidgets())
|
||||
}
|
||||
val widgets = widgetRepository.getWidgets().asLiveData()
|
||||
|
||||
fun setEditMode(editMode: Boolean) {
|
||||
isEditMode.value = editMode
|
||||
}
|
||||
|
||||
fun saveWidgets(widgets: List<Widget>) {
|
||||
viewModelScope.launch {
|
||||
widgetRepository.saveWidgets(widgets)
|
||||
}
|
||||
widgetRepository.saveWidgets(widgets)
|
||||
}
|
||||
|
||||
fun getInternalWidgets() : List<Widget> {
|
||||
fun getInternalWidgets(): List<Widget> {
|
||||
return widgetRepository.getInternalWidgets()
|
||||
}
|
||||
}
|
||||
@ -6,5 +6,4 @@ import org.koin.dsl.module
|
||||
|
||||
val widgetsModule = module {
|
||||
single { WidgetRepository(androidContext()) }
|
||||
viewModel { WidgetViewModel(get()) }
|
||||
}
|
||||
@ -3,19 +3,22 @@ package de.mm20.launcher2.widgets
|
||||
import android.content.Context
|
||||
import de.mm20.launcher2.widgets.R
|
||||
import de.mm20.launcher2.database.AppDatabase
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
class WidgetRepository(
|
||||
val context: Context
|
||||
) {
|
||||
|
||||
suspend fun getWidgets(): List<Widget> {
|
||||
return withContext(Dispatchers.IO) {
|
||||
AppDatabase.getInstance(context).widgetDao().getWidgets().map { Widget(it) }
|
||||
}
|
||||
private val scope = CoroutineScope(Job() + Dispatchers.Default)
|
||||
|
||||
fun getWidgets(): Flow<List<Widget>> {
|
||||
return AppDatabase.getInstance(context).widgetDao()
|
||||
.getWidgets()
|
||||
.map { it.map { Widget(it) } }
|
||||
}
|
||||
|
||||
fun getInternalWidgets(): List<Widget> {
|
||||
@ -27,9 +30,11 @@ class WidgetRepository(
|
||||
}
|
||||
|
||||
|
||||
suspend fun saveWidgets(widgets: List<Widget>) {
|
||||
withContext(Dispatchers.IO) {
|
||||
AppDatabase.getInstance(context).widgetDao().updateWidgets(widgets.mapIndexed { i, widget -> widget.toDatabaseEntity(i) })
|
||||
fun saveWidgets(widgets: List<Widget>) {
|
||||
scope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
AppDatabase.getInstance(context).widgetDao().updateWidgets(widgets.mapIndexed { i, widget -> widget.toDatabaseEntity(i) })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
package de.mm20.launcher2.widgets
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class WidgetViewModel(
|
||||
private val widgetRepository: WidgetRepository
|
||||
) : ViewModel() {
|
||||
|
||||
|
||||
suspend fun getWidgets(): List<Widget> {
|
||||
return withContext(viewModelScope.coroutineContext + Dispatchers.IO) {
|
||||
widgetRepository.getWidgets()
|
||||
}
|
||||
}
|
||||
|
||||
fun saveWidgets(widgets: List<Widget>) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
widgetRepository.saveWidgets(widgets)
|
||||
}
|
||||
}
|
||||
|
||||
fun getInternalWidgets(): List<Widget> {
|
||||
return widgetRepository.getInternalWidgets()
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user