1 /*
<lambda>null2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.intentresolver.contentpreview
17 
18 import android.content.res.Resources
19 import android.view.LayoutInflater
20 import android.view.View
21 import android.view.ViewGroup
22 import android.widget.TextView
23 import androidx.annotation.VisibleForTesting
24 import androidx.compose.foundation.isSystemInDarkTheme
25 import androidx.compose.material3.MaterialTheme
26 import androidx.compose.material3.dynamicDarkColorScheme
27 import androidx.compose.material3.dynamicLightColorScheme
28 import androidx.compose.runtime.LaunchedEffect
29 import androidx.compose.ui.platform.ComposeView
30 import androidx.compose.ui.platform.LocalContext
31 import androidx.lifecycle.viewmodel.compose.viewModel
32 import com.android.intentresolver.R
33 import com.android.intentresolver.contentpreview.payloadtoggle.ui.composable.Shareousel
34 import com.android.intentresolver.contentpreview.payloadtoggle.ui.viewmodel.ShareouselViewModel
35 import com.android.intentresolver.ui.viewmodel.ChooserViewModel
36 import kotlinx.coroutines.coroutineScope
37 import kotlinx.coroutines.launch
38 
39 @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
40 class ShareouselContentPreviewUi : ContentPreviewUi() {
41 
42     override fun getType(): Int = ContentPreviewType.CONTENT_PREVIEW_IMAGE
43 
44     override fun display(
45         resources: Resources,
46         layoutInflater: LayoutInflater,
47         parent: ViewGroup,
48         headlineViewParent: View,
49     ): ViewGroup = displayInternal(parent, headlineViewParent)
50 
51     private fun displayInternal(parent: ViewGroup, headlineViewParent: View): ViewGroup {
52         inflateHeadline(headlineViewParent)
53         return ComposeView(parent.context).apply {
54             setContent {
55                 val vm: ChooserViewModel = viewModel()
56                 val viewModel: ShareouselViewModel = vm.shareouselViewModel
57 
58                 LaunchedEffect(viewModel) { bindHeader(viewModel, headlineViewParent) }
59 
60                 MaterialTheme(
61                     colorScheme =
62                         if (isSystemInDarkTheme()) {
63                             dynamicDarkColorScheme(LocalContext.current)
64                         } else {
65                             dynamicLightColorScheme(LocalContext.current)
66                         },
67                 ) {
68                     Shareousel(viewModel)
69                 }
70             }
71         }
72     }
73 
74     private suspend fun bindHeader(viewModel: ShareouselViewModel, headlineViewParent: View) {
75         coroutineScope {
76             launch { bindHeadline(viewModel, headlineViewParent) }
77             launch { bindMetadataText(viewModel, headlineViewParent) }
78         }
79     }
80 
81     private suspend fun bindHeadline(viewModel: ShareouselViewModel, headlineViewParent: View) {
82         viewModel.headline.collect { headline ->
83             headlineViewParent.findViewById<TextView>(R.id.headline)?.apply {
84                 if (headline.isNotBlank()) {
85                     text = headline
86                     visibility = View.VISIBLE
87                 } else {
88                     visibility = View.GONE
89                 }
90             }
91         }
92     }
93 
94     private suspend fun bindMetadataText(viewModel: ShareouselViewModel, headlineViewParent: View) {
95         viewModel.metadataText.collect { metadata ->
96             headlineViewParent.findViewById<TextView>(R.id.metadata)?.apply {
97                 if (metadata?.isNotBlank() == true) {
98                     text = metadata
99                     visibility = View.VISIBLE
100                 } else {
101                     visibility = View.GONE
102                 }
103             }
104         }
105     }
106 }
107