Skip to content

Code Block and Compound Button Card improvements to close in on parity with Web#69

Open
vallesmarinerisapp wants to merge 257 commits into
VikrantSingh01:mainfrom
vallesmarinerisapp:jacob-card-improvements
Open

Code Block and Compound Button Card improvements to close in on parity with Web#69
vallesmarinerisapp wants to merge 257 commits into
VikrantSingh01:mainfrom
vallesmarinerisapp:jacob-card-improvements

Conversation

@vallesmarinerisapp
Copy link
Copy Markdown

Pull Request

Description

This changes the alpha on the line numbers in the code block card type and refactors and improves the Compound Button card to be closer to web implementation.

Known issues: I haven't been able to run the tests yet because of a gradle dependency issue. Working on that now.

Screenshots attached below.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Performance improvement
  • Code refactoring

Cross-Platform Parity Checklist

For all code changes affecting card rendering or schema support:

  • iOS Implementation: Changes implemented in iOS (Swift/SwiftUI)
  • Android Implementation: Changes implemented in Android (Kotlin/Compose)
  • Tests Added: Tests added for both platforms
  • Schema Updated: SchemaValidator updated on both platforms (if new elements/actions)
  • PARITY_MATRIX.md Updated: Documentation reflects current implementation status
  • Shared Test Card: Added/updated test card in shared/test-cards/ (if applicable)
  • Parity Gate Passes: CI parity gate passes (iOS + Android tests)

Impact & Regression Testing (MANDATORY — Zero Regressions Policy)

Every impacted card, flow, and scenario MUST be tested before merge.

Impact Analysis

Impacted modules:
Impacted card types:
Impacted flows:

Regression Test Results

  • Unit Tests for impacted modules: Ran and passed on both iOS and Android
  • Full Test Suite: swift test (iOS) and ./gradlew test (Android) pass
  • Visual Snapshot Tests: Ran visual regression tests (iOS VisualTests + Android Paparazzi) — no regressions
  • Card Parsing Regression: swift test --filter CardParsingRegressionTests passes
  • Impacted Cards Verified: Tested ALL impacted cards via deep links on BOTH platforms with screenshot verification
  • OCR Validation: Ran check-screenshot-text.sh on all screenshots — no unresolved templates or error text
  • Schema Parity: compare-schema-coverage.sh passes (if element/action types changed)
  • Template Cards: test-template-cards-dual.sh passes (if templating changed)
  • Pre-Merge Validation: shared/scripts/pre-merge-validation.sh passes

Cards Tested

Card iOS Android Notes

Testing Checklist

  • Unit Tests: Added/updated unit tests
  • Integration Tests: Added/updated integration tests
  • All Tests Pass: swift test (iOS) and ./gradlew test (Android) pass locally
  • Test Coverage: Maintained or improved test coverage
  • Manual Testing: Manually tested changes on iOS and Android
  • Edge Cases: Tested edge cases and error conditions

Schema Validation (for schema changes)

  • v1.6 Compliance: Changes comply with Adaptive Cards v1.6 spec
  • Schema File Updated: shared/schema/adaptive-card-schema-1.6.json updated (if applicable)
  • Round-Trip Tests: JSON parse → model → JSON serialization works correctly
  • Unknown Elements: Unknown elements handled gracefully

Documentation

  • Code Comments: Added comments for complex logic
  • README Updated: Updated relevant README files
  • Architecture Docs: Updated architecture docs (if applicable)
  • CHANGELOG Updated: Added entry to CHANGELOG.md
  • API Documentation: Updated API documentation (if public API changed)

Accessibility

  • Screen Reader: Works with VoiceOver (iOS) and TalkBack (Android)
  • Dynamic Type: Respects system font size preferences
  • Touch Targets: Minimum 44x44pt (iOS) / 48x48dp (Android)
  • Contrast: Meets WCAG 2.1 AA contrast requirements
  • Semantic Labels: Proper accessibility labels and hints

Performance

  • No Performance Regression: Changes do not negatively impact performance
  • Memory Leaks: Checked for memory leaks
  • Large Card Handling: Tested with large/complex cards

Security

  • No Security Vulnerabilities: Changes do not introduce security issues
  • Input Validation: User input properly validated
  • XSS Prevention: Protected against cross-site scripting (if applicable)
  • Secrets: No secrets or sensitive data in code

Breaking Changes

Screenshots / Videos

Before:
before

After:

after

Related Issues

Additional Notes


Reviewer Checklist

For Maintainers:

  • Code quality meets project standards
  • Cross-platform parity maintained
  • Tests are comprehensive and passing
  • Documentation is clear and complete
  • No breaking changes (or properly documented)
  • CHANGELOG.md updated appropriately
  • CI checks pass (lint, tests, parity gate)

VikrantSingh01 and others added 30 commits March 10, 2026 21:55
…ment

Regenerated all 1033 Paparazzi snapshot baselines to reflect the
updated hostConfig design tokens (button colors from hostConfig,
table grid lines from separator config, corner radii, spacing).
…, Icon element

Major changes across both platforms:

**Figma Alignment (both platforms):**
- Add badgeStyles (7 styles x filled/tint) and pageControl to HostConfig
- Fix iOS container styles: remove extra borderColors, correct attention/accent bg
- Fix Android showCard.style: Emphasis → Default per Figma spec

**Bookmark Feature (both platforms):**
- Persistent bookmark store (UserDefaults on iOS, SharedPreferences on Android)
- Bookmark toggle on gallery card rows and detail view toolbar
- New Bookmarks screen in More tab with remove support
- Android gallery scroll position preserved across navigation

**iOS SDK Integration:**
- Wire ACRendering + ACCore SPM packages into SampleApp Xcode project
- Replace custom CardPreviewPlaceholder with SDK AdaptiveCardView
- Sample app now uses full SDK renderer (matching Android architecture)

**Parsing Fixes (iOS):**
- Add Spacing.ExtraSmall enum case
- Add ImageStyle.RoundedCorners enum case
- Fix TargetElement decoder to accept both string and object formats

**Icon Element (iOS):**
- New IconElement model in ACCore
- New IconElementView renderer with 100+ Fluent UI → SF Symbol mappings
- Resolves "Unknown element type: Icon" across 159 card elements
- test-card-parsing.swift: validates all card JSONs parse without errors
- test-ios-cards-ui.sh: checks cards for unknown element types and reports
  Results: 634 cards tested, 628 pass, 6 warnings (intentional test cards)
Self-healing loop: ran CardParsingRegressionTests against 634 cards,
found 60+ parsing failures, fixed ALL to 0 failures.

Parsing fixes:
- CaseInsensitiveCodable: fallback to default instead of throwing
  (handles template expressions like ${if(...)})
- CompoundButton.icon: accept both string and {name,size,color} object
- RichTextBlock.inlines: accept plain strings as TextRun shorthand
- CardElement.fallback: handle "drop" string per AC spec
- TextBlock.text: make optional (some cards omit it)
- ProgressBar.value: make optional
- ActionStyle: add "other" case
- CardAction: add .unknown case for graceful fallback
- TargetElement: accept string shorthand
- Input.isRequired: decode from string "true"/"false"
- AdaptiveCard.body/actions: skip non-array values gracefully
- Image.themedUrls: handle array format
- Carousel.pages: handle template string expressions
- PopoverAction.popoverBody: make optional

Repo changes:
- Add ios/SampleApp.xcodeproj to git (exception in .gitignore)
- Add CardParsingRegressionTests (4 test groups, 634 cards)
- Add test scripts: auto-test-ios-cards.sh, test-ios-cards-visual.sh
… testing

- Add adaptivecards://card/{path} URL scheme for programmatic navigation
- DeepLinkRouter handles URL → card detail view via fullScreenCover
- visual-test-loop.sh: automated screenshot capture for all Teams Official cards
  Uses simctl openurl + simctl io screenshot — no accessibility permissions needed
- All 19 Teams Official cards render successfully (visual verification)

Remaining minor issues (tracked for future):
- Badge element type not yet supported (shows "Unknown element type: Badge")
- Some Fluent icon names need additional SF Symbol mappings
- Network images (person photos, hero images) depend on connectivity
Documents the adaptivecards:// URL scheme, automated visual test loop,
and card parsing regression test commands for developer reference.
bash shared/scripts/self-heal-ios.sh — full automated test cycle:
  Phase 1: Parse regression (swift test --filter CardParsingRegressionTests)
  Phase 2: Visual smoke (deep-link → screenshot → analyze each card)
  Phase 3: Markdown report with per-card status + screenshots

Modes: --parse-only, --visual-only, --card <name>
Results: 19/19 Teams Official cards pass (0 failures)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…antSingh01#50)

* fix(ios): align TeamsHostConfig to Figma iOS design spec

Update iOS TeamsHostConfig values to match the platform-specific
HostConfig from the Figma AC-Evolution design file (iOS page).

Key changes from Figma iOS Light spec:
- fontFamily: Segoe UI → .SF UI Text (iOS system font)
- fontSizes: 12/14/14/16/20 → 12/15/15/17/22
- fontWeights: lighter 400→300, bolder 500→600
- separator lineColor: #0D16233A → #FFDFDEDE
- spacing: default 8→10, padding 10→8
- factSet spacing: 32→16
- container backgrounds: good #DFF6DD→#E7F2DA, warning #FED9CC→#FBF6D9
- monospace font: Courier New → Menlo
- actions: spacing Medium→Default, showCard style Emphasis→Default

Also updates README with Phase 6A.1 Figma Design Alignment milestone
and refreshes build/test status to 2026-03-10.

* fix(ios,android): replace hardcoded design values with hostConfig

Audit all rendering views against Figma spec and replace hardcoded
colors, spacing, corner radii, and border widths with hostConfig values.

iOS fixes:
- ActionButton: spacing, padding, cornerRadius, borderWidth from hostConfig
- ActionButton: refactor sfSymbol switch to dictionary (fixes SwiftLint
  cyclomatic complexity violation)
- ActionSetView: overflow menu uses hostConfig spacing/radius/thickness
- CodeBlockView: all padding uses hostConfig.spacing.small
- CompoundButtonView: border lineWidth from hostConfig.separator
- AccordionView: divider height from hostConfig.separator.lineThickness
- ProgressIndicatorViews: spinner spacing from hostConfig.spacing.default

Android fixes:
- ActionSetView: positive/destructive button colors from hostConfig
  foregroundColors instead of hardcoded hex; cornerRadius, padding,
  border stroke, icon spacing all from hostConfig
- MediaAndTableViews: table grid line color from hostConfig.separator;
  divider thickness from hostConfig.separator.lineThickness

* chore(android): update Paparazzi snapshot baselines after Figma alignment

Regenerated all 1033 Paparazzi snapshot baselines to reflect the
updated hostConfig design tokens (button colors from hostConfig,
table grid lines from separator config, corner radii, spacing).

* feat(ios,android): bookmark feature, SDK integration, Figma alignment, Icon element

Major changes across both platforms:

**Figma Alignment (both platforms):**
- Add badgeStyles (7 styles x filled/tint) and pageControl to HostConfig
- Fix iOS container styles: remove extra borderColors, correct attention/accent bg
- Fix Android showCard.style: Emphasis → Default per Figma spec

**Bookmark Feature (both platforms):**
- Persistent bookmark store (UserDefaults on iOS, SharedPreferences on Android)
- Bookmark toggle on gallery card rows and detail view toolbar
- New Bookmarks screen in More tab with remove support
- Android gallery scroll position preserved across navigation

**iOS SDK Integration:**
- Wire ACRendering + ACCore SPM packages into SampleApp Xcode project
- Replace custom CardPreviewPlaceholder with SDK AdaptiveCardView
- Sample app now uses full SDK renderer (matching Android architecture)

**Parsing Fixes (iOS):**
- Add Spacing.ExtraSmall enum case
- Add ImageStyle.RoundedCorners enum case
- Fix TargetElement decoder to accept both string and object formats

**Icon Element (iOS):**
- New IconElement model in ACCore
- New IconElementView renderer with 100+ Fluent UI → SF Symbol mappings
- Resolves "Unknown element type: Icon" across 159 card elements

* test(shared): add automated card parsing and UI smoke test scripts

- test-card-parsing.swift: validates all card JSONs parse without errors
- test-ios-cards-ui.sh: checks cards for unknown element types and reports
  Results: 634 cards tested, 628 pass, 6 warnings (intentional test cards)

* fix(ios): resolve all card parsing failures + add xcodeproj to repo

Self-healing loop: ran CardParsingRegressionTests against 634 cards,
found 60+ parsing failures, fixed ALL to 0 failures.

Parsing fixes:
- CaseInsensitiveCodable: fallback to default instead of throwing
  (handles template expressions like ${if(...)})
- CompoundButton.icon: accept both string and {name,size,color} object
- RichTextBlock.inlines: accept plain strings as TextRun shorthand
- CardElement.fallback: handle "drop" string per AC spec
- TextBlock.text: make optional (some cards omit it)
- ProgressBar.value: make optional
- ActionStyle: add "other" case
- CardAction: add .unknown case for graceful fallback
- TargetElement: accept string shorthand
- Input.isRequired: decode from string "true"/"false"
- AdaptiveCard.body/actions: skip non-array values gracefully
- Image.themedUrls: handle array format
- Carousel.pages: handle template string expressions
- PopoverAction.popoverBody: make optional

Repo changes:
- Add ios/SampleApp.xcodeproj to git (exception in .gitignore)
- Add CardParsingRegressionTests (4 test groups, 634 cards)
- Add test scripts: auto-test-ios-cards.sh, test-ios-cards-visual.sh


* feat(ios): deep link navigation + visual test loop for automated card testing

- Add adaptivecards://card/{path} URL scheme for programmatic navigation
- DeepLinkRouter handles URL → card detail view via fullScreenCover
- visual-test-loop.sh: automated screenshot capture for all Teams Official cards
  Uses simctl openurl + simctl io screenshot — no accessibility permissions needed
- All 19 Teams Official cards render successfully (visual verification)

Remaining minor issues (tracked for future):
- Badge element type not yet supported (shows "Unknown element type: Badge")
- Some Fluent icon names need additional SF Symbol mappings
- Network images (person photos, hero images) depend on connectivity


* docs: add sample app deep link testing and visual test loop to CLAUDE.md

Documents the adaptivecards:// URL scheme, automated visual test loop,
and card parsing regression test commands for developer reference.


* feat(testing): add self-healing iOS card test loop command

bash shared/scripts/self-heal-ios.sh — full automated test cycle:
  Phase 1: Parse regression (swift test --filter CardParsingRegressionTests)
  Phase 2: Visual smoke (deep-link → screenshot → analyze each card)
  Phase 3: Markdown report with per-card status + screenshots

Modes: --parse-only, --visual-only, --card <name>
Results: 19/19 Teams Official cards pass (0 failures)


* feat(testing): add self-healing test loops for iOS and Android

Add automated detect → diagnose → recover → fix test scripts for both
platforms. Each runs a 6-phase cycle: parse regression tests, visual
smoke tests with deep-link navigation and screenshots, multi-signal
crash/hang/OOM diagnosis from simulator logs (iOS) or logcat (Android),
auto-retry with escalating recovery, structured fix suggestions with
file-level hints, and a rich markdown report with all artifacts.

iOS script uses xcrun simctl + system log mining; Android script uses
adb + logcat analysis. Both support --parse-only, --visual-only,
--card, --retry, and --category flags.


* feat(ios,android): rendering fixes, input parity, and sample app improvements

Container rendering:
- Add showBorder and roundedCorners support to Container model and view on both platforms
- Render border stroke using host config borderColor when showBorder is true

Image rendering (Android):
- Fix Auto-sized images to fill container width per AC spec (fillMaxWidth)
- Use FillWidth content scale for aspect-ratio-preserving full-width images
- Add RoundedCorners image style enum and 8dp corner radius rendering

Input parity (iOS):
- Fix DateInputView pre-populating today's date when no value specified
- Fix TimeInputView pre-populating current time when no value specified
- Both now show placeholder text until user explicitly selects a value
- Add required field suffix (* indicator) to all input labels via host config

Progress bar (iOS):
- Fix named color resolution (green, accent, attention, etc.) in ProgressBarView
- Color(hex:) was receiving named strings like "green" and falling back to black

Icon mapping (Android):
- Map "Crown" icon to WorkspacePremium instead of Star for better visual parity

App icon:
- Add custom app icon for both iOS (Assets.xcassets) and Android (mipmap resources)
- Update AndroidManifest.xml with icon and roundIcon attributes
- Add Assets.xcassets to Xcode project build phases

Sample app enhancements:
- Improved card gallery, detail screens, and Teams simulator on both platforms
- Added input renderer setup, bookmarks, settings, and performance dashboard
- Enhanced deep link navigation and self-healing test scripts


* feat(ios,android): extended deep link routing, gallery filters, cart icon, and demo script

Add full deep link navigation support (editor, performance, bookmarks, settings, more) on
both platforms with gallery category filtering via adaptivecards://gallery/{filter}. Add
cart/cartfilled icon mapping for parity. Include dual-platform demo-bookmarks.sh script for
automated bookmark walkthroughs. Update README with latest sample app features and 52 test cards.


---------
* fix(ios): resolve all card parsing failures + add xcodeproj to repo

Self-healing loop: ran CardParsingRegressionTests against 634 cards,
found 60+ parsing failures, fixed ALL to 0 failures.

Parsing fixes:
- CaseInsensitiveCodable: fallback to default instead of throwing
  (handles template expressions like ${if(...)})
- CompoundButton.icon: accept both string and {name,size,color} object
- RichTextBlock.inlines: accept plain strings as TextRun shorthand
- CardElement.fallback: handle "drop" string per AC spec
- TextBlock.text: make optional (some cards omit it)
- ProgressBar.value: make optional
- ActionStyle: add "other" case
- CardAction: add .unknown case for graceful fallback
- TargetElement: accept string shorthand
- Input.isRequired: decode from string "true"/"false"
- AdaptiveCard.body/actions: skip non-array values gracefully
- Image.themedUrls: handle array format
- Carousel.pages: handle template string expressions
- PopoverAction.popoverBody: make optional

Repo changes:
- Add ios/SampleApp.xcodeproj to git (exception in .gitignore)
- Add CardParsingRegressionTests (4 test groups, 634 cards)
- Add test scripts: auto-test-ios-cards.sh, test-ios-cards-visual.sh

* feat(ios): deep link navigation + visual test loop for automated card testing

- Add adaptivecards://card/{path} URL scheme for programmatic navigation
- DeepLinkRouter handles URL → card detail view via fullScreenCover
- visual-test-loop.sh: automated screenshot capture for all Teams Official cards
  Uses simctl openurl + simctl io screenshot — no accessibility permissions needed
- All 19 Teams Official cards render successfully (visual verification)

Remaining minor issues (tracked for future):
- Badge element type not yet supported (shows "Unknown element type: Badge")
- Some Fluent icon names need additional SF Symbol mappings
- Network images (person photos, hero images) depend on connectivity

* docs: add sample app deep link testing and visual test loop to CLAUDE.md

Documents the adaptivecards:// URL scheme, automated visual test loop,
and card parsing regression test commands for developer reference.

* feat(testing): add self-healing iOS card test loop command

bash shared/scripts/self-heal-ios.sh — full automated test cycle:
  Phase 1: Parse regression (swift test --filter CardParsingRegressionTests)
  Phase 2: Visual smoke (deep-link → screenshot → analyze each card)
  Phase 3: Markdown report with per-card status + screenshots

Modes: --parse-only, --visual-only, --card <name>
Results: 19/19 Teams Official cards pass (0 failures)

* feat(testing): add self-healing test loops for iOS and Android

Add automated detect → diagnose → recover → fix test scripts for both
platforms. Each runs a 6-phase cycle: parse regression tests, visual
smoke tests with deep-link navigation and screenshots, multi-signal
crash/hang/OOM diagnosis from simulator logs (iOS) or logcat (Android),
auto-retry with escalating recovery, structured fix suggestions with
file-level hints, and a rich markdown report with all artifacts.

iOS script uses xcrun simctl + system log mining; Android script uses
adb + logcat analysis. Both support --parse-only, --visual-only,
--card, --retry, and --category flags.

* feat(ios,android): rendering fixes, input parity, and sample app improvements

Container rendering:
- Add showBorder and roundedCorners support to Container model and view on both platforms
- Render border stroke using host config borderColor when showBorder is true

Image rendering (Android):
- Fix Auto-sized images to fill container width per AC spec (fillMaxWidth)
- Use FillWidth content scale for aspect-ratio-preserving full-width images
- Add RoundedCorners image style enum and 8dp corner radius rendering

Input parity (iOS):
- Fix DateInputView pre-populating today's date when no value specified
- Fix TimeInputView pre-populating current time when no value specified
- Both now show placeholder text until user explicitly selects a value
- Add required field suffix (* indicator) to all input labels via host config

Progress bar (iOS):
- Fix named color resolution (green, accent, attention, etc.) in ProgressBarView
- Color(hex:) was receiving named strings like "green" and falling back to black

Icon mapping (Android):
- Map "Crown" icon to WorkspacePremium instead of Star for better visual parity

App icon:
- Add custom app icon for both iOS (Assets.xcassets) and Android (mipmap resources)
- Update AndroidManifest.xml with icon and roundIcon attributes
- Add Assets.xcassets to Xcode project build phases

Sample app enhancements:
- Improved card gallery, detail screens, and Teams simulator on both platforms
- Added input renderer setup, bookmarks, settings, and performance dashboard
- Enhanced deep link navigation and self-healing test scripts

* feat(ios,android): extended deep link routing, gallery filters, cart icon, and demo script

Add full deep link navigation support (editor, performance, bookmarks, settings, more) on
both platforms with gallery category filtering via adaptivecards://gallery/{filter}. Add
cart/cartfilled icon mapping for parity. Include dual-platform demo-bookmarks.sh script for
automated bookmark walkthroughs. Update README with latest sample app features and 52 test cards.

* docs: Documentation updates with latest changes 3/11

* feat(ios,android): rename sample app to AC Visualizer

Rename the sample app from "Adaptive Cards Sample App" to
"AC Visualizer" across both platforms, including app display names,
hero headers, footer labels, Xcode target/scheme, scripts, and docs.
Verified on both iOS and Android simulators.
…1#55)

* fix(ios): resolve all card parsing failures + add xcodeproj to repo

Self-healing loop: ran CardParsingRegressionTests against 634 cards,
found 60+ parsing failures, fixed ALL to 0 failures.

Parsing fixes:
- CaseInsensitiveCodable: fallback to default instead of throwing
  (handles template expressions like ${if(...)})
- CompoundButton.icon: accept both string and {name,size,color} object
- RichTextBlock.inlines: accept plain strings as TextRun shorthand
- CardElement.fallback: handle "drop" string per AC spec
- TextBlock.text: make optional (some cards omit it)
- ProgressBar.value: make optional
- ActionStyle: add "other" case
- CardAction: add .unknown case for graceful fallback
- TargetElement: accept string shorthand
- Input.isRequired: decode from string "true"/"false"
- AdaptiveCard.body/actions: skip non-array values gracefully
- Image.themedUrls: handle array format
- Carousel.pages: handle template string expressions
- PopoverAction.popoverBody: make optional

Repo changes:
- Add ios/SampleApp.xcodeproj to git (exception in .gitignore)
- Add CardParsingRegressionTests (4 test groups, 634 cards)
- Add test scripts: auto-test-ios-cards.sh, test-ios-cards-visual.sh

* feat(ios): deep link navigation + visual test loop for automated card testing

- Add adaptivecards://card/{path} URL scheme for programmatic navigation
- DeepLinkRouter handles URL → card detail view via fullScreenCover
- visual-test-loop.sh: automated screenshot capture for all Teams Official cards
  Uses simctl openurl + simctl io screenshot — no accessibility permissions needed
- All 19 Teams Official cards render successfully (visual verification)

Remaining minor issues (tracked for future):
- Badge element type not yet supported (shows "Unknown element type: Badge")
- Some Fluent icon names need additional SF Symbol mappings
- Network images (person photos, hero images) depend on connectivity

* docs: add sample app deep link testing and visual test loop to CLAUDE.md

Documents the adaptivecards:// URL scheme, automated visual test loop,
and card parsing regression test commands for developer reference.

* feat(testing): add self-healing iOS card test loop command

bash shared/scripts/self-heal-ios.sh — full automated test cycle:
  Phase 1: Parse regression (swift test --filter CardParsingRegressionTests)
  Phase 2: Visual smoke (deep-link → screenshot → analyze each card)
  Phase 3: Markdown report with per-card status + screenshots

Modes: --parse-only, --visual-only, --card <name>
Results: 19/19 Teams Official cards pass (0 failures)

* feat(testing): add self-healing test loops for iOS and Android

Add automated detect → diagnose → recover → fix test scripts for both
platforms. Each runs a 6-phase cycle: parse regression tests, visual
smoke tests with deep-link navigation and screenshots, multi-signal
crash/hang/OOM diagnosis from simulator logs (iOS) or logcat (Android),
auto-retry with escalating recovery, structured fix suggestions with
file-level hints, and a rich markdown report with all artifacts.

iOS script uses xcrun simctl + system log mining; Android script uses
adb + logcat analysis. Both support --parse-only, --visual-only,
--card, --retry, and --category flags.

* feat(ios,android): rendering fixes, input parity, and sample app improvements

Container rendering:
- Add showBorder and roundedCorners support to Container model and view on both platforms
- Render border stroke using host config borderColor when showBorder is true

Image rendering (Android):
- Fix Auto-sized images to fill container width per AC spec (fillMaxWidth)
- Use FillWidth content scale for aspect-ratio-preserving full-width images
- Add RoundedCorners image style enum and 8dp corner radius rendering

Input parity (iOS):
- Fix DateInputView pre-populating today's date when no value specified
- Fix TimeInputView pre-populating current time when no value specified
- Both now show placeholder text until user explicitly selects a value
- Add required field suffix (* indicator) to all input labels via host config

Progress bar (iOS):
- Fix named color resolution (green, accent, attention, etc.) in ProgressBarView
- Color(hex:) was receiving named strings like "green" and falling back to black

Icon mapping (Android):
- Map "Crown" icon to WorkspacePremium instead of Star for better visual parity

App icon:
- Add custom app icon for both iOS (Assets.xcassets) and Android (mipmap resources)
- Update AndroidManifest.xml with icon and roundIcon attributes
- Add Assets.xcassets to Xcode project build phases

Sample app enhancements:
- Improved card gallery, detail screens, and Teams simulator on both platforms
- Added input renderer setup, bookmarks, settings, and performance dashboard
- Enhanced deep link navigation and self-healing test scripts

* feat(ios,android): extended deep link routing, gallery filters, cart icon, and demo script

Add full deep link navigation support (editor, performance, bookmarks, settings, more) on
both platforms with gallery category filtering via adaptivecards://gallery/{filter}. Add
cart/cartfilled icon mapping for parity. Include dual-platform demo-bookmarks.sh script for
automated bookmark walkthroughs. Update README with latest sample app features and 52 test cards.

* docs: Documentation updates with latest changes 3/11

* feat(ios,android): rename sample app to AC Visualizer

Rename the sample app from "Adaptive Cards Sample App" to
"AC Visualizer" across both platforms, including app display names,
hero headers, footer labels, Xcode target/scheme, scripts, and docs.
Verified on both iOS and Android simulators.

* refactor(ios,android): JSON-driven host config, remove ac-host-config module

Replace hardcoded TeamsHostConfig factory methods with JSON files loaded
at runtime. This aligns with the Teams-AdaptiveCards-Mobile reference
architecture where JSON is the source of truth for host configs.

Architecture changes:
- Host config JSON source of truth in shared/host-configs/{ios,android}/
- iOS TeamsHostConfig loads from bundled SPM resources (227 → 41 lines)
- Android TeamsHostConfig loads from classpath resources (497 → 44 lines)
- iOS gains dark theme support (TeamsHostConfig.createDark())
- Remove ac-host-config module, move HostConfigProvider + TeamsTheme
  into ac-rendering/theme/ — achieves 11/11 module parity
- Update 20 Android import paths
- Self-heal scripts resize screenshots to 540px for smaller file sizes

Verified: dual-platform self-heal test 38/38 pass (19 iOS + 19 Android)
…ikrantSingh01#56)

* fix(ios): resolve all card parsing failures + add xcodeproj to repo

Self-healing loop: ran CardParsingRegressionTests against 634 cards,
found 60+ parsing failures, fixed ALL to 0 failures.

Parsing fixes:
- CaseInsensitiveCodable: fallback to default instead of throwing
  (handles template expressions like ${if(...)})
- CompoundButton.icon: accept both string and {name,size,color} object
- RichTextBlock.inlines: accept plain strings as TextRun shorthand
- CardElement.fallback: handle "drop" string per AC spec
- TextBlock.text: make optional (some cards omit it)
- ProgressBar.value: make optional
- ActionStyle: add "other" case
- CardAction: add .unknown case for graceful fallback
- TargetElement: accept string shorthand
- Input.isRequired: decode from string "true"/"false"
- AdaptiveCard.body/actions: skip non-array values gracefully
- Image.themedUrls: handle array format
- Carousel.pages: handle template string expressions
- PopoverAction.popoverBody: make optional

Repo changes:
- Add ios/SampleApp.xcodeproj to git (exception in .gitignore)
- Add CardParsingRegressionTests (4 test groups, 634 cards)
- Add test scripts: auto-test-ios-cards.sh, test-ios-cards-visual.sh

* feat(ios): deep link navigation + visual test loop for automated card testing

- Add adaptivecards://card/{path} URL scheme for programmatic navigation
- DeepLinkRouter handles URL → card detail view via fullScreenCover
- visual-test-loop.sh: automated screenshot capture for all Teams Official cards
  Uses simctl openurl + simctl io screenshot — no accessibility permissions needed
- All 19 Teams Official cards render successfully (visual verification)

Remaining minor issues (tracked for future):
- Badge element type not yet supported (shows "Unknown element type: Badge")
- Some Fluent icon names need additional SF Symbol mappings
- Network images (person photos, hero images) depend on connectivity

* docs: add sample app deep link testing and visual test loop to CLAUDE.md

Documents the adaptivecards:// URL scheme, automated visual test loop,
and card parsing regression test commands for developer reference.

* feat(testing): add self-healing iOS card test loop command

bash shared/scripts/self-heal-ios.sh — full automated test cycle:
  Phase 1: Parse regression (swift test --filter CardParsingRegressionTests)
  Phase 2: Visual smoke (deep-link → screenshot → analyze each card)
  Phase 3: Markdown report with per-card status + screenshots

Modes: --parse-only, --visual-only, --card <name>
Results: 19/19 Teams Official cards pass (0 failures)

* feat(testing): add self-healing test loops for iOS and Android

Add automated detect → diagnose → recover → fix test scripts for both
platforms. Each runs a 6-phase cycle: parse regression tests, visual
smoke tests with deep-link navigation and screenshots, multi-signal
crash/hang/OOM diagnosis from simulator logs (iOS) or logcat (Android),
auto-retry with escalating recovery, structured fix suggestions with
file-level hints, and a rich markdown report with all artifacts.

iOS script uses xcrun simctl + system log mining; Android script uses
adb + logcat analysis. Both support --parse-only, --visual-only,
--card, --retry, and --category flags.

* feat(ios,android): rendering fixes, input parity, and sample app improvements

Container rendering:
- Add showBorder and roundedCorners support to Container model and view on both platforms
- Render border stroke using host config borderColor when showBorder is true

Image rendering (Android):
- Fix Auto-sized images to fill container width per AC spec (fillMaxWidth)
- Use FillWidth content scale for aspect-ratio-preserving full-width images
- Add RoundedCorners image style enum and 8dp corner radius rendering

Input parity (iOS):
- Fix DateInputView pre-populating today's date when no value specified
- Fix TimeInputView pre-populating current time when no value specified
- Both now show placeholder text until user explicitly selects a value
- Add required field suffix (* indicator) to all input labels via host config

Progress bar (iOS):
- Fix named color resolution (green, accent, attention, etc.) in ProgressBarView
- Color(hex:) was receiving named strings like "green" and falling back to black

Icon mapping (Android):
- Map "Crown" icon to WorkspacePremium instead of Star for better visual parity

App icon:
- Add custom app icon for both iOS (Assets.xcassets) and Android (mipmap resources)
- Update AndroidManifest.xml with icon and roundIcon attributes
- Add Assets.xcassets to Xcode project build phases

Sample app enhancements:
- Improved card gallery, detail screens, and Teams simulator on both platforms
- Added input renderer setup, bookmarks, settings, and performance dashboard
- Enhanced deep link navigation and self-healing test scripts

* feat(ios,android): extended deep link routing, gallery filters, cart icon, and demo script

Add full deep link navigation support (editor, performance, bookmarks, settings, more) on
both platforms with gallery category filtering via adaptivecards://gallery/{filter}. Add
cart/cartfilled icon mapping for parity. Include dual-platform demo-bookmarks.sh script for
automated bookmark walkthroughs. Update README with latest sample app features and 52 test cards.

* docs: Documentation updates with latest changes 3/11

* feat(ios,android): rename sample app to AC Visualizer

Rename the sample app from "Adaptive Cards Sample App" to
"AC Visualizer" across both platforms, including app display names,
hero headers, footer labels, Xcode target/scheme, scripts, and docs.
Verified on both iOS and Android simulators.

* refactor(ios,android): JSON-driven host config, remove ac-host-config module

Replace hardcoded TeamsHostConfig factory methods with JSON files loaded
at runtime. This aligns with the Teams-AdaptiveCards-Mobile reference
architecture where JSON is the source of truth for host configs.

Architecture changes:
- Host config JSON source of truth in shared/host-configs/{ios,android}/
- iOS TeamsHostConfig loads from bundled SPM resources (227 → 41 lines)
- Android TeamsHostConfig loads from classpath resources (497 → 44 lines)
- iOS gains dark theme support (TeamsHostConfig.createDark())
- Remove ac-host-config module, move HostConfigProvider + TeamsTheme
  into ac-rendering/theme/ — achieves 11/11 module parity
- Update 20 Android import paths
- Self-heal scripts resize screenshots to 540px for smaller file sizes

Verified: dual-platform self-heal test 38/38 pass (19 iOS + 19 Android)

* fix(ios,android): rendering parity fixes, image comparison testing, test card cleanup

iOS rendering fixes:
- CarouselView: card container with emphasis background, custom accent-colored
  page indicators, initialPage fix via async dispatch, responsive tablet padding
- TableView: apply gridStyle (good/warning/attention) background colors
- ChoiceSetInputView: filtered mode renders as typeahead text field instead of
  radio button list
- ImageView: failed images silently collapse (matching Android Coil behavior),
  unsized images fill available width (matching Android FillWidth)
- ForEach ID collisions fixed in CarouselView and TableView using index-based IDs
- CarouselPage model now decodes JSON "id" field for unique identification

Android rendering fixes:
- FactSet spacing reduced from 32dp to 8dp in both light/dark hostConfig JSON
  and FactSetConfig default, matching Figma design spec

Testing improvements:
- Dual test script uses pixel-level image comparison (compare-screenshots.py)
  for PARITY MISMATCH detection instead of file-size heuristic
- Report now includes Diff % column showing cross-platform visual similarity
- iOS app launch wait increased to 3s to reduce transient crash false positives
- Test coverage expanded to include versioned/v1.5 and v1.6 cards

Test card cleanup (655 -> 332 files, 49% reduction):
- Removed teams-samples/ (100% duplicate of templates/)
- Removed consolidated/ (duplicate of element-samples/)
- Removed versioned/v1.0-v1.4 (covered by v1.5/v1.6 superset)
- Removed 64 versioned/ files duplicating element-samples/ and official-samples/
- Removed 9 internal versioned/ duplicates and near-duplicates
- Updated iOS/Android sample app galleries to reference templates/ instead of
  teams-samples/
- Updated test scripts to reflect cleaned directory structure
…ile parity (VikrantSingh01#57) (VikrantSingh01#57)

* feat(shared): OS compat fixes, crash safety, chart parity, pre-commit hook (VikrantSingh01#57)

Backward compatibility & build config:
- Enable coreLibraryDesugaring for java.time in ac-inputs and sample-app
- Align compileSdk=34 across all modules (ac-copilot-extensions, ac-teams were 35)
- Add missing targetSdk=34 to ac-templating, ac-copilot-extensions, ac-teams

Crash fixes (Android):
- AccordionView: snapshot keys with .toList() before iterating (ConcurrentModificationException)
- CarouselView: use getOrNull() for page index (IndexOutOfBoundsException)
- DataGridInputView: add bounds checks on cell edit and date picker callbacks
- StringFunctions.substring: fix boundary case when start == str.length
- CodeBlockView: replace Toast with Snackbar, use typed getSystemService()

Crash fixes (iOS):
- CardAction: remove force unwrap on nil actionTitle
- StringFunctions.substring: align boundary case with Android (start == count returns "")
- CarouselView: add UIKit import guard for UIScreen in SPM builds

Parity fixes:
- Wire chart rendering in Android (BarChart, DonutChart, LineChart, PieChart)
- Add ac-charts dependency to ac-rendering module
- Add Badge and Icon to Android SchemaValidator VALID_ELEMENT_TYPES

Pre-commit hook (.githooks/pre-commit):
- 35+ rules across Swift (S1-S14), Kotlin (K1-K20), Gradle (G1-G3),
  JSON (J1-J2), cross-platform parity (P1-P5), and general (A1-A3)
- Inline suppression via // safe: or // pre-commit:allow comments
- Multi-line detection for remember{mutableStateOf}, @volatile annotations,
  @Suppress("UNCHECKED_CAST"), and KDoc comment filtering
- Install: git config core.hooksPath .githooks

* fix(ios,android): ProgressBar max/value normalization, split AdvancedElements into 1:1 files

- Add `max` property to ProgressBar model (iOS + Android) for absolute value scales
- Add `normalizedValue` computed property: auto-detects 0–1 fractional vs 0–100 scale
- Update renderers to use normalizedValue for bar width, percentage text, accessibility
- Split Android AdvancedElements.kt monolith into 9 focused files matching iOS structure:
  Accordion, Carousel, ChartElements, CodeBlock, CompoundButton, ListElement,
  ProgressElements, RatingElements, TabSet
…01#58)

* feat(shared): OS compat fixes, crash safety, chart parity, pre-commit hook (VikrantSingh01#57)

Backward compatibility & build config:
- Enable coreLibraryDesugaring for java.time in ac-inputs and sample-app
- Align compileSdk=34 across all modules (ac-copilot-extensions, ac-teams were 35)
- Add missing targetSdk=34 to ac-templating, ac-copilot-extensions, ac-teams

Crash fixes (Android):
- AccordionView: snapshot keys with .toList() before iterating (ConcurrentModificationException)
- CarouselView: use getOrNull() for page index (IndexOutOfBoundsException)
- DataGridInputView: add bounds checks on cell edit and date picker callbacks
- StringFunctions.substring: fix boundary case when start == str.length
- CodeBlockView: replace Toast with Snackbar, use typed getSystemService()

Crash fixes (iOS):
- CardAction: remove force unwrap on nil actionTitle
- StringFunctions.substring: align boundary case with Android (start == count returns "")
- CarouselView: add UIKit import guard for UIScreen in SPM builds

Parity fixes:
- Wire chart rendering in Android (BarChart, DonutChart, LineChart, PieChart)
- Add ac-charts dependency to ac-rendering module
- Add Badge and Icon to Android SchemaValidator VALID_ELEMENT_TYPES

Pre-commit hook (.githooks/pre-commit):
- 35+ rules across Swift (S1-S14), Kotlin (K1-K20), Gradle (G1-G3),
  JSON (J1-J2), cross-platform parity (P1-P5), and general (A1-A3)
- Inline suppression via // safe: or // pre-commit:allow comments
- Multi-line detection for remember{mutableStateOf}, @volatile annotations,
  @Suppress("UNCHECKED_CAST"), and KDoc comment filtering
- Install: git config core.hooksPath .githooks

* fix(ios,android): ProgressBar max/value normalization, split AdvancedElements into 1:1 files

- Add `max` property to ProgressBar model (iOS + Android) for absolute value scales
- Add `normalizedValue` computed property: auto-detects 0–1 fractional vs 0–100 scale
- Update renderers to use normalizedValue for bar width, percentage text, accessibility
- Split Android AdvancedElements.kt monolith into 9 focused files matching iOS structure:
  Accordion, Carousel, ChartElements, CodeBlock, CompoundButton, ListElement,
  ProgressElements, RatingElements, TabSet


* fix(android): resolve 3 serialization crashes affecting 23 cards

- CompoundButton.icon: handle both string and object JSON forms via
  IconDescriptor + IconDescriptorSerializer (10 cards)
- Image.themedUrls: gracefully skip JSON arrays in CardElementSerializer
  pre-processing (2 cards)
- RichTextBlock inlines: support plain string shorthand via
  TextRunSerializer per Adaptive Cards spec (1 card)
- iOS: themedUrls array tolerance, ImageView/gallery improvements
- self-heal-dual.sh: app-alive wait loops, gallery-baseline retry checks
- Rename test card to remove '&' from filename
* fix(ios): resolve all card parsing failures + add xcodeproj to repo

Self-healing loop: ran CardParsingRegressionTests against 634 cards,
found 60+ parsing failures, fixed ALL to 0 failures.

Parsing fixes:
- CaseInsensitiveCodable: fallback to default instead of throwing
  (handles template expressions like ${if(...)})
- CompoundButton.icon: accept both string and {name,size,color} object
- RichTextBlock.inlines: accept plain strings as TextRun shorthand
- CardElement.fallback: handle "drop" string per AC spec
- TextBlock.text: make optional (some cards omit it)
- ProgressBar.value: make optional
- ActionStyle: add "other" case
- CardAction: add .unknown case for graceful fallback
- TargetElement: accept string shorthand
- Input.isRequired: decode from string "true"/"false"
- AdaptiveCard.body/actions: skip non-array values gracefully
- Image.themedUrls: handle array format
- Carousel.pages: handle template string expressions
- PopoverAction.popoverBody: make optional

Repo changes:
- Add ios/SampleApp.xcodeproj to git (exception in .gitignore)
- Add CardParsingRegressionTests (4 test groups, 634 cards)
- Add test scripts: auto-test-ios-cards.sh, test-ios-cards-visual.sh

* feat(ios): deep link navigation + visual test loop for automated card testing

- Add adaptivecards://card/{path} URL scheme for programmatic navigation
- DeepLinkRouter handles URL → card detail view via fullScreenCover
- visual-test-loop.sh: automated screenshot capture for all Teams Official cards
  Uses simctl openurl + simctl io screenshot — no accessibility permissions needed
- All 19 Teams Official cards render successfully (visual verification)

Remaining minor issues (tracked for future):
- Badge element type not yet supported (shows "Unknown element type: Badge")
- Some Fluent icon names need additional SF Symbol mappings
- Network images (person photos, hero images) depend on connectivity

* docs: add sample app deep link testing and visual test loop to CLAUDE.md

Documents the adaptivecards:// URL scheme, automated visual test loop,
and card parsing regression test commands for developer reference.

* feat(testing): add self-healing iOS card test loop command

bash shared/scripts/self-heal-ios.sh — full automated test cycle:
  Phase 1: Parse regression (swift test --filter CardParsingRegressionTests)
  Phase 2: Visual smoke (deep-link → screenshot → analyze each card)
  Phase 3: Markdown report with per-card status + screenshots

Modes: --parse-only, --visual-only, --card <name>
Results: 19/19 Teams Official cards pass (0 failures)

* feat(testing): add self-healing test loops for iOS and Android

Add automated detect → diagnose → recover → fix test scripts for both
platforms. Each runs a 6-phase cycle: parse regression tests, visual
smoke tests with deep-link navigation and screenshots, multi-signal
crash/hang/OOM diagnosis from simulator logs (iOS) or logcat (Android),
auto-retry with escalating recovery, structured fix suggestions with
file-level hints, and a rich markdown report with all artifacts.

iOS script uses xcrun simctl + system log mining; Android script uses
adb + logcat analysis. Both support --parse-only, --visual-only,
--card, --retry, and --category flags.

* feat(ios,android): rendering fixes, input parity, and sample app improvements

Container rendering:
- Add showBorder and roundedCorners support to Container model and view on both platforms
- Render border stroke using host config borderColor when showBorder is true

Image rendering (Android):
- Fix Auto-sized images to fill container width per AC spec (fillMaxWidth)
- Use FillWidth content scale for aspect-ratio-preserving full-width images
- Add RoundedCorners image style enum and 8dp corner radius rendering

Input parity (iOS):
- Fix DateInputView pre-populating today's date when no value specified
- Fix TimeInputView pre-populating current time when no value specified
- Both now show placeholder text until user explicitly selects a value
- Add required field suffix (* indicator) to all input labels via host config

Progress bar (iOS):
- Fix named color resolution (green, accent, attention, etc.) in ProgressBarView
- Color(hex:) was receiving named strings like "green" and falling back to black

Icon mapping (Android):
- Map "Crown" icon to WorkspacePremium instead of Star for better visual parity

App icon:
- Add custom app icon for both iOS (Assets.xcassets) and Android (mipmap resources)
- Update AndroidManifest.xml with icon and roundIcon attributes
- Add Assets.xcassets to Xcode project build phases

Sample app enhancements:
- Improved card gallery, detail screens, and Teams simulator on both platforms
- Added input renderer setup, bookmarks, settings, and performance dashboard
- Enhanced deep link navigation and self-healing test scripts

* feat(ios,android): extended deep link routing, gallery filters, cart icon, and demo script

Add full deep link navigation support (editor, performance, bookmarks, settings, more) on
both platforms with gallery category filtering via adaptivecards://gallery/{filter}. Add
cart/cartfilled icon mapping for parity. Include dual-platform demo-bookmarks.sh script for
automated bookmark walkthroughs. Update README with latest sample app features and 52 test cards.

* docs: Documentation updates with latest changes 3/11

* feat(ios,android): rename sample app to AC Visualizer

Rename the sample app from "Adaptive Cards Sample App" to
"AC Visualizer" across both platforms, including app display names,
hero headers, footer labels, Xcode target/scheme, scripts, and docs.
Verified on both iOS and Android simulators.

* refactor(ios,android): JSON-driven host config, remove ac-host-config module

Replace hardcoded TeamsHostConfig factory methods with JSON files loaded
at runtime. This aligns with the Teams-AdaptiveCards-Mobile reference
architecture where JSON is the source of truth for host configs.

Architecture changes:
- Host config JSON source of truth in shared/host-configs/{ios,android}/
- iOS TeamsHostConfig loads from bundled SPM resources (227 → 41 lines)
- Android TeamsHostConfig loads from classpath resources (497 → 44 lines)
- iOS gains dark theme support (TeamsHostConfig.createDark())
- Remove ac-host-config module, move HostConfigProvider + TeamsTheme
  into ac-rendering/theme/ — achieves 11/11 module parity
- Update 20 Android import paths
- Self-heal scripts resize screenshots to 540px for smaller file sizes

Verified: dual-platform self-heal test 38/38 pass (19 iOS + 19 Android)

* fix(ios,android): rendering parity fixes, image comparison testing, test card cleanup

iOS rendering fixes:
- CarouselView: card container with emphasis background, custom accent-colored
  page indicators, initialPage fix via async dispatch, responsive tablet padding
- TableView: apply gridStyle (good/warning/attention) background colors
- ChoiceSetInputView: filtered mode renders as typeahead text field instead of
  radio button list
- ImageView: failed images silently collapse (matching Android Coil behavior),
  unsized images fill available width (matching Android FillWidth)
- ForEach ID collisions fixed in CarouselView and TableView using index-based IDs
- CarouselPage model now decodes JSON "id" field for unique identification

Android rendering fixes:
- FactSet spacing reduced from 32dp to 8dp in both light/dark hostConfig JSON
  and FactSetConfig default, matching Figma design spec

Testing improvements:
- Dual test script uses pixel-level image comparison (compare-screenshots.py)
  for PARITY MISMATCH detection instead of file-size heuristic
- Report now includes Diff % column showing cross-platform visual similarity
- iOS app launch wait increased to 3s to reduce transient crash false positives
- Test coverage expanded to include versioned/v1.5 and v1.6 cards

Test card cleanup (655 -> 332 files, 49% reduction):
- Removed teams-samples/ (100% duplicate of templates/)
- Removed consolidated/ (duplicate of element-samples/)
- Removed versioned/v1.0-v1.4 (covered by v1.5/v1.6 superset)
- Removed 64 versioned/ files duplicating element-samples/ and official-samples/
- Removed 9 internal versioned/ duplicates and near-duplicates
- Updated iOS/Android sample app galleries to reference templates/ instead of
  teams-samples/
- Updated test scripts to reflect cleaned directory structure
…ut.DataGrid, and rendering parity fixes

Cross-platform parity update adding new action types (Action.Popover, Action.RunCommands,
Action.OpenUrlDialog), Input.DataGrid element, and rendering improvements across ImageView,
RichTextBlockView, CompoundButtonView, ActionSetView, TableView, and TemplateEngine on both
platforms. Updates schema validators, test cards, and parity matrix.
…ut.DataGrid, and rendering parity fixes (VikrantSingh01#60)

Cross-platform parity update adding new action types (Action.Popover, Action.RunCommands,
Action.OpenUrlDialog), Input.DataGrid element, and rendering improvements across ImageView,
RichTextBlockView, CompoundButtonView, ActionSetView, TableView, and TemplateEngine on both
platforms. Updates schema validators, test cards, and parity matrix.
…sing

- Action.Popover: generate fallback ID when action has no id field,
  fixing popover not opening on Android (iOS already had this)
- Icon resolution: strip ",Filled"/",Regular" style suffix from
  icon:Name,Style format before lookup on both platforms
- Add ArrowReset and ToggleLeft icon mappings on both platforms
- Use firstOrNull() instead of first() in icon suffix stripping to
  avoid potential exception on empty strings (K5 warning)
- Apply same icon suffix stripping fix to ac-actions ActionButton.kt
  (duplicate resolver that was also missing the ,Filled handling)
- Add ArrowReset and ToggleLeft mappings to ac-actions icon table
… icon mappings (VikrantSingh01#61)

- Action.Popover: generate fallback ID ("popover_{title}") when action
  has no id field — fixes popover not opening on Android
- Icon resolution: strip ",Filled"/",Regular" style suffix from
  "icon:Name,Style" format before lookup on all 3 icon resolvers
  (iOS ActionButton, Android ac-rendering, Android ac-actions)
- Add ArrowReset and ToggleLeft icon mappings on both platforms
- Use firstOrNull() for safe icon suffix splitting on Android
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…legate wiring

- Add action-test-loop.sh for dual-platform E2E action card testing (25 cards)
- Fix Android ActionSetView overflow: replace Row with FlowRow so buttons
  wrap to next line instead of being squeezed with vertical text
- Wire ActionDelegate/LoggingActionHandler in both sample apps for action logging
- Add edge-action-crashes.json test card and ACActionsTests
- Register action-overflow and edge-action-crashes in both card loaders
- Screenshot-based pass/fail validation (no false crash detection)
…links

Add action-invoke-test.sh that navigates to action cards, programmatically
triggers every action button, and verifies no crash + correct UX response.

Both platforms now support adaptivecards://tap-action/{title} deep links
that trigger card actions by title, enabling reliable test automation
without fragile coordinate-based UI tapping.

iOS: AdaptiveCardView accepts pendingActionTitle binding, finds the action
by title in the parsed card, and invokes it via ActionHandler with full
CardViewModel access (ShowCard, Popover, ToggleVisibility all work).

Android: Same approach via MutableState<String?> parameter plumbed from
MainActivity → CardDetailScreen → AdaptiveCardView. handleAction and
collectAllActionsForCard made public for cross-module access.

Script features:
- Dual-platform (iOS + Android) action invocation testing
- JSON parsing to extract all actions (card-level + body ActionSets)
- Android: uiautomator dump with Compose parent-traversal for button
  finding, overflow menu handling, fd-based loop to prevent stdin
  consumption by child processes
- iOS: deep link approach (100% reliable vs coordinate estimation)
- Pre/post screenshot comparison for visual action UX verification
- Visual actions (ShowCard, ToggleVisibility, Popover) must change screen
Update README files to reference ACVisualizer (correct scheme name)
instead of outdated AdaptiveCardsSample. Increase demo-bookmarks.sh
wait times for performance dashboard and more page.
Adds the standard 3-line copyright header to all 319 source files:
Swift, Kotlin, shell scripts, Python scripts, YAML CI workflows,
and the pre-commit hook.
Moved video to a published GitHub release asset (MP4 format) and
use a bare URL in README so GitHub renders it as an inline player.
Removed the 26MB .mov from the repo tree.
Show an inline poster image extracted from the demo video.
Clicking the thumbnail downloads the full MP4 from GitHub Releases.
VikrantSingh01 and others added 29 commits March 15, 2026 11:03
…erlap

The markdown renderer used absolute SwiftUI semantic fonts (.title,
.title2, .title3) for header tokens, ignoring the TextBlock's configured
font size. This caused the header text to be much larger than the
allocated space, resulting in overlapping text artifacts. Now uses the
base font with bold applied, matching the TextBlock's own size/weight
properties. Aligns with Android's approach of respecting the base font.

Issue VikrantSingh01#6, VikrantSingh01#20
…ncation

Long cards with multiple ActionSets (e.g., ActionModeTestCard) were
truncated because the card body VStack was clipped without scrolling.
Android uses verticalScroll() for internal scrolling. Now wraps the
card body in ScrollView to match Android behavior, allowing all content
to be accessible via scrolling.

Issue VikrantSingh01#9
…Flow navigation

Navigation Compose 2.7.x route matching fails for filenames with multiple
dots (e.g. Container.Nested.Flow.json). Uri.encode leaves dots unencoded
since they are RFC 3986 unreserved characters, but the dots confuse
Navigation's internal route matching. Manually encoding dots as %2E
prevents this while Uri.decode on the receive side correctly decodes them.
…lView

The DataGrid only showed the header row because a nested
ScrollView(.vertical) inside ScrollView(.horizontal) caused the inner
scroll view to render with zero height. Removed the inner vertical
ScrollView and render data rows directly in the VStack, matching
Android's approach. The card-level ScrollView handles overflow.

Issue VikrantSingh01#10
…P 403

Servers like Wikipedia block requests without a proper User-Agent header,
causing Coil to silently fail with HTTP 403. This made the hero image
invisible in the InputForm card (and potentially other cards with
images from strict servers).

Issue VikrantSingh01#3: Hero image (skier) missing from Android InputForm
The project-dashboard card uses AreaGrid with columns: [50] but areas
referencing column 2. Android's AreaGridLayoutView used columns.size for
columnCount (=1), giving column 2 a minimal weight of 1 vs 50, squeezing
content to ~2% width and pushing everything below off-screen.

iOS correctly uses max(columns.count, maxAreaColumn) to infer the actual
column count. This fix preprocesses the AreaGridLayout in ContainerView
to expand the columns list when areas reference columns beyond the
defined range, distributing remaining width equally to missing columns.

Fixes truncation of ~70% of content in deeply nested cards like
teams-official-samples/project-dashboard.
Action button icons loaded via AsyncImage in ActionSetView were using
plain URL strings without User-Agent headers, causing HTTP 403 from
servers like Wikipedia that require proper User-Agent. Now builds a
proper ImageRequest with User-Agent header, matching the fix in ImageView.

Issue VikrantSingh01#8: Android action button icons missing for themed URLs
… columns

Images with height="auto" and width="auto" (no fitMode) were always
constrained to a 52x52dp square, making them tiny compared to iOS which
renders them at natural size filling the container width. Now only applies
the medium-size constraint in auto-width columns where it prevents layout
expansion; in other contexts, fills available width matching iOS behavior.

Issue VikrantSingh01#12: Different number of image examples visible between platforms
Align chevron to fixed 20pt size with 0.6 opacity (matching Android 20dp)
instead of font-based sizing. Increase minHeight from 44 to 48 to match
Android, improving intrinsic size parity for flow layout wrapping.

Issue VikrantSingh01#8: CompoundButton chevron/icon parity
Standalone clickable icons (direct children of card body) were centered
on iOS due to no frame being applied when horizontalAlignment was nil.
Android naturally left-aligns icons in a Column. Now iOS always applies
frame with maxWidth .infinity and leading alignment by default.

Issue VikrantSingh01#10
Android AdaptiveCardView had verticalScroll on the inner Column, which
conflicted with the sample app scrollable parent container (nested scroll
issue). This caused content to be clipped after Action 4 on long cards
like ActionModeTestCard. Removed inner verticalScroll to let the card
expand to intrinsic content height, matching iOS pattern where the parent
handles scrolling.

Issue VikrantSingh01#11
Remove the 1/3 width cap in ActionFlowLayout that was truncating long
button labels like 'Invalid icon does not render'. Now matches Android
FlowRow behavior where buttons take natural width and wrap to next row.
Individual buttons are still capped to available width to prevent overflow.

Issue VikrantSingh01#15: Button text truncated on iOS but fully visible on Android
…nd icon

Action.ResetInputs was falling to .unknown(type:) case which has no title/iconUrl
properties, causing buttons to render as empty unlabeled squares. Added ResetInputsAction
struct with full base action properties and targetInputIds support.
The User-Agent header added in 2530dee was lost during a merge/rebase.
Servers like Wikipedia block requests without a proper User-Agent header
(HTTP 403), causing the scuba diver image to be invisible in the
input-form-official card.

Issue VikrantSingh01#5: Android missing scuba diver column image in input form cards
…r rendering

Individual images in an ImageSet had no size property, causing ImageView to use
nil width/height and render a 0x0 placeholder. Now copies the ImageSet imageSize
onto each image before rendering, matching Android behavior.
…h iOS

Android was using Modifier.size() for Small/Medium/Large images, which
constrains both width AND height to the same value (e.g., 52x52 for
Medium). This caused portrait-oriented images to render ~20-30% smaller
than iOS, which only constrains width and lets height be proportional.

Changed to Modifier.width() for all named sizes to match iOS behavior.

Issue VikrantSingh01#14: Force-load images render smaller on Android than iOS
Added mappings for Calendar, ImageCircle, Important, Tag, TooltipQuote,
ArrowSync, Checkmark, People, Megaphone, Receipt, Cart, Design to Material
Icons. Previously these all rendered as the generic Label placeholder.
When isMultiSelect is true and style is compact, iOS was rendering
inline checkboxes (expanded-like). Android renders this as a compact
dropdown picker. Changed iOS multiSelectCompactView to use a Menu
dropdown matching Android behavior, with a summary of selected items
shown in the collapsed state.

Issue VikrantSingh01#9
# Conflicts:
#	android/ac-rendering/src/main/kotlin/com/microsoft/adaptivecards/rendering/composables/BadgeView.kt
…overflow

CardDetailScreen: add fallback lookup for .template.json files when deep link
resolves to .json — fixes templates/WeatherLarge and other template cards
showing "Empty JSON string".

ImageView: remove heightIn(min:) from Stretch sizing and use FillWidth content
scale instead of Crop — prevents weather icon images from growing unbounded
in weighted columns.
Cards were vertically centered in the detail view due to SwiftUI default
frame alignment. Short cards appeared floating in the middle of the screen.
Added alignment: .topLeading to pin content to the top.
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.

3 participants