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()
|
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")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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)}')," +
|
||||||
|
|||||||
@ -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>) {
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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() })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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) ->
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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>
|
||||||
|
|||||||
@ -2,34 +2,29 @@ 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
|
||||||
|
|
||||||
class WidgetsVM: ViewModel(), KoinComponent {
|
class WidgetsVM : ViewModel(), KoinComponent {
|
||||||
private val widgetRepository: WidgetRepository by inject()
|
private val widgetRepository: WidgetRepository by inject()
|
||||||
|
|
||||||
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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6,5 +6,4 @@ import org.koin.dsl.module
|
|||||||
|
|
||||||
val widgetsModule = module {
|
val widgetsModule = module {
|
||||||
single { WidgetRepository(androidContext()) }
|
single { WidgetRepository(androidContext()) }
|
||||||
viewModel { WidgetViewModel(get()) }
|
|
||||||
}
|
}
|
||||||
@ -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) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -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