danielsaidi / RichTextKit

RichTextKit is a Swift SDK that helps you use rich text in Swift and SwiftUI.
MIT License
944 stars 126 forks source link

`setAttributedString` sets color to black, instead of primary color #82

Closed henningko closed 10 months ago

henningko commented 1 year ago

Steps to reproduce:

  1. Create a RichTextEditor and set the attributed string to any string or NSAttributedString onAppear:
    RichTextEditor(text: $formattedText, context: rtContext)
    .onAppear {
        rtContext.setAttributedString(to: NSAttributedString(string: note.content))
    }
  2. The RichTextEditor will display the string in black, even when in Dark Mode

Expected Behavior

When adding a string, the color should be set to the primary color, which is dependent on the current view mode (dark mode or light mode). When writing in an empty RichTextEditor, this behaves correctly (white text for dark mode, black text in light mode).

danielsaidi commented 1 year ago

I guess you'd first have to analyze if the string contains any color information, so that intentional black or any other colors isn't converted?

Perhaps it would be better to have a separate setString that takes a raw string and applies the primary color?

henningko commented 1 year ago

I have very little understanding of how NSAttributedString works, but I don't think you'd need to check that—you could just "wrap" the new Attributed String with the proper default color, and any changes/overrides within should remain.

But a setString could also just do the trick.

DominikBucher12 commented 10 months ago

Hello @henningko this is currently work in progress. This will be solved with the Configuration of the TextView and will be implemented in following weeks, I am actively working on this, but have other things from my work on my plate. I can confirm that the default attributes for the string are not correctly set by the Apple SDK.

MrGobert commented 10 months ago

I've been trying to figure out how to use the recently added RichTextColor to turn the text white when in dark mode figuring that was the solution...I guess I misunderstood what that was for? I initially tried manipulating attributed string but nothing seemed to work. If anyone has any ideas how to get the text to turn light while in Dark Mode I'll give you a million internet points!

DominikBucher12 commented 10 months ago

Hello @MrGobert can you maybe share some code what did you actually tried to do and expected result?

To VERY simplify this, as follows:

func adjust(
        _ color: Color,
        for scheme: ColorScheme
    ) -> Color {
        switch self {
        case .background:
            if (color == .black && scheme == .dark) || (color == .white && scheme == .light) {
                return .clear
            }
            return color
        default:
            if (color == .white && scheme == .dark) || (color == .black && scheme == .light) {
                return .primary
            }
            return color
        }
    }

if the color is exact black or white, RichTextView detects this and returns for background always clear and for foreground always primary color which is system defined. The issue you might be facing is some shade of black or white is not exactly .black or .white instance, thus not reflecting the color scheme.

See the demo and tell me if anything is clear.

at last I set color to black to ensure this doesnt meddle with something...

https://github.com/danielsaidi/RichTextKit/assets/17381941/b4d5b0da-fbdf-4ee8-81db-cc8aaa49d912

MrGobert commented 10 months ago

Hello @MrGobert can you maybe share some code what did you actually tried to do and expected result?

To VERY simplify this, as follows:

func adjust(
        _ color: Color,
        for scheme: ColorScheme
    ) -> Color {
        switch self {
        case .background:
            if (color == .black && scheme == .dark) || (color == .white && scheme == .light) {
                return .clear
            }
            return color
        default:
            if (color == .white && scheme == .dark) || (color == .black && scheme == .light) {
                return .primary
            }
            return color
        }
    }

if the color is exact black or white, RichTextView detects this and returns for background always clear and for foreground always primary color which is system defined. The issue you might be facing is some shade of black or white is not exactly .black or .white instance, thus not reflecting the color scheme.

See the demo and tell me if anything is clear.

at last I set color to black to ensure this doesnt meddle with something...

demo.mov

Thank you! This does look super simple, and how I imagined it to work. However I'm not sure how to get access to RichTextColor or how to apply adjust method to my RIchTextEditor

yaroslav2308 commented 9 months ago

Hello @MrGobert can you maybe share some code what did you actually tried to do and expected result?

To VERY simplify this, as follows:

func adjust(
        _ color: Color,
        for scheme: ColorScheme
    ) -> Color {
        switch self {
        case .background:
            if (color == .black && scheme == .dark) || (color == .white && scheme == .light) {
                return .clear
            }
            return color
        default:
            if (color == .white && scheme == .dark) || (color == .black && scheme == .light) {
                return .primary
            }
            return color
        }
    }

if the color is exact black or white, RichTextView detects this and returns for background always clear and for foreground always primary color which is system defined. The issue you might be facing is some shade of black or white is not exactly .black or .white instance, thus not reflecting the color scheme.

See the demo and tell me if anything is clear.

at last I set color to black to ensure this doesnt meddle with something...

demo.mov

Thank you, Dominik! Can you provide some sample code how to implement apply this method adjust?

danielsaidi commented 9 months ago

@yaroslav2308 This approach works well in general, but I adjusted the color picker in particular to not do this automatically, since the user may in fact want a white background even when in light mode. :)