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 17 package com.android.wallpaper.customization.ui.binder 18 19 import android.content.Context 20 import android.content.res.Configuration.UI_MODE_NIGHT_MASK 21 import android.content.res.Configuration.UI_MODE_NIGHT_YES 22 import android.view.View 23 import android.widget.TextView 24 import androidx.lifecycle.Lifecycle 25 import androidx.lifecycle.LifecycleOwner 26 import androidx.lifecycle.lifecycleScope 27 import androidx.lifecycle.repeatOnLifecycle 28 import androidx.recyclerview.widget.LinearLayoutManager 29 import androidx.recyclerview.widget.RecyclerView 30 import com.android.customization.picker.color.ui.binder.ColorOptionIconBinder2 31 import com.android.customization.picker.color.ui.view.ColorOptionIconView2 32 import com.android.customization.picker.color.ui.viewmodel.ColorOptionIconViewModel 33 import com.android.customization.picker.common.ui.view.SingleRowListItemSpacing 34 import com.android.customization.picker.mode.ui.binder.DarkModeBinder 35 import com.android.themepicker.R 36 import com.android.wallpaper.customization.ui.util.ThemePickerCustomizationOptionUtil.ThemePickerHomeCustomizationOption.COLORS 37 import com.android.wallpaper.customization.ui.viewmodel.ThemePickerCustomizationOptionsViewModel 38 import com.android.wallpaper.picker.customization.ui.view.FloatingToolbar 39 import com.android.wallpaper.picker.customization.ui.view.adapter.FloatingToolbarTabAdapter 40 import com.android.wallpaper.picker.customization.ui.viewmodel.ColorUpdateViewModel 41 import com.android.wallpaper.picker.option.ui.adapter.OptionItemAdapter2 42 import java.lang.ref.WeakReference 43 import kotlinx.coroutines.launch 44 45 object ColorsFloatingSheetBinder { 46 47 fun bind( 48 view: View, 49 optionsViewModel: ThemePickerCustomizationOptionsViewModel, 50 colorUpdateViewModel: ColorUpdateViewModel, 51 lifecycleOwner: LifecycleOwner, 52 ) { 53 val viewModel = optionsViewModel.colorPickerViewModel2 54 55 val subhead = view.requireViewById<TextView>(R.id.color_type_tab_subhead) 56 57 val colorsAdapter = 58 createOptionItemAdapter(view.resources.configuration.uiMode, lifecycleOwner) 59 val colorsList = 60 view.requireViewById<RecyclerView>(R.id.colors_horizontal_list).also { 61 it.initColorsList(view.context.applicationContext, colorsAdapter) 62 } 63 64 val tabs = view.requireViewById<FloatingToolbar>(R.id.floating_toolbar) 65 val tabAdapter = 66 FloatingToolbarTabAdapter( 67 colorUpdateViewModel = WeakReference(colorUpdateViewModel), 68 shouldAnimateColor = { optionsViewModel.selectedOption.value == COLORS }, 69 ) 70 .also { tabs.setAdapter(it) } 71 72 DarkModeBinder.bind( 73 darkModeToggle = view.findViewById(R.id.dark_mode_toggle), 74 viewModel = optionsViewModel.darkModeViewModel, 75 lifecycleOwner = lifecycleOwner, 76 ) 77 78 lifecycleOwner.lifecycleScope.launch { 79 lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { 80 launch { viewModel.colorTypeTabs.collect { tabAdapter.submitList(it) } } 81 82 launch { viewModel.colorTypeTabSubheader.collect { subhead.text = it } } 83 84 launch { 85 viewModel.colorOptions.collect { colorOptions -> 86 colorsAdapter.setItems(colorOptions) { 87 var indexToFocus = colorOptions.indexOfFirst { it.isSelected.value } 88 indexToFocus = if (indexToFocus < 0) 0 else indexToFocus 89 (colorsList.layoutManager as LinearLayoutManager) 90 .scrollToPositionWithOffset(indexToFocus, 0) 91 } 92 } 93 } 94 95 launch { 96 viewModel.previewingColorOption.collect { colorModel -> 97 if (colorModel != null) { 98 colorUpdateViewModel.previewColors( 99 colorModel.colorOption.seedColor, 100 colorModel.colorOption.style, 101 ) 102 } else colorUpdateViewModel.resetPreview() 103 } 104 } 105 } 106 } 107 } 108 109 private fun createOptionItemAdapter( 110 uiMode: Int, 111 lifecycleOwner: LifecycleOwner, 112 ): OptionItemAdapter2<ColorOptionIconViewModel> = 113 OptionItemAdapter2( 114 layoutResourceId = R.layout.color_option2, 115 lifecycleOwner = lifecycleOwner, 116 bindPayload = { itemView: View, colorIcon: ColorOptionIconViewModel -> 117 val colorOptionIconView = 118 itemView.requireViewById<ColorOptionIconView2>( 119 com.android.wallpaper.R.id.background 120 ) 121 val night = uiMode and UI_MODE_NIGHT_MASK == UI_MODE_NIGHT_YES 122 ColorOptionIconBinder2.bind(colorOptionIconView, colorIcon, night) 123 // Return null since it does not need the lifecycleOwner to launch any job for later 124 // disposal when rebind. 125 return@OptionItemAdapter2 null 126 }, 127 ) 128 129 private fun RecyclerView.initColorsList( 130 context: Context, 131 adapter: OptionItemAdapter2<ColorOptionIconViewModel>, 132 ) { 133 apply { 134 this.adapter = adapter 135 layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false) 136 addItemDecoration( 137 SingleRowListItemSpacing( 138 context.resources.getDimensionPixelSize( 139 R.dimen.floating_sheet_content_horizontal_padding 140 ), 141 0, 142 ) 143 ) 144 } 145 } 146 } 147