diff --git a/app/build.gradle b/app/build.gradle index 103ce56..c75bb3d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -23,8 +23,8 @@ android { minSdkVersion 21 targetSdkVersion 35 compileSdk 35 - versionCode 39 - versionName "0.0.23" + versionCode 40 + versionName "0.1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } 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 57f13a5..d5e8d13 100644 --- a/app/src/main/java/de/jrpie/android/launcher/Functions.kt +++ b/app/src/main/java/de/jrpie/android/launcher/Functions.kt @@ -194,7 +194,7 @@ fun getApps( loadList.add(detailedAppInfo) } } - loadList.sortBy { it.getCustomLabel(context).toString() } + loadList.sortBy { it.getCustomLabel(context) } var end = System.currentTimeMillis() Log.i(LOG_TAG, "${loadList.size} apps loaded (${end - start}ms)") 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 index a1241af..e44ff1c 100644 --- a/app/src/main/java/de/jrpie/android/launcher/apps/PrivateSpace.kt +++ b/app/src/main/java/de/jrpie/android/launcher/apps/PrivateSpace.kt @@ -91,6 +91,7 @@ fun isPrivateSpaceLocked(context: Context): Boolean { val privateSpaceUser = getPrivateSpaceUser(context) ?: return false return userManager.isQuietModeEnabled(privateSpaceUser) } + fun lockPrivateSpace(context: Context, lock: Boolean) { if (!isPrivateSpaceSupported()) { return @@ -123,10 +124,16 @@ fun togglePrivateSpaceLock(context: Context) { } fun hidePrivateSpaceWhenLocked(context: Context): Boolean { - // TODO: perhaps this should be cached + // Trying to access the setting as a 3rd party launcher raises a security exception. + // This is an Android bug: https://issuetracker.google.com/issues/352276244#comment5 + // The logic for this is implemented. + // TODO: replace this once the Android bug is fixed + return false + // TODO: perhaps this should be cached // https://cs.android.com/android/platform/superproject/main/+/main:packages/apps/Launcher3/src/com/android/launcher3/util/SettingsCache.java;l=61;drc=56bf7ad33bc9d5ed3c18e7abefeec5c177ec75d7 - val key = "hide_privatespace_entry_point" - return Settings.Secure.getInt(context.contentResolver, key, 0) == 1 + + // val key = "hide_privatespace_entry_point" + // return Settings.Secure.getInt(context.contentResolver, key, 0) == 1 } diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/Helper.kt b/app/src/main/java/de/jrpie/android/launcher/ui/Helper.kt index b8fc82e..1ca4d2b 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/Helper.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/Helper.kt @@ -27,10 +27,14 @@ fun View.blink( } // Taken from: https://stackoverflow.com/a/30340794/12787264 -fun ImageView.transformGrayscale() { - this.colorFilter = ColorMatrixColorFilter(ColorMatrix().apply { - setSaturation(0f) - }) +fun ImageView.transformGrayscale(grayscale: Boolean) { + this.colorFilter = if (grayscale) { + ColorMatrixColorFilter(ColorMatrix().apply { + setSaturation(0f) + }) + } else { + null + } } 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 95ed56e..64bd850 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 @@ -1,7 +1,6 @@ package de.jrpie.android.launcher.ui.list import android.app.Activity -import android.content.Context import android.content.Intent import android.content.res.Resources import android.graphics.Rect @@ -33,16 +32,6 @@ import de.jrpie.android.launcher.ui.list.apps.ListFragmentApps import de.jrpie.android.launcher.ui.list.other.ListFragmentOther -// TODO: Better solution for this intercommunication functionality (used in list-fragments) -var intention = ListActivity.ListActivityIntention.VIEW -var favoritesVisibility: AppFilter.Companion.AppSetVisibility = - AppFilter.Companion.AppSetVisibility.VISIBLE -var privateSpaceVisibility: AppFilter.Companion.AppSetVisibility = - AppFilter.Companion.AppSetVisibility.VISIBLE -var hiddenVisibility: AppFilter.Companion.AppSetVisibility = - AppFilter.Companion.AppSetVisibility.HIDDEN -var forGesture: String? = null - /** * The [ListActivity] is the most general purpose activity in Launcher: * - used to view all apps and edit their settings @@ -52,11 +41,19 @@ var forGesture: String? = null */ class ListActivity : AppCompatActivity(), UIObject { private lateinit var binding: ListBinding + var intention = ListActivityIntention.VIEW + var favoritesVisibility: AppFilter.Companion.AppSetVisibility = + AppFilter.Companion.AppSetVisibility.VISIBLE + var privateSpaceVisibility: AppFilter.Companion.AppSetVisibility = + AppFilter.Companion.AppSetVisibility.VISIBLE + var hiddenVisibility: AppFilter.Companion.AppSetVisibility = + AppFilter.Companion.AppSetVisibility.HIDDEN + var forGesture: String? = null private fun updateLockIcon(locked: Boolean) { if ( - // only show lock for VIEW intention + // only show lock for VIEW intention (intention != ListActivityIntention.VIEW) // hide lock when private space does not exist || !isPrivateSpaceSetUp(this) @@ -261,7 +258,7 @@ private val TAB_TITLES = arrayOf( * The [ListSectionsPagerAdapter] returns the fragment, * which corresponds to the selected tab in [ListActivity]. */ -class ListSectionsPagerAdapter(private val context: Context, fm: FragmentManager) : +class ListSectionsPagerAdapter(private val activity: ListActivity, fm: FragmentManager) : FragmentPagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { override fun getItem(position: Int): Fragment { @@ -273,11 +270,11 @@ class ListSectionsPagerAdapter(private val context: Context, fm: FragmentManager } override fun getPageTitle(position: Int): CharSequence { - return context.resources.getString(TAB_TITLES[position]) + return activity.resources.getString(TAB_TITLES[position]) } override fun getCount(): Int { - return when (intention) { + return when (activity.intention) { ListActivity.ListActivityIntention.VIEW -> 1 else -> 2 } diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/AppsRecyclerAdapter.kt b/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/AppsRecyclerAdapter.kt index 1f275e4..c4428b7 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/AppsRecyclerAdapter.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/list/apps/AppsRecyclerAdapter.kt @@ -47,6 +47,7 @@ class AppsRecyclerAdapter( private val apps = (activity.applicationContext as Application).apps private val appsListDisplayed: MutableList = mutableListOf() + private val grayscale = LauncherPreferences.theme().monochromeIcons() // temporarily disable auto launch var disableAutoLaunch: Boolean = false @@ -79,20 +80,19 @@ class AppsRecyclerAdapter( override fun onBindViewHolder(viewHolder: ViewHolder, i: Int) { var appLabel = appsListDisplayed[i].getCustomLabel(activity) + val appIcon = appsListDisplayed[i].getIcon(activity) + + viewHolder.img.transformGrayscale(grayscale) + viewHolder.img.setImageDrawable(appIcon.constantState?.newDrawable() ?: appIcon) + if (layout.useBadgedText) { appLabel = activity.packageManager.getUserBadgedLabel( appLabel, appsListDisplayed[i].getUser(activity) ).toString() } - - val appIcon = appsListDisplayed[i].getIcon(activity) - viewHolder.textView.text = appLabel - viewHolder.img.setImageDrawable(appIcon) - if (LauncherPreferences.theme().monochromeIcons()) - viewHolder.img.transformGrayscale() // decide when to show the options popup menu about if (intention == ListActivity.ListActivityIntention.VIEW) { 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 a02c50f..1a55bbb 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 @@ -17,11 +17,6 @@ import de.jrpie.android.launcher.databinding.ListAppsBinding import de.jrpie.android.launcher.preferences.LauncherPreferences import de.jrpie.android.launcher.ui.UIObject import de.jrpie.android.launcher.ui.list.ListActivity -import de.jrpie.android.launcher.ui.list.favoritesVisibility -import de.jrpie.android.launcher.ui.list.forGesture -import de.jrpie.android.launcher.ui.list.hiddenVisibility -import de.jrpie.android.launcher.ui.list.intention -import de.jrpie.android.launcher.ui.list.privateSpaceVisibility import de.jrpie.android.launcher.ui.openSoftKeyboard @@ -54,7 +49,7 @@ class ListFragmentApps : Fragment(), UIObject { .registerOnSharedPreferenceChangeListener(sharedPreferencesListener) binding.listAppsCheckBoxFavorites.isChecked = - (favoritesVisibility == AppFilter.Companion.AppSetVisibility.EXCLUSIVE) + ((activity as? ListActivity)?.favoritesVisibility == AppFilter.Companion.AppSetVisibility.EXCLUSIVE) } override fun onStop() { @@ -67,16 +62,17 @@ class ListFragmentApps : Fragment(), UIObject { override fun setOnClicks() {} override fun adjustLayout() { + val listActivity = activity as? ListActivity ?: return appsRecyclerAdapter = AppsRecyclerAdapter( - requireActivity(), binding.root, intention, forGesture, + listActivity, binding.root, listActivity.intention, listActivity.forGesture, appFilter = AppFilter( requireContext(), "", - favoritesVisibility = favoritesVisibility, - privateSpaceVisibility = privateSpaceVisibility, - hiddenVisibility = hiddenVisibility + favoritesVisibility = listActivity.favoritesVisibility, + privateSpaceVisibility = listActivity.privateSpaceVisibility, + hiddenVisibility = listActivity.hiddenVisibility ), layout = LauncherPreferences.list().layout() ) @@ -124,7 +120,8 @@ class ListFragmentApps : Fragment(), UIObject { if (newText == " " && !appsRecyclerAdapter.disableAutoLaunch && - intention == ListActivity.ListActivityIntention.VIEW && + (activity as? ListActivity)?.intention + == ListActivity.ListActivityIntention.VIEW && LauncherPreferences.functionality().searchAutoLaunch() ) { appsRecyclerAdapter.disableAutoLaunch = true @@ -141,17 +138,17 @@ class ListFragmentApps : Fragment(), UIObject { }) binding.listAppsCheckBoxFavorites.setOnClickListener { - favoritesVisibility = + listActivity.favoritesVisibility = if (binding.listAppsCheckBoxFavorites.isChecked) { AppFilter.Companion.AppSetVisibility.EXCLUSIVE } else { AppFilter.Companion.AppSetVisibility.VISIBLE } - appsRecyclerAdapter.setFavoritesVisibility(favoritesVisibility) + appsRecyclerAdapter.setFavoritesVisibility(listActivity.favoritesVisibility) (activity as? ListActivity)?.updateTitle() } - if (intention == ListActivity.ListActivityIntention.VIEW + if (listActivity.intention == ListActivity.ListActivityIntention.VIEW && LauncherPreferences.functionality().searchAutoOpenKeyboard() ) { binding.listAppsSearchview.openSoftKeyboard(requireContext()) diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/list/other/OtherRecyclerAdapter.kt b/app/src/main/java/de/jrpie/android/launcher/ui/list/other/OtherRecyclerAdapter.kt index dfba334..70d5376 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/list/other/OtherRecyclerAdapter.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/list/other/OtherRecyclerAdapter.kt @@ -11,7 +11,7 @@ import androidx.recyclerview.widget.RecyclerView import de.jrpie.android.launcher.R import de.jrpie.android.launcher.REQUEST_CHOOSE_APP import de.jrpie.android.launcher.actions.LauncherAction -import de.jrpie.android.launcher.ui.list.forGesture +import de.jrpie.android.launcher.ui.list.ListActivity /** * The [OtherRecyclerAdapter] will only be displayed in the ListActivity, @@ -36,7 +36,7 @@ class OtherRecyclerAdapter(val activity: Activity) : val pos = bindingAdapterPosition val content = othersList[pos] - forGesture?.let { returnChoiceIntent(it, content) } + (activity as? ListActivity)?.forGesture?.let { returnChoiceIntent(it, content) } } init { diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/settings/actions/SettingsFragmentActionsRecycler.kt b/app/src/main/java/de/jrpie/android/launcher/ui/settings/actions/SettingsFragmentActionsRecycler.kt index 1f91913..630b5b0 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/settings/actions/SettingsFragmentActionsRecycler.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/settings/actions/SettingsFragmentActionsRecycler.kt @@ -143,9 +143,7 @@ class ActionsRecyclerAdapter(val activity: Activity) : val description = gesture.getDescription(activity) viewHolder.descriptionTextView.text = description - - if (LauncherPreferences.theme().monochromeIcons()) - viewHolder.img.transformGrayscale() + viewHolder.img.transformGrayscale(LauncherPreferences.theme().monochromeIcons()) updateViewHolder(gesture, viewHolder) viewHolder.img.setOnClickListener { chooseApp(gesture) } diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/TutorialActivity.kt b/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/TutorialActivity.kt index fd60d19..12c6c8a 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/TutorialActivity.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/TutorialActivity.kt @@ -4,23 +4,26 @@ import android.content.Intent import android.content.res.Resources import android.os.Build import android.os.Bundle +import android.view.View import android.window.OnBackInvokedDispatcher import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment -import androidx.fragment.app.FragmentManager -import androidx.fragment.app.FragmentPagerAdapter -import androidx.viewpager.widget.ViewPager -import com.google.android.material.tabs.TabLayout -import de.jrpie.android.launcher.R +import androidx.fragment.app.FragmentActivity +import androidx.viewpager2.adapter.FragmentStateAdapter +import androidx.viewpager2.widget.ViewPager2 +import com.google.android.material.tabs.TabLayoutMediator import de.jrpie.android.launcher.REQUEST_CHOOSE_APP +import de.jrpie.android.launcher.databinding.TutorialBinding import de.jrpie.android.launcher.preferences.LauncherPreferences import de.jrpie.android.launcher.saveListActivityChoice import de.jrpie.android.launcher.ui.UIObject -import de.jrpie.android.launcher.ui.tutorial.tabs.TutorialFragmentConcept -import de.jrpie.android.launcher.ui.tutorial.tabs.TutorialFragmentFinish -import de.jrpie.android.launcher.ui.tutorial.tabs.TutorialFragmentSetup -import de.jrpie.android.launcher.ui.tutorial.tabs.TutorialFragmentStart -import de.jrpie.android.launcher.ui.tutorial.tabs.TutorialFragmentUsage +import de.jrpie.android.launcher.ui.blink +import de.jrpie.android.launcher.ui.tutorial.tabs.TutorialFragment0Start +import de.jrpie.android.launcher.ui.tutorial.tabs.TutorialFragment1Concept +import de.jrpie.android.launcher.ui.tutorial.tabs.TutorialFragment2Usage +import de.jrpie.android.launcher.ui.tutorial.tabs.TutorialFragment3AppList +import de.jrpie.android.launcher.ui.tutorial.tabs.TutorialFragment4Setup +import de.jrpie.android.launcher.ui.tutorial.tabs.TutorialFragment5Finish /** * The [TutorialActivity] is displayed automatically on new installations. @@ -31,10 +34,16 @@ import de.jrpie.android.launcher.ui.tutorial.tabs.TutorialFragmentUsage */ class TutorialActivity : AppCompatActivity(), UIObject { + private lateinit var binding: TutorialBinding + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) super.onCreate() + // Initialise layout + binding = TutorialBinding.inflate(layoutInflater) + setContentView(binding.root) + // Handle back key / gesture on Android 13+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { onBackInvokedDispatcher.registerOnBackInvokedCallback( @@ -48,15 +57,51 @@ class TutorialActivity : AppCompatActivity(), UIObject { } } - // Initialise layout - setContentView(R.layout.tutorial) // set up tabs and swiping in settings - val sectionsPagerAdapter = TutorialSectionsPagerAdapter(supportFragmentManager) - val viewPager: ViewPager = findViewById(R.id.tutorial_viewpager) - viewPager.adapter = sectionsPagerAdapter - val tabs: TabLayout = findViewById(R.id.tutorial_tabs) - tabs.setupWithViewPager(viewPager) + val sectionsPagerAdapter = TutorialSectionsPagerAdapter(this) + binding.tutorialViewpager.apply { + adapter = sectionsPagerAdapter + currentItem = 0 + registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() { + override fun onPageSelected(position: Int) { + binding.tutorialButtonNext.apply { + val lastItem = sectionsPagerAdapter.itemCount - 1 + visibility = if (position == lastItem) { + View.INVISIBLE + } else { + View.VISIBLE + } + if (position == 0) { + blink() + } else { + clearAnimation() + } + } + binding.tutorialButtonBack.apply { + visibility = if (position == 0) { + View.INVISIBLE + } else { + View.VISIBLE + } + } + } + }) + } + TabLayoutMediator(binding.tutorialTabs, binding.tutorialViewpager) { _, _ -> }.attach() + binding.tutorialButtonNext.setOnClickListener { + binding.tutorialViewpager.apply { + setCurrentItem( + (currentItem + 1).coerceAtMost(sectionsPagerAdapter.itemCount - 1), + true + ) + } + } + binding.tutorialButtonBack.setOnClickListener { + binding.tutorialViewpager.apply { + setCurrentItem((currentItem - 1).coerceAtLeast(0), true) + } + } } override fun getTheme(): Resources.Theme { @@ -89,26 +134,22 @@ class TutorialActivity : AppCompatActivity(), UIObject { * * Tabs: (Start | Concept | Usage | Setup | Finish) */ -class TutorialSectionsPagerAdapter(fm: FragmentManager) : - FragmentPagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { +class TutorialSectionsPagerAdapter(activity: FragmentActivity) : + FragmentStateAdapter(activity) { - override fun getItem(position: Int): Fragment { + override fun getItemCount(): Int { + return 6 + } + + override fun createFragment(position: Int): Fragment { return when (position) { - 0 -> TutorialFragmentStart() - 1 -> TutorialFragmentConcept() - 2 -> TutorialFragmentUsage() - 3 -> TutorialFragmentSetup() - 4 -> TutorialFragmentFinish() + 0 -> TutorialFragment0Start() + 1 -> TutorialFragment1Concept() + 2 -> TutorialFragment2Usage() + 3 -> TutorialFragment3AppList() + 4 -> TutorialFragment4Setup() + 5 -> TutorialFragment5Finish() else -> Fragment() } } - - /* We don't use titles here, as we have the dots */ - override fun getPageTitle(position: Int): CharSequence { - return "" - } - - override fun getCount(): Int { - return 5 - } } diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragmentStart.kt b/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragment0Start.kt similarity index 59% rename from app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragmentStart.kt rename to app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragment0Start.kt index 445ded1..5ce5920 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragmentStart.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragment0Start.kt @@ -5,24 +5,22 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment -import de.jrpie.android.launcher.databinding.TutorialStartBinding +import de.jrpie.android.launcher.databinding.Tutorial0StartBinding import de.jrpie.android.launcher.ui.UIObject -import de.jrpie.android.launcher.ui.blink /** - * The [TutorialFragmentStart] is a used as a tab in the TutorialActivity. + * The [TutorialFragment0Start] is a used as a tab in the TutorialActivity. * * It displays info about the app and gets the user into the tutorial */ -class TutorialFragmentStart : Fragment(), UIObject { +class TutorialFragment0Start : Fragment(), UIObject { - private lateinit var binding: TutorialStartBinding + private lateinit var binding: Tutorial0StartBinding override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { - binding = TutorialStartBinding.inflate(inflater, container, false) - binding.tutorialStartIconRight.blink() + binding = Tutorial0StartBinding.inflate(inflater, container, false) return binding.root } 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/TutorialFragment1Concept.kt similarity index 68% rename from app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragmentConcept.kt rename to app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragment1Concept.kt index f0fd233..876266e 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/TutorialFragment1Concept.kt @@ -6,22 +6,22 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import de.jrpie.android.launcher.BuildConfig -import de.jrpie.android.launcher.databinding.TutorialConceptBinding +import de.jrpie.android.launcher.databinding.Tutorial1ConceptBinding import de.jrpie.android.launcher.ui.UIObject /** - * The [TutorialFragmentConcept] is a used as a tab in the TutorialActivity. + * The [TutorialFragment1Concept] is a used as a tab in the TutorialActivity. * * It is used to display info about Launchers concept (open source, efficiency ...) */ -class TutorialFragmentConcept : Fragment(), UIObject { - private lateinit var binding: TutorialConceptBinding +class TutorialFragment1Concept : Fragment(), UIObject { + private lateinit var binding: Tutorial1ConceptBinding override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { - binding = TutorialConceptBinding.inflate(inflater, container, false) + binding = Tutorial1ConceptBinding.inflate(inflater, container, false) binding.tutorialConceptBadgeVersion.text = BuildConfig.VERSION_NAME return binding.root } diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragmentUsage.kt b/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragment2Usage.kt similarity index 75% rename from app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragmentUsage.kt rename to app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragment2Usage.kt index 90db232..4b24dcd 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragmentUsage.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragment2Usage.kt @@ -9,17 +9,17 @@ import de.jrpie.android.launcher.R import de.jrpie.android.launcher.ui.UIObject /** - * The [TutorialFragmentUsage] is a used as a tab in the TutorialActivity. + * The [TutorialFragment2Usage] is a used as a tab in the TutorialActivity. * * Tells the user how his screen will look and how the app can be used */ -class TutorialFragmentUsage : Fragment(), UIObject { +class TutorialFragment2Usage : Fragment(), UIObject { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { - return inflater.inflate(R.layout.tutorial_usage, container, false) + return inflater.inflate(R.layout.tutorial_2_usage, container, false) } override fun onStart() { diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragment3AppList.kt b/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragment3AppList.kt new file mode 100644 index 0000000..78698aa --- /dev/null +++ b/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragment3AppList.kt @@ -0,0 +1,30 @@ +package de.jrpie.android.launcher.ui.tutorial.tabs + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import de.jrpie.android.launcher.R +import de.jrpie.android.launcher.ui.UIObject + +/** + * The [TutorialFragment3AppList] is a used as a tab in the TutorialActivity. + * + * Tells the user how his screen will look and how the app can be used + */ +class TutorialFragment3AppList : Fragment(), UIObject { + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + return inflater.inflate(R.layout.tutorial_3_app_list, container, false) + } + + override fun onStart() { + super.onStart() + super.onStart() + } + +} diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragmentSetup.kt b/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragment4Setup.kt similarity index 74% rename from app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragmentSetup.kt rename to app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragment4Setup.kt index 09ef4c9..56eb6ca 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragmentSetup.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragment4Setup.kt @@ -9,17 +9,17 @@ import de.jrpie.android.launcher.R import de.jrpie.android.launcher.ui.UIObject /** - * The [TutorialFragmentSetup] is a used as a tab in the TutorialActivity. + * The [TutorialFragment4Setup] is a used as a tab in the TutorialActivity. * * It is used to display info in the tutorial */ -class TutorialFragmentSetup : Fragment(), UIObject { +class TutorialFragment4Setup : Fragment(), UIObject { override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { - return inflater.inflate(R.layout.tutorial_setup, container, false) + return inflater.inflate(R.layout.tutorial_4_setup, container, false) } override fun onStart() { diff --git a/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragmentFinish.kt b/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragment5Finish.kt similarity index 80% rename from app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragmentFinish.kt rename to app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragment5Finish.kt index 2d01d0a..2fd093e 100644 --- a/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragmentFinish.kt +++ b/app/src/main/java/de/jrpie/android/launcher/ui/tutorial/tabs/TutorialFragment5Finish.kt @@ -6,25 +6,25 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import de.jrpie.android.launcher.BuildConfig.VERSION_CODE -import de.jrpie.android.launcher.databinding.TutorialFinishBinding +import de.jrpie.android.launcher.databinding.Tutorial5FinishBinding import de.jrpie.android.launcher.preferences.LauncherPreferences import de.jrpie.android.launcher.setDefaultHomeScreen import de.jrpie.android.launcher.ui.UIObject /** - * The [TutorialFragmentFinish] is a used as a tab in the TutorialActivity. + * The [TutorialFragment5Finish] is a used as a tab in the TutorialActivity. * * It is used to display further resources and let the user start Launcher */ -class TutorialFragmentFinish : Fragment(), UIObject { +class TutorialFragment5Finish : Fragment(), UIObject { - private lateinit var binding: TutorialFinishBinding + private lateinit var binding: Tutorial5FinishBinding override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { - binding = TutorialFinishBinding.inflate(inflater, container, false) + binding = Tutorial5FinishBinding.inflate(inflater, container, false) return binding.root } diff --git a/app/src/main/res/drawable/baseline_navigate_before_24.xml b/app/src/main/res/drawable/baseline_navigate_before_24.xml new file mode 100644 index 0000000..4097b26 --- /dev/null +++ b/app/src/main/res/drawable/baseline_navigate_before_24.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/app/src/main/res/drawable/baseline_navigate_next_24.xml b/app/src/main/res/drawable/baseline_navigate_next_24.xml new file mode 100644 index 0000000..22cef28 --- /dev/null +++ b/app/src/main/res/drawable/baseline_navigate_next_24.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/app/src/main/res/drawable/home_round_screen.png b/app/src/main/res/drawable/home_round_screen.png deleted file mode 100644 index f0237e8..0000000 Binary files a/app/src/main/res/drawable/home_round_screen.png and /dev/null differ diff --git a/app/src/main/res/drawable/round_outline.xml b/app/src/main/res/drawable/round_outline.xml new file mode 100644 index 0000000..3650338 --- /dev/null +++ b/app/src/main/res/drawable/round_outline.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/tutorial_app_list.png b/app/src/main/res/drawable/tutorial_app_list.png new file mode 100644 index 0000000..66ebaaf Binary files /dev/null and b/app/src/main/res/drawable/tutorial_app_list.png differ diff --git a/app/src/main/res/drawable/tutorial_home_screen.png b/app/src/main/res/drawable/tutorial_home_screen.png new file mode 100644 index 0000000..ccbce5d Binary files /dev/null and b/app/src/main/res/drawable/tutorial_home_screen.png differ diff --git a/app/src/main/res/layout/tutorial.xml b/app/src/main/res/layout/tutorial.xml index 7f2fd8c..5520aa1 100644 --- a/app/src/main/res/layout/tutorial.xml +++ b/app/src/main/res/layout/tutorial.xml @@ -10,7 +10,7 @@ tools:context=".ui.tutorial.TutorialActivity"> - + + + + + + app:layout_constraintTop_toBottomOf="@+id/tutorial_viewpager" /> \ No newline at end of file diff --git a/app/src/main/res/layout/tutorial_start.xml b/app/src/main/res/layout/tutorial_0_start.xml similarity index 62% rename from app/src/main/res/layout/tutorial_start.xml rename to app/src/main/res/layout/tutorial_0_start.xml index f431486..d383f5e 100644 --- a/app/src/main/res/layout/tutorial_start.xml +++ b/app/src/main/res/layout/tutorial_0_start.xml @@ -8,7 +8,7 @@ android:paddingRight="32sp" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".ui.tutorial.tabs.TutorialFragmentStart"> + tools:context=".ui.tutorial.tabs.TutorialFragment0Start"> - - - \ No newline at end of file diff --git a/app/src/main/res/layout/tutorial_concept.xml b/app/src/main/res/layout/tutorial_1_concept.xml similarity index 75% rename from app/src/main/res/layout/tutorial_concept.xml rename to app/src/main/res/layout/tutorial_1_concept.xml index 9b8495b..9b85552 100644 --- a/app/src/main/res/layout/tutorial_concept.xml +++ b/app/src/main/res/layout/tutorial_1_concept.xml @@ -8,7 +8,7 @@ android:paddingRight="32sp" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".ui.tutorial.tabs.TutorialFragmentConcept"> + tools:context=".ui.tutorial.tabs.TutorialFragment1Concept"> + app:layout_constraintBottom_toTopOf="@id/tutorial_concept_badge_version_label"/> + + diff --git a/app/src/main/res/layout/tutorial_usage.xml b/app/src/main/res/layout/tutorial_2_usage.xml similarity index 92% rename from app/src/main/res/layout/tutorial_usage.xml rename to app/src/main/res/layout/tutorial_2_usage.xml index 29bc475..d395eee 100644 --- a/app/src/main/res/layout/tutorial_usage.xml +++ b/app/src/main/res/layout/tutorial_2_usage.xml @@ -7,7 +7,7 @@ android:layout_height="match_parent" android:paddingLeft="32sp" android:paddingRight="32sp" - tools:context=".ui.tutorial.tabs.TutorialFragmentUsage"> + tools:context=".ui.tutorial.tabs.TutorialFragment2Usage"> + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/tutorial_setup.xml b/app/src/main/res/layout/tutorial_4_setup.xml similarity index 95% rename from app/src/main/res/layout/tutorial_setup.xml rename to app/src/main/res/layout/tutorial_4_setup.xml index 15990aa..bf62261 100644 --- a/app/src/main/res/layout/tutorial_setup.xml +++ b/app/src/main/res/layout/tutorial_4_setup.xml @@ -8,7 +8,7 @@ android:layout_height="match_parent" android:paddingLeft="32sp" android:paddingRight="32sp" - tools:context=".ui.tutorial.tabs.TutorialFragmentSetup"> + tools:context=".ui.tutorial.tabs.TutorialFragment4Setup"> + tools:context=".ui.tutorial.tabs.TutorialFragment5Finish"> Raster Launcher wählen App Info - Das Gerät unterstützt diese Funktion nicht. Stattdessen die App Details bearbeiten? Zum Tutorial Einstellungen zurücksetzen Alle Einstellungen gehen verloren. Weitermachen? diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index df4a50a..742c880 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -75,7 +75,6 @@ --> Seleccionar Launcher Información de la aplicación - Su dispositivo no posee esta caracrerística. Desea cambiar los detalles de la aplicación? Ver tutorial de Launcher Configuración por defecto Todas sus preferencias se eliminarán. Desea continuar? diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 86accb2..5bfb096 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -67,7 +67,6 @@ --> Choisir μLauncher comme application d\'écran d\'accueil par défaut Informations sur l\'application - Votre appareil ne prend pas en charge cette fonctionnalité. Souhaitez-vous plutôt accéder aux détails de l\'application ? Regarder le tutoriel Réinitialiser Vous allez réinitialiser tous vos paramètres. Souhaitez-vous poursuivre ? diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index fe30410..28a7133 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -34,7 +34,6 @@



Puoi cambiare le tue scelte in seguito nelle impostazioni. ]]> - Il tuo dispositivo non supporta questa funzione. Vuoi aprire la pagina di dettaglio dell\'applicazione? Impossibile aprire l\'applicazione Desideri modificare le impostazioni? Apri le impostazioni per abbinare un\'azione a questo gesto diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 6cc844d..c453380 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -192,7 +192,6 @@ この機能を一時的に無効にするにはスペースキーを押します。 プライベートスペース アプリ一覧からプライベートスペースを隠す - この機能はあなたのデバイスでは動作しません。代わりにアプリケーションの詳細を管理しますか? バグを報告 このランチャーの使い方を学ぶのにほんの数秒しかかかりません Launcherは、最小限かつ効率的で、邪魔にならないように設計されています。支払い、広告、追跡サービスは一切ありません。 diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 857e454..3a0734f 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -79,7 +79,6 @@ --> Definir o μLauncher como tela inicial Informações do aplicativo - Seu dispositivo não é compatível com esse recurso. Gerenciar detalhes do app em vez disso? Ver tutorial do launcher Redefinir configuraçãos Você vai descartar todas as suas preferências. Continuar? diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 0c22e97..a283fa9 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -164,7 +164,6 @@ Metin Izgara Uygulama Detayı - Sizin cihazınız bu özelliği desteklemiyor. Onun yerine uygulama detaylarını düzenleyin? Ayarları Sıfırlayın Tüm tercihlerinizi bir kenara bırakacaksınız. Devam mı? Tek uzay diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index c445a75..08bc5b7 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -50,7 +50,6 @@ 搜索时呼出键盘 灵敏度 应用信息 - 您的设备不支持此功能。要不打开应用程序详细? 查看启动器教程 重置设置 你将放弃你所有的配置。继续吗? diff --git a/app/src/main/res/values/donottranslate.xml b/app/src/main/res/values/donottranslate.xml index 33d2e57..89ec086 100644 --- a/app/src/main/res/values/donottranslate.xml +++ b/app/src/main/res/values/donottranslate.xml @@ -176,7 +176,7 @@ µLauncher +

μLauncher

Modifications to Launcher.

github.com/jrpie/launcher

diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a051a67..b94a92b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -179,7 +179,7 @@ Hide paused apps Hide private space from app list Layout of app list - Reverse app list + Reverse the app list Default Text @@ -193,7 +193,7 @@ Set μLauncher as home screen App Info - View Launcher Tutorial + View µLauncher Tutorial Reset Settings You are going to discard all your preferences. Continue? @@ -202,14 +202,14 @@ Report a bug Report a bug - Thank you for helping to improve µLauncher!\nPlease consider adding the following information to your bug report: + Thank you for helping to improve μLauncher!\nPlease consider adding the following information to your bug report: Copy to clipboard Please do not report security vulnerabilities publicly on GitHub, but use the following instead: Report a security vulnerability Create report Contact the developer of the fork - Join µLauncher chat + Join μLauncher chat Donate Privacy Policy @@ -246,7 +246,7 @@ Search Search (no auto launch) - µLauncher Settings + μLauncher Settings All Applications Favorite Applications Private Space @@ -274,22 +274,29 @@ - --> Tutorial - Take a few seconds to learn how to use this Launcher! + 👋\n\nTake a few seconds to learn how to use this Launcher! Concept - Launcher is designed to be minimal, efficient and free of distraction. It is free of payments, ads and tracking services. - The app is open-source (MIT license) and available on GitHub! Make sure to check out the repository! + μLauncher is designed to be minimal, efficient and free of distraction. + \n\nIt contains no ads and collects no data. + It is free software (MIT license)!\nMake sure to check out the repository! + Version Usage Your home screen contains the local date and time. No distraction. - You can launch your apps with a single swipe or button press. Choose some in the next slide. + You can launch your most important apps with touch gestures or button presses. + + All Apps + You can quickly search through all apps in the app list.\n\nSwipe up to open it, or bind it to a different gesture. + Once only one app matches, it launches automatically.\nThis can be disabled by prefixing the query with a space. + Setup We chose some default apps for you. You can change them now if you want to: You can also change your selection later. Let\'s go! - You are ready to get started! I hope this is of great value to you! - Finn (who made Launcher) \tand Josia (who made some improvements and maintains the fork μLauncher) + You are ready to get started!\n\nI hope this is of great value to you!\n\n- Finn (who made Launcher) and Josia (who made some improvements and maintains the fork μLauncher) Start @@ -301,7 +308,7 @@ App hidden. You can make it visible again in settings. Undo Quick Settings - µLauncher needs to be a device admin in order to lock the screen. + μLauncher needs to be a device admin in order to lock the screen. This is required for the lock screen action. Enable the lock screen action No camera with torch detected. @@ -311,18 +318,18 @@ Private space locked Private space unlocked Private space is not available - µLauncher needs to be the default home screen to access private space. + μ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 + μLauncher - lock screen - Setting µLauncher as an accessibility service allows it to lock the screen. + Setting μLauncher as an accessibility service allows it to lock the screen. Note that excessive permissions are required. You should never grant such permissions lightly to any app. - µLauncher will use the accessibility service only for locking the screen. You can check the source code to make sure. + μLauncher will use the accessibility service only for locking the screen. You can check the source code to make sure. - Note that locking the screen can also be accomplished by granting µLauncher device administrator permissions. However that method doesn\'t work with fingerprint and face unlock. + Note that locking the screen can also be accomplished by granting μLauncher device administrator permissions. However that method doesn\'t work with fingerprint and face unlock. @@ -340,7 +347,7 @@

Accessibility Service

Requires excessive privileges. - µLauncher will use those privileges only for locking the screen. + μLauncher will use those privileges only for locking the screen.
(You really should not trust a random app you just downloaded with such a claim, but you can check the source code.)
@@ -363,11 +370,11 @@ Ok Color Choose color - I am aware that this will grant far-reaching privileges to µLauncher. + I am aware that this will grant far-reaching privileges to μLauncher. I am aware that other options exist (using device administrator privileges or the power button). - I consent to µLauncher using the accessibility service to provide functionality unrelated to accessibility. - I consent to µLauncher not collecting any data. - far-reaching privileges to µLauncher.
µLauncher will use these privileges only to lock the screen. µLauncher will never collect any data. In particular, µLauncher does not use the accessibility service to collect any data.]]>
+ I consent to μLauncher using the accessibility service to provide functionality unrelated to accessibility. + I consent to μLauncher not collecting any data. + far-reaching privileges to μLauncher.
μLauncher will use these privileges only to lock the screen. μLauncher will never collect any data. In particular, μLauncher does not use the accessibility service to collect any data.]]>
Activating the Accessibility Service Activate Accessibility Service Cancel diff --git a/fastlane/metadata/android/en-US/changelogs/40.txt b/fastlane/metadata/android/en-US/changelogs/40.txt new file mode 100644 index 0000000..b457e2f --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/40.txt @@ -0,0 +1,13 @@ +* Pinned shortcuts can now be added to app list +* New action: adjust volume (thank you, zabrinu!) +* Added option to hide navigation bar (thank you, acanoe!) +* Added option to reverse the app list (thank you, spacefrogg!) +* Show question mark icon when an unknown app is bound to a gesture + +* Improved German translation +* Improved Portuguese translation (thank you, "Vossa Excelencia"!) + +* Fixed detection of long click gesture +* Fixed blurred text in dialogs +* Fixed a crash when private space is locked after app restarts (thank you, alexytomi!) +* Fixed some additional bugs