Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ae26d5d1 authored by Haijie Hong's avatar Haijie Hong
Browse files

Add help button on the top right corner of more settings page

BUG: 343317785
Test: atest DeviceDetailsFragmentFormatterTest
Flag: com.android.settings.flags.enable_bluetooth_device_details_polish
Change-Id: I3053c0495d4c3cfefcd4f77c9114c4c8c8fe08ca
parent 8cd5a449
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1868,6 +1868,8 @@
    <string name="bluetooth_device_more_settings_preference_title">More settings</string>
    <!-- Title for more settings summary. [CHAR LIMIT=50] -->
    <string name="bluetooth_device_more_settings_preference_summary">Firmware updates, about, and more</string>
    <!-- Title for bluetooth device tips and support. [CHAR LIMIT=50] -->
    <string name="bluetooth_device_tip_support">Tips &amp; support</string>
    <!-- Title of the item to show device MAC address -->
    <string name="bluetooth_device_mac_address">Device\'s Bluetooth address: <xliff:g id="address">%1$s</xliff:g></string>
    <!-- Title of the items to show multuple devices MAC address [CHAR LIMIT=NONE]-->
+7 −1
Original line number Diff line number Diff line
@@ -101,6 +101,12 @@ open class BluetoothFeatureProviderImpl : BluetoothFeatureProvider {
        bluetoothAdapter: BluetoothAdapter,
        cachedDevice: CachedBluetoothDevice
    ): DeviceDetailsFragmentFormatter {
        return DeviceDetailsFragmentFormatterImpl(context, fragment, bluetoothAdapter, cachedDevice)
        return DeviceDetailsFragmentFormatterImpl(
            context,
            fragment,
            bluetoothAdapter,
            cachedDevice,
            Dispatchers.IO
        )
    }
}
+7 −0
Original line number Diff line number Diff line
@@ -66,4 +66,11 @@ sealed interface DeviceSettingPreferenceModel {
    data class MoreSettingsPreference(
        @DeviceSettingId override val id: Int,
    ) : DeviceSettingPreferenceModel

    /** Models a help button on the top right corner of the fragment. */
    data class HelpPreference(
        @DeviceSettingId override val id: Int,
        val icon: DeviceSettingIcon,
        val onClick: (() -> Unit),
    ) : DeviceSettingPreferenceModel
}
+27 −1
Original line number Diff line number Diff line
@@ -52,10 +52,15 @@ import com.android.settingslib.spa.widget.preference.SwitchPreference
import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
import com.android.settingslib.spa.widget.preference.TwoTargetSwitchPreference
import com.android.settingslib.spa.widget.ui.Footer
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.emitAll
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.runBlocking

/** Handles device details fragment layout according to config. */
@@ -65,6 +70,11 @@ interface DeviceDetailsFragmentFormatter {

    /** Updates device details fragment layout. */
    fun updateLayout(fragmentType: FragmentTypeModel)

    /** Gets the menu items of the fragment. */
    fun getMenuItem(
        fragmentType: FragmentTypeModel
    ): Flow<DeviceSettingPreferenceModel.HelpPreference?>
}

@OptIn(ExperimentalCoroutinesApi::class)
@@ -72,7 +82,8 @@ class DeviceDetailsFragmentFormatterImpl(
    private val context: Context,
    private val fragment: SettingsPreferenceFragment,
    bluetoothAdapter: BluetoothAdapter,
    private val cachedDevice: CachedBluetoothDevice
    private val cachedDevice: CachedBluetoothDevice,
    private val backgroundCoroutineContext: CoroutineContext,
) : DeviceDetailsFragmentFormatter {
    private val repository =
        featureFactory.bluetoothFeatureProvider.getDeviceSettingRepository(
@@ -88,6 +99,7 @@ class DeviceDetailsFragmentFormatterImpl(
                    repository,
                    spatialAudioInteractor,
                    cachedDevice,
                    backgroundCoroutineContext,
                ))
            .get(BluetoothDeviceDetailsViewModel::class.java)

@@ -135,6 +147,19 @@ class DeviceDetailsFragmentFormatterImpl(
        fragment.preferenceScreen.addPreference(Preference(context).apply { order = 10000 })
    }

    override fun getMenuItem(
        fragmentType: FragmentTypeModel
    ): Flow<DeviceSettingPreferenceModel.HelpPreference?> = flow {
        val t = viewModel.getHelpItem(fragmentType)

        t?.let { item ->
            emitAll(
                viewModel.getDeviceSetting(cachedDevice, item.settingId).map {
                    it as? DeviceSettingPreferenceModel.HelpPreference
                })
        } ?: emit(null)
    }

    @Composable
    private fun buildPreference(layout: DeviceSettingLayout, row: Int) {
        val contents by
@@ -174,6 +199,7 @@ class DeviceDetailsFragmentFormatterImpl(
                    is DeviceSettingPreferenceModel.MoreSettingsPreference -> {
                        buildMoreSettingsPreference()
                    }
                    is DeviceSettingPreferenceModel.HelpPreference -> {}
                    null -> {}
                }
            }
+44 −0
Original line number Diff line number Diff line
@@ -19,26 +19,65 @@ package com.android.settings.bluetooth.ui.view
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothManager
import android.content.Context
import android.graphics.PorterDuff
import android.os.Bundle
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import androidx.lifecycle.lifecycleScope
import com.android.settings.R
import com.android.settings.bluetooth.BluetoothDetailsProfilesController
import com.android.settings.bluetooth.Utils
import com.android.settings.bluetooth.ui.model.DeviceSettingPreferenceModel
import com.android.settings.bluetooth.ui.model.FragmentTypeModel
import com.android.settings.dashboard.DashboardFragment
import com.android.settings.overlay.FeatureFactory.Companion.featureFactory
import com.android.settingslib.bluetooth.CachedBluetoothDevice
import com.android.settingslib.bluetooth.LocalBluetoothManager
import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingIcon
import com.android.settingslib.core.AbstractPreferenceController
import com.android.settingslib.core.lifecycle.LifecycleObserver
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch

class DeviceDetailsMoreSettingsFragment : DashboardFragment() {
    private lateinit var formatter: DeviceDetailsFragmentFormatter
    private lateinit var localBluetoothManager: LocalBluetoothManager
    private lateinit var cachedDevice: CachedBluetoothDevice
    private lateinit var helpItem: StateFlow<DeviceSettingPreferenceModel.HelpPreference?>

    // TODO(b/343317785): add metrics category
    override fun getMetricsCategory(): Int = 0

    override fun onPrepareOptionsMenu(menu: Menu) {
        super.onPrepareOptionsMenu(menu)
        lifecycleScope.launch {
            helpItem.filterNotNull().collect { item ->
                val iconRes = item.icon as? DeviceSettingIcon.ResourceIcon ?: return@collect
                val item: MenuItem =
                    menu.add(0, MENU_HELP_ITEM_ID, 0, R.string.bluetooth_device_tip_support)
                item.setIcon(iconRes.resId)
                item.icon?.setColorFilter(
                    resources.getColor(
                        com.android.settingslib.widget.theme.R.color
                            .settingslib_materialColorOnSurface),
                    PorterDuff.Mode.SRC_ATOP)
                item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
            }
        }
    }

    override fun onOptionsItemSelected(menuItem: MenuItem): Boolean {
        if (menuItem.itemId == MENU_HELP_ITEM_ID) {
            helpItem.value?.let { it.onClick() }
            return true
        }
        return super.onOptionsItemSelected(menuItem)
    }

    override fun getPreferenceScreenResId(): Int {
        return R.xml.bluetooth_device_more_settings_fragment
    }
@@ -78,6 +117,10 @@ class DeviceDetailsMoreSettingsFragment : DashboardFragment() {
        formatter =
            featureFactory.bluetoothFeatureProvider.getDeviceDetailsFragmentFormatter(
                requireContext(), this, bluetoothManager.adapter, cachedDevice)
        helpItem =
            formatter
                .getMenuItem(FragmentTypeModel.DeviceDetailsMoreSettingsFragment)
                .stateIn(lifecycleScope, SharingStarted.WhileSubscribed(), initialValue = null)
        return listOf(
            BluetoothDetailsProfilesController(
                context, this, localBluetoothManager, cachedDevice, settingsLifecycle))
@@ -88,5 +131,6 @@ class DeviceDetailsMoreSettingsFragment : DashboardFragment() {
    companion object {
        const val TAG: String = "DeviceMoreSettingsFrg"
        const val KEY_DEVICE_ADDRESS: String = "device_address"
        const val MENU_HELP_ITEM_ID = Menu.FIRST
    }
}
Loading