Compare commits

..

9 commits

Author SHA1 Message Date
Vossa Excelencia
15543b2b9c Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (220 of 220 strings)

Translation: jrpie-Launcher/Launcher
Translate-URL: https://toolate.othing.xyz/projects/jrpie-launcher/launcher/pt_BR/
2025-02-10 00:07:17 +00:00
Vossa Excelencia
e6fca45d48 Translated using Weblate (Portuguese (Brazil))
Currently translated at 20.0% (3 of 15 strings)

Translation: jrpie-Launcher/metadata
Translate-URL: https://toolate.othing.xyz/projects/jrpie-launcher/metadata/pt_BR/
2025-02-10 00:07:17 +00:00
Vossa Excelencia
8501e85f2d Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (220 of 220 strings)

Translation: jrpie-Launcher/Launcher
Translate-URL: https://toolate.othing.xyz/projects/jrpie-launcher/launcher/pt_BR/
2025-02-10 00:07:17 +00:00
Nicola Bortoletto
f8d943904a Translated using Weblate (Italian)
Currently translated at 99.0% (216 of 218 strings)

Translation: jrpie-Launcher/Launcher
Translate-URL: https://toolate.othing.xyz/projects/jrpie-launcher/launcher/it/
2025-02-10 00:07:17 +00:00
Vossa Excelencia
09f944ec42 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (218 of 218 strings)

Translation: jrpie-Launcher/Launcher
Translate-URL: https://toolate.othing.xyz/projects/jrpie-launcher/launcher/pt_BR/
2025-02-10 00:07:17 +00:00
Xanadul
91b0c50f83 Translated using Weblate (German)
Currently translated at 13.3% (2 of 15 strings)

Translation: jrpie-Launcher/metadata
Translate-URL: https://toolate.othing.xyz/projects/jrpie-launcher/metadata/de/
2025-02-10 00:07:17 +00:00
Nicola Bortoletto
ef47a8d305 Translated using Weblate (Italian)
Currently translated at 98.1% (214 of 218 strings)

Translation: jrpie-Launcher/Launcher
Translate-URL: https://toolate.othing.xyz/projects/jrpie-launcher/launcher/it/
2025-02-10 00:07:17 +00:00
9c5500aa83
lint
Some checks are pending
Android CI / build (push) Waiting to run
2025-02-09 21:08:16 +01:00
d69e3caf71
implement #98 - add option to show private space in different list 2025-02-09 18:49:41 +01:00
30 changed files with 312 additions and 107 deletions

View file

@ -100,7 +100,7 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.2.0' implementation 'androidx.constraintlayout:constraintlayout:2.2.0'
implementation 'androidx.gridlayout:gridlayout:1.0.0' implementation 'androidx.gridlayout:gridlayout:1.0.0'
implementation 'androidx.palette:palette-ktx:1.0.0' implementation 'androidx.palette:palette-ktx:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.3.2' implementation 'androidx.recyclerview:recyclerview:1.4.0'
implementation 'androidx.preference:preference-ktx:1.2.1' implementation 'androidx.preference:preference-ktx:1.2.1'
implementation 'com.google.android.material:material:1.12.0' implementation 'com.google.android.material:material:1.12.0'
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")

View file

@ -17,12 +17,14 @@ import androidx.preference.PreferenceManager
import de.jrpie.android.launcher.actions.TorchManager import de.jrpie.android.launcher.actions.TorchManager
import de.jrpie.android.launcher.apps.AppInfo import de.jrpie.android.launcher.apps.AppInfo
import de.jrpie.android.launcher.apps.DetailedAppInfo 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.LauncherPreferences
import de.jrpie.android.launcher.preferences.migratePreferencesToNewVersion import de.jrpie.android.launcher.preferences.migratePreferencesToNewVersion
import de.jrpie.android.launcher.preferences.resetPreferences import de.jrpie.android.launcher.preferences.resetPreferences
class Application : android.app.Application() { class Application : android.app.Application() {
val apps = MutableLiveData<List<DetailedAppInfo>>() val apps = MutableLiveData<List<DetailedAppInfo>>()
val privateSpaceLocked = MutableLiveData<Boolean>()
private val profileAvailabilityBroadcastReceiver = object : BroadcastReceiver() { private val profileAvailabilityBroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) { override fun onReceive(context: Context?, intent: Intent?) {
@ -144,6 +146,7 @@ class Application : android.app.Application() {
} }
private fun loadApps() { private fun loadApps() {
privateSpaceLocked.postValue(isPrivateSpaceLocked(this))
AsyncTask.execute { apps.postValue(getApps(packageManager, applicationContext)) } 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.actions.Gesture
import de.jrpie.android.launcher.apps.AppInfo import de.jrpie.android.launcher.apps.AppInfo
import de.jrpie.android.launcher.apps.DetailedAppInfo 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.preferences.LauncherPreferences
import de.jrpie.android.launcher.ui.tutorial.TutorialActivity import de.jrpie.android.launcher.ui.tutorial.TutorialActivity
@ -48,14 +50,15 @@ fun isDefaultHomeScreen(context: Context): Boolean {
} }
fun setDefaultHomeScreen(context: Context, checkDefault: Boolean = false) { 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 // Launcher is already the default home app
return return
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
&& context is Activity && 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) val roleManager = context.getSystemService(RoleManager::class.java)
context.startActivityForResult( context.startActivityForResult(
@ -78,16 +81,6 @@ fun getUserFromId(userId: Int?, context: Context): UserHandle {
return profiles.firstOrNull { it.hashCode() == userId } ?: profiles[0] 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) { fun openInBrowser(url: String, context: Context) {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) 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 launcherApps = context.getSystemService(Service.LAUNCHER_APPS_SERVICE) as LauncherApps
val userManager = context.getSystemService(Service.USER_SERVICE) as UserManager val userManager = context.getSystemService(Service.USER_SERVICE) as UserManager
val privateSpaceUser = getPrivateSpaceUser(context)
// TODO: shortcuts - launcherApps.getShortcuts() // TODO: shortcuts - launcherApps.getShortcuts()
val users = userManager.userProfiles val users = userManager.userProfiles
for (user in users) { for (user in users) {
@ -127,7 +122,7 @@ fun getApps(packageManager: PackageManager, context: Context): MutableList<Detai
continue continue
} }
// hide apps from private space // 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 launcherApps.getLauncherUserInfo(user)?.userType == UserManager.USER_TYPE_PROFILE_PRIVATE
) { ) {
continue continue
@ -135,7 +130,7 @@ fun getApps(packageManager: PackageManager, context: Context): MutableList<Detai
} }
} }
launcherApps.getActivityList(null, user).forEach { 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( val detailedAppInfo = DetailedAppInfo(
app, app,
ri.loadLabel(packageManager), ri.loadLabel(packageManager),
ri.activityInfo.loadIcon(packageManager) ri.activityInfo.loadIcon(packageManager),
false
) )
loadList.add(detailedAppInfo) loadList.add(detailedAppInfo)
} }
@ -186,5 +182,5 @@ fun getDeviceInfo(): String {
fun copyToClipboard(context: Context, text: String) { fun copyToClipboard(context: Context, text: String) {
val clipboardManager = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager val clipboardManager = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clipData = ClipData.newPlainText("Debug Info", text) val clipData = ClipData.newPlainText("Debug Info", text)
clipboardManager.setPrimaryClip(clipData); clipboardManager.setPrimaryClip(clipData)
} }

View file

@ -273,7 +273,7 @@ enum class Gesture(
companion object { companion object {
fun byId(id: String): Gesture? { fun byId(id: String): Gesture? {
return Gesture.values().firstOrNull { it.id == id } return Gesture.entries.firstOrNull { it.id == id }
} }
} }

View file

@ -1,24 +1,20 @@
package de.jrpie.android.launcher.actions package de.jrpie.android.launcher.actions
import android.content.ActivityNotFoundException
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.LauncherApps
import android.graphics.Rect import android.graphics.Rect
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.media.AudioManager import android.media.AudioManager
import android.os.Build import android.os.Build
import android.os.SystemClock import android.os.SystemClock
import android.os.UserManager
import android.provider.Settings
import android.view.KeyEvent import android.view.KeyEvent
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.widget.AppCompatDrawableManager import androidx.appcompat.content.res.AppCompatResources
import de.jrpie.android.launcher.Application import de.jrpie.android.launcher.Application
import de.jrpie.android.launcher.R import de.jrpie.android.launcher.R
import de.jrpie.android.launcher.apps.AppFilter import de.jrpie.android.launcher.apps.AppFilter
import de.jrpie.android.launcher.getPrivateSpaceUser import de.jrpie.android.launcher.apps.isPrivateSpaceSupported
import de.jrpie.android.launcher.isDefaultHomeScreen import de.jrpie.android.launcher.apps.togglePrivateSpaceLock
import de.jrpie.android.launcher.preferences.LauncherPreferences import de.jrpie.android.launcher.preferences.LauncherPreferences
import de.jrpie.android.launcher.ui.list.ListActivity import de.jrpie.android.launcher.ui.list.ListActivity
import de.jrpie.android.launcher.ui.settings.SettingsActivity import de.jrpie.android.launcher.ui.settings.SettingsActivity
@ -62,15 +58,26 @@ enum class LauncherAction(
"choose_from_favorites", "choose_from_favorites",
R.string.list_other_list_favorites, R.string.list_other_list_favorites,
R.drawable.baseline_favorite_24, R.drawable.baseline_favorite_24,
{ context -> openAppsList(context, true) }, { context -> openAppsList(context, favorite = true) },
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(
"toggle_private_space_lock", "toggle_private_space_lock",
R.string.list_other_toggle_private_space_lock, R.string.list_other_toggle_private_space_lock,
R.drawable.baseline_security_24, R.drawable.baseline_security_24,
::togglePrivateSpaceLock, ::togglePrivateSpaceLock,
available = { Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM } available = { _ -> isPrivateSpaceSupported() }
), ),
VOLUME_UP( VOLUME_UP(
"volume_up", "volume_up",
@ -107,7 +114,7 @@ enum class LauncherAction(
LOCK_SCREEN( LOCK_SCREEN(
"lock_screen", "lock_screen",
R.string.list_other_lock_screen, R.string.list_other_lock_screen,
R.drawable.baseline_lock_24px, R.drawable.baseline_lock_24,
{ c -> LauncherPreferences.actions().lockMethod().lockOrEnable(c) } { c -> LauncherPreferences.actions().lockMethod().lockOrEnable(c) }
), ),
TORCH( TORCH(
@ -128,7 +135,7 @@ enum class LauncherAction(
} }
override fun getIcon(context: Context): Drawable? { override fun getIcon(context: Context): Drawable? {
return context.getDrawable(icon) return AppCompatResources.getDrawable(context, icon)
} }
override fun isAvailable(context: Context): Boolean { override fun isAvailable(context: Context): Boolean {
@ -230,37 +237,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) { private fun expandSettingsPanel(context: Context) {
/* https://stackoverflow.com/a/31898506 */ /* https://stackoverflow.com/a/31898506 */
@ -283,7 +259,12 @@ private fun openSettings(context: Context) {
context.startActivity(Intent(context, SettingsActivity::class.java)) 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) val intent = Intent(context, ListActivity::class.java)
intent.putExtra("intention", ListActivity.ListActivityIntention.VIEW.toString()) intent.putExtra("intention", ListActivity.ListActivityIntention.VIEW.toString())
intent.putExtra( intent.putExtra(
@ -302,6 +283,16 @@ fun openAppsList(context: Context, favorite: Boolean = false, hidden: Boolean =
AppFilter.Companion.AppSetVisibility.HIDDEN 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) context.startActivity(intent)
} }

View file

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

View file

@ -9,16 +9,17 @@ import de.jrpie.android.launcher.Application
import de.jrpie.android.launcher.preferences.LauncherPreferences import de.jrpie.android.launcher.preferences.LauncherPreferences
/** /**
* Stores information used to create [AppsRecyclerAdapter] rows. * Stores information used to create [de.jrpie.android.launcher.ui.list.apps.AppsRecyclerAdapter] rows.
*/ */
class DetailedAppInfo( class DetailedAppInfo(
val app: AppInfo, val app: AppInfo,
val label: CharSequence, val label: CharSequence,
val icon: Drawable, val icon: Drawable,
val isPrivateSpaceApp: Boolean,
val isSystemApp: Boolean = false, val isSystemApp: Boolean = false,
) { ) {
constructor(activityInfo: LauncherActivityInfo) : this( constructor(activityInfo: LauncherActivityInfo, private: Boolean) : this(
AppInfo( AppInfo(
activityInfo.applicationInfo.packageName, activityInfo.applicationInfo.packageName,
activityInfo.name, activityInfo.name,
@ -26,6 +27,7 @@ class DetailedAppInfo(
), ),
activityInfo.label, activityInfo.label,
activityInfo.getBadgedIcon(0), activityInfo.getBadgedIcon(0),
private,
activityInfo.applicationInfo.flags.and(ApplicationInfo.FLAG_SYSTEM) != 0 activityInfo.applicationInfo.flags.and(ApplicationInfo.FLAG_SYSTEM) != 0
) )
@ -51,7 +53,9 @@ class DetailedAppInfo(
companion object { companion object {
fun fromAppInfo(appInfo: AppInfo, context: Context): DetailedAppInfo? { 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 = "custom_names", type = HashMap.class, serializer = MapAppInfoStringPreferenceSerializer.class),
@Preference(name = "hide_bound_apps", type = boolean.class, defaultValue = "false"), @Preference(name = "hide_bound_apps", type = boolean.class, defaultValue = "false"),
@Preference(name = "hide_paused_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 = { @PreferenceGroup(name = "list", prefix = "settings_list_", suffix = "_key", value = {
@Preference(name = "layout", type = ListLayout.class, defaultValue = "DEFAULT") @Preference(name = "layout", type = ListLayout.class, defaultValue = "DEFAULT")

View file

@ -68,9 +68,9 @@ private fun Action.Companion.legacyFromPreference(id: String): Action? {
val actionId = preferences.getString("$id.app", "")!! val actionId = preferences.getString("$id.app", "")!!
var u: Int? = preferences.getInt( var u: Int? = preferences.getInt(
"$id.user", "$id.user",
AppInfo.INVALID_USER INVALID_USER
) )
u = if (u == AppInfo.INVALID_USER) null else u u = if (u == INVALID_USER) null else u
return Action.legacyFromId(actionId, u) return Action.legacyFromId(actionId, u)
} }
@ -80,9 +80,9 @@ private fun migrateAppInfoStringMap(key: String) {
MapAppInfoStringPreferenceSerializer().serialize( MapAppInfoStringPreferenceSerializer().serialize(
preferences.getStringSet(key, setOf())?.mapNotNull { entry -> preferences.getStringSet(key, setOf())?.mapNotNull { entry ->
try { try {
val obj = JSONObject(entry); val obj = JSONObject(entry)
val info = AppInfo.legacyDeserialize(obj.getString("key")) val info = AppInfo.legacyDeserialize(obj.getString("key"))
val value = obj.getString("value"); val value = obj.getString("value")
Pair(info, value) Pair(info, value)
} catch (_: JSONException) { } catch (_: JSONException) {
null null

View file

@ -4,7 +4,6 @@ import android.content.Context
import android.content.SharedPreferences import android.content.SharedPreferences
import android.util.Log import android.util.Log
import de.jrpie.android.launcher.preferences.LauncherPreferences import de.jrpie.android.launcher.preferences.LauncherPreferences
import de.jrpie.android.launcher.preferences.PREFERENCE_VERSION
import de.jrpie.android.launcher.preferences.theme.Background import de.jrpie.android.launcher.preferences.theme.Background
import de.jrpie.android.launcher.preferences.theme.ColorTheme import de.jrpie.android.launcher.preferences.theme.ColorTheme

View file

@ -15,7 +15,7 @@ import kotlinx.serialization.json.Json
class SetAppInfoPreferenceSerializer : class SetAppInfoPreferenceSerializer :
PreferenceSerializer<java.util.Set<AppInfo>?, java.util.Set<java.lang.String>?> { PreferenceSerializer<java.util.Set<AppInfo>?, java.util.Set<java.lang.String>?> {
@Throws(PreferenceSerializationException::class) @Throws(PreferenceSerializationException::class)
override fun serialize(value: java.util.Set<AppInfo>?): java.util.Set<java.lang.String>? { override fun serialize(value: java.util.Set<AppInfo>?): java.util.Set<java.lang.String> {
return value?.map(AppInfo::serialize)?.toHashSet() as java.util.Set<java.lang.String> return value?.map(AppInfo::serialize)?.toHashSet() as java.util.Set<java.lang.String>
} }
@ -29,7 +29,7 @@ class SetAppInfoPreferenceSerializer :
class MapAppInfoStringPreferenceSerializer : class MapAppInfoStringPreferenceSerializer :
PreferenceSerializer<java.util.HashMap<AppInfo, String>?, java.util.Set<java.lang.String>?> { PreferenceSerializer<java.util.HashMap<AppInfo, String>?, java.util.Set<java.lang.String>?> {
@Serializable() @Serializable
private class MapEntry(val key: AppInfo, val value: String) private class MapEntry(val key: AppInfo, val value: String)
@Throws(PreferenceSerializationException::class) @Throws(PreferenceSerializationException::class)

View file

@ -216,7 +216,7 @@ class HomeActivity : UIObject, AppCompatActivity(),
if (e1 == null) return false if (e1 == null) return false
val displayMetrics: DisplayMetrics = DisplayMetrics() val displayMetrics = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(displayMetrics) windowManager.defaultDisplay.getMetrics(displayMetrics)
val width = displayMetrics.widthPixels val width = displayMetrics.widthPixels

View file

@ -11,15 +11,20 @@ import android.view.View
import android.widget.Toast import android.widget.Toast
import android.window.OnBackInvokedDispatcher import android.window.OnBackInvokedDispatcher
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.content.res.AppCompatResources
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentPagerAdapter import androidx.fragment.app.FragmentPagerAdapter
import androidx.viewpager.widget.ViewPager import androidx.viewpager.widget.ViewPager
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import de.jrpie.android.launcher.Application
import de.jrpie.android.launcher.R import de.jrpie.android.launcher.R
import de.jrpie.android.launcher.REQUEST_UNINSTALL import de.jrpie.android.launcher.REQUEST_UNINSTALL
import de.jrpie.android.launcher.actions.LauncherAction import de.jrpie.android.launcher.actions.LauncherAction
import de.jrpie.android.launcher.apps.AppFilter 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.databinding.ListBinding
import de.jrpie.android.launcher.preferences.LauncherPreferences import de.jrpie.android.launcher.preferences.LauncherPreferences
import de.jrpie.android.launcher.ui.UIObject import de.jrpie.android.launcher.ui.UIObject
@ -30,6 +35,8 @@ import de.jrpie.android.launcher.ui.list.other.ListFragmentOther
// TODO: Better solution for this intercommunication functionality (used in list-fragments) // TODO: Better solution for this intercommunication functionality (used in list-fragments)
var intention = ListActivity.ListActivityIntention.VIEW var intention = ListActivity.ListActivityIntention.VIEW
var favoritesVisibility: AppFilter.Companion.AppSetVisibility = AppFilter.Companion.AppSetVisibility.VISIBLE 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 hiddenVisibility: AppFilter.Companion.AppSetVisibility = AppFilter.Companion.AppSetVisibility.HIDDEN
var forGesture: String? = null var forGesture: String? = null
@ -44,6 +51,30 @@ class ListActivity : AppCompatActivity(), UIObject {
private lateinit var binding: ListBinding private lateinit var binding: ListBinding
private fun updateLockIcon(locked: Boolean) {
binding.listLock.setImageDrawable(
AppCompatResources.getDrawable(
this,
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) { enum class ListActivityIntention(val titleResource: Int) {
VIEW(R.string.list_title_view), /* view list of apps */ 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 */ PICK(R.string.list_title_pick) /* choose app or action to associate to a gesture */
@ -70,8 +101,10 @@ class ListActivity : AppCompatActivity(), UIObject {
favoritesVisibility = bundle.getSerializable("favoritesVisibility") favoritesVisibility = bundle.getSerializable("favoritesVisibility")
as? AppFilter.Companion.AppSetVisibility ?: favoritesVisibility as? AppFilter.Companion.AppSetVisibility ?: favoritesVisibility
privateSpaceVisibility = bundle.getSerializable("privateSpaceVisibility")
as? AppFilter.Companion.AppSetVisibility ?: privateSpaceVisibility
hiddenVisibility = bundle.getSerializable("hiddenVisibility") hiddenVisibility = bundle.getSerializable("hiddenVisibility")
as? AppFilter.Companion.AppSetVisibility ?: favoritesVisibility as? AppFilter.Companion.AppSetVisibility ?: hiddenVisibility
if (intention != ListActivityIntention.VIEW) if (intention != ListActivityIntention.VIEW)
forGesture = bundle.getString("forGesture") forGesture = bundle.getString("forGesture")
@ -86,6 +119,31 @@ class ListActivity : AppCompatActivity(), UIObject {
LauncherAction.SETTINGS.launch(this@ListActivity) 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. // android:windowSoftInputMode="adjustResize" doesn't work in full screen.
// workaround from https://stackoverflow.com/a/57623505 // workaround from https://stackoverflow.com/a/57623505
@ -144,6 +202,8 @@ class ListActivity : AppCompatActivity(), UIObject {
if (intention == ListActivityIntention.VIEW) { if (intention == ListActivityIntention.VIEW) {
titleResource = if (hiddenVisibility == AppFilter.Companion.AppSetVisibility.EXCLUSIVE) { titleResource = if (hiddenVisibility == AppFilter.Companion.AppSetVisibility.EXCLUSIVE) {
R.string.list_title_hidden 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) { } else if (favoritesVisibility == AppFilter.Companion.AppSetVisibility.EXCLUSIVE) {
R.string.list_title_favorite R.string.list_title_favorite
} else { } else {
@ -161,6 +221,12 @@ class ListActivity : AppCompatActivity(), UIObject {
override fun setOnClicks() { override fun setOnClicks() {
binding.listClose.setOnClickListener { finish() } binding.listClose.setOnClickListener { finish() }
binding.listLock.setOnClickListener {
togglePrivateSpaceLock(this)
if (privateSpaceVisibility == AppFilter.Companion.AppSetVisibility.EXCLUSIVE) {
finish()
}
}
} }
override fun adjustLayout() { override fun adjustLayout() {

View file

@ -33,7 +33,7 @@ fun AppInfo.openSettings(
} }
fun AppInfo.uninstall(activity: android.app.Activity) { fun AppInfo.uninstall(activity: android.app.Activity) {
val packageName = this.packageName.toString() val packageName = this.packageName
val userId = this.user val userId = this.user
Log.i(LOG_TAG, "uninstalling $this") Log.i(LOG_TAG, "uninstalling $this")

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.forGesture
import de.jrpie.android.launcher.ui.list.hiddenVisibility import de.jrpie.android.launcher.ui.list.hiddenVisibility
import de.jrpie.android.launcher.ui.list.intention import de.jrpie.android.launcher.ui.list.intention
import de.jrpie.android.launcher.ui.list.privateSpaceVisibility
import de.jrpie.android.launcher.ui.openSoftKeyboard import de.jrpie.android.launcher.ui.openSoftKeyboard
@ -72,6 +73,7 @@ class ListFragmentApps : Fragment(), UIObject {
requireContext(), requireContext(),
"", "",
favoritesVisibility = favoritesVisibility, favoritesVisibility = favoritesVisibility,
privateSpaceVisibility = privateSpaceVisibility,
hiddenVisibility = hiddenVisibility hiddenVisibility = hiddenVisibility
), ),
layout = LauncherPreferences.list().layout() layout = LauncherPreferences.list().layout()

View file

@ -45,21 +45,6 @@ class SettingsFragmentMeta : Fragment(), UIObject {
super<UIObject>.onStart() super<UIObject>.onStart()
} }
// Rate App
// Just copied code from https://stackoverflow.com/q/10816757/12787264
// that is how we write good software ^^
private fun rateIntentForUrl(url: String): Intent {
val intent = Intent(
Intent.ACTION_VIEW,
Uri.parse(String.format("%s?id=%s", url, this.requireContext().packageName))
)
var flags = Intent.FLAG_ACTIVITY_NO_HISTORY or Intent.FLAG_ACTIVITY_MULTIPLE_TASK
flags = flags or Intent.FLAG_ACTIVITY_NEW_DOCUMENT
intent.addFlags(flags)
return intent
}
override fun setOnClicks() { override fun setOnClicks() {
binding.settingsMetaButtonViewTutorial.setOnClickListener { binding.settingsMetaButtonViewTutorial.setOnClickListener {

View file

@ -21,7 +21,7 @@ class TutorialFragmentConcept : Fragment(), UIObject {
inflater: LayoutInflater, container: ViewGroup?, inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View { ): View {
val binding = TutorialConceptBinding.inflate(inflater, container, false) binding = TutorialConceptBinding.inflate(inflater, container, false)
binding.tutorialConceptBadgeVersion.text = BuildConfig.VERSION_NAME binding.tutorialConceptBadgeVersion.text = BuildConfig.VERSION_NAME
return binding.root return binding.root
} }

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

@ -32,7 +32,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:layout_marginLeft="8dp" android:layout_marginEnd="8dp"
android:contentDescription="@string/settings" android:contentDescription="@string/settings"
android:gravity="center" android:gravity="center"
android:paddingLeft="16sp" android:paddingLeft="16sp"
@ -53,8 +53,8 @@
android:text="@string/list_title_pick" android:text="@string/list_title_pick"
android:textAppearance="@style/TextAppearance.Widget.AppCompat.Toolbar.Title" android:textAppearance="@style/TextAppearance.Widget.AppCompat.Toolbar.Title"
android:textSize="30sp" android:textSize="30sp"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toStartOf="@id/list_lock"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toEndOf="@id/list_settings"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<ImageView <ImageView
@ -62,7 +62,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:layout_marginRight="8dp" android:layout_marginStart="8dp"
android:gravity="center" android:gravity="center"
android:includeFontPadding="true" android:includeFontPadding="true"
android:paddingLeft="16sp" android:paddingLeft="16sp"
@ -72,6 +72,21 @@
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
custom:type="solid" /> 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> </androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.tabs.TabLayout <com.google.android.material.tabs.TabLayout

View file

@ -25,6 +25,7 @@
android:gravity="start|center_horizontal" android:gravity="start|center_horizontal"
android:padding="5dp" android:padding="5dp"
android:paddingStart="20dp" android:paddingStart="20dp"
android:paddingEnd="20dp"
android:text="" android:text=""
android:textSize="20sp" android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"

View file

@ -22,9 +22,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="60sp" android:layout_marginStart="60sp"
android:layout_marginLeft="60sp"
android:layout_marginEnd="5dp" android:layout_marginEnd="5dp"
android:layout_marginRight="5dp"
android:gravity="start" android:gravity="start"
android:text="" android:text=""
android:textSize="20sp" android:textSize="20sp"

View file

@ -39,7 +39,7 @@
android:id="@+id/settings_close" android:id="@+id/settings_close"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginRight="8dp" android:layout_marginEnd="8dp"
android:gravity="center" android:gravity="center"
android:includeFontPadding="true" android:includeFontPadding="true"
android:paddingLeft="16sp" android:paddingLeft="16sp"
@ -55,7 +55,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:layout_marginLeft="8dp" android:layout_marginEnd="8dp"
android:gravity="center" android:gravity="center"
android:includeFontPadding="true" android:includeFontPadding="true"
android:paddingLeft="16sp" android:paddingLeft="16sp"

View file

@ -2,4 +2,5 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@mipmap/ic_launcher_background"/> <background android:drawable="@mipmap/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/> <foreground android:drawable="@drawable/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon> </adaptive-icon>

View file

@ -2,4 +2,5 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@mipmap/ic_launcher_background"/> <background android:drawable="@mipmap/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/> <foreground android:drawable="@drawable/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon> </adaptive-icon>

View file

@ -34,10 +34,10 @@
<string name="settings_gesture_right_bottom_edge">Para direita (em baixo)</string> <string name="settings_gesture_right_bottom_edge">Para direita (em baixo)</string>
<string name="settings_gesture_left_bottom_edge">Para esquerda (em baixo)</string> <string name="settings_gesture_left_bottom_edge">Para esquerda (em baixo)</string>
<string name="settings_gesture_left_top_edge">Para esquerda (no topo)</string> <string name="settings_gesture_left_top_edge">Para esquerda (no topo)</string>
<string name="settings_gesture_up_left_edge">Para cima (Borda esquerda)</string> <string name="settings_gesture_up_left_edge">Para cima (borda esquerda)</string>
<string name="settings_gesture_up_right_edge">Para cima (Borda direita)</string> <string name="settings_gesture_up_right_edge">Para cima (borda direita)</string>
<string name="settings_gesture_down_left_edge">Para baixo (Borda esquerda)</string> <string name="settings_gesture_down_left_edge">Para baixo (borda esquerda)</string>
<string name="settings_gesture_down_right_edge">Para baixo (Borda direita)</string> <string name="settings_gesture_down_right_edge">Para baixo (borda direita)</string>
<string name="settings_gesture_vol_up">Aumento de volume</string> <string name="settings_gesture_vol_up">Aumento de volume</string>
<string name="settings_gesture_vol_down">Diminuição de volume</string> <string name="settings_gesture_vol_down">Diminuição de volume</string>
<string name="settings_gesture_double_click">Toque duplo</string> <string name="settings_gesture_double_click">Toque duplo</string>
@ -62,7 +62,7 @@
<string name="settings_clock_date_visible">Mostrar Data</string> <string name="settings_clock_date_visible">Mostrar Data</string>
<string name="settings_clock_localized">Use formato de data localizado</string> <string name="settings_clock_localized">Use formato de data localizado</string>
<string name="settings_clock_flip_date_time">Inverter data e hora</string> <string name="settings_clock_flip_date_time">Inverter data e hora</string>
<string name="settings_theme_wallpaper">Escolha um papel de parede</string> <string name="settings_theme_wallpaper">Escolha papel de parede</string>
<string name="settings_launcher_change_wallpaper">Alterar papel de parede</string> <string name="settings_launcher_change_wallpaper">Alterar papel de parede</string>
<string name="settings_launcher_section_display">Exibição</string> <string name="settings_launcher_section_display">Exibição</string>
<string name="settings_display_screen_timeout_disabled">Manter a tela ligada</string> <string name="settings_display_screen_timeout_disabled">Manter a tela ligada</string>
@ -121,11 +121,11 @@
<string name="tutorial_concept_text">O Launcher foi criado para ser minimalista, eficiente e livre de distrações. Ele é livre de pagamentos, anúncios e serviços de rastreamento.</string> <string name="tutorial_concept_text">O Launcher foi criado para ser minimalista, eficiente e livre de distrações. Ele é livre de pagamentos, anúncios e serviços de rastreamento.</string>
<string name="tutorial_concept_text_2">O app é de código aberto (licença MIT) e está disponível no GitHub! Não deixe de conferir o repositório!</string> <string name="tutorial_concept_text_2">O app é de código aberto (licença MIT) e está disponível no GitHub! Não deixe de conferir o repositório!</string>
<string name="tutorial_usage_title">Uso</string> <string name="tutorial_usage_title">Uso</string>
<string name="tutorial_usage_text">Sua tela inicial contém a data e hora local. Sem distração.</string> <string name="tutorial_usage_text">Sua tela inicial contém a data e hora local. Sem distrações.</string>
<string name="tutorial_usage_text_2">Você pode iniciar seus aplicativos com um toque único ou pressionando um botão. Escolha algumas ações no próximo slide.</string> <string name="tutorial_usage_text_2">Você pode iniciar seus aplicativos com um gesto único ou apertando um botão. Escolha algumas ações no próximo slide.</string>
<string name="tutorial_setup_title">Configurar</string> <string name="tutorial_setup_title">Configurar</string>
<string name="tutorial_setup_text">Selecionamos alguns aplicativos padrão para você. Se quiser, você pode alterá-los agora:</string> <string name="tutorial_setup_text">Selecionamos alguns aplicativos padrão para você. Se quiser, você pode alterá-los agora:</string>
<string name="tutorial_setup_text_2">Você também pode alterar suas escolhas mais tarde.</string> <string name="tutorial_setup_text_2">Você pode alterar suas escolhas mais tarde.</string>
<string name="tutorial_finish_title">Vamos lá!</string> <string name="tutorial_finish_title">Vamos lá!</string>
<string name="tutorial_finish_text">Tá todo pronto para começar! Espero que isso seja de grande valor para você! - Finn (que criou o Launcher) \te Josia (que fez algumas melhorias e tb mantém o fork do μLauncher)</string> <string name="tutorial_finish_text">Tá todo pronto para começar! Espero que isso seja de grande valor para você! - Finn (que criou o Launcher) \te Josia (que fez algumas melhorias e tb mantém o fork do μLauncher)</string>
<string name="tutorial_finish_button">Começar</string> <string name="tutorial_finish_button">Começar</string>
@ -162,7 +162,7 @@
<string name="screen_lock_method_use_accessibility">Usar o Serviço de acessibilidade</string> <string name="screen_lock_method_use_accessibility">Usar o Serviço de acessibilidade</string>
<string name="screen_lock_method_use_device_admin">Usar o Administrador do dispositivo</string> <string name="screen_lock_method_use_device_admin">Usar o Administrador do dispositivo</string>
<string name="screen_lock_method_dialog_title">Escolha um método de bloqueio</string> <string name="screen_lock_method_dialog_title">Escolha um método de bloqueio</string>
<string name="settings_actions_lock_method">Escolha um método de bloqueio da tela</string> <string name="settings_actions_lock_method">Escolha método de bloqueio da tela</string>
<string name="list_other_expand_settings_panel">Configurações rápidas</string> <string name="list_other_expand_settings_panel">Configurações rápidas</string>
<string name="alert_requires_android_m">Essa funcionalidade requer o Android 6 ou mais recente.</string> <string name="alert_requires_android_m">Essa funcionalidade requer o Android 6 ou mais recente.</string>
<string name="alert_no_torch_found">Nenhuma câmera com lanterna detectada.</string> <string name="alert_no_torch_found">Nenhuma câmera com lanterna detectada.</string>

View file

@ -14,6 +14,7 @@
<string name="settings_apps_custom_names_key" translatable="false">apps.custom_names</string> <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_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_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_list_layout_key" translatable="false">list.layout</string>
<string name="settings_general_choose_home_screen_key" translatable="false">general.select_launcher</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_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_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_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">Layout of app list</string>
<string name="settings_list_layout_item_default">Default</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_view">All Apps</string>
<string name="list_title_favorite">Favorite Apps</string> <string name="list_title_favorite">Favorite Apps</string>
<string name="list_title_hidden">Hidden 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_title_pick">Choose App</string>
<string name="list_tab_app">Apps</string> <string name="list_tab_app">Apps</string>
@ -219,6 +221,7 @@
<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">All Applications</string>
<string name="list_other_list_favorites">Favorite 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_toggle_private_space_lock">Toggle Private Space Lock</string>
<string name="list_other_volume_up">Music: Louder</string> <string name="list_other_volume_up">Music: Louder</string>
<string name="list_other_volume_down">Music: Quieter</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_unlocked">Private space unlocked</string>
<string name="toast_private_space_not_available">Private space is not available</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="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"> <string name="accessibility_service_description">

View file

@ -151,6 +151,11 @@
android:title="@string/settings_apps_hide_paused_apps" android:title="@string/settings_apps_hide_paused_apps"
android:defaultValue="false" /> 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 <DropDownPreference
android:key="@string/settings_list_layout_key" android:key="@string/settings_list_layout_key"
android:title="@string/settings_list_layout" android:title="@string/settings_list_layout"