-
Notifications
You must be signed in to change notification settings - Fork 334
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: [CustomerCenter] Introduce CompatibilityLabeledContent (#4659)
- Loading branch information
1 parent
d86e100
commit 174e685
Showing
1 changed file
with
113 additions
and
0 deletions.
There are no files selected for viewing
113 changes: 113 additions & 0 deletions
113
RevenueCatUI/CustomerCenter/Views/CompatibilityLabeledContent.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
// | ||
// Copyright RevenueCat Inc. All Rights Reserved. | ||
// | ||
// Licensed under the MIT License (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://opensource.org/licenses/MIT | ||
// | ||
// CompatibilityLabeledContent.swift | ||
// | ||
// | ||
// Created by Facundo Menzella on 14/1/25. | ||
// | ||
|
||
import SwiftUI | ||
|
||
#if os(iOS) | ||
|
||
/// A SwiftUI view that displays a label and content in a layout that adapts to the iOS version. | ||
/// | ||
/// This view is designed to be compatible with both iOS 16.0+ and earlier versions. | ||
/// | ||
/// - Parameters: | ||
/// - label: A closure that returns the label view, typically a `Text` or any other view. | ||
/// - content: A closure that returns the content view | ||
/// | ||
/// ## Usage: | ||
/// ```swift | ||
/// CompatibilityLabeledContent { | ||
/// Text("Name:") | ||
/// } content: { | ||
/// Text("John Doe") | ||
/// } | ||
/// ``` | ||
/// | ||
/// ## Available Initializers: | ||
/// - `init(_ label: String, content: @escaping () -> Content)` for easy usage with `String` labels. | ||
/// - `init(_ label: String, content: String)` for cases where both the label and content are strings. | ||
/// | ||
/// ## iOS 16.0 and higher: | ||
/// Uses `LabeledContent` to display the label and content in a more advanced and consistent way. | ||
/// | ||
/// ## Earlier OS versions: | ||
/// Uses a simple `HStack` to display the label and content, ensuring backward compatibility. | ||
/// | ||
/// ## Discussion: | ||
/// Although the `label` is a closure that returns a view (`() -> Label`), it is **not marked with `@ViewBuilder` | ||
/// intentionally** for backwards compatibility. | ||
/// | ||
/// If you need to pass multiple views in the label, you can still compose them manually using `HStack` or other layout | ||
/// views in the closure passed to `label`. For example: | ||
/// ```swift | ||
/// CompatibilityLabeledContent("Name") { | ||
/// HStack { | ||
/// Text("First Name") | ||
/// Text("Last Name") | ||
/// } | ||
/// } content: { | ||
/// Text("John Doe") | ||
/// } | ||
/// ``` | ||
@available(iOS 15.0, *) | ||
@available(macOS, unavailable) | ||
@available(tvOS, unavailable) | ||
@available(watchOS, unavailable) | ||
struct CompatibilityLabeledContent<Label: View, Content: View>: View { | ||
|
||
let label: () -> Label | ||
let content: () -> Content | ||
|
||
var body: some View { | ||
if #available(iOS 16.0, *) { | ||
LabeledContent { | ||
content() | ||
} label: { | ||
label() | ||
} | ||
} else { | ||
HStack { | ||
label() | ||
|
||
Spacer() | ||
|
||
content() | ||
} | ||
} | ||
} | ||
} | ||
|
||
@available(iOS 15.0, *) | ||
@available(macOS, unavailable) | ||
@available(tvOS, unavailable) | ||
@available(watchOS, unavailable) | ||
extension CompatibilityLabeledContent where Label == Text { | ||
init(_ label: String, @ViewBuilder content: @escaping () -> Content) { | ||
self.label = { Text(label) } | ||
self.content = content | ||
} | ||
} | ||
|
||
@available(iOS 15.0, *) | ||
@available(macOS, unavailable) | ||
@available(tvOS, unavailable) | ||
@available(watchOS, unavailable) | ||
extension CompatibilityLabeledContent where Label == Text, Content == Text { | ||
init(_ label: String, content: String) { | ||
self.label = { Text(label) } | ||
self.content = { Text(content) } | ||
} | ||
} | ||
|
||
#endif |