Compare commits

...

28 commits

Author SHA1 Message Date
919108bbd0
fix: stop longPressHandler when activity finishes
Some checks failed
Android CI / build (push) Has been cancelled
2025-06-05 12:02:37 +02:00
ce939111d0
fixed italian translation
Some checks failed
Android CI / build (push) Has been cancelled
2025-05-29 19:29:05 +02:00
Too Late (bot)
33dd3ef3c2
Translations update from Toolate (#175)
* Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 99.6% (288 of 289 strings)

Translation: jrpie-Launcher/Launcher
Translate-URL: https://toolate.othing.xyz/projects/jrpie-launcher/launcher/zh_Hans/

* Translated using Weblate (Arabic)

Currently translated at 100.0% (289 of 289 strings)

Translation: jrpie-Launcher/Launcher
Translate-URL: https://toolate.othing.xyz/projects/jrpie-launcher/launcher/ar/

* Translated using Weblate (Italian)

Currently translated at 100.0% (290 of 290 strings)

Translation: jrpie-Launcher/Launcher
Translate-URL: https://toolate.othing.xyz/projects/jrpie-launcher/launcher/it/

* Translated using Weblate (Italian)

Currently translated at 100.0% (290 of 290 strings)

Translation: jrpie-Launcher/Launcher
Translate-URL: https://toolate.othing.xyz/projects/jrpie-launcher/launcher/it/

---------

Co-authored-by: class0068 <monkeyotw@proton.me>
Co-authored-by: abdelbasset jabrane <cehiwa4149@oronny.com>
Co-authored-by: Vladi69 <vladimirogalante@yahoo.it>
Co-authored-by: renar <opensource.tjxzm@aleeas.com>
2025-05-29 19:18:01 +02:00
Luke Wass
1d793c485e
Improve documentation (#190)
* fix grammar
2025-05-29 17:16:05 +02:00
04a2b4d248
merge #193 - codebase improvements
Co-authored-by: Luke Wass <wassupluke@gmail.com>

Squashed commit of the following:

commit 075b4a5353cedea531ec6ebefa60d92de82e8e21
Author: Josia Pietsch <git@jrpie.de>
Date:   Thu May 29 15:34:23 2025 +0200

    some changes

commit ced2e30531
Author: Luke Wass <wassupluke@gmail.com>
Date:   Thu May 29 00:18:21 2025 -0500

    remove unused imports/functions/variables, improve naming convention, remove unused widget context

commit 956ad9795c
Author: Luke Wass <wassupluke@gmail.com>
Date:   Wed May 28 22:40:05 2025 -0500

    add contentDescriptions, ignore unspeakable sections, minor code reorganization

commit cb793860c0
Author: Luke Wass <wassupluke@gmail.com>
Date:   Wed May 28 21:03:03 2025 -0500

    remove empty method

commit 893de14c79
Author: Luke Wass <wassupluke@gmail.com>
Date:   Tue May 27 22:56:03 2025 -0500

    Simplify constructors by removing unused init parameters; clean up handle list type declaration

commit 39164d2e54
Author: Luke Wass <wassupluke@gmail.com>
Date:   Tue May 27 22:54:16 2025 -0500

    Refactor getAppWidgetProviders to use explicit lambda parameter names for clarity

commit 8e53ef0ebe
Author: Luke Wass <wassupluke@gmail.com>
Date:   Tue May 27 22:52:21 2025 -0500

    improve naming convention

commit 8c2a266c22
Author: Luke Wass <wassupluke@gmail.com>
Date:   Tue May 27 22:50:55 2025 -0500

    remove unused resources

commit be03af8ac6
Author: Luke Wass <wassupluke@gmail.com>
Date:   Tue May 27 22:50:33 2025 -0500

    fix table format
2025-05-29 15:48:41 +02:00
15d36eeff4
delete appwidgethost when resetting settings
Some checks failed
Android CI / build (push) Has been cancelled
2025-05-26 14:34:42 +02:00
3c2efe04de
Merge branch 'master' of https://github.com/jrpie/launcher 2025-05-26 14:33:04 +02:00
Luke Wass
d33f250a56
fix cardView shadow clipping (#188)
* fix cardView shadow clipping

* decrease margin above cardView
2025-05-26 13:26:13 +02:00
23c5973501
Merge pull request #182 from wassupluke/improve-tutorial
Some checks are pending
Android CI / build (push) Waiting to run
Add visual cues and interactive styling to the settings fragment
2025-05-25 10:56:04 +00:00
394f66dde9
change card background in light theme 2025-05-25 12:54:54 +02:00
8f3a8539cb
explain background settings (#144) 2025-05-25 03:10:17 +02:00
059480fad1
Merge pull request #183 from wassupluke/improve-documentation
Some checks are pending
Android CI / build (push) Waiting to run
pull in hedgedoc content
2025-05-24 22:39:36 +00:00
3b70416b66
implement #181 2025-05-24 23:00:55 +02:00
Luke Wass
4f71011b1a
fix formatting 2025-05-24 15:20:13 -05:00
Luke Wass
e9585fa4dd
pull in hedgedoc content 2025-05-24 15:04:18 -05:00
85a7ed24ab
add documentation button 2025-05-24 21:08:45 +02:00
dfaec30fac
Merge branch 'master' of https://github.com/jrpie/launcher 2025-05-24 20:55:03 +02:00
1d10d65adb
update documentation 2025-05-24 20:41:37 +02:00
71193a2e50
fixed typo 2025-05-24 20:34:15 +02:00
580644f9d4
add documentation of app drawer 2025-05-24 20:29:01 +02:00
ea5a4ad7bf
add example to docs 2025-05-24 19:30:15 +02:00
f94c2b5962
add example to docs 2025-05-24 19:24:48 +02:00
ac1639b77e
add termux example to docs (see #147 and #149)
Some checks are pending
Android CI / build (push) Waiting to run
2025-05-24 19:01:15 +02:00
e4c7ad0994
prepare docs/ for hugo ssg (see #176) 2025-05-24 17:40:32 +02:00
c07ab0e029
prevent crash when unable to access widgetproviderinfo 2025-05-24 13:31:00 +02:00
Luke Wass
a56cc772f7 Add visual cues and interactive styling to the settings fragment 2025-05-20 11:58:12 -05:00
7783d26d4c
Merge pull request #179 from wassupluke/widget-list-spacing
Some checks failed
Android CI / build (push) Has been cancelled
Improve widget list layout
2025-05-20 12:32:41 +00:00
Luke Wass
ba3255d9ec Improve widget list layout 2025-05-19 16:34:56 -05:00
60 changed files with 1158 additions and 394 deletions

View file

@ -28,7 +28,7 @@ import kotlinx.coroutines.launch
import kotlin.system.exitProcess
const val APP_WIDGET_HOST_ID = 42;
const val APP_WIDGET_HOST_ID = 42
class Application : android.app.Application() {

View file

@ -1,7 +1,6 @@
package de.jrpie.android.launcher.actions
import android.content.Context
import android.hardware.camera2.CameraAccessException
import android.hardware.camera2.CameraCharacteristics
import android.hardware.camera2.CameraManager
import android.os.Build

View file

@ -1,5 +1,6 @@
package de.jrpie.android.launcher.actions
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.graphics.Rect
@ -25,11 +26,18 @@ class WidgetPanelAction(val widgetPanelId: Int) : Action {
override fun invoke(context: Context, rect: Rect?): Boolean {
if (WidgetPanel.byId(widgetPanelId) == null) {
if (context is WidgetPanelActivity) {
if (context.widgetPanelId == widgetPanelId) {
context.finish()
return true
}
}
if (WidgetPanel.byId(this.widgetPanelId) == null) {
Toast.makeText(context, R.string.alert_widget_panel_not_found, Toast.LENGTH_LONG).show()
} else {
context.startActivity(Intent(context, WidgetPanelActivity::class.java).also {
it.putExtra(EXTRA_PANEL_ID, widgetPanelId)
it.putExtra(EXTRA_PANEL_ID, this.widgetPanelId)
})
}
return true

View file

@ -6,7 +6,6 @@ import android.widget.Button
import androidx.appcompat.app.AlertDialog
import de.jrpie.android.launcher.BuildConfig
import de.jrpie.android.launcher.R
import de.jrpie.android.launcher.actions.lock.LauncherAccessibilityService
import de.jrpie.android.launcher.preferences.LauncherPreferences

View file

@ -2,7 +2,6 @@ package de.jrpie.android.launcher.preferences
import android.content.Context
import android.util.Log
import de.jrpie.android.launcher.Application
import de.jrpie.android.launcher.BuildConfig
import de.jrpie.android.launcher.actions.Action
import de.jrpie.android.launcher.apps.AbstractAppInfo
@ -21,8 +20,8 @@ import de.jrpie.android.launcher.widgets.ClockWidget
import de.jrpie.android.launcher.widgets.DebugInfoWidget
import de.jrpie.android.launcher.widgets.WidgetPanel
import de.jrpie.android.launcher.widgets.WidgetPosition
import de.jrpie.android.launcher.widgets.deleteAllWidgets
import de.jrpie.android.launcher.widgets.generateInternalId
import de.jrpie.android.launcher.widgets.getAppWidgetHost
/* Current version of the structure of preferences.
* Increase when breaking changes are introduced and write an appropriate case in
@ -92,7 +91,7 @@ fun resetPreferences(context: Context) {
Log.i(TAG, "Resetting preferences")
LauncherPreferences.clear()
LauncherPreferences.internal().versionCode(PREFERENCE_VERSION)
deleteAllWidgets(context)
context.getAppWidgetHost().deleteHost()
LauncherPreferences.widgets().widgets(
setOf(

View file

@ -1,9 +1,7 @@
package de.jrpie.android.launcher.preferences.legacy
import android.content.Context
import de.jrpie.android.launcher.Application
import de.jrpie.android.launcher.preferences.LauncherPreferences
import de.jrpie.android.launcher.preferences.PREFERENCE_VERSION
import de.jrpie.android.launcher.widgets.ClockWidget
import de.jrpie.android.launcher.widgets.WidgetPanel
import de.jrpie.android.launcher.widgets.WidgetPosition

View file

@ -1,16 +1,9 @@
package de.jrpie.android.launcher.ui
import android.annotation.SuppressLint
import android.app.Activity
import android.content.SharedPreferences
import android.content.res.Configuration
import android.content.res.Resources
import android.os.Build
import android.os.Bundle
import android.view.KeyEvent
import android.view.MotionEvent
import android.view.View
import android.window.OnBackInvokedDispatcher
import de.jrpie.android.launcher.Application
import de.jrpie.android.launcher.actions.Action
import de.jrpie.android.launcher.actions.Gesture
@ -19,6 +12,7 @@ import de.jrpie.android.launcher.databinding.ActivityHomeBinding
import de.jrpie.android.launcher.openTutorial
import de.jrpie.android.launcher.preferences.LauncherPreferences
import de.jrpie.android.launcher.ui.tutorial.TutorialActivity
import de.jrpie.android.launcher.ui.util.LauncherGestureActivity
/**
* [HomeActivity] is the actual application Launcher,
@ -32,10 +26,9 @@ import de.jrpie.android.launcher.ui.tutorial.TutorialActivity
* - Setting global variables (preferences etc.)
* - Opening the [TutorialActivity] on new installations
*/
class HomeActivity : UIObject, Activity() {
class HomeActivity : UIObject, LauncherGestureActivity() {
private lateinit var binding: ActivityHomeBinding
private var touchGestureDetector: TouchGestureDetector? = null
private var sharedPreferencesListener =
SharedPreferences.OnSharedPreferenceChangeListener { _, prefKey ->
@ -54,35 +47,21 @@ class HomeActivity : UIObject, Activity() {
}
override fun onCreate(savedInstanceState: Bundle?) {
super<Activity>.onCreate(savedInstanceState)
super<LauncherGestureActivity>.onCreate(savedInstanceState)
super<UIObject>.onCreate()
// Initialise layout
binding = ActivityHomeBinding.inflate(layoutInflater)
setContentView(binding.root)
// Handle back key / gesture on Android 13+, cf. onKeyDown()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
onBackInvokedDispatcher.registerOnBackInvokedCallback(
OnBackInvokedDispatcher.PRIORITY_OVERLAY
) {
handleBack()
}
}
binding.buttonFallbackSettings.setOnClickListener {
LauncherAction.SETTINGS.invoke(this)
}
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
touchGestureDetector?.updateScreenSize(windowManager)
}
override fun onStart() {
super<Activity>.onStart()
super<LauncherGestureActivity>.onStart()
super<UIObject>.onStart()
// If the tutorial was not finished, start it
@ -133,82 +112,30 @@ class HomeActivity : UIObject, Activity() {
override fun onResume() {
super.onResume()
/* This should be initialized in onCreate()
However on some devices there seems to be a bug where the touchGestureDetector
is not working properly after resuming the app.
Reinitializing the touchGestureDetector every time the app is resumed might help to fix that.
(see issue #138)
*/
touchGestureDetector = TouchGestureDetector(
this, 0, 0,
LauncherPreferences.enabled_gestures().edgeSwipeEdgeWidth() / 100f
).also {
it.updateScreenSize(windowManager)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
binding.root.setOnApplyWindowInsetsListener { _, windowInsets ->
@Suppress("deprecation") // required to support API 29
val insets = windowInsets.systemGestureInsets
touchGestureDetector?.setSystemGestureInsets(insets)
windowInsets
}
}
updateSettingsFallbackButtonVisibility()
binding.homeWidgetContainer.updateWidgets(this@HomeActivity,
LauncherPreferences.widgets().widgets()
)
(application as Application).appWidgetHost.startListening()
}
override fun onDestroy() {
LauncherPreferences.getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(sharedPreferencesListener)
super.onDestroy()
}
@SuppressLint("GestureBackNavigation")
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
when (keyCode) {
KeyEvent.KEYCODE_BACK -> {
// Only used pre Android 13, cf. onBackInvokedDispatcher
handleBack()
}
KeyEvent.KEYCODE_VOLUME_UP -> {
if (Action.forGesture(Gesture.VOLUME_UP) == LauncherAction.VOLUME_UP) {
// Let the OS handle the key event. This works better with some custom ROMs
// and apps like Samsung Sound Assistant.
return false
}
Gesture.VOLUME_UP(this)
}
KeyEvent.KEYCODE_VOLUME_DOWN -> {
if (Action.forGesture(Gesture.VOLUME_DOWN) == LauncherAction.VOLUME_DOWN) {
// see above
return false
}
Gesture.VOLUME_DOWN(this)
}
}
return true
}
override fun onTouchEvent(event: MotionEvent): Boolean {
touchGestureDetector?.onTouchEvent(event)
return true
}
private fun handleBack() {
override fun handleBack() {
Gesture.BACK(this)
}
override fun getRootView(): View {
return binding.root
}
override fun isHomeScreen(): Boolean {
return true
}

View file

@ -1,7 +1,6 @@
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
@ -45,7 +44,7 @@ class PinShortcutActivity : AppCompatActivity(), UIObject {
binding = ActivityPinShortcutBinding.inflate(layoutInflater)
setContentView(binding.root)
val launcherApps = getSystemService(Service.LAUNCHER_APPS_SERVICE) as LauncherApps
val launcherApps = getSystemService(LAUNCHER_APPS_SERVICE) as LauncherApps
val request = launcherApps.getPinItemRequest(intent)
this.request = request
@ -56,7 +55,7 @@ class PinShortcutActivity : AppCompatActivity(), UIObject {
if (request.requestType == PinItemRequest.REQUEST_TYPE_APPWIDGET) {
// TODO
// TODO handle app widgets
request.getAppWidgetProviderInfo(this)
// startActivity()
finish()

View file

@ -17,6 +17,7 @@ import kotlin.math.max
import kotlin.math.min
import kotlin.math.tan
@Suppress("PrivatePropertyName")
class TouchGestureDetector(
private val context: Context,
var width: Int,
@ -34,13 +35,13 @@ class TouchGestureDetector(
private val MIN_TRIANGLE_HEIGHT = 250
private val longPressHandler = Handler(Looper.getMainLooper())
private var systemGestureInsetTop = 100
private var systemGestureInsetBottom = 0
private var systemGestureInsetLeft = 0
private var systemGestureInsetRight = 0
private val longPressHandler = Handler(Looper.getMainLooper())
data class Vector(val x: Float, val y: Float) {
fun absSquared(): Float {

View file

@ -237,9 +237,4 @@ class AppsRecyclerAdapter(
appFilter.favoritesVisibility = v
updateAppsList()
}
fun setHiddenAppsVisibility(v: AppFilter.Companion.AppSetVisibility) {
appFilter.hiddenVisibility = v
updateAppsList()
}
}

View file

@ -96,7 +96,6 @@ class ListFragmentApps : Fragment(), UIObject {
if (LauncherPreferences.functionality().searchAutoCloseKeyboard()) {
addOnScrollListener(object : RecyclerView.OnScrollListener() {
var totalDy: Int = 0
var threshold = (resources.displayMetrics.density * 100).toInt()
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
totalDy += dy

View file

@ -79,6 +79,9 @@ class SettingsFragmentMeta : Fragment(), UIObject {
// view code
bindURL(binding.settingsMetaButtonViewCode, R.string.settings_meta_link_github)
// view documentation
bindURL(binding.settingsMetaButtonViewDocs, R.string.settings_meta_link_docs)
// report a bug
binding.settingsMetaButtonReportBug.setOnClickListener {
val deviceInfo = getDeviceInfo()

View file

@ -5,7 +5,6 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import de.jrpie.android.launcher.BuildConfig.VERSION_CODE
import de.jrpie.android.launcher.databinding.Tutorial5FinishBinding
import de.jrpie.android.launcher.preferences.LauncherPreferences
import de.jrpie.android.launcher.requestNotificationPermission

View file

@ -0,0 +1,104 @@
package de.jrpie.android.launcher.ui.util
import android.annotation.SuppressLint
import android.app.Activity
import android.content.res.Configuration
import android.os.Build
import android.os.Bundle
import android.view.KeyEvent
import android.view.MotionEvent
import android.view.View
import android.window.OnBackInvokedDispatcher
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.preferences.LauncherPreferences
import de.jrpie.android.launcher.ui.TouchGestureDetector
/**
* An activity with a [TouchGestureDetector] as well as handling of volume and back keys set up.
*/
abstract class LauncherGestureActivity: Activity() {
protected var touchGestureDetector: TouchGestureDetector? = null
override fun onTouchEvent(event: MotionEvent): Boolean {
touchGestureDetector?.onTouchEvent(event)
return true
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Handle back key / gesture on Android 13+, cf. onKeyDown()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
onBackInvokedDispatcher.registerOnBackInvokedCallback(
OnBackInvokedDispatcher.PRIORITY_OVERLAY
) {
handleBack()
}
}
}
override fun onResume() {
super.onResume()
/* This should be initialized in onCreate()
However on some devices there seems to be a bug where the touchGestureDetector
is not working properly after resuming the app.
Reinitializing the touchGestureDetector every time the app is resumed might help to fix that.
(see issue #138)
*/
touchGestureDetector = TouchGestureDetector(
this, 0, 0,
LauncherPreferences.enabled_gestures().edgeSwipeEdgeWidth() / 100f
).also {
it.updateScreenSize(windowManager)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
getRootView()?.setOnApplyWindowInsetsListener { _, windowInsets ->
@Suppress("deprecation") // required to support API 29
val insets = windowInsets.systemGestureInsets
touchGestureDetector?.setSystemGestureInsets(insets)
windowInsets
}
}
}
@SuppressLint("GestureBackNavigation")
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
when (keyCode) {
KeyEvent.KEYCODE_BACK -> {
// Only used pre Android 13, cf. onBackInvokedDispatcher
handleBack()
}
KeyEvent.KEYCODE_VOLUME_UP -> {
if (Action.forGesture(Gesture.VOLUME_UP) == LauncherAction.VOLUME_UP) {
// Let the OS handle the key event. This works better with some custom ROMs
// and apps like Samsung Sound Assistant.
return false
}
Gesture.VOLUME_UP(this)
}
KeyEvent.KEYCODE_VOLUME_DOWN -> {
if (Action.forGesture(Gesture.VOLUME_DOWN) == LauncherAction.VOLUME_DOWN) {
// see above
return false
}
Gesture.VOLUME_DOWN(this)
}
}
return true
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
touchGestureDetector?.updateScreenSize(windowManager)
}
protected abstract fun getRootView(): View?
protected abstract fun handleBack()
}

View file

@ -8,9 +8,11 @@ import androidx.core.view.isVisible
import de.jrpie.android.launcher.actions.Gesture
import de.jrpie.android.launcher.databinding.WidgetClockBinding
import de.jrpie.android.launcher.preferences.LauncherPreferences
import de.jrpie.android.launcher.widgets.WidgetPanel
import java.util.Locale
class ClockView(context: Context, attrs: AttributeSet? = null, val appWidgetId: Int): ConstraintLayout(context, attrs) {
class ClockView(context: Context, attrs: AttributeSet? = null, val appWidgetId: Int, val panelId: Int): ConstraintLayout(context, attrs) {
constructor(context: Context, attrs: AttributeSet?): this(context, attrs, WidgetPanel.HOME.id, -1)
val binding: WidgetClockBinding = WidgetClockBinding.inflate(LayoutInflater.from(context), this, true)
init {
@ -57,7 +59,7 @@ class ClockView(context: Context, attrs: AttributeSet? = null, val appWidgetId:
binding.clockUpperView.format12Hour = upperFormat
}
fun setOnClicks() {
private fun setOnClicks() {
binding.clockUpperView.setOnClickListener {
if (LauncherPreferences.clock().flipDateTime()) {
Gesture.TIME(context)
@ -74,7 +76,4 @@ class ClockView(context: Context, attrs: AttributeSet? = null, val appWidgetId:
}
}
}
}

View file

@ -61,7 +61,7 @@ open class WidgetContainerView(
it.value.y + it.value.height
).contains(position) == true
}.any {
Widget.byId(context, it.key)?.allowInteraction == false
Widget.byId(it.key)?.allowInteraction == false
}
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {

View file

@ -1,27 +1,31 @@
package de.jrpie.android.launcher.ui.widgets
import android.app.Activity
import android.content.res.Resources
import android.os.Bundle
import android.view.View
import androidx.core.view.ViewCompat
import de.jrpie.android.launcher.Application
import de.jrpie.android.launcher.R
import de.jrpie.android.launcher.databinding.ActivityWidgetPanelBinding
import de.jrpie.android.launcher.preferences.LauncherPreferences
import de.jrpie.android.launcher.ui.UIObject
import de.jrpie.android.launcher.ui.util.LauncherGestureActivity
import de.jrpie.android.launcher.ui.widgets.manage.EXTRA_PANEL_ID
import de.jrpie.android.launcher.widgets.WidgetPanel
class WidgetPanelActivity : Activity(), UIObject {
lateinit var binding: ActivityWidgetPanelBinding
private var widgetPanelId: Int = WidgetPanel.HOME.id
class WidgetPanelActivity : LauncherGestureActivity(), UIObject {
var binding: ActivityWidgetPanelBinding? = null
var widgetPanelId: Int = WidgetPanel.HOME.id
override fun onCreate(savedInstanceState: Bundle?) {
super<Activity>.onCreate(savedInstanceState)
super<LauncherGestureActivity>.onCreate(savedInstanceState)
super<UIObject>.onCreate()
widgetPanelId = intent.getIntExtra(EXTRA_PANEL_ID, WidgetPanel.HOME.id)
val binding = ActivityWidgetPanelBinding.inflate(layoutInflater)
setContentView(binding.root)
widgetPanelId = intent.getIntExtra(EXTRA_PANEL_ID, WidgetPanel.HOME.id)
// The widget container should extend below the status and navigation bars,
// so let's set an empty WindowInsetsListener to prevent it from being moved.
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { _, windowInsets ->
@ -56,9 +60,8 @@ class WidgetPanelActivity : Activity(), UIObject {
}
override fun onStart() {
super<Activity>.onStart()
super<LauncherGestureActivity>.onStart()
super<UIObject>.onStart()
}
override fun onPause() {
@ -76,6 +79,14 @@ class WidgetPanelActivity : Activity(), UIObject {
(application as Application).appWidgetHost.startListening()
}
override fun getRootView(): View? {
return binding?.root
}
override fun handleBack() {
finish()
}
override fun isHomeScreen(): Boolean {
return true
}

View file

@ -9,7 +9,6 @@ import android.widget.EditText
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import de.jrpie.android.launcher.Application
import de.jrpie.android.launcher.R
import de.jrpie.android.launcher.databinding.ActivityManageWidgetPanelsBinding
import de.jrpie.android.launcher.preferences.LauncherPreferences

View file

@ -5,7 +5,6 @@ import android.appwidget.AppWidgetManager
import android.content.Intent
import android.content.SharedPreferences
import android.content.res.Resources
import android.graphics.Rect
import android.os.Bundle
import android.util.Log
import android.view.ViewGroup
@ -21,7 +20,6 @@ import de.jrpie.android.launcher.widgets.GRID_SIZE
import de.jrpie.android.launcher.widgets.WidgetPanel
import de.jrpie.android.launcher.widgets.WidgetPosition
import kotlin.math.max
import kotlin.math.min
import kotlin.math.roundToInt
@ -132,7 +130,6 @@ class ManageWidgetsActivity : UIObject, Activity() {
private fun selectWidget() {
val appWidgetHost = (application as Application).appWidgetHost
startActivityForResult(
Intent(this, SelectWidgetActivity::class.java).also {
it.putExtra(
@ -147,13 +144,17 @@ class ManageWidgetsActivity : UIObject, Activity() {
private fun createWidget(data: Intent) {
Log.i("Launcher", "creating widget")
val appWidgetManager = (application as Application).appWidgetManager
val appWidgetHost = (application as Application).appWidgetHost
val appWidgetId = data.extras?.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID) ?: return
val provider = appWidgetManager.getAppWidgetInfo(appWidgetId)
val display = windowManager.defaultDisplay
val widgetInfo = appWidgetManager.getAppWidgetInfo(appWidgetId)
if (widgetInfo == null) {
Log.w("Launcher", "can't access widget")
appWidgetHost.deleteAppWidgetId(appWidgetId)
return
}
val position = WidgetPosition.findFreeSpace(
WidgetPanel.byId(panelId),
@ -161,7 +162,7 @@ class ManageWidgetsActivity : UIObject, Activity() {
max(3, (GRID_SIZE * (widgetInfo.minHeight) / display.height.toFloat()).roundToInt())
)
val widget = AppWidget(appWidgetId, position, panelId, provider)
val widget = AppWidget(appWidgetId, position, panelId, widgetInfo)
LauncherPreferences.widgets().widgets(
(LauncherPreferences.widgets().widgets() ?: HashSet()).also {
it.add(widget)

View file

@ -31,19 +31,19 @@ class WidgetManagerView(widgetPanelId: Int, context: Context, attrs: AttributeSe
WidgetContainerView(widgetPanelId, context, attrs) {
constructor(context: Context, attrs: AttributeSet?) : this(WidgetPanel.HOME.id, context, attrs)
val TOUCH_SLOP: Int
val TOUCH_SLOP_SQUARE: Int
val LONG_PRESS_TIMEOUT: Long
val touchSlop: Int
val touchSlopSquare: Int
val longPressTimeout: Long
private var overlayViewById = HashMap<Int, WidgetOverlayView>()
init {
val configuration = ViewConfiguration.get(context)
TOUCH_SLOP = configuration.scaledTouchSlop
TOUCH_SLOP_SQUARE = TOUCH_SLOP * TOUCH_SLOP
touchSlop = configuration.scaledTouchSlop
touchSlopSquare = touchSlop * touchSlop
LONG_PRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout().toLong()
longPressTimeout = ViewConfiguration.getLongPressTimeout().toLong()
}
@ -127,14 +127,14 @@ class WidgetManagerView(widgetPanelId: Int, context: Context, attrs: AttributeSe
view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
endInteraction()
}
}, LONG_PRESS_TIMEOUT)
}, longPressTimeout)
}
if (event.actionMasked == MotionEvent.ACTION_MOVE ||
event.actionMasked == MotionEvent.ACTION_UP
) {
val distanceX = event.x - (currentGestureStart?.x ?: return true)
val distanceY = event.y - (currentGestureStart?.y ?: return true)
if (distanceX * distanceX + distanceY * distanceY > TOUCH_SLOP_SQUARE) {
if (distanceX * distanceX + distanceY * distanceY > touchSlopSquare) {
longPressHandler.removeCallbacksAndMessages(null)
}
val view = selectedWidgetOverlayView ?: return true
@ -160,9 +160,8 @@ class WidgetManagerView(widgetPanelId: Int, context: Context, attrs: AttributeSe
}
if (event.actionMasked == MotionEvent.ACTION_UP) {
longPressHandler.removeCallbacksAndMessages(null)
val id = selectedWidgetOverlayView?.widgetId ?: return true
val widget = Widget.byId(context, id) ?: return true
val widget = Widget.byId(id) ?: return true
widget.position = newPosition
endInteraction()
updateWidget(widget)
@ -176,8 +175,16 @@ class WidgetManagerView(widgetPanelId: Int, context: Context, attrs: AttributeSe
}
private fun endInteraction() {
startWidgetPosition = null
selectedWidgetOverlayView?.mode = null
synchronized(this) {
longPressHandler.removeCallbacksAndMessages(null)
startWidgetPosition = null
selectedWidgetOverlayView?.mode = null
}
}
override fun onDetachedFromWindow() {
endInteraction()
super.onDetachedFromWindow()
}
override fun updateWidgets(activity: Activity, widgets: Collection<Widget>?) {

View file

@ -54,26 +54,18 @@ class WidgetOverlayView : ViewGroup {
var widgetId: Int = -1
set(newId) {
field = newId
preview = Widget.byId(context, widgetId)?.getPreview(context)
preview = Widget.byId(widgetId)?.getPreview(context)
}
constructor(context: Context) : super(context) {
init(null, 0)
}
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
init(attrs, 0)
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(
context,
attrs,
defStyle
) {
init(attrs, defStyle)
}
private fun init(attrs: AttributeSet?, defStyle: Int) { }
)
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
@ -101,13 +93,13 @@ class WidgetOverlayView : ViewGroup {
}
fun showPopupMenu() {
val widget = Widget.byId(context, widgetId)?: return
val widget = Widget.byId(widgetId)?: return
val menu = PopupMenu(context, popupAnchor)
menu.menu.let {
it.add(
context.getString(R.string.widget_menu_remove)
).setOnMenuItemClickListener { _ ->
Widget.byId(context, widgetId)?.delete(context)
Widget.byId(widgetId)?.delete(context)
return@setOnMenuItemClickListener true
}
it.add(
@ -126,7 +118,7 @@ class WidgetOverlayView : ViewGroup {
}
fun getHandles(): List<Handle> {
return listOf<Handle>(
return listOf(
Handle(WidgetManagerView.EditMode.TOP,
Rect(HANDLE_EDGE_SIZE, 0, width - HANDLE_EDGE_SIZE, HANDLE_SIZE)),
Handle(WidgetManagerView.EditMode.BOTTOM,

View file

@ -18,8 +18,8 @@ class ClockWidget(
override var allowInteraction: Boolean = true
) : Widget() {
override fun createView(activity: Activity): View? {
return ClockView(activity, null, id)
override fun createView(activity: Activity): View {
return ClockView(activity, null, id, panelId)
}
override fun findView(views: Sequence<View>): ClockView? {

View file

@ -38,10 +38,6 @@ sealed class Widget {
)
}
fun getPanel(): WidgetPanel? {
return WidgetPanel.byId(panelId)
}
override fun hashCode(): Int {
return id
}
@ -57,9 +53,9 @@ sealed class Widget {
fun deserialize(serialized: String): Widget {
return Json.decodeFromString(serialized)
}
fun byId(context: Context, id: Int): Widget? {
fun byId(id: Int): Widget? {
// TODO: do some caching
return LauncherPreferences.widgets().widgets().firstOrNull() {
return LauncherPreferences.widgets().widgets().firstOrNull {
it.id == id
}
}

View file

@ -15,11 +15,6 @@ import de.jrpie.android.launcher.Application
import de.jrpie.android.launcher.preferences.LauncherPreferences
import kotlin.math.min
fun deleteAllWidgets(context: Context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.getAppWidgetHost().appWidgetIds.forEach { AppWidget(it).delete(context) }
}
}
/**
* Tries to bind [providerInfo] to the id [id].
@ -60,8 +55,8 @@ fun getAppWidgetProviders( context: Context ): List<LauncherWidgetProvider> {
(context.getSystemService(Service.USER_SERVICE) as UserManager).userProfiles
}
list.addAll(
profiles.map {
appWidgetManager.getInstalledProvidersForProfile(it)
profiles.map { profile ->
appWidgetManager.getInstalledProvidersForProfile(profile)
.map { LauncherAppWidgetProvider(it) }
}.flatten()
)

View file

@ -40,6 +40,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:contentDescription="@string/content_description_close"
android:gravity="center"
android:includeFontPadding="true"
android:paddingLeft="16sp"
@ -64,6 +65,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:contentDescription="@string/content_description_add_widget_panel"
android:src="@drawable/baseline_add_24"
app:layout_anchor="@+id/manage_widget_panels_recycler"
app:layout_anchorGravity="end|bottom"

View file

@ -20,6 +20,7 @@
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:clickable="true"
android:contentDescription="@string/content_description_add_widget"
android:focusable="true"
android:src="@drawable/baseline_add_24"
app:layout_constraintBottom_toBottomOf="parent"

View file

@ -44,6 +44,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:contentDescription="@string/content_description_close"
android:gravity="center"
android:includeFontPadding="true"
android:paddingLeft="16sp"

View file

@ -45,6 +45,7 @@
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:contentDescription="@string/content_description_close"
android:gravity="center"
android:includeFontPadding="true"
android:paddingLeft="16sp"

View file

@ -62,6 +62,7 @@
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:contentDescription="@string/content_description_close"
android:gravity="center"
android:includeFontPadding="true"
android:paddingLeft="16sp"
@ -72,6 +73,7 @@
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/list_lock"
android:contentDescription="@string/content_description_lock"
android:visibility="gone"
tools:visibility="visible"
android:layout_width="wrap_content"
@ -91,7 +93,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabIndicatorColor="?attr/colorAccent"
custom:tabTextColor="?attr/android:textColor" />
custom:tabTextColor="?attr/android:textColor"
tools:ignore="SpeakableTextPresentCheck" />
</com.google.android.material.appbar.AppBarLayout>
@ -110,6 +113,7 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/list_appbar"
app:layout_constraintVertical_bias="0.0"
custom:layout_behavior="@string/appbar_scrolling_view_behavior" />
custom:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:ignore="SpeakableTextPresentCheck" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -11,6 +11,7 @@
android:id="@+id/list_other_row_icon"
android:layout_width="35sp"
android:layout_height="35sp"
android:contentDescription="@null"
android:gravity="center"
android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="parent"

View file

@ -6,55 +6,96 @@
android:id="@+id/list_apps_row_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15sp">
android:layout_marginHorizontal="30sp">
<ImageView
android:id="@+id/list_widgets_row_icon"
android:layout_width="40dp"
android:layout_height="40dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:src="@mipmap/ic_launcher_round"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/list_widgets_row_name"
android:layout_width="0dp"
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10sp"
android:layout_marginEnd="10sp"
android:gravity="start"
android:text=""
android:textSize="20sp"
tools:text="some widget"
app:layout_constraintStart_toEndOf="@id/list_widgets_row_icon"
app:cardBackgroundColor="?cardBackgroundColor"
app:cardElevation="8dp"
app:cardCornerRadius="12dp"
app:cardUseCompatPadding="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/list_widgets_row_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="10sp"
android:gravity="start"
android:text=""
android:textSize="12sp"
app:layout_constraintStart_toStartOf="@+id/list_widgets_row_name"
app:layout_constraintTop_toBottomOf="@+id/list_widgets_row_name"
tools:text="a longer description of the widget" />
<ImageView
android:id="@+id/list_widgets_row_preview"
android:layout_width="0dp"
android:maxHeight="100dp"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:layout_height="100dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/list_widgets_row_description"
tools:src="@mipmap/ic_launcher_round"
tools:ignore="ContentDescription" />
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_margin="10dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/icon_title_description_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/list_widgets_row_icon"
android:layout_width="40dp"
android:layout_height="40dp"
tools:src="@mipmap/ic_launcher_round"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/list_widgets_row_name"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_marginStart="10sp"
android:layout_marginEnd="10sp"
android:text=""
style="@style/TextAppearance.Material3.HeadlineSmall"
tools:text="Some Widget"
app:layout_constraintStart_toEndOf="@id/list_widgets_row_icon"
app:layout_constraintTop_toTopOf="@id/list_widgets_row_icon"
app:layout_constraintBottom_toBottomOf="@id/list_widgets_row_icon"/>
<TextView
android:id="@+id/list_widgets_row_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text=""
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/list_widgets_row_name"
app:layout_constraintTop_toBottomOf="@+id/list_widgets_row_name"
tools:text="A longer description of the widget that may take up multiple lines." />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
app:layout_constraintTop_toBottomOf="@id/icon_title_description_container">
<ImageView
android:id="@+id/list_widgets_row_preview"
android:layout_width="match_parent"
android:layout_height="100dp"
android:maxHeight="100dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/list_widgets_row_icon"
tools:src="@mipmap/ic_launcher_round"
tools:ignore="ContentDescription,NotSibling" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -20,6 +20,22 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/settings_system"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:contentDescription="@string/settings"
android:gravity="center"
android:includeFontPadding="true"
android:paddingLeft="16sp"
android:paddingRight="16sp"
android:src="@drawable/baseline_settings_applications_24"
custom:layout_constraintBottom_toBottomOf="parent"
custom:layout_constraintStart_toStartOf="parent"
custom:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/settings_heading"
android:layout_width="wrap_content"
@ -40,6 +56,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:contentDescription="@string/content_description_close"
android:gravity="center"
android:includeFontPadding="true"
android:paddingLeft="16sp"
@ -48,28 +65,14 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/settings_system"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:gravity="center"
android:includeFontPadding="true"
android:paddingLeft="16sp"
android:paddingRight="16sp"
android:src="@drawable/baseline_settings_applications_24"
custom:layout_constraintBottom_toBottomOf="parent"
custom:layout_constraintStart_toStartOf="parent"
custom:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.tabs.TabLayout
android:id="@+id/settings_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabTextColor="?attr/android:textColor" />
app:tabTextColor="?attr/android:textColor"
tools:ignore="SpeakableTextPresentCheck" />
</com.google.android.material.appbar.AppBarLayout>

View file

@ -68,6 +68,7 @@
android:id="@+id/settings_actions_row_remove"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/content_description_settings_actions_row_button_remove"
android:padding="8sp"
android:src="@drawable/baseline_close_24"
app:layout_constraintBottom_toBottomOf="parent"

View file

@ -41,6 +41,13 @@
android:text="@string/settings_meta_view_code"
android:textAllCaps="false" />
<Button
android:id="@+id/settings_meta_button_view_docs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/settings_meta_view_docs"
android:textAllCaps="false" />
<Button
android:id="@+id/settings_meta_button_report_bug"
android:layout_width="match_parent"

View file

@ -26,6 +26,7 @@
android:id="@+id/tutorial_button_back"
android:layout_width="50dp"
android:layout_height="50dp"
android:contentDescription="@string/content_description_navigate_back"
android:gravity="center"
android:alpha="0.5"
android:src="@drawable/baseline_navigate_before_24"
@ -43,12 +44,14 @@
app:layout_constraintStart_toEndOf="@+id/tutorial_button_back"
app:tabBackground="@drawable/tutorial_tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp" />
app:tabIndicatorHeight="0dp"
tools:ignore="SpeakableTextPresentCheck" />
<ImageView
android:id="@+id/tutorial_button_next"
android:layout_width="50dp"
android:layout_height="50dp"
android:contentDescription="@string/content_description_navigate_next"
android:gravity="center"
android:src="@drawable/baseline_navigate_next_24"
app:layout_constraintBottom_toBottomOf="parent"

View file

@ -33,17 +33,27 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tutorial_setup_title" />
<androidx.fragment.app.FragmentContainerView
android:id="@+id/tutorial_setup_actions_rview_fragment"
android:name="de.jrpie.android.launcher.ui.settings.actions.SettingsFragmentActionsRecycler"
android:layout_width="0dp"
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="32dp"
android:layout_marginBottom="16dp"
app:cardElevation="8dp"
app:cardBackgroundColor="?cardBackgroundColor"
app:cardCornerRadius="12dp"
app:cardUseCompatPadding="true"
app:layout_constraintTop_toBottomOf="@id/tutorial_setup_subtitle"
app:layout_constraintBottom_toTopOf="@id/tutorial_setup_text_bottom"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tutorial_setup_subtitle" />
app:layout_constraintEnd_toEndOf="parent">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/tutorial_setup_actions_rview_fragment"
android:name="de.jrpie.android.launcher.ui.settings.actions.SettingsFragmentActionsRecycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginVertical="4dp"
android:layout_marginStart="10dp"/>
</androidx.cardview.widget.CardView>
<TextView
android:id="@+id/tutorial_setup_text_bottom"

View file

@ -95,9 +95,9 @@
<string name="settings_display_hide_status_bar">إخفِ شريط الحالة</string>
<string name="settings_display_rotate_screen">تدوير الشاشة</string>
<string name="settings_launcher_section_functionality">الوظائف</string>
<string name="settings_enabled_gestures_double_swipe">أوامر السحب بأصبعين</string>
<string name="settings_enabled_gestures_double_swipe">إيماءات التمرير المزدوج</string>
<string name="settings_enabled_gestures_double_swipe_summary">اسحب باستخدام أصبعين</string>
<string name="settings_enabled_gestures_edge_swipe">أوامر السحب من الحواف</string>
<string name="settings_enabled_gestures_edge_swipe">إيماءات تمرير الحافة</string>
<string name="settings_enabled_gestures_edge_swipe_edge_width">عرض الحواف</string>
<string name="settings_functionality_auto_launch">إظهار نتائج البحث</string>
<string name="settings_functionality_auto_launch_summary">اضغط مسافة لتعطيل هذه الميزة مؤقتًا</string>
@ -162,11 +162,11 @@
<string name="tutorial_concept_text_2">إنه برنامج مجاني (ترخيص MIT)!\nتأكد من مراجعة المستودع!</string>
<string name="tutorial_concept_label_version">النسخة</string>
<string name="tutorial_usage_title">الاستخدام</string>
<string name="tutorial_usage_text">تحتوي شاشتك الرئيسية على التاريخ والوقت المحليين. لا الهاء.</string>
<string name="tutorial_usage_text">تحتوي شاشة المنزل الخاصة بك على التاريخ والوقت المحليين. بدون أي مشتتات.</string>
<string name="tutorial_app_list_title">كل التطبيقات</string>
<string name="tutorial_app_list_text_2">بمجرد تطابق تطبيق واحد فقط، يتم تشغيله تلقائيًا.\nيمكن تعطيل ذلك عن طريق اضافة مساحة في بداية استعلام.</string>
<string name="tutorial_setup_title">الإعداد</string>
<string name="tutorial_setup_text">اخترنا بعض التطبيقات الافتراضية لك. يمكنك تغييرها الآن إذا كنت تريد:</string>
<string name="tutorial_setup_text">اخترنا لك بعض التطبيقات الافتراضية. يمكنك تغييرها الآن إذا كنت ترغب في ذلك:</string>
<string name="tutorial_setup_text_2">يمكنك أيضًا تغيير اختيارك لاحقًا.</string>
<string name="tutorial_finish_title">لنبدأ!</string>
<string name="tutorial_finish_button">ابدأ</string>
@ -235,7 +235,7 @@
<string name="settings_apps_hide_bound_apps">لا تظهر التطبيقات المرتبطة بإيماءة في قائمة التطبيقات</string>
<string name="list_other_list_favorites">درج التطبيقات المفضلة</string>
<string name="list_other_track_next">الموسيقى: التالي</string>
<string name="tutorial_concept_text">تم تصميم μlauncher ليكون فعال، وخالي من الهاء.\n\nلا يحتوي على أي إعلانات ولا يجمع أي بيانات.</string>
<string name="tutorial_concept_text">تم تصميم μLauncher ليكون فعالًا وخاليًا من مشتتات الانتباه.\n\nلا يحتوي على أي إعلانات ولا يجمع أي بيانات.</string>
<string name="tutorial_finish_text">أنت مستعد للبدء!\n\nآمل أن يكون هذا ذا قيمة كبيرة بالنسبة لك!\n\n- المطورين</string>
<string name="toast_private_space_default_home_screen">يجب أن يكون μlauncher الشاشة الرئيسية الافتراضية للوصول إلى مساحة خاصة.</string>
<string name="settings_gesture_description_left_bottom_edge">اسحب إلى اليسار من أسفل الشاشة</string>
@ -245,7 +245,7 @@
<string name="list_app_info">معلومات التطبيق</string>
<string name="list_app_favorite_add">أضف إلى المفضلة</string>
<string name="list_other_expand_notifications_panel">توسيع لوحة الاشعارات</string>
<string name="tutorial_app_list_text">يمكنك البحث بسرعة من خلال جميع التطبيقات في قائمة التطبيقات.\n\nاسحب لأعلى لفتح القائمة، أو ربطها بإيماءة ما.</string>
<string name="tutorial_app_list_text">يمكنك البحث بسرعة في جميع التطبيقات في قائمة التطبيقات.\n\nاسحب لأعلى لفتحها، أو اربطها بإيماءة مختلفة.</string>
<string name="alert_lock_screen_failed">خطأ: فشل في قفل الشاشة. (إذا قمت للتو بترقية التطبيق ، فحاول تعطيل خدمة الوصول وإعادة تمكينها في إعدادات الهاتف)</string>
<string name="settings_gesture_description_down_right_edge">اسحب إلى الأسفل من حافة الشاشة اليمنى</string>
<string name="settings_theme_font_item_serif_monospace">أحادي المسافة مذيل</string>
@ -257,7 +257,7 @@
<string name="dialog_report_bug_info">شكرا لك على المساعدة في تحسين μLauncher!\nيرجى إضافة المعلومات التالية إلى تقرير الأخطاء الخاص بك:</string>
<string name="settings_meta_contact">اتصل بالمطور الأصلي</string>
<string name="list_other_volume_down">اخفض الصوت</string>
<string name="tutorial_usage_text_2">يمكنك تشغيل أهم تطبيقاتك بوسطة إيماءات اللمس أو الضغط على الأزرار.</string>
<string name="tutorial_usage_text_2">يمكنك تشغيل أهم تطبيقاتك بإيماءات اللمس أو الضغط على الأزرار.</string>
<string name="settings_enabled_gestures_edge_swipe_summary">اسحب من حواف الشاشة</string>
<string name="toast_lock_screen_not_supported">خطأ: قفل الشاشة باستخدام إمكانية الوصول غير مدعوم على هذا الجهاز. الرجاء استخدام طريقة مسؤول الجهاز بدلاً من ذلك.</string>
<string name="accessibility_service_description">يتيح تعيين μlauncher كخدمة إمكانية الوصول قفل الشاشة وفتح قائمة التطبيقات الحديثة. يرجى ملاحظة أنه يتطلب كمية كبيرة من الأذونات. يجب ألا تمنح مثل هذه الأذونات باستخفاف لأي تطبيق. سوف يستخدم μlauncher خدمة إمكانية الوصول فقط لأداء الإجراءات التالية عند طلب المستخدم: * قفل شاشة * فتح التطبيقات الحديثة μlauncher لن يستخدم أبدًا خدمة إمكانية الوصول لجمع البيانات. يمكنك التحقق من شيفرة المصدر للتأكد. يرجى ملاحظة أنه يمكنك قفل الشاشة من خلال منح أذونات مسؤول الجهاز، لكنها لا تعمل مع بصمات الأصابع وفتح الوجه.</string>
@ -288,11 +288,13 @@
يمكنك تغيير اختيارك لاحقًا في الإعدادات.
]]></string>
<string name="widget_clock_description">الساعة الافتراضية لـ μLauncher</string>
<string name="dialog_select_widget_panel_info_no_panels">&lt;![CDATA[لم يتم العثور على لوحات عناصر واجهة المستخدم. يمكنك إنشاء لوحات الأدوات في الإعدادات &gt; المشغّل &gt; إدارة لوحات الأدوات.]].</string>
<string name="dialog_select_widget_panel_info_no_panels"><![CDATA[
لم يتم العثور على أي لوحات أدوات. يمكنك إنشاء لوحات أدوات في الإعدادات > المشغل > إدارة لوحات الأدوات.
]]></string>
<string name="select_widget_title">اختر الأداة</string>
<string name="widget_menu_remove">إزالة</string>
<string name="widget_menu_configure">تهيئة</string>
<string name="widget_menu_enable_interaction">Enable Interaction</string>
<string name="widget_menu_enable_interaction">تمكين التفاعل</string>
<string name="widget_menu_disable_interaction">تعطيل التفاعل</string>
<string name="widget_clock_label">ساعة</string>
<string name="manage_widget_panels_delete">حذف</string>
@ -305,12 +307,35 @@
<string name="alert_widget_panel_not_found">لم تعد لوحة الأدوات هذه موجودة.</string>
<string name="settings_launcher_section_widgets">الأدوات</string>
<plurals name="widget_panel_number_of_widgets">
<item quantity="zero">يحتوي على %d أداة.</item>
<item quantity="one">يحتوي على %d أداة.</item>
<item quantity="two">يحتوي على %d أدوات.</item>
<item quantity="few">يحتوي على %d أدوات.</item>
<item quantity="many">يحتوي على %d أداة.</item>
<item quantity="other"></item>
<item quantity="zero">يحتوي على %1$dأداة.</item>
<item quantity="one">يحتوي على %1$d أداة.</item>
<item quantity="two">يحتوي على %1$d أدوات.</item>
<item quantity="few">يحتوي على%1$d أدوات.</item>
<item quantity="many">يحتوي على %1$d أداة.</item>
<item quantity="other">يحتوي على%1$d أداة.</item>
</plurals>
<string name="settings_functionality_auto_close_keyboard">إغلاق لوحة المفاتيح عند التمرير</string>
<string name="crash_info"><![CDATA[
يبدو أن هناك خطأ ما، نعتذر عن ذلك!<br><br>
لأسباب تتعلق بالخصوصية، لا يتم جمع سجلات الأعطال تلقائيًا.<br>
ومع ذلك، فإن السجلات مفيدة جدًا لتصحيح الأخطاء، لذا سأكون ممتنًا جدًا إذا كان بإمكانك إرسال السجل المرفق عبر البريد
أو إنشاء تقرير عن الخطأ على GitHub.<br><br>
يرجى ملاحظة أن سجلات الأعطال قد تحتوي على <strong>معلومات حساسة</strong>، مثل اسم التطبيق الذي حاولت تشغيله.
يرجى <strong>حذف</strong> مثل هذه المعلومات قبل إرسال التقرير.
<h2>ماذا يمكنني أن أفعل الآن؟</h2>
إذا ظهر هذا الخطأ مرة أخرى، يمكنك تجربة عدة أشياء:
<ul>
<li>إيقاف μLauncher بالقوة</li>
<li>مسح بيانات μLauncher&#39;s (<strong>ستفقد إعداداتك!</strong>)</li>
<li>تثبيت إصدار أقدم (<a href="https://github.com/jrpie/Launcher/releases">GitHub</a>, <a href="https://f-droid.org/en/packages/de.jrpie.android.launcher">F-Droid</a>)</li>
</ul>
]]></string>
<string name="notification_crash_title">تعطل μLauncher</string>
<string name="notification_crash_explanation">آسف! انقر للحصول على مزيد من المعلومات.</string>
<string name="report_crash_button_copy">نسخ تقرير التعطل إلى الحافظة</string>
<string name="report_crash_button_mail">إرسال التقرير بالبريد</string>
<string name="report_crash_button_report">إنشاء تقرير خطأ على GitHub</string>
<string name="report_crash_title">تعطل μLauncher</string>
<string name="send_email">إرسال بريد إلكتروني</string>
<string name="notification_channel_crash">الأعطال ومعلومات التصحيح</string>
</resources>

View file

@ -312,4 +312,28 @@
<string name="settings_launcher_section_widgets">Widget</string>
<string name="dialog_select_widget_panel_title">Seleziona pannello widget</string>
<string name="dialog_select_widget_panel_info_no_panels"><![CDATA[Nessun pannello widget trovato. Puoi creare pannelli widget da Impostazioni > Launcher > Gestione Pannelli Widget.]]></string>
<string name="settings_meta_view_docs">Documentazione</string>
<string name="notification_crash_explanation">Scusa! Clicca per altre info.</string>
<string name="notification_crash_title">µLauncher è crashato</string>
<string name="report_crash_button_copy">Copia il rapporto del crash negli appunti</string>
<string name="report_crash_button_mail">Invia il rapporto per email</string>
<string name="report_crash_button_report">Crea un bug report in GitHub</string>
<string name="report_crash_title">µLauncher è crashato</string>
<string name="send_email">Invia email</string>
<string name="notification_channel_crash">Info su crash e debug</string>
<string name="crash_info"><![CDATA[
Sembra che qualcosa sia andato storto, mi scuso per questo!<br><br>
Per motivi di privacy, i log dei crash non sono raccolti automaticamente.<br>
Comunque i log sono molto utili per il debug, quindi ti sarei molto grato se potessi inviarmi i log per email
oppure aprire un bug report su github.<br><br>
Nota che i crash log potrebbero contenere <strong>informazioni sensibili</strong>, come il nome dell\'app che hai provato ad avviare.
Please <strong>redact</strong> such information before sending the report.
<h2>What can I do now?</h2>
If this bug appears again and again, you can try several things:
<ul>
<li>Force stop μLauncher</li>
<li>Clear μLauncher\'s storage (<strong>Your settings will be lost!</strong>)</li>
<li>Install an older version (<a href=\"https://github.com/jrpie/Launcher/releases\">GitHub</a>, <a href=\"https://f-droid.org/en/packages/de.jrpie.android.launcher\">F-Droid</a>)</li>
</ul>
]]></string>
</resources>

View file

@ -260,7 +260,7 @@
<string name="settings_gesture_swipe_v_reverse">V反向</string>
<string name="settings_gesture_swipe_larger_reverse"><![CDATA[>(反向)]]></string>
<string name="settings_gesture_swipe_smaller_reverse"><![CDATA[<(反向)]]></string>
<string name="settings_functionality_auto_launch_summary">启后将直接启动搜索所匹配到的应用,可以通过在搜索内容前添加空格来临时停用该功能。</string>
<string name="settings_functionality_auto_launch_summary">后将直接启动搜索所匹配到的应用,可以通过在搜索内容前添加空格来临时停用该功能。</string>
<string name="settings_list_layout">应用程序列表样式</string>
<string name="pin_shortcut_button_bind">绑定到手势</string>
<string name="list_other_track_play_pause">音乐:播放 / 暂停</string>
@ -287,7 +287,7 @@
<string name="settings_functionality_auto_close_keyboard">滚动应用程序列表时自动隐藏键盘</string>
<string name="settings_widgets_widgets">设置小部件</string>
<string name="widget_menu_remove">删除</string>
<string name="widget_menu_enable_interaction">启交互功能</string>
<string name="widget_menu_enable_interaction">交互功能</string>
<string name="widget_menu_disable_interaction">关闭交互功能</string>
<string name="widget_clock_label">时钟</string>
<string name="manage_widget_panels_delete">删除</string>
@ -303,4 +303,31 @@
<string name="widget_clock_description">μLauncher 默认时钟小部件</string>
<string name="select_widget_title">选择小部件</string>
<string name="settings_widgets_custom_panels">设置小部件面板</string>
<string name="dialog_ok">确认</string>
<plurals name="widget_panel_number_of_widgets">
<item quantity="other">包含 %1$d 个小部件。</item>
</plurals>
<string name="notification_crash_title">μLauncher 崩溃了</string>
<string name="notification_crash_explanation">抱歉!点击查看更多信息。</string>
<string name="report_crash_button_copy">复制崩溃报告到剪贴板</string>
<string name="report_crash_button_mail">通过 Email 发送报告</string>
<string name="report_crash_title">μLauncher 崩溃了</string>
<string name="report_crash_button_report">在 GitHub 上创建错误反馈</string>
<string name="send_email">发送 Email</string>
<string name="notification_channel_crash">崩溃和调试信息</string>
<string name="crash_info"><![CDATA[
发生了一些错误,非常抱歉!<br><br>
出于保护隐私的考量,默认不会记录崩溃日志。<br>
但是,日志对应用调试非常有帮助,若您原意,请将所附日志文件通过 Email 发送给我,
或在 GitHub 上创建错误报告,非常感谢!<br><br>
请注意,崩溃日志可能包含<strong>敏感信息</strong>,如,您尝试启动的应用名称。
因此,请在发送报告前,先将此类信息<strong>去除</strong>
<h2>我现在应该怎么做?</h2>
如果这个错误重复发生,您可以做如下尝试:
<ul>
<li>强行停止 μLauncher</li>
<li>清空 μLauncher 的存储空间(<strong>您的设置将被重置!</strong></li>
<li>安装旧版本(<a href=\"https://github.com/jrpie/Launcher/releases\">GitHub</a>, <a href=\"https://f-droid.org/en/packages/de.jrpie.android.launcher\">F-Droid</a></li>
</ul>
]]></string>
</resources>

View file

@ -11,9 +11,5 @@
<color name="lightTheme_background_color">#fff</color>
<color name="lightTheme_accent_color">#9999ff</color>
<color name="lightTheme_text_color">#000</color>
<color name="light_blue_400">#FF29B6F6</color>
<color name="light_blue_600">#FF039BE5</color>
<color name="gray_400">#FFBDBDBD</color>
<color name="gray_600">#FF757575</color>
</resources>

View file

@ -1,11 +1,5 @@
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="appbar_padding">16dp</dimen>
<dimen name="fab_margin">16dp</dimen>
<dimen name="appbar_padding_top">8dp</dimen>
<dimen name="app_icon_side">40dip</dimen>
<dimen name="app_action_height">48dip</dimen>
</resources>

View file

@ -161,6 +161,7 @@
-
-->
<string name="settings_meta_link_github" translatable="false">https://github.com/jrpie/Launcher</string>
<string name="settings_meta_link_docs" translatable="false">https://launcher.jrpie.de/</string>
<string name="settings_meta_report_bug_link" translatable="false">https://github.com/jrpie/Launcher/issues/new?template=bug_report.yaml</string>
<string name="settings_meta_report_bug_mail" translatable="false">android-launcher-crash@jrpie.de</string>
<string name="settings_meta_report_vulnerability_link" translatable="false">https://github.com/jrpie/Launcher/security/policy</string>

View file

@ -443,4 +443,17 @@
<string name="report_crash_title">μLauncher crashed</string>
<string name="send_email">Send Email</string>
<string name="notification_channel_crash">Crashes and Debug Information</string>
<string name="settings_meta_view_docs">Documentation</string>
<!--
-
- Content Descriptions
-
-->
<string name="content_description_add_widget">Add widget</string>
<string name="content_description_add_widget_panel">Add widget panel</string>
<string name="content_description_close">Close</string>
<string name="content_description_navigate_back">Navigate back</string>
<string name="content_description_navigate_next">Navigate next</string>
<string name="content_description_lock">Lock</string>
<string name="content_description_settings_actions_row_button_remove">Remove binding</string>
</resources>

View file

@ -14,6 +14,7 @@
<item name="android:buttonStyle">@style/Widget.AppCompat.Button.Colored</item>
<item name="colorButtonNormal">?colorAccent</item>
<item name="cardBackgroundColor">@color/cardview_dark_background</item>
<!--<item name="android:popupMenuStyle">@style/PopupMenuCustom</item>-->
@ -32,6 +33,7 @@
<item name="colorPrimaryDark">@color/darkTheme_background_color</item>
<item name="colorAccent">@color/darkTheme_accent_color</item>
<item name="android:colorBackground">@color/darkTheme_background_color</item>
<item name="cardBackgroundColor">@color/cardview_dark_background</item>
<item name="android:textColor">@color/darkTheme_text_color</item>
</style>
@ -40,6 +42,7 @@
<item name="colorPrimaryDark">@color/finnmglasTheme_background_color</item>
<item name="colorAccent">@color/finnmglasTheme_accent_color</item>
<item name="android:colorBackground">@color/finnmglasTheme_background_color</item>
<item name="cardBackgroundColor">@color/cardview_dark_background</item>
<item name="android:textColor">@color/finnmglasTheme_text_color</item>
</style>
@ -48,6 +51,7 @@
<item name="colorPrimaryDark">@color/lightTheme_background_color</item>
<item name="colorAccent">@color/lightTheme_accent_color</item>
<item name="android:colorBackground">@color/lightTheme_background_color</item>
<item name="cardBackgroundColor">@color/cardview_light_background</item>
<item name="android:textColor">@color/lightTheme_text_color</item>
</style>
@ -57,6 +61,7 @@
<item name="colorPrimaryDark">@color/material_dynamic_primary50</item>
<item name="colorAccent">@color/material_dynamic_tertiary50</item>
<item name="android:colorBackground">@color/material_dynamic_neutral10</item>
<item name="cardBackgroundColor">@color/cardview_dark_background</item>
<item name="android:textColor">@color/material_dynamic_neutral_variant90</item>
</style>

0
docs/_index.md Normal file
View file

View file

@ -1,7 +1,11 @@
# Gestures and Actions
+++
weight = 10
+++
# Actions and Gestures
µLauncher's central mechanism for accessing important functionality quickly
is to bind actions (e.g. launching an app) to gestures (e.g. swiping up).
is to bind actions (e.g., launching an app) to gestures (e.g., swiping up).
These bindings can be configured in µLauncher Settings > ACTIONS.
@ -28,7 +32,7 @@ These bindings can be configured in µLauncher Settings > ACTIONS.
- Tap then swipe up, down, left, or right
To execute these gesture consistently, it is helpful to think of them as double taps,
To execute these gestures 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.
@ -58,14 +62,14 @@ To any of the available gestures, one of the following actions can be bound:
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.
- Lock the screen: This allows you 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
- 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.
- Open [recent apps](https://developer.android.com/guide/components/activities/recents): Requires accessibility service. It can be used as a workaround for an 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.
- Do nothing: Simply prevents showing the message that no action is bound to this gesture.

452
docs/alternatives.md Normal file
View file

@ -0,0 +1,452 @@
+++
weight = 100
+++
# FOSS Launchers
This is a comparison of open-source home screens for Android.
**Inclusion criteria:** Apps in this list must be [open source](https://opensource.org/licenses) and maintained
<!-- New contributors, please reference https://www.markdownguide.org/basic-syntax/ -->
<!-- TEMPLATE
### <launcher name>
**License:** `<license type>`
[Website](<launcher website url>) | [Repository](<github or other repo url>) | [F-Droid](<fdroid url>)
<notes can go here>
**Main mode of interaction:** `<Search | Gestures | App grid>`
#### Features:
:white_check_mark: | :x: | :grey_question: Search: <list what you can search: e.g., apps, contacts, call history, ...>
:white_check_mark: | :x: | :grey_question: Search history
:white_check_mark: | :x: | :grey_question: Customizable gestures: <list usable gestures: e.g., up, down, tap+up, ...>
:white_check_mark: | :x: | :grey_question: Folders
:white_check_mark: | :x: | :grey_question: Tags
:white_check_mark: | :x: | :grey_question: Rename apps
:white_check_mark: | :x: | :grey_question: Widgets
:white_check_mark: | :x: | :grey_question: Private space
:white_check_mark: | :x: | :grey_question: Work profile
:white_check_mark: | :x: | :grey_question: Pinned shortcuts
:white_check_mark: | :x: | :grey_question: Icon packs
:white_check_mark: | :x: | :grey_question: Material You
---
-->
## Grid-Based Launchers
### Discreet Launcher
**License:** `GPL-3.0`
[Website](https://vincent-falzon.com/) | [Repository](https://github.com/falzonv/discreet-launcher) | [F-Droid](https://f-droid.org/en/packages/com.vincent_falzon.discreetlauncher/)
**Main mode of interaction:** `app grid`
#### Features:
:white_check_mark: Search: `apps`
:x: Search history
:x: Customizable gestures
:white_check_mark:Folders
:x: Tags
:white_check_mark: Rename apps
:x: Widgets
:grey_question: Private space
:white_check_mark: Work profile
:white_check_mark: Pinned shortcuts
:white_check_mark: Icon packs
:x: Material You
---
### Fossify
**License:** `GPL-3.0`
[Website](https://www.fossify.org/) | [Repository](https://github.com/FossifyOrg/Launcher) | [F-Droid](https://f-droid.org/en/packages/org.fossify.home/)
**Main mode of interaction:** `app grid`
#### Features:
:white_check_mark: Search: `apps`
:x: Search history
:x: Customizable gestures
:white_check_mark: Folders
:x: Tags
:white_check_mark: Rename apps
:white_check_mark: Widgets
:grey_question: Private space
:x: Work profile
:white_check_mark: Pinned shortcuts
:x: Icon packs
:white_check_mark: Material You
---
### Lawnchair
**License:** `Apache License 2.0`
[Website](https://lawnchair.app/) | [Repository](https://github.com/LawnchairLauncher/lawnchair)
Seems to be a regular (grid of apps) launcher.
**Main mode of interaction:** App grid
#### Features:
:white_check_mark: Search: `Apps & Shortcuts` `Web suggestions` `People` `Files` `Android Settings` `Calculator`
:white_check_mark: Search history
:white_check_mark: Customizable gestures: `double tap` `swipe up` `swipe down` `home button` `back button`
:white_check_mark: Folders
:x: Tags
:white_check_mark: Rename apps
:white_check_mark: Widgets
:grey_question: Private space
:grey_question: Work profile
:x: Pinned shortcuts
:white_check_mark: Icon packs
:white_check_mark: Material You
---
### Rootless Pixel Launcher
> **Abandoned**
**License:** `Apache License 2.0`
[Repository](https://github.com/amirzaidi/Launcher3)
**Main mode of interaction:** `App grid`
#### Features:
:white_check_mark: Search: `Apps`
:x: Search history
:x: Customizable gestures
:x: Folders
:x: Tags
:x: Rename apps
:warning: Widgets `buggy/broken`
:grey_question: Private space
:white_check_mark: Work profile
:white_check_mark: Pinned shortcuts
:white_check_mark: Icon packs
:x: Material You
---
## Search-Based
### Aster Launcher
> **Abandoned**
>
**License:** `GPL-3.0`
[Repository](https://github.com/neophtex/AsterLauncher) | [F-Droid](https://f-droid.org/en/packages/com.series.aster.launcher/)
**Main mode of interaction:** `search`
#### Features:
:warning: Search: `apps` (apps list is buggy/broken) `web`
:x: Search history
:x: Customizable gestures
:x: Folders
:x: Tags
:x: Rename apps
:x: Widgets
:grey_question: Private space
:white_check_mark: Work profile
:white_check_mark: Pinned shortcuts
:x: Icon packs
:x: Material You
---
### KISS Launcher
**License:** `GPL-3.0`
[Website](https://kisslauncher.com/) | [Repository](https://github.com/Neamar/KISS) | [F-Droid](https://f-droid.org/packages/fr.neamar.kiss/)
**Main mode of interaction:** `Search` `Some gestures available`
#### Features:
:white_check_mark: Search: `Apps` `Contacts` `Call history`
:white_check_mark: Search history
:white_check_mark: Customizable gestures: `swipe left` `swipe right` `swipe up` `swipe down` `long press` `double tap`
:x: Folders
:white_check_mark: Tags
:white_check_mark: Rename apps
:white_check_mark: Widgets
:grey_question: Private space
:white_check_mark: Work profile
:white_check_mark: Pinned shortcuts
:white_check_mark: Icon packs
:grey_question: Material You
---
### Lunar Launcher
**License:** `GPL-3.0`
[Repository](https://github.com/iamrasel/lunar-launcher) | [F-Droid](https://f-droid.org/en/packages/rasel.lunar.launcher/)
Even natively supports RSS feeds to the homescreen?
**Main mode of interaction:** `alphabet scroller`
#### Features:
:white_check_mark: Search: `swipe up` `swipe down` `swipe left` `swipe right` `tap and hold battery indicator/clock` `tap and hold lower part of screen` `double tap` `tap and hold favorite item`
:x: Search history
:x: Customizable gestures
:x: Folders
:x: Tags
:x: Rename apps
:x: Widgets
:grey_question: Private space
:x: Work profile
:white_check_mark: Pinned shortcuts
:x: Icon packs
:x: Material You
---
### OLauncher
**License:** `GPL-3.0`
[Repository](https://github.com/tanujnotes/Olauncher) | [F-Droid](https://f-droid.org/en/packages/app.olauncher/)
Extremely minimal launcher with lots of forks.
**Main mode of interaction:** `Search`
#### Features:
:white_check_mark: Search: `apps`
:x: Search history.
:white_check_mark: Customizable gestures: `swipe left` `swipe right` `double tap`
:x: Folders
:x: Tags
:white_check_mark: Rename apps
:x: Widgets
:grey_question: Private space
:white_check_mark: Work profile
:grey_question: Pinned shortcuts
:x: Icon packs
:grey_question: Material You
#### Forks:
* [Olauncher Clutter Free](https://f-droid.org/en/packages/app.olaunchercf/)
* [mLauncher](https://f-droid.org/en/packages/app.mlauncher/)
* [CLauncher](https://f-droid.org/en/packages/app.clauncher/) (even more minimalistic, search without feedback)
* [CCLauncher](https://f-droid.org/en/packages/app.cclauncher/) (rewrite using compose)
---
### TinyBit Launcher
**License:** `GPL-3.0`
[Repository](https://github.com/TBog/TBLauncher) | [F-Droid](https://f-droid.org/en/packages/rocks.tbog.tblauncher/)
**Main mode of interaction:** `search` `some gestures`
#### Features:
:white_check_mark: Search: `apps` `contacts` `web` `maps` `playstore` `youtube`
:white_check_mark: Search history
:white_check_mark: Customizable gestures: `tap` `double tap` `swipe up` `swipe left` `swipe right` `swipe down on left` `swipe down on right`
:x: Folders
:white_check_mark: Tags
:white_check_mark: Rename apps
:white_check_mark: Widgets
:grey_question: Private space
:white_check_mark: Work profile
:white_check_mark: Pinned shortcuts
:white_check_mark: Icon packs
:x: Material You
---
### YAM Launcher
**License:** `MIT`
[Repository](https://codeberg.org/ottoptj/yamlauncher) | [F-Droid](https://f-droid.org/en/packages/eu.ottop.yamlauncher/)
Similar to OLauncher?
**Main mode of interaction:** `search` `home screen text buttons`
#### Features:
:white_check_mark: Search: `apps` `contacts (optional)`
:x: Search history
:white_check_mark: Customizable gestures: `swipe left` `swipe right`
:x: Folders
:x: Tags
:white_check_mark: Rename apps
:x: Widgets
:grey_question: Private space
:white_check_mark: Work profile
:white_check_mark: Pinned shortcuts
:x: Icon packs
:white_check_mark: Material You
---
## Directory-Based
### folder launcher
**License:** `MIT`
[Repository](https://github.com/Robby-Blue/SimpleFolderLauncher) | [F-Droid](https://f-droid.org/en/packages/me.robbyblue.mylauncher/)
**Main mode of interaction:** `directory navigation`
#### Features:
:white_check_mark: Search: `apps`
:x: Search history
:x: Customizable gestures
:white_check_mark: Folders
:x: Tags
:white_check_mark: Rename apps
:white_check_mark: Widgets
:grey_question: Private space
:x: Work profile
:white_check_mark: Pinned shortcuts
:x: Icon packs
:x: Material You
---
### Ion Launcher
**License:** `GPL-3.0`
[Repository](https://codeberg.org/zagura/ion-launcher) | [F-Droid](https://f-droid.org/en/packages/one.zagura.IonLauncher/)
**Main mode of interaction:** `App grid` `Search`
#### Features:
:warning: Search: `apps` `contacts: buggy/broken`
:white_check_mark: Search history: `shows recently launched apps`
:x: Customizable gestures
:warning: Folders `prebuilt` `not customizable`
:x: Tags
:white_check_mark: Rename apps
:x: Widgets
:grey_question: Private space
:white_check_mark: Work profile
:white_check_mark: Pinned shortcuts
:white_check_mark: Icon packs
:x: Material You
---
## Gesture-Based
### Pie Launcher
**License:** `MIT`
[Repository](https://github.com/markusfisch/PieLauncher)
**Main mode of interaction:** `Selection wheel`
#### Features:
:white_check_mark: Search: `apps`
:x: Search history
:x: Customizable gestures
:x: Folders
:x: Tags
:x: Rename apps
:x: Widgets
:grey_question: Private space
:white_check_mark: Work profile
:white_check_mark: Pinned shortcuts
:x: Icon packs
:x: Material You
---
### µLauncher
**License:** `MIT`
[Repository](https://github.com/jrpie/launcher) | [F-Droid](https://f-droid.org/en/packages/de.jrpie.android.launcher/)
**Main mode of interaction:** `Gestures` `Search`
#### Features:
:white_check_mark: Search: `apps`
:x: Search history
:white_check_mark: Customizable gestures: `35 avilable` [read the docs](https://github.com/jrpie/launcher/blob/master/docs/actions-and-gestures.md)
:x: Folders
:x: Tags
:white_check_mark: Rename apps
:white_check_mark: Widgets
:white_check_mark: Private space
:white_check_mark: Work profile
:white_check_mark: Pinned shortcuts
:x:Icon packs
:white_check_mark: Material You
---
### Tabular Summary
#### Legend:
:white_check_mark: = Supported
:x: = Unsupported
:warning: = Buggy/Broken; check this launcher's notes above
| Launcher | Search | Search history | Customizable gestures | Folders | Tags | Rename apps | Widgets | Private space | Work profile | Pinned shortcuts | Icon packs | Material You |
|------------------------------------------------------|--------------------|--------------------|-----------------------|--------------------|--------------------|--------------------|--------------------|--------------------|--------------------|--------------------|--------------------|--------------------|
| [µLauncher](#µLauncher) | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: |
| [Fossify](#Fossify) | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :grey_question: | :x: | :white_check_mark: | :x: | :white_check_mark: |
| [Lawnchair](#Lawnchair) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :grey_question: | :grey_question: | :x: | :white_check_mark: | :white_check_mark: |
| [Rootless Pixel Launcher](#Rootless-Pixel-Launcher) | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :warning: | :grey_question: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: |
| [KISS Launcher](#KISS-Launcher) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :grey_question: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :grey_question: |
| [Lunar Launcher](#Lunar-Launcher) | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :grey_question: | :x: | :white_check_mark: | :x: | :x: |
| [OLauncher](#OLauncher) | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :grey_question: | :white_check_mark: | :grey_question: | :x: | :grey_question: |
| [TinyBit Launcher](#TinyBit-Launcher) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :grey_question: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: |
| [YAM Launcher](#YAM-Launcher) | :white_check_mark: | :x: | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :grey_question: | :white_check_mark: | :white_check_mark: | :x: | :white_check_mark: |
| [Ion Launcher](#Ion-Launcher) | :warning: | :white_check_mark: | :x: | :warning: | :x: | :white_check_mark: | :x: | :grey_question: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: |
| [Pie Launcher](#Pie-Launcher) | :white_check_mark: | :x: | :x: | :x: | :x: | :x: | :x: | :grey_question: | :white_check_mark: | :white_check_mark: | :x: | :x: |
| [folder launcher](#folder-launcher) | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :white_check_mark: | :grey_question: | :x: | :white_check_mark: | :x: | :x: |
| [Discreet Launcher](#Discreet-Launcher) | :white_check_mark: | :x: | :x: | :white_check_mark: | :x: | :white_check_mark: | :x: | :grey_question: | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: |
| [Aster Launcher](#Aster-Launcher) | :warning: | :x: | :x: | :x: | :x: | :x: | :x: | :grey_question: | :white_check_mark: | :white_check_mark: | :x: | :x: |
<!-- Automating checkboxes for the table
You can use this python script, copy the contents of the Features section for the launcher, and paste it in the fixit() function. Note, since you're pasting in multiple lines, you will need to start and end your paste with triple-quotes.
import re
def fix(features):
# Use: fixed("""<paste here>""")
fixed = ' | '.join(re.findall('(:[\w\_]*:)', features))
return f"| {fixed} |"
-->
---
## Not Tested
Feel free to test these and add
https://f-droid.org/en/packages/app.easy.launcher/
https://f-droid.org/en/packages/de.nodomain.tobihille.seniorlauncher/
https://f-droid.org/en/packages/com.mrmannwood.hexlauncher/
https://f-droid.org/en/packages/com.simplemobiletools.applauncher/
https://f-droid.org/en/packages/peterfajdiga.fastdraw/
https://f-droid.org/en/packages/de.mm20.launcher2.release/
[Even more launchers](https://docs.arcticons.com/faq/supported-launchers) (most of them don't seem to be FOSS)

52
docs/app-drawer.md Normal file
View file

@ -0,0 +1,52 @@
+++
weight = 10
+++
# App Drawer
Apps that are not needed all the time are shown in the app drawer.
There are several such drawers, but the basic concept is the same.
Besides regular apps, app drawers also show [pinned shortcuts](https://developer.android.com/develop/ui/views/launch/shortcuts/creating-shortcuts)[^1].
&mu;Launcher treats apps and shortcuts in the same way.
The idea of the app drawer is to search for apps using the keyboard.
By default[^2], an app is launched automatically once it is the only app matching the query.
This can be prevented by typing a space.
Usually, only two or three characters are needed, which is much faster than scrolling to find an app.
[^1]: A pinned shortcut is created, for example, when pinning a website to the home screen.
[^2]: There are [several settings](/docs/settings/#functionality) available to modify the behavior.
When long-pressing an app, additional options are shown:
* Rename the app
* Add to / remove from Favorites: Adds the app to the [Favorite Apps](#favorite-apps) list or removes it from there.
* Hide / Show: This hides the app from all drawers (except from [Hidden Apps](#hidden-apps)) or makes it visible again if it was hidden.
* App Info: Opens the system settings page for the app.
* Uninstall: Tries to uninstall the app or remove the shortcut.
## All Apps
This lists all apps except hidden apps.
By default, it is bound to `Swipe up`.
## Favorite Apps
Only shows favorite apps.
Pressing the star icon on the bottom right of any app drawer toggles whether only favorite apps should be shown.
Additionally, the `Favorite Apps` action can be used to launch this drawer directly.
By default, it is bound to `Swipe up (left edge)`.
## Private Space
When [private space](/docs/profiles/#private-space) is available, this drawer
shows only apps from the private space.
It can be opened using the `Private Space` action.
If the private space is locked, instead of showing the list, the unlock dialog is shown.
By default, apps from the private space are shown in All Apps as well; however, this is [configurable](/docs/settings/#hide-private-space-from-app-list).
## Hidden Apps
This list shows hidden apps.
It is only accessible through the settings.
The feature is intended to be used only for apps that are not needed at all but [can not be uninstalled](https://en.wikipedia.org/wiki/Software_bloat#Bloatware).

View file

@ -1,3 +1,8 @@
+++
weight = 50
+++
# Building from Source
## Using the command line
@ -12,7 +17,7 @@ cd Launcher
./gradlew assembleDefaultRelease
```
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:
@ -37,9 +42,13 @@ for further instructions.
Install [Android Studio](https://developer.android.com/studio), import this project and build it.
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.
{{% hint warning %}}
Note: These builds are not signed.
They are built in debug mode and are only suitable for testing.
{{% /hint %}}

View file

@ -1,15 +1,19 @@
+++
title = 'Differences to the original Launcher'
+++
# Notable changes compared to Finn's Launcher
µLauncher is a fork of [finnmglas's app Launcher](https://github.com/finnmglas/Launcher).
Here is an incomplete list of changes:
<!--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),
which at the time was still intended as a patch for launcher.
which at the time was still intended as a patch for the launcher.
The decision to create a hard fork was made two years later.-->
- Additional gestures:
- Back
- V,Λ,<,>
- 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.
@ -31,26 +35,25 @@ The decision to create a hard fork was made two years later.-->
- 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.
- 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 shown at the top right when necessary.
## 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.
## Technical
- Improved gesture detection.
- Different apps set as default.
- Different apps are set as the defaults.
- Package name was changed to `de.jrpie.android.launcher` to avoid clashing with the original app.
- Dropped support for API < 21 (i.e. pre Lollypop)
- Fixed some bugs
- Some refactoring
- Dropped support for API < 21 (i.e., pre Lollypop).
- Fixed some bugs.
- Some refactoring.
The complete list of changes can be viewed [here](https://github.com/jrpie/launcher/compare/340ee731...master).
---
\[original-repo\]: [https://github.com/finnmglas/Launcher](https://github.com/finnmglas/Launcher)
\[hack-font\]: [https://sourcefoundry.org/hack/](https://sourcefoundry.org/hack/)
[original-repo]: https://github.com/finnmglas/Launcher
[hack-font]: https://sourcefoundry.org/hack/

View file

@ -1,11 +1,16 @@
+++
weight = 40
+++
# 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].
* 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.
> 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.
@ -13,7 +18,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.
See [here](/docs/build) for instructions on how to build this project.
The [CI pipeline](https://github.com/jrpie/Launcher/actions) automatically creates debug builds.

7
docs/examples/_index.md Normal file
View file

@ -0,0 +1,7 @@
+++
bookCollapseSection = true
weight = 20
+++
# Examples
This section contains some examples how &mu;Launcher can be tweaked.

View file

@ -0,0 +1,18 @@
+++
title = 'Showing Apps on the Home Screen'
+++
# Showing Apps on the Home Screen
Even though this is somewhat contrary to the general idea of &mu;Launcher,
it is possible to show apps on the home screen using widgets.
Users suggested:
* [Launchy](https://launchywidget.com/) (proprietary!)
* KWGT Kustom Widget Maker (proprietary!)
{{% hint danger %}}
Both of these apps are not open source and KWGT even has ads.
Please contact me if you know FOSS alternatives!
{{% /hint %}}

View file

@ -0,0 +1,23 @@
+++
title = 'Integration with Termux'
+++
# Termux
&mu;Launcher has no special support for [Termux](https://termux.dev/).
However it is possible to run Termux commands from &mu;Launcher by using [Termux:Widget](https://wiki.termux.com/wiki/Termux:Widget) to create a pinned shortcut and bind that to a gesture.
* Install Termux:Widget.
* Make sure that &mu;Launcher is set as the default home screen.[^1]
* Put the script you want to run into `~/.shortcuts/`.
* Run `am start com.termux.widget/com.termux.widget.TermuxCreateShortcutActivity`. This will create a pinned shortcut which is treated like an app by &mu;Launcher, i.e. open &mu;Launcher's activity to create a shortcut.
<img src="./screenshot1.png"
alt="screenshot"
width="200" height="400">
<img src="./screenshot2.png"
alt="screenshot"
width="200" height="400">
[^1]: Only the default home screen can access shortcuts.

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View file

@ -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?
[![Get it on F-Droid](https://fdroid.gitlab.io/artwork/badge/get-it-on.png)](https://f-droid.org/packages/de.jrpie.android.launcher/)
[![Get it on Accrescent](https://accrescent.app/badges/get-it-on.png)](https://accrescent.app/app/de.jrpie.android.launcher.accrescent)
[![Get it on Obtainium](https://raw.githubusercontent.com/ImranR98/Obtainium/b1c8ac6f2ab08497189721a788a5763e28ff64cd/assets/graphics/badge_obtainium.png)](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})
[![Get it on GitHub](https://raw.githubusercontent.com/NeoApplications/Neo-Backup/034b226cea5c1b30eb4f6a6f313e4dadcbb0ece4/badge_github.png)](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
![μLauncher Home Screen screenshot](https://github.com/jrpie/launcher/blob/master/fastlane/metadata/android/en-US/images/phoneScreenshots/1.jpg)
![μLauncher Settings screenshot](https://github.com/jrpie/launcher/blob/master/fastlane/metadata/android/en-US/images/phoneScreenshots/2.jpg)
![μLauncher All Apps list view with icons screenshot](https://github.com/jrpie/launcher/blob/master/fastlane/metadata/android/en-US/images/phoneScreenshots/3.jpg)
![μLauncher Favorite Apps list view with icons screenshot](https://github.com/jrpie/launcher/blob/master/fastlane/metadata/android/en-US/images/phoneScreenshots/4.jpg)
![μLauncher Choose App to bind to gesture screenshot](https://github.com/jrpie/launcher/blob/master/fastlane/metadata/android/en-US/images/phoneScreenshots/5.jpg)
![μLauncher App options card from list view with icons screenshot](https://github.com/jrpie/launcher/blob/master/fastlane/metadata/android/en-US/images/phoneScreenshots/7.jpg
)
![μLauncher All Apps list view without icons screenshot](https://github.com/jrpie/launcher/blob/master/fastlane/metadata/android/en-US/images/phoneScreenshots/8.jpg)
<!-- missing μLauncher grid view screenshot-->

View file

@ -1,3 +1,9 @@
+++
title = 'User Profiles'
weight = 12
+++
# 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.

View file

@ -1,19 +1,22 @@
# Launcher Settings
+++
weight = 10
+++
Tweaks and customizations can be made from within the Launcher Settings page.
# Settings
These settings let you change wallpapers, change colors and fonts, enable monochrome app icons, change the app drawer layout, and much more.
Tweaks and customizations can be made from within the settings page.
The settings can be opened by binding the Settings action to a gesture (this is especially useful when configuring &mu;Launcher for the first time) or from the settings icon in the app drawer.[^1]
In the following documentation, 'app drawer' will be used to refer to the 'All Apps', 'Favorite Apps' and 'Private Space' views.
[^1]: i.e., the 'All Apps', 'Favorite Apps', and 'Private Space' views.
## Appearance
> ### Choose a wallpaper
### 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.
This triggers Android's mechanism to change the wallpaper using a photo 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)
### Font (in-app font)
Set the font used within the app settings. This setting does not affect the date/time home screen font.
@ -21,17 +24,26 @@ Set the font used within the app settings. This setting does not affect the date
**options:**&nbsp;`Hack`,`System default`,`Sans serif`,`Serif`,`Monospace`,`Serif monospace`
> ### Text Shadow
### Text Shadow
**type:**&nbsp;`toggle`
> ### Background (app list and setting)
### Background (app list and settings)
Defines which background should be used in app drawers, settings, etc.
to increase legibility.
* `Transparent` does not change the wallpaper.
* `Dim` dims the wallpaper.
* `Blur` tries to blur the wallpaper. This is not possible on all devices. Some older devices don't support the operation. Also blur can be temporarily unavailable when the device is in power saving mode. In these case, `Dim` is used as a fallback.
* `Solid` sets the background to a solid color (depending on the color theme). For the light theme only this option is available.
On the home screen and widget panels, the wallpaper is always shown unmodified.
**type:**&nbsp;`dropdown`
**type:**&nbsp;`Transparent`,`Dim`,`Blur`,`Solid`
> ### Monochrome app icons
### Monochrome app icons
Remove coloring from all app icons. Can help decrease visual stimulus when enabled.
@ -39,49 +51,56 @@ Remove coloring from all app icons. Can help decrease visual stimulus when enabl
## Date & Time
> ### Font (home screen)
These settings affect the clock shown on the home screen (or on widget panels).
If the clock is removed, the settings are not used.
Set the home screen font for date and time. This setting does not affect the in-app font.
### Font (home screen)
Set the home screen font for date and time. This setting does not affect the font of other components.
**type:**&nbsp;`dropdown`
**options:**&nbsp;`Hack`,`System default`,`Sans serif`,`Serif`,`Monospace`,`Serif monospace`
> ### Color [`[bug]`](https://github.com/jrpie/launcher/issues/151)
### Color
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.
Accepts a 6-digit RGB or 8-digit ARGB color code characters.[^2]
Note that on Android, the ARGB color format is used, i.e., the alpha component is specified first.
This differs from the more common RGBA, which is used in web development.
[Color wheel picker](https://rgbacolorpicker.com/color-wheel-picker)
**type:**&nbsp;`HEX`,`RGBA`
[^2]: More precisely, everything that is valid input for [parseColor](https://developer.android.com/reference/android/graphics/Color#parseColor(java.lang.String)) can be used.
> ### 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:**&nbsp;`ARGB`
### Use localized date format
Adapt the display of dates and times to the specific conventions of a particular locale or region as set by the system. Different locales use different date orders (e.g., MM/DD/YYYY in the US, DD/MM/YYYY in Europe).
**type:**&nbsp;`toggle`
> ### Show time
### Show time
Show the current time on the home screen.
**type:**&nbsp;`toggle`
> ### Show seconds
### Show seconds
Show the current time down to the second on the home screen.
**type:**&nbsp;`toggle`
> ### Show date
### Show date
Show the current date on the home screen.
**type:**&nbsp;`toggle`
> ### Flip date and time
### Flip date and time
Place the current time above the current date on the home screen.
@ -89,9 +108,9 @@ Place the current time above the current date on the home screen.
## Functionality
> ### Launch search results
### Launch search results
Launches any app that matches user keyboard input when no other apps match.
Launches any app that matches the user's 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.
@ -105,39 +124,39 @@ Press space to temporarily disable this feature and allow text entry without pre
**type:**&nbsp;`toggle`
> ### Search the web
### Search the web
Press return/enter while searching the app list to launch a web search.
Press return while searching the app list to launch a web search.
**type:**&nbsp;`toggle`
> ### Start keyboard for search
### Start keyboard for search
Automatically open the keyboard when the app drawer is opened.
**type:**&nbsp;`toggle`
> ### Double swipe gestures
### Double swipe gestures
Enable double swipe (two finger) gestures in launcher settings. Does not erase gesture bindings if accidentally turned off.
**type:**&nbsp;`toggle`
> ### Edge swipe gestures
### Edge swipe gestures
Enable edge swipe (near edges of screen) gestures in launcher settings. Does not erase gesture bindings if accidentally turned off.
**type:**&nbsp;`toggle`
> ### Edge width
### Edge width
Change how large a margin is used for detecting edge gestures. Shows the edge margin preview when using the slider.
**type:**&nbsp;`slider`
> ### Choose method for locking the screen
### Choose method for locking the screen
There are two methods to lock the screen and unfortunately both have downsides.
There are two methods to lock the screen, and unfortunately, both have downsides.
1. **`Device Admin`**
@ -147,7 +166,7 @@ There are two methods to lock the screen and unfortunately both have downsides.
- 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.
- 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 to a random app. Always review the [source code](https://github.com/jrpie/Launcher) before granting accessibility permissions so you can 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.
@ -157,32 +176,33 @@ There are two methods to lock the screen and unfortunately both have downsides.
## Apps
> ### Hidden 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
### 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.
Reduces redundancy and tidies up the app drawer.
**type:**&nbsp;`toggle`
> ### Hide paused apps
### 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.
For example, an app belonging to the work profile is paused when the work profile is inactive.
**type:**&nbsp;`toggle`
> ### Hide private space from app list
### Hide private space from app list
Remove private space from app drawer.
Remove private space from the app drawer.
Private space apps can be accessed using a separate app drawer, which can be opened with the Private Space action.
**type:**&nbsp;`toggle`
> ### Layout of app list
### Layout of app list
Changes how the apps are displayed when accessing the app drawer.
@ -195,7 +215,7 @@ Changes how the apps are displayed when accessing the app drawer.
**options:**&nbsp;`Default`,`Text`,`Grid`
> ### Reverse the app list
### Reverse the app list
Enable reverse alphabetical sorting of apps in the app drawer.
Useful for keeping apps within easier reach from the keyboard.
@ -204,32 +224,22 @@ Useful for keeping apps within easier reach from the keyboard.
## Display
> ### Rotate screen
### Rotate screen
**type:**&nbsp;`toggle`
> ### Keep screen on
### Keep screen on
**type:**&nbsp;`toggle`
> ### Hide status bar
### Hide status bar
Remove the top status bar from the home screen.
**type:**&nbsp;`toggle`
> ### Hide navigation bar
### 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.
Remove the navigation bar from the home screen. Enabling this setting may make it difficult to use the device if gestures are not set up properly.
**type:**&nbsp;`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:**&nbsp;`dropdown`
**options:**&nbsp;`App Info`,`Add to favorites`,`Hide`,`Rename`,`Uninstall`

28
docs/widgets.md Normal file
View file

@ -0,0 +1,28 @@
+++
title = 'Widgets'
weight = 11
+++
# Widgets
&mu;Launcher allows to add [app widgets](https://developer.android.com/develop/ui/views/appwidgets/overview) to the home screen and to widget panels.
Widgets can be added, moved, removed, and configured in `Settings > Manage Widgets`.
It is configurable whether or not interaction with a widget should be enabled.
* If interaction is enabled, touch events are forwarded to the widget as usual.
However, &mu;Launcher [gestures](/docs/actions-and-gestures/) can not be executed in areas where such a widget is present.
* If interaction is disabled, the widget does not respond to any touch events.
This is recommended when using a widget only to display information.
&mu;Launcher's clock behaves similarly to an app widget and can be managed in the same way.[^1]
[^1]: However, it is technically not an app widget and cannot be used with other launchers.
# Widget Panels
Widget panels can contain widgets that are not needed on the home screen.
They can be managed in `Settings > Manage Widget Panels`.
Widget panels can be opened by using the [Open Widget Panel](/docs/actions-and-gestures/#available-actions) action.