Skip to content

Display images in the summary view#7234

Open
grzesiek2010 wants to merge 17 commits into
getodk:masterfrom
grzesiek2010:images
Open

Display images in the summary view#7234
grzesiek2010 wants to merge 17 commits into
getodk:masterfrom
grzesiek2010:images

Conversation

@grzesiek2010

@grzesiek2010 grzesiek2010 commented May 15, 2026

Copy link
Copy Markdown
Member

Work towards #6084
Closes #7168

Why is this the best possible solution? Were any other approaches considered?

The new ImageWidgetAnswer component continues the approach we already introduced for video and file questions. Similar to those question types, I started refactoring the widgets so they can share the same answer component with the summary view.
To avoid making this PR too large, I started with the basic image question. I decided not only to rework it to use the new ImageWidgetAnswer, but also to shift from inheritance to composition by detaching it from its previous hierarchy. It previously extended BaseImageWidget, which had become a fairly convoluted structure.

How does this change affect users? Describe intentional changes to behavior and behavior that could have accidentally been affected by code changes. In other words, what are the regression risks?

Images should be displayed in the summary view regardless of which image question type they come from (image/draw/signature/annotate). The summary view should be tested with all image question types, but we don’t need to test each image question type in form entry. Only the basic image question has been refactored, so that is the one that requires thorough testing. Only the basic image question currently shares the new image component with the summary view, so only that question type will display images with rounded corners. We plan to apply the same approach to the other image question types in the future.

Do we need any specific form for testing your changes? If so, please attach one.

The All question types forms should be enough.

Does this change require updates to documentation? If so, please file an issue here and include the link below.

No.

Before submitting this PR, please make sure you have:

  • added or modified tests for any new or changed behavior
  • run ./gradlew connectedAndroidTest (or ./gradlew testLab) and confirmed all checks still pass
  • added a comment above any new strings describing it for translators
  • added any new strings with date formatting to DateFormatsTest
  • verified that any code or assets from external sources are properly credited in comments and/or in the about file.
  • verified that any new UI elements use theme colors. UI Components Style guidelines

@grzesiek2010 grzesiek2010 force-pushed the images branch 3 times, most recently from bcd10a8 to bde4db2 Compare May 20, 2026 15:38
@grzesiek2010 grzesiek2010 marked this pull request as ready for review May 20, 2026 22:21

@seadowg seadowg left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Some initial thoughts before going deeper.

Comment thread collect_app/build.gradle
@grzesiek2010 grzesiek2010 requested a review from seadowg June 12, 2026 22:36

@seadowg seadowg left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@grzesiek2010 grzesiek2010 requested a review from seadowg June 16, 2026 09:19

override fun clearAnswer() {
fileAnswerDelegate.deleteFile()
widgetValueChanged()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could the delegate also take the current widget as a constructor param so it can handle the widgetValueChanged calls as well?

modifier: Modifier,
answer: String,
contentScale: ContentScale,
mediaWidgetAnswerViewModel: MediaWidgetAnswerViewModel,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Passing the ViewModel here seems inconsistent with the other "widget answer" Composables: they mostly take data and listeners (like onClick) and handle wiring up the ViewModel in WidgetAnswer.

}
}
Constants.CONTROL_IMAGE_CHOOSE -> ImageWidgetAnswer(
if (summaryView) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could this param be named to "centered" or something more oriented towards the visual difference?


@Test
override fun usingReadOnlyOptionShouldMakeAllClickableElementsDisabled() {
whenever(formEntryPrompt.isReadOnly).thenReturn(true)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This could use MockFormEntryPromptBuilder instead

@Test
fun `when read-only override option is used should all clickable elements be disabled`() {
readOnlyOverride = true
whenever(formEntryPrompt.isReadOnly).thenReturn(false)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This could use MockFormEntryPromptBuilder instead

}

@Test
fun `when prompt has current answer shows in image view`() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This doesn't really test that?

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.

Too little margin on the right in the hierarchy view

2 participants