diff --git a/app/src/main/java/se/ajpanton/notificationlog/SettingsFragment.kt b/app/src/main/java/se/ajpanton/notificationlog/SettingsFragment.kt index df1c3e0..1fb90f6 100644 --- a/app/src/main/java/se/ajpanton/notificationlog/SettingsFragment.kt +++ b/app/src/main/java/se/ajpanton/notificationlog/SettingsFragment.kt @@ -1,6 +1,7 @@ package se.ajpanton.notificationlog import android.os.Bundle +import android.content.ClipData import android.view.View import android.widget.ArrayAdapter import androidx.fragment.app.Fragment @@ -16,12 +17,13 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder class SettingsFragment : Fragment(R.layout.fragment_settings) { private var binding: FragmentSettingsBinding? = null + private var selectedCopyTargets = emptySet() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding = FragmentSettingsBinding.bind(view) val store = LogViewSettingsStore(requireContext()) var settings = store.load() - LogField.entries.forEach { field -> + settings.order.forEach { field -> binding!!.fieldToggles.addView(SwitchMaterial(requireContext()).apply { text = when (field) { LogField.TIMESTAMP -> "Timestamp"; LogField.APP_NAME -> "App name" @@ -29,6 +31,11 @@ class SettingsFragment : Fragment(R.layout.fragment_settings) { LogField.CONTENTS -> "Contents of the notification" } isChecked = field in settings.visibleFields + tag = field + setOnLongClickListener { + startDragAndDrop(ClipData.newPlainText("field", field.name), View.DragShadowBuilder(this), this, 0) + true + } setOnCheckedChangeListener { _, checked -> settings = settings.copy(visibleFields = settings.visibleFields.toMutableSet().apply { if (checked) add(field) else remove(field) @@ -37,6 +44,16 @@ class SettingsFragment : Fragment(R.layout.fragment_settings) { } }) } + binding!!.fieldToggles.setOnDragListener { _, event -> + if (event.action != android.view.DragEvent.ACTION_DROP) return@setOnDragListener true + val source = event.localState as? View ?: return@setOnDragListener false + val container = binding!!.fieldToggles + val index = (0 until container.childCount).firstOrNull { event.y < container.getChildAt(it).bottom } ?: container.childCount + container.removeView(source); container.addView(source, index.coerceAtMost(container.childCount)) + settings = settings.copy(order = (0 until container.childCount).map { container.getChildAt(it).tag as LogField }) + store.save(settings) + true + } val labels = listOf("Current local timezone", "UTC", "Local timezone when event happened") binding!!.timezone.adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_dropdown_item, labels) binding!!.timezone.setSelection(TimestampZone.entries.indexOf(settings.timestampZone)) @@ -46,19 +63,26 @@ class SettingsFragment : Fragment(R.layout.fragment_settings) { settings = settings.copy(timestampZone = TimestampZone.entries[position]); store.save(settings) } } - binding!!.copyEventSettings.setOnClickListener { chooseCopySource() } + setupCopyControls() val lockStore = AppLockStore(requireContext()) binding!!.appLock.isChecked = lockStore.enabled binding!!.appLock.setOnCheckedChangeListener { _, enabled -> lockStore.enabled = enabled } } override fun onDestroyView() { binding = null; super.onDestroyView() } - private fun chooseCopySource() { - val types = LoggingType.entries - MaterialAlertDialogBuilder(requireContext()) - .setTitle("Copy settings from") - .setItems(types.map { it.label() }.toTypedArray()) { _, index -> chooseCopyTargets(types[index]) } - .show() + private fun setupCopyControls() { + val labels = listOf("From") + LoggingType.entries.map { it.label() } + binding!!.copyFrom.adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_dropdown_item, labels) + binding!!.copyFrom.onItemSelectedListener = object : android.widget.AdapterView.OnItemSelectedListener { + override fun onNothingSelected(parent: android.widget.AdapterView<*>?) = Unit + override fun onItemSelected(parent: android.widget.AdapterView<*>?, view: View?, position: Int, id: Long) { + selectedCopyTargets = emptySet(); binding!!.copyTo.isEnabled = position > 0; updateCopyButton() + } + } + binding!!.copyTo.setOnClickListener { chooseCopyTargets(LoggingType.entries[binding!!.copyFrom.selectedItemPosition - 1]) } + binding!!.copyEventSettings.setOnClickListener { + LoggingRuleStore(requireContext()).copy(LoggingType.entries[binding!!.copyFrom.selectedItemPosition - 1], selectedCopyTargets) + } } private fun chooseCopyTargets(source: LoggingType) { @@ -69,9 +93,11 @@ class SettingsFragment : Fragment(R.layout.fragment_settings) { .setMultiChoiceItems(targets.map { it.label() }.toTypedArray(), checked) { _, index, selected -> checked[index] = selected } .setNegativeButton("Cancel", null) .setPositiveButton("Copy") { _, _ -> - LoggingRuleStore(requireContext()).copy(source, targets.filterIndexed { index, _ -> checked[index] }.toSet()) + selectedCopyTargets = targets.filterIndexed { index, _ -> checked[index] }.toSet(); updateCopyButton() }.show() } + private fun updateCopyButton() { binding?.copyEventSettings?.isEnabled = selectedCopyTargets.isNotEmpty() } + private fun LoggingType.label() = name.lowercase().replace('_', ' ').replaceFirstChar(Char::uppercase) } diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml index 0ee1f05..f63919a 100644 --- a/app/src/main/res/layout/fragment_settings.xml +++ b/app/src/main/res/layout/fragment_settings.xml @@ -1,2 +1,2 @@ -