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

Commit 2a3e8b30 authored by Matías Hernández's avatar Matías Hernández
Browse files

Update "Dark Theme" Settings screen to account for Modes that can toggle it

Bedtime is no longer a special case.

Fixes: 361592187
Test: atest com.android.settings.display.darkmode
Flag: android.app.modes_ui
Change-Id: Iddc5d8142d6bc0bb1f5c4ead876ee201c8818b12
parent 1ffafd36
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -2929,6 +2929,8 @@
    <string name="dark_ui_summary_off_auto_mode_custom">Will turn on automatically at <xliff:g name="time" example="6 AM">%1$s</xliff:g></string>
    <!-- Display settings screen, summary of Dark UI when off and will turn on automatically at bedtime. [CHAR LIMIT=NONE] -->
    <string name="dark_ui_summary_off_auto_mode_custom_bedtime">Will turn on automatically at bedtime</string>
    <!-- Display settings screen, summary of Dark UI when off and controlled by Modes. [CHAR LIMIT=NONE] -->
    <string name="dark_ui_summary_off_auto_mode_modes">Will turn on when <xliff:g name="modeName" example="Bedtime">%1$s</xliff:g> starts</string>
    <!-- Display settings screen, summary of Dark UI when on and will *never* turn off automatically. [CHAR LIMIT=NONE] -->
    <string name="dark_ui_summary_on_auto_mode_never">Will never turn off automatically</string>
    <!-- Display settings screen, summary of Dark UI when on and will turn off automatically at sunrise. [CHAR LIMIT=NONE] -->
@@ -2937,12 +2939,26 @@
    <string name="dark_ui_summary_on_auto_mode_custom">Will turn off automatically at <xliff:g name="time" example="10 PM">%1$s</xliff:g></string>
    <!-- Display settings screen, summary of Dark UI when on and will turn off automatically after bedtime. [CHAR LIMIT=NONE] -->
    <string name="dark_ui_summary_on_auto_mode_custom_bedtime">Will turn off automatically after bedtime</string>
    <!-- Display settings screen, summary of Dark UI when on and controlled by Modes. [CHAR LIMIT=NONE] -->
    <string name="dark_ui_summary_on_auto_mode_modes">Will turn off when <xliff:g name="modeName" example="Bedtime">%1$s</xliff:g> ends</string>
    <!-- Dark theme screen, description of Dark theme feature. [CHAR LIMIT=NONE] -->
    <string name="dark_ui_text">Dark theme uses a black background to help keep battery alive longer on some screens. Dark theme schedules wait to turn on until your screen is off.</string>
    <!-- Dark UI screen footer summary text shown when the when Dark theme turns on/off automatically according to a user bedtime schedule. [CHAR LIMIT=NONE] -->
    <string name="dark_ui_bedtime_footer_summary">Dark theme is currently following your Bedtime mode schedule</string>
    <!-- Dark UI screen footer action text shown when the when Dark theme turns on/off automatically according to a user bedtime schedule. [CHAR LIMIT=NONE] -->
    <string name="dark_ui_bedtime_footer_action">Bedtime mode settings</string>
    <!-- Dark UI screen footer summary text shown to indicate Modes may turn on/off Dark theme automatically according to their triggers. [CHAR LIMIT=NONE] -->
    <string name="dark_ui_modes_footer_summary">
        {count, plural, offset:2
            =0    {Modes can also activate dark theme}
            =1    {{mode_1} also activates dark theme}
            =2    {{mode_1} and {mode_2} also activate dark theme}
            =3    {{mode_1}, {mode_2}, and {mode_3} also activate dark theme}
            other {{mode_1}, {mode_2}, and # more also activate dark theme}
        }
    </string>
    <!-- Dark UI screen footer action text linking to Modes settings. [CHAR LIMIT=NONE] -->
    <string name="dark_ui_modes_footer_action">Modes settings</string>
    <!-- Even Dimmer setting title. Allows device to reduce brightness even further than standard range. [CHAR LIMIT=NONE] -->
    <string name="even_dimmer_display_title">Even dimmer</string>
    <!-- Even Dimmer setting summary. [CHAR LIMIT=NONE] -->
+1 −1
Original line number Diff line number Diff line
@@ -60,6 +60,6 @@
        android:title="@string/dark_ui_bedtime_footer_summary"
        android:selectable="false"
        settings:searchable="false"
        settings:controller="com.android.settings.display.darkmode.DarkModeCustomBedtimePreferenceController" />
        settings:controller="com.android.settings.display.darkmode.DarkModeCustomModesPreferenceController" />

</PreferenceScreen>
+105 −0
Original line number Diff line number Diff line
/*
 * 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.display.darkmode;

import static android.app.UiModeManager.MODE_ATTENTION_THEME_OVERLAY_NIGHT;
import static android.app.UiModeManager.MODE_NIGHT_AUTO;
import static android.app.UiModeManager.MODE_NIGHT_CUSTOM_TYPE_BEDTIME;
import static android.app.UiModeManager.MODE_NIGHT_CUSTOM_TYPE_SCHEDULE;

import static com.google.common.base.Preconditions.checkNotNull;

import android.app.Flags;
import android.app.UiModeManager;
import android.content.Context;

import com.android.settings.R;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;

import java.time.LocalTime;
import java.util.List;

class AutoDarkTheme {

    static String getStatus(Context context, boolean active) {
        UiModeManager uiModeManager = checkNotNull(context.getSystemService(UiModeManager.class));
        final int mode = uiModeManager.getNightMode();

        if (mode == MODE_NIGHT_AUTO) {
            return context.getString(active
                    ? R.string.dark_ui_summary_on_auto_mode_auto
                    : R.string.dark_ui_summary_off_auto_mode_auto);
        }

        if (Flags.modesUi()) {
            if (active && uiModeManager.getAttentionModeThemeOverlay()
                    == MODE_ATTENTION_THEME_OVERLAY_NIGHT) {
                List<String> modes = getActiveModesThatChangeDarkTheme(context);
                if (!modes.isEmpty()) {
                    return context.getString(R.string.dark_ui_summary_on_auto_mode_modes,
                            modes.get(0));
                }
            } else if (!active) {
                List<String> modes = getModesThatChangeDarkTheme(context);
                if (!modes.isEmpty()) {
                    return context.getString(R.string.dark_ui_summary_off_auto_mode_modes,
                            modes.get(0));
                }
            }
        }

        if (mode == UiModeManager.MODE_NIGHT_CUSTOM) {
            int modeCustomType = uiModeManager.getNightModeCustomType();
            if (!Flags.modesUi() && modeCustomType == MODE_NIGHT_CUSTOM_TYPE_BEDTIME) {
                return context.getString(active
                        ? R.string.dark_ui_summary_on_auto_mode_custom_bedtime
                        : R.string.dark_ui_summary_off_auto_mode_custom_bedtime);
            }
            if (modeCustomType == MODE_NIGHT_CUSTOM_TYPE_SCHEDULE) {
                final LocalTime time = active
                        ? uiModeManager.getCustomNightModeEnd()
                        : uiModeManager.getCustomNightModeStart();
                final String timeStr = new TimeFormatter(context).of(time);
                return context.getString(active
                        ? R.string.dark_ui_summary_on_auto_mode_custom
                        : R.string.dark_ui_summary_off_auto_mode_custom, timeStr);
            }
        }

        return context.getString(active
                ? R.string.dark_ui_summary_on_auto_mode_never
                : R.string.dark_ui_summary_off_auto_mode_never);
    }

    static List<String> getModesThatChangeDarkTheme(Context context) {
        return ZenModesBackend.getInstance(context)
                .getModes().stream()
                .filter(m -> m.getDeviceEffects().shouldUseNightMode())
                .map(ZenMode::getName)
                .toList();
    }

    static List<String> getActiveModesThatChangeDarkTheme(Context context) {
        return ZenModesBackend.getInstance(context)
                .getModes().stream()
                .filter(ZenMode::isActive)
                .filter(m -> m.getDeviceEffects().shouldUseNightMode())
                .map(ZenMode::getName)
                .toList();
    }
}
+1 −37
Original line number Diff line number Diff line
@@ -24,14 +24,11 @@ import android.widget.CompoundButton.OnCheckedChangeListener;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;

import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.widget.MainSwitchPreference;

import java.time.LocalTime;

/**
 * Controller for activate/deactivate night mode button
 */
@@ -40,22 +37,14 @@ public class DarkModeActivationPreferenceController extends BasePreferenceContro

    private final UiModeManager mUiModeManager;
    private final MetricsFeatureProvider mMetricsFeatureProvider;
    private TimeFormatter mFormat;
    private MainSwitchPreference mPreference;

    public DarkModeActivationPreferenceController(Context context, String preferenceKey) {
        super(context, preferenceKey);
        mUiModeManager = context.getSystemService(UiModeManager.class);
        mFormat = new TimeFormatter(context);
        mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider();
    }

    public DarkModeActivationPreferenceController(Context context, String preferenceKey,
            TimeFormatter f) {
        this(context, preferenceKey);
        mFormat = f;
    }

    @Override
    public final void updateState(Preference preference) {
        final boolean active = (mContext.getResources().getConfiguration().uiMode
@@ -67,32 +56,7 @@ public class DarkModeActivationPreferenceController extends BasePreferenceContro
    public CharSequence getSummary() {
        final boolean isActivated = (mContext.getResources().getConfiguration().uiMode
                & Configuration.UI_MODE_NIGHT_YES) != 0;
        final int mode = mUiModeManager.getNightMode();
        if (mode == UiModeManager.MODE_NIGHT_AUTO) {
            return mContext.getString(isActivated
                    ? R.string.dark_ui_summary_on_auto_mode_auto
                    : R.string.dark_ui_summary_off_auto_mode_auto);
        } else if (mode == UiModeManager.MODE_NIGHT_CUSTOM) {
            if (mUiModeManager.getNightModeCustomType()
                    == UiModeManager.MODE_NIGHT_CUSTOM_TYPE_BEDTIME) {
                return mContext.getString(isActivated
                        ? R.string.dark_ui_summary_on_auto_mode_custom_bedtime
                        : R.string.dark_ui_summary_off_auto_mode_custom_bedtime);
            }

            final LocalTime time = isActivated
                    ? mUiModeManager.getCustomNightModeEnd()
                    : mUiModeManager.getCustomNightModeStart();
            final String timeStr = mFormat.of(time);

            return mContext.getString(isActivated
                    ? R.string.dark_ui_summary_on_auto_mode_custom
                    : R.string.dark_ui_summary_off_auto_mode_custom, timeStr);
        } else {
            return mContext.getString(isActivated
                    ? R.string.dark_ui_summary_on_auto_mode_never
                    : R.string.dark_ui_summary_off_auto_mode_never);
        }
        return AutoDarkTheme.getStatus(mContext, isActivated);
    }

    @Override
+112 −0
Original line number Diff line number Diff line
@@ -17,25 +17,37 @@
package com.android.settings.display.darkmode;

import static android.app.UiModeManager.MODE_NIGHT_CUSTOM_TYPE_BEDTIME;
import static android.app.settings.SettingsEnums.DARK_UI_SETTINGS;

import static com.google.common.base.Preconditions.checkNotNull;

import android.app.Flags;
import android.app.UiModeManager;
import android.content.Context;
import android.content.Intent;
import android.icu.text.MessageFormat;

import androidx.annotation.NonNull;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;

import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.notification.modes.ZenModesListFragment;
import com.android.settingslib.widget.FooterPreference;

/** Controller for the night mode bedtime custom mode footer. */
public class DarkModeCustomBedtimePreferenceController extends BasePreferenceController {
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/** Controller for the dark theme Modes / Bedtime custom footer. */
public class DarkModeCustomModesPreferenceController extends BasePreferenceController {
    private final UiModeManager mUiModeManager;
    private FooterPreference mFooterPreference;
    private BedtimeSettings mBedtimeSettings;
    private final BedtimeSettings mBedtimeSettings;

    public DarkModeCustomBedtimePreferenceController(Context context, String key) {
    public DarkModeCustomModesPreferenceController(@NonNull Context context, @NonNull String key) {
        super(context, key);
        mUiModeManager = context.getSystemService(UiModeManager.class);
        mBedtimeSettings = new BedtimeSettings(context);
@@ -43,28 +55,53 @@ public class DarkModeCustomBedtimePreferenceController extends BasePreferenceCon

    @Override
    public int getAvailabilityStatus() {
        return mBedtimeSettings.getBedtimeSettingsIntent() == null
                ? UNSUPPORTED_ON_DEVICE
                : AVAILABLE_UNSEARCHABLE;
        return (Flags.modesUi() || mBedtimeSettings.getBedtimeSettingsIntent() != null)
                ? AVAILABLE_UNSEARCHABLE
                : UNSUPPORTED_ON_DEVICE;
    }

    @Override
    public void displayPreference(PreferenceScreen screen) {
    public void displayPreference(@NonNull PreferenceScreen screen) {
        super.displayPreference(screen);
        mFooterPreference = screen.findPreference(getPreferenceKey());
        mFooterPreference.setLearnMoreAction(
        FooterPreference footerPreference = checkNotNull(screen.findPreference(getPreferenceKey()));
        if (Flags.modesUi()) {
            List<String> modesUsingDarkTheme = AutoDarkTheme.getModesThatChangeDarkTheme(
                    screen.getContext());

            MessageFormat titleFormat = new MessageFormat(
                    mContext.getString(R.string.dark_ui_modes_footer_summary),
                    Locale.getDefault());
            Map<String, Object> args = new HashMap<>();
            args.put("count", modesUsingDarkTheme.size());
            for (int i = 0; i < modesUsingDarkTheme.size() && i < 3; i++) {
                args.put("mode_" + (i + 1), modesUsingDarkTheme.get(i));
            }
            footerPreference.setTitle(titleFormat.format(args));

            footerPreference.setLearnMoreAction(
                    v -> new SubSettingLauncher(v.getContext())
                            .setDestination(ZenModesListFragment.class.getName())
                            .setSourceMetricsCategory(DARK_UI_SETTINGS)
                            .launch());
            footerPreference.setLearnMoreText(
                    mContext.getString(R.string.dark_ui_modes_footer_action));
        } else {
            footerPreference.setTitle(R.string.dark_ui_bedtime_footer_summary);
            footerPreference.setLearnMoreAction(
                    v -> {
                        Intent bedtimeSettingsIntent = mBedtimeSettings.getBedtimeSettingsIntent();
                        if (bedtimeSettingsIntent != null) {
                            v.getContext().startActivity(bedtimeSettingsIntent);
                        }
                    });
        mFooterPreference.setLearnMoreText(
            footerPreference.setLearnMoreText(
                    mContext.getString(R.string.dark_ui_bedtime_footer_action));
        }
    }

    @Override
    public void updateState(Preference preference) {
    public void updateState(@NonNull Preference preference) {
        if (!Flags.modesUi()) {
            if (mUiModeManager.getNightModeCustomType() != MODE_NIGHT_CUSTOM_TYPE_BEDTIME) {
                preference.setVisible(false);
                return;
@@ -72,3 +109,4 @@ public class DarkModeCustomBedtimePreferenceController extends BasePreferenceCon
            preference.setVisible(true);
        }
    }
}
Loading