From 158ddee6c3997fe12974995af0ea20e86842e00b Mon Sep 17 00:00:00 2001 From: 92 <169070113+I21b@users.noreply.github.com> Date: Mon, 14 Jul 2025 21:12:54 +0000 Subject: [PATCH 01/13] Translated using Weblate (Chinese (Simplified Han script)) Currently translated at 100.0% (828 of 828 strings) Translation: Kvaesitso/i18n --- .../src/main/res/values-zh-rCN/strings.xml | 63 ++++++++++++++++++- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/core/i18n/src/main/res/values-zh-rCN/strings.xml b/core/i18n/src/main/res/values-zh-rCN/strings.xml index 862270e6..bd8979c6 100644 --- a/core/i18n/src/main/res/values-zh-rCN/strings.xml +++ b/core/i18n/src/main/res/values-zh-rCN/strings.xml @@ -575,7 +575,7 @@ 开启于 %1$s, %2$s 在地图上查看 打开网站 - 您需要先设置该插件 + 您需要先设置此插件 此插件未正常运行 Bug 报告 长度单位 @@ -613,7 +613,7 @@ 支持的单位 链接的文件不为空,且其内容与此笔记的上次保存版本不匹配。您想保留哪个版本? 错误读取注释 - 无法读取链接文件。可能已被移动或删除。已从启动器的内部存储中恢复副本。如果您编辑笔记,链接文件可能会被覆盖 + 无法读取链接的文件,可能其已被移动或删除。已从启动器的存储中恢复副本。如果您编辑笔记,链接的文件可能会被覆盖。 保存笔记时出错 从原色开始 无法读取所选文件。请确保您选择的是有效的主题文件 (*.kvtheme),并且该文件未损坏。 @@ -793,4 +793,63 @@ 12小时 系统默认 需要通话权限才能开始通话 + 已有的样式将会被覆盖 + 透明 + 隐藏 + 填充 + 文件包含 + 标题字体 + 导入样式 + 刻度 + 导出样式 + 高对比度 + 形状 + 默认 + 直角 + 大圆角 + 基础形状 + 向上滑动 + 组件页 + 删除形状预设“%1$s”吗? + 你探索出了一套访问不了搜索和组件页的配置,使你无法进入设置 — 让启动器桌面变成了启动弃。 + 默认 + 透明度 + 半透明 + 删除透明度预设“%1$s”吗? + 雷雨 + 雾霾 + 任务 + 打开 Breezy Weather + 未选 + 保存为文件 + Breezy Weather + 名称 + 作者 + Breezy Weather + 在 Breezy Weather 中管理位置 + 搜索在 Tasks 应用中的任务 + (新建) + 设备默认的 + 可交互进度条 + 删除字体预设“%1$s”吗? + 恭喜!你给你自个儿锁里头了! + 需要 Tasks 权限来接入 Tasks 应用 + 要使用 Breezy Weather 作为天气数据源:\n\n1. 启用 Breezy Weather > 设置 > 微件与动态壁纸 > 发送天气数据到 Gadgetbridge 中的 %1$s\n\n2. 在 %1$s 中将 Breezy Weather 设为天气数据源 + 安装 + Tasks + 已成功接入 Tasks 并可以开始使用了。 + Tasks 是一个免费的开源 to-do 及提醒事项应用。如果已经安装,%1$s 可以显示并搜索在 Tasks 应用中的任务。 + + +%1$d 个未完成任务 + + 需要 Tasks 应用权限来搜索任务 + 文字 + 字体 + Breezy Weather 是一款免费的开源天气应用。安装后 %1$s 可将其作为天气数据的数据源。 + 正文字体 + 常规字体 + 直达组件 + 在主屏幕而不是组件页显示组件 + 标签必须拥有一个名字。如果继续设为空,这个标签会被删除。 + 打开 Tasks 应用 \ No newline at end of file From c0f69160b9e9c5ea41eae3ca44690286bd20be8a Mon Sep 17 00:00:00 2001 From: 92 <169070113+I21b@users.noreply.github.com> Date: Mon, 14 Jul 2025 21:30:11 +0000 Subject: [PATCH 02/13] Translated using Weblate (Chinese (Simplified Han script)) Currently translated at 100.0% (121 of 121 strings) Translation: Kvaesitso/units --- .../i18n/src/main/res/values-zh-rCN/units.xml | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/core/i18n/src/main/res/values-zh-rCN/units.xml b/core/i18n/src/main/res/values-zh-rCN/units.xml index d4a5b295..b6530c50 100644 --- a/core/i18n/src/main/res/values-zh-rCN/units.xml +++ b/core/i18n/src/main/res/values-zh-rCN/units.xml @@ -4,7 +4,7 @@ 米 - 公里 + 千米 厘米 @@ -119,28 +119,28 @@ 吉位字节 - 万亿位字节 + 太位字节 千比特 - kbit - Mbit + kb + Mb 兆比特 - Gbit + Gb 吉比特 - 万亿比特 + TB - terabits + 太比特 m/s km/h - 公里每小时 + 千米每小时 mph @@ -160,7 +160,7 @@ t - 公吨 + 吨 tn.l. @@ -192,7 +192,7 @@ 开 - 万亿字节 + 太字节 kiB From e6e7ada855a3699fd12bebf8f37f750a1b610d24 Mon Sep 17 00:00:00 2001 From: Oliver Tzeng Date: Fri, 18 Jul 2025 03:46:08 +0000 Subject: [PATCH 03/13] Translated using Weblate (Chinese (Traditional Han script)) Currently translated at 99.8% (827 of 828 strings) Translation: Kvaesitso/i18n --- core/i18n/src/main/res/values-zh-rTW/strings.xml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/core/i18n/src/main/res/values-zh-rTW/strings.xml b/core/i18n/src/main/res/values-zh-rTW/strings.xml index 60750bb4..ba4f6b0f 100644 --- a/core/i18n/src/main/res/values-zh-rTW/strings.xml +++ b/core/i18n/src/main/res/values-zh-rTW/strings.xml @@ -66,7 +66,7 @@ 西北偏西 西北 西北偏北 - https://en.wikipedia.org + https://zh.wikipedia.org/zh-tw/ 來自維基百科 標題:%1$s 藝術家:%1$s @@ -620,7 +620,7 @@ 線上結果 應用程式 中間 - 顯示秒 + 顯示秒數 底部 動態區域 自訂篩選器列 @@ -845,4 +845,9 @@ 向上滑動 小工具 開啟 Tasks 應用程式 + 不透明 + 隱藏 + 透明 + 時鐘標記 + 互動式播放器進度條 \ No newline at end of file From 8f2573fcbbd22e1b3a9dca1e9081beb805faa8b9 Mon Sep 17 00:00:00 2001 From: leekleak <142348248+leekleak@users.noreply.github.com> Date: Sat, 19 Jul 2025 18:59:24 +0300 Subject: [PATCH 04/13] fix (#1537) --- .../java/de/mm20/launcher2/ui/launcher/widgets/WidgetColumn.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/WidgetColumn.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/WidgetColumn.kt index b08b3ba6..3f064a37 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/WidgetColumn.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/widgets/WidgetColumn.kt @@ -66,7 +66,7 @@ fun WidgetColumn( Column( - modifier = modifier + modifier = modifier.fillMaxWidth() ) { val scope = rememberCoroutineScope() Column { From 154a81cafa76e9af7cf8ec298d32374b850b772c Mon Sep 17 00:00:00 2001 From: MM20 <15646950+MM2-0@users.noreply.github.com> Date: Sat, 19 Jul 2025 18:35:33 +0200 Subject: [PATCH 05/13] optimize/rename function --- .gitignore | 1 + .../launcher2/ui/launcher/search/SearchVM.kt | 70 ++++++++++--------- 2 files changed, 39 insertions(+), 32 deletions(-) diff --git a/.gitignore b/.gitignore index 05373ccf..198a321c 100644 --- a/.gitignore +++ b/.gitignore @@ -308,5 +308,6 @@ fabric.properties .idea/deploymentTargetSelector.xml .idea/copilot .idea/other.xml +.idea/studiobot.xml .kotlin \ No newline at end of file diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/SearchVM.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/SearchVM.kt index e9059df3..622303a2 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/SearchVM.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/search/SearchVM.kt @@ -250,10 +250,10 @@ class SearchVM : ViewModel(), KoinComponent { previousResults = SearchResults(apps = apps) searchActionResults.clear() - appResults.mergeWith(apps) - workAppResults.mergeWith(workApps) - privateSpaceAppResults.mergeWith(privateApps) - hiddenResults.mergeWith(hiddenItems) + appResults.updateItems(apps) + workAppResults.updateItems(workApps) + privateSpaceAppResults.updateItems(privateApps) + hiddenResults.updateItems(hiddenItems) } } else { @@ -273,19 +273,31 @@ class SearchVM : ViewModel(), KoinComponent { workAppResults.clear() privateSpaceAppResults.clear() - appResults.mergeWith(results.apps, hiddenKeys, query) - appShortcutResults.mergeWith(results.shortcuts, hiddenKeys, query) - fileResults.mergeWith(results.files, hiddenKeys, query) + appResults.updateItems( + results.apps + ?.filterNot { hiddenKeys.contains(it.key) } + ?.applyRanking(query) + ) + appShortcutResults.updateItems( + results.shortcuts + ?.filterNot { hiddenKeys.contains(it.key) } + ?.applyRanking(query) + ) + fileResults.updateItems( + results.files + ?.filterNot { hiddenKeys.contains(it.key) } + ?.applyRanking(query) + ) - contactResults.mergeWith( + contactResults.updateItems( results.contacts?.filterNot { hiddenKeys.contains(it.key) } ?.applyRanking(query) ) - calendarResults.mergeWith( + calendarResults.updateItems( results.calendars?.filterNot { hiddenKeys.contains(it.key) } ?.applyRanking(query) ) - locationResults.mergeWith( + locationResults.updateItems( results.locations?.filterNot { hiddenKeys.contains(it.key) } ?.let { locations -> devicePoseProvider.lastCachedLocation?.let { @@ -298,17 +310,17 @@ class SearchVM : ViewModel(), KoinComponent { } ?: locations.applyRanking(query) } ) - articleResults.mergeWith( + articleResults.updateItems( results.wikipedia?.applyRanking(query) ) - websiteResults.mergeWith( + websiteResults.updateItems( results.websites?.applyRanking(query) ) - calculatorResults.mergeWith(results.calculators) - unitConverterResults.mergeWith(results.unitConverters) + calculatorResults.updateItems(results.calculators) + unitConverterResults.updateItems(results.unitConverters) if (results.searchActions != null) { - searchActionResults.mergeWith(results.searchActions!!) + searchActionResults.updateItems(results.searchActions!!) } if (launchOnEnter.value) { @@ -429,24 +441,18 @@ class SearchVM : ViewModel(), KoinComponent { return sorted.distinctBy { it.key }.toList() } - private fun SnapshotStateList.mergeWith(newItems: List?) { - val items = newItems ?: emptyList() - val diff = toSet() subtract items.toSet() - removeAll(diff) - for ((i, item) in items.withIndex()) { - if (i < size) - set(i, item) - else - add(item) - } + /** + * Merges a list of new items into the current SnapshotStateList. + * It removes items that are in the current list but not in the new list. + * Then, it updates existing items or adds new items from the new list. + * + * @param T The type of items in the list. + * @param newItems The list of new items to merge with. If null, an empty list is used. + */ + private fun SnapshotStateList.updateItems(newItems: List?) { + clear() + addAll(newItems ?: emptyList()) } - - private suspend fun SnapshotStateList.mergeWith( - newItems: List?, - hiddenKeys: List, - query: String - ) = this.mergeWith((newItems ?: emptyList()).filterNot { hiddenKeys.contains(it.key) } - .applyRanking(query)) } From c212d904086f884c7759b7c765fdb576eab33b2f Mon Sep 17 00:00:00 2001 From: MM20 <15646950+MM2-0@users.noreply.github.com> Date: Sat, 19 Jul 2025 19:11:03 +0200 Subject: [PATCH 06/13] Fix Nextcloud logout when server is no longer reachable Close #1527 --- .../de/mm20/launcher2/nextcloud/NextcloudApiHelper.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libs/nextcloud/src/main/java/de/mm20/launcher2/nextcloud/NextcloudApiHelper.kt b/libs/nextcloud/src/main/java/de/mm20/launcher2/nextcloud/NextcloudApiHelper.kt index 27d3c3f2..3003788a 100644 --- a/libs/nextcloud/src/main/java/de/mm20/launcher2/nextcloud/NextcloudApiHelper.kt +++ b/libs/nextcloud/src/main/java/de/mm20/launcher2/nextcloud/NextcloudApiHelper.kt @@ -231,8 +231,12 @@ class NextcloudApiHelper(val context: Context) { .url("$server/ocs/v2.php/core/apppassword") .build() withContext(Dispatchers.IO) { - val response = httpClient.newCall(request).execute() - response + try { + val response = httpClient.newCall(request).execute() + response + } catch (e: IOException) { + Log.e("NextcloudApiHelper", "Error during Nextcloud logout", e) + } } preferences.edit { putString("server", null) From 4fc0de4518547c3ea2d95199db3958fad7c4d3d8 Mon Sep 17 00:00:00 2001 From: chipechop Date: Sun, 20 Jul 2025 12:59:33 +0000 Subject: [PATCH 07/13] Translated using Weblate (Italian) Currently translated at 100.0% (828 of 828 strings) Translation: Kvaesitso/i18n --- core/i18n/src/main/res/values-it/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/i18n/src/main/res/values-it/strings.xml b/core/i18n/src/main/res/values-it/strings.xml index 94d155c3..ede85009 100644 --- a/core/i18n/src/main/res/values-it/strings.xml +++ b/core/i18n/src/main/res/values-it/strings.xml @@ -589,7 +589,7 @@ Semplice Orbita Binario - Mani + Lancette 7 segmenti Nessun orologio Delineato From 64f309c144e9f1446f8a51de4995174b1880d5cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Marques?= Date: Sun, 20 Jul 2025 22:22:39 +0000 Subject: [PATCH 08/13] Translated using Weblate (Portuguese) Currently translated at 97.3% (806 of 828 strings) Translation: Kvaesitso/i18n --- core/i18n/src/main/res/values-pt/strings.xml | 61 +++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/core/i18n/src/main/res/values-pt/strings.xml b/core/i18n/src/main/res/values-pt/strings.xml index ef7dfb8b..ac7c886b 100644 --- a/core/i18n/src/main/res/values-pt/strings.xml +++ b/core/i18n/src/main/res/values-pt/strings.xml @@ -554,7 +554,7 @@ Aplicação Modelo de URL Ativar plugin - Pesquisa de ficheiros + Ficheiros Experimental Já existe uma etiqueta com este nome. Já existe uma etiqueta com este nome. Se continuar, as etiquetas serão combinadas. @@ -799,4 +799,63 @@ 24 horas 12 horas Padrão do sistema + Importar tema + O tema já existe e será atualizado + Transparente + Sólida + Oculta + Conteúdo + Ponteiros + Exportar tema + Alto contraste + Nome + Autor + Padrão + Super redonda + Formas + Forma base + Retangular + Tem a certeza de que deseja eliminar o esquema de formas %1$s? + Parabéns, acabou de se bloquear! + Abrir Breezy Weather + Transparência + Padrão + Semi-transparente + Breezy Weather + (sem nome) + Para utilizar Breezy Weather como serviço meteorológico:\n\n1. Aceda a Breezy Weather > Definições > Widgets & Papel de parede > Enviara dados Gadgetbridge > Ativar%1$s\n\n2. Em %1$s, selecione Breezy Weather como servoço de meteorologia. + Barra de progresso interativa + A permissão Tasks é necessária para a integração Tasks + Gerir localização em Breezy Weather + Nada selecionado + Guardar como ficheiro + Breezy Weather + Contactos + Tem a certeza de que deseja eliminar o esquema de transparência %1$s? + Instalar + A permissão Tasks é necessária para pesquisar tarefas + Tarefas + Pesquisar tarefas na aplicação Tasks + Tasks + Tasks é uma aplicação open souce para gerir tarefas, listas e lembretes. Se instalada, %1$s pode mostrar e pesquisar as tarefas na aplicação. + Integração com Tasks finalizada e pronta para utilização. + + +%1$d tarefa por realizar + +%1$d tarefas por realizar + +%1$d tarefas por realizar + + Tipografia + Breezy Weather é uma aplicação open source de meteorologia. Se instalada, %1$s pode utilizar Breezy Weather com a fonte de dados meteorológicos. + Tem a certeza de que deseja eliminar o esquema tipográfico %1$s? + Tipo de letra + Definições do dispositivo + Tipo de letra padrão + Tipo de letra do dispositivo + Genérica + Widgets no ecrã principal + Deslize acima + Mostrar widgets no ecrã principal e não em página secundária + Widgets + Você conseguir encontrar uma combinação de definições em não é possível aceder às pesquisas e às definições. Acabou de se bloquear. + Abrir Tasks \ No newline at end of file From f0374a08c7f6b54d95179d1f045d27a648ba2472 Mon Sep 17 00:00:00 2001 From: leekleak <142348248+leekleak@users.noreply.github.com> Date: Thu, 24 Jul 2025 21:13:46 +0300 Subject: [PATCH 09/13] fix widget duplicates (#1536) --- .../mm20/launcher2/services/widgets/WidgetsService.kt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/services/widgets/src/main/java/de/mm20/launcher2/services/widgets/WidgetsService.kt b/services/widgets/src/main/java/de/mm20/launcher2/services/widgets/WidgetsService.kt index b4184257..34b652c0 100644 --- a/services/widgets/src/main/java/de/mm20/launcher2/services/widgets/WidgetsService.kt +++ b/services/widgets/src/main/java/de/mm20/launcher2/services/widgets/WidgetsService.kt @@ -4,6 +4,7 @@ import android.appwidget.AppWidgetManager import android.appwidget.AppWidgetProviderInfo import android.content.Context import android.content.pm.LauncherApps +import android.os.Build import androidx.core.content.getSystemService import de.mm20.launcher2.widgets.CalendarWidget import de.mm20.launcher2.widgets.FavoritesWidget @@ -32,7 +33,15 @@ class WidgetsService( for (profile in profiles) { widgets.addAll(appWidgetManager.getInstalledProvidersForProfile(profile)) } - widgets + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + // Ignore widgets that the launcher is not supposed to access + widgets.filter { + it.widgetFeatures and AppWidgetProviderInfo.WIDGET_FEATURE_HIDE_FROM_PICKER == 0 + } + } else { + widgets + } } fun getAvailableBuiltInWidgets(): Flow> { From 341259d09f4dfe4741783d1c6e7b7d2dbd6ea07b Mon Sep 17 00:00:00 2001 From: MM20 <15646950+MM2-0@users.noreply.github.com> Date: Sun, 27 Jul 2025 16:47:24 +0200 Subject: [PATCH 10/13] Disallow extra widget page if widgets on home screen is enabled Close #1569 --- .../mm20/launcher2/ui/base/AppWidgetHost.kt | 4 +-- .../ui/launcher/SharedLauncherActivity.kt | 19 +++++++---- .../gestures/GestureSettingsScreen.kt | 5 +-- .../gestures/GestureSettingsScreenVM.kt | 3 ++ .../homescreen/HomescreenSettingsScreenVM.kt | 32 ------------------- 5 files changed, 21 insertions(+), 42 deletions(-) diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/base/AppWidgetHost.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/base/AppWidgetHost.kt index f2648693..189dafff 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/base/AppWidgetHost.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/base/AppWidgetHost.kt @@ -7,8 +7,8 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.remember import androidx.compose.runtime.staticCompositionLocalOf import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.lifecycle.Lifecycle +import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.lifecycle.repeatOnLifecycle import de.mm20.launcher2.crashreporter.CrashReporter import kotlinx.coroutines.awaitCancellation @@ -24,7 +24,7 @@ fun ProvideAppWidgetHost( val context = LocalContext.current val widgetHost = remember { AppWidgetHost(context.applicationContext, 44203) } LaunchedEffect(null) { - lifecycleOwner.lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { + lifecycleOwner.lifecycle.repeatOnLifecycle(Lifecycle.State.RESUMED) { widgetHost.startListening() try { awaitCancellation() diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/SharedLauncherActivity.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/SharedLauncherActivity.kt index 9b324033..3cb3cf48 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/SharedLauncherActivity.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/SharedLauncherActivity.kt @@ -77,7 +77,6 @@ import de.mm20.launcher2.ui.locals.LocalWindowSize import de.mm20.launcher2.ui.overlays.OverlayHost import de.mm20.launcher2.ui.theme.LauncherTheme import de.mm20.launcher2.ui.theme.wallpaperColorsAsState -import kotlin.math.pow abstract class SharedLauncherActivity( @@ -195,7 +194,10 @@ abstract class SharedLauncherActivity( if (it != null) { enterTransitionProgress.value = 0f enterTransition = it - enterTransitionProgress.animateTo(100f, animationSpec = animMotionSpec) + enterTransitionProgress.animateTo( + 100f, + animationSpec = animMotionSpec + ) enterTransition = null } } @@ -275,10 +277,15 @@ abstract class SharedLauncherActivity( }, ) - is GestureAction.Widgets -> ScaffoldGesture( - component = widgetComponent, - animation = if (gesture.orientation == null) ScaffoldAnimation.ZoomIn else ScaffoldAnimation.Push, - ) + is GestureAction.Widgets -> + if (widgetsOnHomeScreen == true) { + null + } else { + ScaffoldGesture( + component = widgetComponent, + animation = if (gesture.orientation == null) ScaffoldAnimation.ZoomIn else ScaffoldAnimation.Push, + ) + } is GestureAction.Notifications -> ScaffoldGesture( component = NotificationsComponent, diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/gestures/GestureSettingsScreen.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/gestures/GestureSettingsScreen.kt index 73066d09..7a3ff0be 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/gestures/GestureSettingsScreen.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/gestures/GestureSettingsScreen.kt @@ -52,6 +52,7 @@ fun GestureSettingsScreen() { val viewModel: GestureSettingsScreenVM = viewModel() val hasPermission by viewModel.hasPermission.collectAsStateWithLifecycle(null) + val allowWidgetGesture by viewModel.allowWidgetGesture.collectAsStateWithLifecycle(null) val options = buildList { add(stringResource(R.string.gesture_action_none) to GestureAction.NoAction) @@ -61,7 +62,7 @@ fun GestureSettingsScreen() { add(stringResource(R.string.gesture_action_recents) to GestureAction.Recents) add(stringResource(R.string.gesture_action_power_menu) to GestureAction.PowerMenu) add(stringResource(R.string.gesture_action_open_search) to GestureAction.Search) - add(stringResource(R.string.gesture_action_widgets) to GestureAction.Widgets) + if (allowWidgetGesture == true) add(stringResource(R.string.gesture_action_widgets) to GestureAction.Widgets) add(stringResource(R.string.gesture_action_launch_app) to GestureAction.Launch(null)) } @@ -265,7 +266,7 @@ fun GesturePreference( icon = icon, items = options, value = value, - summary = options.find { value?.javaClass == it.second.javaClass }?.first, + summary = options.find { value?.javaClass == it.second.javaClass }?.first ?: stringResource(R.string.gesture_action_none), onValueChanged = { if (it != null) onValueChanged(it) } ) } diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/gestures/GestureSettingsScreenVM.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/gestures/GestureSettingsScreenVM.kt index 1471af46..1f2fc989 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/gestures/GestureSettingsScreenVM.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/gestures/GestureSettingsScreenVM.kt @@ -34,6 +34,9 @@ class GestureSettingsScreenVM : ViewModel(), KoinComponent { val hasPermission = permissionsManager.hasPermission(PermissionGroup.Accessibility) .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) + val allowWidgetGesture = uiSettings.homeScreenWidgets.map { it == false } + .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) + val swipeDown = gestureSettings.swipeDown .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) val swipeLeft = gestureSettings.swipeLeft diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/homescreen/HomescreenSettingsScreenVM.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/homescreen/HomescreenSettingsScreenVM.kt index 7867b26f..fec61653 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/settings/homescreen/HomescreenSettingsScreenVM.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/settings/homescreen/HomescreenSettingsScreenVM.kt @@ -157,38 +157,6 @@ class HomescreenSettingsScreenVM( fun setWidgetsOnHomeScreen(widgetsOnHomeScreen: Boolean) { uiSettings.setHomeScreenWidgets(widgetsOnHomeScreen) - viewModelScope.launch { - val gestures = gestureSettings.first() - if (widgetsOnHomeScreen) { - if (gestures.swipeUp is GestureAction.Widgets) { - gestureSettings.setSwipeUp(GestureAction.NoAction) - } else if (gestures.swipeRight is GestureAction.Widgets) { - gestureSettings.setSwipeUp(GestureAction.NoAction) - } else if (gestures.swipeLeft is GestureAction.Widgets) { - gestureSettings.setSwipeUp(GestureAction.NoAction) - } else if (gestures.swipeDown is GestureAction.Widgets) { - gestureSettings.setSwipeUp(GestureAction.NoAction) - } else if (gestures.longPress is GestureAction.Widgets) { - gestureSettings.setLongPress(GestureAction.NoAction) - } else if (gestures.doubleTap is GestureAction.Widgets) { - gestureSettings.setDoubleTap(GestureAction.NoAction) - } - } else { - if (gestures.swipeUp is GestureAction.NoAction || gestures.swipeUp is GestureAction.Widgets) { - gestureSettings.setSwipeUp(GestureAction.Widgets) - } else if (gestures.swipeRight is GestureAction.NoAction || gestures.swipeRight is GestureAction.Widgets) { - gestureSettings.setSwipeRight(GestureAction.Widgets) - } else if (gestures.swipeLeft is GestureAction.NoAction || gestures.swipeLeft is GestureAction.Widgets) { - gestureSettings.setSwipeLeft(GestureAction.Widgets) - } else if (gestures.swipeDown is GestureAction.NoAction || gestures.swipeDown is GestureAction.Widgets) { - gestureSettings.setSwipeDown(GestureAction.Widgets) - } else if (gestures.longPress is GestureAction.NoAction || gestures.longPress is GestureAction.Widgets) { - gestureSettings.setLongPress(GestureAction.Widgets) - } else if (gestures.doubleTap is GestureAction.NoAction || gestures.doubleTap is GestureAction.Widgets) { - gestureSettings.setDoubleTap(GestureAction.Widgets) - } - } - } } companion object : KoinComponent { From 457a924a51f2ab297d91f5484d5091c6aac3ecb5 Mon Sep 17 00:00:00 2001 From: leekleak <142348248+leekleak@users.noreply.github.com> Date: Sun, 27 Jul 2025 17:51:49 +0300 Subject: [PATCH 11/13] fix duplicate pins (#1566) --- .../launcher2/ui/launcher/sheets/EditFavoritesSheet.kt | 7 +++++-- data/appshortcuts/build.gradle.kts | 1 + .../mm20/launcher2/appshortcuts/AppShortcutRepository.kt | 7 +++++-- .../src/main/java/de/mm20/launcher2/appshortcuts/Module.kt | 2 +- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/EditFavoritesSheet.kt b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/EditFavoritesSheet.kt index 705b1783..c59b28be 100644 --- a/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/EditFavoritesSheet.kt +++ b/app/ui/src/main/java/de/mm20/launcher2/ui/launcher/sheets/EditFavoritesSheet.kt @@ -119,10 +119,13 @@ fun EditFavoritesSheet( .align(Alignment.Center) ) } - } else if (createShortcutTarget != null) { - ShortcutPicker(viewModel, it) } else { ReorderFavoritesGrid(viewModel, it) + if (createShortcutTarget != null) { + BottomSheetDialog({viewModel.cancelPickShortcut()}) { + ShortcutPicker(viewModel, it) + } + } } } } diff --git a/data/appshortcuts/build.gradle.kts b/data/appshortcuts/build.gradle.kts index 1c2e6c3a..99d4665d 100644 --- a/data/appshortcuts/build.gradle.kts +++ b/data/appshortcuts/build.gradle.kts @@ -48,5 +48,6 @@ dependencies { implementation(project(":core:ktx")) implementation(project(":core:crashreporter")) implementation(project(":core:preferences")) + implementation(project(":core:profiles")) } \ No newline at end of file diff --git a/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/AppShortcutRepository.kt b/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/AppShortcutRepository.kt index 4dee8303..f5da3137 100644 --- a/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/AppShortcutRepository.kt +++ b/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/AppShortcutRepository.kt @@ -13,6 +13,7 @@ import de.mm20.launcher2.ktx.normalize import de.mm20.launcher2.permissions.PermissionGroup import de.mm20.launcher2.permissions.PermissionsManager import de.mm20.launcher2.preferences.search.ShortcutSearchSettings +import de.mm20.launcher2.profiles.ProfileManager import de.mm20.launcher2.search.AppShortcut import de.mm20.launcher2.search.ResultScore import de.mm20.launcher2.search.SearchableRepository @@ -27,6 +28,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map @@ -54,6 +56,7 @@ internal class AppShortcutRepositoryImpl( private val context: Context, private val permissionsManager: PermissionsManager, private val settings: ShortcutSearchSettings, + private val profileManager: ProfileManager, ) : AppShortcutRepository { private val scope = CoroutineScope(Dispatchers.Default + Job()) @@ -213,9 +216,9 @@ internal class AppShortcutRepositoryImpl( val launcherApps = context.getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps if (!launcherApps.hasShortcutHostPermission()) return emptyList() val results = mutableListOf() - val profiles = launcherApps.profiles + val profiles = profileManager.activeProfiles.first() for (profile in profiles) { - val activities = launcherApps.getShortcutConfigActivityList(null, profile) + val activities = launcherApps.getShortcutConfigActivityList(null, profile.userHandle) results.addAll( activities.map { AppShortcutConfigActivity(it) diff --git a/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/Module.kt b/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/Module.kt index 67b7bead..49bd6dcf 100644 --- a/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/Module.kt +++ b/data/appshortcuts/src/main/java/de/mm20/launcher2/appshortcuts/Module.kt @@ -8,7 +8,7 @@ import org.koin.core.qualifier.named import org.koin.dsl.module val appShortcutsModule = module { - factory { AppShortcutRepositoryImpl(androidContext(), get(), get()) } + factory { AppShortcutRepositoryImpl(androidContext(), get(), get(), get()) } factory>(named()) { get() } factory(named(LauncherShortcut.Domain)) { LauncherShortcutDeserializer(androidContext()) } factory(named(LegacyShortcut.Domain)) { LegacyShortcutDeserializer(androidContext()) } From f8e7bb99b568241b74df1d4e39f80c0437aadf0b Mon Sep 17 00:00:00 2001 From: Adhya D Date: Sat, 2 Aug 2025 16:25:48 +0530 Subject: [PATCH 12/13] Fixed typo in unsplash link text (#1576) --- docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index 7609d8d0..0e30c1bf 100644 --- a/docs/index.md +++ b/docs/index.md @@ -23,6 +23,6 @@ hero: - Wallpaper by Allec Gomes on Unspash.com + Wallpaper by Allec Gomes on Unsplash.com From 51e8cdbfe08c576d76696e6dced2f5abe91f71e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Marques?= Date: Sat, 2 Aug 2025 15:28:32 +0000 Subject: [PATCH 13/13] Translated using Weblate (Portuguese) Currently translated at 97.4% (807 of 828 strings) Translation: Kvaesitso/i18n --- core/i18n/src/main/res/values-pt/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/i18n/src/main/res/values-pt/strings.xml b/core/i18n/src/main/res/values-pt/strings.xml index ac7c886b..96d7dd44 100644 --- a/core/i18n/src/main/res/values-pt/strings.xml +++ b/core/i18n/src/main/res/values-pt/strings.xml @@ -805,7 +805,7 @@ Sólida Oculta Conteúdo - Ponteiros + Ponteiros 2 Exportar tema Alto contraste Nome @@ -823,7 +823,7 @@ Semi-transparente Breezy Weather (sem nome) - Para utilizar Breezy Weather como serviço meteorológico:\n\n1. Aceda a Breezy Weather > Definições > Widgets & Papel de parede > Enviara dados Gadgetbridge > Ativar%1$s\n\n2. Em %1$s, selecione Breezy Weather como servoço de meteorologia. + Para utilizar Breezy Weather como serviço meteorológico:\n\n1. Aceda a Breezy Weather > Definições > Widgets & Papel de parede > Enviara dados Gadgetbridge > Ativar%1$s\n\n2. Em %1$s, selecione Breezy Weather como serviço de meteorologia. Barra de progresso interativa A permissão Tasks é necessária para a integração Tasks Gerir localização em Breezy Weather