From 6fac398223185e6b56343c5d4594ae73b1859714 Mon Sep 17 00:00:00 2001 From: class0068 Date: Thu, 13 Mar 2025 22:24:37 +0000 Subject: [PATCH 01/20] Translated using Weblate (Chinese (Simplified Han script)) Currently translated at 98.4% (251 of 255 strings) Translation: jrpie-Launcher/Launcher Translate-URL: https://toolate.othing.xyz/projects/jrpie-launcher/launcher/zh_Hans/ --- app/src/main/res/values-zh-rCN/strings.xml | 61 +++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 793ef9d..72acf81 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -47,7 +47,7 @@ 使用全屏 功能 边缘滑动动作 - 零点击启动唯一搜索结果 + 直接启动匹配搜索内容的应用 搜索时呼出键盘 灵敏度 应用信息 @@ -213,4 +213,63 @@ µLauncher 需要作为默认的主屏幕来访问私人空间。 没有找到处理搜索的应用。 无法打开 URL:找不到浏览器。 + 我已知晓,这将赋予 µLauncher 广泛且重要的权限。 + 在应用程序列表中隐藏私人空间 + 隐藏已被暂停的应用 + 返回按键 / 返回手势 + 先单击然后再下滑 + 在网络上搜索 + (从)右上 (滑向)中左(滑向)右下 + 通过按回车键在应用列表搜索界面激活网络搜索。 + (从)左下 (滑向)中上(滑向)右下 + 选择锁定设备的方式 + 有2种方式可以用来锁定屏幕。 + 遗憾的是,两者都有缺点:

+ +

通过设置“设备管理应用”

+ 无法和指纹解锁和脸部解锁共同使用。 + +
+
+ +

通过“无障碍”功能

+ 需要更多的权限。 + µLauncher 将这些权限仅用于锁定屏幕。 +
+ (对于任何一个从网上下载的应用所做的类似声明,你都不应该抱持“默认为可信”的态度,你可以并应该检查一下它的源代码.) +
+ 在某些设备上,激活辅助功能服务后,启动PIN码将不再用于加密数据。 + 如果遇到该问题,可以通过该方法重新激活启动PIN码用于数据加密。 + +



+ 你可以在设置中随时更改这个选项。 + ]]>
+ 搜索(不触发自动启动应用程序) + 广泛且重要的权限。
µLauncher 将这些权限仅用于锁定屏幕。µLauncher 绝不会收集任何数据。尤其是,µLauncher 不会使用“无障碍”服务来收集任何数据。]]>
+ (从)左上 (滑向)中右(滑向)左下 + 单击 + 上滑 + 单击 + 下滑 + 单击 + 左滑 + 先单击然后再左滑 + 先单击然后再上滑 + 单击 + 右滑 + 先单击然后再右滑 + (从)左下 (滑向)中右(滑向)左上 + (从)右下 (滑向)中左(滑向)右上 + (从)左上 (滑向)中下(滑向)右上 + (从)右上 (滑向)中下(滑向)左上 + (从)右下 (滑向)中上(滑向)左下 + Λ (反向) + V(反向) + (反向)]]> + + 按空格键临时暂停该功能。 + 应用程序列表样式 + 绑定到手势 + 音乐:播放 / 暂停 + 报告安全漏洞 + 安全漏洞请不要在 Github 上以公开的方式提交,而是使用以下方式进行报告: + 感谢您帮助改进 µLauncher!\n请考虑在您的应用程序错误报告中添加以下信息: + 我已知晓,还有其他替代方法(使用设备管理员权限或电源按键)。 From b046388c36a99aca51cf8c38ad850ff5d54d5f8d Mon Sep 17 00:00:00 2001 From: anmoti Date: Thu, 13 Mar 2025 22:27:15 +0000 Subject: [PATCH 02/20] Translated using Weblate (Japanese) Currently translated at 17.6% (3 of 17 strings) Translation: jrpie-Launcher/metadata Translate-URL: https://toolate.othing.xyz/projects/jrpie-launcher/metadata/ja/ --- .../android/ja-JP/full_description.txt | 22 +++++++++++++++++++ .../android/ja-JP/short_description.txt | 1 + fastlane/metadata/android/ja-JP/title.txt | 1 + 3 files changed, 24 insertions(+) create mode 100644 fastlane/metadata/android/ja-JP/full_description.txt create mode 100644 fastlane/metadata/android/ja-JP/short_description.txt create mode 100644 fastlane/metadata/android/ja-JP/title.txt diff --git a/fastlane/metadata/android/ja-JP/full_description.txt b/fastlane/metadata/android/ja-JP/full_description.txt new file mode 100644 index 0000000..7d7e6bf --- /dev/null +++ b/fastlane/metadata/android/ja-JP/full_description.txt @@ -0,0 +1,22 @@ +µLauncherは、スワイプジェスチャとタップだけでアプリを起動できるホーム画面です。 +必要最小限で、効率的で、気が散らない。 + +ホーム画面には日付、時刻、壁紙のみが表示されます。 +戻るを押すか上にスワイプすると(これは設定可能)、 +インストールされているすべてのアプリのリストが開き、効率的に検索できます。 + + +このアプリは、Finn M Glas氏のアプリ Launcher のフォークです。 + +機能: +* 35種のジェスチャーにアクションを設定できます。 +* アクションは以下のいずれかになります: + - アプリを起動 + - アプリを表示 + - お気に入りのアプリを表示 + - ボリュームを上げる/下げる + - 音楽: 次/前の曲 + - 画面をロック + - ライトの切り替え + - 通知 / クイック設定を表示 +* 仕事用プロファイルに対応しているので、Shelterなどのアプリも使えます。 diff --git a/fastlane/metadata/android/ja-JP/short_description.txt b/fastlane/metadata/android/ja-JP/short_description.txt new file mode 100644 index 0000000..58b8c41 --- /dev/null +++ b/fastlane/metadata/android/ja-JP/short_description.txt @@ -0,0 +1 @@ +気が散らない、最小限の Android ホーム画面。 diff --git a/fastlane/metadata/android/ja-JP/title.txt b/fastlane/metadata/android/ja-JP/title.txt new file mode 100644 index 0000000..4305604 --- /dev/null +++ b/fastlane/metadata/android/ja-JP/title.txt @@ -0,0 +1 @@ +µLauncher From 718645d748816e489508cbefb46eb8782fcfa73c Mon Sep 17 00:00:00 2001 From: anmoti Date: Thu, 13 Mar 2025 22:46:11 +0000 Subject: [PATCH 03/20] Translated using Weblate (Japanese) Currently translated at 78.4% (200 of 255 strings) Translation: jrpie-Launcher/Launcher Translate-URL: https://toolate.othing.xyz/projects/jrpie-launcher/launcher/ja/ --- app/src/main/res/values-ja/strings.xml | 202 ++++++++++++++++++++++++- 1 file changed, 201 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index a6b3dae..077bb7e 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -1,2 +1,202 @@ - \ No newline at end of file + + アプリを開けません + 設定を変更しますか? + 設定 + アプリ + ランチャー + その他 + このジェスチャのアクションを選択するには設定を開きます + 上にスワイプ + タップしてから上にスワイプ + Double Up + Tap + Up + Up + Back + 2本指で上にスワイプ + Down + 下にスワイプ + Tap + Down + タップしてから下にスワイプ + Double Down + 2本指で下にスワイプ + Left + 左にスワイプ + Tap + Left + タップしてから左にスワイプ + Double Left + 2本指で左にスワイプ + Right + 右にスワイプ + タップしてから右にスワイプ + Double Right + Right (Top) + 画面の上部で右にスワイプ + Right (Bottom) + 画面の下部で右にスワイプ + Left (Bottom) + 画面の下部で左にスワイプ + Left (Top) + 画面の上部で左にスワイプ + Up (Left Edge) + Up (Right Edge) + 画面の右端で上にスワイプ + Down (Left Edge) + 画面の左端で下にスワイプ + Down (Right Edge) + ]]> + 左上 -> 右中 -> 左下 + (Reverse)]]> + 左下 -> 右中 -> 左上 + + 右上 -> 左中 -> 右下 + + V + 左上 -> 中下 -> 右上 + V (Reverse) + 右上 -> 中下 -> 左上 + Λ + 左下 -> 中上 -> 右下 + Λ (Reverse) + 右下 -> 中上 -> 左下 + Volume Down + 音量ダウンボタンを押す + Double Click + 空白部分をダブルタップ + Long Click + Date + 日付をタップ + Time + 時刻をタップ + アプリを選択 + 外観 + カラーテーマ + デフォルト + ダーク + ダイナミック + 文字の影 + 透明 + ブラー + ソリッド + フォント + システムデフォルト + モノクロのアプリアイコン + + + 時刻を表示 + 日付を表示 + ローカライズされた日付形式を使用する + 秒を表示 + 日付と時刻を反転 + 壁紙を選択 + 壁紙を変更 + 表示 + 画面オンを維持 + フルスクリーンを仕様 + 画面の回転 + 2本指でスワイプ + Edgeスワイプアクション + 画面端でスワイプ + アプリリストで検索中にリターンキーを押すとWeb検索が起動します。 + Webで検索 + 検索時にキーボードを表示 + アプリ + ジェスチャーに設定されたアプリをアプリ一覧に表示しない + 一時停止されたアプリを隠す + アプリ一覧のレイアウト + アプリ一覧を反転 + デフォルト + テキスト + グリッド + ランチャーのチュートリアルを見る + 設定をリセット + すべての設定を破棄します。続行しますか? + ソースコードを見る + バグを報告 + クリップボードにコピー + セキュリティ上の脆弱性をGitHubに公開しないでください。代わりに以下を使用してください。 + セキュリティ上の脆弱性を報告 + レポートを作成 + µLauncherのチャットに入る + プライバシーポリシー + Discordに参加してください! + 非表示のアプリ + プライベートスペース + アプリを選択 + アプリ + その他 + アンインストール + アプリ情報 + お気に入りから削除 + 隠す + 名称を変更 + アプリを削除できませんでした + 検索 + 検索(自動起動なし) + µLauncherの設定 + すべてのアプリ + プライベートスペースのロックを切り替え + 音楽: うるさい + 音楽: ひっそり + 音楽: 次 + 音楽: 前 + 通知パネルを表示 + なにもしねぇ + 画面をロック + ライトを切り替え + ショートカットを追加 + ジェシュチャーに設定 + Ok + アプリ一覧に表示 + チュートリアル + コンセプト + 使い方 + ホーム画面には現地の日付と時刻が表示されます。邪魔されることはありません。 + 1回のスワイプまたはボタンのタップでアプリを起動できます。次のスライドでいくつか選択してください。 + セットアップ + 選択内容は後で変更することもできます。 + さあ行きましょう! + 始める + 設定 + 戻るボタン / 戻るジェスチャ + ライト + Doubleスワイプアクション + 検索結果を起動 + お気に入りのアプリ + 音量アップボタンを押す + 空白部分をロングタップ + 機能性 + µLauncherの改善にご協力いただきありがとうございます。\nバグレポートに次の情報を追加することを検討してください。 + お気に入りに追加 + 画面の左端で上にスワイプ + 画面の右端で下にスワイプ + アプリをインストール + 選択されたアプリを削除しました + 始める準備はできました!これがあなたにとって大きな価値となることを願っています! \t- Finn(Launcherの作成者)とJosia(いくつかの改良を行い、フォーク μLauncher を保守) + Tap + Right + 2本指で右にスワイプ + 非表示のアプリ + μLauncherホーム画面に設定 + フォークの開発者に問い合わせ + オリジナルの開発者に問い合わせる + お気に入りのアプリ + 音楽: 再生 / 一時停止 + 薄暗い + 感度 + アプリ情報 + Volume Up + すべてのアプリ + 表示 + 右下 -> 左中 -> 右上 + 背景(アプリ一覧と設定) + 端の幅 + この機能を一時的に無効にするにはスペースキーを押します。 + プライベートスペース + アプリ一覧からプライベートスペースを隠す + この機能はあなたのデバイスでは動作しません。代わりにアプリケーションの詳細を管理しますか? + バグを報告 + このランチャーの使い方を学ぶのにほんの数秒しかかかりません + Launcherは、最小限かつ効率的で、邪魔にならないように設計されています。支払い、広告、追跡サービスは一切ありません。 + このアプリはオープンソース(MIT ライセンス)であり、GitHub で入手できます!リポジトリを必ずチェックしてください! + デフォルトのアプリをいくつか選択しました。必要に応じて今すぐ変更できます。 + From f048566bf6e29bc136dd5617f5e75d38e20e4f0a Mon Sep 17 00:00:00 2001 From: toolatebot Date: Fri, 14 Mar 2025 00:07:18 +0000 Subject: [PATCH 04/20] Update translation files Updated by "Cleanup translation files" add-on in Weblate. Translation: jrpie-Launcher/Launcher Translate-URL: https://toolate.othing.xyz/projects/jrpie-launcher/launcher/ --- app/src/main/res/values-de/strings.xml | 3 +-- app/src/main/res/values-es/strings.xml | 3 +-- app/src/main/res/values-fr/strings.xml | 3 +-- app/src/main/res/values-it/strings.xml | 3 +-- app/src/main/res/values-ja/strings.xml | 1 - app/src/main/res/values-pt-rBR/strings.xml | 1 - app/src/main/res/values-tr/strings.xml | 3 +-- app/src/main/res/values-zh-rCN/strings.xml | 1 - 8 files changed, 5 insertions(+), 13 deletions(-) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index e7c7546..9b3deda 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -97,7 +97,6 @@ Hintergrund ändern Bildschirm Bildschirm nicht ausschalten - Vollbild Bildschirm drehen Funktionalität Doppelte Wischaktionen @@ -277,4 +276,4 @@ Ich willige ein, dass µLauncher eine Bedienungshilfe für Zwecke verwendet, die nicht unter Barrierefreiheit fallen. Ich willige ein, dass µLauncher keine Daten sammelt. Bedienungshilfe aktivieren - \ No newline at end of file + diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index f0a80c6..df4a50a 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -63,7 +63,6 @@ Cambiar fondo de pantalla Pantalla Mantener encendida - Pantalla completa Funciones Deslizar con dos dedos Auto-lanzar búsquedas @@ -127,4 +126,4 @@ Iniciar Configuración Más opciones - \ No newline at end of file + diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 388e089..86accb2 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -55,7 +55,6 @@ Changer le fond d\'écran Écran Garder l\'écran allumé - Utiliser le plein écran Fonctions Actions de double balayage Lancer apps par recherche @@ -231,4 +230,4 @@ Balayer vers le bas au bord gauche de l\'écran Balayer au bord de l\'écran Couleur - \ No newline at end of file + diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 320bfc6..fe30410 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -115,7 +115,6 @@ Cambia immagine di sfondo Schermo Mantieni lo schermo acceso - Schermo intero Ruota lo schermo Funzionalità Apri automaticamente la tastiera per cercare @@ -237,4 +236,4 @@ Impossibile aprire l\'URL: nessun browser trovato. Non è stata trovata un\'applicazione per gestire la ricerca. privilegi più ampi a µLauncher.
µLauncher utilizzerà questi privilegi solo per bloccare lo schermo. µLauncher non raccoglierà mai alcun dato. In particolare, µLauncher non usa il servizio di accessibilità per raccogliere nessun dato.]]>
- \ No newline at end of file + diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 077bb7e..6cc844d 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -92,7 +92,6 @@ 壁紙を変更 表示 画面オンを維持 - フルスクリーンを仕様 画面の回転 2本指でスワイプ Edgeスワイプアクション diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 6a6149c..857e454 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -66,7 +66,6 @@ Alterar papel de parede Exibição Manter a tela ligada - Usar tela cheia Funcionalidades Gestos com 2 dedos Ações de deslize nas bordas diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index bfd0cfe..0c22e97 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -137,7 +137,6 @@ Duvar kağıdını değiştir Ekran Ekranı açık tut - Tam ekran kullan Ekranı döndür İşlevsellik Ekranın köşesinden kaydırın @@ -209,4 +208,4 @@ OK Renk Renk seçin - \ No newline at end of file + diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 72acf81..c445a75 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -44,7 +44,6 @@ 选择一个壁纸 换壁纸 保持屏幕常亮 - 使用全屏 功能 边缘滑动动作 直接启动匹配搜索内容的应用 From c9ee2c6304f9745cd314784e1d8174adbb2f2f53 Mon Sep 17 00:00:00 2001 From: Josia Pietsch Date: Fri, 14 Mar 2025 02:00:26 +0100 Subject: [PATCH 05/20] handle exception when acessing shortcuts --- .../de/jrpie/android/launcher/Functions.kt | 2 +- .../launcher/apps/PinnedShortcutInfo.kt | 23 +++++++++++-------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/de/jrpie/android/launcher/Functions.kt b/app/src/main/java/de/jrpie/android/launcher/Functions.kt index 81e58d7..7c2abbf 100644 --- a/app/src/main/java/de/jrpie/android/launcher/Functions.kt +++ b/app/src/main/java/de/jrpie/android/launcher/Functions.kt @@ -100,7 +100,7 @@ fun removeUnusedShortcuts(context: Context) { }, profile ) - } catch (e: IllegalStateException) { + } catch (e: Exception) { // https://github.com/jrpie/launcher/issues/116 return null } diff --git a/app/src/main/java/de/jrpie/android/launcher/apps/PinnedShortcutInfo.kt b/app/src/main/java/de/jrpie/android/launcher/apps/PinnedShortcutInfo.kt index a2815e5..1dc1e1f 100644 --- a/app/src/main/java/de/jrpie/android/launcher/apps/PinnedShortcutInfo.kt +++ b/app/src/main/java/de/jrpie/android/launcher/apps/PinnedShortcutInfo.kt @@ -28,15 +28,20 @@ class PinnedShortcutInfo( fun getShortcutInfo(context: Context): ShortcutInfo? { val launcherApps = context.getSystemService(Service.LAUNCHER_APPS_SERVICE) as LauncherApps - return launcherApps.getShortcuts( - ShortcutQuery().apply { - setQueryFlags(ShortcutQuery.FLAG_MATCH_PINNED) - setPackage(packageName) - setActivity(ComponentName(packageName, activityName)) - setShortcutIds(listOf(id)) - }, - getUserFromId(user, context) - )?.firstOrNull() + return try { + launcherApps.getShortcuts( + ShortcutQuery().apply { + setQueryFlags(ShortcutQuery.FLAG_MATCH_PINNED) + setPackage(packageName) + setActivity(ComponentName(packageName, activityName)) + setShortcutIds(listOf(id)) + }, + getUserFromId(user, context) + )?.firstOrNull() + } catch(_: Exception) { + // can throw SecurityException or IllegalStateException when profile is locked + null + } } override fun equals(other: Any?): Boolean { From b156b68d5380cc18582b9784e4868b1cd1bb85ed Mon Sep 17 00:00:00 2001 From: Josia Pietsch Date: Fri, 14 Mar 2025 02:39:30 +0100 Subject: [PATCH 06/20] improve German translation --- app/src/main/res/values-de/strings.xml | 32 +++++++++++++------------- app/src/main/res/values/strings.xml | 1 - 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index e7c7546..17b840f 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -6,8 +6,8 @@ - --> App kann nicht geöffnet werden - Möchtest du die App-Einstellungen anpassen? - Öffne die Einstellungen um für diese Geste eine Aktion zu wählen + App-Einstellungen anpassen? + Einstellungen öffnen um für diese Geste eine Aktion zu wählen Taschenlampe umschalten Tutorial - Nimm dir kurz Zeit und lerne, wie du diesen Launcher verwendest! + Hier eine kurze Erklärung, wie dieser Launcher funktioniert. Konzept - µLauncher bietet eine minimalistische, effiziente und ablenkungsfreie digitale Umgebung.\n\nDie App kostet dich nichts, enthält keine Werbung und sammelt keinerlei Daten. - Launcher ist open-source (MIT license) und auf GitHub!\n\nSchau gerne mal dort vorbei! + µLauncher bietet eine minimalistische, effiziente und ablenkungsfreie digitale Umgebung.\n\nDie App ist freie Software, enthält keine Werbung und sammelt keinerlei Daten. + Der Quellcode ist bei GitHub zu finden. Benutzung - Auf deinem Homescreen siehst du nur das Datum und die Uhrzeit. Keine Ablenkung. - Du öffnest Apps indem du über den Bildschirm wischt oder die Lautstärketasten drückst. Gleich wählst du deine Apps. + Der Homescreen zeigt nur das Datum und die Uhrzeit. Keine Ablenkung. + Häufig verwendete Apps können mittels Gesten, z.B. Wischen oder den Lautstärketasten geöffnet werden. Gleich können die Apps ausgewählt werden. Einrichtung - Wir haben dir ein paar Standardapps ausgewählt, du kannst sie hier gerne ändern: - Du kannst deine Auswahl in den Einstellungen später jederzeit ändern. + Es wurden Standardapps ausgewählt, die Zuordnung kann hier angepasst werden: + Die Auswahl kann in den Einstellungen später jederzeit geändert werden. Los gehts! - Du bist bereit loszulegen!\n\nIch hoffe diese App ist nützlich für dich!\n\n- Finn (der Entwickler)\n\tund Josia (der einige Änderungen vorgenommen hat und den Fork μLauncher entwickelt) + Es kann losgehen!\n\nWir hoffen, dass diese App hilfreich ist!\n\n- Finn (der Entwickler)\n\tund Josia (der einige Änderungen vorgenommen hat und den Fork μLauncher entwickelt) Starten Einstellungen Mehr Optionen Benachrichtigungen - Fehler: Diese Funktion wird von deinem Gerät leider nicht unterstützt. + Fehler: Die Funktion wird von diesem Gerät leider nicht unterstützt. Sekunden anzeigen Rückgängig Schnelleinstellungen @@ -195,7 +195,7 @@ Diese Funktionalität benötigt Android 15 oder neuer. Die App wurde versteckt. Sie kann in den Einstellungen wieder sichtbar gemacht werden. µLauncher muss Geräteadministrator sein, um den Bildschirm sperren zu dürfen. - Dies ist erforderlich, damit µLauncher den Bildschirm spreen kann. + Dies ist erforderlich, damit µLauncher den Bildschirm sperren kann. Die Aktion \"Bildschirm sperren\" aktivieren Es wurde keine geeignete Kamera gefunden. Fehler: Kein Zugriff auf die Kamera möglich. @@ -234,8 +234,8 @@ Dies erfordert sehr weitgehende Berechtigungen. µLauncher wird diese ausschließlich zum Sperren des Bildschirms verwenden.
- (Irgeneiner gerade heruntergeladenen App sollte man eine solche Behauptung natürlich nicht einfach glauben. - Du kannst jedoch den Source Code selbst prüfen.) + (Irgendeiner gerade heruntergeladenen App sollte man eine solche Behauptung natürlich nicht einfach glauben. + Der Quelltext dieser App ist jedoch frei verfügbar und kann überprüft werden.)



@@ -277,4 +277,4 @@ Ich willige ein, dass µLauncher eine Bedienungshilfe für Zwecke verwendet, die nicht unter Barrierefreiheit fallen. Ich willige ein, dass µLauncher keine Daten sammelt. Bedienungshilfe aktivieren - \ No newline at end of file + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 902e147..3177442 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -192,7 +192,6 @@ --> Set μLauncher as home screen App Info - Your device does not support this feature. Manage application details instead? View Launcher Tutorial From 6cd17343fcc856a6fab0ef6ffbea28f58a174ef6 Mon Sep 17 00:00:00 2001 From: Josia Pietsch Date: Fri, 14 Mar 2025 04:09:28 +0100 Subject: [PATCH 07/20] show questionmark when unkown app or shortcut is bound to gesture --- .../actions/SettingsFragmentActionsRecycler.kt | 10 ++++++++-- .../main/res/drawable/baseline_question_mark_24.xml | 12 ++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 app/src/main/res/drawable/baseline_question_mark_24.xml diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/settings/actions/SettingsFragmentActionsRecycler.kt b/app/src/main/java/de/jrpie/android/launcher/ui/settings/actions/SettingsFragmentActionsRecycler.kt index d7862fa..1f91913 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/settings/actions/SettingsFragmentActionsRecycler.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/settings/actions/SettingsFragmentActionsRecycler.kt @@ -11,6 +11,7 @@ import android.view.ViewGroup import android.widget.Button import android.widget.ImageView import android.widget.TextView +import androidx.appcompat.content.res.AppCompatResources import androidx.fragment.app.Fragment import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -94,6 +95,8 @@ class SettingsFragmentActionsRecycler : Fragment(), UIObject { class ActionsRecyclerAdapter(val activity: Activity) : RecyclerView.Adapter() { + private val drawableUnknown = AppCompatResources.getDrawable(activity, R.drawable.baseline_question_mark_24) + private val gesturesList: ArrayList = Gesture.entries.filter(Gesture::isEnabled) as ArrayList @@ -115,15 +118,18 @@ class ActionsRecyclerAdapter(val activity: Activity) : private fun updateViewHolder(gesture: Gesture, viewHolder: ViewHolder) { val action = Action.forGesture(gesture) - val drawable = action?.getIcon(activity) - if (action == null || drawable == null) { + if (action == null) { viewHolder.img.visibility = View.INVISIBLE viewHolder.removeAction.visibility = View.GONE viewHolder.chooseButton.visibility = View.VISIBLE return } + // Use the unknown icon if there is an action, but we can't find its icon. + // Probably an app was uninstalled. + val drawable = action.getIcon(activity) ?: drawableUnknown + viewHolder.img.visibility = View.VISIBLE viewHolder.removeAction.visibility = View.VISIBLE viewHolder.chooseButton.visibility = View.INVISIBLE diff --git a/app/src/main/res/drawable/baseline_question_mark_24.xml b/app/src/main/res/drawable/baseline_question_mark_24.xml new file mode 100644 index 0000000..9a2b28a --- /dev/null +++ b/app/src/main/res/drawable/baseline_question_mark_24.xml @@ -0,0 +1,12 @@ + + + + + From c7af387a944dfb90a2a50db80a582cfa192caea5 Mon Sep 17 00:00:00 2001 From: Josia Pietsch Date: Fri, 14 Mar 2025 04:11:47 +0100 Subject: [PATCH 08/20] implement #98 - hide lock icon when 'hide private space when locked' setting is set --- .../launcher/actions/LauncherAction.kt | 17 ++++-- .../android/launcher/apps/PrivateSpace.kt | 14 +++++ .../android/launcher/ui/list/ListActivity.kt | 58 ++++++++++--------- 3 files changed, 57 insertions(+), 32 deletions(-) diff --git a/app/src/main/java/de/jrpie/android/launcher/actions/LauncherAction.kt b/app/src/main/java/de/jrpie/android/launcher/actions/LauncherAction.kt index 1ed6473..3c89a67 100644 --- a/app/src/main/java/de/jrpie/android/launcher/actions/LauncherAction.kt +++ b/app/src/main/java/de/jrpie/android/launcher/actions/LauncherAction.kt @@ -13,6 +13,7 @@ import androidx.appcompat.content.res.AppCompatResources import de.jrpie.android.launcher.Application import de.jrpie.android.launcher.R import de.jrpie.android.launcher.apps.AppFilter +import de.jrpie.android.launcher.apps.hidePrivateSpaceWhenLocked import de.jrpie.android.launcher.apps.isPrivateSpaceSupported import de.jrpie.android.launcher.apps.togglePrivateSpaceLock import de.jrpie.android.launcher.preferences.LauncherPreferences @@ -66,7 +67,11 @@ enum class LauncherAction( R.string.list_other_list_private_space, R.drawable.baseline_security_24, { context -> - openAppsList(context, private = true) + if ((context.applicationContext as Application).privateSpaceLocked.value != true + || !hidePrivateSpaceWhenLocked(context) + ) { + openAppsList(context, private = true) + } }, available = { _ -> isPrivateSpaceSupported() @@ -83,31 +88,31 @@ enum class LauncherAction( "volume_up", R.string.list_other_volume_up, R.drawable.baseline_volume_up_24, - { context -> audioVolumeAdjust(context, true)} + { context -> audioVolumeAdjust(context, true) } ), VOLUME_DOWN( "volume_down", R.string.list_other_volume_down, R.drawable.baseline_volume_down_24, - { context -> audioVolumeAdjust(context, false)} + { context -> audioVolumeAdjust(context, false) } ), TRACK_PLAY_PAUSE( "play_pause_track", R.string.list_other_track_play_pause, R.drawable.baseline_play_arrow_24, - { context -> audioManagerPressKey(context, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE)} + { context -> audioManagerPressKey(context, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) } ), TRACK_NEXT( "next_track", R.string.list_other_track_next, R.drawable.baseline_skip_next_24, - { context -> audioManagerPressKey(context, KeyEvent.KEYCODE_MEDIA_NEXT)} + { context -> audioManagerPressKey(context, KeyEvent.KEYCODE_MEDIA_NEXT) } ), TRACK_PREV( "previous_track", R.string.list_other_track_previous, R.drawable.baseline_skip_previous_24, - { context -> audioManagerPressKey(context, KeyEvent.KEYCODE_MEDIA_PREVIOUS)} + { context -> audioManagerPressKey(context, KeyEvent.KEYCODE_MEDIA_PREVIOUS) } ), EXPAND_NOTIFICATIONS_PANEL( "expand_notifications_panel", diff --git a/app/src/main/java/de/jrpie/android/launcher/apps/PrivateSpace.kt b/app/src/main/java/de/jrpie/android/launcher/apps/PrivateSpace.kt index 9b37d60..a1241af 100644 --- a/app/src/main/java/de/jrpie/android/launcher/apps/PrivateSpace.kt +++ b/app/src/main/java/de/jrpie/android/launcher/apps/PrivateSpace.kt @@ -95,6 +95,12 @@ fun lockPrivateSpace(context: Context, lock: Boolean) { if (!isPrivateSpaceSupported()) { return } + + // silently return when trying to unlock but hide when locked is set + if (!lock && hidePrivateSpaceWhenLocked(context)) { + return + } + val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager val privateSpaceUser = getPrivateSpaceUser(context) ?: return userManager.requestQuietModeEnabled(lock, privateSpaceUser) @@ -116,3 +122,11 @@ fun togglePrivateSpaceLock(context: Context) { } } +fun hidePrivateSpaceWhenLocked(context: Context): Boolean { + // TODO: perhaps this should be cached + + // https://cs.android.com/android/platform/superproject/main/+/main:packages/apps/Launcher3/src/com/android/launcher3/util/SettingsCache.java;l=61;drc=56bf7ad33bc9d5ed3c18e7abefeec5c177ec75d7 + val key = "hide_privatespace_entry_point" + return Settings.Secure.getInt(context.contentResolver, key, 0) == 1 +} + diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/list/ListActivity.kt b/app/src/main/java/de/jrpie/android/launcher/ui/list/ListActivity.kt index 334bd62..95ed56e 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/list/ListActivity.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/list/ListActivity.kt @@ -22,6 +22,7 @@ import de.jrpie.android.launcher.R import de.jrpie.android.launcher.REQUEST_UNINSTALL import de.jrpie.android.launcher.actions.LauncherAction import de.jrpie.android.launcher.apps.AppFilter +import de.jrpie.android.launcher.apps.hidePrivateSpaceWhenLocked import de.jrpie.android.launcher.apps.isPrivateSpaceLocked import de.jrpie.android.launcher.apps.isPrivateSpaceSetUp import de.jrpie.android.launcher.apps.togglePrivateSpaceLock @@ -34,10 +35,12 @@ import de.jrpie.android.launcher.ui.list.other.ListFragmentOther // TODO: Better solution for this intercommunication functionality (used in list-fragments) var intention = ListActivity.ListActivityIntention.VIEW -var favoritesVisibility: AppFilter.Companion.AppSetVisibility = AppFilter.Companion.AppSetVisibility.VISIBLE +var favoritesVisibility: AppFilter.Companion.AppSetVisibility = + AppFilter.Companion.AppSetVisibility.VISIBLE var privateSpaceVisibility: AppFilter.Companion.AppSetVisibility = AppFilter.Companion.AppSetVisibility.VISIBLE -var hiddenVisibility: AppFilter.Companion.AppSetVisibility = AppFilter.Companion.AppSetVisibility.HIDDEN +var hiddenVisibility: AppFilter.Companion.AppSetVisibility = + AppFilter.Companion.AppSetVisibility.HIDDEN var forGesture: String? = null /** @@ -52,6 +55,23 @@ class ListActivity : AppCompatActivity(), UIObject { private fun updateLockIcon(locked: Boolean) { + if ( + // only show lock for VIEW intention + (intention != ListActivityIntention.VIEW) + // hide lock when private space does not exist + || !isPrivateSpaceSetUp(this) + // hide lock when private space apps are hidden from the main list and we are not in the private space list + || (LauncherPreferences.apps().hidePrivateSpaceApps() + && privateSpaceVisibility != AppFilter.Companion.AppSetVisibility.EXCLUSIVE) + // hide lock when private space is locked and the hidden when locked setting is set + || (locked && hidePrivateSpaceWhenLocked(this)) + ) { + binding.listLock.visibility = View.GONE + return + } + + binding.listLock.visibility = View.VISIBLE + binding.listLock.setImageDrawable( AppCompatResources.getDrawable( this, @@ -74,7 +94,6 @@ class ListActivity : AppCompatActivity(), UIObject { } - enum class ListActivityIntention(val titleResource: Int) { VIEW(R.string.list_title_view), /* view list of apps */ PICK(R.string.list_title_pick) /* choose app or action to associate to a gesture */ @@ -119,20 +138,6 @@ class ListActivity : AppCompatActivity(), UIObject { LauncherAction.SETTINGS.launch(this@ListActivity) } - binding.listLock.visibility = - if (intention != ListActivityIntention.VIEW) { - View.GONE - } else if (!isPrivateSpaceSetUp(this)) { - View.GONE - } else if (LauncherPreferences.apps().hidePrivateSpaceApps()) { - if (privateSpaceVisibility == AppFilter.Companion.AppSetVisibility.EXCLUSIVE) { - View.VISIBLE - } else { - View.GONE - } - } else { - View.VISIBLE - } if (privateSpaceVisibility == AppFilter.Companion.AppSetVisibility.EXCLUSIVE) { isPrivateSpaceSetUp(this, showToast = true, launchSettings = true) @@ -200,15 +205,16 @@ class ListActivity : AppCompatActivity(), UIObject { fun updateTitle() { var titleResource = intention.titleResource if (intention == ListActivityIntention.VIEW) { - titleResource = if (hiddenVisibility == AppFilter.Companion.AppSetVisibility.EXCLUSIVE) { - R.string.list_title_hidden - } else if (privateSpaceVisibility == AppFilter.Companion.AppSetVisibility.EXCLUSIVE) { - R.string.list_title_private_space - } else if (favoritesVisibility == AppFilter.Companion.AppSetVisibility.EXCLUSIVE) { - R.string.list_title_favorite - } else { - R.string.list_title_view - } + titleResource = + if (hiddenVisibility == AppFilter.Companion.AppSetVisibility.EXCLUSIVE) { + R.string.list_title_hidden + } else if (privateSpaceVisibility == AppFilter.Companion.AppSetVisibility.EXCLUSIVE) { + R.string.list_title_private_space + } else if (favoritesVisibility == AppFilter.Companion.AppSetVisibility.EXCLUSIVE) { + R.string.list_title_favorite + } else { + R.string.list_title_view + } } binding.listHeading.text = getString(titleResource) From e250a58ef4509c682376470b557bf5cf72713006 Mon Sep 17 00:00:00 2001 From: Josia Pietsch Date: Fri, 14 Mar 2025 13:37:41 +0100 Subject: [PATCH 09/20] add new action: adjust volume --- .../android/launcher/actions/LauncherAction.kt | 18 ++++++++++-------- .../res/drawable/baseline_volume_adjust_24.xml | 16 ++++++++++++++++ app/src/main/res/values-de/strings.xml | 5 +++-- app/src/main/res/values/strings.xml | 5 +++-- 4 files changed, 32 insertions(+), 12 deletions(-) create mode 100644 app/src/main/res/drawable/baseline_volume_adjust_24.xml diff --git a/app/src/main/java/de/jrpie/android/launcher/actions/LauncherAction.kt b/app/src/main/java/de/jrpie/android/launcher/actions/LauncherAction.kt index 3c89a67..5d2be94 100644 --- a/app/src/main/java/de/jrpie/android/launcher/actions/LauncherAction.kt +++ b/app/src/main/java/de/jrpie/android/launcher/actions/LauncherAction.kt @@ -88,13 +88,19 @@ enum class LauncherAction( "volume_up", R.string.list_other_volume_up, R.drawable.baseline_volume_up_24, - { context -> audioVolumeAdjust(context, true) } + { context -> audioVolumeAdjust(context, AudioManager.ADJUST_RAISE) } ), VOLUME_DOWN( "volume_down", R.string.list_other_volume_down, R.drawable.baseline_volume_down_24, - { context -> audioVolumeAdjust(context, false) } + { context -> audioVolumeAdjust(context, AudioManager.ADJUST_LOWER) } + ), + VOLUME_ADJUST( + "volume_adjust", + R.string.list_other_volume_adjust, + R.drawable.baseline_volume_adjust_24, + { context -> audioVolumeAdjust(context, AudioManager.ADJUST_SAME) } ), TRACK_PLAY_PAUSE( "play_pause_track", @@ -181,17 +187,13 @@ private fun audioManagerPressKey(context: Context, key: Int) { } -private fun audioVolumeAdjust(context: Context, louder: Boolean) { +private fun audioVolumeAdjust(context: Context, direction: Int) { val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager audioManager.adjustStreamVolume( AudioManager.STREAM_MUSIC, - if (louder) { - AudioManager.ADJUST_RAISE - } else { - AudioManager.ADJUST_LOWER - }, + direction, AudioManager.FLAG_SHOW_UI ) } diff --git a/app/src/main/res/drawable/baseline_volume_adjust_24.xml b/app/src/main/res/drawable/baseline_volume_adjust_24.xml new file mode 100644 index 0000000..38e6a8b --- /dev/null +++ b/app/src/main/res/drawable/baseline_volume_adjust_24.xml @@ -0,0 +1,16 @@ + + + + + + diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 17b840f..cf7f681 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -152,8 +152,9 @@ Alle Anwendungen Favoriten Privaten Bereich (ent)sperren - Musik: Lauter - Musik: Leiser + Lauter + Leiser + Lautstärke ändern Musik: Weiter Musik: Zurück Nichts tun diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3177442..1a79b5f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -250,8 +250,9 @@ Favorite Applications Private Space Toggle Private Space Lock - Music: Louder - Music: Quieter + Raise Volume + Lower Volume + Adjust Volume Music: Next Music: Previous Music: Play / Pause From 077ee4381a7783ff1d044b9cb6cce437eae2f942 Mon Sep 17 00:00:00 2001 From: Josia Pietsch Date: Fri, 14 Mar 2025 15:27:26 +0100 Subject: [PATCH 10/20] lint --- .../de/jrpie/android/launcher/Application.kt | 11 +++--- .../de/jrpie/android/launcher/Functions.kt | 4 +-- .../LauncherPreferences$Config.java | 2 ++ .../launcher/preferences/legacy/Version1.kt | 2 +- .../launcher/preferences/legacy/Version3.kt | 16 ++++----- .../jrpie/android/launcher/ui/HomeActivity.kt | 15 ++++---- .../launcher/ui/TouchGestureDetector.kt | 34 +++++++++++++++---- .../ui/list/apps/AppsRecyclerAdapter.kt | 2 +- .../ui/list/apps/ContextMenuActions.kt | 3 +- .../ui/list/other/OtherRecyclerAdapter.kt | 2 +- .../ui/settings/meta/SettingsFragmentMeta.kt | 3 +- .../launcher/ui/tutorial/TutorialActivity.kt | 17 +++++++++- 12 files changed, 75 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/de/jrpie/android/launcher/Application.kt b/app/src/main/java/de/jrpie/android/launcher/Application.kt index 09229ab..e674e4e 100644 --- a/app/src/main/java/de/jrpie/android/launcher/Application.kt +++ b/app/src/main/java/de/jrpie/android/launcher/Application.kt @@ -10,6 +10,8 @@ import android.content.pm.ShortcutInfo import android.os.AsyncTask import android.os.Build import android.os.Build.VERSION_CODES +import android.os.Handler +import android.os.Looper import android.os.UserHandle import androidx.core.content.ContextCompat import androidx.lifecycle.MutableLiveData @@ -108,12 +110,10 @@ class Application : android.app.Application() { // Try to restore old preferences migratePreferencesToNewVersion(this) - // First time opening the app: set defaults and start tutorial + // First time opening the app: set defaults + // The tutorial is started from HomeActivity#onStart, as starting it here is blocked by android if (!LauncherPreferences.internal().started()) { resetPreferences(this) - - LauncherPreferences.internal().started(true) - openTutorial(this) } @@ -134,7 +134,8 @@ class Application : android.app.Application() { it.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE) } } - ContextCompat.registerReceiver(this, profileAvailabilityBroadcastReceiver, filter, + ContextCompat.registerReceiver( + this, profileAvailabilityBroadcastReceiver, filter, ContextCompat.RECEIVER_EXPORTED ) } diff --git a/app/src/main/java/de/jrpie/android/launcher/Functions.kt b/app/src/main/java/de/jrpie/android/launcher/Functions.kt index 7c2abbf..57f13a5 100644 --- a/app/src/main/java/de/jrpie/android/launcher/Functions.kt +++ b/app/src/main/java/de/jrpie/android/launcher/Functions.kt @@ -135,9 +135,7 @@ fun openInBrowser(url: String, context: Context) { } fun openTutorial(context: Context) { - context.startActivity(Intent(context, TutorialActivity::class.java).apply { - addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - }) + context.startActivity(Intent(context, TutorialActivity::class.java)) } diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/LauncherPreferences$Config.java b/app/src/main/java/de/jrpie/android/launcher/preferences/LauncherPreferences$Config.java index ca60591..85979fe 100644 --- a/app/src/main/java/de/jrpie/android/launcher/preferences/LauncherPreferences$Config.java +++ b/app/src/main/java/de/jrpie/android/launcher/preferences/LauncherPreferences$Config.java @@ -21,8 +21,10 @@ import eu.jonahbauer.android.preference.annotations.Preferences; r = R.class, value = { @PreferenceGroup(name = "internal", prefix = "settings_internal_", suffix = "_key", value = { + // set after the user finished the tutorial @Preference(name = "started", type = boolean.class, defaultValue = "false"), @Preference(name = "started_time", type = long.class), + // see PREFERENCE_VERSION in de.jrpie.android.launcher.preferences.Preferences.kt @Preference(name = "version_code", type = int.class, defaultValue = "-1"), }), @PreferenceGroup(name = "apps", prefix = "settings_apps_", suffix = "_key", value = { diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version1.kt b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version1.kt index 6408b70..6252811 100644 --- a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version1.kt +++ b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version1.kt @@ -100,7 +100,7 @@ private fun migrateAppInfoStringMap(key: String) { } }?.toMap(HashMap()) )?.let { - preferences.edit().putStringSet(key, it as Set).apply() + preferences.edit().putStringSet(key, it).apply() } } diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version3.kt b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version3.kt index 7698e62..4a9241f 100644 --- a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version3.kt +++ b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version3.kt @@ -11,6 +11,7 @@ import de.jrpie.android.launcher.preferences.serialization.SetAbstractAppInfoPre import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json import java.util.HashSet +import androidx.core.content.edit /** * Migrate preferences from version 3 (used until version 0.0.23) to the current format @@ -42,6 +43,7 @@ private fun migrateSetAppInfo(key: String, preferences: SharedPreferences, edito deserializeSet(preferences.getStringSet(key, null))?.let { set.addAll(it) } + @Suppress("UNCHECKED_CAST") editor.putStringSet( key, serializer.serialize(set as java.util.Set) as Set? @@ -60,6 +62,7 @@ private fun migrateMapAppInfoString(key: String, preferences: SharedPreferences, deserializeMap(preferences.getStringSet(key, null))?.let { map.putAll(it) } + @Suppress("UNCHECKED_CAST") editor.putStringSet(key, serializer.serialize(map) as Set?) } catch (e: Exception) { e.printStackTrace() @@ -72,14 +75,11 @@ fun migratePreferencesFromVersion3() { assert(LauncherPreferences.internal().versionCode() == 3) val preferences = LauncherPreferences.getSharedPreferences() - val editor = preferences.edit() - migrateSetAppInfo(LauncherPreferences.apps().keys().favorites(), preferences, editor) - migrateSetAppInfo(LauncherPreferences.apps().keys().hidden(), preferences, editor) - migrateMapAppInfoString(LauncherPreferences.apps().keys().customNames(), preferences, editor) - - editor.apply() - - + preferences.edit { + migrateSetAppInfo(LauncherPreferences.apps().keys().favorites(), preferences, this) + migrateSetAppInfo(LauncherPreferences.apps().keys().hidden(), preferences, this) + migrateMapAppInfoString(LauncherPreferences.apps().keys().customNames(), preferences, this) + } LauncherPreferences.internal().versionCode(4) } \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/HomeActivity.kt b/app/src/main/java/de/jrpie/android/launcher/ui/HomeActivity.kt index 61a4250..7875473 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/HomeActivity.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/HomeActivity.kt @@ -9,9 +9,6 @@ import android.util.DisplayMetrics import android.view.KeyEvent import android.view.MotionEvent import android.view.View -import android.view.Window -import android.view.WindowInsets -import android.view.WindowInsetsController import android.window.OnBackInvokedDispatcher import androidx.appcompat.app.AppCompatActivity import androidx.core.view.isVisible @@ -20,6 +17,7 @@ import de.jrpie.android.launcher.actions.Action import de.jrpie.android.launcher.actions.Gesture import de.jrpie.android.launcher.actions.LauncherAction import de.jrpie.android.launcher.databinding.HomeBinding +import de.jrpie.android.launcher.openTutorial import de.jrpie.android.launcher.preferences.LauncherPreferences import de.jrpie.android.launcher.ui.tutorial.TutorialActivity import java.util.Locale @@ -58,7 +56,6 @@ class HomeActivity : UIObject, AppCompatActivity() { super.onCreate(savedInstanceState) super.onCreate() - val displayMetrics = DisplayMetrics() windowManager.defaultDisplay.getMetrics(displayMetrics) @@ -88,8 +85,6 @@ class HomeActivity : UIObject, AppCompatActivity() { binding.buttonFallbackSettings.setOnClickListener { LauncherAction.SETTINGS.invoke(this) } - - } override fun onStart() { @@ -97,6 +92,11 @@ class HomeActivity : UIObject, AppCompatActivity() { super.onStart() + // If the tutorial was not finished, start it + if (!LauncherPreferences.internal().started()) { + openTutorial(this) + } + LauncherPreferences.getSharedPreferences() .registerOnSharedPreferenceChangeListener(sharedPreferencesListener) @@ -220,7 +220,8 @@ class HomeActivity : UIObject, AppCompatActivity() { } override fun onTouchEvent(event: MotionEvent): Boolean { - return touchGestureDetector.onTouchEvent(event) || super.onTouchEvent(event) + touchGestureDetector.onTouchEvent(event) + return true } override fun setOnClicks() { diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/TouchGestureDetector.kt b/app/src/main/java/de/jrpie/android/launcher/ui/TouchGestureDetector.kt index 00629a5..1c05d54 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/TouchGestureDetector.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/TouchGestureDetector.kt @@ -1,6 +1,8 @@ package de.jrpie.android.launcher.ui import android.content.Context +import android.os.Handler +import android.os.Looper import android.view.MotionEvent import android.view.ViewConfiguration import de.jrpie.android.launcher.actions.Gesture @@ -27,6 +29,8 @@ class TouchGestureDetector( private val MIN_TRIANGLE_HEIGHT = 250 + private val longPressHandler = Handler(Looper.getMainLooper()) + data class Vector(val x: Float, val y: Float) { fun absSquared(): Float { @@ -83,16 +87,28 @@ class TouchGestureDetector( } private var paths = HashMap() + private var gestureIsLongClick = false private var lastTappedTime = 0L private var lastTappedLocation: Vector? = null - fun onTouchEvent(event: MotionEvent): Boolean { + fun onTouchEvent(event: MotionEvent) { val pointerIdToIndex = (0.. LONG_PRESS_TIMEOUT) { - // TODO: Don't wait until the finger is lifted. - // Instead set a timer to start long click as soon as LONG_PRESS_TIMEOUT is reached - Gesture.LONG_CLICK.invoke(context) } } else { // detect swipes diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/AppsRecyclerAdapter.kt b/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/AppsRecyclerAdapter.kt index 0c0407e..1f275e4 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/AppsRecyclerAdapter.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/AppsRecyclerAdapter.kt @@ -67,7 +67,7 @@ class AppsRecyclerAdapter( override fun onClick(v: View) { val rect = Rect() img.getGlobalVisibleRect(rect) - selectItem(adapterPosition, rect) + selectItem(bindingAdapterPosition, rect) } init { diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ContextMenuActions.kt b/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ContextMenuActions.kt index c1f3406..8b681b9 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ContextMenuActions.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ContextMenuActions.kt @@ -22,6 +22,7 @@ import de.jrpie.android.launcher.apps.DetailedAppInfo import de.jrpie.android.launcher.apps.PinnedShortcutInfo import de.jrpie.android.launcher.getUserFromId import de.jrpie.android.launcher.preferences.LauncherPreferences +import androidx.core.net.toUri private const val LOG_TAG = "AppContextMenu" @@ -44,7 +45,7 @@ fun AbstractAppInfo.uninstall(activity: Activity) { Log.i(LOG_TAG, "uninstalling $this") val intent = Intent(Intent.ACTION_UNINSTALL_PACKAGE) - intent.data = Uri.parse("package:$packageName") + intent.data = "package:$packageName".toUri() getUserFromId(userId, activity).let { user -> intent.putExtra(Intent.EXTRA_USER, user) } diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/list/other/OtherRecyclerAdapter.kt b/app/src/main/java/de/jrpie/android/launcher/ui/list/other/OtherRecyclerAdapter.kt index 97d1c84..dfba334 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/list/other/OtherRecyclerAdapter.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/list/other/OtherRecyclerAdapter.kt @@ -33,7 +33,7 @@ class OtherRecyclerAdapter(val activity: Activity) : override fun onClick(v: View) { - val pos = adapterPosition + val pos = bindingAdapterPosition val content = othersList[pos] forGesture?.let { returnChoiceIntent(it, content) } diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/settings/meta/SettingsFragmentMeta.kt b/app/src/main/java/de/jrpie/android/launcher/ui/settings/meta/SettingsFragmentMeta.kt index 70a225d..4cce930 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/settings/meta/SettingsFragmentMeta.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/settings/meta/SettingsFragmentMeta.kt @@ -16,6 +16,7 @@ import de.jrpie.android.launcher.copyToClipboard import de.jrpie.android.launcher.databinding.SettingsMetaBinding import de.jrpie.android.launcher.getDeviceInfo import de.jrpie.android.launcher.openInBrowser +import de.jrpie.android.launcher.openTutorial import de.jrpie.android.launcher.preferences.resetPreferences import de.jrpie.android.launcher.ui.LegalInfoActivity import de.jrpie.android.launcher.ui.UIObject @@ -48,7 +49,7 @@ class SettingsFragmentMeta : Fragment(), UIObject { override fun setOnClicks() { binding.settingsMetaButtonViewTutorial.setOnClickListener { - startActivity(Intent(this.context, TutorialActivity::class.java)) + openTutorial(requireContext()) } // prompting for settings-reset confirmation diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/TutorialActivity.kt b/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/TutorialActivity.kt index 28e2e02..fd60d19 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/TutorialActivity.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/TutorialActivity.kt @@ -2,7 +2,9 @@ package de.jrpie.android.launcher.ui.tutorial import android.content.Intent import android.content.res.Resources +import android.os.Build import android.os.Bundle +import android.window.OnBackInvokedDispatcher import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager @@ -33,6 +35,19 @@ class TutorialActivity : AppCompatActivity(), UIObject { super.onCreate(savedInstanceState) super.onCreate() + // Handle back key / gesture on Android 13+ + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + onBackInvokedDispatcher.registerOnBackInvokedCallback( + OnBackInvokedDispatcher.PRIORITY_OVERLAY + ) { + // prevent going back when the tutorial is shown for the first time + if (!LauncherPreferences.internal().started()) { + return@registerOnBackInvokedCallback + } + finish() + } + } + // Initialise layout setContentView(R.layout.tutorial) @@ -60,7 +75,7 @@ class TutorialActivity : AppCompatActivity(), UIObject { } } - // Default: prevent going back, allow if viewed again later + // prevent going back when the tutorial is shown for the first time override fun onBackPressed() { if (LauncherPreferences.internal().started()) super.onBackPressed() From 55af3927063b31ba75d5e03a2794f7284175fcba Mon Sep 17 00:00:00 2001 From: Josia Pietsch Date: Fri, 14 Mar 2025 15:40:06 +0100 Subject: [PATCH 11/20] add donate button --- .../ui/settings/meta/SettingsFragmentMeta.kt | 48 +++++++------------ app/src/main/res/layout/settings_meta.xml | 11 ++++- app/src/main/res/values-de/strings.xml | 1 + app/src/main/res/values/donottranslate.xml | 1 + app/src/main/res/values/strings.xml | 1 + 5 files changed, 29 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/settings/meta/SettingsFragmentMeta.kt b/app/src/main/java/de/jrpie/android/launcher/ui/settings/meta/SettingsFragmentMeta.kt index 4cce930..26f276a 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/settings/meta/SettingsFragmentMeta.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/settings/meta/SettingsFragmentMeta.kt @@ -48,6 +48,15 @@ class SettingsFragmentMeta : Fragment(), UIObject { override fun setOnClicks() { + fun bindURL(view: View, urlRes: Int) { + view.setOnClickListener { + openInBrowser( + getString(urlRes), + requireContext() + ) + } + } + binding.settingsMetaButtonViewTutorial.setOnClickListener { openTutorial(requireContext()) } @@ -70,12 +79,7 @@ class SettingsFragmentMeta : Fragment(), UIObject { // view code - binding.settingsMetaButtonViewCode.setOnClickListener { - openInBrowser( - getString(R.string.settings_meta_link_github), - requireContext() - ) - } + bindURL(binding.settingsMetaButtonViewCode, R.string.settings_meta_link_github) // report a bug binding.settingsMetaButtonReportBug.setOnClickListener { @@ -111,37 +115,19 @@ class SettingsFragmentMeta : Fragment(), UIObject { } // join chat - binding.settingsMetaButtonJoinChat.setOnClickListener { - openInBrowser( - getString(R.string.settings_meta_chat_url), - requireContext() - ) - } - + bindURL(binding.settingsMetaButtonJoinChat, R.string.settings_meta_chat_url) // contact developer - binding.settingsMetaButtonContact.setOnClickListener { - openInBrowser( - getString(R.string.settings_meta_contact_url), - requireContext() - ) - } + // bindURL(binding.settingsMetaButtonContact, R.string.settings_meta_contact_url) // contact fork developer - binding.settingsMetaButtonForkContact.setOnClickListener { - openInBrowser( - getString(R.string.settings_meta_fork_contact_url), - requireContext() - ) - } + bindURL(binding.settingsMetaButtonForkContact, R.string.settings_meta_fork_contact_url) + + // donate + bindURL(binding.settingsMetaButtonDonate, R.string.settings_meta_donate_url) // privacy policy - binding.settingsMetaButtonPrivacy.setOnClickListener { - openInBrowser( - getString(R.string.settings_meta_privacy_url), - requireContext() - ) - } + bindURL(binding.settingsMetaButtonPrivacy, R.string.settings_meta_privacy_url) // legal info binding.settingsMetaButtonLicenses.setOnClickListener { diff --git a/app/src/main/res/layout/settings_meta.xml b/app/src/main/res/layout/settings_meta.xml index a5876e6..6f21baa 100644 --- a/app/src/main/res/layout/settings_meta.xml +++ b/app/src/main/res/layout/settings_meta.xml @@ -59,12 +59,12 @@ android:text="@string/settings_meta_join_chat" android:textAllCaps="false" /> -