Compare commits

..

11 commits

Author SHA1 Message Date
Too Late (bot)
3a16cd003e
Merge 3e632c9892 into c1511cd475 2025-03-15 03:40:08 +01:00
c1511cd475
merge #124 - improve tutorial
Some checks are pending
Android CI / build (push) Waiting to run
* Add new "app list" section
* Rename fragments
* Replace screenshots
* Replace ViewPager by ViewPager2
* Add navigation buttons

Co-authored-by: Luke Wass <wassupluke@gmail.com>
2025-03-15 03:26:37 +01:00
toolatebot
3e632c9892 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: jrpie-Launcher/Launcher
Translate-URL: https://toolate.othing.xyz/projects/jrpie-launcher/launcher/
2025-03-15 00:07:18 +00:00
toolatebot
268acedb2c Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: jrpie-Launcher/Launcher
Translate-URL: https://toolate.othing.xyz/projects/jrpie-launcher/launcher/
2025-03-15 00:07:18 +00:00
anmoti
4b756d47ee Translated using Weblate (Japanese)
Currently translated at 78.4% (200 of 255 strings)

Translation: jrpie-Launcher/Launcher
Translate-URL: https://toolate.othing.xyz/projects/jrpie-launcher/launcher/ja/
2025-03-15 00:07:18 +00:00
anmoti
e323309cf9 Translated using Weblate (Japanese)
Currently translated at 17.6% (3 of 17 strings)

Translation: jrpie-Launcher/metadata
Translate-URL: https://toolate.othing.xyz/projects/jrpie-launcher/metadata/ja/
2025-03-15 00:07:18 +00:00
class0068
47a5476978 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 98.4% (251 of 255 strings)

Translation: jrpie-Launcher/Launcher
Translate-URL: https://toolate.othing.xyz/projects/jrpie-launcher/launcher/zh_Hans/
2025-03-15 00:07:18 +00:00
3597baee1f
fix problem which switching from grayscale icons back to normal
Some checks are pending
Android CI / build (push) Waiting to run
2025-03-14 22:33:08 +01:00
e02ca4091f
0.1.0 2025-03-14 16:35:41 +01:00
541e60356c
implement #98 - disable functionality because of Android bug: https://issuetracker.google.com/issues/352276244#comment5 2025-03-14 16:35:13 +01:00
492749a340
remove global variables from ListActivity 2025-03-14 16:03:59 +01:00
40 changed files with 365 additions and 163 deletions

View file

@ -23,8 +23,8 @@ android {
minSdkVersion 21
targetSdkVersion 35
compileSdk 35
versionCode 39
versionName "0.0.23"
versionCode 40
versionName "0.1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

View file

@ -194,7 +194,7 @@ fun getApps(
loadList.add(detailedAppInfo)
}
}
loadList.sortBy { it.getCustomLabel(context).toString() }
loadList.sortBy { it.getCustomLabel(context) }
var end = System.currentTimeMillis()
Log.i(LOG_TAG, "${loadList.size} apps loaded (${end - start}ms)")

View file

@ -91,6 +91,7 @@ fun isPrivateSpaceLocked(context: Context): Boolean {
val privateSpaceUser = getPrivateSpaceUser(context) ?: return false
return userManager.isQuietModeEnabled(privateSpaceUser)
}
fun lockPrivateSpace(context: Context, lock: Boolean) {
if (!isPrivateSpaceSupported()) {
return
@ -123,10 +124,16 @@ fun togglePrivateSpaceLock(context: Context) {
}
fun hidePrivateSpaceWhenLocked(context: Context): Boolean {
// TODO: perhaps this should be cached
// Trying to access the setting as a 3rd party launcher raises a security exception.
// This is an Android bug: https://issuetracker.google.com/issues/352276244#comment5
// The logic for this is implemented.
// TODO: replace this once the Android bug is fixed
return false
// TODO: perhaps this should be cached
// https://cs.android.com/android/platform/superproject/main/+/main:packages/apps/Launcher3/src/com/android/launcher3/util/SettingsCache.java;l=61;drc=56bf7ad33bc9d5ed3c18e7abefeec5c177ec75d7
val key = "hide_privatespace_entry_point"
return Settings.Secure.getInt(context.contentResolver, key, 0) == 1
// val key = "hide_privatespace_entry_point"
// return Settings.Secure.getInt(context.contentResolver, key, 0) == 1
}

View file

@ -27,10 +27,14 @@ fun View.blink(
}
// Taken from: https://stackoverflow.com/a/30340794/12787264
fun ImageView.transformGrayscale() {
this.colorFilter = ColorMatrixColorFilter(ColorMatrix().apply {
fun ImageView.transformGrayscale(grayscale: Boolean) {
this.colorFilter = if (grayscale) {
ColorMatrixColorFilter(ColorMatrix().apply {
setSaturation(0f)
})
} else {
null
}
}

View file

@ -1,7 +1,6 @@
package de.jrpie.android.launcher.ui.list
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.res.Resources
import android.graphics.Rect
@ -33,16 +32,6 @@ import de.jrpie.android.launcher.ui.list.apps.ListFragmentApps
import de.jrpie.android.launcher.ui.list.other.ListFragmentOther
// TODO: Better solution for this intercommunication functionality (used in list-fragments)
var intention = ListActivity.ListActivityIntention.VIEW
var favoritesVisibility: AppFilter.Companion.AppSetVisibility =
AppFilter.Companion.AppSetVisibility.VISIBLE
var privateSpaceVisibility: AppFilter.Companion.AppSetVisibility =
AppFilter.Companion.AppSetVisibility.VISIBLE
var hiddenVisibility: AppFilter.Companion.AppSetVisibility =
AppFilter.Companion.AppSetVisibility.HIDDEN
var forGesture: String? = null
/**
* The [ListActivity] is the most general purpose activity in Launcher:
* - used to view all apps and edit their settings
@ -52,6 +41,14 @@ var forGesture: String? = null
*/
class ListActivity : AppCompatActivity(), UIObject {
private lateinit var binding: ListBinding
var intention = ListActivityIntention.VIEW
var favoritesVisibility: AppFilter.Companion.AppSetVisibility =
AppFilter.Companion.AppSetVisibility.VISIBLE
var privateSpaceVisibility: AppFilter.Companion.AppSetVisibility =
AppFilter.Companion.AppSetVisibility.VISIBLE
var hiddenVisibility: AppFilter.Companion.AppSetVisibility =
AppFilter.Companion.AppSetVisibility.HIDDEN
var forGesture: String? = null
private fun updateLockIcon(locked: Boolean) {
@ -261,7 +258,7 @@ private val TAB_TITLES = arrayOf(
* The [ListSectionsPagerAdapter] returns the fragment,
* which corresponds to the selected tab in [ListActivity].
*/
class ListSectionsPagerAdapter(private val context: Context, fm: FragmentManager) :
class ListSectionsPagerAdapter(private val activity: ListActivity, fm: FragmentManager) :
FragmentPagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
override fun getItem(position: Int): Fragment {
@ -273,11 +270,11 @@ class ListSectionsPagerAdapter(private val context: Context, fm: FragmentManager
}
override fun getPageTitle(position: Int): CharSequence {
return context.resources.getString(TAB_TITLES[position])
return activity.resources.getString(TAB_TITLES[position])
}
override fun getCount(): Int {
return when (intention) {
return when (activity.intention) {
ListActivity.ListActivityIntention.VIEW -> 1
else -> 2
}

View file

@ -47,6 +47,7 @@ class AppsRecyclerAdapter(
private val apps = (activity.applicationContext as Application).apps
private val appsListDisplayed: MutableList<AbstractDetailedAppInfo> = mutableListOf()
private val grayscale = LauncherPreferences.theme().monochromeIcons()
// temporarily disable auto launch
var disableAutoLaunch: Boolean = false
@ -79,20 +80,19 @@ class AppsRecyclerAdapter(
override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) {
var appLabel = appsListDisplayed[i].getCustomLabel(activity)
val appIcon = appsListDisplayed[i].getIcon(activity)
viewHolder.img.transformGrayscale(grayscale)
viewHolder.img.setImageDrawable(appIcon.constantState?.newDrawable() ?: appIcon)
if (layout.useBadgedText) {
appLabel = activity.packageManager.getUserBadgedLabel(
appLabel,
appsListDisplayed[i].getUser(activity)
).toString()
}
val appIcon = appsListDisplayed[i].getIcon(activity)
viewHolder.textView.text = appLabel
viewHolder.img.setImageDrawable(appIcon)
if (LauncherPreferences.theme().monochromeIcons())
viewHolder.img.transformGrayscale()
// decide when to show the options popup menu about
if (intention == ListActivity.ListActivityIntention.VIEW) {

View file

@ -17,11 +17,6 @@ import de.jrpie.android.launcher.databinding.ListAppsBinding
import de.jrpie.android.launcher.preferences.LauncherPreferences
import de.jrpie.android.launcher.ui.UIObject
import de.jrpie.android.launcher.ui.list.ListActivity
import de.jrpie.android.launcher.ui.list.favoritesVisibility
import de.jrpie.android.launcher.ui.list.forGesture
import de.jrpie.android.launcher.ui.list.hiddenVisibility
import de.jrpie.android.launcher.ui.list.intention
import de.jrpie.android.launcher.ui.list.privateSpaceVisibility
import de.jrpie.android.launcher.ui.openSoftKeyboard
@ -54,7 +49,7 @@ class ListFragmentApps : Fragment(), UIObject {
.registerOnSharedPreferenceChangeListener(sharedPreferencesListener)
binding.listAppsCheckBoxFavorites.isChecked =
(favoritesVisibility == AppFilter.Companion.AppSetVisibility.EXCLUSIVE)
((activity as? ListActivity)?.favoritesVisibility == AppFilter.Companion.AppSetVisibility.EXCLUSIVE)
}
override fun onStop() {
@ -67,16 +62,17 @@ class ListFragmentApps : Fragment(), UIObject {
override fun setOnClicks() {}
override fun adjustLayout() {
val listActivity = activity as? ListActivity ?: return
appsRecyclerAdapter =
AppsRecyclerAdapter(
requireActivity(), binding.root, intention, forGesture,
listActivity, binding.root, listActivity.intention, listActivity.forGesture,
appFilter = AppFilter(
requireContext(),
"",
favoritesVisibility = favoritesVisibility,
privateSpaceVisibility = privateSpaceVisibility,
hiddenVisibility = hiddenVisibility
favoritesVisibility = listActivity.favoritesVisibility,
privateSpaceVisibility = listActivity.privateSpaceVisibility,
hiddenVisibility = listActivity.hiddenVisibility
),
layout = LauncherPreferences.list().layout()
)
@ -124,7 +120,8 @@ class ListFragmentApps : Fragment(), UIObject {
if (newText == " " &&
!appsRecyclerAdapter.disableAutoLaunch &&
intention == ListActivity.ListActivityIntention.VIEW &&
(activity as? ListActivity)?.intention
== ListActivity.ListActivityIntention.VIEW &&
LauncherPreferences.functionality().searchAutoLaunch()
) {
appsRecyclerAdapter.disableAutoLaunch = true
@ -141,17 +138,17 @@ class ListFragmentApps : Fragment(), UIObject {
})
binding.listAppsCheckBoxFavorites.setOnClickListener {
favoritesVisibility =
listActivity.favoritesVisibility =
if (binding.listAppsCheckBoxFavorites.isChecked) {
AppFilter.Companion.AppSetVisibility.EXCLUSIVE
} else {
AppFilter.Companion.AppSetVisibility.VISIBLE
}
appsRecyclerAdapter.setFavoritesVisibility(favoritesVisibility)
appsRecyclerAdapter.setFavoritesVisibility(listActivity.favoritesVisibility)
(activity as? ListActivity)?.updateTitle()
}
if (intention == ListActivity.ListActivityIntention.VIEW
if (listActivity.intention == ListActivity.ListActivityIntention.VIEW
&& LauncherPreferences.functionality().searchAutoOpenKeyboard()
) {
binding.listAppsSearchview.openSoftKeyboard(requireContext())

View file

@ -11,7 +11,7 @@ import androidx.recyclerview.widget.RecyclerView
import de.jrpie.android.launcher.R
import de.jrpie.android.launcher.REQUEST_CHOOSE_APP
import de.jrpie.android.launcher.actions.LauncherAction
import de.jrpie.android.launcher.ui.list.forGesture
import de.jrpie.android.launcher.ui.list.ListActivity
/**
* The [OtherRecyclerAdapter] will only be displayed in the ListActivity,
@ -36,7 +36,7 @@ class OtherRecyclerAdapter(val activity: Activity) :
val pos = bindingAdapterPosition
val content = othersList[pos]
forGesture?.let { returnChoiceIntent(it, content) }
(activity as? ListActivity)?.forGesture?.let { returnChoiceIntent(it, content) }
}
init {

View file

@ -143,9 +143,7 @@ class ActionsRecyclerAdapter(val activity: Activity) :
val description = gesture.getDescription(activity)
viewHolder.descriptionTextView.text = description
if (LauncherPreferences.theme().monochromeIcons())
viewHolder.img.transformGrayscale()
viewHolder.img.transformGrayscale(LauncherPreferences.theme().monochromeIcons())
updateViewHolder(gesture, viewHolder)
viewHolder.img.setOnClickListener { chooseApp(gesture) }

View file

@ -4,23 +4,26 @@ import android.content.Intent
import android.content.res.Resources
import android.os.Build
import android.os.Bundle
import android.view.View
import android.window.OnBackInvokedDispatcher
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentPagerAdapter
import androidx.viewpager.widget.ViewPager
import com.google.android.material.tabs.TabLayout
import de.jrpie.android.launcher.R
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import com.google.android.material.tabs.TabLayoutMediator
import de.jrpie.android.launcher.REQUEST_CHOOSE_APP
import de.jrpie.android.launcher.databinding.TutorialBinding
import de.jrpie.android.launcher.preferences.LauncherPreferences
import de.jrpie.android.launcher.saveListActivityChoice
import de.jrpie.android.launcher.ui.UIObject
import de.jrpie.android.launcher.ui.tutorial.tabs.TutorialFragmentConcept
import de.jrpie.android.launcher.ui.tutorial.tabs.TutorialFragmentFinish
import de.jrpie.android.launcher.ui.tutorial.tabs.TutorialFragmentSetup
import de.jrpie.android.launcher.ui.tutorial.tabs.TutorialFragmentStart
import de.jrpie.android.launcher.ui.tutorial.tabs.TutorialFragmentUsage
import de.jrpie.android.launcher.ui.blink
import de.jrpie.android.launcher.ui.tutorial.tabs.TutorialFragment0Start
import de.jrpie.android.launcher.ui.tutorial.tabs.TutorialFragment1Concept
import de.jrpie.android.launcher.ui.tutorial.tabs.TutorialFragment2Usage
import de.jrpie.android.launcher.ui.tutorial.tabs.TutorialFragment3AppList
import de.jrpie.android.launcher.ui.tutorial.tabs.TutorialFragment4Setup
import de.jrpie.android.launcher.ui.tutorial.tabs.TutorialFragment5Finish
/**
* The [TutorialActivity] is displayed automatically on new installations.
@ -31,10 +34,16 @@ import de.jrpie.android.launcher.ui.tutorial.tabs.TutorialFragmentUsage
*/
class TutorialActivity : AppCompatActivity(), UIObject {
private lateinit var binding: TutorialBinding
override fun onCreate(savedInstanceState: Bundle?) {
super<AppCompatActivity>.onCreate(savedInstanceState)
super<UIObject>.onCreate()
// Initialise layout
binding = TutorialBinding.inflate(layoutInflater)
setContentView(binding.root)
// Handle back key / gesture on Android 13+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
onBackInvokedDispatcher.registerOnBackInvokedCallback(
@ -48,15 +57,51 @@ class TutorialActivity : AppCompatActivity(), UIObject {
}
}
// Initialise layout
setContentView(R.layout.tutorial)
// set up tabs and swiping in settings
val sectionsPagerAdapter = TutorialSectionsPagerAdapter(supportFragmentManager)
val viewPager: ViewPager = findViewById(R.id.tutorial_viewpager)
viewPager.adapter = sectionsPagerAdapter
val tabs: TabLayout = findViewById(R.id.tutorial_tabs)
tabs.setupWithViewPager(viewPager)
val sectionsPagerAdapter = TutorialSectionsPagerAdapter(this)
binding.tutorialViewpager.apply {
adapter = sectionsPagerAdapter
currentItem = 0
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
binding.tutorialButtonNext.apply {
val lastItem = sectionsPagerAdapter.itemCount - 1
visibility = if (position == lastItem) {
View.INVISIBLE
} else {
View.VISIBLE
}
if (position == 0) {
blink()
} else {
clearAnimation()
}
}
binding.tutorialButtonBack.apply {
visibility = if (position == 0) {
View.INVISIBLE
} else {
View.VISIBLE
}
}
}
})
}
TabLayoutMediator(binding.tutorialTabs, binding.tutorialViewpager) { _, _ -> }.attach()
binding.tutorialButtonNext.setOnClickListener {
binding.tutorialViewpager.apply {
setCurrentItem(
(currentItem + 1).coerceAtMost(sectionsPagerAdapter.itemCount - 1),
true
)
}
}
binding.tutorialButtonBack.setOnClickListener {
binding.tutorialViewpager.apply {
setCurrentItem((currentItem - 1).coerceAtLeast(0), true)
}
}
}
override fun getTheme(): Resources.Theme {
@ -89,26 +134,22 @@ class TutorialActivity : AppCompatActivity(), UIObject {
*
* Tabs: (Start | Concept | Usage | Setup | Finish)
*/
class TutorialSectionsPagerAdapter(fm: FragmentManager) :
FragmentPagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
class TutorialSectionsPagerAdapter(activity: FragmentActivity) :
FragmentStateAdapter(activity) {
override fun getItem(position: Int): Fragment {
override fun getItemCount(): Int {
return 6
}
override fun createFragment(position: Int): Fragment {
return when (position) {
0 -> TutorialFragmentStart()
1 -> TutorialFragmentConcept()
2 -> TutorialFragmentUsage()
3 -> TutorialFragmentSetup()
4 -> TutorialFragmentFinish()
0 -> TutorialFragment0Start()
1 -> TutorialFragment1Concept()
2 -> TutorialFragment2Usage()
3 -> TutorialFragment3AppList()
4 -> TutorialFragment4Setup()
5 -> TutorialFragment5Finish()
else -> Fragment()
}
}
/* We don't use titles here, as we have the dots */
override fun getPageTitle(position: Int): CharSequence {
return ""
}
override fun getCount(): Int {
return 5
}
}

View file

@ -5,24 +5,22 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import de.jrpie.android.launcher.databinding.TutorialStartBinding
import de.jrpie.android.launcher.databinding.Tutorial0StartBinding
import de.jrpie.android.launcher.ui.UIObject
import de.jrpie.android.launcher.ui.blink
/**
* The [TutorialFragmentStart] is a used as a tab in the TutorialActivity.
* The [TutorialFragment0Start] is a used as a tab in the TutorialActivity.
*
* It displays info about the app and gets the user into the tutorial
*/
class TutorialFragmentStart : Fragment(), UIObject {
class TutorialFragment0Start : Fragment(), UIObject {
private lateinit var binding: TutorialStartBinding
private lateinit var binding: Tutorial0StartBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = TutorialStartBinding.inflate(inflater, container, false)
binding.tutorialStartIconRight.blink()
binding = Tutorial0StartBinding.inflate(inflater, container, false)
return binding.root
}

View file

@ -6,22 +6,22 @@ import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import de.jrpie.android.launcher.BuildConfig
import de.jrpie.android.launcher.databinding.TutorialConceptBinding
import de.jrpie.android.launcher.databinding.Tutorial1ConceptBinding
import de.jrpie.android.launcher.ui.UIObject
/**
* The [TutorialFragmentConcept] is a used as a tab in the TutorialActivity.
* The [TutorialFragment1Concept] is a used as a tab in the TutorialActivity.
*
* It is used to display info about Launchers concept (open source, efficiency ...)
*/
class TutorialFragmentConcept : Fragment(), UIObject {
private lateinit var binding: TutorialConceptBinding
class TutorialFragment1Concept : Fragment(), UIObject {
private lateinit var binding: Tutorial1ConceptBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = TutorialConceptBinding.inflate(inflater, container, false)
binding = Tutorial1ConceptBinding.inflate(inflater, container, false)
binding.tutorialConceptBadgeVersion.text = BuildConfig.VERSION_NAME
return binding.root
}

View file

@ -9,17 +9,17 @@ import de.jrpie.android.launcher.R
import de.jrpie.android.launcher.ui.UIObject
/**
* The [TutorialFragmentUsage] is a used as a tab in the TutorialActivity.
* The [TutorialFragment2Usage] is a used as a tab in the TutorialActivity.
*
* Tells the user how his screen will look and how the app can be used
*/
class TutorialFragmentUsage : Fragment(), UIObject {
class TutorialFragment2Usage : Fragment(), UIObject {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.tutorial_usage, container, false)
return inflater.inflate(R.layout.tutorial_2_usage, container, false)
}
override fun onStart() {

View file

@ -0,0 +1,30 @@
package de.jrpie.android.launcher.ui.tutorial.tabs
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import de.jrpie.android.launcher.R
import de.jrpie.android.launcher.ui.UIObject
/**
* The [TutorialFragment3AppList] is a used as a tab in the TutorialActivity.
*
* Tells the user how his screen will look and how the app can be used
*/
class TutorialFragment3AppList : Fragment(), UIObject {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.tutorial_3_app_list, container, false)
}
override fun onStart() {
super<Fragment>.onStart()
super<UIObject>.onStart()
}
}

View file

@ -9,17 +9,17 @@ import de.jrpie.android.launcher.R
import de.jrpie.android.launcher.ui.UIObject
/**
* The [TutorialFragmentSetup] is a used as a tab in the TutorialActivity.
* The [TutorialFragment4Setup] is a used as a tab in the TutorialActivity.
*
* It is used to display info in the tutorial
*/
class TutorialFragmentSetup : Fragment(), UIObject {
class TutorialFragment4Setup : Fragment(), UIObject {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.tutorial_setup, container, false)
return inflater.inflate(R.layout.tutorial_4_setup, container, false)
}
override fun onStart() {

View file

@ -6,25 +6,25 @@ 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.TutorialFinishBinding
import de.jrpie.android.launcher.databinding.Tutorial5FinishBinding
import de.jrpie.android.launcher.preferences.LauncherPreferences
import de.jrpie.android.launcher.setDefaultHomeScreen
import de.jrpie.android.launcher.ui.UIObject
/**
* The [TutorialFragmentFinish] is a used as a tab in the TutorialActivity.
* The [TutorialFragment5Finish] is a used as a tab in the TutorialActivity.
*
* It is used to display further resources and let the user start Launcher
*/
class TutorialFragmentFinish : Fragment(), UIObject {
class TutorialFragment5Finish : Fragment(), UIObject {
private lateinit var binding: TutorialFinishBinding
private lateinit var binding: Tutorial5FinishBinding
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = TutorialFinishBinding.inflate(inflater, container, false)
binding = Tutorial5FinishBinding.inflate(inflater, container, false)
return binding.root
}

View file

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?android:textColor"
android:pathData="M15.41,7.41L14,6l-6,6 6,6 1.41,-1.41L10.83,12z" />
</vector>

View file

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?android:textColor"
android:pathData="M10,6L8.59,7.41 13.17,12l-4.58,4.59L10,18l6,-6z" />
</vector>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 KiB

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- https://stackoverflow.com/a/30692466 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="10dp" />
</shape>

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

View file

@ -10,7 +10,7 @@
tools:context=".ui.tutorial.TutorialActivity">
<androidx.viewpager.widget.ViewPager
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/tutorial_viewpager"
android:layout_width="0dp"
android:layout_height="0dp"
@ -22,15 +22,37 @@
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
<ImageView
android:id="@+id/tutorial_button_back"
android:layout_width="50dp"
android:layout_height="50dp"
android:gravity="center"
android:alpha="0.5"
android:src="@drawable/baseline_navigate_before_24"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tutorial_viewpager" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tutorial_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_height="50dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/tutorial_button_next"
app:layout_constraintStart_toEndOf="@+id/tutorial_button_back"
app:tabBackground="@drawable/tutorial_tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"
app:tabIndicatorHeight="0dp" />
<ImageView
android:id="@+id/tutorial_button_next"
android:layout_width="50dp"
android:layout_height="50dp"
android:gravity="center"
android:src="@drawable/baseline_navigate_next_24"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
app:layout_constraintTop_toBottomOf="@+id/tutorial_viewpager" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -8,7 +8,7 @@
android:paddingRight="32sp"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.tutorial.tabs.TutorialFragmentStart">
tools:context=".ui.tutorial.tabs.TutorialFragment0Start">
<TextView
android:id="@+id/tutorial_start_text"
@ -21,16 +21,4 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tutorial_start_icon_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=">>>>>>"
android:textSize="64sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tutorial_start_text" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -8,7 +8,7 @@
android:paddingRight="32sp"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.tutorial.tabs.TutorialFragmentConcept">
tools:context=".ui.tutorial.tabs.TutorialFragment1Concept">
<TextView
android:id="@+id/tutorial_concept_title"
@ -28,11 +28,10 @@
android:gravity="center"
android:text="@string/tutorial_concept_text"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tutorial_concept_title"
app:layout_constraintVertical_bias="0.19999999" />
app:layout_constraintBottom_toTopOf="@id/tutorial_concept_badge_version_label"/>
<TextView
android:id="@+id/tutorial_concept_text_2"
@ -60,6 +59,22 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tutorial_concept_text"
tools:text="0.0.7"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/tutorial_concept_badge_version_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:gravity="center"
android:textSize="18sp"
android:text="@string/tutorial_concept_label_version"
app:layout_constraintBottom_toTopOf="@+id/tutorial_concept_badge_version"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
tools:ignore="ContentDescription" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -7,7 +7,7 @@
android:layout_height="match_parent"
android:paddingLeft="32sp"
android:paddingRight="32sp"
tools:context=".ui.tutorial.tabs.TutorialFragmentUsage">
tools:context=".ui.tutorial.tabs.TutorialFragment2Usage">
<TextView
android:id="@+id/tutorial_usage_title"
@ -39,12 +39,12 @@
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="centerInside"
android:src="@drawable/home_round_screen"
android:src="@drawable/tutorial_home_screen"
app:layout_constraintBottom_toTopOf="@id/tutorial_usage_text_2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/tutorial_usage_text"
app:layout_constraintTop_toBottomOf="@id/tutorial_usage_text"
app:srcCompat="@drawable/home_round_screen"
app:srcCompat="@drawable/tutorial_home_screen"
tools:ignore="ContentDescription" />
<TextView

View file

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/tutorial_usage_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="32sp"
android:paddingRight="32sp"
tools:context=".ui.tutorial.tabs.TutorialFragment3AppList">
<TextView
android:id="@+id/tutorial_app_list_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/tutorial_app_list_title"
android:textSize="30sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tutorial_app_list_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="32dp"
android:gravity="center"
android:text="@string/tutorial_app_list_text"
android:textSize="18sp"
app:layout_constraintBottom_toTopOf="@+id/tutorial_app_list_screen"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tutorial_app_list_title" />
<ImageView
android:id="@+id/tutorial_app_list_screen"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="centerInside"
android:src="@drawable/tutorial_app_list"
app:layout_constraintBottom_toTopOf="@id/tutorial_app_list_text_2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/tutorial_app_list_text"
app:layout_constraintTop_toBottomOf="@id/tutorial_app_list_text"
app:srcCompat="@drawable/tutorial_app_list"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/tutorial_app_list_text_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:layout_marginBottom="16dp"
android:gravity="center"
android:text="@string/tutorial_app_list_text_2"
android:textSize="18sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tutorial_app_list_screen" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -8,7 +8,7 @@
android:layout_height="match_parent"
android:paddingLeft="32sp"
android:paddingRight="32sp"
tools:context=".ui.tutorial.tabs.TutorialFragmentSetup">
tools:context=".ui.tutorial.tabs.TutorialFragment4Setup">
<TextView
android:id="@+id/tutorial_setup_title"

View file

@ -7,7 +7,7 @@
android:paddingRight="32sp"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.tutorial.tabs.TutorialFragmentFinish">
tools:context=".ui.tutorial.tabs.TutorialFragment5Finish">
<TextView
android:id="@+id/tutorial_finish_title"
@ -24,6 +24,7 @@
android:id="@+id/tutorial_finish_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/tutorial_finish_text"
android:textSize="18sp"
app:layout_constraintBottom_toTopOf="@id/tutorial_finish_button_start"

View file

@ -117,7 +117,6 @@
<string name="settings_list_layout_item_grid">Raster</string>
<string name="settings_general_choose_home_screen">Launcher wählen</string>
<string name="settings_meta_cant_select_launcher">App Info</string>
<string name="settings_meta_cant_select_launcher_msg">Das Gerät unterstützt diese Funktion nicht. Stattdessen die App Details bearbeiten?</string>
<string name="settings_meta_show_tutorial">Zum Tutorial</string>
<string name="settings_meta_reset">Einstellungen zurücksetzen</string>
<string name="settings_meta_reset_confirm">Alle Einstellungen gehen verloren. Weitermachen?</string>

View file

@ -75,7 +75,6 @@
-->
<string name="settings_general_choose_home_screen">Seleccionar Launcher</string>
<string name="settings_meta_cant_select_launcher">Información de la aplicación</string>
<string name="settings_meta_cant_select_launcher_msg">Su dispositivo no posee esta caracrerística. Desea cambiar los detalles de la aplicación?</string>
<string name="settings_meta_show_tutorial">Ver tutorial de Launcher</string>
<string name="settings_meta_reset">Configuración por defecto</string>
<string name="settings_meta_reset_confirm">Todas sus preferencias se eliminarán. Desea continuar?</string>

View file

@ -67,7 +67,6 @@
-->
<string name="settings_general_choose_home_screen">Choisir μLauncher comme application d\'écran d\'accueil par défaut</string>
<string name="settings_meta_cant_select_launcher">Informations sur l\'application</string>
<string name="settings_meta_cant_select_launcher_msg">Votre appareil ne prend pas en charge cette fonctionnalité. Souhaitez-vous plutôt accéder aux détails de l\'application ?</string>
<string name="settings_meta_show_tutorial">Regarder le tutoriel</string>
<string name="settings_meta_reset">Réinitialiser</string>
<string name="settings_meta_reset_confirm">Vous allez réinitialiser tous vos paramètres. Souhaitez-vous poursuivre ?</string>

View file

@ -34,7 +34,6 @@
<br/><br/><br/><br/>
Puoi cambiare le tue scelte in seguito nelle impostazioni.
]]></string>
<string name="settings_meta_cant_select_launcher_msg">Il tuo dispositivo non supporta questa funzione. Vuoi aprire la pagina di dettaglio dell\'applicazione?</string>
<string name="alert_cant_open_title">Impossibile aprire l\'applicazione</string>
<string name="alert_cant_open_message">Desideri modificare le impostazioni?</string>
<string name="toast_cant_open_message">Apri le impostazioni per abbinare un\'azione a questo gesto</string>

View file

@ -192,7 +192,6 @@
<string name="settings_functionality_auto_launch_summary">この機能を一時的に無効にするにはスペースキーを押します。</string>
<string name="list_other_list_private_space">プライベートスペース</string>
<string name="settings_apps_hide_private_space_apps">アプリ一覧からプライベートスペースを隠す</string>
<string name="settings_meta_cant_select_launcher_msg">この機能はあなたのデバイスでは動作しません。代わりにアプリケーションの詳細を管理しますか?</string>
<string name="settings_meta_report_bug">バグを報告</string>
<string name="tutorial_start_text">このランチャーの使い方を学ぶのにほんの数秒しかかかりません</string>
<string name="tutorial_concept_text">Launcherは、最小限かつ効率的で、邪魔にならないように設計されています。支払い、広告、追跡サービスは一切ありません。</string>

View file

@ -79,7 +79,6 @@
-->
<string name="settings_general_choose_home_screen">Definir o μLauncher como tela inicial</string>
<string name="settings_meta_cant_select_launcher">Informações do aplicativo</string>
<string name="settings_meta_cant_select_launcher_msg">Seu dispositivo não é compatível com esse recurso. Gerenciar detalhes do app em vez disso?</string>
<string name="settings_meta_show_tutorial">Ver tutorial do launcher</string>
<string name="settings_meta_reset">Redefinir configuraçãos</string>
<string name="settings_meta_reset_confirm">Você vai descartar todas as suas preferências. Continuar?</string>

View file

@ -164,7 +164,6 @@
<string name="settings_list_layout_item_text">Metin</string>
<string name="settings_list_layout_item_grid">Izgara</string>
<string name="settings_meta_cant_select_launcher">Uygulama Detayı</string>
<string name="settings_meta_cant_select_launcher_msg">Sizin cihazınız bu özelliği desteklemiyor. Onun yerine uygulama detaylarını düzenleyin?</string>
<string name="settings_meta_reset">Ayarları Sıfırlayın</string>
<string name="settings_meta_reset_confirm">Tüm tercihlerinizi bir kenara bırakacaksınız. Devam mı?</string>
<string name="settings_theme_font_item_monospace">Tek uzay</string>

View file

@ -50,7 +50,6 @@
<string name="settings_functionality_auto_keyboard">搜索时呼出键盘</string>
<string name="settings_launcher_sensitivity">灵敏度</string>
<string name="settings_meta_cant_select_launcher">应用信息</string>
<string name="settings_meta_cant_select_launcher_msg">您的设备不支持此功能。要不打开应用程序详细?</string>
<string name="settings_meta_show_tutorial">查看启动器教程</string>
<string name="settings_meta_reset">重置设置</string>
<string name="settings_meta_reset_confirm">你将放弃你所有的配置。继续吗?</string>

View file

@ -176,7 +176,7 @@
<!-- Legal -->
<string name="legal_info_text"><![CDATA[
<h2>µLauncher</h2>
<h2>μLauncher</h2>
Modifications to Launcher.
<p><a href=\"https://github.com/jrpie/launcher\">github.com/jrpie/launcher</a></p>

View file

@ -179,7 +179,7 @@
<string name="settings_apps_hide_paused_apps">Hide paused apps</string>
<string name="settings_apps_hide_private_space_apps">Hide private space from app list</string>
<string name="settings_list_layout">Layout of app list</string>
<string name="settings_list_reverse_layout">Reverse app list</string>
<string name="settings_list_reverse_layout">Reverse the app list</string>
<string name="settings_list_layout_item_default">Default</string>
<string name="settings_list_layout_item_text">Text</string>
@ -193,7 +193,7 @@
<string name="settings_general_choose_home_screen">Set μLauncher as home screen</string>
<string name="settings_meta_cant_select_launcher">App Info</string>
<string name="settings_meta_show_tutorial">View Launcher Tutorial</string>
<string name="settings_meta_show_tutorial">View µLauncher Tutorial</string>
<string name="settings_meta_reset">Reset Settings</string>
<string name="settings_meta_reset_confirm">You are going to discard all your preferences. Continue?</string>
@ -202,14 +202,14 @@
<string name="settings_meta_report_bug">Report a bug</string>
<string name="dialog_report_bug_title">Report a bug</string>
<string name="dialog_report_bug_info">Thank you for helping to improve µLauncher!\nPlease consider adding the following information to your bug report:</string>
<string name="dialog_report_bug_info">Thank you for helping to improve μLauncher!\nPlease consider adding the following information to your bug report:</string>
<string name="dialog_report_bug_button_clipboard">Copy to clipboard</string>
<string name="dialog_report_bug_security_info">Please do not report security vulnerabilities publicly on GitHub, but use the following instead:</string>
<string name="dialog_report_bug_button_security">Report a security vulnerability</string>
<string name="dialog_report_bug_create_report">Create report</string>
<string name="settings_meta_fork_contact">Contact the developer of the fork</string>
<string name="settings_meta_join_chat">Join µLauncher chat</string>
<string name="settings_meta_join_chat">Join μLauncher chat</string>
<string name="settings_meta_donate">Donate</string>
<string name="settings_meta_privacy">Privacy Policy</string>
@ -246,7 +246,7 @@
<string name="list_apps_search_hint">Search</string>
<string name="list_apps_search_hint_no_auto_launch">Search (no auto launch)</string>
<string name="list_other_settings">µLauncher Settings</string>
<string name="list_other_settings">μLauncher Settings</string>
<string name="list_other_list">All Applications</string>
<string name="list_other_list_favorites">Favorite Applications</string>
<string name="list_other_list_private_space">Private Space</string>
@ -274,22 +274,29 @@
-
-->
<string name="tutorial_title">Tutorial</string>
<string name="tutorial_start_text">Take a few seconds to learn how to use this Launcher!</string>
<string name="tutorial_start_text">👋\n\nTake a few seconds to learn how to use this Launcher!</string>
<string name="tutorial_concept_title">Concept</string>
<string name="tutorial_concept_text">Launcher is designed to be minimal, efficient and free of distraction. It is free of payments, ads and tracking services.</string>
<string name="tutorial_concept_text_2">The app is open-source (MIT license) and available on GitHub! Make sure to check out the repository!</string>
<string name="tutorial_concept_text">μLauncher is designed to be minimal, efficient and free of distraction.
\n\nIt contains no ads and collects no data.</string>
<string name="tutorial_concept_text_2">It is free software (MIT license)!\nMake sure to check out the repository!</string>
<string name="tutorial_concept_label_version">Version</string>
<string name="tutorial_usage_title">Usage</string>
<string name="tutorial_usage_text">Your home screen contains the local date and time. No distraction.</string>
<string name="tutorial_usage_text_2">You can launch your apps with a single swipe or button press. Choose some in the next slide.</string>
<string name="tutorial_usage_text_2">You can launch your most important apps with touch gestures or button presses.</string>
<string name="tutorial_app_list_title">All Apps</string>
<string name="tutorial_app_list_text">You can quickly search through all apps in the app list.\n\nSwipe up to open it, or bind it to a different gesture.</string>
<string name="tutorial_app_list_text_2">Once only one app matches, it launches automatically.\nThis can be disabled by prefixing the query with a space.</string>
<string name="tutorial_setup_title">Setup</string>
<string name="tutorial_setup_text">We chose some default apps for you. You can change them now if you want to:</string>
<string name="tutorial_setup_text_2">You can also change your selection later.</string>
<string name="tutorial_finish_title">Let\'s go!</string>
<string name="tutorial_finish_text">You are ready to get started! I hope this is of great value to you! - Finn (who made Launcher) \tand Josia (who made some improvements and maintains the fork μLauncher)</string>
<string name="tutorial_finish_text">You are ready to get started!\n\nI hope this is of great value to you!\n\n- Finn (who made Launcher) and Josia (who made some improvements and maintains the fork μLauncher)</string>
<string name="tutorial_finish_button">Start</string>
@ -301,7 +308,7 @@
<string name="snackbar_app_hidden">App hidden. You can make it visible again in settings.</string>
<string name="undo">Undo</string>
<string name="list_other_expand_settings_panel">Quick Settings</string>
<string name="toast_device_admin_not_enabled">µLauncher needs to be a device admin in order to lock the screen.</string>
<string name="toast_device_admin_not_enabled">μLauncher needs to be a device admin in order to lock the screen.</string>
<string name="device_admin_explanation">This is required for the lock screen action.</string>
<string name="device_admin_description">Enable the lock screen action</string>
<string name="alert_no_torch_found">No camera with torch detected.</string>
@ -311,18 +318,18 @@
<string name="toast_private_space_locked">Private space locked</string>
<string name="toast_private_space_unlocked">Private space unlocked</string>
<string name="toast_private_space_not_available">Private space is not available</string>
<string name="toast_private_space_default_home_screen">µLauncher needs to be the default home screen to access private space.</string>
<string name="toast_private_space_default_home_screen">μLauncher needs to be the default home screen to access private space.</string>
<string name="tooltip_lock_private_space">Lock private space</string>
<string name="tooltip_unlock_private_space">Unlock private space</string>
<string name="toast_lock_screen_not_supported">Error: Locking the screen using accessibility is not supported on this device. Please use device admin instead.</string>
<string name="accessibility_service_name">µLauncher - lock screen</string>
<string name="accessibility_service_name">μLauncher - lock screen</string>
<string name="accessibility_service_description">
Setting µLauncher as an accessibility service allows it to lock the screen.
Setting μLauncher as an accessibility service allows it to lock the screen.
Note that excessive permissions are required. You should never grant such permissions lightly to any app.
µLauncher will use the accessibility service only for locking the screen. You can check the source code to make sure.
μLauncher will use the accessibility service only for locking the screen. You can check the source code to make sure.
Note that locking the screen can also be accomplished by granting µLauncher device administrator permissions. However that method doesn\'t work with fingerprint and face unlock.
Note that locking the screen can also be accomplished by granting μLauncher device administrator permissions. However that method doesn\'t work with fingerprint and face unlock.
</string>
@ -340,7 +347,7 @@
<h3>Accessibility Service</h3>
Requires excessive privileges.
µLauncher will use those privileges only for locking the screen.
μLauncher will use those privileges only for locking the screen.
<br/>
(You really should not trust a random app you just downloaded with such a claim, but you can check the <a href=\"https://github.com/jrpie/Launcher\">source code</a>.)
<br/>
@ -363,11 +370,11 @@
<string name="dialog_select_color_ok">Ok</string>
<string name="dialog_select_color_color_hex">Color</string>
<string name="dialog_choose_color_title">Choose color</string>
<string name="dialog_consent_accessibility_privileges">I am aware that this will grant far-reaching privileges to µLauncher.</string>
<string name="dialog_consent_accessibility_privileges">I am aware that this will grant far-reaching privileges to μLauncher.</string>
<string name="dialog_consent_accessibility_other_options">I am aware that other options exist (using device administrator privileges or the power button).</string>
<string name="dialog_consent_accessibility_consent">I consent to µLauncher using the accessibility service to provide functionality unrelated to accessibility.</string>
<string name="dialog_consent_accessibility_data_collection">I consent to µLauncher not collecting any data.</string>
<string name="dialog_consent_accessibility_text"><![CDATA[You are about to activate the accessibility service. This will grant <strong>far-reaching privileges</strong> to µLauncher.<br/>µLauncher will use these privileges <strong>only to lock the screen</strong>. µLauncher <strong>will never collect any data</strong>. In particular, µLauncher does not use the accessibility service to collect any data.]]></string>
<string name="dialog_consent_accessibility_consent">I consent to μLauncher using the accessibility service to provide functionality unrelated to accessibility.</string>
<string name="dialog_consent_accessibility_data_collection">I consent to μLauncher not collecting any data.</string>
<string name="dialog_consent_accessibility_text"><![CDATA[You are about to activate the accessibility service. This will grant <strong>far-reaching privileges</strong> to μLauncher.<br/>μLauncher will use these privileges <strong>only to lock the screen</strong>. μLauncher <strong>will never collect any data</strong>. In particular, μLauncher does not use the accessibility service to collect any data.]]></string>
<string name="dialog_consent_accessibility_title">Activating the Accessibility Service</string>
<string name="dialog_consent_accessibility_ok">Activate Accessibility Service</string>
<string name="dialog_cancel">Cancel</string>

View file

@ -0,0 +1,13 @@
* Pinned shortcuts can now be added to app list
* New action: adjust volume (thank you, zabrinu!)
* Added option to hide navigation bar (thank you, acanoe!)
* Added option to reverse the app list (thank you, spacefrogg!)
* Show question mark icon when an unknown app is bound to a gesture
* Improved German translation
* Improved Portuguese translation (thank you, "Vossa Excelencia"!)
* Fixed detection of long click gesture
* Fixed blurred text in dialogs
* Fixed a crash when private space is locked after app restarts (thank you, alexytomi!)
* Fixed some additional bugs