LeoNatan / LNPopupUI

A SwiftUI library for presenting views as popups, much like the Apple Music and Podcasts apps.
MIT License
320 stars 29 forks source link

Unable to change text attributes in .popupBarCustomizer #43

Closed HvrByte closed 2 months ago

HvrByte commented 2 months ago

Describe the Bug

The documentation states that we can use the .popupBarCustomizer modifier to change the appearance of the title and subtitle, but that does not seem to actually work since the Swift compiler throws an error stating that we can not assign a value of type [AnyHashable: NSObject] to type AttributeContainer.

I am specifically trying to change the color To Reproduce Steps to reproduce the behavior:

  1. Modify PlayerView in the MusicScene and add the following (from the README)
     .popupBarCustomizer { popupBar in
      let paragraphStyle = NSMutableParagraphStyle()
      paragraphStyle.alignment = .right
      paragraphStyle.lineBreakMode = .byTruncatingTail

      popupBar.standardAppearance.backgroundEffect = UIBlurEffect(style: .dark)
      popupBar.standardAppearance.titleTextAttributes = [ .paragraphStyle: paragraphStyle, .font: UIFont(name: "Chalkduster", size: 14)!, .foregroundColor: UIColor.yellow ]
      popupBar.standardAppearance.subtitleTextAttributes = [ .paragraphStyle: paragraphStyle, .font: UIFont(name: "Chalkduster", size: 12)!, .foregroundColor: UIColor.green ]

      popupBar.tintColor = .yellow
    }
  1. Build the project.
  2. We get the error: "Cannot assign value of type '[AnyHashable : NSObject]' to type 'AttributeContainer'"

Expected Behavior To be able to set the titleTextAttributes and subTitleTextAttributes

Screenshots

These are the errors above and where I put the customizer Screenshot 2024-07-02 at 21 54 48

Additional Context

I also tried to use a typed dictionary, but it leads to the same error

Screenshot 2024-07-02 at 22 03 23

Since it clearly does not accept a dictionary I also tried using an AttributeContainer, but then I get "Undefined symbol: (extension in LNPopupController):__C.LNPopupBarAppearance.titleTextAttributes.setter : Foundation.AttributeContainer? "

Screenshot 2024-07-02 at 22 05 49

As a final attempt, I also tried using the .popupBarTitleTextAttributes modifier, but although that does build and run it does not actually change the font or text color

Screenshot 2024-07-02 at 22 11 23

Please let me know if I am doing something incorrect here.

LeoNatan commented 2 months ago

Something is really wrong in your setup (as seen with the “Undefined symbol” error). Could you please try cloning this repo and running the demo project? In settings, enable Customization and see if that works. Thanks

IMG_6545 IMG_6546

HvrByte commented 2 months ago

Thanks for the quick reply, I really appreciate that. I'd also like to take the opportunity to say that LNPopupUI and LNPopupController is truly amazing work.

I'm primarily interested in being able to change the font color in .popupBarCustomizer so that I can use the floating version of the popupBar since using a custom view with .popupBarCustomView() does not seem to support the floating presentation.

Turning on customizations in the demo app does indeed change the presentation of the bar (although I notice that Marquee seem to stop working).

I've forked this repo and added 2 branches so that you can see the "Undefined Symbol" error is reproducible in your environment.

You can find the fork at https://github.com/HvrByte/LNPopupUI/tree/master

There are 2 branches:

  1. https://github.com/HvrByte/LNPopupUI/tree/popupBarCustomizer_Readme simply adds the README code for changing the font
  2. https://github.com/HvrByte/LNPopupUI/tree/popupBarCustomizer_AttributeContainer tries to use an AttributeContainer to make the font changes which leads to the "Undefined Symbol" error

PS: in the second branch, if you try to pass the attributes dictionary, you will get Cannot assign value of type '[NSAttributedString.Key : Any]' to type 'AttributeContainer'

HvrByte commented 2 months ago

I dug through the demo code a bit more and got it working in this branch: https://github.com/HvrByte/LNPopupUI/tree/popupBarTextAttribute_modifiers

Instead of using the code in the README or trying to use an AttributeContainer the way to make it work is to use .popupBarTitleTextAttributes() and .popupBarSubtitleTextAttributes() and change the font that way.

Since there is a supported way to do it, I think we can close this bug and I will issue a PR to update the documentation to clarify that those 2 modifiers should be used to change the the font/color/paragraph properties.

HvrByte commented 2 months ago

Issued pull request #44 to update the README

LeoNatan commented 2 months ago

Reproduced the issue, looking into it. This shouldn’t happen.

LeoNatan commented 2 months ago

The pure Objective C works as expected:

let attributes: [NSAttributedString.Key: Any] = [
    .paragraphStyle: paragraphStyle,
    .font: UIFont(name: "Chalkduster", size: 14)!,
    .foregroundColor: UIColor.yellow
]

popupBar.standardAppearance.__titleTextAttributes = attributes

So somehow the Swift overlay in LNPopupController is incorrectly linked.

LeoNatan commented 2 months ago

Huh, this looks like a bug in Xcode compiler/linker. Changing the target to be a static framework (instead of dynamic), it compiles and links as expected. Investigating.

LeoNatan commented 2 months ago

Importing LNPopupController like so:

.product(name: "LNPopupController-Static", package: "LNPopupController”)

seems to solve the issue for me.

LeoNatan commented 2 months ago

I’ll create a release for you to test.

LeoNatan commented 2 months ago

Please try with 1.7.5.

HvrByte commented 2 months ago

Seems that I can now use the following to set the text attributes in 1.7.5:

    .popupBarCustomizer { popupBar in
      let paragraphStyle = NSMutableParagraphStyle()
      paragraphStyle.alignment = .right
      paragraphStyle.lineBreakMode = .byTruncatingTail

      popupBar.standardAppearance.backgroundEffect = UIBlurEffect(style: .dark)

      popupBar.standardAppearance.titleTextAttributes = AttributeContainer([
        .paragraphStyle: paragraphStyle,
        .font: UIFont(name: "Chalkduster", size: 14)!,
        .foregroundColor: UIColor.yellow
      ])
      popupBar.standardAppearance.subtitleTextAttributes = AttributeContainer([
        .paragraphStyle: paragraphStyle,
        .font: UIFont(name: "Chalkduster", size: 14)!,
        .foregroundColor: UIColor.yellow
      ])

      popupBar.tintColor = .yellow
    }

I will go ahead and close this issue.

Thank you, really appreciate it

LeoNatan commented 2 months ago

Great.

Please note the nuanced differences between popupBar.standardAppearance.titleTextAttributes, which expects UIKit scoped attributes only, and popupBarTitleTextAttributes(), which also supports SwiftUI scoped attributes.

LeoNatan commented 2 months ago

Investigating broken marquee in LNPopupUI when customization is enabled here:

https://github.com/LeoNatan/LNPopupUI/issues/45