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

Commit 4bf9336d authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Implementing available part of UX spec for DW toast" into ub-launcher3-master

parents 866a8f98 759db43f
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2019 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.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
    <solid android:color="#E61A73E8" />
    <corners android:radius="@dimen/task_corner_radius" />
</shape>
 No newline at end of file
+4 −2
Original line number Diff line number Diff line
@@ -38,9 +38,11 @@
    <com.android.quickstep.views.DigitalWellBeingToast
        android:id="@+id/digital_well_being_toast"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_height="48dp"
        android:importantForAccessibility="noHideDescendants"
        android:background="#800000FF"
        android:fontFamily="sans-serif"
        android:textSize="14sp"
        android:background="@drawable/bg_wellbeing_toast"
        android:layout_gravity="bottom"
        android:gravity="center"
        android:textColor="@android:color/white"
+21 −1
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@
* limitations under the License.
*/
-->
<resources>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">

    <!-- Application name -->
    <string name="derived_app_name" translatable="false">Quickstep</string>
@@ -46,4 +46,24 @@

    <!-- Accessibility title for the list of recent apps [CHAR_LIMIT=none] -->
    <string name="accessibility_recent_apps">Recent apps</string>

    <!-- Accessibility title for an app card in Recents for apps that have time limit set
     [CHAR_LIMIT=none] -->
    <string name="task_contents_description_with_remaining_time"><xliff:g id="task_description" example="GMail">%1$s</xliff:g>, <xliff:g id="remaining_time" example="7 minutes left today">%2$s</xliff:g></string>

    <!-- Text to show total app usage per day if it is less than 1 minute ("&lt;" is the
     escaped form of '<'). [CHAR LIMIT=10] -->
    <string name="shorter_duration_less_than_one_minute">&lt; 1 minute</string>

    <!-- Annotation shown on an app card in Recents, telling that the app was switched to a
    grayscale because it ran over its time limit [CHAR LIMIT=25] -->
    <string name="app_in_grayscale">App in grayscale</string>

    <!-- Annotation shown on an app card in Recents, telling that the app has a usage limit set by
    the user, and a given time is left for it today [CHAR LIMIT=20] -->
    <string name="time_left_for_app"><xliff:g id="time" example="7 minutes">%1$s</xliff:g> left today</string>

    <!-- Annotation shown on an app card in Recents, telling that the app is in a group that has a
    usage limit set by the user, and a given time is left for the group today [CHAR LIMIT=20] -->
    <string name="time_left_for_group"><xliff:g id="time" example="1 hour">%1$s</xliff:g> left for group</string>
</resources>
 No newline at end of file
+80 −8
Original line number Diff line number Diff line
@@ -20,17 +20,27 @@ import android.app.ActivityOptions;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.icu.text.MeasureFormat;
import android.icu.text.MeasureFormat.FormatWidth;
import android.icu.util.Measure;
import android.icu.util.MeasureUnit;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

import androidx.annotation.StringRes;

import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.systemui.shared.recents.model.Task;

import java.time.Duration;
import java.util.Locale;

public final class DigitalWellBeingToast extends TextView {

    public interface InitializeCallback {
@@ -65,16 +75,78 @@ public final class DigitalWellBeingToast extends TextView {

                callback.call(
                        appUsageLimitTimeMs >= 0 && appRemainingTimeMs < 0 ? 0 : 1,
                        getContentDescriptionForTask(task, appRemainingTimeMs, isGroupLimit));
                        getContentDescriptionForTask(
                                task, appUsageLimitTimeMs, appRemainingTimeMs, isGroupLimit));
            });
        });
    }

    public static String getText(long remainingTime, boolean isGroupLimit) {
        return remainingTime < 0 ?
                "Grayed" :
                "Remaining time:" + (remainingTime + 59999) / 60000
                        + " min " + (isGroupLimit ? "for group" : "for the app");
    private String getReadableDuration(
            Duration duration,
            FormatWidth formatWidthHourAndMinute,
            @StringRes int durationLessThanOneMinuteStringId,
            boolean forceFormatWidth) {
        int hours = Math.toIntExact(duration.toHours());
        int minutes = Math.toIntExact(duration.minusHours(hours).toMinutes());

        // Apply formatWidthHourAndMinute if both the hour part and the minute part are non-zero.
        if (hours > 0 && minutes > 0) {
            return MeasureFormat.getInstance(Locale.getDefault(), formatWidthHourAndMinute)
                    .formatMeasures(
                            new Measure(hours, MeasureUnit.HOUR),
                            new Measure(minutes, MeasureUnit.MINUTE));
        }

        // Apply formatWidthHourOrMinute if only the hour part is non-zero (unless forced).
        if (hours > 0) {
            return MeasureFormat.getInstance(
                    Locale.getDefault(),
                    forceFormatWidth ? formatWidthHourAndMinute : FormatWidth.WIDE)
                    .formatMeasures(new Measure(hours, MeasureUnit.HOUR));
        }

        // Apply formatWidthHourOrMinute if only the minute part is non-zero (unless forced).
        if (minutes > 0) {
            return MeasureFormat.getInstance(
                    Locale.getDefault()
                    , forceFormatWidth ? formatWidthHourAndMinute : FormatWidth.WIDE)
                    .formatMeasures(new Measure(minutes, MeasureUnit.MINUTE));
        }

        // Use a specific string for usage less than one minute but non-zero.
        if (duration.compareTo(Duration.ZERO) > 0) {
            return getResources().getString(durationLessThanOneMinuteStringId);
        }

        // Otherwise, return 0-minute string.
        return MeasureFormat.getInstance(
                Locale.getDefault(), forceFormatWidth ? formatWidthHourAndMinute : FormatWidth.WIDE)
                .formatMeasures(new Measure(0, MeasureUnit.MINUTE));
    }

    private String getReadableDuration(
            Duration duration,
            FormatWidth formatWidthHourAndMinute,
            @StringRes int durationLessThanOneMinuteStringId) {
        return getReadableDuration(
                duration,
                formatWidthHourAndMinute,
                durationLessThanOneMinuteStringId,
                /* forceFormatWidth= */ false);
    }

    private String getShorterReadableDuration(Duration duration) {
        return getReadableDuration(
                duration, FormatWidth.NARROW, R.string.shorter_duration_less_than_one_minute);
    }

    private String getText(long remainingTime, boolean isGroupLimit) {
        final Resources resources = getResources();
        return (remainingTime < 0) ?
                resources.getString(R.string.app_in_grayscale) :
                resources.getString(
                        isGroupLimit ? R.string.time_left_for_group : R.string.time_left_for_app,
                        getShorterReadableDuration(Duration.ofMillis(remainingTime)));
    }

    public void openAppUsageSettings() {
@@ -97,8 +169,8 @@ public final class DigitalWellBeingToast extends TextView {
    }

    private String getContentDescriptionForTask(
            Task task, long appRemainingTimeMs, boolean isGroupLimit) {
        return appRemainingTimeMs > 0 ?
            Task task, long appUsageLimitTimeMs, long appRemainingTimeMs, boolean isGroupLimit) {
        return appUsageLimitTimeMs > 0 ?
                getResources().getString(
                        R.string.task_contents_description_with_remaining_time,
                        task.titleDescription,
+0 −2
Original line number Diff line number Diff line
@@ -336,6 +336,4 @@

    <!-- Failed action error message: e.g. Failed: Pause -->
    <string name="remote_action_failed">Failed: <xliff:g id="what" example="Pause">%1$s</xliff:g></string>

    <string name="task_contents_description_with_remaining_time" translatable="false"><xliff:g id="task_description" example="GMail">%1$s</xliff:g>, <xliff:g id="remaining_time" example="7 minutes">%2$s</xliff:g></string>
</resources>