1
Fork 0

Add proper support for dark mode on attributed text

This commit is contained in:
redstrate 2020-11-18 09:03:56 -05:00
parent 99620c849f
commit c4d49c423a
4 changed files with 73 additions and 55 deletions

View file

@ -0,0 +1,64 @@
import Foundation
#if os(macOS)
import AppKit
extension NSMutableAttributedString {
func with(font: NSFont) -> NSMutableAttributedString {
enumerateAttribute(NSAttributedString.Key.font, in: NSMakeRange(0, length), options: .longestEffectiveRangeNotRequired, using: { (value, range, stop) in
if let originalFont = value as? NSFont, let newFont = applyTraitsFromFont(originalFont, to: font) {
addAttribute(NSAttributedString.Key.font, value: newFont, range: range)
}
})
addAttribute(NSAttributedString.Key.foregroundColor, value: NSColor.controlTextColor, range: NSRange(location: 0, length: self.length))
return self
}
func applyTraitsFromFont(_ originalFont: NSFont, to newFont: NSFont) -> NSFont? {
let originalTrait = originalFont.fontDescriptor.symbolicTraits
if(originalTrait.contains(NSFontDescriptor.SymbolicTraits.bold)) {
var traits = newFont.fontDescriptor.symbolicTraits
traits.insert(.bold)
let fontDescriptor = newFont.fontDescriptor.withSymbolicTraits(traits)
return NSFont.init(descriptor: fontDescriptor, size: 0)
}
return newFont
}
}
#elseif os(iOS)
import UIKit
extension NSMutableAttributedString {
func with(font: UIFont) -> NSMutableAttributedString {
enumerateAttribute(NSAttributedString.Key.font, in: NSMakeRange(0, length), options: .longestEffectiveRangeNotRequired, using: { (value, range, stop) in
if let originalFont = value as? UIFont, let newFont = applyTraitsFromFont(originalFont, to: font) {
addAttribute(NSAttributedString.Key.font, value: newFont, range: range)
}
})
addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.label, range: NSRange(location: 0, length: self.length))
return self
}
func applyTraitsFromFont(_ originalFont: UIFont, to newFont: UIFont) -> UIFont? {
let originalTrait = originalFont.fontDescriptor.symbolicTraits
if originalTrait.contains(.traitBold) {
var traits = newFont.fontDescriptor.symbolicTraits
traits.insert(.traitBold)
if let fontDescriptor = newFont.fontDescriptor.withSymbolicTraits(traits) {
return UIFont.init(descriptor: fontDescriptor, size: 0)
}
}
return newFont
}
}
#endif

View file

@ -1,32 +1,5 @@
import SwiftUI
extension NSMutableAttributedString {
func with(font: UIFont) -> NSMutableAttributedString {
enumerateAttribute(NSAttributedString.Key.font, in: NSMakeRange(0, length), options: .longestEffectiveRangeNotRequired, using: { (value, range, stop) in
if let originalFont = value as? UIFont, let newFont = applyTraitsFromFont(originalFont, to: font) {
addAttribute(NSAttributedString.Key.font, value: newFont, range: range)
}
})
return self
}
func applyTraitsFromFont(_ originalFont: UIFont, to newFont: UIFont) -> UIFont? {
let originalTrait = originalFont.fontDescriptor.symbolicTraits
if originalTrait.contains(.traitBold) {
var traits = newFont.fontDescriptor.symbolicTraits
traits.insert(.traitBold)
if let fontDescriptor = newFont.fontDescriptor.withSymbolicTraits(traits) {
return UIFont.init(descriptor: fontDescriptor, size: 0)
}
}
return newFont
}
}
final class AttributedTextComponent: UIViewRepresentable {
let string: NSMutableAttributedString

View file

@ -1,31 +1,5 @@
import SwiftUI
extension NSMutableAttributedString {
func with(font: NSFont) -> NSMutableAttributedString {
enumerateAttribute(NSAttributedString.Key.font, in: NSMakeRange(0, length), options: .longestEffectiveRangeNotRequired, using: { (value, range, stop) in
if let originalFont = value as? NSFont, let newFont = applyTraitsFromFont(originalFont, to: font) {
addAttribute(NSAttributedString.Key.font, value: newFont, range: range)
}
})
return self
}
func applyTraitsFromFont(_ originalFont: NSFont, to newFont: NSFont) -> NSFont? {
let originalTrait = originalFont.fontDescriptor.symbolicTraits
if(originalTrait.contains(NSFontDescriptor.SymbolicTraits.bold)) {
var traits = newFont.fontDescriptor.symbolicTraits
traits.insert(.bold)
let fontDescriptor = newFont.fontDescriptor.withSymbolicTraits(traits)
return NSFont.init(descriptor: fontDescriptor, size: 0)
}
return newFont
}
}
final class AttributedTextComponent: NSViewRepresentable {
let string: NSMutableAttributedString
@ -39,9 +13,9 @@ final class AttributedTextComponent: NSViewRepresentable {
func updateNSView(_ uiView: NSTextField, context: Context) {
uiView.backgroundColor = .clear
//uiView.numberOfLines = 0
uiView.lineBreakMode = .byWordWrapping
uiView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
uiView.attributedStringValue = string
}
}
@ -62,7 +36,7 @@ struct AttributedText: View {
@State var lastSize: CGSize = .zero
init(_ html: NSMutableAttributedString) {
self.html = html.with(font: NSFont.systemFont(ofSize: 15))
self.html = html.with(font: NSFont.systemFont(ofSize: NSFont.systemFontSize))
self.component = AttributedTextComponent(html)
}
@ -73,6 +47,7 @@ struct AttributedText: View {
label.lineBreakMode = .byWordWrapping
//label.attributedText = self.html
label.attributedStringValue = self.html
label.sizeToFit()

View file

@ -26,6 +26,8 @@
03B2BAA8256556D100483FE3 /* URLImage in Frameworks */ = {isa = PBXBuildFile; productRef = 03B2BAA7256556D100483FE3 /* URLImage */; };
03B2BAB225655A1100483FE3 /* WebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B2BAB125655A1100483FE3 /* WebView.swift */; };
03B2BAB325655A1100483FE3 /* WebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B2BAB125655A1100483FE3 /* WebView.swift */; };
03B2BAB72565608400483FE3 /* AttributedStringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B2BAB62565608400483FE3 /* AttributedStringExtensions.swift */; };
03B2BAB82565608400483FE3 /* AttributedStringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03B2BAB62565608400483FE3 /* AttributedStringExtensions.swift */; };
03BCD7432488947200DA1F27 /* ProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BCD7422488947200DA1F27 /* ProfileView.swift */; };
03BCD7452488948200DA1F27 /* PostView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BCD7442488948200DA1F27 /* PostView.swift */; };
03BCD74A2489322500DA1F27 /* AttributedText.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03BCD7492489322500DA1F27 /* AttributedText.swift */; };
@ -50,6 +52,7 @@
03B2BA84256550FA00483FE3 /* AttributedText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedText.swift; sourceTree = "<group>"; };
03B2BA9E2565555500483FE3 /* MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = "<group>"; };
03B2BAB125655A1100483FE3 /* WebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebView.swift; sourceTree = "<group>"; };
03B2BAB62565608400483FE3 /* AttributedStringExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedStringExtensions.swift; sourceTree = "<group>"; };
03BCD7422488947200DA1F27 /* ProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileView.swift; sourceTree = "<group>"; };
03BCD7442488948200DA1F27 /* PostView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostView.swift; sourceTree = "<group>"; };
03BCD7492489322500DA1F27 /* AttributedText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedText.swift; sourceTree = "<group>"; };
@ -139,6 +142,7 @@
03BCD7422488947200DA1F27 /* ProfileView.swift */,
03BCD7442488948200DA1F27 /* PostView.swift */,
03B2BAB125655A1100483FE3 /* WebView.swift */,
03B2BAB62565608400483FE3 /* AttributedStringExtensions.swift */,
);
path = Common;
sourceTree = "<group>";
@ -262,6 +266,7 @@
03427F6D248887D200A0073D /* Common.swift in Sources */,
03B2BAB225655A1100483FE3 /* WebView.swift in Sources */,
03427F592488856C00A0073D /* AppDelegate.swift in Sources */,
03B2BAB72565608400483FE3 /* AttributedStringExtensions.swift in Sources */,
03BCD7432488947200DA1F27 /* ProfileView.swift in Sources */,
03427F5B2488856C00A0073D /* SceneDelegate.swift in Sources */,
03BCD7452488948200DA1F27 /* PostView.swift in Sources */,
@ -278,6 +283,7 @@
03B2BA9F2565555500483FE3 /* MainView.swift in Sources */,
03B2BA7025654F0500483FE3 /* Common.swift in Sources */,
03B2BA7125654F0500483FE3 /* ProfileView.swift in Sources */,
03B2BAB82565608400483FE3 /* AttributedStringExtensions.swift in Sources */,
03B2BA7225654F0500483FE3 /* PostView.swift in Sources */,
03B2BA5C25654E9700483FE3 /* AppDelegate.swift in Sources */,
03B2BAB325655A1100483FE3 /* WebView.swift in Sources */,