Merge "Show confirmation dialogs when enabling or disabling a mode" into main
This commit is contained in:
committed by
Android (Google) Code Review
commit
5eb776adef
@@ -9498,6 +9498,19 @@
|
||||
<!-- Priority Modes: Generic trigger summary for modes where the owner app did not provide neither a triggerDescription nor a configurationActivity to call [CHAR LIMIT=60] -->
|
||||
<string name="zen_mode_trigger_summary_managed_by_app">Managed by <xliff:g id="app_name" example="The Awesome App">%1$s</xliff:g></string>
|
||||
|
||||
<!-- Priority Modes: Title of the confirmation dialog for disabling an enabled mode [CHAR LIMIT=30] -->
|
||||
<string name="zen_mode_confirm_disable_title">Disable Mode</string>
|
||||
<!-- Priority Modes: Message body of the confirmation dialog for disabling an enabled mode [CHAR LIMIT=NONE] -->
|
||||
<string name="zen_mode_confirm_disable_message">If you disable this feature, the mode will no longer work as intended and its settings will be hidden.</string>
|
||||
<!-- Priority Modes: Button to disable a mode [CHAR LIMIT=20] -->
|
||||
<string name="zen_mode_action_disable">Disable</string>
|
||||
<!-- Priority Modes: Title of the confirmation dialog for enabling a disabled mode [CHAR LIMIT=30] -->
|
||||
<string name="zen_mode_confirm_enable_title">Enable Mode</string>
|
||||
<!-- Priority Modes: Message body of the confirmation dialog for enabling a disabled mode [CHAR LIMIT=NONE] -->
|
||||
<string name="zen_mode_confirm_enable_message">If you enable this feature, the mode will activate automatically according to its schedule.</string>
|
||||
<!-- Priority Modes: Button to disable a mode [CHAR LIMIT=20] -->
|
||||
<string name="zen_mode_action_enable">Enable</string>
|
||||
|
||||
<!-- Content description for help icon button [CHAR LIMIT=20] -->
|
||||
<string name="warning_button_text">Warning</string>
|
||||
|
||||
|
@@ -25,6 +25,7 @@ import static android.service.notification.ZenModeConfig.tryParseScheduleConditi
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
@@ -231,12 +232,40 @@ class ZenModeSetTriggerLinkPreferenceController extends AbstractZenModePreferenc
|
||||
});
|
||||
|
||||
private final Preference.OnPreferenceChangeListener mSwitchChangeListener = (p, newValue) -> {
|
||||
final boolean newEnabled = (Boolean) newValue;
|
||||
return saveMode((zenMode) -> {
|
||||
if (newEnabled != zenMode.getRule().isEnabled()) {
|
||||
zenMode.getRule().setEnabled(newEnabled);
|
||||
confirmChangeEnabled(p, (boolean) newValue);
|
||||
return true;
|
||||
};
|
||||
|
||||
private void confirmChangeEnabled(Preference preference, boolean enabled) {
|
||||
@StringRes int title = enabled ? R.string.zen_mode_confirm_enable_title
|
||||
: R.string.zen_mode_confirm_disable_title;
|
||||
@StringRes int message = enabled ? R.string.zen_mode_confirm_enable_message
|
||||
: R.string.zen_mode_confirm_disable_message;
|
||||
@StringRes int confirmButton = enabled ? R.string.zen_mode_action_enable
|
||||
: R.string.zen_mode_action_disable;
|
||||
|
||||
new AlertDialog.Builder(mContext)
|
||||
.setTitle(title)
|
||||
.setMessage(message)
|
||||
.setPositiveButton(confirmButton,
|
||||
(dialog, which) -> setModeEnabled(enabled))
|
||||
.setNegativeButton(R.string.cancel,
|
||||
(dialog, which) -> undoToggleSwitch(preference, enabled))
|
||||
.setOnCancelListener(dialog -> undoToggleSwitch(preference, enabled))
|
||||
.show();
|
||||
}
|
||||
|
||||
private void setModeEnabled(boolean enabled) {
|
||||
saveMode((zenMode) -> {
|
||||
if (enabled != zenMode.getRule().isEnabled()) {
|
||||
zenMode.getRule().setEnabled(enabled);
|
||||
}
|
||||
return zenMode;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
private void undoToggleSwitch(Preference preference, boolean wasSwitchedTo) {
|
||||
PrimarySwitchPreference switchPreference = (PrimarySwitchPreference) preference;
|
||||
switchPreference.setChecked(!wasSwitchedTo);
|
||||
}
|
||||
}
|
||||
|
@@ -32,9 +32,12 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.robolectric.Shadows.shadowOf;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.AutomaticZenRule;
|
||||
import android.app.Flags;
|
||||
import android.content.Context;
|
||||
@@ -42,6 +45,7 @@ import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Looper;
|
||||
import android.platform.test.annotations.EnableFlags;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
import android.service.notification.SystemZenRules;
|
||||
@@ -74,6 +78,7 @@ import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.shadows.ShadowAlertDialog;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
@@ -161,19 +166,86 @@ public class ZenModeSetTriggerLinkPreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPreferenceChange_updatesMode() {
|
||||
public void onPreferenceChange_toggleOn_enablesModeAfterConfirmation() {
|
||||
// Start with a disabled mode
|
||||
ZenMode zenMode = new TestModeBuilder().setEnabled(false).build();
|
||||
|
||||
// start with disabled rule
|
||||
mController.updateZenMode(mPrefCategory, zenMode);
|
||||
|
||||
// then flip the switch
|
||||
// Flip the switch
|
||||
mConfigPreference.callChangeListener(true);
|
||||
verify(mBackend, never()).updateMode(any());
|
||||
|
||||
// verify the backend got asked to update the mode to be enabled
|
||||
// Oh wait, I forgot to confirm! Let's do that
|
||||
assertThat(ShadowAlertDialog.getLatestAlertDialog()).isNotNull();
|
||||
assertThat(ShadowAlertDialog.getLatestAlertDialog().isShowing()).isTrue();
|
||||
ShadowAlertDialog.getLatestAlertDialog()
|
||||
.getButton(AlertDialog.BUTTON_POSITIVE).performClick();
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
// Verify the backend got asked to update the mode to be enabled
|
||||
ArgumentCaptor<ZenMode> captor = ArgumentCaptor.forClass(ZenMode.class);
|
||||
verify(mBackend).updateMode(captor.capture());
|
||||
assertThat(captor.getValue().getRule().isEnabled()).isTrue();
|
||||
assertThat(ShadowAlertDialog.getLatestAlertDialog().isShowing()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPreferenceChange_toggleOff_disablesModeAfterConfirmation() {
|
||||
// Start with an enabled mode
|
||||
ZenMode zenMode = new TestModeBuilder().setEnabled(true).build();
|
||||
mController.updateZenMode(mPrefCategory, zenMode);
|
||||
|
||||
// Flip the switch
|
||||
mConfigPreference.callChangeListener(false);
|
||||
verify(mBackend, never()).updateMode(any());
|
||||
|
||||
// Oh wait, I forgot to confirm! Let's do that
|
||||
assertThat(ShadowAlertDialog.getLatestAlertDialog()).isNotNull();
|
||||
assertThat(ShadowAlertDialog.getLatestAlertDialog().isShowing()).isTrue();
|
||||
ShadowAlertDialog.getLatestAlertDialog()
|
||||
.getButton(AlertDialog.BUTTON_POSITIVE).performClick();
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
// Verify the backend got asked to update the mode to be disabled
|
||||
ArgumentCaptor<ZenMode> captor = ArgumentCaptor.forClass(ZenMode.class);
|
||||
verify(mBackend).updateMode(captor.capture());
|
||||
assertThat(captor.getValue().getRule().isEnabled()).isFalse();
|
||||
assertThat(ShadowAlertDialog.getLatestAlertDialog().isShowing()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPreferenceChange_ifPressCancelButton_doesNotUpdateMode() {
|
||||
// Start with a disabled mode
|
||||
ZenMode zenMode = new TestModeBuilder().setEnabled(false).build();
|
||||
mController.updateZenMode(mPrefCategory, zenMode);
|
||||
|
||||
// Flip the switch, then have second thoughts about it
|
||||
mConfigPreference.callChangeListener(true);
|
||||
ShadowAlertDialog.getLatestAlertDialog()
|
||||
.getButton(AlertDialog.BUTTON_NEGATIVE).performClick();
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
// Verify nothing changed, and the switch shows the correct (pre-change) value.
|
||||
verify(mBackend, never()).updateMode(any());
|
||||
assertThat(mConfigPreference.isChecked()).isFalse();
|
||||
assertThat(ShadowAlertDialog.getLatestAlertDialog().isShowing()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onPreferenceChange_ifExitingDialog_doesNotUpdateMode() {
|
||||
// Start with a disabled mode
|
||||
ZenMode zenMode = new TestModeBuilder().setEnabled(false).build();
|
||||
mController.updateZenMode(mPrefCategory, zenMode);
|
||||
|
||||
// Flip the switch, but close the dialog without selecting either button.
|
||||
mConfigPreference.callChangeListener(true);
|
||||
ShadowAlertDialog.getLatestAlertDialog().dismiss();
|
||||
shadowOf(Looper.getMainLooper()).idle();
|
||||
|
||||
// Verify nothing changed, and the switch shows the correct (pre-change) value.
|
||||
verify(mBackend, never()).updateMode(any());
|
||||
assertThat(mConfigPreference.isChecked()).isFalse();
|
||||
assertThat(ShadowAlertDialog.getLatestAlertDialog().isShowing()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
Reference in New Issue
Block a user