Add PaywallWarning model and validation documentation#6341
Conversation
Adds ColorComputationHelpers.swift with pure utility functions for: - WCAG 2.1 relative luminance and contrast ratio calculations - sRGB linearization (gamma correction removal) - Platform-agnostic RGB component extraction - Best-contrast color selection from a candidate set These will be used by the upcoming fallback paywall to adaptively choose text colors with sufficient contrast against backgrounds. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds AppStyleExtractor which extracts the app icon, display name, and prominent colors from the host app bundle. Uses pixel sampling with color quantization to identify 1-2 dominant colors from the app icon, filtering transparent/extreme brightness pixels. Also adds: - DualColorImageGenerator (DEBUG only) for creating deterministic test images with known color splits - AppStyleExtractorTests covering accuracy for multiple color combinations and edge cases (nil, transparent, dark/bright) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nto jzdesign/fallback-paywall-2-app-style-extractor
Remove unreachable non-static instance methods from ColorComputationHelpers enum (dead code left over from global-to-enum conversion). Update tests to use qualified ColorComputationHelpers.method() calls. Co-authored-by: Cursor <cursoragent@cursor.com>
8e25223 to
606081b
Compare
…nto jzdesign/fallback-paywall-2-app-style-extractor
|
The Set ordering in Consider sorting before joining: case .invalidVariables(let set):
return "The following variables are not recognized: \(set.sorted().joined(separator: ", "))..."
case .invalidIcons(let set):
return "The following icon names are not valid: \(set.sorted().joined(separator: ", "))..."This ensures consistent UX and avoids potential flaky snapshot tests if the warning UI is ever snapshotted. |
- Add @mainactor to AppIconDetailProvider since it is an ObservableObject with @published properties - Add #if !os(watchOS) guards in AppStyleExtractor for icon loading — watchOS app icons are system-managed with no runtime API to load them - Fix toAppIconDetailprovider -> toAppIconDetailProvider typo Co-authored-by: Cursor <cursoragent@cursor.com>
606081b to
5e9167b
Compare
5e9167b to
4202bca
Compare
Adds PaywallWarning enum that maps PaywallValidationError cases to user-facing titles, body text, and help URLs linking to the RevenueCat dashboard or docs. This model will power the debug warning banner in the upcoming fallback paywall. Also adds comprehensive documentation to PaywallData+Validation.swift explaining each validation error case, when it occurs, and how to resolve it. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix "Unkown" -> "Unknown" in invalidTemplate title. Add .missingLocalization to the helpURL case group so it returns the paywalls docs URL instead of nil. Co-authored-by: Cursor <cursoragent@cursor.com>
4202bca to
1f253ce
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
| case .invalidVariables: | ||
| return URL(string: "https://www.revenuecat.com/docs/tools/paywalls/creating-paywalls/variables") | ||
| default: | ||
| return nil |
There was a problem hiding this comment.
Missing help links for some warnings
Low Severity
helpURL falls through to nil for invalidTemplate and invalidIcons, so those validation warnings have no documentation link while other paywall validation warnings do. This creates inconsistent warning behavior and removes in-context guidance for two known error cases.
There was a problem hiding this comment.
This are not things that the user can work on, so no link was Hidde's thought IIRC
* Add color computation helpers for WCAG-compliant contrast calculations Adds ColorComputationHelpers.swift with pure utility functions for: - WCAG 2.1 relative luminance and contrast ratio calculations - sRGB linearization (gamma correction removal) - Platform-agnostic RGB component extraction - Best-contrast color selection from a candidate set These will be used by the upcoming fallback paywall to adaptively choose text colors with sufficient contrast against backgrounds. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Add app style extractor for icon color extraction Adds AppStyleExtractor which extracts the app icon, display name, and prominent colors from the host app bundle. Uses pixel sampling with color quantization to identify 1-2 dominant colors from the app icon, filtering transparent/extreme brightness pixels. Also adds: - DualColorImageGenerator (DEBUG only) for creating deterministic test images with known color splits - AppStyleExtractorTests covering accuracy for multiple color combinations and edge cases (nil, transparent, dark/bright) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * PR Feedback * Create AppIconDetailProvider.swift * Update project.pbxproj * Remove duplicate instance methods and qualify test calls Remove unreachable non-static instance methods from ColorComputationHelpers enum (dead code left over from global-to-enum conversion). Update tests to use qualified ColorComputationHelpers.method() calls. Co-authored-by: Cursor <cursoragent@cursor.com> * Add @mainactor, fix watchOS icon guards, fix typo - Add @mainactor to AppIconDetailProvider since it is an ObservableObject with @published properties - Add #if !os(watchOS) guards in AppStyleExtractor for icon loading — watchOS app icons are system-managed with no runtime API to load them - Fix toAppIconDetailprovider -> toAppIconDetailProvider typo Co-authored-by: Cursor <cursoragent@cursor.com> * correct use of main actor * address cursor comment about brightness filter * import Combine needed for watchos to compile and build -> @published * Add PaywallWarning model and validation documentation Adds PaywallWarning enum that maps PaywallValidationError cases to user-facing titles, body text, and help URLs linking to the RevenueCat dashboard or docs. This model will power the debug warning banner in the upcoming fallback paywall. Also adds comprehensive documentation to PaywallData+Validation.swift explaining each validation error case, when it occurs, and how to resolve it. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Fix typo and add missing helpURL for missingLocalization Fix "Unkown" -> "Unknown" in invalidTemplate title. Add .missingLocalization to the helpURL case group so it returns the paywalls docs URL instead of nil. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com>


Summary
PaywallWarningenum mappingPaywallValidationErrorcases to user-facing titles, body text, and help URLs (RevenueCat dashboard/docs links)PaywallData+Validation.swiftexplaining each error case, when it occurs, and how to resolve itStacked PRs breaking up #5930
This is PR 3 of 5 for the fallback paywall feature:
Test plan
🤖 Generated with Claude Code
Note
Low Risk
Low risk: adds a new warning model and documentation only, with no changes to paywall validation logic or runtime behavior.
Overview
Adds a new
PaywallWarningenum that convertsOffering.PaywallValidationError(and a few non-validation states like missing offering/products) into user-facingtitle,bodyText, and optionalhelpURLfor linking to relevant RevenueCat docs.Expands inline documentation for
PaywallValidationErrorinPaywallData+Validation.swift, describing when each validation error occurs and how fallback paywall behavior is handled.Written by Cursor Bugbot for commit d3cc5f4. This will update automatically on new commits. Configure here.