1 /* 2 * Copyright (C) 2022 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.adservices.ui.settings.delegates; 17 18 import android.content.Intent; 19 import android.os.Build; 20 import android.text.method.LinkMovementMethod; 21 import android.util.Pair; 22 import android.view.View; 23 import android.widget.TextView; 24 25 import androidx.annotation.RequiresApi; 26 import androidx.lifecycle.Observer; 27 28 import com.android.adservices.api.R; 29 import com.android.adservices.data.topics.Topic; 30 import com.android.adservices.service.FlagsFactory; 31 import com.android.adservices.service.stats.UiStatsLogger; 32 import com.android.adservices.ui.settings.DialogFragmentManager; 33 import com.android.adservices.ui.settings.DialogManager; 34 import com.android.adservices.ui.settings.activities.BlockedTopicsActivity; 35 import com.android.adservices.ui.settings.activities.TopicsActivity; 36 import com.android.adservices.ui.settings.fragments.AdServicesSettingsTopicsFragment; 37 import com.android.adservices.ui.settings.viewmodels.TopicsViewModel; 38 import com.android.adservices.ui.settings.viewmodels.TopicsViewModel.TopicsViewModelUiEvent; 39 import com.android.settingslib.widget.MainSwitchBar; 40 41 /** 42 * Delegate class that helps AdServices Settings fragments to respond to all view model/user events. 43 */ 44 @RequiresApi(Build.VERSION_CODES.S) 45 public class TopicsActionDelegate { 46 private final TopicsActivity mTopicsActivity; 47 private final TopicsViewModel mTopicsViewModel; 48 TopicsActionDelegate(TopicsActivity topicsActivity, TopicsViewModel topicsViewModel)49 public TopicsActionDelegate(TopicsActivity topicsActivity, TopicsViewModel topicsViewModel) { 50 mTopicsActivity = topicsActivity; 51 mTopicsViewModel = topicsViewModel; 52 listenToTopicsViewModelUiEvents(); 53 } 54 listenToTopicsViewModelUiEvents()55 private void listenToTopicsViewModelUiEvents() { 56 Observer<Pair<TopicsViewModelUiEvent, Topic>> observer = 57 eventTopicPair -> { 58 if (eventTopicPair == null) { 59 return; 60 } 61 TopicsViewModelUiEvent event = eventTopicPair.first; 62 Topic topic = eventTopicPair.second; 63 if (event == null) { 64 return; 65 } 66 try { 67 switch (event) { 68 case SWITCH_ON_TOPICS: 69 if (FlagsFactory.getFlags().getToggleSpeedBumpEnabled()) { 70 DialogFragmentManager.showOptInTopicsDialog(mTopicsActivity); 71 } 72 mTopicsViewModel.setTopicsConsent(true); 73 mTopicsViewModel.refresh(); 74 break; 75 case SWITCH_OFF_TOPICS: 76 if (FlagsFactory.getFlags().getToggleSpeedBumpEnabled()) { 77 DialogFragmentManager.showOptOutTopicsDialog( 78 mTopicsActivity, mTopicsViewModel); 79 } else { 80 mTopicsViewModel.setTopicsConsent(false); 81 mTopicsViewModel.refresh(); 82 } 83 break; 84 case BLOCK_TOPIC: 85 UiStatsLogger.logBlockTopicSelected(); 86 if (FlagsFactory.getFlags().getUiDialogsFeatureEnabled()) { 87 if (FlagsFactory.getFlags().getUiDialogFragmentEnabled()) { 88 DialogFragmentManager.showBlockTopicDialog( 89 mTopicsActivity, mTopicsViewModel, topic); 90 } else { 91 DialogManager.showBlockTopicDialog( 92 mTopicsActivity, mTopicsViewModel, topic); 93 } 94 } else { 95 mTopicsViewModel.revokeTopicConsent(topic); 96 } 97 break; 98 case RESET_TOPICS: 99 UiStatsLogger.logResetTopicSelected(); 100 if (FlagsFactory.getFlags().getUiDialogsFeatureEnabled()) { 101 if (FlagsFactory.getFlags().getUiDialogFragmentEnabled()) { 102 DialogFragmentManager.showResetTopicDialog( 103 mTopicsActivity, mTopicsViewModel); 104 } else { 105 DialogManager.showResetTopicDialog( 106 mTopicsActivity, mTopicsViewModel); 107 } 108 } else { 109 mTopicsViewModel.resetTopics(); 110 } 111 break; 112 case DISPLAY_BLOCKED_TOPICS_FRAGMENT: 113 Intent intent = 114 new Intent(mTopicsActivity, BlockedTopicsActivity.class); 115 mTopicsActivity.startActivity(intent); 116 break; 117 } 118 } finally { 119 mTopicsViewModel.uiEventHandled(); 120 } 121 }; 122 mTopicsViewModel.getUiEvents().observe(mTopicsActivity, observer); 123 } 124 125 /** 126 * Configure all UI elements (except topics list) in {@link AdServicesSettingsTopicsFragment} to 127 * handle user actions. 128 */ initTopicsFragment(AdServicesSettingsTopicsFragment fragment)129 public void initTopicsFragment(AdServicesSettingsTopicsFragment fragment) { 130 mTopicsActivity.setTitle(R.string.settingsUI_topics_ga_title); 131 132 configureTopicsConsentSwitch(fragment); 133 134 setGaUxTopicsViewText(); 135 configureBlockedTopicsFragmentButton(fragment); 136 configureResetTopicsButton(fragment); 137 } 138 setGaUxTopicsViewText()139 private void setGaUxTopicsViewText() { 140 ((TextView) mTopicsActivity.findViewById(R.id.blocked_topics_button_child)) 141 .setText(R.string.settingsUI_blocked_topics_ga_title); 142 ((TextView) mTopicsActivity.findViewById(R.id.reset_topics_button_child)) 143 .setText(R.string.settingsUI_reset_topics_ga_title); 144 ((TextView) mTopicsActivity.findViewById(R.id.no_topics_state)) 145 .setText(R.string.settingsUI_topics_view_no_topics_ga_text); 146 ((TextView) mTopicsActivity.findViewById(R.id.no_topics_state)) 147 .setMovementMethod(LinkMovementMethod.getInstance()); 148 } 149 configureTopicsConsentSwitch(AdServicesSettingsTopicsFragment fragment)150 private void configureTopicsConsentSwitch(AdServicesSettingsTopicsFragment fragment) { 151 MainSwitchBar topicsSwitchBar = mTopicsActivity.findViewById(R.id.topics_switch_bar); 152 153 mTopicsViewModel.getTopicsConsent().observe(fragment, topicsSwitchBar::setChecked); 154 topicsSwitchBar.setOnClickListener( 155 switchBar -> mTopicsViewModel.consentSwitchClickHandler((MainSwitchBar) switchBar)); 156 } 157 configureBlockedTopicsFragmentButton(AdServicesSettingsTopicsFragment fragment)158 private void configureBlockedTopicsFragmentButton(AdServicesSettingsTopicsFragment fragment) { 159 View blockedTopicsButton = fragment.requireView().findViewById(R.id.blocked_topics_button); 160 View blockedTopicsWhenEmptyListButton = 161 fragment.requireView().findViewById(R.id.blocked_topics_when_empty_state_button); 162 blockedTopicsButton.setOnClickListener( 163 view -> mTopicsViewModel.blockedTopicsFragmentButtonClickHandler()); 164 blockedTopicsWhenEmptyListButton.setOnClickListener( 165 view -> mTopicsViewModel.blockedTopicsFragmentButtonClickHandler()); 166 } 167 configureResetTopicsButton(AdServicesSettingsTopicsFragment fragment)168 private void configureResetTopicsButton(AdServicesSettingsTopicsFragment fragment) { 169 View resetTopicsButton = fragment.requireView().findViewById(R.id.reset_topics_button); 170 resetTopicsButton.setOnClickListener( 171 view -> mTopicsViewModel.resetTopicsButtonClickHandler()); 172 } 173 } 174