Skip to content

Commit

Permalink
Use font representable to support multi platform (#17)
Browse files Browse the repository at this point in the history
* Update font with representable
  • Loading branch information
cp-divyesh-v authored Jan 17, 2024
1 parent 7d742ef commit d0b4dea
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 58 deletions.
20 changes: 20 additions & 0 deletions .github/workflows/build_package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: build_package

run-name: build

on: [push]

jobs:
build:
name: Swift ${{ matrix.swift }} on ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: swift-actions/setup-swift@65540b95f51493d65f5e59e97dcef9629ddf11bf
- uses: actions/checkout@v4
- name: Build
run: swift build
- name: Run tests
run: swift test
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
//

import Foundation
import UIKit

public extension NSMutableAttributedString {

Expand Down Expand Up @@ -49,13 +48,10 @@ public extension NSMutableAttributedString {
/**
This will reset font size befor multiplying new size
*/
private func byTogglingFontSizeFor(style: TextSpanStyle, font: UIFont, shouldAdd: Bool) -> CGFloat {
private func byTogglingFontSizeFor(style: TextSpanStyle, font: FontRepresentable, shouldAdd: Bool) -> CGFloat {
guard style.isHeaderStyle || style.isDefault else { return font.pointSize }

let cleanFont = style.getFontAfterRemovingStyle(font: font)
// if style.isDefault {
// return cleanFont.pointSize
// }
if shouldAdd {
return cleanFont.pointSize * style.fontSizeMultiplier
} else {
Expand Down
34 changes: 34 additions & 0 deletions Sources/RichEditorSwiftUI/Fonts/FontMetricsRepresentable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// File.swift
//
//
// Created by Divyesh Vekariya on 17/01/24.
//

import Foundation

#if canImport(AppKit) && !targetEnvironment(macCatalyst)
import AppKit

/**
This typealias bridges platform-specific font matrics to
simplify multi-platform support.
The typealias also defines additional functionality as type
extensions for the platform-specific types.
*/
public typealias FontMetricsRepresentable = NSFont.NSFontMetrics
#endif

#if canImport(UIKit)
import UIKit

/**
This typealias bridges platform-specific font matrics to
simplify multi-platform support.
The typealias also defines additional functionality as type
extensions for the platform-specific types.
*/
public typealias FontMetricsRepresentable = UIFontMetrics
#endif
2 changes: 1 addition & 1 deletion Sources/RichEditorSwiftUI/UI/Editor/RichEditorState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class RichEditorState: ObservableObject {
@Published internal var editableText: NSMutableAttributedString
@Published internal var activeStyles: Set<TextSpanStyle> = []
@Published internal var activeAttributes: [NSAttributedString.Key: Any]? = [:]
internal var curretFont: UIFont = .systemFont(ofSize: .standardRichTextFontSize)
internal var curretFont: FontRepresentable = .systemFont(ofSize: .standardRichTextFontSize)

@Published internal var attributesToApply: ((spans: [(span:RichTextSpan, shouldApply: Bool)], onCompletion: () -> Void))? = nil

Expand Down
6 changes: 3 additions & 3 deletions Sources/RichEditorSwiftUI/UI/Editor/TextSpanStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public enum TextSpanStyle: String, Equatable, Codable, CaseIterable {
return self.rawValue
}

func defaultAttributeValue(font: UIFont? = nil) -> Any {
func defaultAttributeValue(font: FontRepresentable? = nil) -> Any {
let font = font ?? .systemFont(ofSize: .standardRichTextFontSize)
switch self {
case .underline:
Expand Down Expand Up @@ -90,7 +90,7 @@ public enum TextSpanStyle: String, Equatable, Codable, CaseIterable {
}
}

func getFontWithUpdating(font: UIFont) -> UIFont {
func getFontWithUpdating(font: FontRepresentable) -> FontRepresentable {
switch self {
case .default:
return font
Expand Down Expand Up @@ -130,7 +130,7 @@ public enum TextSpanStyle: String, Equatable, Codable, CaseIterable {
}
}

func getFontAfterRemovingStyle(font: UIFont) -> UIFont {
func getFontAfterRemovingStyle(font: FontRepresentable) -> FontRepresentable {
switch self {
case .bold, .italic:
return font.removeFontStyle(self)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
//
// UIFont+Extension.swift
// FontRepresentable+Extension.swift
//
//
// Created by Divyesh Vekariya on 26/12/23.
//

import SwiftUI

extension UIFont {
extension FontRepresentable {
/// Check if font is bold
var isBold: Bool {
return fontDescriptor.symbolicTraits.contains(.traitBold)
Expand All @@ -19,61 +19,61 @@ extension UIFont {
}

/// Make font **Bold**
func makeBold() -> UIFont {
func makeBold() -> FontRepresentable {
if isBold {
return self
} else {
let fontDesc = fontDescriptor.byTogglingStyle(.bold)
fontDesc.withFamily(familyName)
return UIFont(descriptor: fontDesc, size: pointSize)
return FontRepresentable(descriptor: fontDesc, size: pointSize)
}
}

/// Make font **Italic**
func makeItalic() -> UIFont {
func makeItalic() -> FontRepresentable {
if isItalic {
return self
} else {
let fontDesc = fontDescriptor.byTogglingStyle(.italic)
fontDesc.withFamily(familyName)
return UIFont(descriptor: fontDesc, size: pointSize)
return FontRepresentable(descriptor: fontDesc, size: pointSize)
}
}

/// Make font **Bold** and **Italic**
func setBoldItalicStyles() -> UIFont {
func setBoldItalicStyles() -> FontRepresentable {
return makeBold().makeItalic()
}

/// Remove **Bold** style from font
func removeBoldStyle() -> UIFont {
func removeBoldStyle() -> FontRepresentable {
if !isBold {
return self
} else {
let fontDesc = fontDescriptor.byTogglingStyle(.bold)
fontDesc.withFamily(familyName)
return UIFont(descriptor: fontDesc, size: pointSize)
return FontRepresentable(descriptor: fontDesc, size: pointSize)
}
}

/// Remove **Italic** style from font
func removeItalicStyle() -> UIFont {
func removeItalicStyle() -> FontRepresentable {
if !isItalic {
return self
} else {
let fontDesc = fontDescriptor.byTogglingStyle(.italic)
fontDesc.withFamily(familyName)
return UIFont(descriptor: fontDesc, size: pointSize)
return FontRepresentable(descriptor: fontDesc, size: pointSize)
}
}

/// Remove **Bold** and **Italic** style from font
func makeNormal() -> UIFont {
func makeNormal() -> FontRepresentable {
return removeBoldStyle().removeItalicStyle()
}

/// Toggle **Bold** style of font
func toggleBoldTrait() -> UIFont {
func toggleBoldTrait() -> FontRepresentable {
if isBold {
return removeBoldStyle()
} else {
Expand All @@ -82,7 +82,7 @@ extension UIFont {
}

/// Toggle **Italic** style of font
func toggleItalicStyle() -> UIFont {
func toggleItalicStyle() -> FontRepresentable {
if isItalic {
return removeItalicStyle()
} else {
Expand All @@ -91,49 +91,49 @@ extension UIFont {
}

/// Get a new font with updated font size by **size**
func updateFontSize(size: CGFloat) -> UIFont {
func updateFontSize(size: CGFloat) -> FontRepresentable {
if pointSize != size {
let fontDesc = fontDescriptor
fontDesc.withFamily(familyName)
return UIFont(descriptor: fontDesc, size: size)
return FontRepresentable(descriptor: fontDesc, size: size)
} else {
return self
}
}

func updateFontSize(multiple: CGFloat) -> UIFont {
func updateFontSize(multiple: CGFloat) -> FontRepresentable {
if pointSize != multiple * pointSize {
let size = multiple * pointSize
let fontDesc = fontDescriptor
fontDesc.withFamily(familyName)
return UIFont(descriptor: fontDesc, size: size)
return FontRepresentable(descriptor: fontDesc, size: size)
} else {
return self
}
}
}

public extension UIFont {
public extension FontRepresentable {
/// Get a new font by adding a text style.
func addFontStyle(_ style: TextSpanStyle) -> UIFont {
func addFontStyle(_ style: TextSpanStyle) -> FontRepresentable {
guard let trait = style.symbolicTraits, !fontDescriptor.symbolicTraits.contains(trait) else { return self }
let fontDesc = fontDescriptor.byTogglingStyle(style)
fontDesc.withFamily(familyName)
return UIFont(descriptor: fontDesc, size: pointSize)
return FontRepresentable(descriptor: fontDesc, size: pointSize)
}

///Get a new font by removing a text style.
func removeFontStyle(_ style: TextSpanStyle) -> UIFont {
func removeFontStyle(_ style: TextSpanStyle) -> FontRepresentable {
guard let trait = style.symbolicTraits, fontDescriptor.symbolicTraits.contains(trait) else { return self }
let fontDesc = fontDescriptor.byTogglingStyle(style)
fontDesc.withFamily(familyName)
return UIFont(descriptor: fontDesc, size: pointSize)
return FontRepresentable(descriptor: fontDesc, size: pointSize)
}

/// Get a new font by toggling a text style.
func byToggalingFontStyle(_ style: TextSpanStyle) -> UIFont {
func byToggalingFontStyle(_ style: TextSpanStyle) -> FontRepresentable {
let fontDesc = fontDescriptor.byTogglingStyle(style)
fontDesc.withFamily(familyName)
return UIFont(descriptor: fontDesc, size: pointSize)
return FontRepresentable(descriptor: fontDesc, size: pointSize)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ internal struct NSFontTraitMask: OptionSet {
extension NSMutableAttributedString {
internal func applyFontTraits(_ traitMask: NSFontTraitMask, range: NSRange) {
enumerateAttribute(.font, in: range, options: [.longestEffectiveRangeNotRequired]) { (attr, attrRange, stop) in
guard let font = attr as? UIFont else { return }
guard let font = attr as? FontRepresentable else { return }
let descriptor = font.fontDescriptor
var symbolicTraits = descriptor.symbolicTraits
if traitMask.contains(.boldFontMask) {
Expand All @@ -60,7 +60,7 @@ extension NSMutableAttributedString {
symbolicTraits.remove(.traitItalic)
}
guard let newDescriptor = descriptor.withSymbolicTraits(symbolicTraits) else { return }
let newFont = UIFont(descriptor: newDescriptor, size: font.pointSize)
let newFont = FontRepresentable(descriptor: newDescriptor, size: font.pointSize)
self.addAttribute(.font, value: newFont, range: attrRange)
}
}
Expand Down

This file was deleted.

4 changes: 2 additions & 2 deletions Sources/RichEditorSwiftUI/UI/Utils/TextViewWrapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ internal struct TextViewWrapper: UIViewRepresentable {
private let isUserInteractionEnabled: Bool
private let isScrollEnabled: Bool
private let linelimit: Int?
private let fontStyle: UIFont?
private let fontStyle: FontRepresentable?
private let fontColor: Color
private let backGroundColor: UIColor
private let tag: Int?
Expand All @@ -30,7 +30,7 @@ internal struct TextViewWrapper: UIViewRepresentable {
isUserInteractionEnabled: Bool = true,
isScrollEnabled: Bool = false,
linelimit: Int? = nil,
fontStyle: UIFont? = nil,
fontStyle: FontRepresentable? = nil,
fontColor: Color = .black,
backGroundColor: UIColor = .clear,
tag: Int? = nil,
Expand Down

0 comments on commit d0b4dea

Please sign in to comment.