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 // TODO(b/269798827): Enable for R. 45 @RequiresApi(Build.VERSION_CODES.S) 46 public class TopicsActionDelegate { 47 private final TopicsActivity mTopicsActivity; 48 private final TopicsViewModel mTopicsViewModel; 49 TopicsActionDelegate(TopicsActivity topicsActivity, TopicsViewModel topicsViewModel)50 public TopicsActionDelegate(TopicsActivity topicsActivity, TopicsViewModel topicsViewModel) { 51 mTopicsActivity = topicsActivity; 52 mTopicsViewModel = topicsViewModel; 53 listenToTopicsViewModelUiEvents(); 54 } 55 listenToTopicsViewModelUiEvents()56 private void listenToTopicsViewModelUiEvents() { 57 Observer<Pair<TopicsViewModelUiEvent, Topic>> observer = 58 eventTopicPair -> { 59 if (eventTopicPair == null) { 60 return; 61 } 62 TopicsViewModelUiEvent event = eventTopicPair.first; 63 Topic topic = eventTopicPair.second; 64 if (event == null) { 65 return; 66 } 67 try { 68 switch (event) { 69 case SWITCH_ON_TOPICS: 70 mTopicsViewModel.setTopicsConsent(true); 71 mTopicsViewModel.refresh(); 72 break; 73 case SWITCH_OFF_TOPICS: 74 mTopicsViewModel.setTopicsConsent(false); 75 mTopicsViewModel.refresh(); 76 break; 77 case BLOCK_TOPIC: 78 UiStatsLogger.logBlockTopicSelected(mTopicsActivity); 79 if (FlagsFactory.getFlags().getUIDialogsFeatureEnabled()) { 80 if (FlagsFactory.getFlags().getUiDialogFragmentEnabled()) { 81 DialogFragmentManager.showBlockTopicDialog( 82 mTopicsActivity, mTopicsViewModel, topic); 83 } else { 84 DialogManager.showBlockTopicDialog( 85 mTopicsActivity, mTopicsViewModel, topic); 86 } 87 } else { 88 mTopicsViewModel.revokeTopicConsent(topic); 89 } 90 break; 91 case RESET_TOPICS: 92 UiStatsLogger.logResetTopicSelected(mTopicsActivity); 93 if (FlagsFactory.getFlags().getUIDialogsFeatureEnabled()) { 94 if (FlagsFactory.getFlags().getUiDialogFragmentEnabled()) { 95 DialogFragmentManager.showResetTopicDialog( 96 mTopicsActivity, mTopicsViewModel); 97 } else { 98 DialogManager.showResetTopicDialog( 99 mTopicsActivity, mTopicsViewModel); 100 } 101 } else { 102 mTopicsViewModel.resetTopics(); 103 } 104 break; 105 case DISPLAY_BLOCKED_TOPICS_FRAGMENT: 106 Intent intent = 107 new Intent(mTopicsActivity, BlockedTopicsActivity.class); 108 mTopicsActivity.startActivity(intent); 109 break; 110 } 111 } finally { 112 mTopicsViewModel.uiEventHandled(); 113 } 114 }; 115 mTopicsViewModel.getUiEvents().observe(mTopicsActivity, observer); 116 } 117 118 /** 119 * Configure all UI elements (except topics list) in {@link AdServicesSettingsTopicsFragment} to 120 * handle user actions. 121 */ initTopicsFragment(AdServicesSettingsTopicsFragment fragment)122 public void initTopicsFragment(AdServicesSettingsTopicsFragment fragment) { 123 if (FlagsFactory.getFlags().getGaUxFeatureEnabled()) { 124 mTopicsActivity.setTitle(R.string.settingsUI_topics_ga_title); 125 126 configureTopicsConsentSwitch(fragment); 127 128 setGaUxLayoutVisibilities(View.VISIBLE); 129 setBetaLayoutVisibilities(View.GONE); 130 setGaUxTopicsViewText(); 131 } else { 132 mTopicsActivity.setTitle(R.string.settingsUI_topics_view_title); 133 134 setGaUxLayoutVisibilities(View.GONE); 135 setBetaLayoutVisibilities(View.VISIBLE); 136 setBetaTopicsViewText(); 137 } 138 configureBlockedTopicsFragmentButton(fragment); 139 configureResetTopicsButton(fragment); 140 } 141 setGaUxTopicsViewText()142 private void setGaUxTopicsViewText() { 143 ((TextView) mTopicsActivity.findViewById(R.id.blocked_topics_button_child)) 144 .setText(R.string.settingsUI_blocked_topics_ga_title); 145 ((TextView) mTopicsActivity.findViewById(R.id.reset_topics_button_child)) 146 .setText(R.string.settingsUI_reset_topics_ga_title); 147 ((TextView) mTopicsActivity.findViewById(R.id.no_topics_state)) 148 .setText(R.string.settingsUI_topics_view_no_topics_ga_text); 149 ((TextView) mTopicsActivity.findViewById(R.id.no_topics_state)) 150 .setMovementMethod(LinkMovementMethod.getInstance()); 151 } 152 setBetaTopicsViewText()153 private void setBetaTopicsViewText() { 154 ((TextView) mTopicsActivity.findViewById(R.id.blocked_topics_button_child)) 155 .setText(R.string.settingsUI_blocked_topics_title); 156 ((TextView) mTopicsActivity.findViewById(R.id.reset_topics_button_child)) 157 .setText(R.string.settingsUI_reset_topics_title); 158 ((TextView) mTopicsActivity.findViewById(R.id.no_topics_state)) 159 .setText(R.string.settingsUI_topics_view_no_topics_text); 160 } 161 setBetaLayoutVisibilities(int visibility)162 private void setBetaLayoutVisibilities(int visibility) { 163 mTopicsActivity.findViewById(R.id.topics_introduction).setVisibility(visibility); 164 mTopicsActivity.findViewById(R.id.topics_view_footer).setVisibility(visibility); 165 } 166 setGaUxLayoutVisibilities(int visibility)167 private void setGaUxLayoutVisibilities(int visibility) { 168 mTopicsActivity.findViewById(R.id.topics_ga_introduction).setVisibility(visibility); 169 mTopicsActivity.findViewById(R.id.topics_view_ga_footer).setVisibility(visibility); 170 } 171 configureTopicsConsentSwitch(AdServicesSettingsTopicsFragment fragment)172 private void configureTopicsConsentSwitch(AdServicesSettingsTopicsFragment fragment) { 173 MainSwitchBar topicsSwitchBar = mTopicsActivity.findViewById(R.id.topics_switch_bar); 174 topicsSwitchBar.setVisibility(View.VISIBLE); 175 176 mTopicsViewModel.getTopicsConsent().observe(fragment, topicsSwitchBar::setChecked); 177 topicsSwitchBar.setOnClickListener( 178 switchBar -> mTopicsViewModel.consentSwitchClickHandler((MainSwitchBar) switchBar)); 179 } 180 configureBlockedTopicsFragmentButton(AdServicesSettingsTopicsFragment fragment)181 private void configureBlockedTopicsFragmentButton(AdServicesSettingsTopicsFragment fragment) { 182 View blockedTopicsButton = fragment.requireView().findViewById(R.id.blocked_topics_button); 183 View blockedTopicsWhenEmptyListButton = 184 fragment.requireView().findViewById(R.id.blocked_topics_when_empty_state_button); 185 blockedTopicsButton.setOnClickListener( 186 view -> mTopicsViewModel.blockedTopicsFragmentButtonClickHandler()); 187 blockedTopicsWhenEmptyListButton.setOnClickListener( 188 view -> mTopicsViewModel.blockedTopicsFragmentButtonClickHandler()); 189 } 190 configureResetTopicsButton(AdServicesSettingsTopicsFragment fragment)191 private void configureResetTopicsButton(AdServicesSettingsTopicsFragment fragment) { 192 View resetTopicsButton = fragment.requireView().findViewById(R.id.reset_topics_button); 193 resetTopicsButton.setOnClickListener( 194 view -> mTopicsViewModel.resetTopicsButtonClickHandler()); 195 } 196 } 197