Open alelordelo opened 8 months ago
Hi @alelordelo
Can you try this with the main
branch? There was a font bug that causes styles to be ignored.
hi @danielsaidi, just tried now but didn't work also...
RichTextEditor render rich text fine when editing, but not when read from database.
Any idea why this read the rich text attributes, but RichTextEditor not? Text(AttributedString(cellViewModel.richTextContent))
I found a bug in the theming, and disabled applying the theme if the string's not empty...but perhaps something else needs to be fixed as well.
Just to clarify, how do you serialize? If you only serialize the raw string, the format will be thrown away. Have a look at the demo, and see how it persists to file.
hey @danielsaidi
So, this is basically my workflow:
Editing works fine
RichTextEditor(text: $viewModel.richTextContent, context: cellViewModel.context) { _ in }
Serialize
if let richTextData = try? richTextContent.data(from: NSRange(location: 0, length: richTextContent.length), documentAttributes: [.documentType: NSAttributedString.DocumentType.rtf]) {
newCell.content = richTextData
}
Deserialize
func deserializeRichText(from data: Data) -> NSAttributedString {
do {
let options: [NSAttributedString.DocumentReadingOptionKey: Any] = [
.documentType: NSAttributedString.DocumentType.rtf
]
let attributedString = try NSAttributedString(data: data, options: options, documentAttributes: nil)
// Print success message with some details about the attributed string
print("Successfully deserialized RTF data. Length: \(attributedString.length). Preview: \(attributedString.string.prefix(50))")
return attributedString
} catch {
print("Error deserializing RTF data: \(error)")
return NSAttributedString(string: "Failed to load content")
}
}
A- Read deserializeRichText into RichTextEditor, renders without complete rich text (underscript works)
RichTextEditor(text: $viewModel.richTextContent, context: cellViewModel.context) { _ in }
.onAppear {
// Debugging: Log the preview of richTextContent before loading it into the RichTextEditor
let previewText = viewModel.richTextContent.string.prefix(100) // Limiting to the first 100 characters for brevity
print("Loading rich text into RichTextEditor. Preview: \(previewText)")
print("Assigning rich text to cell \(cellViewModel.id). Preview: \(previewText)")
// Debugging: Log the attributes at the beginning of the content
if viewModel.richTextContent.length > 0 {
let range = NSRange(location: 0, length: min(10, cellViewModel.richTextContent.length)) // Inspect the first 10 characters
let attributes = cellViewModel.richTextContent.attributes(at: 0, effectiveRange: nil)
print("Attributes at start of rich text: \(attributes)")
}
}
Print this
Loading rich text into RichTextEditor. Preview: hello
Assigning rich text to cell 2DE583D2-2B09-4F2E-8AA6-7380C3E7A708. Preview: hello
Attributes at start of rich text: [:]
updateNSView called
Updated attributed string: hello
Attributes in range {0, 5}: [:]
makeNSView called
Initial attributed string: Academy typewriter, size 46, colour blue
updateNSView called
Updated attributed string: Academy typewriter, size 46, colour blue
Attributes in range {0, 42}: [__C.NSAttributedStringKey(_rawValue: NSStrikethroughColor): sRGB IEC61966-2.1 colorspace 0 0.47843 1 1, __C.NSAttributedStringKey(_rawValue: NSColor): Catalog color: System textColor, __C.NSAttributedStringKey(_rawValue: NSStrikethrough): 1, __C.NSAttributedStringKey(_rawValue: NSFont): "HelveticaNeue 16.00 pt. P [] (0x12e791e20) fobj=0x12e745790, spc=4.45", __C.NSAttributedStringKey(_rawValue: NSParagraphStyle): Alignment Right, LineSpacing 0, ParagraphSpacing 0, ParagraphSpacingBefore 0, HeadIndent 0, TailIndent 0, FirstLineHeadIndent 0, LineHeight 0/0, LineHeightMultiple 0, LineBreakMode WordWrapping, Tabs (
B- Read deserializeRichText into Text(AttributedString( )) for debug purposes. Render correctly
Text(AttributedString(viewModel.richTextContent))
Print this
Successfully deserialized RTF data. Length: 42. Preview: Academy typewriter, size 46, colour blue
Successfully deserialized RTF data. Length: 42. Preview: Academy typewriter, size 46, colour blue
DesignView rendered with namespace: ID(id: 626)
DesignView rendered with layout.id): 73A3271C-FC19-456F-AE02-935F72DD27B4
Loading rich text into RichTextEditor. Preview: hello
Assigning rich text to cell F7B9B307-177E-45B9-8DB5-E6F2F9B4E3CC. Preview: hello
Attributes at start of rich text: [:]
Loading rich text into RichTextEditor. Preview: Academy typewriter, size 46, colour blue
Assigning rich text to cell 6621503E-929A-4758-B076-EA3A406661C2. Preview: Academy typewriter, size 46, colour blue
Attributes at start of rich text: [__C.NSAttributedStringKey(_rawValue: NSStrikethrough): 1, __C.NSAttributedStringKey(_rawValue: NSStrikethroughColor): sRGB IEC61966-2.1 colorspace 0 0.47843 1 1, __C.NSAttributedStringKey(_rawValue: NSFont): "AcademyEngravedLetPlain 48.00 pt. P [] (0x142e57960) fobj=0x142f11f40, spc=15.89", __C.NSAttributedStringKey(_rawValue: NSColor): sRGB IEC61966-2.1 colorspace 0 0.47843 1 1, __C.NSAttributedStringKey(_rawValue: NSParagraphStyle): Alignment Right, LineSpacing 0, ParagraphSpacing 0, ParagraphSpacingBefore 0, HeadIndent 0, TailIndent 0, FirstLineHeadIndent 0, LineHeight 0/0, LineHeightMultiple 0, LineBreakMode WordWrapping, Tabs (
@alelordelo Thank you for the detailed bug report! 🙏
In that case, I think it may be the font bug, since underline works.
@DominikBucher12 We should look into this.
@danielsaidi and @DominikBucher12 ,
Updates on the debug...
I added some prints to RichTextEditor ViewRepresentable:
public init(
text: Binding<NSAttributedString>,
context: RichTextContext,
config: RichTextView.Configuration = .standard,
format: RichTextDataFormat = .archivedData,
viewConfiguration: @escaping ViewConfiguration = { _ in }
) {
self.text = text
self.config = config
self._context = ObservedObject(wrappedValue: context)
self.format = format
self.viewConfiguration = viewConfiguration
}
public typealias ViewConfiguration = (RichTextViewComponent) -> Void
@ObservedObject
private var context: RichTextContext
private var text: Binding<NSAttributedString>
private let config: RichTextView.Configuration
private var format: RichTextDataFormat
private var viewConfiguration: ViewConfiguration
#if iOS || os(tvOS) || os(visionOS)
public let textView = RichTextView()
#endif
#if macOS
public let scrollView = RichTextView.scrollableTextView()
public var textView: RichTextView {
scrollView.documentView as? RichTextView ?? RichTextView()
}
#endif
public func makeCoordinator() -> RichTextCoordinator {
RichTextCoordinator(
text: text,
textView: textView,
richTextContext: context
)
}
#if iOS || os(tvOS) || os(visionOS)
public func makeUIView(context: Context) -> some UIView {
textView.setup(with: text.wrappedValue, format: format)
textView.configuration = config
viewConfiguration(textView)
return textView
}
public func updateUIView(_ view: UIViewType, context: Context) {}
#else
public func makeNSView(context: Context) -> some NSView {
print("makeNSView called")
print("Initial attributed string inside makeNSView : \(text.wrappedValue.string.prefix(100))") // Print the first 100 characters for brevity
textView.setup(with: text.wrappedValue, format: format)
textView.configuration = config
viewConfiguration(textView)
return scrollView
}
public func updateNSView(_ view: NSViewType, context: Context) {
print("updateNSView called")
let attributedString = text.wrappedValue
print("Updated attributed string inside updateNSView: \(attributedString.string.prefix(100))") // Print the first 100 characters for brevity
// Print attributes of the entire attributed string
attributedString.enumerateAttributes(in: NSRange(location: 0, length: attributedString.length), options: []) { attributes, range, _ in
print("Attributes inside updateNSView in range \(range): \(attributes)")
}
}
#endif
}
// MARK: RichTextPresenter
public extension RichTextEditor {
/// Get the currently selected range.
var selectedRange: NSRange {
textView.selectedRange
}
}
// MARK: RichTextReader
public extension RichTextEditor {
/// Get the string that is managed by the editor.
var attributedString: NSAttributedString {
text.wrappedValue
}
}
// MARK: RichTextWriter
public extension RichTextEditor {
/// Get the mutable string that is managed by the editor.
var mutableAttributedString: NSMutableAttributedString? {
textView.mutableAttributedString
}
}
#endif
And found that:
Initially the font is read correctly: Attributes inside updateNSView in range {0, 14}: [__C.NSAttributedStringKey(_rawValue: NSStrikethrough): 1, __C.NSAttributedStringKey(_rawValue: NSFont): "AcademyEngravedLetPlain 72.00 pt.
But when updated, it defaults to AppleSystemUIFont: Attributes inside updateNSView in range {0, 14}: [__C.NSAttributedStringKey(_rawValue: NSStrikethroughColor): sRGB IEC61966-2.1 colorspace 0 0.47843 1 1, __C.NSAttributedStringKey(_rawValue: NSFont): ".AppleSystemUIFont 16.00 pt.
Probably something is causing the view to be refreshed, and it defaults to apple font?
I tested the demo app in the main branch, and opening a saved text document still works. It restores fonts, colors, styles, etc.
This renders rich text deserialised from Realm:
This render text and I can style it fine, but does NOT render rich text .rtf deserialised from Realm:
I tried to manually refresh the view, but that didn't work. Really lost here on what could be wrong...
Any inputs are supper appreciated!