Compare commits

..

2 commits

Author SHA1 Message Date
86528f4e27
add tap-swipe combo gestures (see #110)
Some checks failed
Android CI / build (push) Has been cancelled
2025-02-18 19:20:53 +01:00
3aee137a3c
basic support for pinned shortcuts (see #45)
TODO: Show pinned shortcuts in app list
2025-02-18 19:02:25 +01:00
29 changed files with 150 additions and 76 deletions

View file

@ -59,6 +59,7 @@ The following gestures are available:
- swipe up / down / left / right,
- swipe with two fingers,
- swipe on the left / right resp. top / bottom edge,
- tap, then swipe up / down / left / right,
- draw < / > / V / Λ
- click on date / time,
- double click,

View file

@ -104,7 +104,6 @@ fun removeUnusedShortcuts(context: Context) {
.toSet()
try {
userManager.userProfiles.filter { !userManager.isQuietModeEnabled(it) }.forEach { profile ->
Log.e("Shortcuts", "$profile : ${getShortcuts(profile)?.size} shortcuts")
getShortcuts(profile)?.groupBy { it.`package` }?.forEach { (p, shortcuts) ->
launcherApps.pinShortcuts(p,
shortcuts.filter { boundActions.contains(PinnedShortcutInfo(it)) }
@ -114,7 +113,6 @@ fun removeUnusedShortcuts(context: Context) {
}
}
} catch (_: SecurityException) { }
}
fun openInBrowser(url: String, context: Context) {

View file

@ -79,6 +79,13 @@ enum class Gesture(
R.array.default_up_right,
R.anim.bottom_up
),
TAP_AND_SWIPE_UP(
"action.tap_up",
R.string.settings_gesture_tap_up,
R.string.settings_gesture_description_tap_up,
R.array.default_up,
R.anim.bottom_up
),
SWIPE_UP_DOUBLE(
"action.double_up",
R.string.settings_gesture_double_up,
@ -107,6 +114,13 @@ enum class Gesture(
R.array.default_down_right,
R.anim.top_down
),
TAP_AND_SWIPE_DOWN(
"action.tap_down",
R.string.settings_gesture_tap_down,
R.string.settings_gesture_description_tap_down,
R.array.default_down,
R.anim.bottom_up
),
SWIPE_DOWN_DOUBLE(
"action.double_down",
R.string.settings_gesture_double_down,
@ -135,6 +149,13 @@ enum class Gesture(
R.array.default_messengers,
R.anim.right_left
),
TAP_AND_SWIPE_LEFT(
"action.tap_left",
R.string.settings_gesture_tap_left,
R.string.settings_gesture_description_tap_left,
R.array.default_messengers,
R.anim.right_left
),
SWIPE_LEFT_DOUBLE(
"action.double_left",
R.string.settings_gesture_double_left,
@ -163,6 +184,13 @@ enum class Gesture(
R.array.default_right_bottom,
R.anim.left_right
),
TAP_AND_SWIPE_RIGHT(
"action.tap_right",
R.string.settings_gesture_tap_right,
R.string.settings_gesture_description_tap_right,
R.array.default_right,
R.anim.left_right
),
SWIPE_RIGHT_DOUBLE(
"action.double_right",
R.string.settings_gesture_double_right,
@ -279,6 +307,17 @@ enum class Gesture(
}
}
fun getTapComboVariant(): Gesture {
return when (this) {
SWIPE_UP -> TAP_AND_SWIPE_UP
SWIPE_DOWN -> TAP_AND_SWIPE_DOWN
SWIPE_LEFT -> TAP_AND_SWIPE_LEFT
SWIPE_RIGHT -> TAP_AND_SWIPE_RIGHT
else -> this
}
}
fun isDoubleVariant(): Boolean {
return when (this) {
SWIPE_UP_DOUBLE,

View file

@ -2,6 +2,7 @@ package de.jrpie.android.launcher.ui
import android.app.AlertDialog
import android.app.Service
import android.content.Context
import android.content.pm.LauncherApps
import android.content.pm.LauncherApps.PinItemRequest
import android.content.res.Resources
@ -27,8 +28,11 @@ import de.jrpie.android.launcher.preferences.LauncherPreferences
class PinShortcutActivity : AppCompatActivity(), UIObject {
private lateinit var binding: ActivityPinShortcutBinding
private var isBound = false
override fun onCreate(savedInstanceState: Bundle?) {
super<AppCompatActivity>.onCreate(savedInstanceState)
super<UIObject>.onCreate()
enableEdgeToEdge()
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
@ -47,10 +51,12 @@ class PinShortcutActivity : AppCompatActivity(), UIObject {
return
}
request.accept()
binding.pinShortcutLabel.text = request.shortcutInfo!!.shortLabel ?: "?"
binding.pinShortcutIcon.setImageDrawable(launcherApps.getShortcutBadgedIconDrawable(request.shortcutInfo, 0))
binding.pinShortcutLabel.setCompoundDrawables(
launcherApps.getShortcutBadgedIconDrawable(request.shortcutInfo, 0).also {
val size = (40 * resources.displayMetrics.density).toInt()
it.setBounds(0,0, size, size)
}, null, null, null)
binding.pinShortcutButtonBind.setOnClickListener {
AlertDialog.Builder(this, R.style.AlertDialogCustom)
@ -59,7 +65,11 @@ class PinShortcutActivity : AppCompatActivity(), UIObject {
.setNegativeButton(android.R.string.cancel, null)
.create().also { it.show() }.let { dialog ->
val viewManager = LinearLayoutManager(dialog.context)
val viewAdapter = GestureRecyclerAdapter { gesture ->
val viewAdapter = GestureRecyclerAdapter (dialog.context) { gesture ->
if (!isBound) {
isBound = true
request.accept()
}
val editor = LauncherPreferences.getSharedPreferences().edit()
ShortcutAction(PinnedShortcutInfo(request.shortcutInfo!!)).bindToGesture(editor, gesture.id)
editor.apply()
@ -72,6 +82,8 @@ class PinShortcutActivity : AppCompatActivity(), UIObject {
}
}
}
binding.pinShortcutClose.setOnClickListener { finish() }
}
override fun onStart() {
@ -83,7 +95,7 @@ class PinShortcutActivity : AppCompatActivity(), UIObject {
return modifyTheme(super.getTheme())
}
inner class GestureRecyclerAdapter(val onClick: (Gesture) -> Unit): RecyclerView.Adapter<GestureRecyclerAdapter.ViewHolder>() {
inner class GestureRecyclerAdapter(val context: Context, val onClick: (Gesture) -> Unit): RecyclerView.Adapter<GestureRecyclerAdapter.ViewHolder>() {
val gestures = Gesture.entries.filter { it.isEnabled() }.toList()
inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val label = itemView.findViewById<TextView>(R.id.dialog_select_gesture_row_name)
@ -99,10 +111,10 @@ class PinShortcutActivity : AppCompatActivity(), UIObject {
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val gesture = gestures[position]
holder.label.text = gesture.getLabel(applicationContext)
holder.description.text = gesture.getDescription(applicationContext)
holder.label.text = gesture.getLabel(context)
holder.description.text = gesture.getDescription(context)
holder.icon.setImageDrawable(
Action.forGesture(gesture)?.getIcon(applicationContext)
Action.forGesture(gesture)?.getIcon(context)
)
holder.itemView.setOnClickListener {
onClick(gesture)

View file

@ -240,6 +240,10 @@ class TouchGestureDetector(
gesture = gesture?.getEdgeVariant(Gesture.Edge.BOTTOM)
}
}
if (timeStart - lastTappedTime < 2 * DOUBLE_TAP_TIMEOUT) {
gesture = gesture?.getTapComboVariant()
}
gesture?.invoke(context)
}
}

View file

@ -1,7 +1,6 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">

View file

@ -1,7 +1,6 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">

View file

@ -1,7 +1,6 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?android:textColor"
android:viewportWidth="24"
android:viewportHeight="24">

View file

@ -1,7 +1,6 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">

View file

@ -2,8 +2,7 @@
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?attr/colorControlNormal">
android:viewportHeight="960">
<path
android:fillColor="?android:textColor"
android:pathData="M240,880Q207,880 183.5,856.5Q160,833 160,800L160,400Q160,367 183.5,343.5Q207,320 240,320L280,320L280,240Q280,157 338.5,98.5Q397,40 480,40Q563,40 621.5,98.5Q680,157 680,240L680,320L720,320Q753,320 776.5,343.5Q800,367 800,400L800,800Q800,833 776.5,856.5Q753,880 720,880L240,880ZM240,800L720,800Q720,800 720,800Q720,800 720,800L720,400Q720,400 720,400Q720,400 720,400L240,400Q240,400 240,400Q240,400 240,400L240,800Q240,800 240,800Q240,800 240,800ZM480,680Q513,680 536.5,656.5Q560,633 560,600Q560,567 536.5,543.5Q513,520 480,520Q447,520 423.5,543.5Q400,567 400,600Q400,633 423.5,656.5Q447,680 480,680ZM360,320L600,320L600,240Q600,190 565,155Q530,120 480,120Q430,120 395,155Q360,190 360,240L360,320ZM240,800Q240,800 240,800Q240,800 240,800L240,400Q240,400 240,400Q240,400 240,400L240,400Q240,400 240,400Q240,400 240,400L240,800Q240,800 240,800Q240,800 240,800Z" />

View file

@ -1,7 +1,6 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path

View file

@ -1,5 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="?android:textColor" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="?android:textColor" android:pathData="M3,18h18v-2L3,16v2zM3,13h18v-2L3,11v2zM3,6v2h18L21,6L3,6z"/>
<path
android:fillColor="?android:textColor"
android:pathData="M3,18h18v-2L3,16v2zM3,13h18v-2L3,11v2zM3,6v2h18L21,6L3,6z" />
</vector>

View file

@ -1,5 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp">
<path android:fillColor="?android:textColor" android:pathData="M6,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM18,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"/>
<path
android:fillColor="?android:textColor"
android:pathData="M6,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM18,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z" />
</vector>

View file

@ -1,7 +1,6 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">

View file

@ -1,7 +1,6 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">

View file

@ -1,7 +1,6 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">

View file

@ -1,6 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp">

View file

@ -1,7 +1,6 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">

View file

@ -1,7 +1,6 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">

View file

@ -1,7 +1,6 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">

View file

@ -1,7 +1,6 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">

View file

@ -2,7 +2,6 @@
android:width="24dp"
android:height="24dp"
android:autoMirrored="true"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">

View file

@ -2,7 +2,6 @@
android:width="24dp"
android:height="24dp"
android:autoMirrored="true"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">

View file

@ -21,6 +21,11 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/list_heading"
android:layout_width="match_parent"
@ -30,41 +35,51 @@
android:padding="@dimen/appbar_padding"
android:text="@string/pin_shortcut_title"
android:textAppearance="@style/TextAppearance.Widget.AppCompat.Toolbar.Title"
android:textSize="30sp" />
android:textSize="30sp"
app:layout_constraintEnd_toStartOf="@id/pin_shortcut_close"
app:layout_constraintStart_toStartOf="parent" />
<ImageView
android:id="@+id/pin_shortcut_close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:gravity="center"
android:includeFontPadding="true"
android:paddingLeft="16sp"
android:paddingRight="16sp"
android:src="@drawable/baseline_close_24"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.appbar.AppBarLayout>
<ScrollView
app:layout_constraintTop_toBottomOf="@id/pin_shortcut_appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/pin_shortcut_appbar">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_margin="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="horizontal"
android:layout_gravity="center"
android:layout_margin="50dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/pin_shortcut_icon"
android:layout_width="40sp"
android:layout_height="40sp" />
android:orientation="vertical">
<TextView
android:layout_marginLeft="10dp"
android:id="@+id/pin_shortcut_label"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="50dp"
android:drawablePadding="10dp"
android:gravity="center_vertical"
android:minHeight="40dp"
tools:drawableLeft="@drawable/baseline_settings_24"
tools:text="Shortcut name" />
</LinearLayout>
<!--
<Space
android:layout_width="match_parent"
@ -84,9 +99,9 @@
<Button
android:id="@+id/pin_shortcut_button_bind"
android:text="@string/pin_shortcut_button_bind"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
android:layout_height="wrap_content"
android:text="@string/pin_shortcut_button_bind" />
</LinearLayout>

View file

@ -3,6 +3,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/dialog_select_gesture_row_container"
style="@style/AlertDialogCustom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp">
@ -44,8 +45,8 @@
android:layout_height="@dimen/app_icon_side"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.2"
app:layout_constraintTop_toTopOf="parent"
tools:srcCompat="@drawable/baseline_flashlight_on_24"
tools:ignore="ContentDescription" />

View file

@ -29,18 +29,26 @@
<string name="settings_gesture_description_back">Back button / back gesture</string>
<string name="settings_gesture_up">Up</string>
<string name="settings_gesture_description_up">Swipe up</string>
<string name="settings_gesture_tap_up">Tap + Up</string>
<string name="settings_gesture_description_tap_up">Tap and swipe up</string>
<string name="settings_gesture_double_up">Double Up</string>
<string name="settings_gesture_description_double_up">Swipe up with two fingers</string>
<string name="settings_gesture_down">Down</string>
<string name="settings_gesture_description_down">Swipe down</string>
<string name="settings_gesture_tap_down">Tap + Down</string>
<string name="settings_gesture_description_tap_down">Tap and swipe down</string>
<string name="settings_gesture_double_down">Double Down</string>
<string name="settings_gesture_description_double_down">Swipe down with two fingers</string>
<string name="settings_gesture_left">Left</string>
<string name="settings_gesture_description_left">Swipe left</string>
<string name="settings_gesture_tap_left">Tap + Left</string>
<string name="settings_gesture_description_tap_left">Tap and swipe left</string>
<string name="settings_gesture_double_left">Double Left</string>
<string name="settings_gesture_description_double_left">Swipe left with two fingers</string>
<string name="settings_gesture_right">Right</string>
<string name="settings_gesture_description_right">Swipe right</string>
<string name="settings_gesture_tap_right">Tap + Right</string>
<string name="settings_gesture_description_tap_right">Tap and swipe right</string>
<string name="settings_gesture_double_right">Double Right</string>
<string name="settings_gesture_description_double_right">Swipe right with two fingers</string>
<string name="settings_gesture_right_top_edge">Right (Top)</string>
@ -62,19 +70,19 @@
<string name="settings_gesture_swipe_larger"><![CDATA[>]]></string>
<string name="settings_gesture_description_swipe_larger">Top left -> mid right -> bottom left</string>
<string name="settings_gesture_swipe_larger_reverse"><![CDATA[> (reverse)]]></string>
<string name="settings_gesture_swipe_larger_reverse"><![CDATA[> (Reverse)]]></string>
<string name="settings_gesture_description_swipe_larger_reverse">Bottom left -> mid right -> top left</string>
<string name="settings_gesture_swipe_smaller"><![CDATA[<]]></string>
<string name="settings_gesture_description_swipe_smaller">Top right -> mid left -> bottom right</string>
<string name="settings_gesture_swipe_smaller_reverse"><![CDATA[< (reverse)]]></string>
<string name="settings_gesture_swipe_smaller_reverse"><![CDATA[< (Reverse)]]></string>
<string name="settings_gesture_description_swipe_smaller_reverse">Bottom right -> mid left -> top right</string>
<string name="settings_gesture_swipe_v">V</string>
<string name="settings_gesture_description_swipe_v">Top left -> bottom mid -> top right</string>
<string name="settings_gesture_swipe_v_reverse">V (reverse)</string>
<string name="settings_gesture_swipe_v_reverse">V (Reverse)</string>
<string name="settings_gesture_description_swipe_v_reverse">Top right -> bottom mid -> top left</string>
<string name="settings_gesture_swipe_lambda">Λ</string>
<string name="settings_gesture_description_swipe_lambda">Bottom left -> top mid -> bottom right</string>
<string name="settings_gesture_swipe_lambda_reverse">Λ (reverse)</string>
<string name="settings_gesture_swipe_lambda_reverse">Λ (Reverse)</string>
<string name="settings_gesture_description_swipe_lambda_reverse">Bottom right -> top mid -> bottom left</string>
<string name="settings_gesture_vol_up">Volume Up</string>

View file

@ -11,7 +11,7 @@ Es handelt sich um einen Fork von <a href="https://f-droid.org/packages/com.finn
App Launcher</a>.
<b>Funktionen:</b>
* Aktionen können an 22 verschiedene Gesten gebunden werden.
* Aktionen können an 35 verschiedene Gesten gebunden werden.
* Die folgenden Aktionen stehen zur Verfügung:
- Eine App starten
- Alle Apps auflisten

View file

@ -10,7 +10,7 @@ This is a fork of the app <a href="https://f-droid.org/packages/com.finnmglas.la
by Finn M Glas.
Features:
* You can bind actions to 22 different gestures.
* You can bind actions to 35 different gestures.
* An action can be one of the following:
- Launch an app
- List all apps

View file

@ -10,7 +10,7 @@ O app é uma modificação do <a href="https://f-droid.org/packages/com.finnmgla
feito por Finn M Glas.
Funcionalidades:
* Você pode associar várias ações a 22 gestos diferentes.
* Você pode associar várias ações a 35 gestos diferentes.
* Pode definir algumas das seguintes ações:
- Iniciar vários apps
- Listar todos aplicativos