From 05f05a27bee236c1562af8ae70f8841b6cd61db2 Mon Sep 17 00:00:00 2001 From: F0x1d Date: Fri, 6 Oct 2023 16:25:39 +0300 Subject: [PATCH] [feat]: dock slide animation --- .../f0x1d/logfox/extensions/APIExtensions.kt | 17 +++++ .../logfox/extensions/ContextExtensions.kt | 11 +-- .../extensions/PendingIntentsExtensions.kt | 3 +- .../f0x1d/logfox/ui/activity/MainActivity.kt | 68 +++++++++++++++++-- .../logfox/ui/activity/base/BaseActivity.kt | 7 +- .../ui/fragment/filters/FiltersFragment.kt | 4 +- .../settings/SettingsNotificationsFragment.kt | 4 +- .../settings/SettingsServiceFragment.kt | 6 +- .../res/layout-land/activity_main_no_bar.xml | 30 ++++++++ .../main/res/layout/activity_main_no_bar.xml | 30 ++++++++ 10 files changed, 159 insertions(+), 21 deletions(-) create mode 100644 app/src/main/java/com/f0x1d/logfox/extensions/APIExtensions.kt create mode 100644 app/src/main/res/layout-land/activity_main_no_bar.xml create mode 100644 app/src/main/res/layout/activity_main_no_bar.xml diff --git a/app/src/main/java/com/f0x1d/logfox/extensions/APIExtensions.kt b/app/src/main/java/com/f0x1d/logfox/extensions/APIExtensions.kt new file mode 100644 index 00000000..f3b8f28f --- /dev/null +++ b/app/src/main/java/com/f0x1d/logfox/extensions/APIExtensions.kt @@ -0,0 +1,17 @@ +package com.f0x1d.logfox.extensions + +import android.os.Build + +val isAtLeastAndroid13 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU + +val gesturesAvailable = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q +val contrastedNavBarAvailable = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 + +val notificationsChannelsAvailable = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O +val shouldRequestNotificationsPermission = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU +val startForegroundServiceAvailable = notificationsChannelsAvailable + +val canPickJSON = Build.VERSION.SDK_INT >= Build.VERSION_CODES.R + +val uiModeManagerAvailable = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S +val mutablePendingIntentAvailable = uiModeManagerAvailable \ No newline at end of file diff --git a/app/src/main/java/com/f0x1d/logfox/extensions/ContextExtensions.kt b/app/src/main/java/com/f0x1d/logfox/extensions/ContextExtensions.kt index 030c9220..dd73bec4 100644 --- a/app/src/main/java/com/f0x1d/logfox/extensions/ContextExtensions.kt +++ b/app/src/main/java/com/f0x1d/logfox/extensions/ContextExtensions.kt @@ -1,6 +1,7 @@ package com.f0x1d.logfox.extensions import android.Manifest +import android.annotation.SuppressLint import android.app.ActivityManager import android.app.NotificationManager import android.app.UiModeManager @@ -10,7 +11,6 @@ import android.content.Context import android.content.Intent import android.content.pm.PackageManager import android.content.res.Configuration -import android.os.Build import android.widget.Toast import androidx.appcompat.app.AppCompatDelegate import androidx.core.app.NotificationManagerCompat @@ -50,9 +50,10 @@ fun Context.startLoggingAndServiceIfCan(loggingRepository: LoggingRepository, ap } } +@SuppressLint("NewApi") fun Context.startLoggingService() { Intent(this, LoggingService::class.java).also { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) + if (startForegroundServiceAvailable) startForegroundService(it) else startService(it) @@ -103,7 +104,8 @@ fun Context.sendKillApp() = sendService(LoggingService.ACTION_KILL_SERVICE) fun Context.sendStopService() = sendService(LoggingService.ACTION_STOP_SERVICE) private fun Context.sendService(action: String) = startService(Intent(this, LoggingService::class.java).setAction(action)) -fun Context.hasNotificationsPermission() = if (Build.VERSION.SDK_INT >= 33) +@SuppressLint("InlinedApi") +fun Context.hasNotificationsPermission() = if (shouldRequestNotificationsPermission) ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED else true @@ -113,8 +115,9 @@ fun Context.doIfPermitted(block: NotificationManagerCompat.() -> Unit) = if (has else Unit +@SuppressLint("NewApi") fun Context.applyTheme(nightMode: Int, force: Boolean = false) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + if (uiModeManagerAvailable) { if (force) uiModeManager.setApplicationNightMode( if (nightMode != 0) nightMode else UiModeManager.MODE_NIGHT_CUSTOM ) diff --git a/app/src/main/java/com/f0x1d/logfox/extensions/PendingIntentsExtensions.kt b/app/src/main/java/com/f0x1d/logfox/extensions/PendingIntentsExtensions.kt index 88b9fb54..b837ef95 100644 --- a/app/src/main/java/com/f0x1d/logfox/extensions/PendingIntentsExtensions.kt +++ b/app/src/main/java/com/f0x1d/logfox/extensions/PendingIntentsExtensions.kt @@ -6,7 +6,6 @@ import android.app.Service import android.content.BroadcastReceiver import android.content.Context import android.content.Intent -import android.os.Build import android.os.Bundle import com.f0x1d.logfox.ui.activity.MainActivity @@ -20,7 +19,7 @@ const val STOP_RECORDING_INTENT_ID = 6 const val OPEN_APP_INTENT_ID = 7 const val SHIZUKU_PERMISSION_REQUEST_ID = 8 -val pendingIntentFlags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) +val pendingIntentFlags = if (mutablePendingIntentAvailable) PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT else PendingIntent.FLAG_UPDATE_CURRENT diff --git a/app/src/main/java/com/f0x1d/logfox/ui/activity/MainActivity.kt b/app/src/main/java/com/f0x1d/logfox/ui/activity/MainActivity.kt index db12d03e..5d02ff36 100644 --- a/app/src/main/java/com/f0x1d/logfox/ui/activity/MainActivity.kt +++ b/app/src/main/java/com/f0x1d/logfox/ui/activity/MainActivity.kt @@ -3,17 +3,24 @@ package com.f0x1d.logfox.ui.activity import android.Manifest import android.annotation.SuppressLint import android.content.Intent +import android.graphics.Color import android.os.Bundle -import android.view.View import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.viewModels +import androidx.constraintlayout.widget.ConstraintSet import androidx.navigation.NavController import androidx.navigation.NavDestination import androidx.navigation.fragment.NavHostFragment import androidx.navigation.ui.setupWithNavController +import androidx.transition.ChangeBounds +import androidx.transition.Transition +import androidx.transition.Transition.TransitionListener +import androidx.transition.TransitionManager import com.f0x1d.logfox.NavGraphDirections import com.f0x1d.logfox.R import com.f0x1d.logfox.databinding.ActivityMainBinding +import com.f0x1d.logfox.extensions.contrastedNavBarAvailable +import com.f0x1d.logfox.extensions.gesturesAvailable import com.f0x1d.logfox.extensions.hasNotificationsPermission import com.f0x1d.logfox.ui.activity.base.BaseViewModelActivity import com.f0x1d.logfox.utils.event.Event @@ -29,6 +36,33 @@ class MainActivity: BaseViewModelActivity(), private val requestNotificationPermissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()) {} + private var barShown = false + private val barScene by lazy { + ConstraintSet().apply { + clone(this@MainActivity, R.layout.activity_main) + } + } + private val noBarScene by lazy { + ConstraintSet().apply { + clone(this@MainActivity, R.layout.activity_main_no_bar) + } + } + private val changeBoundsTransition by lazy { + ChangeBounds().apply { + duration = resources.getInteger(androidx.navigation.ui.R.integer.config_navAnimTime).toLong() + + addListener(object : TransitionListener { + override fun onTransitionStart(transition: Transition) {} + override fun onTransitionEnd(transition: Transition) { + TransitionManager.endTransitions(binding.root) + } + override fun onTransitionCancel(transition: Transition) {} + override fun onTransitionPause(transition: Transition) {} + override fun onTransitionResume(transition: Transition) {} + }) + } + } + override fun inflateBinding() = ActivityMainBinding.inflate(layoutInflater) @SuppressLint("InlinedApi") @@ -74,13 +108,39 @@ class MainActivity: BaseViewModelActivity(), R.id.filtersFragment -> false R.id.editFilterFragment -> false R.id.chooseAppFragment -> false + else -> true } + val animateBarTransition = when (destination.id) { + R.id.setupFragment -> false + + else -> true + } + + if (!gesturesAvailable && contrastedNavBarAvailable) { + window.navigationBarColor = when (barShown) { + true -> Color.TRANSPARENT + + else -> getColor(R.color.navbar_transparent_background) + } + } + + if (this.barShown != barShown) { + this.barShown = barShown + + binding.root.also { + if (animateBarTransition) TransitionManager.beginDelayedTransition( + it, + changeBoundsTransition + ) - binding.barView?.visibility = when (barShown) { - true -> View.VISIBLE + val scene = when (barShown) { + true -> barScene - else -> View.GONE + else -> noBarScene + } + scene.applyTo(it) + } } } diff --git a/app/src/main/java/com/f0x1d/logfox/ui/activity/base/BaseActivity.kt b/app/src/main/java/com/f0x1d/logfox/ui/activity/base/BaseActivity.kt index 3a3bacf8..2fc6ee2e 100644 --- a/app/src/main/java/com/f0x1d/logfox/ui/activity/base/BaseActivity.kt +++ b/app/src/main/java/com/f0x1d/logfox/ui/activity/base/BaseActivity.kt @@ -2,13 +2,14 @@ package com.f0x1d.logfox.ui.activity.base import android.content.Context import android.graphics.Color -import android.os.Build import android.os.Bundle import android.view.View import androidx.appcompat.app.AppCompatActivity import androidx.core.view.WindowCompat import androidx.viewbinding.ViewBinding import com.f0x1d.logfox.R +import com.f0x1d.logfox.extensions.contrastedNavBarAvailable +import com.f0x1d.logfox.extensions.gesturesAvailable import com.f0x1d.logfox.extensions.snackbar import dagger.hilt.EntryPoint import dagger.hilt.InstallIn @@ -28,10 +29,10 @@ abstract class BaseActivity: AppCompatActivity() { WindowCompat.setDecorFitsSystemWindows(window, false) window.navigationBarColor = when { - Build.VERSION.SDK_INT < Build.VERSION_CODES.O_MR1 -> getColor( + !contrastedNavBarAvailable -> getColor( R.color.transparent_black ) - Build.VERSION.SDK_INT < Build.VERSION_CODES.Q -> getColor( + !gesturesAvailable -> getColor( R.color.navbar_transparent_background ) diff --git a/app/src/main/java/com/f0x1d/logfox/ui/fragment/filters/FiltersFragment.kt b/app/src/main/java/com/f0x1d/logfox/ui/fragment/filters/FiltersFragment.kt index 06b60738..9be8e40f 100644 --- a/app/src/main/java/com/f0x1d/logfox/ui/fragment/filters/FiltersFragment.kt +++ b/app/src/main/java/com/f0x1d/logfox/ui/fragment/filters/FiltersFragment.kt @@ -1,6 +1,5 @@ package com.f0x1d.logfox.ui.fragment.filters -import android.os.Build import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -12,6 +11,7 @@ import androidx.recyclerview.widget.LinearLayoutManager import com.f0x1d.logfox.R import com.f0x1d.logfox.adapter.FiltersAdapter import com.f0x1d.logfox.databinding.FragmentFiltersBinding +import com.f0x1d.logfox.extensions.canPickJSON import com.f0x1d.logfox.extensions.setClickListenerOn import com.f0x1d.logfox.extensions.showAreYouSureDialog import com.f0x1d.logfox.ui.fragment.base.BaseViewModelFragment @@ -68,7 +68,7 @@ class FiltersFragment: BaseViewModelFragment= Build.VERSION_CODES.R) "application/json" else "*/*")) + importFiltersLauncher.launch(arrayOf(if (canPickJSON) "application/json" else "*/*")) } setClickListenerOn(R.id.export_all_item) { exportFiltersLauncher.launch("filters.json") diff --git a/app/src/main/java/com/f0x1d/logfox/ui/fragment/settings/SettingsNotificationsFragment.kt b/app/src/main/java/com/f0x1d/logfox/ui/fragment/settings/SettingsNotificationsFragment.kt index 91c21a3a..099f45f4 100644 --- a/app/src/main/java/com/f0x1d/logfox/ui/fragment/settings/SettingsNotificationsFragment.kt +++ b/app/src/main/java/com/f0x1d/logfox/ui/fragment/settings/SettingsNotificationsFragment.kt @@ -2,7 +2,6 @@ package com.f0x1d.logfox.ui.fragment.settings import android.annotation.SuppressLint import android.content.Intent -import android.os.Build import android.os.Bundle import android.provider.Settings import androidx.preference.Preference @@ -10,6 +9,7 @@ import com.f0x1d.logfox.BuildConfig import com.f0x1d.logfox.LogFoxApp import com.f0x1d.logfox.R import com.f0x1d.logfox.extensions.hasNotificationsPermission +import com.f0x1d.logfox.extensions.notificationsChannelsAvailable import com.f0x1d.logfox.ui.fragment.settings.base.BasePreferenceFragment import com.f0x1d.logfox.utils.preferences.AppPreferences import dagger.hilt.android.AndroidEntryPoint @@ -37,7 +37,7 @@ class SettingsNotificationsFragment: BasePreferenceFragment() { } findPreference("pref_logging_notification")?.apply { - isVisible = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O + isVisible = notificationsChannelsAvailable setOnPreferenceClickListener { startActivity(Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS).apply { diff --git a/app/src/main/java/com/f0x1d/logfox/ui/fragment/settings/SettingsServiceFragment.kt b/app/src/main/java/com/f0x1d/logfox/ui/fragment/settings/SettingsServiceFragment.kt index 8812740d..72b9e576 100644 --- a/app/src/main/java/com/f0x1d/logfox/ui/fragment/settings/SettingsServiceFragment.kt +++ b/app/src/main/java/com/f0x1d/logfox/ui/fragment/settings/SettingsServiceFragment.kt @@ -1,11 +1,11 @@ package com.f0x1d.logfox.ui.fragment.settings -import android.os.Build import android.os.Bundle import androidx.lifecycle.lifecycleScope import androidx.preference.Preference import androidx.preference.SwitchPreferenceCompat import com.f0x1d.logfox.R +import com.f0x1d.logfox.extensions.isAtLeastAndroid13 import com.f0x1d.logfox.extensions.observeAndUpdateSummaryForList import com.f0x1d.logfox.extensions.setupAsListPreference import com.f0x1d.logfox.extensions.toast @@ -99,6 +99,4 @@ class SettingsServiceFragment: BasePreferenceFragment() { .setPositiveButton(android.R.string.ok, null) .show() } -} - -val isAtLeastAndroid13 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU \ No newline at end of file +} \ No newline at end of file diff --git a/app/src/main/res/layout-land/activity_main_no_bar.xml b/app/src/main/res/layout-land/activity_main_no_bar.xml new file mode 100644 index 00000000..d79e6c68 --- /dev/null +++ b/app/src/main/res/layout-land/activity_main_no_bar.xml @@ -0,0 +1,30 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main_no_bar.xml b/app/src/main/res/layout/activity_main_no_bar.xml new file mode 100644 index 00000000..caca3030 --- /dev/null +++ b/app/src/main/res/layout/activity_main_no_bar.xml @@ -0,0 +1,30 @@ + + + + + + + + \ No newline at end of file