diff --git a/app/build.gradle b/app/build.gradle index 53410d61..cb882817 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -13,8 +13,8 @@ android { applicationId "com.f0x1d.logfox" minSdk 21 targetSdk 33 - versionCode 20 - versionName "1.1.9" + versionCode 21 + versionName "1.2.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } 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 1583ce91..8d90ae52 100644 --- a/app/src/main/java/com/f0x1d/logfox/extensions/ContextExtensions.kt +++ b/app/src/main/java/com/f0x1d/logfox/extensions/ContextExtensions.kt @@ -23,9 +23,6 @@ import kotlin.system.exitProcess fun Context.copyText(text: String) = (getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager) .setPrimaryClip(ClipData.newPlainText(getString(R.string.app_name), text)) - .apply { - toast(R.string.text_copied) - } fun Context.hasPermissionToReadLogs() = ContextCompat.checkSelfPermission( this, diff --git a/app/src/main/java/com/f0x1d/logfox/extensions/PreferenceExtensions.kt b/app/src/main/java/com/f0x1d/logfox/extensions/PreferenceExtensions.kt index d90bd3c7..87bba0c7 100644 --- a/app/src/main/java/com/f0x1d/logfox/extensions/PreferenceExtensions.kt +++ b/app/src/main/java/com/f0x1d/logfox/extensions/PreferenceExtensions.kt @@ -8,7 +8,7 @@ import com.f0x1d.logfox.databinding.DialogTextBinding import com.f0x1d.logfox.utils.preferences.AppPreferences import com.google.android.material.dialog.MaterialAlertDialogBuilder -fun Preference.setupAsEditTextPreference(setup: (DialogTextBinding) -> Unit, get: () -> String?, save: (String?) -> Unit) { +fun Preference.setupAsEditTextPreference(setup: (DialogTextBinding) -> Unit, setupDialog: MaterialAlertDialogBuilder.() -> Unit, get: () -> String?, save: (String?) -> Unit) { setOnPreferenceClickListener { val dialogBinding = DialogTextBinding.inflate(LayoutInflater.from(context)) setup.invoke(dialogBinding) @@ -22,6 +22,7 @@ fun Preference.setupAsEditTextPreference(setup: (DialogTextBinding) -> Unit, get save.invoke(dialogBinding.text.text?.toString()) } .setNegativeButton(android.R.string.cancel, null) + .apply(setupDialog) .create() .apply { window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE) @@ -32,7 +33,7 @@ fun Preference.setupAsEditTextPreference(setup: (DialogTextBinding) -> Unit, get } } -fun Preference.setupAsListPreference(items: Array, selected: Int, onSelected: (Int) -> Unit) { +fun Preference.setupAsListPreference(setupDialog: MaterialAlertDialogBuilder.() -> Unit, items: Array, selected: Int, onSelected: (Int) -> Unit) { setOnPreferenceClickListener { MaterialAlertDialogBuilder(context) .setTitle(title) @@ -41,6 +42,7 @@ fun Preference.setupAsListPreference(items: Array, selected: Int, onSele onSelected.invoke(which) } .setPositiveButton(android.R.string.cancel, null) + .apply(setupDialog) .show() return@setOnPreferenceClickListener true } diff --git a/app/src/main/java/com/f0x1d/logfox/extensions/ViewExtensions.kt b/app/src/main/java/com/f0x1d/logfox/extensions/ViewExtensions.kt new file mode 100644 index 00000000..f0e97913 --- /dev/null +++ b/app/src/main/java/com/f0x1d/logfox/extensions/ViewExtensions.kt @@ -0,0 +1,6 @@ +package com.f0x1d.logfox.extensions + +import android.view.View +import com.google.android.material.snackbar.Snackbar + +fun View.snackbar(text: String) = Snackbar.make(this, text, Snackbar.LENGTH_SHORT).show() \ No newline at end of file diff --git a/app/src/main/java/com/f0x1d/logfox/extensions/ViewInsetsExtensions.kt b/app/src/main/java/com/f0x1d/logfox/extensions/ViewInsetsExtensions.kt new file mode 100644 index 00000000..b91d57a9 --- /dev/null +++ b/app/src/main/java/com/f0x1d/logfox/extensions/ViewInsetsExtensions.kt @@ -0,0 +1,30 @@ +package com.f0x1d.logfox.extensions + +import android.view.View +import android.view.ViewGroup +import androidx.core.graphics.Insets +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat +import androidx.core.view.updateLayoutParams + +fun View.applyTopInsets(view: View) = applyInsets(view) { insets -> + updateLayoutParams { + topMargin = insets.top + } +} + +fun View.applyBottomInsets(view: View) = applyInsets(view) { insets -> + updateLayoutParams { + bottomMargin = insets.bottom + } +} + +fun View.applyInsets(view: View, block: View.(Insets) -> Unit) { + ViewCompat.setOnApplyWindowInsetsListener(view) { _, windowInsets -> + val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) + + block.invoke(this, insets) + + windowInsets + } +} \ No newline at end of file diff --git a/app/src/main/java/com/f0x1d/logfox/receiver/CopyReceiver.kt b/app/src/main/java/com/f0x1d/logfox/receiver/CopyReceiver.kt index 3ab533dd..c6186be1 100644 --- a/app/src/main/java/com/f0x1d/logfox/receiver/CopyReceiver.kt +++ b/app/src/main/java/com/f0x1d/logfox/receiver/CopyReceiver.kt @@ -3,8 +3,10 @@ package com.f0x1d.logfox.receiver import android.content.BroadcastReceiver import android.content.Context import android.content.Intent +import com.f0x1d.logfox.R import com.f0x1d.logfox.extensions.copyText import com.f0x1d.logfox.extensions.notificationManagerCompat +import com.f0x1d.logfox.extensions.toast class CopyReceiver: BroadcastReceiver() { @@ -15,6 +17,7 @@ class CopyReceiver: BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { context.copyText(intent.getStringExtra(Intent.EXTRA_TEXT) ?: "") + context.toast(R.string.text_copied) context.notificationManagerCompat.cancel( intent.getStringExtra(EXTRA_PACKAGE_NAME), diff --git a/app/src/main/java/com/f0x1d/logfox/repository/logging/readers/crashes/JNICrashDetector.kt b/app/src/main/java/com/f0x1d/logfox/repository/logging/readers/crashes/JNICrashDetector.kt index 8d780955..9290591a 100644 --- a/app/src/main/java/com/f0x1d/logfox/repository/logging/readers/crashes/JNICrashDetector.kt +++ b/app/src/main/java/com/f0x1d/logfox/repository/logging/readers/crashes/JNICrashDetector.kt @@ -12,17 +12,16 @@ class JNICrashDetector(collected: suspend (AppCrash) -> Unit): BaseCrashDetector removeAll { !it.debugTag } } - private var wasBacktrace = false + private var firstLineTime = 0L - override fun foundFirstLine(line: LogLine) = line.debugTag && line.content == "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***" + override fun foundFirstLine(line: LogLine) = line.firstJNICrashLine.also { + if (it) firstLineTime = System.currentTimeMillis() + } override fun stillCollecting(line: LogLine): Boolean { - if (line.debugTag && line.content == "backtrace:") - wasBacktrace = true + if (line.firstJNICrashLine) return false - return if (super.stillCollecting(line)) - true - else !wasBacktrace + return super.stillCollecting(line) || firstLineTime + 1000 > System.currentTimeMillis() } override fun packageFromCollected(lines: List): String { @@ -38,6 +37,9 @@ class JNICrashDetector(collected: suspend (AppCrash) -> Unit): BaseCrashDetector return "???" } + private val LogLine.firstJNICrashLine + get() = debugTag && content == "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***" + private val LogLine.debugTag get() = tag.startsWith("DEBUG") } \ No newline at end of file diff --git a/app/src/main/java/com/f0x1d/logfox/ui/activity/CrashDetailsActivity.kt b/app/src/main/java/com/f0x1d/logfox/ui/activity/CrashDetailsActivity.kt index 25eb148c..0041b2a6 100644 --- a/app/src/main/java/com/f0x1d/logfox/ui/activity/CrashDetailsActivity.kt +++ b/app/src/main/java/com/f0x1d/logfox/ui/activity/CrashDetailsActivity.kt @@ -39,6 +39,8 @@ class CrashDetailsActivity: BaseViewModelActivity(), if (!hasNotificationsPermission() && !viewModel.askedNotificationsPermission) { MaterialAlertDialogBuilder(this) + .setIcon(R.drawable.ic_dialog_notification_important) .setTitle(R.string.no_notification_permission) .setMessage(R.string.notification_permission_is_required) .setCancelable(false) 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 c00c9927..e46f89e2 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,9 +2,12 @@ package com.f0x1d.logfox.ui.activity.base import android.content.Context import android.os.Bundle +import android.view.View import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatDelegate +import androidx.core.view.WindowCompat import androidx.viewbinding.ViewBinding +import com.f0x1d.logfox.extensions.snackbar import com.f0x1d.logfox.utils.preferences.AppPreferences import dagger.hilt.EntryPoint import dagger.hilt.InstallIn @@ -19,6 +22,8 @@ abstract class BaseActivity: AppCompatActivity() { abstract fun inflateBinding(): T? override fun onCreate(savedInstanceState: Bundle?) { + WindowCompat.setDecorFitsSystemWindows(window, false) + EntryPointAccessors.fromApplication(applicationContext, BaseActivityEntryPoint::class.java).appPreferences().nightTheme.also { nightInt -> AppCompatDelegate.setDefaultNightMode(if (nightInt != 0) nightInt else AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) } @@ -34,6 +39,12 @@ abstract class BaseActivity: AppCompatActivity() { override fun attachBaseContext(newBase: Context) { super.attachBaseContext(ViewPumpContextWrapper.wrap(newBase)) } + + protected fun snackbar(text: String) { + findViewById(android.R.id.content).snackbar(text) + } + + protected fun snackbar(id: Int) = snackbar(getString(id)) } @EntryPoint diff --git a/app/src/main/java/com/f0x1d/logfox/ui/activity/base/BaseViewModelActivity.kt b/app/src/main/java/com/f0x1d/logfox/ui/activity/base/BaseViewModelActivity.kt index b4d97750..404e7baa 100644 --- a/app/src/main/java/com/f0x1d/logfox/ui/activity/base/BaseViewModelActivity.kt +++ b/app/src/main/java/com/f0x1d/logfox/ui/activity/base/BaseViewModelActivity.kt @@ -17,6 +17,12 @@ abstract class BaseViewModelActivity: BaseAc onEvent(it) } + + viewModel.snackbarEventsData.observe(this) { + if (it.isConsumed) return@observe + + snackbar(it.consume()!!) + } } open fun onEvent(event: Event) {} diff --git a/app/src/main/java/com/f0x1d/logfox/ui/dialog/FilterBottomSheet.kt b/app/src/main/java/com/f0x1d/logfox/ui/dialog/FilterBottomSheet.kt index c5f7af0d..6cad8bcb 100644 --- a/app/src/main/java/com/f0x1d/logfox/ui/dialog/FilterBottomSheet.kt +++ b/app/src/main/java/com/f0x1d/logfox/ui/dialog/FilterBottomSheet.kt @@ -82,6 +82,7 @@ class FilterBottomSheet: BaseViewModelBottomSheet viewModel.filterLevel(which, checked) } diff --git a/app/src/main/java/com/f0x1d/logfox/ui/fragment/ExtendedCopyFragment.kt b/app/src/main/java/com/f0x1d/logfox/ui/fragment/ExtendedCopyFragment.kt index 3eb41d23..dfb7676a 100644 --- a/app/src/main/java/com/f0x1d/logfox/ui/fragment/ExtendedCopyFragment.kt +++ b/app/src/main/java/com/f0x1d/logfox/ui/fragment/ExtendedCopyFragment.kt @@ -7,6 +7,7 @@ import android.view.ViewGroup import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs import com.f0x1d.logfox.databinding.FragmentExtendedCopyBinding +import com.f0x1d.logfox.extensions.applyBottomInsets import com.f0x1d.logfox.ui.fragment.base.BaseFragment class ExtendedCopyFragment: BaseFragment() { @@ -18,6 +19,8 @@ class ExtendedCopyFragment: BaseFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + binding.logText.applyBottomInsets(view) + binding.toolbar.setNavigationOnClickListener { findNavController().popBackStack() } diff --git a/app/src/main/java/com/f0x1d/logfox/ui/fragment/FiltersFragment.kt b/app/src/main/java/com/f0x1d/logfox/ui/fragment/FiltersFragment.kt index 8129be4b..e5ae7833 100644 --- a/app/src/main/java/com/f0x1d/logfox/ui/fragment/FiltersFragment.kt +++ b/app/src/main/java/com/f0x1d/logfox/ui/fragment/FiltersFragment.kt @@ -6,6 +6,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.activity.result.contract.ActivityResultContracts +import androidx.core.view.updatePadding import androidx.fragment.app.viewModels import androidx.hilt.navigation.fragment.hiltNavGraphViewModels import androidx.navigation.fragment.findNavController @@ -13,6 +14,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.applyInsets import com.f0x1d.logfox.extensions.setClickListenerOn import com.f0x1d.logfox.ui.fragment.base.BaseViewModelFragment import com.f0x1d.logfox.viewmodel.LogsViewModel @@ -45,6 +47,10 @@ class FiltersFragment: BaseViewModelFragment + updatePadding(bottom = insets.bottom) + } + binding.toolbar.setOnClickListener { findNavController().popBackStack() } binding.toolbar.inflateMenu(R.menu.filters_menu) binding.toolbar.menu.apply { diff --git a/app/src/main/java/com/f0x1d/logfox/ui/fragment/LogsFragment.kt b/app/src/main/java/com/f0x1d/logfox/ui/fragment/LogsFragment.kt index 6d3be9c4..739d0ac9 100644 --- a/app/src/main/java/com/f0x1d/logfox/ui/fragment/LogsFragment.kt +++ b/app/src/main/java/com/f0x1d/logfox/ui/fragment/LogsFragment.kt @@ -162,16 +162,20 @@ class LogsFragment: BaseViewModelFragment(), private fun showSelectedDialog() { if (adapter.selectedItems.isEmpty()) { - requireContext().toast(R.string.nothing_is_selected) + snackbar(R.string.nothing_is_selected) return } MaterialAlertDialogBuilder(requireContext()) .setTitle(R.string.selected) + .setIcon(R.drawable.ic_dialog_checklist) .setItems(intArrayOf(android.R.string.copy, R.string.extended_copy).fillWithStrings(requireContext())) { dialog, which -> val textToCopy = adapter.selectedItems.joinToString("\n") { it.original } when (which) { - 0 -> requireContext().copyText(textToCopy) + 0 -> { + requireContext().copyText(textToCopy) + snackbar(R.string.text_copied) + } 1 -> findNavController().navigate(LogsFragmentDirections.actionLogsFragmentToLogsExtendedCopyFragment(textToCopy)) } } diff --git a/app/src/main/java/com/f0x1d/logfox/ui/fragment/RecordingsFragment.kt b/app/src/main/java/com/f0x1d/logfox/ui/fragment/RecordingsFragment.kt index 2cb81785..319fa19e 100644 --- a/app/src/main/java/com/f0x1d/logfox/ui/fragment/RecordingsFragment.kt +++ b/app/src/main/java/com/f0x1d/logfox/ui/fragment/RecordingsFragment.kt @@ -17,8 +17,6 @@ import com.f0x1d.logfox.ui.fragment.base.BaseViewModelFragment import com.f0x1d.logfox.utils.RecyclerViewDivider import com.f0x1d.logfox.utils.dpToPx import com.f0x1d.logfox.utils.event.Event -import com.f0x1d.logfox.utils.toDrawable -import com.f0x1d.logfox.utils.toString import com.f0x1d.logfox.viewmodel.recordings.RecordingsViewModel import dagger.hilt.android.AndroidEntryPoint @@ -43,8 +41,8 @@ class RecordingsFragment: BaseViewModelFragment { - binding.recordButton.apply { - icon = R.drawable.ic_recording.toDrawable(requireContext()) - text = R.string.record.toString(requireContext()) - } - binding.recordButton.isEnabled = true - binding.pauseButton.visibility = View.GONE + binding.recordFab.setImageResource(R.drawable.ic_recording) + binding.recordFab.isEnabled = true + + binding.pauseFab.hide() } RecordingState.RECORDING -> { - binding.recordButton.apply { - icon = R.drawable.ic_stop.toDrawable(requireContext()) - text = R.string.stop.toString(requireContext()) - } - binding.recordButton.isEnabled = true - binding.pauseButton.apply { - icon = R.drawable.ic_pause.toDrawable(requireContext()) - text = R.string.pause.toString(requireContext()) - } - binding.pauseButton.visibility = View.VISIBLE + binding.recordFab.setImageResource(R.drawable.ic_stop) + binding.recordFab.isEnabled = true + + binding.pauseFab.setImageResource(R.drawable.ic_pause) + binding.pauseFab.show() } RecordingState.PAUSED -> { - binding.recordButton.apply { - icon = R.drawable.ic_stop.toDrawable(requireContext()) - text = R.string.stop.toString(requireContext()) - } - binding.recordButton.isEnabled = true - binding.pauseButton.apply { - icon = R.drawable.ic_play.toDrawable(requireContext()) - text = R.string.resume.toString(requireContext()) - } - binding.pauseButton.visibility = View.VISIBLE + binding.recordFab.setImageResource(R.drawable.ic_stop) + binding.recordFab.isEnabled = true + + binding.pauseFab.setImageResource(R.drawable.ic_play) + binding.pauseFab.show() } RecordingState.SAVING -> { - binding.recordButton.apply { - icon = R.drawable.ic_recording.toDrawable(requireContext()) - text = R.string.record.toString(requireContext()) - } - binding.recordButton.isEnabled = false - binding.pauseButton.visibility = View.GONE + binding.recordFab.setImageResource(R.drawable.ic_recording) + binding.recordFab.isEnabled = false + + binding.pauseFab.hide() } } } diff --git a/app/src/main/java/com/f0x1d/logfox/ui/fragment/SetupFragment.kt b/app/src/main/java/com/f0x1d/logfox/ui/fragment/SetupFragment.kt index f3dd4694..a817a0d4 100644 --- a/app/src/main/java/com/f0x1d/logfox/ui/fragment/SetupFragment.kt +++ b/app/src/main/java/com/f0x1d/logfox/ui/fragment/SetupFragment.kt @@ -7,6 +7,7 @@ import android.view.ViewGroup import androidx.fragment.app.viewModels import com.f0x1d.logfox.R import com.f0x1d.logfox.databinding.FragmentSetupBinding +import com.f0x1d.logfox.extensions.applyTopInsets import com.f0x1d.logfox.extensions.copyText import com.f0x1d.logfox.extensions.hardRestartApp import com.f0x1d.logfox.ui.fragment.base.BaseViewModelFragment @@ -25,6 +26,8 @@ class SetupFragment: BaseViewModelFragment override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + binding.toolbar.applyTopInsets(view) + binding.rootButton.setOnClickListener { viewModel.root() } @@ -38,10 +41,14 @@ class SetupFragment: BaseViewModelFragment SetupViewModel.EVENT_TYPE_GOT_PERMISSION -> requireContext().hardRestartApp() SetupViewModel.EVENT_TYPE_SHOW_ADB_DIALOG -> { MaterialAlertDialogBuilder(requireContext()) + .setIcon(R.drawable.ic_dialog_adb) .setTitle(R.string.adb) .setMessage(getString(R.string.how_to_use_adb, viewModel.adbCommand)) .setPositiveButton(R.string.check) { dialog, which -> viewModel.checkPermission() } - .setNeutralButton(android.R.string.copy) { dialog, which -> requireContext().copyText(viewModel.adbCommand) } + .setNeutralButton(android.R.string.copy) { dialog, which -> + requireContext().copyText(viewModel.adbCommand) + snackbar(R.string.text_copied) + } .show() } } diff --git a/app/src/main/java/com/f0x1d/logfox/ui/fragment/base/BaseFragment.kt b/app/src/main/java/com/f0x1d/logfox/ui/fragment/base/BaseFragment.kt index 1b1cf8b6..b94bab06 100644 --- a/app/src/main/java/com/f0x1d/logfox/ui/fragment/base/BaseFragment.kt +++ b/app/src/main/java/com/f0x1d/logfox/ui/fragment/base/BaseFragment.kt @@ -6,6 +6,7 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.viewbinding.ViewBinding +import com.f0x1d.logfox.extensions.snackbar abstract class BaseFragment: Fragment() { @@ -27,4 +28,10 @@ abstract class BaseFragment: Fragment() { super.onDestroyView() mutableBinding = null } + + protected fun snackbar(text: String) { + requireView().snackbar(text) + } + + protected fun snackbar(id: Int) = snackbar(getString(id)) } \ No newline at end of file diff --git a/app/src/main/java/com/f0x1d/logfox/ui/fragment/base/BaseViewModelFragment.kt b/app/src/main/java/com/f0x1d/logfox/ui/fragment/base/BaseViewModelFragment.kt index fe55e6ab..4bce3df6 100644 --- a/app/src/main/java/com/f0x1d/logfox/ui/fragment/base/BaseViewModelFragment.kt +++ b/app/src/main/java/com/f0x1d/logfox/ui/fragment/base/BaseViewModelFragment.kt @@ -18,6 +18,12 @@ abstract class BaseViewModelFragment: BaseFr onEvent(it) } + + viewModel.snackbarEventsData.observe(viewLifecycleOwner) { + if (it.isConsumed) return@observe + + snackbar(it.consume()!!) + } } open fun onEvent(event: Event) {} diff --git a/app/src/main/java/com/f0x1d/logfox/ui/fragment/settings/SettingsUIFragment.kt b/app/src/main/java/com/f0x1d/logfox/ui/fragment/settings/SettingsUIFragment.kt index c16565bb..5863926b 100644 --- a/app/src/main/java/com/f0x1d/logfox/ui/fragment/settings/SettingsUIFragment.kt +++ b/app/src/main/java/com/f0x1d/logfox/ui/fragment/settings/SettingsUIFragment.kt @@ -33,6 +33,9 @@ class SettingsUIFragment: BaseSettingsWrapperFragment() { val filledThemeSettings = intArrayOf(R.string.follow_system, R.string.light, R.string.dark).fillWithStrings(requireContext()) setupAsListPreference( + { + setIcon(R.drawable.ic_dialog_theme) + }, filledThemeSettings, appPreferences.nightTheme ) { @@ -46,6 +49,7 @@ class SettingsUIFragment: BaseSettingsWrapperFragment() { findPreference("pref_logs_format")?.setOnPreferenceClickListener { MaterialAlertDialogBuilder(requireContext()) .setTitle(R.string.logs_format) + .setIcon(R.drawable.ic_dialog_list) .setMultiChoiceItems( intArrayOf(R.string.time, R.string.pid, R.string.tid, R.string.tag, R.string.content).fillWithStrings(requireContext()), appPreferences.showLogValues @@ -67,6 +71,8 @@ class SettingsUIFragment: BaseSettingsWrapperFragment() { setupAsEditTextPreference({ it.textLayout.setHint(R.string.in_ms) it.text.inputType = InputType.TYPE_CLASS_NUMBER + }, { + setIcon(R.drawable.ic_dialog_timer) }, { appPreferences.logsUpdateInterval.toString() }, { @@ -81,6 +87,8 @@ class SettingsUIFragment: BaseSettingsWrapperFragment() { findPreference("pref_logs_text_size")?.apply { setupAsEditTextPreference({ it.text.inputType = InputType.TYPE_CLASS_NUMBER + }, { + setIcon(R.drawable.ic_dialog_text_fields) }, { appPreferences.logsTextSize.toString() }, { diff --git a/app/src/main/java/com/f0x1d/logfox/ui/fragment/settings/base/BaseSettingsWrapperFragment.kt b/app/src/main/java/com/f0x1d/logfox/ui/fragment/settings/base/BaseSettingsWrapperFragment.kt index a349bb21..bc170a0e 100644 --- a/app/src/main/java/com/f0x1d/logfox/ui/fragment/settings/base/BaseSettingsWrapperFragment.kt +++ b/app/src/main/java/com/f0x1d/logfox/ui/fragment/settings/base/BaseSettingsWrapperFragment.kt @@ -8,6 +8,7 @@ import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController import com.f0x1d.logfox.R import com.f0x1d.logfox.databinding.FragmentSettingsBinding +import com.f0x1d.logfox.extensions.applyTopInsets import com.f0x1d.logfox.ui.fragment.base.BaseFragment abstract class BaseSettingsWrapperFragment: BaseFragment() { @@ -21,6 +22,8 @@ abstract class BaseSettingsWrapperFragment: BaseFragment() + val snackbarEventsData = MutableLiveData() protected fun launchCatching(context: CoroutineContext, errorBlock: suspend CoroutineScope.() -> Unit = {}, @@ -32,9 +33,13 @@ abstract class BaseViewModel(application: Application): AndroidViewModel(applica e.printStackTrace() - withContext(Dispatchers.Main.immediate) { - Toast.makeText(ctx, ctx.getString(R.string.error, e.localizedMessage), Toast.LENGTH_SHORT).show() - } + snackbar(ctx.getString(R.string.error, e.localizedMessage)) } } + + protected fun snackbar(id: Int) = snackbar(ctx.getString(id)) + + protected fun snackbar(text: String) = viewModelScope.launch(Dispatchers.Main.immediate) { + snackbarEventsData.value = SnackbarEvent(text) + } } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_dialog_adb.xml b/app/src/main/res/drawable/ic_dialog_adb.xml new file mode 100644 index 00000000..0ae6bc7e --- /dev/null +++ b/app/src/main/res/drawable/ic_dialog_adb.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_dialog_checklist.xml b/app/src/main/res/drawable/ic_dialog_checklist.xml new file mode 100644 index 00000000..b085dfda --- /dev/null +++ b/app/src/main/res/drawable/ic_dialog_checklist.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_dialog_list.xml b/app/src/main/res/drawable/ic_dialog_list.xml new file mode 100644 index 00000000..0843918b --- /dev/null +++ b/app/src/main/res/drawable/ic_dialog_list.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_dialog_notification_important.xml b/app/src/main/res/drawable/ic_dialog_notification_important.xml new file mode 100644 index 00000000..b5d6eba8 --- /dev/null +++ b/app/src/main/res/drawable/ic_dialog_notification_important.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_dialog_text_fields.xml b/app/src/main/res/drawable/ic_dialog_text_fields.xml new file mode 100644 index 00000000..bff5c948 --- /dev/null +++ b/app/src/main/res/drawable/ic_dialog_text_fields.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_dialog_theme.xml b/app/src/main/res/drawable/ic_dialog_theme.xml new file mode 100644 index 00000000..767c3f84 --- /dev/null +++ b/app/src/main/res/drawable/ic_dialog_theme.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_dialog_timer.xml b/app/src/main/res/drawable/ic_dialog_timer.xml new file mode 100644 index 00000000..330d235b --- /dev/null +++ b/app/src/main/res/drawable/ic_dialog_timer.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/activity_crash_details.xml b/app/src/main/res/layout/activity_crash_details.xml index 0124aec2..63308e6b 100644 --- a/app/src/main/res/layout/activity_crash_details.xml +++ b/app/src/main/res/layout/activity_crash_details.xml @@ -1,28 +1,29 @@ - - + android:fitsSystemWindows="true" + app:liftOnScroll="true"> - + + + + - + - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_text.xml b/app/src/main/res/layout/dialog_text.xml index 1f0ff49b..b53c431c 100644 --- a/app/src/main/res/layout/dialog_text.xml +++ b/app/src/main/res/layout/dialog_text.xml @@ -14,8 +14,8 @@ app:boxCornerRadiusBottomStart="10dp" app:boxCornerRadiusBottomEnd="10dp" android:layout_marginTop="10dp" - android:layout_marginStart="10dp" - android:layout_marginEnd="10dp" + android:layout_marginStart="20dp" + android:layout_marginEnd="20dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" diff --git a/app/src/main/res/layout/fragment_crashes.xml b/app/src/main/res/layout/fragment_crashes.xml index 6fdeb010..190ee185 100644 --- a/app/src/main/res/layout/fragment_crashes.xml +++ b/app/src/main/res/layout/fragment_crashes.xml @@ -1,27 +1,28 @@ - - + android:fitsSystemWindows="true" + app:liftOnScroll="true"> + + + + android:layout_width="match_parent" + android:layout_height="match_parent" + app:layout_behavior="@string/appbar_scrolling_view_behavior"/> - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_extended_copy.xml b/app/src/main/res/layout/fragment_extended_copy.xml index 988e9675..f7ca9ef6 100644 --- a/app/src/main/res/layout/fragment_extended_copy.xml +++ b/app/src/main/res/layout/fragment_extended_copy.xml @@ -1,28 +1,30 @@ - - + android:fitsSystemWindows="true" + app:liftOnScroll="true"> - + + + + - + - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_filters.xml b/app/src/main/res/layout/fragment_filters.xml index 1f21d8a9..f1c86d72 100644 --- a/app/src/main/res/layout/fragment_filters.xml +++ b/app/src/main/res/layout/fragment_filters.xml @@ -1,28 +1,32 @@ - - + android:fitsSystemWindows="true" + app:liftOnScroll="true"> + + + + android:layout_width="match_parent" + android:layout_height="match_parent" + android:clipToPadding="false" + android:paddingBottom="10dp" + app:layout_behavior="@string/appbar_scrolling_view_behavior"/> - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_logs.xml b/app/src/main/res/layout/fragment_logs.xml index 7a803acd..c26cee2e 100644 --- a/app/src/main/res/layout/fragment_logs.xml +++ b/app/src/main/res/layout/fragment_logs.xml @@ -1,28 +1,29 @@ - - + android:fitsSystemWindows="true" + app:liftOnScroll="true"> + + + + android:layout_width="match_parent" + android:layout_height="match_parent" + app:layout_behavior="@string/appbar_scrolling_view_behavior" /> + app:layout_anchorGravity="bottom|right|end" + android:layout_gravity="end|bottom"/> - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_recordings.xml b/app/src/main/res/layout/fragment_recordings.xml index 201470f4..3431ea1c 100644 --- a/app/src/main/res/layout/fragment_recordings.xml +++ b/app/src/main/res/layout/fragment_recordings.xml @@ -1,67 +1,49 @@ - - + android:fitsSystemWindows="true" + app:liftOnScroll="true"> - - - - - - - + + + android:layout_width="match_parent" + android:layout_height="match_parent" + app:layout_behavior="@string/appbar_scrolling_view_behavior"/> + + + + - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/item_filter.xml b/app/src/main/res/layout/item_filter.xml index 7209918e..789e9310 100644 --- a/app/src/main/res/layout/item_filter.xml +++ b/app/src/main/res/layout/item_filter.xml @@ -10,7 +10,7 @@ android:layout_marginBottom="5dp" app:cardBackgroundColor="?android:colorBackground" app:strokeWidth="1dp" - app:strokeColor="?noteStrokeColor"> + app:strokeColor="?attr/logFoxCardStrokeColor"> @color/amoled true - @color/noteStrokeColorDark + @color/card_stroke_color_dark + + @style/ThemeOverlay.LogFoxMaterialAlertDialog @font/google_sans @font/google_sans diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 6fe4ec30..f46e74f6 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index c00584ca..81124a5c 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -17,6 +17,6 @@ #FFFFFFFF #ff020202 - #ffdadce0 - #3a3c3e + #ffdadce0 + #3a3c3e \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 55344e51..ff55bbe3 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -1,3 +1,12 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 168b1ae7..62efbfe3 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -18,7 +18,9 @@ true true - @color/noteStrokeColor + @color/card_stroke_color + + @style/ThemeOverlay.LogFoxMaterialAlertDialog @font/google_sans @font/google_sans