Merge branch 'MM2-0:main' into french-launcher

This commit is contained in:
BrightDV 2022-02-08 19:33:46 +01:00 committed by GitHub
commit d9ca048fa7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 64 additions and 77 deletions

View File

@ -26,7 +26,7 @@ android {
minSdk = sdk.versions.minSdk.get().toInt() minSdk = sdk.versions.minSdk.get().toInt()
targetSdk = sdk.versions.targetSdk.get().toInt() targetSdk = sdk.versions.targetSdk.get().toInt()
versionCode = versionCodeDate() versionCode = versionCodeDate()
versionName = "1.4.2" versionName = "1.4.3"
multiDexEnabled = true multiDexEnabled = true
signingConfig = signingConfigs.getByName("debug") signingConfig = signingConfigs.getByName("debug")
} }

View File

@ -6,7 +6,7 @@ buildscript {
mavenCentral() mavenCentral()
} }
dependencies { dependencies {
classpath("com.android.tools.build:gradle:7.1.0") classpath("com.android.tools.build:gradle:7.1.1")
classpath(libs.kotlin.gradle) classpath(libs.kotlin.gradle)
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10")
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong

View File

@ -35,9 +35,9 @@ abstract class AppDatabase : RoomDatabase() {
override fun onCreate(db: SupportSQLiteDatabase) { override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db) super.onCreate(db)
db.execSQL("INSERT INTO Websearch (urlTemplate, label, color, icon) VALUES " + 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_google_url)}', '${context.getString(R.string.websearch_google)}', 0, NULL )," +
"('${context.getString(R.string.websearch_youtube_url)}', '${context.getString(R.string.websearch_youtube)}', 0xFFFF0000, 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)}', 0xFF00D3FF, 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 " + db.execSQL("INSERT INTO Widget (type, data, height, position, label) VALUES " +
"('internal', 'weather', -1, 0, '${context.getString(R.string.widget_name_weather)}')," + "('internal', 'weather', -1, 0, '${context.getString(R.string.widget_name_weather)}')," +

View File

@ -3,11 +3,12 @@ package de.mm20.launcher2.database
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.room.* import androidx.room.*
import de.mm20.launcher2.database.entities.WidgetEntity import de.mm20.launcher2.database.entities.WidgetEntity
import kotlinx.coroutines.flow.Flow
@Dao @Dao
interface WidgetDao { interface WidgetDao {
@Query("SELECT * FROM Widget ORDER BY position ASC") @Query("SELECT * FROM Widget ORDER BY position ASC")
fun getWidgets(): List<WidgetEntity> fun getWidgets(): Flow<List<WidgetEntity>>
@Transaction @Transaction
fun updateWidgets(widgets: List<WidgetEntity>) { fun updateWidgets(widgets: List<WidgetEntity>) {

View File

@ -18,9 +18,10 @@ data class FavoritesItem(
var pinPosition: Int, var pinPosition: Int,
var hidden: Boolean var hidden: Boolean
) : KoinComponent { ) : 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( return FavoritesItemEntity(
key = key, key = key,

View File

@ -103,7 +103,7 @@ internal class FavoritesRepositoryImpl(
pinPosition = 1, pinPosition = 1,
hidden = false hidden = false
) )
dao.insertReplaceExisting(favoritesItem.toDatabaseEntity()) favoritesItem.toDatabaseEntity()?.let { dao.insertReplaceExisting(it) }
} }
} }
} }
@ -132,7 +132,7 @@ internal class FavoritesRepositoryImpl(
pinPosition = 0, pinPosition = 0,
hidden = true hidden = true
) )
dao.insertReplaceExisting(favoritesItem.toDatabaseEntity()) favoritesItem.toDatabaseEntity()?.let { dao.insertReplaceExisting(it) }
} }
} }
} }
@ -149,8 +149,10 @@ internal class FavoritesRepositoryImpl(
scope.launch { scope.launch {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
val item = FavoritesItem(searchable.key, searchable, 0, 0, false) val item = FavoritesItem(searchable.key, searchable, 0, 0, false)
item.toDatabaseEntity()?.let {
AppDatabase.getInstance(context).searchDao() AppDatabase.getInstance(context).searchDao()
.incrementLaunchCount(item.toDatabaseEntity()) .incrementLaunchCount(it)
}
} }
} }
} }
@ -167,7 +169,7 @@ internal class FavoritesRepositoryImpl(
scope.launch { scope.launch {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
AppDatabase.getInstance(context).searchDao() AppDatabase.getInstance(context).searchDao()
.saveFavorites(favorites.map { it.toDatabaseEntity() }) .saveFavorites(favorites.mapNotNull { it.toDatabaseEntity() })
} }
} }
} }

View File

@ -50,7 +50,7 @@ val favoritesModule = module {
if (searchable is Website) { if (searchable is Website) {
return@factory WebsiteSerializer() return@factory WebsiteSerializer()
} }
throw IllegalArgumentException("No known serializer exists for type ${searchable.javaClass.canonicalName}") return@factory null
} }
factory { (serialized: String) -> factory { (serialized: String) ->

View File

@ -2,10 +2,8 @@ package de.mm20.launcher2.search.data
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri import android.net.Uri
import de.mm20.launcher2.files.R
import de.mm20.launcher2.helper.NetworkUtils
import de.mm20.launcher2.nextcloud.NextcloudApiHelper
class NextcloudFile( class NextcloudFile(
fileId: Long, fileId: Long,
@ -28,6 +26,22 @@ class NextcloudFile(
return Intent(Intent.ACTION_VIEW).apply { return Intent(Intent.ACTION_VIEW).apply {
data = Uri.parse("$server/f/$id") data = Uri.parse("$server/f/$id")
flags = Intent.FLAG_ACTIVITY_NEW_TASK 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
} }
} }
} }

View File

@ -210,7 +210,7 @@
<string name="preference_screen_badges_summary">Configure icon badges</string> <string name="preference_screen_badges_summary">Configure icon badges</string>
<string name="preference_notification_badges">Notification 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_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_suspended_badges">Suspended apps</string>
<string name="preference_cloud_badges">Cloud badges</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> <string name="preference_cloud_badges_summary">Show a badge for files that are stored in a cloud</string>

View File

@ -2,11 +2,10 @@ package de.mm20.launcher2.ui.launcher.widgets
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.asLiveData
import androidx.lifecycle.liveData import androidx.lifecycle.liveData
import androidx.lifecycle.viewModelScope
import de.mm20.launcher2.widgets.Widget import de.mm20.launcher2.widgets.Widget
import de.mm20.launcher2.widgets.WidgetRepository import de.mm20.launcher2.widgets.WidgetRepository
import kotlinx.coroutines.launch
import org.koin.core.component.KoinComponent import org.koin.core.component.KoinComponent
import org.koin.core.component.inject import org.koin.core.component.inject
@ -15,19 +14,15 @@ class WidgetsVM: ViewModel(), KoinComponent {
val isEditMode = MutableLiveData(false) val isEditMode = MutableLiveData(false)
val widgets = liveData<List<Widget>?> { val widgets = widgetRepository.getWidgets().asLiveData()
emit(widgetRepository.getWidgets())
}
fun setEditMode(editMode: Boolean) { fun setEditMode(editMode: Boolean) {
isEditMode.value = editMode isEditMode.value = editMode
} }
fun saveWidgets(widgets: List<Widget>) { fun saveWidgets(widgets: List<Widget>) {
viewModelScope.launch {
widgetRepository.saveWidgets(widgets) widgetRepository.saveWidgets(widgets)
} }
}
fun getInternalWidgets(): List<Widget> { fun getInternalWidgets(): List<Widget> {
return widgetRepository.getInternalWidgets() return widgetRepository.getInternalWidgets()

View File

@ -6,5 +6,4 @@ import org.koin.dsl.module
val widgetsModule = module { val widgetsModule = module {
single { WidgetRepository(androidContext()) } single { WidgetRepository(androidContext()) }
viewModel { WidgetViewModel(get()) }
} }

View File

@ -3,19 +3,22 @@ package de.mm20.launcher2.widgets
import android.content.Context import android.content.Context
import de.mm20.launcher2.widgets.R import de.mm20.launcher2.widgets.R
import de.mm20.launcher2.database.AppDatabase import de.mm20.launcher2.database.AppDatabase
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.*
import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.withContext import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import java.util.concurrent.Executors import java.util.concurrent.Executors
class WidgetRepository( class WidgetRepository(
val context: Context val context: Context
) { ) {
suspend fun getWidgets(): List<Widget> { private val scope = CoroutineScope(Job() + Dispatchers.Default)
return withContext(Dispatchers.IO) {
AppDatabase.getInstance(context).widgetDao().getWidgets().map { Widget(it) } fun getWidgets(): Flow<List<Widget>> {
} return AppDatabase.getInstance(context).widgetDao()
.getWidgets()
.map { it.map { Widget(it) } }
} }
fun getInternalWidgets(): List<Widget> { fun getInternalWidgets(): List<Widget> {
@ -27,9 +30,11 @@ class WidgetRepository(
} }
suspend fun saveWidgets(widgets: List<Widget>) { fun saveWidgets(widgets: List<Widget>) {
scope.launch {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
AppDatabase.getInstance(context).widgetDao().updateWidgets(widgets.mapIndexed { i, widget -> widget.toDatabaseEntity(i) }) AppDatabase.getInstance(context).widgetDao().updateWidgets(widgets.mapIndexed { i, widget -> widget.toDatabaseEntity(i) })
} }
} }
} }
}

View File

@ -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()
}
}