diff --git a/BUILD.md b/BUILD.md
index 5f62a30..ac1f11d 100644
--- a/BUILD.md
+++ b/BUILD.md
@@ -11,6 +11,8 @@ cd Launcher
./gradlew build
```
+Note that you need to sign the apk.
+
See [this guide](https://developer.android.com/build/building-cmdline)
for further instructions.
diff --git a/README.md b/README.md
index 3379726..81efe24 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,13 @@
[![][shield-release]][latest-release]
+[](https://github.com/jrpie/Launcher/actions/workflows/android.yml)
[![][shield-license]][license]
[][matrix]
[][discord]
+
# μLauncher
@@ -16,9 +18,9 @@ Your home screen only displays the date, time and a wallpaper.
Pressing back or swiping up (this can be configures) opens a list
of all installed apps, which can be searched efficiently.
-
This is a fork of [finnmglas's app Launcher][original-repo].
+
[
](https://f-droid.org/packages/de.jrpie.android.launcher/)
@@ -28,6 +30,23 @@ This is a fork of [finnmglas's app Launcher][original-repo].
Or download the latest APK from the [Releases Section](https://github.com/jrpie/Launcher/releases/latest).
+
+
+
+
+
+
+
## Contributing
There are several ways to contribute to this app:
@@ -39,6 +58,7 @@ There are several ways to contribute to this app:
- Open a new pull request.
+See [BUILD.md](BUILD.md) for instructions how to build this project.
## Notable changes compared to [Finn's Launcher][original-repo]:
diff --git a/app/src/main/java/de/jrpie/android/launcher/actions/Action.kt b/app/src/main/java/de/jrpie/android/launcher/actions/Action.kt
index 1eab2ee..0912207 100644
--- a/app/src/main/java/de/jrpie/android/launcher/actions/Action.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/actions/Action.kt
@@ -10,6 +10,7 @@ import android.widget.Toast
import de.jrpie.android.launcher.R
import de.jrpie.android.launcher.apps.AppInfo
import de.jrpie.android.launcher.apps.AppInfo.Companion.INVALID_USER
+import de.jrpie.android.launcher.apps.DetailedAppInfo
import de.jrpie.android.launcher.preferences.LauncherPreferences
interface Action {
@@ -22,7 +23,18 @@ interface Action {
fun writeToIntent(intent: Intent)
companion object {
- private fun fromId(id: String, user: Int?): Action? {
+ /**
+ * Get an action for a specific id.
+ * An id is of the form:
+ * - "launcher:${launcher_action_name}", see [LauncherAction]
+ * - "${package_name}", see [AppAction]
+ * - "${package_name}:${activity_name}", see [AppAction]
+ *
+ * @param id
+ * @param user a user id, ignored if the action is a [LauncherAction].
+ * @param context used to complete [AppInfo] if possible
+ */
+ private fun fromId(id: String, user: Int?, context: Context? = null): Action? {
if (id.isEmpty()) {
return null
}
@@ -32,7 +44,14 @@ interface Action {
val values = id.split(";")
- return AppAction(AppInfo(values[0], values.getOrNull(1), user ?: INVALID_USER))
+ var info = AppInfo(values[0], values.getOrNull(1), user ?: INVALID_USER)
+
+ // try to complete an incomplete AppInfo if a context is provided
+ if (context != null && (info.user == INVALID_USER || info.activityName == null)) {
+ info = DetailedAppInfo.fromAppInfo(info, context)?.app?:info
+ }
+
+ return AppAction(info)
}
fun forGesture(gesture: Gesture): Action? {
@@ -48,12 +67,17 @@ interface Action {
fun resetToDefaultActions(context: Context) {
val editor = LauncherPreferences.getSharedPreferences().edit()
+ val boundActions = HashSet()
Gesture.entries.forEach { gesture ->
context.resources
.getStringArray(gesture.defaultsResource)
- .map { fromId(it, null) }
- .firstOrNull { it?.isAvailable(context) ?: false }
- ?.bindToGesture(editor, gesture.id)
+ .filterNot { boundActions.contains(it) }
+ .map { Pair(it, fromId(it, null, context)) }
+ .firstOrNull { it.second?.isAvailable(context) ?: false }
+ ?.apply {
+ boundActions.add(first)
+ second?.bindToGesture(editor, gesture.id)
+ }
}
editor.apply()
}
diff --git a/app/src/main/java/de/jrpie/android/launcher/actions/AppAction.kt b/app/src/main/java/de/jrpie/android/launcher/actions/AppAction.kt
index 29fb4b7..c8a75cf 100644
--- a/app/src/main/java/de/jrpie/android/launcher/actions/AppAction.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/actions/AppAction.kt
@@ -16,7 +16,7 @@ import de.jrpie.android.launcher.apps.DetailedAppInfo
import de.jrpie.android.launcher.getIntent
import de.jrpie.android.launcher.openAppSettings
-class AppAction(private var appInfo: AppInfo) : Action {
+class AppAction(val appInfo: AppInfo) : Action {
override fun invoke(context: Context, rect: Rect?): Boolean {
val packageName = appInfo.packageName.toString()
diff --git a/app/src/main/java/de/jrpie/android/launcher/actions/Gesture.kt b/app/src/main/java/de/jrpie/android/launcher/actions/Gesture.kt
index 6270eba..e7358ba 100644
--- a/app/src/main/java/de/jrpie/android/launcher/actions/Gesture.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/actions/Gesture.kt
@@ -2,6 +2,7 @@ package de.jrpie.android.launcher.actions
import android.content.Context
import de.jrpie.android.launcher.R
+import de.jrpie.android.launcher.preferences.LauncherPreferences
/**
* @param id internal id to serialize the action. Used as a key in shared preferences.
@@ -32,14 +33,18 @@ enum class Gesture(
R.string.settings_gesture_description_vol_down,
R.array.default_volume_down, 0, 0
),
- TIME("action.time",
+ TIME(
+ "action.time",
R.string.settings_gesture_time,
R.string.settings_gesture_description_time,
- R.array.default_time),
- DATE("action.date",
+ R.array.default_time
+ ),
+ DATE(
+ "action.date",
R.string.settings_gesture_date,
R.string.settings_gesture_description_date,
- R.array.default_date),
+ R.array.default_date
+ ),
LONG_CLICK(
"action.long_click",
R.string.settings_gesture_long_click,
@@ -52,11 +57,13 @@ enum class Gesture(
R.string.settings_gesture_description_double_click,
R.array.default_double_click, 0, 0
),
- SWIPE_UP("action.up",
+ SWIPE_UP(
+ "action.up",
R.string.settings_gesture_up,
R.string.settings_gesture_description_up,
R.array.default_up,
- R.anim.bottom_up),
+ R.anim.bottom_up
+ ),
SWIPE_UP_LEFT_EDGE(
"action.up_left",
R.string.settings_gesture_up_left_edge,
@@ -110,28 +117,28 @@ enum class Gesture(
"action.left",
R.string.settings_gesture_left,
R.string.settings_gesture_description_left,
- R.array.default_left,
+ R.array.default_messengers,
R.anim.right_left
),
SWIPE_LEFT_TOP_EDGE(
"action.left_top",
R.string.settings_gesture_left_top_edge,
R.string.settings_gesture_description_left_top_edge,
- R.array.default_left_top,
+ R.array.default_messengers,
R.anim.right_left
),
SWIPE_LEFT_BOTTOM_EDGE(
"action.left_bottom",
R.string.settings_gesture_left_bottom_edge,
R.string.settings_gesture_description_left_bottom_edge,
- R.array.default_left_bottom,
+ R.array.default_messengers,
R.anim.right_left
),
SWIPE_LEFT_DOUBLE(
"action.double_left",
R.string.settings_gesture_double_left,
R.string.settings_gesture_description_double_left,
- R.array.default_double_left,
+ R.array.default_messengers,
R.anim.right_left
),
SWIPE_RIGHT(
@@ -170,6 +177,7 @@ enum class Gesture(
fun getLabel(context: Context): String {
return context.resources.getString(this.labelResource)
}
+
fun getDescription(context: Context): String {
return context.resources.getString(this.descriptionResource)
}
@@ -242,6 +250,16 @@ enum class Gesture(
}
}
+ fun isEnabled(): Boolean {
+ if (isEdgeVariant()) {
+ return LauncherPreferences.enabled_gestures().edgeSwipe()
+ }
+ if (isDoubleVariant()) {
+ return LauncherPreferences.enabled_gestures().doubleSwipe()
+ }
+ return true
+ }
+
operator fun invoke(context: Context) {
val action = Action.forGesture(this)
Action.launch(action, context, this.animationIn, this.animationOut)
diff --git a/app/src/main/java/de/jrpie/android/launcher/apps/AppFilter.kt b/app/src/main/java/de/jrpie/android/launcher/apps/AppFilter.kt
index 004c992..b51adf2 100644
--- a/app/src/main/java/de/jrpie/android/launcher/apps/AppFilter.kt
+++ b/app/src/main/java/de/jrpie/android/launcher/apps/AppFilter.kt
@@ -1,5 +1,8 @@
package de.jrpie.android.launcher.apps
+import de.jrpie.android.launcher.actions.Action
+import de.jrpie.android.launcher.actions.AppAction
+import de.jrpie.android.launcher.actions.Gesture
import de.jrpie.android.launcher.preferences.LauncherPreferences
import java.util.Locale
import kotlin.text.Regex.Companion.escapeReplacement
@@ -14,20 +17,29 @@ class AppFilter(
val hidden = LauncherPreferences.apps().hidden() ?: setOf()
val favorites = LauncherPreferences.apps().favorites() ?: setOf()
+
apps = apps.filter { info ->
favoritesVisibility.predicate(favorites, info)
&& hiddenVisibility.predicate(hidden, info)
}
+ if (LauncherPreferences.apps().hideBoundApps()) {
+ val boundApps = Gesture.entries
+ .filter(Gesture::isEnabled)
+ .mapNotNull { g -> (Action.forGesture(g) as? AppAction)?.appInfo }
+ .toSet()
+ apps = apps.filterNot { info -> boundApps.contains(info.app) }
+ }
+
// normalize text for search
- var allowedSpecialCharacters = search
+ val allowedSpecialCharacters = search
.lowercase(Locale.ROOT)
.toCharArray()
.distinct()
.filter { c -> !c.isLetter() }
.map { c -> escapeReplacement(c.toString()) }
.fold("") { x, y -> x + y }
- var disallowedCharsRegex = "[^\\p{L}$allowedSpecialCharacters]".toRegex()
+ val disallowedCharsRegex = "[^\\p{L}$allowedSpecialCharacters]".toRegex()
fun normalize(text: String): String {
return text.lowercase(Locale.ROOT).replace(disallowedCharsRegex, "")
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 c876fc3..b98a157 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
@@ -28,6 +28,7 @@ import eu.jonahbauer.android.preference.annotations.serializer.PreferenceSeriali
@PreferenceGroup(name = "apps", prefix = "settings_apps_", suffix = "_key", value = {
@Preference(name = "favorites", type = Set.class, serializer = LauncherPreferences$Config.AppInfoSetSerializer.class),
@Preference(name = "hidden", type = Set.class, serializer = LauncherPreferences$Config.AppInfoSetSerializer.class),
+ @Preference(name = "hide_bound_apps", type = boolean.class, defaultValue = "false"),
}),
@PreferenceGroup(name = "gestures", prefix = "settings_gesture_", suffix = "_key", value = {
}),
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 e8465e0..6a23caf 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
@@ -155,12 +155,7 @@ class ActionsRecyclerAdapter(val activity: Activity) :
}
init {
- val doubleActions = LauncherPreferences.enabled_gestures().doubleSwipe()
- val edgeActions = LauncherPreferences.enabled_gestures().edgeSwipe()
- gesturesList = Gesture.entries.filter {
- (doubleActions || !it.isDoubleVariant())
- && (edgeActions || !it.isEdgeVariant())
- } as ArrayList
+ gesturesList = Gesture.entries.filter(Gesture::isEnabled) as ArrayList
}
fun updateActions() {
diff --git a/app/src/main/res/values/defaults.xml b/app/src/main/res/values/defaults.xml
index 84e4781..e532965 100644
--- a/app/src/main/res/values/defaults.xml
+++ b/app/src/main/res/values/defaults.xml
@@ -61,6 +61,7 @@
+ - net.thunderbird.android
- com.fsck.k9
- de.web.mobile.android.mail
- com.samsung.android.email.provider
@@ -87,31 +88,22 @@
- info.tangential.cone
-
-
+
- de.spiritcroc.riotx
- io.element.android.x
- im.vector.app
- org.thoughtcrime.securesms
-
-
-
+ - org.briarproject.briar.android
+ - eu.siacs.conversations
+ - ch.threema.app.libre
- com.android.messaging
- - com.android.google.messaging
+ - com.google.android.apps.messaging
- com.samsung.android.messaging
-
-
- - org.thoughtcrime.securesms
-
-
-
-
-
- com.whatsapp
- org.telegram.messenger
+ - com.discord
-
- launcher:volumeUp
@@ -134,6 +126,8 @@
- com.beemdevelopment.aegis
- org.fedorahosted.freeotp
+ - proton.android.pass.fdroid
+ - com.kunzisoft.keepass.libre
- launcher:settings
diff --git a/app/src/main/res/values/donottranslate.xml b/app/src/main/res/values/donottranslate.xml
index d3cac4b..fc255ab 100644
--- a/app/src/main/res/values/donottranslate.xml
+++ b/app/src/main/res/values/donottranslate.xml
@@ -11,6 +11,7 @@
internal.version_code
apps.favorites
apps.hidden
+ apps.hide_bound_apps
general.select_launcher