Fix segmented Text
This commit is contained in:
parent
cb6359431d
commit
c0a580653a
|
@ -33,14 +33,11 @@ public struct Text: View {
|
|||
let storage: _Storage
|
||||
let modifiers: [_Modifier]
|
||||
|
||||
@Environment(\.self) public var environment
|
||||
@Environment(\.font) var font
|
||||
@Environment(\.foregroundColor) var foregroundColor
|
||||
@Environment(\.redactionReasons) var redactionReasons
|
||||
@Environment(\.self) var environment
|
||||
|
||||
public enum _Storage {
|
||||
case verbatim(String)
|
||||
case segmentedText([Text])
|
||||
case segmentedText([(_Storage, [_Modifier])])
|
||||
}
|
||||
|
||||
public enum _Modifier: Equatable {
|
||||
|
@ -59,8 +56,7 @@ public struct Text: View {
|
|||
init(storage: _Storage, modifiers: [_Modifier] = []) {
|
||||
if case let .segmentedText(segments) = storage {
|
||||
self.storage = .segmentedText(segments.map {
|
||||
Self(storage: $0.storage,
|
||||
modifiers: modifiers + $0.modifiers)
|
||||
($0.0, modifiers + $0.1)
|
||||
})
|
||||
} else {
|
||||
self.storage = storage
|
||||
|
@ -81,6 +77,19 @@ public struct Text: View {
|
|||
}
|
||||
}
|
||||
|
||||
extension Text._Storage {
|
||||
public var rawText: String {
|
||||
switch self {
|
||||
case let .segmentedText(segments):
|
||||
return segments
|
||||
.map { $0.0.rawText }
|
||||
.reduce("", +)
|
||||
case let .verbatim(text):
|
||||
return text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This is a helper class that works around absence of "package private" access control in Swift
|
||||
public struct _TextProxy {
|
||||
public let subject: Text
|
||||
|
@ -89,24 +98,17 @@ public struct _TextProxy {
|
|||
|
||||
public var storage: Text._Storage { subject.storage }
|
||||
public var rawText: String {
|
||||
switch subject.storage {
|
||||
case let .segmentedText(segments):
|
||||
return segments
|
||||
.map { Self($0).rawText }
|
||||
.reduce("", +)
|
||||
case let .verbatim(text):
|
||||
return text
|
||||
}
|
||||
subject.storage.rawText
|
||||
}
|
||||
|
||||
public var modifiers: [Text._Modifier] {
|
||||
[
|
||||
.font(subject.font),
|
||||
.color(subject.foregroundColor),
|
||||
.font(subject.environment.font),
|
||||
.color(subject.environment.foregroundColor),
|
||||
] + subject.modifiers
|
||||
}
|
||||
|
||||
public var redactionReasons: RedactionReasons { subject.redactionReasons }
|
||||
public var environment: EnvironmentValues { subject.environment }
|
||||
}
|
||||
|
||||
public extension Text {
|
||||
|
@ -149,6 +151,9 @@ public extension Text {
|
|||
|
||||
extension Text {
|
||||
public static func _concatenating(lhs: Self, rhs: Self) -> Self {
|
||||
.init(storage: .segmentedText([lhs, rhs]))
|
||||
.init(storage: .segmentedText([
|
||||
(lhs.storage, lhs.modifiers),
|
||||
(rhs.storage, rhs.modifiers),
|
||||
]))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,14 +89,28 @@ extension Font: StylesConvertible {
|
|||
}
|
||||
}
|
||||
|
||||
private struct TextSpan: AnyHTML {
|
||||
let content: String
|
||||
let attributes: [String: String]
|
||||
|
||||
var innerHTML: String? { content }
|
||||
var tag: String { "span" }
|
||||
}
|
||||
|
||||
extension Text: AnyHTML {
|
||||
public var innerHTML: String? {
|
||||
switch _TextProxy(self).storage {
|
||||
let proxy = _TextProxy(self)
|
||||
switch proxy.storage {
|
||||
case let .verbatim(text):
|
||||
return text
|
||||
case let .segmentedText(segments):
|
||||
return segments
|
||||
.map(\.outerHTML)
|
||||
.map {
|
||||
TextSpan(content: $0.0.rawText,
|
||||
attributes: Self.attributes(from: $0.1,
|
||||
environment: proxy.environment))
|
||||
.outerHTML
|
||||
}
|
||||
.reduce("", +)
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +118,15 @@ extension Text: AnyHTML {
|
|||
public var tag: String { "span" }
|
||||
public var attributes: [String: String] {
|
||||
let proxy = _TextProxy(self)
|
||||
let isRedacted = proxy.redactionReasons.contains(.placeholder)
|
||||
return Self.attributes(from: proxy.modifiers,
|
||||
environment: proxy.environment)
|
||||
}
|
||||
}
|
||||
|
||||
extension Text {
|
||||
static func attributes(from modifiers: [_Modifier],
|
||||
environment: EnvironmentValues) -> [String: String] {
|
||||
let isRedacted = environment.redactionReasons.contains(.placeholder)
|
||||
|
||||
var font: Font?
|
||||
var color: Color?
|
||||
|
@ -114,7 +136,7 @@ extension Text: AnyHTML {
|
|||
var baseline: CGFloat?
|
||||
var strikethrough: (Bool, Color?)?
|
||||
var underline: (Bool, Color?)?
|
||||
for modifier in proxy.modifiers {
|
||||
for modifier in modifiers {
|
||||
switch modifier {
|
||||
case let .color(_color):
|
||||
color = _color
|
||||
|
|
Loading…
Reference in New Issue