Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 77191e95 authored by Matías Hernández's avatar Matías Hernández
Browse files

Show confirmation dialogs when enabling or disabling a mode

(Strings are not final, but structure is there).

Bug: 349376785
Test: atest ZenModeSetTriggerLinkPreferenceControllerTest
Flag: android.app.modes_ui
Change-Id: Ia9e604483b90bc30ad1c12e5663a07e251084073
parent 9e2ac046
Loading
Loading
Loading
Loading
+13 −0
Original line number Original line Diff line number Diff line
@@ -9496,6 +9496,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] -->
    <!-- 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>
    <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] -->
    <!-- Content description for help icon button [CHAR LIMIT=20] -->
    <string name="warning_button_text">Warning</string>
    <string name="warning_button_text">Warning</string>
+34 −5
Original line number Original line Diff line number Diff line
@@ -25,6 +25,7 @@ import static android.service.notification.ZenModeConfig.tryParseScheduleConditi
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkNotNull;


import android.annotation.SuppressLint;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.ApplicationInfo;
@@ -231,12 +232,40 @@ class ZenModeSetTriggerLinkPreferenceController extends AbstractZenModePreferenc
            });
            });


    private final Preference.OnPreferenceChangeListener mSwitchChangeListener = (p, newValue) -> {
    private final Preference.OnPreferenceChangeListener mSwitchChangeListener = (p, newValue) -> {
        final boolean newEnabled = (Boolean) newValue;
        confirmChangeEnabled(p, (boolean) newValue);
        return saveMode((zenMode) -> {
        return true;
            if (newEnabled != zenMode.getRule().isEnabled()) {
    };
                zenMode.getRule().setEnabled(newEnabled);

    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;
            return zenMode;
        });
        });
    };
    }

    private void undoToggleSwitch(Preference preference, boolean wasSwitchedTo) {
        PrimarySwitchPreference switchPreference = (PrimarySwitchPreference) preference;
        switchPreference.setChecked(!wasSwitchedTo);
    }
}
}
+77 −5
Original line number Original line Diff line number Diff line
@@ -32,9 +32,12 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf;


import android.app.AlertDialog;
import android.app.AutomaticZenRule;
import android.app.AutomaticZenRule;
import android.app.Flags;
import android.app.Flags;
import android.content.Context;
import android.content.Context;
@@ -42,6 +45,7 @@ import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.net.Uri;
import android.os.Looper;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.platform.test.flag.junit.SetFlagsRule;
import android.service.notification.SystemZenRules;
import android.service.notification.SystemZenRules;
@@ -74,6 +78,7 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoAnnotations;
import org.mockito.stubbing.Answer;
import org.mockito.stubbing.Answer;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.shadows.ShadowAlertDialog;


import java.util.Calendar;
import java.util.Calendar;


@@ -161,19 +166,86 @@ public class ZenModeSetTriggerLinkPreferenceControllerTest {
    }
    }


    @Test
    @Test
    public void onPreferenceChange_updatesMode() {
    public void onPreferenceChange_toggleOn_enablesModeAfterConfirmation() {
        // Start with a disabled mode
        ZenMode zenMode = new TestModeBuilder().setEnabled(false).build();
        ZenMode zenMode = new TestModeBuilder().setEnabled(false).build();

        // start with disabled rule
        mController.updateZenMode(mPrefCategory, zenMode);
        mController.updateZenMode(mPrefCategory, zenMode);


        // then flip the switch
        // Flip the switch
        mConfigPreference.callChangeListener(true);
        mConfigPreference.callChangeListener(true);
        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 enabled
        // Verify the backend got asked to update the mode to be enabled
        ArgumentCaptor<ZenMode> captor = ArgumentCaptor.forClass(ZenMode.class);
        ArgumentCaptor<ZenMode> captor = ArgumentCaptor.forClass(ZenMode.class);
        verify(mBackend).updateMode(captor.capture());
        verify(mBackend).updateMode(captor.capture());
        assertThat(captor.getValue().getRule().isEnabled()).isTrue();
        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
    @Test