Add buttons for new settings design

This adds a new class called PrimaryProviderPreference
which is responsible for laying out the old cog view if
the feature is disabled and the new button view if it
is enabled.

Screenshots:
https://hsv.googleplex.com/5109836204212224
https://hsv.googleplex.com/5574754636398592
https://hsv.googleplex.com/6737135727017984

Change-Id: I1ad0c59a4afc5be3694b499f66bbd7306dfbee69
Test: Manual test with flag on + off & unit tests
Bug: 300979487
This commit is contained in:
Becca Hughes
2024-01-10 19:20:22 +00:00
parent 306df3beaa
commit 782fcb9bd5
13 changed files with 833 additions and 114 deletions

View File

@@ -0,0 +1,144 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications.credentials;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Looper;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import androidx.preference.PreferenceViewHolder;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.settings.R;
import com.android.settings.testutils.ResourcesUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
public class DefaultCombinedPreferenceControllerTest {
private Context mContext;
private PrimaryProviderPreference.Delegate mDelegate;
private AttributeSet mAttributes;
@Before
public void setUp() {
mContext = spy(ApplicationProvider.getApplicationContext());
if (Looper.myLooper() == null) {
Looper.prepare(); // needed to create the preference screen
}
mDelegate =
new PrimaryProviderPreference.Delegate() {
public void onOpenButtonClicked() {}
public void onChangeButtonClicked() {}
};
}
@Test
public void ensureSettingIntentNullForNewDesign() {
if (!PrimaryProviderPreference.shouldUseNewSettingsUi()) {
return;
}
// The setting intent should be null for the new design since this
// is handled by the delegate for the PrimaryProviderPreference.
DefaultCombinedPreferenceController dcpc =
new DefaultCombinedPreferenceController(mContext);
assertThat(dcpc.getSettingIntent(null).getPackage()).isNull();
}
@Test
public void ensureSettingIntentNotNullForOldDesign() {
if (PrimaryProviderPreference.shouldUseNewSettingsUi()) {
return;
}
// For the old design the setting intent should still be used.
DefaultCombinedPreferenceController dcpc =
new DefaultCombinedPreferenceController(mContext);
assertThat(dcpc.getSettingIntent(null).getPackage()).isNotNull();
}
@Test
public void ensureSettingsActivityIntentCreatedSuccessfully() {
DefaultCombinedPreferenceController dcpc =
new DefaultCombinedPreferenceController(mContext);
// Ensure that the settings activity is only created if we haved the right combination
// of package and class name.
assertThat(dcpc.createSettingsActivityIntent(null, null)).isNull();
assertThat(dcpc.createSettingsActivityIntent("", null)).isNull();
assertThat(dcpc.createSettingsActivityIntent("", "")).isNull();
assertThat(dcpc.createSettingsActivityIntent("com.test", "")).isNull();
assertThat(dcpc.createSettingsActivityIntent("com.test", "ClassName")).isNotNull();
}
@Test
public void ensureUpdatePreferenceForProviderPopulatesInfo() {
if (!PrimaryProviderPreference.shouldUseNewSettingsUi()) {
return;
}
DefaultCombinedPreferenceController dcpc =
new DefaultCombinedPreferenceController(mContext);
PrimaryProviderPreference ppp = createTestPreference();
Drawable appIcon = mContext.getResources().getDrawable(R.drawable.ic_settings_delete);
// Update the preference to use the provider and make sure the view
// was updated.
dcpc.updatePreferenceForProvider(ppp, "App Name", "Subtitle", appIcon, null);
assertThat(ppp.getTitle().toString()).isEqualTo("App Name");
assertThat(ppp.getSummary().toString()).isEqualTo("Subtitle");
assertThat(ppp.getIcon()).isEqualTo(appIcon);
// Set the preference back to none and make sure the view was updated.
dcpc.updatePreferenceForProvider(ppp, null, null, null, null);
assertThat(ppp.getTitle().toString()).isEqualTo("None");
assertThat(ppp.getSummary()).isNull();
assertThat(ppp.getIcon()).isNull();
}
private PrimaryProviderPreference createTestPreference() {
int layoutId =
ResourcesUtils.getResourcesId(
mContext, "layout", "preference_credential_manager_with_buttons");
PreferenceViewHolder holder =
PreferenceViewHolder.createInstanceForTests(
LayoutInflater.from(mContext).inflate(layoutId, null));
PreferenceViewHolder holderForTest = spy(holder);
View gearView = new View(mContext, null);
int gearId = ResourcesUtils.getResourcesId(mContext, "id", "settings_button");
when(holderForTest.findViewById(gearId)).thenReturn(gearView);
PrimaryProviderPreference ppp = new PrimaryProviderPreference(mContext, mAttributes);
ppp.setDelegate(mDelegate);
ppp.onBindViewHolder(holderForTest);
return ppp;
}
}

View File

@@ -0,0 +1,182 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.applications.credentials;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.os.Looper;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import androidx.preference.PreferenceViewHolder;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.settings.testutils.ResourcesUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
public class PrimaryProviderPreferenceTest {
private Context mContext;
private PrimaryProviderPreference.Delegate mDelegate;
private boolean mReceivedOpenButtonClicked = false;
private boolean mReceivedChangeButtonClicked = false;
private AttributeSet mAttributes;
@Before
public void setUp() {
mContext = spy(ApplicationProvider.getApplicationContext());
if (Looper.myLooper() == null) {
Looper.prepare(); // needed to create the preference screen
}
mReceivedOpenButtonClicked = false;
mReceivedChangeButtonClicked = false;
mDelegate =
new PrimaryProviderPreference.Delegate() {
public void onOpenButtonClicked() {
mReceivedOpenButtonClicked = true;
}
public void onChangeButtonClicked() {
mReceivedChangeButtonClicked = true;
}
};
}
@Test
public void ensureButtonsClicksCallDelegate_newDesign() {
if (!PrimaryProviderPreference.shouldUseNewSettingsUi()) {
return;
}
PrimaryProviderPreference ppp = createTestPreferenceWithNewLayout();
// Test that all the views & buttons are bound correctly.
assertThat(ppp.getOpenButton()).isNotNull();
assertThat(ppp.getChangeButton()).isNotNull();
assertThat(ppp.getButtonFrameView()).isNotNull();
// Test that clicking the open button results in the delegate being
// called.
assertThat(mReceivedOpenButtonClicked).isFalse();
ppp.getOpenButton().performClick();
assertThat(mReceivedOpenButtonClicked).isTrue();
// Test that clicking the change button results in the delegate being
// called.
assertThat(mReceivedChangeButtonClicked).isFalse();
ppp.getChangeButton().performClick();
assertThat(mReceivedChangeButtonClicked).isTrue();
}
@Test
public void ensureButtonsClicksCallDelegate_newDesign_openButtonVisibility() {
if (!PrimaryProviderPreference.shouldUseNewSettingsUi()) {
return;
}
PrimaryProviderPreference ppp = createTestPreferenceWithNewLayout();
// Test that the open button is visible.
assertThat(ppp.getOpenButton()).isNotNull();
assertThat(ppp.getOpenButton().getVisibility()).isEqualTo(View.GONE);
// Show the button and make sure the view was updated.
ppp.setOpenButtonVisible(true);
assertThat(ppp.getOpenButton().getVisibility()).isEqualTo(View.VISIBLE);
// Hide the button and make sure the view was updated.
ppp.setOpenButtonVisible(false);
assertThat(ppp.getOpenButton().getVisibility()).isEqualTo(View.GONE);
}
@Test
public void ensureButtonsClicksCallDelegate_newDesign_buttonsHidden() {
if (!PrimaryProviderPreference.shouldUseNewSettingsUi()) {
return;
}
PrimaryProviderPreference ppp = createTestPreferenceWithNewLayout();
// Test that the buttons are visible.
assertThat(ppp.getButtonFrameView()).isNotNull();
assertThat(ppp.getButtonFrameView().getVisibility()).isEqualTo(View.GONE);
assertThat(mReceivedChangeButtonClicked).isFalse();
// If we show the buttons the visiblility should be updated.
ppp.setButtonsVisible(true);
assertThat(ppp.getButtonFrameView().getVisibility()).isEqualTo(View.VISIBLE);
// If we hide the buttons the visibility should be updated.
ppp.setButtonsVisible(false);
assertThat(ppp.getButtonFrameView().getVisibility()).isEqualTo(View.GONE);
}
@Test
public void ensureButtonsClicksCallDelegate_oldDesign() {
if (PrimaryProviderPreference.shouldUseNewSettingsUi()) {
return;
}
PrimaryProviderPreference ppp = createTestPreference("preference_widget_gear");
// Test that clicking the preference results in the delegate being
// called.
assertThat(mReceivedOpenButtonClicked).isFalse();
ppp.getOnPreferenceClickListener().onPreferenceClick(ppp);
assertThat(mReceivedOpenButtonClicked).isTrue();
// Test that the gear button is present and visible.
assertThat(ppp.getGearView()).isNotNull();
assertThat(ppp.getGearView().getVisibility()).isEqualTo(View.VISIBLE);
// Test that clicking the gear button results in the delegate being
// called.
assertThat(mReceivedChangeButtonClicked).isFalse();
ppp.getGearView().performClick();
assertThat(mReceivedChangeButtonClicked).isTrue();
}
private PrimaryProviderPreference createTestPreferenceWithNewLayout() {
return createTestPreference("preference_credential_manager_with_buttons");
}
private PrimaryProviderPreference createTestPreference(String layoutName) {
int layoutId = ResourcesUtils.getResourcesId(mContext, "layout", layoutName);
PreferenceViewHolder holder =
PreferenceViewHolder.createInstanceForTests(
LayoutInflater.from(mContext).inflate(layoutId, null));
PreferenceViewHolder holderForTest = spy(holder);
View gearView = new View(mContext, null);
int gearId = ResourcesUtils.getResourcesId(mContext, "id", "settings_button");
when(holderForTest.findViewById(gearId)).thenReturn(gearView);
PrimaryProviderPreference ppp = new PrimaryProviderPreference(mContext, mAttributes);
ppp.setDelegate(mDelegate);
ppp.onBindViewHolder(holderForTest);
return ppp;
}
}