diff --git a/app/build.gradle b/app/build.gradle index 23273af..76bd285 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -100,7 +100,7 @@ dependencies { implementation 'androidx.constraintlayout:constraintlayout:2.2.0' implementation 'androidx.gridlayout:gridlayout: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 'com.google.android.material:material:1.12.0' implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3") diff --git a/app/src/main/java/de/jrpie/android/launcher/Application.kt b/app/src/main/java/de/jrpie/android/launcher/Application.kt index 6e924c2..c856066 100644 --- a/app/src/main/java/de/jrpie/android/launcher/Application.kt +++ b/app/src/main/java/de/jrpie/android/launcher/Application.kt @@ -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>() + val privateSpaceLocked = MutableLiveData() 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)) } } } diff --git a/app/src/main/java/de/jrpie/android/launcher/Functions.kt b/app/src/main/java/de/jrpie/android/launcher/Functions.kt index 721caa2..5f7e9c9 100644 --- a/app/src/main/java/de/jrpie/android/launcher/Functions.kt +++ b/app/src/main/java/de/jrpie/android/launcher/Functions.kt @@ -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= 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 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 +114,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( @@ -128,7 +135,7 @@ enum class LauncherAction( } override fun getIcon(context: Context): Drawable? { - return context.getDrawable(icon) + return AppCompatResources.getDrawable(context, icon) } 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) { /* https://stackoverflow.com/a/31898506 */ @@ -283,7 +259,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 +283,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) } diff --git a/app/src/main/java/de/jrpie/android/launcher/apps/AppFilter.kt b/app/src/main/java/de/jrpie/android/launcher/apps/AppFilter.kt index f3640d2..ecc7eaa 100644 --- a/app/src/main/java/de/jrpie/android/launcher/apps/AppFilter.kt +++ b/app/src/main/java/de/jrpie/android/launcher/apps/AppFilter.kt @@ -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): List { @@ -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()) { diff --git a/app/src/main/java/de/jrpie/android/launcher/apps/DetailedAppInfo.kt b/app/src/main/java/de/jrpie/android/launcher/apps/DetailedAppInfo.kt index 519798d..d77bf93 100644 --- a/app/src/main/java/de/jrpie/android/launcher/apps/DetailedAppInfo.kt +++ b/app/src/main/java/de/jrpie/android/launcher/apps/DetailedAppInfo.kt @@ -9,16 +9,17 @@ import de.jrpie.android.launcher.Application 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( 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)) + } } } } \ No newline at end of file diff --git a/app/src/main/java/de/jrpie/android/launcher/apps/PrivateSpace.kt b/app/src/main/java/de/jrpie/android/launcher/apps/PrivateSpace.kt new file mode 100644 index 0000000..9b37d60 --- /dev/null +++ b/app/src/main/java/de/jrpie/android/launcher/apps/PrivateSpace.kt @@ -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() + } +} + diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/LauncherPreferences$Config.java b/app/src/main/java/de/jrpie/android/launcher/preferences/LauncherPreferences$Config.java index 98496ce..c216911 100644 --- a/app/src/main/java/de/jrpie/android/launcher/preferences/LauncherPreferences$Config.java +++ b/app/src/main/java/de/jrpie/android/launcher/preferences/LauncherPreferences$Config.java @@ -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") diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version1.kt b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version1.kt index d617127..a61980a 100644 --- a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version1.kt +++ b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/Version1.kt @@ -68,9 +68,9 @@ private fun Action.Companion.legacyFromPreference(id: String): Action? { val actionId = preferences.getString("$id.app", "")!! var u: Int? = preferences.getInt( "$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) } @@ -80,9 +80,9 @@ private fun migrateAppInfoStringMap(key: String) { MapAppInfoStringPreferenceSerializer().serialize( preferences.getStringSet(key, setOf())?.mapNotNull { entry -> try { - val obj = JSONObject(entry); + val obj = JSONObject(entry) val info = AppInfo.legacyDeserialize(obj.getString("key")) - val value = obj.getString("value"); + val value = obj.getString("value") Pair(info, value) } catch (_: JSONException) { null diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/VersionUnknown.kt b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/VersionUnknown.kt index c61ca95..a33670b 100644 --- a/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/VersionUnknown.kt +++ b/app/src/main/java/de/jrpie/android/launcher/preferences/legacy/VersionUnknown.kt @@ -4,7 +4,6 @@ import android.content.Context import android.content.SharedPreferences import android.util.Log 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.ColorTheme diff --git a/app/src/main/java/de/jrpie/android/launcher/preferences/serialization/PreferenceSerializers.kt b/app/src/main/java/de/jrpie/android/launcher/preferences/serialization/PreferenceSerializers.kt index 4a745a2..041fe4d 100644 --- a/app/src/main/java/de/jrpie/android/launcher/preferences/serialization/PreferenceSerializers.kt +++ b/app/src/main/java/de/jrpie/android/launcher/preferences/serialization/PreferenceSerializers.kt @@ -15,7 +15,7 @@ import kotlinx.serialization.json.Json class SetAppInfoPreferenceSerializer : PreferenceSerializer?, java.util.Set?> { @Throws(PreferenceSerializationException::class) - override fun serialize(value: java.util.Set?): java.util.Set? { + override fun serialize(value: java.util.Set?): java.util.Set { return value?.map(AppInfo::serialize)?.toHashSet() as java.util.Set } @@ -29,7 +29,7 @@ class SetAppInfoPreferenceSerializer : class MapAppInfoStringPreferenceSerializer : PreferenceSerializer?, java.util.Set?> { - @Serializable() + @Serializable private class MapEntry(val key: AppInfo, val value: String) @Throws(PreferenceSerializationException::class) diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/HomeActivity.kt b/app/src/main/java/de/jrpie/android/launcher/ui/HomeActivity.kt index 42dc01b..b41eff3 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/HomeActivity.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/HomeActivity.kt @@ -216,7 +216,7 @@ class HomeActivity : UIObject, AppCompatActivity(), if (e1 == null) return false - val displayMetrics: DisplayMetrics = DisplayMetrics() + val displayMetrics = DisplayMetrics() windowManager.defaultDisplay.getMetrics(displayMetrics) val width = displayMetrics.widthPixels diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/list/ListActivity.kt b/app/src/main/java/de/jrpie/android/launcher/ui/list/ListActivity.kt index 1fe5afb..c4ecded 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/list/ListActivity.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/list/ListActivity.kt @@ -11,15 +11,20 @@ import android.view.View import android.widget.Toast import android.window.OnBackInvokedDispatcher import androidx.appcompat.app.AppCompatActivity +import androidx.appcompat.content.res.AppCompatResources 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.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 +35,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 +51,30 @@ class ListActivity : AppCompatActivity(), UIObject { 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) { 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 +101,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 +119,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 +202,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 +221,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() { diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ContextMenuActions.kt b/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ContextMenuActions.kt index e09111e..9636dc2 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ContextMenuActions.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ContextMenuActions.kt @@ -33,7 +33,7 @@ fun AppInfo.openSettings( } fun AppInfo.uninstall(activity: android.app.Activity) { - val packageName = this.packageName.toString() + val packageName = this.packageName val userId = this.user Log.i(LOG_TAG, "uninstalling $this") diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ListFragmentApps.kt b/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ListFragmentApps.kt index c52f951..3a6e403 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ListFragmentApps.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/ListFragmentApps.kt @@ -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() diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/settings/meta/SettingsFragmentMeta.kt b/app/src/main/java/de/jrpie/android/launcher/ui/settings/meta/SettingsFragmentMeta.kt index fd3a738..70a225d 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/settings/meta/SettingsFragmentMeta.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/settings/meta/SettingsFragmentMeta.kt @@ -45,21 +45,6 @@ class SettingsFragmentMeta : Fragment(), UIObject { super.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() { binding.settingsMetaButtonViewTutorial.setOnClickListener { diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragmentConcept.kt b/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragmentConcept.kt index 26d4141..f0fd233 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragmentConcept.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragmentConcept.kt @@ -21,7 +21,7 @@ class TutorialFragmentConcept : Fragment(), UIObject { inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { - val binding = TutorialConceptBinding.inflate(inflater, container, false) + binding = TutorialConceptBinding.inflate(inflater, container, false) binding.tutorialConceptBadgeVersion.text = BuildConfig.VERSION_NAME return binding.root } diff --git a/app/src/main/res/drawable/baseline_lock_24px.xml b/app/src/main/res/drawable/baseline_lock_24.xml similarity index 100% rename from app/src/main/res/drawable/baseline_lock_24px.xml rename to app/src/main/res/drawable/baseline_lock_24.xml diff --git a/app/src/main/res/drawable/baseline_lock_open_24.xml b/app/src/main/res/drawable/baseline_lock_open_24.xml new file mode 100644 index 0000000..f0f6ea3 --- /dev/null +++ b/app/src/main/res/drawable/baseline_lock_open_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/layout/list.xml b/app/src/main/res/layout/list.xml index 062cab4..e68c895 100644 --- a/app/src/main/res/layout/list.xml +++ b/app/src/main/res/layout/list.xml @@ -32,7 +32,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" - android:layout_marginLeft="8dp" + android:layout_marginEnd="8dp" android:contentDescription="@string/settings" android:gravity="center" android:paddingLeft="16sp" @@ -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" /> + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml index 6f2acb4..8b20aae 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -2,4 +2,5 @@ + \ No newline at end of file diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 0ec4a32..fef6043 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -34,10 +34,10 @@ Para direita (em baixo) Para esquerda (em baixo) Para esquerda (no topo) - Para cima (Borda esquerda) - Para cima (Borda direita) - Para baixo (Borda esquerda) - Para baixo (Borda direita) + Para cima (borda esquerda) + Para cima (borda direita) + Para baixo (borda esquerda) + Para baixo (borda direita) Aumento de volume Diminuição de volume Toque duplo @@ -62,7 +62,7 @@ Mostrar Data Use formato de data localizado Inverter data e hora - Escolha um papel de parede + Escolha papel de parede Alterar papel de parede Exibição Manter a tela ligada @@ -121,11 +121,11 @@ O Launcher foi criado para ser minimalista, eficiente e livre de distrações. Ele é livre de pagamentos, anúncios e serviços de rastreamento. O app é de código aberto (licença MIT) e está disponível no GitHub! Não deixe de conferir o repositório! Uso - Sua tela inicial contém a data e hora local. Sem distração. - Você pode iniciar seus aplicativos com um toque único ou pressionando um botão. Escolha algumas ações no próximo slide. + Sua tela inicial contém a data e hora local. Sem distrações. + Você pode iniciar seus aplicativos com um gesto único ou apertando um botão. Escolha algumas ações no próximo slide. Configurar Selecionamos alguns aplicativos padrão para você. Se quiser, você pode alterá-los agora: - Você também pode alterar suas escolhas mais tarde. + Você pode alterar suas escolhas mais tarde. Vamos lá! 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) Começar @@ -162,7 +162,7 @@ Usar o Serviço de acessibilidade Usar o Administrador do dispositivo Escolha um método de bloqueio - Escolha um método de bloqueio da tela + Escolha método de bloqueio da tela Configurações rápidas Essa funcionalidade requer o Android 6 ou mais recente. Nenhuma câmera com lanterna detectada. diff --git a/app/src/main/res/values/donottranslate.xml b/app/src/main/res/values/donottranslate.xml index 53aabad..6ebdf63 100644 --- a/app/src/main/res/values/donottranslate.xml +++ b/app/src/main/res/values/donottranslate.xml @@ -14,6 +14,7 @@ apps.custom_names apps.hide_bound_apps apps.hide_paused_apps + apps.hide_private_space_apps list.layout general.select_launcher diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9c07ed6..97d7384 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -150,6 +150,7 @@ Hidden apps Don\'t show apps that are bound to a gesture in the app list Hide paused apps + Hide private space from app list Layout of app list Default @@ -197,6 +198,7 @@ All Apps Favorite Apps Hidden Apps + Private Space Choose App Apps @@ -219,6 +221,7 @@ µLauncher Settings All Applications Favorite Applications + Private Space Toggle Private Space Lock Music: Louder Music: Quieter @@ -273,6 +276,8 @@ Private space unlocked Private space is not available µLauncher needs to be the default home screen to access private space. + Lock private space + Unlock private space Error: Locking the screen using accessibility is not supported on this device. Please use device admin instead. µLauncher - lock screen diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 314f85f..406f81a 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -151,6 +151,11 @@ android:title="@string/settings_apps_hide_paused_apps" android:defaultValue="false" /> + +