Skip to content

feat: Jetpack Compose reimplementation of GapFillTextView#1

Draft
Copilot wants to merge 2 commits intomasterfrom
copilot/research-gapfilltextview-implementation
Draft

feat: Jetpack Compose reimplementation of GapFillTextView#1
Copilot wants to merge 2 commits intomasterfrom
copilot/research-gapfilltextview-implementation

Conversation

Copy link
Copy Markdown

Copilot AI commented Apr 15, 2026

Adds a pure-Compose equivalent of GapFillTextView, replacing the View-based span/popup/dialog machinery with idiomatic Compose state, layout, and effect primitives. Also upgrades the build system to support Kotlin + Compose.

Build system

  • AGP 3.5.2 → 8.2.2, Gradle 5.4.1 → 8.4, Kotlin 1.9.22, compileSdk/targetSdk 28 → 34, minSdk 15 → 21
  • Compose BOM 2024.02.01 added to richtextview module (ui, foundation, material3, runtime, animation)
  • Removed bintray/dcendents publishing plugins; namespace moved from AndroidManifest to build.gradle

New files — com.rayworks.library.compose

GapFillParser.kt

Parses raw gap-fill text into a typed segment list. Applies the same normalisation and markdown→HTML conversion (Utils.getHtmlTextWithMarkups) as the original before splitting on {…} patterns.

sealed class Segment {
    data class TextSegment(val html: String) : Segment()
    data class BlankSegment(val index: Int, val defaultPlaceholder: String) : Segment()
}
data class GapFillParsed(val segments: List<Segment>, val errorCorrectionEnabled: Boolean, val totalBlanks: Int)

GapFillState.kt

Compose state holder — filledAnswers and activeBlankIndex backed by mutableStateOf. Includes reset(), firstUnfilledBlankIndex(), and formattedFullText() (regex-based so it handles both {} and {placeholder} blanks).

GapFillAnnotatedString.kt

Builds the AnnotatedString from parsed segments + current state. Handles:

  • BLANK string annotations on every blank span for tap resolution
  • Correct/wrong/editor colour spans (SpanStyle) on answered blanks
  • TextDecoration.Underline for error-correction + review mode
  • InlineTextContent + appendInlineContent for the deletion-icon blank
  • Spanned → AnnotatedString conversion for StyleSpan / ForegroundColorSpan

GapFillPopup.kt

DropdownMenu-based option picker styled to match popupwnd_bkg.xml (blue, 8dp corners). Deletion option renders an icon+label row. Max 4 items visible before scroll.

GapFillEditorDialog.kt

Dialog-based free-form editor. Background animates blue → orange-red when word limit is exceeded (mirrors rectangle_gapfill_form_bkg*.xml). Dim scrim removed via DialogWindowProvider. Keyboard hidden on dismiss.

GapFillText.kt

Top-level composable + GapFillConfig data class (replaces XML attrs and setter methods).

@Composable
fun GapFillText(
    config: GapFillConfig,
    state: GapFillState = rememberGapFillState(),
    answerChecker: AnswerCorrectionChecker? = null,
    resultObserver: AnswerResultObserver? = null,
    modifier: Modifier = Modifier,
    textStyle: TextStyle = TextStyle.Default,
)
  • Tap handling via BasicText + detectTapGestures + TextLayoutResult.getOffsetForPosition
  • Idle-detection timer via LaunchedEffect(interactionKey) — restarts on every blank tap, cancelling the previous delay (replaces Handler.postDelayed)
  • Full AnswerResultObserver / AnswerCorrectionChecker callback parity with the original
  • Outer Box carries the writing_text_frame_bkg border (1dp light-grey stroke, 8dp corners)

All existing Java source files are unchanged.

Copilot AI and others added 2 commits April 15, 2026 02:36
- Upgrade build system: Gradle 8.4, AGP 8.2.2, Kotlin 1.9.22, Compose BOM 2024.02.01
- Add GapFillParser.kt: sealed Segment hierarchy + parseRawText()
- Add GapFillState.kt: GapFillState (mutableStateOf-backed) + rememberGapFillState()
- Add GapFillAnnotatedString.kt: AnnotatedString builder, inline deletion-icon content, Spanned→AnnotatedString converter, orderedAnswers helper
- Add GapFillPopup.kt: DropdownMenu-based option picker (styled to match popupwnd_bkg.xml)
- Add GapFillEditorDialog.kt: Dialog-based free-form editor with animated colour, no-scrim, keyboard handling
- Add GapFillText.kt: GapFillConfig data class + GapFillText composable with idle detection, tap handling, and observer callbacks

Agent-Logs-Url: https://github.com/rayworks/RichTextView/sessions/db30412a-5e23-4911-a342-83615401ef14

Co-authored-by: rayworks <1329281+rayworks@users.noreply.github.com>
- formattedFullText: use regex to match both {} and {placeholder} blanks
- populateAnswer: use local val to avoid redundant !! assertions on currentChecker

Agent-Logs-Url: https://github.com/rayworks/RichTextView/sessions/db30412a-5e23-4911-a342-83615401ef14

Co-authored-by: rayworks <1329281+rayworks@users.noreply.github.com>
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