Add proper support for dark mode on attributed text
This commit is contained in:
parent
99620c849f
commit
c4d49c423a
4 changed files with 73 additions and 55 deletions
64
MobileFort/Common/AttributedStringExtensions.swift
Normal file
64
MobileFort/Common/AttributedStringExtensions.swift
Normal 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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 */,
|
||||
|
|
Reference in a new issue