Skip to content

CCCT-2515 Add Reusable Semi-Circle Progress Bar#3779

Open
OrangeAndGreen wants to merge 2 commits into
masterfrom
CCCT-2515-semicircle-progress-bar
Open

CCCT-2515 Add Reusable Semi-Circle Progress Bar#3779
OrangeAndGreen wants to merge 2 commits into
masterfrom
CCCT-2515-semicircle-progress-bar

Conversation

@OrangeAndGreen

@OrangeAndGreen OrangeAndGreen commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

CCCT-2515

Technical Summary

Adds a reusable 180° semi-circle progress indicator. It is split into two pieces:

  • SemiCircleArcView — a focused custom View that draws only the track + progress arcs (exposes a progress fraction, arc colors, and stroke width).
  • SemiCircleProgressBar — a ConstraintLayout composite that overlays two centered TextViews (a "X of Y" value line and a description line) on the arc, so text centering/rendering is handled by the layout rather than canvas math.

The four colors (progressColor, trackColor, valueTextColor, descriptionTextColor) are mapped in one place via the Widget.CommCare.SemiCircleProgressBar style; current, max, and descriptionText are the per-instance content. The value line uses a localized format string (semi_circle_progress_value_format) translated across all supported languages.

Note that the active value is clipped between 0 and the max, i.e.:

  • Inputs -1 and 40 result in "0 of 40" and the bar showing 0% filled
  • Inputs 50 and 40 result in "40 of 40" and the bar showing 100% filled

Also, the max value is floored at 0 (to handle negative inputs) and will always show an empty progress bar when drawing with max=0. Since the current value is clipped between (0, max), the text will always read "0 of 0" when max=0.

This PR adds the component only — it is not yet wired into any production screen.

Demo of the new component (temporarily added to Learning Progress and hard-coded with some sample data):
Screenshot_20260629_120847

Safety Assurance

Safety story

What gives me confidence:

  • I ran the app and visually confirmed the component renders correctly (arc fill, centered text) on a temporary demo placement on the Learning Progress page — see the screenshot above.
  • The diff is purely additive: new view classes, a new layout, and new resource entries (style, attrs, dimens, string + translations). No existing code paths or layouts are modified.
  • Compiles cleanly and passes ktlint; resources link successfully.

@OrangeAndGreen OrangeAndGreen self-assigned this Jun 29, 2026
@OrangeAndGreen

Copy link
Copy Markdown
Contributor Author

Suggested Review Order

  • app/src/org/commcare/views/connect/SemiCircleArcView.kt — core arc drawing (measurement + the two drawArc calls); start here
  • app/src/org/commcare/views/connect/SemiCircleProgressBar.kt — composite that wraps the arc and routes content/colors to its children
  • app/res/layout/view_semi_circle_progress_bar.xml — layout the composite inflates (arc + centered text block)
  • app/res/values/attrs.xml — the SemiCircleProgressBar styleable attributes
  • app/res/values/styles.xmlWidget.CommCare.SemiCircleProgressBar style mapping the four colors
  • app/res/values/dimens.xml — default stroke width and text sizes
  • app/res/values/strings.xml — the semi_circle_progress_value_format value string
  • app/res/values-*/strings.xml — translations of the value string (skim last)

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

A new SemiCircleProgressBar compound view is introduced. It consists of SemiCircleArcView, a custom View that renders a 180° semicircular track arc with a proportional progress overlay, and a ConstraintLayout-based layout (view_semi_circle_progress_bar.xml) with two TextViews overlaid on the arc. SemiCircleProgressBar inflates this layout, reads styleable attributes for colors, sizes, and numeric values, enforces clamping on current and max, and updates text, arc progress, and contentDescription. Supporting resources include new attrs with format qualifiers, dimension values, a default style, and a semi_circle_progress_value_format string in 10 locales.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • conroy-ricketts
  • shubham1g5
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: a reusable semi-circle progress bar.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description covers the ticket, technical summary, and safety story, and is mostly complete despite missing product description, test coverage, and labels sections.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch CCCT-2515-semicircle-progress-bar

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/src/org/commcare/views/connect/SemiCircleArcView.kt`:
- Around line 78-82: The width measurement in SemiCircleArcView’s sizing logic
treats MeasureSpec.AT_MOST the same as EXACTLY, which makes wrap_content use the
parent’s full available width instead of the view’s intrinsic size. Update the
measurement branch in the width/height calculation to treat AT_MOST as a cap
over the default dimension rather than directly returning MeasureSpec.getSize,
and keep the intrinsic default from resources as the preferred size in
SemiCircleArcView.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 06dceec0-5aa5-46da-9b54-677f045e5091

📥 Commits

Reviewing files that changed from the base of the PR and between 4b25464 and 0144430.

📒 Files selected for processing (16)
  • app/res/layout/view_semi_circle_progress_bar.xml
  • app/res/values-es/strings.xml
  • app/res/values-fr/strings.xml
  • app/res/values-ha/strings.xml
  • app/res/values-hi/strings.xml
  • app/res/values-lt/strings.xml
  • app/res/values-no/strings.xml
  • app/res/values-pt/strings.xml
  • app/res/values-sw/strings.xml
  • app/res/values-ti/strings.xml
  • app/res/values/attrs.xml
  • app/res/values/dimens.xml
  • app/res/values/strings.xml
  • app/res/values/styles.xml
  • app/src/org/commcare/views/connect/SemiCircleArcView.kt
  • app/src/org/commcare/views/connect/SemiCircleProgressBar.kt

Comment thread app/src/org/commcare/views/connect/SemiCircleArcView.kt
@codecov

codecov Bot commented Jun 29, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 25.82%. Comparing base (00da1d5) to head (4a6bb3e).
⚠️ Report is 138 commits behind head on master.

Additional details and impacted files
@@             Coverage Diff              @@
##             master    #3779      +/-   ##
============================================
- Coverage     25.84%   25.82%   -0.02%     
- Complexity     4387     4427      +40     
============================================
  Files           951      966      +15     
  Lines         57199    57851     +652     
  Branches       6812     6884      +72     
============================================
+ Hits          14782    14939     +157     
- Misses        40590    41075     +485     
- Partials       1827     1837      +10     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Treat AT_MOST as a cap over the 240dp default instead of filling the
available width, so wrap_content no longer behaves like match_parent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@OrangeAndGreen OrangeAndGreen marked this pull request as ready for review June 29, 2026 17:14
@conroy-ricketts

Copy link
Copy Markdown
Contributor

Out of curiosity, was the design change intentional (i.e. using X of Y rather than X/Y)?

<string name="connect_progress_delivery">Delivery</string>
<string name="connect_progress_title">Delivery Progress</string>
<string name="connect_progress_status">You have completed %d of %d visits.</string>
<string name="semi_circle_progress_value_format" cc:translatable="true">%1$d of %2$d</string>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we name this connect_progress_text instead

And confirming that this needs to be cc:translatable?

android:layout_height="wrap_content"
android:textSize="@dimen/semi_circle_progress_value_text_size"
android:textStyle="bold"
tools:text="25 of 40" />

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this tested in the Android Studio preview window? Trying to gauge how valuable tools:text is in this layout. We could maybe go without it

Image

Comment thread app/res/values/attrs.xml
<attr name="strokeWidth" format="dimension" />
</declare-styleable>

<declare-styleable name="SemiCircleProgressBar">

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious how the team feels about prefixing these with Connect

Comment thread app/res/values/dimens.xml
Comment on lines +145 to +148
<dimen name="semi_circle_progress_default_width">240dp</dimen>
<dimen name="semi_circle_progress_stroke_width">14dp</dimen>
<dimen name="semi_circle_progress_value_text_size">28sp</dimen>
<dimen name="semi_circle_progress_description_text_size">16sp</dimen>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar comment as above, are these worth prefixing with connect like we do strings currently?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noting that there is a contrast with how it was defined for the Connect info card

@OrangeAndGreen

Copy link
Copy Markdown
Contributor Author

Out of curiosity, was the design change intentional (i.e. using X of Y rather than X/Y)?

@conroy-ricketts Confirmed, the design changed slightly in the final Figma so I went with the latest from there

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants