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.fragments; 17 18 import android.os.Build; 19 import android.os.Bundle; 20 import android.view.LayoutInflater; 21 import android.view.View; 22 import android.view.ViewGroup; 23 import android.widget.Button; 24 25 import androidx.annotation.NonNull; 26 import androidx.annotation.RequiresApi; 27 import androidx.fragment.app.Fragment; 28 import androidx.lifecycle.ViewModelProvider; 29 import androidx.recyclerview.widget.LinearLayoutManager; 30 import androidx.recyclerview.widget.RecyclerView; 31 32 import com.android.adservices.api.R; 33 import com.android.adservices.service.FlagsFactory; 34 import com.android.adservices.service.consent.App; 35 import com.android.adservices.ui.settings.activities.AppsActivity; 36 import com.android.adservices.ui.settings.delegates.AppsActionDelegate; 37 import com.android.adservices.ui.settings.viewadatpors.AppsListViewAdapter; 38 import com.android.adservices.ui.settings.viewmodels.AppsViewModel; 39 40 import java.util.function.Function; 41 42 /** Fragment for the apps view of the AdServices Settings App. */ 43 // TODO(b/269798827): Enable for R. 44 @RequiresApi(Build.VERSION_CODES.S) 45 public class AdServicesSettingsAppsFragment extends Fragment { 46 47 @Override onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)48 public View onCreateView( 49 LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 50 return inflater.inflate(R.layout.apps_fragment, container, false); 51 } 52 53 @Override onViewCreated(@onNull View view, Bundle savedInstanceState)54 public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { 55 setupViewModel(view); 56 } 57 58 @Override onResume()59 public void onResume() { 60 super.onResume(); 61 AppsViewModel viewModel = new ViewModelProvider(requireActivity()).get(AppsViewModel.class); 62 viewModel.refresh(); 63 initActionListeners(); 64 } 65 66 // initialize all action listeners except for actions in apps list initActionListeners()67 private void initActionListeners() { 68 AppsActionDelegate actionDelegate = ((AppsActivity) requireActivity()).getActionDelegate(); 69 actionDelegate.initAppsFragment(this); 70 } 71 72 // initializes view model connection with apps list. 73 // (Action listeners for each item in the list will be handled by the adapter) setupViewModel(View rootView)74 private void setupViewModel(View rootView) { 75 // create adapter 76 AppsViewModel viewModel = new ViewModelProvider(requireActivity()).get(AppsViewModel.class); 77 Function<App, View.OnClickListener> getOnclickListener = 78 app -> view -> viewModel.revokeAppConsentButtonClickHandler(app); 79 AppsListViewAdapter adapter = 80 new AppsListViewAdapter( 81 requireContext(), viewModel.getApps(), getOnclickListener, false); 82 83 // set adapter for recyclerView 84 RecyclerView recyclerView = rootView.findViewById(R.id.apps_list); 85 recyclerView.setLayoutManager(new LinearLayoutManager(requireContext())); 86 recyclerView.setAdapter(adapter); 87 88 View noAppsMessage = rootView.findViewById(R.id.no_apps_message); 89 View emptyAppsHiddenSection = rootView.findViewById(R.id.empty_apps_hidden_section); 90 View blockedAppsBtn = rootView.findViewById(R.id.blocked_apps_button); 91 92 // "Empty State": the state when the non-blocked list of apps/topics is empty. 93 // blocked_apps_when_empty_state_button is added to noAppsMessage 94 // noAppsMessages is visible only when Empty State 95 // blocked_apps_when_empty_state_button differs from blocked_apps_button 96 // in style with rounded corners, centered, colored 97 viewModel 98 .getApps() 99 .observe( 100 getViewLifecycleOwner(), 101 appsList -> { 102 if (appsList.isEmpty()) { 103 noAppsMessage.setVisibility(View.VISIBLE); 104 emptyAppsHiddenSection.setVisibility(View.GONE); 105 blockedAppsBtn.setVisibility(View.GONE); 106 } else { 107 noAppsMessage.setVisibility(View.GONE); 108 emptyAppsHiddenSection.setVisibility(View.VISIBLE); 109 blockedAppsBtn.setVisibility(View.VISIBLE); 110 } 111 adapter.notifyDataSetChanged(); 112 }); 113 114 Button blockedAppsWhenEmptyStateButton = 115 rootView.findViewById(R.id.blocked_apps_when_empty_state_button); 116 viewModel 117 .getBlockedApps() 118 .observe( 119 getViewLifecycleOwner(), 120 blockedAppsList -> { 121 if (blockedAppsList.isEmpty()) { 122 blockedAppsWhenEmptyStateButton.setEnabled(false); 123 blockedAppsWhenEmptyStateButton.setAlpha( 124 getResources().getFloat(R.dimen.disabled_button_alpha)); 125 blockedAppsWhenEmptyStateButton.setText( 126 FlagsFactory.getFlags().getGaUxFeatureEnabled() 127 ? R.string.settingsUI_no_blocked_apps_ga_text 128 : R.string 129 .settingsUI_apps_view_no_blocked_apps_text); 130 } else { 131 blockedAppsWhenEmptyStateButton.setEnabled(true); 132 blockedAppsWhenEmptyStateButton.setAlpha( 133 getResources().getFloat(R.dimen.enabled_button_alpha)); 134 blockedAppsWhenEmptyStateButton.setText( 135 FlagsFactory.getFlags().getGaUxFeatureEnabled() 136 ? R.string.settingsUI_view_blocked_apps_title 137 : R.string.settingsUI_blocked_apps_title); 138 } 139 }); 140 } 141 } 142