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

Commit 95864092 authored by Xiaowen Lei's avatar Xiaowen Lei
Browse files

Update logic for shifting points outside of drawable bounds.

Also removed `format="dimension"` for the
NotificationProgressDrawableSegments.minWidth attribute, since it was
already included in a pre-existing attribute.

Flag: android.app.api_rich_ongoing
Bug: 372908709
Fix: 383566179
Test: NotificationProgressBarTest
Test: Post ProgressStyle notifs via test app
Change-Id: Ie4cf2992837f4169939281f5b4e139d7e61a4b96
parent af949563
Loading
Loading
Loading
Loading
+11 −8
Original line number Diff line number Diff line
@@ -836,11 +836,16 @@ public final class NotificationProgressBar extends ProgressBar implements
            } else if (part instanceof Point point) {
                final float pointWidth = 2 * pointRadius;
                float start = x - pointRadius;
                if (start < 0) start = 0;
                float end = start + pointWidth;
                if (end > totalWidth) {
                float end = x + pointRadius;
                // Only shift the points right at the start/end.
                // For the points close to the start/end, the segment minimum width requirement
                // would take care of shifting them to be within the bounds.
                if (x == 0) {
                    start = 0;
                    end = pointWidth;
                } else if (x == totalWidth) {
                    start = totalWidth - pointWidth;
                    end = totalWidth;
                    if (totalWidth > pointWidth) start = totalWidth - pointWidth;
                }

                drawableParts.add(new DrawablePoint(start, end, point.mColor));
@@ -853,7 +858,7 @@ public final class NotificationProgressBar extends ProgressBar implements
    private static float getSegStartOffset(Part prevPart, float pointRadius, float segPointGap,
            float startX) {
        if (!(prevPart instanceof Point)) return 0F;
        final float pointOffset = (startX < pointRadius) ? (pointRadius - startX) : 0;
        final float pointOffset = (startX == 0) ? pointRadius : 0;
        return pointOffset + pointRadius + segPointGap;
    }

@@ -869,9 +874,7 @@ public final class NotificationProgressBar extends ProgressBar implements
            return segSegGap;
        }

        final float pointWidth = 2 * pointRadius;
        final float pointOffset = (endX + pointRadius > totalWidth && totalWidth > pointWidth)
                ? (endX + pointRadius - totalWidth) : 0;
        final float pointOffset = (endX == totalWidth) ? pointRadius : 0;
        return segPointGap + pointRadius + pointOffset;
    }

+1 −1
Original line number Diff line number Diff line
@@ -7590,7 +7590,7 @@
        <!-- Minimum required drawing width. The drawing width refers to the width after
         the original segments have been adjusted for the neighboring Points and gaps. This is
         enforced by stretching the segments that are too short. -->
        <attr name="minWidth" format="dimension" />
        <attr name="minWidth" />
        <!-- Height of the solid segments. -->
        <attr name="height" />
        <!-- Height of the faded segments. -->
+170 −9
Original line number Diff line number Diff line
@@ -336,10 +336,14 @@ public class NotificationProgressBarTest {
                progress, progressMax);

        List<Part> expectedParts = new ArrayList<>(
                List.of(new Segment(0.15f, Color.BLUE), new Point(Color.RED),
                        new Segment(0.10f, Color.BLUE), new Point(Color.BLUE),
                        new Segment(0.35f, Color.BLUE), new Point(Color.BLUE),
                        new Segment(0.15f, Color.BLUE), new Point(Color.YELLOW),
                List.of(new Segment(0.15f, Color.BLUE),
                        new Point(Color.RED),
                        new Segment(0.10f, Color.BLUE),
                        new Point(Color.BLUE),
                        new Segment(0.35f, Color.BLUE),
                        new Point(Color.BLUE),
                        new Segment(0.15f, Color.BLUE),
                        new Point(Color.YELLOW),
                        new Segment(0.25f, Color.BLUE)));

        assertThat(parts).isEqualTo(expectedParts);
@@ -408,11 +412,16 @@ public class NotificationProgressBarTest {
                progress, progressMax);

        List<Part> expectedParts = new ArrayList<>(
                List.of(new Segment(0.15f, Color.RED), new Point(Color.RED),
                        new Segment(0.10f, Color.RED), new Point(Color.BLUE),
                        new Segment(0.25f, Color.RED), new Segment(0.10f, Color.GREEN),
                        new Point(Color.BLUE), new Segment(0.15f, Color.GREEN),
                        new Point(Color.YELLOW), new Segment(0.25f, Color.GREEN)));
                List.of(new Segment(0.15f, Color.RED),
                        new Point(Color.RED),
                        new Segment(0.10f, Color.RED),
                        new Point(Color.BLUE),
                        new Segment(0.25f, Color.RED),
                        new Segment(0.10f, Color.GREEN),
                        new Point(Color.BLUE),
                        new Segment(0.15f, Color.GREEN),
                        new Point(Color.YELLOW),
                        new Segment(0.25f, Color.GREEN)));

        assertThat(parts).isEqualTo(expectedParts);

@@ -463,6 +472,158 @@ public class NotificationProgressBarTest {
        assertThat(p.first).isEqualTo(expectedDrawableParts);
    }

    @Test
    public void processAndConvertToParts_multipleSegmentsWithPointsAtStartAndEnd() {
        List<ProgressStyle.Segment> segments = new ArrayList<>();
        segments.add(new ProgressStyle.Segment(50).setColor(Color.RED));
        segments.add(new ProgressStyle.Segment(50).setColor(Color.GREEN));
        List<ProgressStyle.Point> points = new ArrayList<>();
        points.add(new ProgressStyle.Point(0).setColor(Color.RED));
        points.add(new ProgressStyle.Point(25).setColor(Color.BLUE));
        points.add(new ProgressStyle.Point(60).setColor(Color.BLUE));
        points.add(new ProgressStyle.Point(100).setColor(Color.YELLOW));
        int progress = 60;
        int progressMax = 100;

        List<Part> parts = NotificationProgressBar.processAndConvertToViewParts(segments, points,
                progress, progressMax);

        List<Part> expectedParts = new ArrayList<>(
                List.of(new Point(Color.RED),
                        new Segment(0.25f, Color.RED),
                        new Point(Color.BLUE),
                        new Segment(0.25f, Color.RED),
                        new Segment(0.10f, Color.GREEN),
                        new Point(Color.BLUE),
                        new Segment(0.4f, Color.GREEN),
                        new Point(Color.YELLOW)));

        assertThat(parts).isEqualTo(expectedParts);

        float drawableWidth = 300;
        float segSegGap = 4;
        float segPointGap = 4;
        float pointRadius = 6;
        boolean hasTrackerIcon = true;
        List<DrawablePart> drawableParts = NotificationProgressBar.processAndConvertToDrawableParts(
                parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);

        List<DrawablePart> expectedDrawableParts = new ArrayList<>(
                List.of(new DrawablePoint(0, 12, Color.RED),
                        new DrawableSegment(16, 65, Color.RED),
                        new DrawablePoint(69, 81, Color.BLUE),
                        new DrawableSegment(85, 146, Color.RED),
                        new DrawableSegment(150, 170, Color.GREEN),
                        new DrawablePoint(174, 186, Color.BLUE),
                        new DrawableSegment(190, 284, Color.GREEN),
                        new DrawablePoint(288, 300, Color.YELLOW)));

        assertThat(drawableParts).isEqualTo(expectedDrawableParts);

        float segmentMinWidth = 16;
        boolean isStyledByProgress = true;

        Pair<List<DrawablePart>, Float> p = NotificationProgressBar.maybeStretchAndRescaleSegments(
                parts, drawableParts, segmentMinWidth, pointRadius, (float) progress / progressMax,
                300, isStyledByProgress, hasTrackerIcon ? 0 : segSegGap);

        // Colors with 40% opacity
        int fadedGreen = 0x6600FF00;
        int fadedYellow = 0x66FFFF00;
        expectedDrawableParts = new ArrayList<>(
                List.of(new DrawablePoint(0, 12, Color.RED),
                        new DrawableSegment(16, 65, Color.RED),
                        new DrawablePoint(69, 81, Color.BLUE),
                        new DrawableSegment(85, 146, Color.RED),
                        new DrawableSegment(150, 170, Color.GREEN),
                        new DrawablePoint(174, 186, Color.BLUE),
                        new DrawableSegment(190, 284, fadedGreen, true),
                        new DrawablePoint(288, 300, fadedYellow)));

        assertThat(p.second).isEqualTo(180);
        assertThat(p.first).isEqualTo(expectedDrawableParts);
    }

    // The points are so close to start/end that they would go out of bounds without the minimum
    // segment width requirement.
    @Test
    public void processAndConvertToParts_multipleSegmentsWithPointsNearStartAndEnd() {
        List<ProgressStyle.Segment> segments = new ArrayList<>();
        segments.add(new ProgressStyle.Segment(50).setColor(Color.RED));
        segments.add(new ProgressStyle.Segment(50).setColor(Color.GREEN));
        List<ProgressStyle.Point> points = new ArrayList<>();
        points.add(new ProgressStyle.Point(1).setColor(Color.RED));
        points.add(new ProgressStyle.Point(25).setColor(Color.BLUE));
        points.add(new ProgressStyle.Point(60).setColor(Color.BLUE));
        points.add(new ProgressStyle.Point(99).setColor(Color.YELLOW));
        int progress = 60;
        int progressMax = 100;

        List<Part> parts = NotificationProgressBar.processAndConvertToViewParts(segments, points,
                progress, progressMax);

        List<Part> expectedParts = new ArrayList<>(
                List.of(new Segment(0.01f, Color.RED),
                        new Point(Color.RED),
                        new Segment(0.24f, Color.RED),
                        new Point(Color.BLUE),
                        new Segment(0.25f, Color.RED),
                        new Segment(0.10f, Color.GREEN),
                        new Point(Color.BLUE),
                        new Segment(0.39f, Color.GREEN),
                        new Point(Color.YELLOW),
                        new Segment(0.01f, Color.GREEN)));

        assertThat(parts).isEqualTo(expectedParts);

        float drawableWidth = 300;
        float segSegGap = 4;
        float segPointGap = 4;
        float pointRadius = 6;
        boolean hasTrackerIcon = true;
        List<DrawablePart> drawableParts = NotificationProgressBar.processAndConvertToDrawableParts(
                parts, drawableWidth, segSegGap, segPointGap, pointRadius, hasTrackerIcon);

        List<DrawablePart> expectedDrawableParts = new ArrayList<>(
                List.of(new DrawableSegment(0, -7, Color.RED),
                        new DrawablePoint(-3, 9, Color.RED),
                        new DrawableSegment(13, 65, Color.RED),
                        new DrawablePoint(69, 81, Color.BLUE),
                        new DrawableSegment(85, 146, Color.RED),
                        new DrawableSegment(150, 170, Color.GREEN),
                        new DrawablePoint(174, 186, Color.BLUE),
                        new DrawableSegment(190, 287, Color.GREEN),
                        new DrawablePoint(291, 303, Color.YELLOW),
                        new DrawableSegment(307, 300, Color.GREEN)));

        assertThat(drawableParts).isEqualTo(expectedDrawableParts);

        float segmentMinWidth = 16;
        boolean isStyledByProgress = true;

        Pair<List<DrawablePart>, Float> p = NotificationProgressBar.maybeStretchAndRescaleSegments(
                parts, drawableParts, segmentMinWidth, pointRadius, (float) progress / progressMax,
                300, isStyledByProgress, hasTrackerIcon ? 0 : segSegGap);

        // Colors with 40% opacity
        int fadedGreen = 0x6600FF00;
        int fadedYellow = 0x66FFFF00;
        expectedDrawableParts = new ArrayList<>(
                List.of(new DrawableSegment(0, 16, Color.RED),
                        new DrawablePoint(20, 32, Color.RED),
                        new DrawableSegment(36, 78.02409F, Color.RED),
                        new DrawablePoint(82.02409F, 94.02409F, Color.BLUE),
                        new DrawableSegment(98.02409F, 146.55421F, Color.RED),
                        new DrawableSegment(150.55421F, 169.44579F, Color.GREEN),
                        new DrawablePoint(173.44579F, 185.44579F, Color.BLUE),
                        new DrawableSegment(189.44579F, 264, fadedGreen, true),
                        new DrawablePoint(268, 280, fadedYellow),
                        new DrawableSegment(284, 300, fadedGreen, true)));

        assertThat(p.second).isEqualTo(179.44579F);
        assertThat(p.first).isEqualTo(expectedDrawableParts);
    }

    @Test
    public void processAndConvertToParts_multipleSegmentsWithPoints_notStyledByProgress() {
        List<ProgressStyle.Segment> segments = new ArrayList<>();