• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.providers.media.photopicker.ui.settings;
18 
19 import static com.android.providers.media.MediaApplication.getConfigStore;
20 
21 import static java.util.Objects.requireNonNull;
22 
23 import android.content.Context;
24 import android.os.Bundle;
25 import android.os.UserHandle;
26 import android.text.TextUtils;
27 import android.widget.Toast;
28 
29 import androidx.annotation.NonNull;
30 import androidx.annotation.UiThread;
31 import androidx.lifecycle.ViewModel;
32 import androidx.lifecycle.ViewModelProvider;
33 import androidx.preference.Preference;
34 import androidx.preference.PreferenceFragmentCompat;
35 import androidx.preference.PreferenceScreen;
36 
37 import com.android.providers.media.R;
38 import com.android.providers.media.photopicker.data.model.UserId;
39 import com.android.settingslib.widget.SelectorWithWidgetPreference;
40 
41 /**
42  * This fragment will display a list of available cloud providers for the profile selected.
43  * Users can view or change the preferred cloud provider media app.
44  */
45 public class SettingsCloudMediaSelectFragment extends PreferenceFragmentCompat
46         implements SelectorWithWidgetPreference.OnClickListener {
47     public static final String EXTRA_TAB_USER_ID = "user_id";
48     private static final String TAG = "SettingsCMSelectFgmt";
49 
50     @NonNull
51     private UserId mUserId;
52     @NonNull
53     private Context mContext;
54     @NonNull
55     private SettingsCloudMediaViewModel mSettingsCloudMediaViewModel;
56 
57     @Override
onAttach(@onNull Context context)58     public void onAttach(@NonNull Context context) {
59         super.onAttach(context);
60 
61         mContext = requireNonNull(context);
62         mUserId = requireNonNull(getUserId());
63         mSettingsCloudMediaViewModel = createViewModel();
64     }
65 
66     @Override
onResume()67     public void onResume() {
68         super.onResume();
69 
70         mSettingsCloudMediaViewModel.loadAccountNameAsync();
71     }
72 
73     @UiThread
74     @Override
onRadioButtonClicked(@onNull SelectorWithWidgetPreference selectedPref)75     public void onRadioButtonClicked(@NonNull SelectorWithWidgetPreference selectedPref) {
76         final String selectedProviderKey = selectedPref.getKey();
77         // Check if current provider is different from the selected provider.
78         if (!TextUtils.equals(selectedProviderKey,
79                 mSettingsCloudMediaViewModel.getSelectedPreferenceKey())) {
80             final boolean success =
81                     mSettingsCloudMediaViewModel.updateSelectedProvider(selectedProviderKey);
82             if (success) {
83                 updateSelectedRadioButton();
84             } else {
85                 Toast.makeText(getContext(),
86                         R.string.picker_settings_toast_error, Toast.LENGTH_SHORT).show();
87             }
88         }
89     }
90 
91     @Override
onCreatePreferences(Bundle savedInstanceState, String rootKey)92     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
93         super.addPreferencesFromResource(R.xml.pref_screen_picker_settings);
94 
95         mSettingsCloudMediaViewModel.loadData(getConfigStore());
96         observeAccountNameChanges();
97         refreshUI();
98     }
99 
100     @UiThread
refreshUI()101     private void refreshUI() {
102         final PreferenceScreen screen = getPreferenceScreen();
103         resetPreferenceScreen(screen);
104 
105         screen.addPreference(buildTitlePreference());
106         for (CloudMediaProviderOption provider :
107                 mSettingsCloudMediaViewModel.getProviderOptions()) {
108             screen.addPreference(buildProviderOptionPreference(provider));
109         }
110 
111         updateSelectedRadioButton();
112     }
113 
observeAccountNameChanges()114     private void observeAccountNameChanges() {
115         mSettingsCloudMediaViewModel.getCurrentProviderAccount()
116                 .observe(this, accountDetails -> {
117                     // Only update current account name on the UI if cloud provider linked to the
118                     // account name matches the current provider.
119                     if (accountDetails != null
120                             && accountDetails.getCloudProviderAuthority()
121                             .equals(mSettingsCloudMediaViewModel.getSelectedProviderAuthority())) {
122                         final Preference selectedPref = findPreference(
123                                 mSettingsCloudMediaViewModel.getSelectedPreferenceKey());
124                         // TODO(b/262002538): {@code selectedPref} could be null if the selected
125                         //  cloud provider is not in the allowed list. This is not something a
126                         //  typical user will encounter.
127                         if (selectedPref != null) {
128                             selectedPref.setSummary(accountDetails.getCloudProviderAccountName());
129                         }
130                     }
131                 });
132     }
133 
134     @UiThread
updateSelectedRadioButton()135     private void updateSelectedRadioButton() {
136         final String selectedPreferenceKey =
137                 mSettingsCloudMediaViewModel.getSelectedPreferenceKey();
138         for (CloudMediaProviderOption providerOption
139                 : mSettingsCloudMediaViewModel.getProviderOptions()) {
140             final Preference pref = findPreference(providerOption.getKey());
141             if (pref instanceof SelectorWithWidgetPreference) {
142                 final SelectorWithWidgetPreference providerPref =
143                         (SelectorWithWidgetPreference) pref;
144 
145                 final boolean newSelectionState =
146                         TextUtils.equals(providerPref.getKey(), selectedPreferenceKey);
147                 providerPref.setChecked(newSelectionState);
148 
149                 providerPref.setSummary(null);
150                 if (newSelectionState) {
151                     mSettingsCloudMediaViewModel.loadAccountNameAsync();
152                 }
153             }
154         }
155     }
156 
157     @NonNull
buildProviderOptionPreference(@onNull CloudMediaProviderOption provider)158     private Preference buildProviderOptionPreference(@NonNull CloudMediaProviderOption provider) {
159         final SelectorWithWidgetPreference pref =
160                 new SelectorWithWidgetPreference(getPrefContext());
161 
162         // Preferences are stored in SharedPreferences by default. This feature is disabled
163         // as Cloud picker preferences are stored in SharedPreferences separately.
164         pref.setPersistent(false);
165         pref.setTitle(provider.getLabel());
166         pref.setIcon(provider.getIcon());
167         pref.setKey(provider.getKey());
168         pref.setOnClickListener(this);
169         return pref;
170     }
171 
172     @NonNull
buildTitlePreference()173     private Preference buildTitlePreference() {
174         final Preference titlePref = new Preference(getPrefContext());
175         titlePref.setTitle(R.string.picker_settings_selection_message);
176         titlePref.setSelectable(false);
177         titlePref.setPersistent(false);
178         titlePref.setLayoutResource(R.layout.pref_settings_cloud_select_title);
179         return titlePref;
180     }
181 
getPrefContext()182     private Context getPrefContext() {
183         return getPreferenceManager().getContext();
184     }
185 
resetPreferenceScreen(PreferenceScreen screen)186     private void resetPreferenceScreen(PreferenceScreen screen) {
187         screen.removeAll();
188     }
189 
190     @NonNull
getUserId()191     private UserId getUserId() {
192         if (getArguments() != null && getArguments().containsKey(EXTRA_TAB_USER_ID)) {
193             final int currentUID = getArguments().getInt(EXTRA_TAB_USER_ID);
194             final UserHandle userHandle = UserHandle.of(currentUID);
195             return UserId.of(userHandle);
196         } else {
197             throw new IllegalArgumentException(
198                     "User Id for a SettingsCloudMediaSelectFragment is not set.");
199         }
200     }
201 
202     @NonNull
createViewModel()203     private SettingsCloudMediaViewModel createViewModel() {
204         final ViewModelProvider viewModelProvider =
205                 new ViewModelProvider(
206                         requireActivity(),
207                         new SettingsViewModelFactory(mContext, mUserId)
208                 );
209         final String viewModelKey = Integer.toString(mUserId.getIdentifier());
210 
211         return viewModelProvider.get(viewModelKey, SettingsCloudMediaViewModel.class);
212     }
213 
214     private static class SettingsViewModelFactory implements ViewModelProvider.Factory {
215         @NonNull
216         private final Context mContext;
217         @NonNull
218         private final UserId mUserId;
219 
SettingsViewModelFactory(@onNull Context context, @NonNull UserId userId)220         SettingsViewModelFactory(@NonNull Context context, @NonNull UserId userId) {
221             mContext = requireNonNull(context);
222             mUserId = requireNonNull(userId);
223         }
224 
225         @NonNull
226         @Override
create(@onNull Class<T> modelClass)227         public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
228             return (T) new SettingsCloudMediaViewModel(mContext, mUserId);
229         }
230     }
231 }