Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use font representable to support multi platform #17

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading