implement #98 - add option to show private space in different list

This commit is contained in:
Josia Pietsch 2025-02-09 18:49:41 +01:00
parent 944eb89fef
commit d69e3caf71
Signed by: jrpie
GPG key ID: E70B571D66986A2D
15 changed files with 279 additions and 62 deletions

View file

@ -17,12 +17,14 @@ import androidx.preference.PreferenceManager
import de.jrpie.android.launcher.actions.TorchManager
import de.jrpie.android.launcher.apps.AppInfo
import de.jrpie.android.launcher.apps.DetailedAppInfo
import de.jrpie.android.launcher.apps.isPrivateSpaceLocked
import de.jrpie.android.launcher.preferences.LauncherPreferences
import de.jrpie.android.launcher.preferences.migratePreferencesToNewVersion
import de.jrpie.android.launcher.preferences.resetPreferences
class Application : android.app.Application() {
val apps = MutableLiveData<List<DetailedAppInfo>>()
val privateSpaceLocked = MutableLiveData<Boolean>()
private val profileAvailabilityBroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
@ -144,6 +146,7 @@ class Application : android.app.Application() {
}
private fun loadApps() {
privateSpaceLocked.postValue(isPrivateSpaceLocked(this))
AsyncTask.execute { apps.postValue(getApps(packageManager, applicationContext)) }
}
}

View file

@ -22,6 +22,8 @@ import de.jrpie.android.launcher.actions.Action
import de.jrpie.android.launcher.actions.Gesture
import de.jrpie.android.launcher.apps.AppInfo
import de.jrpie.android.launcher.apps.DetailedAppInfo
import de.jrpie.android.launcher.apps.getPrivateSpaceUser
import de.jrpie.android.launcher.apps.isPrivateSpaceSupported
import de.jrpie.android.launcher.preferences.LauncherPreferences
import de.jrpie.android.launcher.ui.tutorial.TutorialActivity
@ -48,14 +50,15 @@ fun isDefaultHomeScreen(context: Context): Boolean {
}
fun setDefaultHomeScreen(context: Context, checkDefault: Boolean = false) {
if (checkDefault && isDefaultHomeScreen(context)) {
val isDefault = isDefaultHomeScreen(context)
if (checkDefault && isDefault) {
// Launcher is already the default home app
return
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
&& context is Activity
&& checkDefault // using role manager only works when µLauncher is not already the default.
&& !isDefault // using role manager only works when µLauncher is not already the default.
) {
val roleManager = context.getSystemService(RoleManager::class.java)
context.startActivityForResult(
@ -78,16 +81,6 @@ fun getUserFromId(userId: Int?, context: Context): UserHandle {
return profiles.firstOrNull { it.hashCode() == userId } ?: profiles[0]
}
fun getPrivateSpaceUser(context: Context): UserHandle? {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.VANILLA_ICE_CREAM) {
return null
}
val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager
val launcherApps = context.getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps
return userManager.userProfiles.firstOrNull { u ->
launcherApps.getLauncherUserInfo(u)?.userType == UserManager.USER_TYPE_PROFILE_PRIVATE
}
}
fun openInBrowser(url: String, context: Context) {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
@ -116,6 +109,8 @@ fun getApps(packageManager: PackageManager, context: Context): MutableList<Detai
val launcherApps = context.getSystemService(Service.LAUNCHER_APPS_SERVICE) as LauncherApps
val userManager = context.getSystemService(Service.USER_SERVICE) as UserManager
val privateSpaceUser = getPrivateSpaceUser(context)
// TODO: shortcuts - launcherApps.getShortcuts()
val users = userManager.userProfiles
for (user in users) {
@ -127,7 +122,7 @@ fun getApps(packageManager: PackageManager, context: Context): MutableList<Detai
continue
}
// hide apps from private space
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM &&
if (isPrivateSpaceSupported() &&
launcherApps.getLauncherUserInfo(user)?.userType == UserManager.USER_TYPE_PROFILE_PRIVATE
) {
continue
@ -135,7 +130,7 @@ fun getApps(packageManager: PackageManager, context: Context): MutableList<Detai
}
}
launcherApps.getActivityList(null, user).forEach {
loadList.add(DetailedAppInfo(it))
loadList.add(DetailedAppInfo(it, it.user == privateSpaceUser))
}
}
@ -150,7 +145,8 @@ fun getApps(packageManager: PackageManager, context: Context): MutableList<Detai
val detailedAppInfo = DetailedAppInfo(
app,
ri.loadLabel(packageManager),
ri.activityInfo.loadIcon(packageManager)
ri.activityInfo.loadIcon(packageManager),
false
)
loadList.add(detailedAppInfo)
}

View file

@ -1,24 +1,19 @@
package de.jrpie.android.launcher.actions
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.content.pm.LauncherApps
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.media.AudioManager
import android.os.Build
import android.os.SystemClock
import android.os.UserManager
import android.provider.Settings
import android.view.KeyEvent
import android.widget.Toast
import androidx.appcompat.widget.AppCompatDrawableManager
import de.jrpie.android.launcher.Application
import de.jrpie.android.launcher.R
import de.jrpie.android.launcher.apps.AppFilter
import de.jrpie.android.launcher.getPrivateSpaceUser
import de.jrpie.android.launcher.isDefaultHomeScreen
import de.jrpie.android.launcher.apps.isPrivateSpaceSupported
import de.jrpie.android.launcher.apps.togglePrivateSpaceLock
import de.jrpie.android.launcher.preferences.LauncherPreferences
import de.jrpie.android.launcher.ui.list.ListActivity
import de.jrpie.android.launcher.ui.settings.SettingsActivity
@ -62,15 +57,26 @@ enum class LauncherAction(
"choose_from_favorites",
R.string.list_other_list_favorites,
R.drawable.baseline_favorite_24,
{ context -> openAppsList(context, true) },
{ context -> openAppsList(context, favorite = true) },
true
),
CHOOSE_FROM_PRIVATE_SPACE(
"choose_from_private_space",
R.string.list_other_list_private_space,
R.drawable.baseline_security_24,
{ context ->
openAppsList(context, private = true)
},
available = { _ ->
isPrivateSpaceSupported()
}
),
TOGGLE_PRIVATE_SPACE_LOCK(
"toggle_private_space_lock",
R.string.list_other_toggle_private_space_lock,
R.drawable.baseline_security_24,
::togglePrivateSpaceLock,
available = { Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM }
available = { _ -> isPrivateSpaceSupported() }
),
VOLUME_UP(
"volume_up",
@ -107,7 +113,7 @@ enum class LauncherAction(
LOCK_SCREEN(
"lock_screen",
R.string.list_other_lock_screen,
R.drawable.baseline_lock_24px,
R.drawable.baseline_lock_24,
{ c -> LauncherPreferences.actions().lockMethod().lockOrEnable(c) }
),
TORCH(
@ -230,37 +236,6 @@ private fun expandNotificationsPanel(context: Context) {
}
}
private fun togglePrivateSpaceLock(context: Context) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.VANILLA_ICE_CREAM) {
Toast.makeText(
context,
context.getString(R.string.alert_requires_android_v),
Toast.LENGTH_LONG
).show()
return
}
val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager
val privateSpaceUser = getPrivateSpaceUser(context)
if (privateSpaceUser == null) {
Toast.makeText(context, context.getString(R.string.toast_private_space_not_available), Toast.LENGTH_LONG).show()
if (!isDefaultHomeScreen(context)) {
Toast.makeText(context, context.getString(R.string.toast_private_space_default_home_screen), Toast.LENGTH_LONG).show()
return
}
try {
context.startActivity(Intent(Settings.ACTION_PRIVACY_SETTINGS))
} catch (_: ActivityNotFoundException) {}
return
}
if (userManager.isQuietModeEnabled(privateSpaceUser)) {
userManager.requestQuietModeEnabled(false, privateSpaceUser)
return
}
userManager.requestQuietModeEnabled(true, privateSpaceUser)
Toast.makeText(context, context.getString(R.string.toast_private_space_locked), Toast.LENGTH_LONG).show()
}
private fun expandSettingsPanel(context: Context) {
/* https://stackoverflow.com/a/31898506 */
@ -283,7 +258,12 @@ private fun openSettings(context: Context) {
context.startActivity(Intent(context, SettingsActivity::class.java))
}
fun openAppsList(context: Context, favorite: Boolean = false, hidden: Boolean = false) {
fun openAppsList(
context: Context,
favorite: Boolean = false,
hidden: Boolean = false,
private: Boolean = false
) {
val intent = Intent(context, ListActivity::class.java)
intent.putExtra("intention", ListActivity.ListActivityIntention.VIEW.toString())
intent.putExtra(
@ -302,6 +282,16 @@ fun openAppsList(context: Context, favorite: Boolean = false, hidden: Boolean =
AppFilter.Companion.AppSetVisibility.HIDDEN
}
)
intent.putExtra(
"privateSpaceVisibility",
if (private) {
AppFilter.Companion.AppSetVisibility.EXCLUSIVE
} else if (!hidden && LauncherPreferences.apps().hidePrivateSpaceApps()) {
AppFilter.Companion.AppSetVisibility.HIDDEN
} else {
AppFilter.Companion.AppSetVisibility.VISIBLE
}
)
context.startActivity(intent)
}

View file

@ -15,6 +15,7 @@ class AppFilter(
var query: String,
var favoritesVisibility: AppSetVisibility = AppSetVisibility.VISIBLE,
var hiddenVisibility: AppSetVisibility = AppSetVisibility.HIDDEN,
var privateSpaceVisibility: AppSetVisibility = AppSetVisibility.VISIBLE
) {
operator fun invoke(apps: List<DetailedAppInfo>): List<DetailedAppInfo> {
@ -23,10 +24,12 @@ class AppFilter(
val hidden = LauncherPreferences.apps().hidden() ?: setOf()
val favorites = LauncherPreferences.apps().favorites() ?: setOf()
val private = apps.filter { it.isPrivateSpaceApp }.map { it.app }.toSet()
apps = apps.filter { info ->
favoritesVisibility.predicate(favorites, info)
&& hiddenVisibility.predicate(hidden, info)
&& privateSpaceVisibility.predicate(private, info)
}
if (LauncherPreferences.apps().hideBoundApps()) {

View file

@ -15,10 +15,11 @@ class DetailedAppInfo(
val app: AppInfo,
val label: CharSequence,
val icon: Drawable,
val isPrivateSpaceApp: Boolean,
val isSystemApp: Boolean = false,
) {
constructor(activityInfo: LauncherActivityInfo) : this(
constructor(activityInfo: LauncherActivityInfo, private: Boolean) : this(
AppInfo(
activityInfo.applicationInfo.packageName,
activityInfo.name,
@ -26,6 +27,7 @@ class DetailedAppInfo(
),
activityInfo.label,
activityInfo.getBadgedIcon(0),
private,
activityInfo.applicationInfo.flags.and(ApplicationInfo.FLAG_SYSTEM) != 0
)
@ -51,7 +53,9 @@ class DetailedAppInfo(
companion object {
fun fromAppInfo(appInfo: AppInfo, context: Context): DetailedAppInfo? {
return appInfo.getLauncherActivityInfo(context)?.let { DetailedAppInfo(it) }
return appInfo.getLauncherActivityInfo(context)?.let {
DetailedAppInfo(it, it.user == getPrivateSpaceUser(context))
}
}
}
}

View file

@ -0,0 +1,118 @@
package de.jrpie.android.launcher.apps
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.content.pm.LauncherApps
import android.os.Build
import android.os.UserHandle
import android.os.UserManager
import android.provider.Settings
import android.widget.Toast
import de.jrpie.android.launcher.R
import de.jrpie.android.launcher.isDefaultHomeScreen
import de.jrpie.android.launcher.setDefaultHomeScreen
/*
* Checks whether the device supports private space.
*/
fun isPrivateSpaceSupported(): Boolean {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM
}
fun getPrivateSpaceUser(context: Context): UserHandle? {
if (!isPrivateSpaceSupported()) {
return null
}
val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager
val launcherApps = context.getSystemService(Context.LAUNCHER_APPS_SERVICE) as LauncherApps
return userManager.userProfiles.firstOrNull { u ->
launcherApps.getLauncherUserInfo(u)?.userType == UserManager.USER_TYPE_PROFILE_PRIVATE
}
}
/**
* Check whether the user has created a private space and whether µLauncher can access it.
*/
fun isPrivateSpaceSetUp(
context: Context,
showToast: Boolean = false,
launchSettings: Boolean = false
): Boolean {
if (!isPrivateSpaceSupported()) {
if (showToast) {
Toast.makeText(
context,
context.getString(R.string.alert_requires_android_v),
Toast.LENGTH_LONG
).show()
}
return false
}
val privateSpaceUser = getPrivateSpaceUser(context)
if (privateSpaceUser != null) {
return true
}
if (!isDefaultHomeScreen(context)) {
if (showToast) {
Toast.makeText(
context,
context.getString(R.string.toast_private_space_default_home_screen),
Toast.LENGTH_LONG
).show()
}
if (launchSettings) {
setDefaultHomeScreen(context)
}
} else {
if (showToast) {
Toast.makeText(
context,
context.getString(R.string.toast_private_space_not_available),
Toast.LENGTH_LONG
).show()
}
if (launchSettings) {
try {
context.startActivity(Intent(Settings.ACTION_PRIVACY_SETTINGS))
} catch (_: ActivityNotFoundException) {
}
}
}
return false
}
fun isPrivateSpaceLocked(context: Context): Boolean {
if (!isPrivateSpaceSupported()) {
return false
}
val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager
val privateSpaceUser = getPrivateSpaceUser(context) ?: return false
return userManager.isQuietModeEnabled(privateSpaceUser)
}
fun lockPrivateSpace(context: Context, lock: Boolean) {
if (!isPrivateSpaceSupported()) {
return
}
val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager
val privateSpaceUser = getPrivateSpaceUser(context) ?: return
userManager.requestQuietModeEnabled(lock, privateSpaceUser)
}
fun togglePrivateSpaceLock(context: Context) {
if (!isPrivateSpaceSetUp(context, showToast = true, launchSettings = true)) {
return
}
val lock = isPrivateSpaceLocked(context)
lockPrivateSpace(context, !lock)
if (!lock) {
Toast.makeText(
context,
context.getString(R.string.toast_private_space_locked),
Toast.LENGTH_LONG
).show()
}
}

View file

@ -30,6 +30,7 @@ import eu.jonahbauer.android.preference.annotations.Preferences;
@Preference(name = "custom_names", type = HashMap.class, serializer = MapAppInfoStringPreferenceSerializer.class),
@Preference(name = "hide_bound_apps", type = boolean.class, defaultValue = "false"),
@Preference(name = "hide_paused_apps", type = boolean.class, defaultValue = "false"),
@Preference(name = "hide_private_space_apps", type = boolean.class, defaultValue = "false"),
}),
@PreferenceGroup(name = "list", prefix = "settings_list_", suffix = "_key", value = {
@Preference(name = "layout", type = ListLayout.class, defaultValue = "DEFAULT")

View file

@ -16,10 +16,14 @@ 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.Application
import de.jrpie.android.launcher.R
import de.jrpie.android.launcher.REQUEST_UNINSTALL
import de.jrpie.android.launcher.actions.LauncherAction
import de.jrpie.android.launcher.apps.AppFilter
import de.jrpie.android.launcher.apps.isPrivateSpaceLocked
import de.jrpie.android.launcher.apps.isPrivateSpaceSetUp
import de.jrpie.android.launcher.apps.togglePrivateSpaceLock
import de.jrpie.android.launcher.databinding.ListBinding
import de.jrpie.android.launcher.preferences.LauncherPreferences
import de.jrpie.android.launcher.ui.UIObject
@ -30,6 +34,8 @@ 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
@ -44,6 +50,29 @@ class ListActivity : AppCompatActivity(), UIObject {
private lateinit var binding: ListBinding
private fun updateLockIcon(locked: Boolean) {
binding.listLock.setImageDrawable(
getDrawable(
if (locked) {
R.drawable.baseline_lock_24
} else {
R.drawable.baseline_lock_open_24
}
)
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
binding.listLock.tooltipText = getString(
if (locked) {
R.string.tooltip_unlock_private_space
} else {
R.string.tooltip_lock_private_space
}
)
}
}
enum class ListActivityIntention(val titleResource: Int) {
VIEW(R.string.list_title_view), /* view list of apps */
PICK(R.string.list_title_pick) /* choose app or action to associate to a gesture */
@ -70,8 +99,10 @@ class ListActivity : AppCompatActivity(), UIObject {
favoritesVisibility = bundle.getSerializable("favoritesVisibility")
as? AppFilter.Companion.AppSetVisibility ?: favoritesVisibility
privateSpaceVisibility = bundle.getSerializable("privateSpaceVisibility")
as? AppFilter.Companion.AppSetVisibility ?: privateSpaceVisibility
hiddenVisibility = bundle.getSerializable("hiddenVisibility")
as? AppFilter.Companion.AppSetVisibility ?: favoritesVisibility
as? AppFilter.Companion.AppSetVisibility ?: hiddenVisibility
if (intention != ListActivityIntention.VIEW)
forGesture = bundle.getString("forGesture")
@ -86,6 +117,31 @@ class ListActivity : AppCompatActivity(), UIObject {
LauncherAction.SETTINGS.launch(this@ListActivity)
}
binding.listLock.visibility =
if (intention != ListActivityIntention.VIEW) {
View.GONE
} else if (!isPrivateSpaceSetUp(this)) {
View.GONE
} else if (LauncherPreferences.apps().hidePrivateSpaceApps()) {
if (privateSpaceVisibility == AppFilter.Companion.AppSetVisibility.EXCLUSIVE) {
View.VISIBLE
} else {
View.GONE
}
} else {
View.VISIBLE
}
if (privateSpaceVisibility == AppFilter.Companion.AppSetVisibility.EXCLUSIVE) {
isPrivateSpaceSetUp(this, showToast = true, launchSettings = true)
if (isPrivateSpaceLocked(this)) {
togglePrivateSpaceLock(this)
}
}
updateLockIcon(isPrivateSpaceLocked(this))
val privateSpaceLocked = (this.applicationContext as Application).privateSpaceLocked
privateSpaceLocked.observe(this) { updateLockIcon(it) }
// android:windowSoftInputMode="adjustResize" doesn't work in full screen.
// workaround from https://stackoverflow.com/a/57623505
@ -144,6 +200,8 @@ class ListActivity : AppCompatActivity(), UIObject {
if (intention == ListActivityIntention.VIEW) {
titleResource = if (hiddenVisibility == AppFilter.Companion.AppSetVisibility.EXCLUSIVE) {
R.string.list_title_hidden
} else if (privateSpaceVisibility == AppFilter.Companion.AppSetVisibility.EXCLUSIVE) {
R.string.list_title_private_space
} else if (favoritesVisibility == AppFilter.Companion.AppSetVisibility.EXCLUSIVE) {
R.string.list_title_favorite
} else {
@ -161,6 +219,12 @@ class ListActivity : AppCompatActivity(), UIObject {
override fun setOnClicks() {
binding.listClose.setOnClickListener { finish() }
binding.listLock.setOnClickListener {
togglePrivateSpaceLock(this)
if (privateSpaceVisibility == AppFilter.Companion.AppSetVisibility.EXCLUSIVE) {
finish()
}
}
}
override fun adjustLayout() {

View file

@ -19,6 +19,7 @@ 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
@ -72,6 +73,7 @@ class ListFragmentApps : Fragment(), UIObject {
requireContext(),
"",
favoritesVisibility = favoritesVisibility,
privateSpaceVisibility = privateSpaceVisibility,
hiddenVisibility = hiddenVisibility
),
layout = LauncherPreferences.list().layout()

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="?android:textColor"
android:pathData="M12,17c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6h1.9c0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0 3.1,1.39 3.1,3.1v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM18,20L6,20L6,10h12v10z" />
</vector>

View file

@ -53,8 +53,8 @@
android:text="@string/list_title_pick"
android:textAppearance="@style/TextAppearance.Widget.AppCompat.Toolbar.Title"
android:textSize="30sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/list_lock"
app:layout_constraintStart_toEndOf="@id/list_settings"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
@ -72,6 +72,21 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
custom:type="solid" />
<ImageView
android:id="@+id/list_lock"
android:visibility="gone"
tools:visibility="visible"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:includeFontPadding="true"
android:paddingLeft="0sp"
android:paddingRight="0sp"
android:src="@drawable/baseline_lock_24"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/list_close"
app:layout_constraintTop_toTopOf="parent"
custom:type="solid" />
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.tabs.TabLayout

View file

@ -14,6 +14,7 @@
<string name="settings_apps_custom_names_key" translatable="false">apps.custom_names</string>
<string name="settings_apps_hide_bound_apps_key" translatable="false">apps.hide_bound_apps</string>
<string name="settings_apps_hide_paused_apps_key" translatable="false">apps.hide_paused_apps</string>
<string name="settings_apps_hide_private_space_apps_key" translatable="false">apps.hide_private_space_apps</string>
<string name="settings_list_layout_key" translatable="false">list.layout</string>
<string name="settings_general_choose_home_screen_key" translatable="false">general.select_launcher</string>

View file

@ -150,6 +150,7 @@
<string name="settings_apps_hidden">Hidden apps</string>
<string name="settings_apps_hide_bound_apps">Don\'t show apps that are bound to a gesture in the app list</string>
<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_layout_item_default">Default</string>
@ -197,6 +198,7 @@
<string name="list_title_view">All Apps</string>
<string name="list_title_favorite">Favorite Apps</string>
<string name="list_title_hidden">Hidden Apps</string>
<string name="list_title_private_space">Private Space</string>
<string name="list_title_pick">Choose App</string>
<string name="list_tab_app">Apps</string>
@ -219,6 +221,7 @@
<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>
<string name="list_other_toggle_private_space_lock">Toggle Private Space Lock</string>
<string name="list_other_volume_up">Music: Louder</string>
<string name="list_other_volume_down">Music: Quieter</string>
@ -273,6 +276,8 @@
<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="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_description">

View file

@ -151,6 +151,11 @@
android:title="@string/settings_apps_hide_paused_apps"
android:defaultValue="false" />
<SwitchPreference
android:key="@string/settings_apps_hide_private_space_apps_key"
android:title="@string/settings_apps_hide_private_space_apps"
android:defaultValue="false" />
<DropDownPreference
android:key="@string/settings_list_layout_key"
android:title="@string/settings_list_layout"