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