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()
targetSdk = sdk.versions.targetSdk.get().toInt()
versionCode = versionCodeDate()
versionName = "1.4.2"
versionName = "1.4.3"
multiDexEnabled = true
signingConfig = signingConfigs.getByName("debug")
}

View File

@ -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

View File

@ -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)}')," +

View File

@ -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>) {

View File

@ -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,

View File

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

View File

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

View File

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

View File

@ -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>

View File

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

View File

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

View File

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

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