mirror of
https://github.com/jrpie/Launcher.git
synced 2025-06-08 10:20:15 +02:00
Compare commits
No commits in common. "24e90deb627f76c2d528fbc12510ea4825dc9a98" and "a4fcdf60c7d3be3d37be15fb3fc8c9b286a7f953" have entirely different histories.
24e90deb62
...
a4fcdf60c7
15 changed files with 58 additions and 483 deletions
|
@ -1,25 +1,9 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# This script builds all variants of µLauncher to create a release, namely:
|
|
||||||
# - app-release.apk (GitHub release; used by F-Droid for reproducible builds)
|
|
||||||
# - launcher-accrescent.apks (Accrescent)
|
|
||||||
# - app-release.aab (Play Store)
|
|
||||||
|
|
||||||
# This is only intended to work on my (@jrpie) computer.
|
|
||||||
# To use this script for building a fork you need to:
|
|
||||||
# - install bundletool.jar and
|
|
||||||
# - create a keystore and modify the variables below accordingly
|
|
||||||
|
|
||||||
export JAVA_HOME="/usr/lib/jvm/java-21-openjdk/"
|
export JAVA_HOME="/usr/lib/jvm/java-21-openjdk/"
|
||||||
OUTPUT_DIR="$HOME/launcher-release"
|
OUTPUT_DIR="$HOME/launcher-release"
|
||||||
BUILD_TOOLS_DIR="$HOME/Android/Sdk/build-tools/35.0.0"
|
BUILD_TOOLS_DIR="$HOME/Android/Sdk/build-tools/35.0.0"
|
||||||
|
|
||||||
# keystore for the default release
|
|
||||||
KEYSTORE="$HOME/data/keys/launcher_jrpie.jks"
|
KEYSTORE="$HOME/data/keys/launcher_jrpie.jks"
|
||||||
# keystore for the default accrescent release
|
|
||||||
KEYSTORE_ACCRESCENT="$HOME/data/keys/launcher_jrpie_accrescent.jks"
|
KEYSTORE_ACCRESCENT="$HOME/data/keys/launcher_jrpie_accrescent.jks"
|
||||||
|
|
||||||
# keepassxc-password is a custom script to fetch passwords from my password manager
|
|
||||||
KEYSTORE_PASS=$(keepassxc-password "android_keys/launcher")
|
KEYSTORE_PASS=$(keepassxc-password "android_keys/launcher")
|
||||||
KEYSTORE_ACCRESCENT_PASS=$(keepassxc-password "android_keys/launcher-accrescent")
|
KEYSTORE_ACCRESCENT_PASS=$(keepassxc-password "android_keys/launcher-accrescent")
|
||||||
|
|
||||||
|
@ -27,11 +11,12 @@ if [[ $(git status --porcelain) ]]; then
|
||||||
echo "There are uncommitted changes."
|
echo "There are uncommitted changes."
|
||||||
|
|
||||||
read -p "Continue anyway? (y/n) " -n 1 -r
|
read -p "Continue anyway? (y/n) " -n 1 -r
|
||||||
echo
|
echo # (optional) move to a new line
|
||||||
if ! [[ $REPLY =~ ^[Yy]$ ]]
|
if ! [[ $REPLY =~ ^[Yy]$ ]]
|
||||||
then
|
then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -rf "$OUTPUT_DIR"
|
rm -rf "$OUTPUT_DIR"
|
||||||
|
|
|
@ -22,6 +22,8 @@ import de.jrpie.android.launcher.apps.isPrivateSpaceLocked
|
||||||
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
import de.jrpie.android.launcher.preferences.LauncherPreferences
|
||||||
import de.jrpie.android.launcher.preferences.migratePreferencesToNewVersion
|
import de.jrpie.android.launcher.preferences.migratePreferencesToNewVersion
|
||||||
import de.jrpie.android.launcher.preferences.resetPreferences
|
import de.jrpie.android.launcher.preferences.resetPreferences
|
||||||
|
import de.jrpie.android.launcher.widgets.LauncherWidgetProvider
|
||||||
|
import de.jrpie.android.launcher.widgets.Widget
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
@ -32,6 +34,7 @@ const val APP_WIDGET_HOST_ID = 42;
|
||||||
|
|
||||||
class Application : android.app.Application() {
|
class Application : android.app.Application() {
|
||||||
val apps = MutableLiveData<List<AbstractDetailedAppInfo>>()
|
val apps = MutableLiveData<List<AbstractDetailedAppInfo>>()
|
||||||
|
val widgets = MutableLiveData<Set<Widget>>()
|
||||||
val privateSpaceLocked = MutableLiveData<Boolean>()
|
val privateSpaceLocked = MutableLiveData<Boolean>()
|
||||||
lateinit var appWidgetHost: AppWidgetHost
|
lateinit var appWidgetHost: AppWidgetHost
|
||||||
lateinit var appWidgetManager: AppWidgetManager
|
lateinit var appWidgetManager: AppWidgetManager
|
||||||
|
@ -98,6 +101,8 @@ class Application : android.app.Application() {
|
||||||
customAppNames = LauncherPreferences.apps().customNames()
|
customAppNames = LauncherPreferences.apps().customNames()
|
||||||
} else if (pref == LauncherPreferences.apps().keys().pinnedShortcuts()) {
|
} else if (pref == LauncherPreferences.apps().keys().pinnedShortcuts()) {
|
||||||
loadApps()
|
loadApps()
|
||||||
|
} else if (pref == LauncherPreferences.widgets().keys().widgets()) {
|
||||||
|
widgets.postValue(LauncherPreferences.widgets().widgets() ?: setOf())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,7 @@ class ManageWidgetPanelsActivity : AppCompatActivity(), UIObject {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
binding.manageWidgetPanelsRecycler.apply {
|
binding.manageWidgetPanelsRecycler.apply {
|
||||||
|
// improve performance (since content changes don't change the layout size)
|
||||||
setHasFixedSize(true)
|
setHasFixedSize(true)
|
||||||
layoutManager = viewManager
|
layoutManager = viewManager
|
||||||
adapter = viewAdapter
|
adapter = viewAdapter
|
||||||
|
|
|
@ -34,11 +34,10 @@ class ManageWidgetsActivity : Activity(), UIObject {
|
||||||
|
|
||||||
var panelId: Int = WidgetPanel.HOME.id
|
var panelId: Int = WidgetPanel.HOME.id
|
||||||
|
|
||||||
|
|
||||||
// We can't observe the livedata because this is not an AppCompatActivity
|
|
||||||
private var sharedPreferencesListener =
|
private var sharedPreferencesListener =
|
||||||
SharedPreferences.OnSharedPreferenceChangeListener { _, prefKey ->
|
SharedPreferences.OnSharedPreferenceChangeListener { _, prefKey ->
|
||||||
if (prefKey == LauncherPreferences.widgets().keys().widgets()) {
|
if (prefKey == LauncherPreferences.widgets().keys().widgets()) {
|
||||||
|
// We can't observe the livedata because this is not an AppCompatActivity
|
||||||
findViewById<WidgetContainerView>(R.id.manage_widgets_container).updateWidgets(this,
|
findViewById<WidgetContainerView>(R.id.manage_widgets_container).updateWidgets(this,
|
||||||
LauncherPreferences.widgets().widgets()
|
LauncherPreferences.widgets().widgets()
|
||||||
)
|
)
|
||||||
|
@ -64,7 +63,7 @@ class ManageWidgetsActivity : Activity(), UIObject {
|
||||||
|
|
||||||
findViewById<WidgetContainerView>(R.id.manage_widgets_container).let {
|
findViewById<WidgetContainerView>(R.id.manage_widgets_container).let {
|
||||||
it.widgetPanelId = panelId
|
it.widgetPanelId = panelId
|
||||||
it.updateWidgets(this, LauncherPreferences.widgets().widgets())
|
it.updateWidgets(this, (application as Application).widgets.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@ import androidx.core.graphics.minus
|
||||||
import androidx.core.graphics.toRect
|
import androidx.core.graphics.toRect
|
||||||
import androidx.core.view.children
|
import androidx.core.view.children
|
||||||
import de.jrpie.android.launcher.ui.widgets.WidgetContainerView
|
import de.jrpie.android.launcher.ui.widgets.WidgetContainerView
|
||||||
import de.jrpie.android.launcher.widgets.GRID_SIZE
|
|
||||||
import de.jrpie.android.launcher.widgets.Widget
|
import de.jrpie.android.launcher.widgets.Widget
|
||||||
import de.jrpie.android.launcher.widgets.WidgetPanel
|
import de.jrpie.android.launcher.widgets.WidgetPanel
|
||||||
import de.jrpie.android.launcher.widgets.WidgetPosition
|
import de.jrpie.android.launcher.widgets.WidgetPosition
|
||||||
|
@ -48,27 +47,21 @@ class WidgetManagerView(widgetPanelId: Int, context: Context, attrs: AttributeSe
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
enum class EditMode(val resize: (dx: Int, dy: Int, screenWidth: Int, screenHeight: Int, rect: Rect) -> Rect) {
|
enum class EditMode(val resize: (dx: Int, dy: Int, rect: Rect) -> Rect) {
|
||||||
MOVE({ dx, dy, sw, sh, rect ->
|
MOVE({ dx, dy, rect ->
|
||||||
val cdx = dx.coerceIn(-rect.left, sw - rect.right)
|
Rect(rect.left + dx, rect.top + dy, rect.right + dx, rect.bottom + dy)
|
||||||
val cdy = dy.coerceIn(-rect.top, sh - rect.bottom)
|
|
||||||
Rect(rect.left + cdx, rect.top + cdy, rect.right + cdx, rect.bottom + cdy)
|
|
||||||
}),
|
}),
|
||||||
TOP({ dx, dy, sw, sh, rect ->
|
TOP({ dx, dy, rect ->
|
||||||
val cdy = dy.coerceIn(-rect.top, rect.bottom - rect.top - (2 * sh / GRID_SIZE) + 5)
|
Rect(rect.left, min(rect.top + dy, rect.bottom - 200), rect.right, rect.bottom)
|
||||||
Rect(rect.left, rect.top + cdy, rect.right, rect.bottom)
|
|
||||||
}),
|
}),
|
||||||
BOTTOM({ dx, dy, sw, sh, rect ->
|
BOTTOM({ dx, dy, rect ->
|
||||||
val cdy = dy.coerceIn((2 * sh / GRID_SIZE) + 5 + rect.top - rect.bottom, sh - rect.bottom)
|
Rect(rect.left, rect.top, rect.right, max(rect.top + 200, rect.bottom + dy))
|
||||||
Rect(rect.left, rect.top, rect.right, rect.bottom + cdy)
|
|
||||||
}),
|
}),
|
||||||
LEFT({ dx, dy, sw, sh, rect ->
|
LEFT({ dx, dy, rect ->
|
||||||
val cdx = dx.coerceIn(-rect.left, rect.right - rect.left - (2 * sw / GRID_SIZE) + 5)
|
Rect(min(rect.left + dx, rect.right - 200), rect.top, rect.right, rect.bottom)
|
||||||
Rect(rect.left + cdx, rect.top, rect.right, rect.bottom)
|
|
||||||
}),
|
}),
|
||||||
RIGHT({ dx, dy, sw, sh, rect ->
|
RIGHT({ dx, dy, rect ->
|
||||||
val cdx = dx.coerceIn((2 * sw / GRID_SIZE) + 5 + rect.left - rect.right, sw - rect.right)
|
Rect(rect.left, rect.top, max(rect.left + 200, rect.right + dx), rect.bottom)
|
||||||
Rect(rect.left, rect.top, rect.right + cdx, rect.bottom)
|
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +120,6 @@ class WidgetManagerView(widgetPanelId: Int, context: Context, attrs: AttributeSe
|
||||||
val absoluteNewPosition = view.mode?.resize(
|
val absoluteNewPosition = view.mode?.resize(
|
||||||
distanceX.toInt(),
|
distanceX.toInt(),
|
||||||
distanceY.toInt(),
|
distanceY.toInt(),
|
||||||
width, height,
|
|
||||||
start
|
start
|
||||||
) ?: return true
|
) ?: return true
|
||||||
val newPosition = WidgetPosition.fromAbsoluteRect(
|
val newPosition = WidgetPosition.fromAbsoluteRect(
|
||||||
|
@ -170,7 +162,7 @@ class WidgetManagerView(widgetPanelId: Int, context: Context, attrs: AttributeSe
|
||||||
if (widgets == null) {
|
if (widgets == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
children.filter { it is WidgetOverlayView }.forEach { removeView(it) }
|
children.mapNotNull { it as? WidgetOverlayView }.forEach { removeView(it) }
|
||||||
|
|
||||||
widgets.filter { it.panelId == widgetPanelId }.forEach { widget ->
|
widgets.filter { it.panelId == widgetPanelId }.forEach { widget ->
|
||||||
WidgetOverlayView(activity).let {
|
WidgetOverlayView(activity).let {
|
||||||
|
|
|
@ -57,8 +57,7 @@ sealed class Widget {
|
||||||
return Json.decodeFromString(serialized)
|
return Json.decodeFromString(serialized)
|
||||||
}
|
}
|
||||||
fun byId(context: Context, id: Int): Widget? {
|
fun byId(context: Context, id: Int): Widget? {
|
||||||
// TODO: do some caching
|
return (context.applicationContext as Application).widgets.value?.firstOrNull {
|
||||||
return LauncherPreferences.widgets().widgets().firstOrNull() {
|
|
||||||
it.id == id
|
it.id == id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,21 +24,6 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="10dp" />
|
android:layout_height="10dp" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/dialog_select_color_alpha" />
|
|
||||||
|
|
||||||
<SeekBar
|
|
||||||
android:id="@+id/dialog_select_color_seekbar_alpha"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:max="255" />
|
|
||||||
|
|
||||||
<Space
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="10dp" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
@ -80,4 +65,18 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:max="255" />
|
android:max="255" />
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="10dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/dialog_select_color_alpha" />
|
||||||
|
|
||||||
|
<SeekBar
|
||||||
|
android:id="@+id/dialog_select_color_seekbar_alpha"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:max="255" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
|
@ -159,9 +159,9 @@
|
||||||
|
|
||||||
<string name="settings_launcher_section_functionality">Functionality</string>
|
<string name="settings_launcher_section_functionality">Functionality</string>
|
||||||
|
|
||||||
<string name="settings_enabled_gestures_double_swipe">Double swipe gestures</string>
|
<string name="settings_enabled_gestures_double_swipe">Double swipe actions</string>
|
||||||
<string name="settings_enabled_gestures_double_swipe_summary">Swipe with two fingers</string>
|
<string name="settings_enabled_gestures_double_swipe_summary">Swipe with two fingers</string>
|
||||||
<string name="settings_enabled_gestures_edge_swipe">Edge swipe gestures</string>
|
<string name="settings_enabled_gestures_edge_swipe">Edge swipe actions</string>
|
||||||
<string name="settings_enabled_gestures_edge_swipe_summary">Swipe at the edge of the screen</string>
|
<string name="settings_enabled_gestures_edge_swipe_summary">Swipe at the edge of the screen</string>
|
||||||
<string name="settings_enabled_gestures_edge_swipe_edge_width">Edge width</string>
|
<string name="settings_enabled_gestures_edge_swipe_edge_width">Edge width</string>
|
||||||
<string name="settings_functionality_auto_launch">Launch search results</string>
|
<string name="settings_functionality_auto_launch">Launch search results</string>
|
||||||
|
|
|
@ -1,71 +0,0 @@
|
||||||
# Gestures and Actions
|
|
||||||
|
|
||||||
µLauncher's central mechanism for accessing important functionality quickly
|
|
||||||
is to bind actions (e.g. launching an app) to gestures (e.g. swiping up).
|
|
||||||
These bindings can be configured in µLauncher Settings > ACTIONS.
|
|
||||||
|
|
||||||
|
|
||||||
## Available Gestures
|
|
||||||
|
|
||||||
### Swipes
|
|
||||||
|
|
||||||
- Basic swipes: Swipe up, down, left, or right
|
|
||||||
- Double swipes: Swipe up, down, left, or right with two fingers
|
|
||||||
- Edge swipes:
|
|
||||||
- Swipe up or down on the left or right edge
|
|
||||||
- Swipe left or right on the top or bottom edge
|
|
||||||
|
|
||||||
The size of the edges is configurable in settings.
|
|
||||||
For a swipe to be detected as an edge swipe, the finger must not leave the respective edge region while swiping.
|
|
||||||
|
|
||||||
### Taps
|
|
||||||
|
|
||||||
- Tap on date or time
|
|
||||||
- Double tap
|
|
||||||
- Long click
|
|
||||||
|
|
||||||
### Tap-then-Swipes
|
|
||||||
|
|
||||||
- Tap then swipe up, down, left, or right
|
|
||||||
|
|
||||||
To execute these gesture consistently, it is helpful to think of them as double taps,
|
|
||||||
where the finger stays on the screen after the second tap and then does a swipe.
|
|
||||||
The swipe must start very shortly after the tap ended.
|
|
||||||
|
|
||||||
### Complex Gestures
|
|
||||||
|
|
||||||
- Draw <, >, V, or Λ
|
|
||||||
- Draw <, >, V, or Λ in reverse direction
|
|
||||||
|
|
||||||
### Hardware Buttons as Gestures
|
|
||||||
|
|
||||||
- Back button (or back gesture if gesture navigation is enabled)
|
|
||||||
- Volume buttons
|
|
||||||
|
|
||||||
***
|
|
||||||
|
|
||||||
## Available Actions
|
|
||||||
|
|
||||||
To any of the available gestures, one of the following actions can be bound:
|
|
||||||
|
|
||||||
- Launch an app (or a pinned shortcut)
|
|
||||||
- Open a widget panel.
|
|
||||||
Widget panels can hold widgets that are not needed on the home screen itself.
|
|
||||||
They can be created and managed in µLauncher Settings > Manage Widget Panels
|
|
||||||
- Open a list of all, favorite, or private apps (hidden apps are excluded).
|
|
||||||
Actions related to private space are only shown if private space is set up on the device.
|
|
||||||
µLauncher's settings can be accessed from those lists.
|
|
||||||
If private space is set up, an icon to (un)lock it is shown on the top right.
|
|
||||||
- Open µLauncher's settings
|
|
||||||
- Toggle private space lock
|
|
||||||
- Lock the screen: This allows to lock the screen.
|
|
||||||
There are two mechanisms by which the screen can be locked, accessibility service and device admin.
|
|
||||||
- Toggle the flashlight
|
|
||||||
- Raise, lower or adjust volume
|
|
||||||
- Play or pause media playback
|
|
||||||
- Skip to previous or next audio track
|
|
||||||
- Open notifications panel: Might be useful if the top of your screen is broken.
|
|
||||||
- Open quick settings panel: Why swipe down twice?
|
|
||||||
- Open [recent apps](https://developer.android.com/guide/components/activities/recents): Requires accessibility service. Can be used as a workaround for a Android bug.
|
|
||||||
- Launch another home screen: Allows using another installed home screen temporarily.
|
|
||||||
- Do nothing: Just prevents showing the message saying that no action is bound to this gesture.
|
|
|
@ -1,11 +1,11 @@
|
||||||
# Building from Source
|
# Building µLauncher
|
||||||
|
|
||||||
## Using the command line
|
## Using the command line
|
||||||
|
|
||||||
Install JDK 17 and the Android SDK.
|
Install JDK 17 and the Android Sdk.
|
||||||
Make sure that `JAVA_HOME` and `ANDROID_HOME` are set correctly.
|
Make sure that `JAVA_HOME` and `ANDROID_HOME` are set correctly.
|
||||||
|
|
||||||
```bash
|
```
|
||||||
git clone https://github.com/jrpie/Launcher
|
git clone https://github.com/jrpie/Launcher
|
||||||
cd Launcher
|
cd Launcher
|
||||||
|
|
||||||
|
@ -15,8 +15,7 @@ cd Launcher
|
||||||
This will create an apk file at `app/build/outputs/apk/default/release/app-default-release-unsigned.apk`.
|
This will create an apk file at `app/build/outputs/apk/default/release/app-default-release-unsigned.apk`.
|
||||||
|
|
||||||
Note that you need to sign it:
|
Note that you need to sign it:
|
||||||
|
```
|
||||||
```bash
|
|
||||||
apksigner sign --ks "$YOUR_KEYSTORE" \
|
apksigner sign --ks "$YOUR_KEYSTORE" \
|
||||||
--ks-key-alias "$YOUR_ALIAS" \
|
--ks-key-alias "$YOUR_ALIAS" \
|
||||||
--ks-pass="pass:$YOUR_PASSWORD" \
|
--ks-pass="pass:$YOUR_PASSWORD" \
|
||||||
|
@ -29,17 +28,13 @@ apksigner sign --ks "$YOUR_KEYSTORE" \
|
||||||
app-default-release-unsigned.apk
|
app-default-release-unsigned.apk
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
See [this guide](https://developer.android.com/build/building-cmdline)
|
See [this guide](https://developer.android.com/build/building-cmdline)
|
||||||
for further instructions.
|
for further instructions.
|
||||||
|
|
||||||
## Using Android Studio
|
|
||||||
|
|
||||||
|
## Using Android Studio
|
||||||
Install [Android Studio](https://developer.android.com/studio), import this project and build it.
|
Install [Android Studio](https://developer.android.com/studio), import this project and build it.
|
||||||
|
|
||||||
See [this guide](https://developer.android.com/studio/run)
|
See [this guide](https://developer.android.com/studio/run)
|
||||||
for further instructions. How to
|
for further instructions.
|
||||||
|
|
||||||
## CI Pipeline
|
|
||||||
|
|
||||||
The [CI pipeline](https://github.com/jrpie/Launcher/actions) automatically creates debug builds.
|
|
||||||
> Note: These builds are *not* signed. They are in built in debug mode and only suitable for testing.
|
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
# Contributing
|
|
||||||
|
|
||||||
There are several ways to contribute to this app:
|
|
||||||
* You can add or improve [translations][toolate].
|
|
||||||
<br><img src="https://toolate.othing.xyz/widget/jrpie-launcher/launcher/horizontal-auto.svg" alt="translation status">
|
|
||||||
* If you found a bug or have an idea for a new feature you can [join the chat][chat] or open an [issue][issues].
|
|
||||||
|
|
||||||
> Please note that I work on this project in my free time. Thus I might not respond immediately and not all ideas will be implemented.
|
|
||||||
|
|
||||||
* You can implement a new feature yourself:
|
|
||||||
- Create a [fork][fork] of this repository.
|
|
||||||
- Create a new branch named `feature/<your feature>` or `fix/<your fix>` and commit your changes.
|
|
||||||
- Open a new pull request.
|
|
||||||
|
|
||||||
|
|
||||||
See [build.md](build.md) for instructions how to build this project.
|
|
||||||
The [CI pipeline](https://github.com/jrpie/Launcher/actions) automatically creates debug builds.
|
|
||||||
|
|
||||||
|
|
||||||
---
|
|
||||||
[fork]: https://github.com/jrpie/Launcher/fork/
|
|
||||||
[issues]: https://github.com/jrpie/Launcher/issues/
|
|
||||||
[chat]: https://s.jrpie.de/launcher-chat
|
|
||||||
[toolate]: https://toolate.othing.xyz/projects/jrpie-launcher/
|
|
43
docs/home.md
43
docs/home.md
|
@ -1,43 +0,0 @@
|
||||||
# Welcome to the μLauncher Documentation
|
|
||||||
|
|
||||||
## What is μLauncher?
|
|
||||||
|
|
||||||
µLauncher is an *minimal* and *distraction-free* Android home screen that lets you launch apps using [swipe gestures and button presses](/actions-and-gestured.md).
|
|
||||||
|
|
||||||
This project is a fork of [finnmglas's app Launcher](https://github.com/finnmglas/Launcher). An incomplete list of changes can be found [here](https://github.com/wassupluke/Launcher/blob/master/docs/launcher.md).
|
|
||||||
|
|
||||||
## Where can I get μLauncher?
|
|
||||||
|
|
||||||
[](https://f-droid.org/packages/de.jrpie.android.launcher/)
|
|
||||||
|
|
||||||
[](https://accrescent.app/app/de.jrpie.android.launcher.accrescent)
|
|
||||||
|
|
||||||
[](https://apps.obtainium.imranr.dev/redirect?r=obtainium://app/{%22id%22:%22de.jrpie.android.launcher%22,%22url%22:%22https://github.com/jrpie/Launcher%22,%22author%22:%22jrpie%22,%22name%22:%22%c2%b5Launcher%22,%22additionalSettings%22:%22{\%22apkFilterRegEx\%22:\%22release\%22,\%22invertAPKFilter\%22:false,\%22about\%22:\%22%c2%b5Launcher%20is%20a%20minimal%20home%20screen.\%22}%22})
|
|
||||||
|
|
||||||
[](https://github.com/jrpie/launcher/releases/latest)
|
|
||||||
|
|
||||||
> You can also [get it on Google Play](https://play.google.com/store/apps/details?id=de.jrpie.android.launcher), but this is not recommend.
|
|
||||||
|
|
||||||
|
|
||||||
## How can I contribute?
|
|
||||||
|
|
||||||
See [docs/contribute](/contribute.md)
|
|
||||||
|
|
||||||
## Screenshots
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
<!-- missing μLauncher grid view screenshot-->
|
|
|
@ -1,45 +1,40 @@
|
||||||
# Notable changes compared to Finn's Launcher
|
# Notable changes compared to [Finn's Launcher][original-repo]:
|
||||||
|
|
||||||
µLauncher is a fork of [finnmglas's app Launcher](https://github.com/finnmglas/Launcher).
|
µLauncher is a fork of [finnmglas's app Launcher][original-repo].
|
||||||
Here is an incomplete list of changes:
|
Here is an incomplete list of changes:
|
||||||
<!--The last commit of the original project is [340ee731](https://github.com/jrpie/launcher/commit/340ee7315293b028c060638e058516435bca296a)
|
<!--The last commit of the original project is [340ee731](https://github.com/jrpie/launcher/commit/340ee7315293b028c060638e058516435bca296a)
|
||||||
The first commit of µLauncher is [cc2e7710](https://github.com/jrpie/launcher/commit/cc2e7710c824549c367d97a81a1646d27c6c8993),
|
The first commit of µLauncher is [cc2e7710](https://github.com/jrpie/launcher/commit/cc2e7710c824549c367d97a81a1646d27c6c8993),
|
||||||
which at the time was still intended as a patch for launcher.
|
which at the time was still intended as a patch for launcher.
|
||||||
The decision to create a hard fork was made two years later.-->
|
The decision to create a hard fork was made two years later.-->
|
||||||
|
|
||||||
- Additional gestures:
|
|
||||||
- Back
|
|
||||||
- V,Λ,<,>
|
|
||||||
- Edge gestures: There is a setting to allow distinguishing swiping at the edges of the screen from swiping in the center.
|
|
||||||
|
|
||||||
|
- Additional gestures:
|
||||||
|
- Back
|
||||||
|
- V,Λ,<,>
|
||||||
|
- Edge gestures: There is a setting to allow distinguishing swiping at the edges of the screen from swiping in the center.
|
||||||
- Compatible with [work profile](https://www.android.com/enterprise/work-profile/), so apps like [Shelter](https://gitea.angry.im/PeterCxy/Shelter) can be used.
|
- Compatible with [work profile](https://www.android.com/enterprise/work-profile/), so apps like [Shelter](https://gitea.angry.im/PeterCxy/Shelter) can be used.
|
||||||
- Compatible with [private space](https://source.android.com/docs/security/features/private-space)
|
- Compatible with [private space](https://source.android.com/docs/security/features/private-space)
|
||||||
- Support for [app widgets](https://developer.android.com/develop/ui/views/appwidgets/overview)
|
|
||||||
- Support for [pinned shortcuts](https://developer.android.com/develop/ui/views/launch/shortcuts/creating-shortcuts)
|
|
||||||
- Option to rename apps
|
- Option to rename apps
|
||||||
- Option to hide apps
|
- Option to hide apps
|
||||||
- Favorite apps
|
- Favorite apps
|
||||||
- New actions:
|
- New actions:
|
||||||
- Toggle Torch
|
- Toggle Torch
|
||||||
- Lock screen
|
- Lock screen
|
||||||
- Open a widget panel
|
|
||||||
- The home button now works as expected.
|
- The home button now works as expected.
|
||||||
- Improved gesture detection.
|
- Improved gesture detection.
|
||||||
|
|
||||||
## Visual
|
### Visual
|
||||||
|
|
||||||
- This app uses the system wallpaper instead of a custom solution.
|
- This app uses the system wallpaper instead of a custom solution.
|
||||||
- The font has been changed to [Hack][hack-font], other fonts can be selected.
|
- The font has been changed to [Hack][hack-font], other fonts can be selected.
|
||||||
- Font Awesome Icons were replaced by Material icons.
|
- Font Awesome Icons were replaced by Material icons.
|
||||||
- The gear button on the home screen was removed. A smaller button is show at the top right when necessary.
|
- The gear button on the home screen was removed. A smaller button is show at the top right when necessary.
|
||||||
|
|
||||||
## Search
|
|
||||||
|
|
||||||
|
### Search
|
||||||
- The search algorithm was modified to prefer matches at the beginning of the app name, i.e. when searching for `"te"`, `"termux"` is sorted before `"notes"`.
|
- The search algorithm was modified to prefer matches at the beginning of the app name, i.e. when searching for `"te"`, `"termux"` is sorted before `"notes"`.
|
||||||
- The search bar was moved to the bottom of the screen.
|
- The search bar was moved to the bottom of the screen.
|
||||||
|
|
||||||
## Technical
|
### Technical
|
||||||
|
|
||||||
- Improved gesture detection.
|
- Improved gesture detection.
|
||||||
- Different apps set as default.
|
- Different apps set as default.
|
||||||
- Package name was changed to `de.jrpie.android.launcher` to avoid clashing with the original app.
|
- Package name was changed to `de.jrpie.android.launcher` to avoid clashing with the original app.
|
||||||
|
@ -47,10 +42,9 @@ The decision to create a hard fork was made two years later.-->
|
||||||
- Fixed some bugs
|
- Fixed some bugs
|
||||||
- Some refactoring
|
- Some refactoring
|
||||||
|
|
||||||
|
|
||||||
The complete list of changes can be viewed [here](https://github.com/jrpie/launcher/compare/340ee731...master).
|
The complete list of changes can be viewed [here](https://github.com/jrpie/launcher/compare/340ee731...master).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
[original-repo]: https://github.com/finnmglas/Launcher
|
||||||
\[original-repo\]: [https://github.com/finnmglas/Launcher](https://github.com/finnmglas/Launcher)
|
[hack-font]: https://sourcefoundry.org/hack/
|
||||||
|
|
||||||
\[hack-font\]: [https://sourcefoundry.org/hack/](https://sourcefoundry.org/hack/)
|
|
|
@ -1,21 +0,0 @@
|
||||||
# Work Profile
|
|
||||||
|
|
||||||
µLauncher is compatible with [work profile](https://www.android.com/enterprise/work-profile/), so apps like [Shelter](https://gitea.angry.im/PeterCxy/Shelter) can be used.
|
|
||||||
Apps from the work profile are shown in the usual app list.
|
|
||||||
|
|
||||||
|
|
||||||
# Private Space
|
|
||||||
|
|
||||||
µLauncher is compatible with [private space](https://source.android.com/docs/security/features/private-space).
|
|
||||||
|
|
||||||
|
|
||||||
The private space can be (un)locked by a dedicated action.
|
|
||||||
|
|
||||||
It is configurable whether apps from private space are
|
|
||||||
|
|
||||||
1. shown in the usual app list
|
|
||||||
(in this case, (un)locking is accessible through a lock icon on the top right of the app drawer)
|
|
||||||
or
|
|
||||||
2. only shown in a separate list.
|
|
||||||
|
|
||||||
|
|
235
docs/settings.md
235
docs/settings.md
|
@ -1,235 +0,0 @@
|
||||||
# Launcher Settings
|
|
||||||
|
|
||||||
Tweaks and customizations can be made from within the Launcher Settings page.
|
|
||||||
|
|
||||||
These settings let you change wallpapers, change colors and fonts, enable monochrome app icons, change the app drawer layout, and much more.
|
|
||||||
|
|
||||||
In the following documentation, 'app drawer' will be used to refer to the 'All Apps', 'Favorite Apps' and 'Private Space' views.
|
|
||||||
|
|
||||||
## Appearance
|
|
||||||
|
|
||||||
> ### Choose a wallpaper
|
|
||||||
|
|
||||||
This triggers Android's mechanism to change the wallpaper using a photos app, file explorer, or native wallpaper setting app.
|
|
||||||
µLauncher uses the system-wide wallpaper, i.e. this change also affects other launchers.
|
|
||||||
|
|
||||||
> ### Font (in-app font)
|
|
||||||
|
|
||||||
Set the font used within the app settings. This setting does not affect the date/time home screen font.
|
|
||||||
|
|
||||||
**type:** `dropdown`
|
|
||||||
|
|
||||||
**options:** `Hack`,`System default`,`Sans serif`,`Serif`,`Monospace`,`Serif monospace`
|
|
||||||
|
|
||||||
> ### Text Shadow
|
|
||||||
|
|
||||||
**type:** `toggle`
|
|
||||||
|
|
||||||
> ### Background (app list and setting)
|
|
||||||
|
|
||||||
**type:** `dropdown`
|
|
||||||
|
|
||||||
**type:** `Transparent`,`Dim`,`Blur`,`Solid`
|
|
||||||
|
|
||||||
> ### Monochrome app icons
|
|
||||||
|
|
||||||
Remove coloring from all app icons. Can help decrease visual stimulus when enabled.
|
|
||||||
|
|
||||||
**type:** `toggle`
|
|
||||||
|
|
||||||
## Date & Time
|
|
||||||
|
|
||||||
> ### Font (home screen)
|
|
||||||
|
|
||||||
Set the home screen font for date and time. This setting does not affect the in-app font.
|
|
||||||
|
|
||||||
**type:** `dropdown`
|
|
||||||
|
|
||||||
**options:** `Hack`,`System default`,`Sans serif`,`Serif`,`Monospace`,`Serif monospace`
|
|
||||||
|
|
||||||
> ### Color [`[bug]`](https://github.com/jrpie/launcher/issues/151)
|
|
||||||
|
|
||||||
Set the color for the home screen date and time.
|
|
||||||
|
|
||||||
Accepts a HEX color code (consisting of a '#' followed by three sets of two alphanumeric (letters and numbers) characters. A fourth set of two alphanumeric characters may be added to set the transparency of the color.
|
|
||||||
|
|
||||||
[Color wheel picker](https://rgbacolorpicker.com/color-wheel-picker)
|
|
||||||
|
|
||||||
**type:** `HEX`,`RGBA`
|
|
||||||
|
|
||||||
> ### Use localized date format
|
|
||||||
|
|
||||||
Adapt the display of dates and times to the specific conventions of a particular locale or region. Different locales use different date orders (e.g., MM/DD/YYYY in the US, DD/MM/YYYY in Europe).
|
|
||||||
|
|
||||||
**type:** `toggle`
|
|
||||||
|
|
||||||
> ### Show time
|
|
||||||
|
|
||||||
Show the current time on the home screen.
|
|
||||||
|
|
||||||
**type:** `toggle`
|
|
||||||
|
|
||||||
> ### Show seconds
|
|
||||||
|
|
||||||
Show the current time down to the second on the home screen.
|
|
||||||
|
|
||||||
**type:** `toggle`
|
|
||||||
|
|
||||||
> ### Show date
|
|
||||||
|
|
||||||
Show the current date on the home screen.
|
|
||||||
|
|
||||||
**type:** `toggle`
|
|
||||||
|
|
||||||
> ### Flip date and time
|
|
||||||
|
|
||||||
Place the current time above the current date on the home screen.
|
|
||||||
|
|
||||||
**type:** `toggle`
|
|
||||||
|
|
||||||
## Functionality
|
|
||||||
|
|
||||||
> ### Launch search results
|
|
||||||
|
|
||||||
Launches any app that matches user keyboard input when no other apps match.
|
|
||||||
|
|
||||||
As you type inside the app drawer, the app narrows down the list of apps shown based on the app title matching your text input.
|
|
||||||
With the 'launch search results' setting, once only one matching app remains, it is launched immediately.
|
|
||||||
Usually it suffices to type two or three characters the single out the desired app.
|
|
||||||
|
|
||||||
This feature becomes more powerful when combined with [renaming](#additional-settings) apps, effectively letting you define custom app names that could be considered 'aliases' or shortcuts.
|
|
||||||
For instance, if you want the keyboard input `gh` to open your `GitHub` app, you could rename `GitHub` to `GitHub gh`, `gh GitHub`, or simply `gh`.
|
|
||||||
Assuming no other installed apps have the `gh` combination of letters in them, opening the app drawer and typing `gh` would immediately launch your `GitHub` app.
|
|
||||||
|
|
||||||
Press space to temporarily disable this feature and allow text entry without prematurely launching an app. Useful when combined with the [Search the web](#search-the-web) feature.
|
|
||||||
|
|
||||||
**type:** `toggle`
|
|
||||||
|
|
||||||
> ### Search the web
|
|
||||||
|
|
||||||
Press return/enter while searching the app list to launch a web search.
|
|
||||||
|
|
||||||
**type:** `toggle`
|
|
||||||
|
|
||||||
> ### Start keyboard for search
|
|
||||||
|
|
||||||
Automatically open the keyboard when the app drawer is opened.
|
|
||||||
|
|
||||||
**type:** `toggle`
|
|
||||||
|
|
||||||
> ### Double swipe gestures
|
|
||||||
|
|
||||||
Enable double swipe (two finger) gestures in launcher settings. Does not erase gesture bindings if accidentally turned off.
|
|
||||||
|
|
||||||
**type:** `toggle`
|
|
||||||
|
|
||||||
> ### Edge swipe gestures
|
|
||||||
|
|
||||||
Enable edge swipe (near edges of screen) gestures in launcher settings. Does not erase gesture bindings if accidentally turned off.
|
|
||||||
|
|
||||||
**type:** `toggle`
|
|
||||||
|
|
||||||
> ### Edge width
|
|
||||||
|
|
||||||
Change how large a margin is used for detecting edge gestures. Shows the edge margin preview when using the slider.
|
|
||||||
|
|
||||||
**type:** `slider`
|
|
||||||
|
|
||||||
> ### Choose method for locking the screen
|
|
||||||
|
|
||||||
There are two methods to lock the screen and unfortunately both have downsides.
|
|
||||||
|
|
||||||
1. **`Device Admin`**
|
|
||||||
|
|
||||||
- Doesn't work with unlocking by fingerprint or face recognition.
|
|
||||||
|
|
||||||
2. **`Accessibility Service`**
|
|
||||||
|
|
||||||
- Requires excessive privileges.
|
|
||||||
- μLauncher will use those privileges *only* for locking the screen.
|
|
||||||
- As a rule of thumb, it is [not recommended](https://android.stackexchange.com/questions/248171/is-it-safe-to-give-accessibility-permission-to-an-app) to grant access to accessibility services on a random app. Always review the [source code](https://github.com/jrpie/Launcher) before granting accessibility permissions so you familiarize yourself with what the code might do.
|
|
||||||
- On some devices, the start-up PIN will no longer be used for encrypting data after activating an accessibility service.
|
|
||||||
- This can be [reactivated](https://issuetracker.google.com/issues/37010136#comment36) afterwards.
|
|
||||||
|
|
||||||
**type:** `text buttons`
|
|
||||||
|
|
||||||
**options:** `USE DEVICE ADMIN`,`USE ACCESSIBILITY SERVICE`
|
|
||||||
|
|
||||||
## Apps
|
|
||||||
|
|
||||||
> ### Hidden apps
|
|
||||||
|
|
||||||
Open an app drawer containing only hidden apps.
|
|
||||||
|
|
||||||
> ### Don't show apps that are bound to a gesture in the app list
|
|
||||||
|
|
||||||
Remove certain apps from the app drawer if they are already accessible via a gesture.
|
|
||||||
|
|
||||||
Reduces redundancy and tidies up app drawer.
|
|
||||||
|
|
||||||
**type:** `toggle`
|
|
||||||
|
|
||||||
> ### Hide paused apps
|
|
||||||
|
|
||||||
Remove paused apps from the app drawer.
|
|
||||||
For example an app belonging to the work profile is paused when the work profile is inactive.
|
|
||||||
|
|
||||||
**type:** `toggle`
|
|
||||||
|
|
||||||
> ### Hide private space from app list
|
|
||||||
|
|
||||||
Remove private space from app drawer.
|
|
||||||
|
|
||||||
**type:** `toggle`
|
|
||||||
|
|
||||||
> ### Layout of app list
|
|
||||||
|
|
||||||
Changes how the apps are displayed when accessing the app drawer.
|
|
||||||
|
|
||||||
- `Default`: All apps in the drawer will show in a vertically-scrolled list with their app icon and title.
|
|
||||||
- `Text`: Removes the app icons, shows only app titles in the drawer as a vertically-scrolled list.
|
|
||||||
Work profile and private space apps are distinguished by a different label instead of a badge.
|
|
||||||
- `Grid`: Shows apps with their app icon and title in a grid layout.
|
|
||||||
|
|
||||||
**type:** `dropdown`
|
|
||||||
|
|
||||||
**options:** `Default`,`Text`,`Grid`
|
|
||||||
|
|
||||||
> ### Reverse the app list
|
|
||||||
|
|
||||||
Enable reverse alphabetical sorting of apps in the app drawer.
|
|
||||||
Useful for keeping apps within easier reach from the keyboard.
|
|
||||||
|
|
||||||
**type:** `toggle`
|
|
||||||
|
|
||||||
## Display
|
|
||||||
|
|
||||||
> ### Rotate screen
|
|
||||||
|
|
||||||
**type:** `toggle`
|
|
||||||
|
|
||||||
> ### Keep screen on
|
|
||||||
|
|
||||||
**type:** `toggle`
|
|
||||||
|
|
||||||
> ### Hide status bar
|
|
||||||
|
|
||||||
Remove the top status bar from the home screen.
|
|
||||||
|
|
||||||
**type:** `toggle`
|
|
||||||
|
|
||||||
> ### Hide navigation bar
|
|
||||||
|
|
||||||
Remove the navigation bar from the home screen. Enabling this setting may make it difficult to use the device if gestures are not setup properly.
|
|
||||||
|
|
||||||
**type:** `toggle`
|
|
||||||
|
|
||||||
## Additional Settings
|
|
||||||
|
|
||||||
> ### App Drawer Long Press on App
|
|
||||||
|
|
||||||
Access additional per-app details and settings. To use, open the app drawer and long press on any app.
|
|
||||||
|
|
||||||
**type:** `dropdown`
|
|
||||||
|
|
||||||
**options:** `App Info`,`Add to favorites`,`Hide`,`Rename`,`Uninstall`
|
|
Loading…
Add table
Add a link
Reference in a new issue