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

Commit 5ab32f19 authored by Andre Le's avatar Andre Le
Browse files

QSDetailedView: Create BaseMediaProjectPermissionViewBinder

Create the new view binder class according to the design in
go/al-screen-record-detailed-view. This new class will be used by both
the current media dialogs, as well as the new screen recording detailed
view (mentioned in the design doc).

This CL move some functionalities (start button, screen share options,
and warning text) to the view binder. More functionalities will be moved
to this class in the future CLs.

Bug: b/378514312
Flag: NONE refactor
Test: ScreenRecordPermissionDialogDelegateTest
Test: Click on screen record tile in the QS -> verify that screen
recording in single app and entire screen both works
Change-Id: Ie1f50a45c4d1d6b647f97ca58443ea3dffa738c7

Change-Id: I1e6c69521c2318e9db9580c3d528730b5e425dc2
parent 705fe7f3
Loading
Loading
Loading
Loading
+21 −37
Original line number Diff line number Diff line
@@ -50,22 +50,14 @@ abstract class BaseMediaProjectionPermissionDialogDelegate<T : AlertDialog>(
    @ScreenShareMode val defaultSelectedMode: Int = screenShareOptions.first().mode,
) : DialogDelegate<T>, AdapterView.OnItemSelectedListener {
    private lateinit var dialogTitle: TextView
    private lateinit var startButton: TextView
    private lateinit var cancelButton: TextView
    private lateinit var warning: TextView
    private lateinit var screenShareModeSpinner: Spinner
    protected lateinit var dialog: AlertDialog
    private var shouldLogCancel: Boolean = true
    var selectedScreenShareOption: ScreenShareOption =
        screenShareOptions.first { it.mode == defaultSelectedMode }
    private lateinit var viewBinder: BaseMediaProjectionPermissionViewBinder

    @CallSuper
    override fun onStop(dialog: T) {
        // onStop can be called multiple times and we only want to log once.
        if (shouldLogCancel) {
            mediaProjectionMetricsLogger.notifyProjectionRequestCancelled(hostUid)
            shouldLogCancel = false
        }
        viewBinder.unbind()
    }

    @CallSuper
@@ -75,12 +67,22 @@ abstract class BaseMediaProjectionPermissionDialogDelegate<T : AlertDialog>(
        dialog.window?.setGravity(Gravity.CENTER)
        dialog.setContentView(R.layout.screen_share_dialog)
        dialogTitle = dialog.requireViewById(R.id.screen_share_dialog_title)
        warning = dialog.requireViewById(R.id.text_warning)
        startButton = dialog.requireViewById(android.R.id.button1)
        cancelButton = dialog.requireViewById(android.R.id.button2)
        updateIcon()
        initScreenShareOptions()
        createOptionsView(getOptionsViewLayoutId())
        if (!::viewBinder.isInitialized) {
            viewBinder =
                BaseMediaProjectionPermissionViewBinder(
                    screenShareOptions,
                    appName,
                    hostUid,
                    mediaProjectionMetricsLogger,
                    defaultSelectedMode,
                    dialog,
                )
        }
        viewBinder.bind()
        initScreenShareSpinner()
    }

    private fun updateIcon() {
@@ -93,18 +95,6 @@ abstract class BaseMediaProjectionPermissionDialogDelegate<T : AlertDialog>(
        }
    }

    private fun initScreenShareOptions() {
        selectedScreenShareOption = screenShareOptions.first { it.mode == defaultSelectedMode }
        setOptionSpecificFields()
        initScreenShareSpinner()
    }

    private val warningText: String
        get() = dialog.context.getString(selectedScreenShareOption.warningText, appName)

    private val startButtonText: String
        get() = dialog.context.getString(selectedScreenShareOption.startButtonText)

    private fun initScreenShareSpinner() {
        val adapter = OptionsAdapter(dialog.context.applicationContext, screenShareOptions)
        screenShareModeSpinner = dialog.requireViewById(R.id.screen_share_mode_options)
@@ -128,18 +118,15 @@ abstract class BaseMediaProjectionPermissionDialogDelegate<T : AlertDialog>(
    }

    override fun onItemSelected(adapterView: AdapterView<*>?, view: View, pos: Int, id: Long) {
        selectedScreenShareOption = screenShareOptions[pos]
        setOptionSpecificFields()
    }

    /** Sets fields on the dialog that change based on which option is selected. */
    private fun setOptionSpecificFields() {
        warning.text = warningText
        startButton.text = startButtonText
        viewBinder.onItemSelected(pos)
    }

    override fun onNothingSelected(parent: AdapterView<*>?) {}

    fun getSelectedScreenShareOption(): ScreenShareOption {
        return viewBinder.selectedScreenShareOption
    }

    /** Protected methods for the text updates & functionality */
    protected fun setDialogTitle(@StringRes stringId: Int) {
        val title = dialog.context.getString(stringId, appName)
@@ -147,10 +134,7 @@ abstract class BaseMediaProjectionPermissionDialogDelegate<T : AlertDialog>(
    }

    protected fun setStartButtonOnClickListener(listener: View.OnClickListener?) {
        startButton.setOnClickListener { view ->
            shouldLogCancel = false
            listener?.onClick(view)
        }
        viewBinder.setStartButtonOnClickListener(listener)
    }

    protected fun setCancelButtonOnClickListener(listener: View.OnClickListener?) {
+81 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.mediaprojection.permission

import android.app.AlertDialog
import android.view.View
import android.widget.TextView
import com.android.systemui.mediaprojection.MediaProjectionMetricsLogger
import com.android.systemui.res.R

open class BaseMediaProjectionPermissionViewBinder(
    private val screenShareOptions: List<ScreenShareOption>,
    private val appName: String?,
    private val hostUid: Int,
    private val mediaProjectionMetricsLogger: MediaProjectionMetricsLogger,
    @ScreenShareMode val defaultSelectedMode: Int = screenShareOptions.first().mode,
    private val dialog: AlertDialog,
) {
    private lateinit var warning: TextView
    private lateinit var startButton: TextView
    var selectedScreenShareOption: ScreenShareOption =
        screenShareOptions.first { it.mode == defaultSelectedMode }
    private var shouldLogCancel: Boolean = true

    fun unbind() {
        // unbind can be called multiple times and we only want to log once.
        if (shouldLogCancel) {
            mediaProjectionMetricsLogger.notifyProjectionRequestCancelled(hostUid)
            shouldLogCancel = false
        }
    }

    open fun bind() {
        warning = dialog.requireViewById(R.id.text_warning)
        startButton = dialog.requireViewById(android.R.id.button1)
        initScreenShareOptions()
    }

    private fun initScreenShareOptions() {
        selectedScreenShareOption = screenShareOptions.first { it.mode == defaultSelectedMode }
        setOptionSpecificFields()
    }

    /** Sets fields on the dialog that change based on which option is selected. */
    private fun setOptionSpecificFields() {
        warning.text = warningText
        startButton.text = startButtonText
    }

    fun onItemSelected(pos: Int) {
        selectedScreenShareOption = screenShareOptions[pos]
        setOptionSpecificFields()
    }

    private val warningText: String
        get() = dialog.context.getString(selectedScreenShareOption.warningText, appName)

    private val startButtonText: String
        get() = dialog.context.getString(selectedScreenShareOption.startButtonText)

    fun setStartButtonOnClickListener(listener: View.OnClickListener?) {
        startButton.setOnClickListener { view ->
            shouldLogCancel = false
            listener?.onClick(view)
        }
    }
}
+4 −2
Original line number Diff line number Diff line
@@ -133,6 +133,7 @@ class ScreenRecordPermissionDialogDelegate(
        dialog.setTitle(R.string.screenrecord_title)
        setStartButtonOnClickListener { v: View? ->
            onStartRecordingClicked?.run()
            val selectedScreenShareOption = getSelectedScreenShareOption()
            if (selectedScreenShareOption.mode == ENTIRE_SCREEN) {
                requestScreenCapture(/* captureTarget= */ null, selectedScreenShareOption.displayId)
            }
@@ -212,7 +213,8 @@ class ScreenRecordPermissionDialogDelegate(
    }

    private fun updateTapsViewVisibility() {
        tapsView.visibility = if (selectedScreenShareOption.mode == SINGLE_APP) GONE else VISIBLE
        tapsView.visibility =
            if (getSelectedScreenShareOption().mode == SINGLE_APP) GONE else VISIBLE
    }

    /**
@@ -226,7 +228,7 @@ class ScreenRecordPermissionDialogDelegate(
        displayId: Int = Display.DEFAULT_DISPLAY,
    ) {
        val userContext = userContextProvider.userContext
        val showTaps = selectedScreenShareOption.mode != SINGLE_APP && tapsSwitch.isChecked
        val showTaps = getSelectedScreenShareOption().mode != SINGLE_APP && tapsSwitch.isChecked
        val audioMode =
            if (audioSwitch.isChecked) options.selectedItem as ScreenRecordingAudioSource
            else ScreenRecordingAudioSource.NONE