From e6f43de2503f060b30eb60b50cc506e5821ea7cd Mon Sep 17 00:00:00 2001 From: Marcin Krzyzanowski Date: Sat, 14 Dec 2024 21:24:26 +0100 Subject: [PATCH] Refactor annotation label view into shared package Move AnnotationLabelView into STAnnotationsPluginShared so it can be used by both AppKit and UIKit demo apps. Rename it to STAnnotationLabelView for consistency with other public types in the package. Update the view to take an action closure that is invoked when the annotation is tapped, allowing the demo apps to remove the tapped annotation. Simplify the container shape to use a standard RoundedRectangle. Remove the now unused AnnotationLabelView files from the demo app projects. --- .../DemoApp.AppKit.xcodeproj/project.pbxproj | 12 --- DemoApp.AppKit/EditorViewController.swift | 2 +- .../DemoApp.UIKit.xcodeproj/project.pbxproj | 12 --- DemoApp.UIKit/View/AnnotationLabelView.swift | 102 ------------------ DemoApp.UIKit/ViewController.swift | 8 +- .../STAnnotationLabelView.swift | 12 +-- 6 files changed, 11 insertions(+), 137 deletions(-) delete mode 100644 DemoApp.UIKit/View/AnnotationLabelView.swift rename DemoApp.AppKit/View/AnnotationLabelView.swift => Sources/STAnnotationsPluginShared/STAnnotationLabelView.swift (87%) diff --git a/DemoApp.AppKit/DemoApp.AppKit.xcodeproj/project.pbxproj b/DemoApp.AppKit/DemoApp.AppKit.xcodeproj/project.pbxproj index f38b377..e70b085 100644 --- a/DemoApp.AppKit/DemoApp.AppKit.xcodeproj/project.pbxproj +++ b/DemoApp.AppKit/DemoApp.AppKit.xcodeproj/project.pbxproj @@ -7,7 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - 752C90732AB1AF12006C835E /* AnnotationLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 752C90722AB1AF12006C835E /* AnnotationLabelView.swift */; }; 7565EBBE2A9BE09D0005B170 /* EditorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7565EBBD2A9BE09D0005B170 /* EditorViewController.swift */; }; 7565EBC12A9BE0B10005B170 /* STTextView in Frameworks */ = {isa = PBXBuildFile; productRef = 7565EBC02A9BE0B10005B170 /* STTextView */; }; 7576EDCD2AB062F400540BF5 /* STTextViewAnnotationsPlugin in Frameworks */ = {isa = PBXBuildFile; productRef = 7576EDCC2AB062F400540BF5 /* STTextViewAnnotationsPlugin */; }; @@ -17,7 +16,6 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 752C90722AB1AF12006C835E /* AnnotationLabelView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnnotationLabelView.swift; sourceTree = ""; }; 7565EBBD2A9BE09D0005B170 /* EditorViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditorViewController.swift; sourceTree = ""; }; 7576EDCA2AB0627D00540BF5 /* STTextView-Plugin-Annotations */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = "STTextView-Plugin-Annotations"; path = ..; sourceTree = ""; }; 758BAB4F2A9BDFC200D840BF /* DemoApp.AppKit.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DemoApp.AppKit.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -51,7 +49,6 @@ isa = PBXGroup; children = ( 7576EDCA2AB0627D00540BF5 /* STTextView-Plugin-Annotations */, - 7590AFEA2B64617E00947F82 /* View */, 7565EBBD2A9BE09D0005B170 /* EditorViewController.swift */, 758BAB522A9BDFC200D840BF /* AppDelegate.swift */, 758BAB542A9BDFC300D840BF /* Assets.xcassets */, @@ -70,14 +67,6 @@ name = Products; sourceTree = ""; }; - 7590AFEA2B64617E00947F82 /* View */ = { - isa = PBXGroup; - children = ( - 752C90722AB1AF12006C835E /* AnnotationLabelView.swift */, - ); - path = View; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -156,7 +145,6 @@ buildActionMask = 2147483647; files = ( 758BAB532A9BDFC200D840BF /* AppDelegate.swift in Sources */, - 752C90732AB1AF12006C835E /* AnnotationLabelView.swift in Sources */, 7565EBBE2A9BE09D0005B170 /* EditorViewController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/DemoApp.AppKit/EditorViewController.swift b/DemoApp.AppKit/EditorViewController.swift index 8634a0d..d3ba9ba 100644 --- a/DemoApp.AppKit/EditorViewController.swift +++ b/DemoApp.AppKit/EditorViewController.swift @@ -74,7 +74,7 @@ extension EditorViewController: STAnnotationsDataSource { } return STAnnotationView(frame: proposedViewFrame) { - AnnotationLabelView(Text(lineAnnotation.message), annotation: lineAnnotation) { [weak self] annotation in + STAnnotationLabelView(Text(lineAnnotation.message), annotation: lineAnnotation) { [weak self] annotation in // Remove annotation self?.annotations.removeAll(where: { $0.id == annotation.id }) } diff --git a/DemoApp.UIKit/DemoApp.UIKit.xcodeproj/project.pbxproj b/DemoApp.UIKit/DemoApp.UIKit.xcodeproj/project.pbxproj index 4ae1095..89dc467 100644 --- a/DemoApp.UIKit/DemoApp.UIKit.xcodeproj/project.pbxproj +++ b/DemoApp.UIKit/DemoApp.UIKit.xcodeproj/project.pbxproj @@ -14,7 +14,6 @@ 3E8504C52C991A98004DC5CC /* Base in Resources */ = {isa = PBXBuildFile; fileRef = 3E8504C42C991A98004DC5CC /* Base */; }; 3E8504C72C991A99004DC5CC /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3E8504C62C991A99004DC5CC /* Assets.xcassets */; }; 3E8504CA2C991A99004DC5CC /* Base in Resources */ = {isa = PBXBuildFile; fileRef = 3E8504C92C991A99004DC5CC /* Base */; }; - 3EB326C72C991D4D00F5C862 /* AnnotationLabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EB326C62C991D4900F5C862 /* AnnotationLabelView.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -26,7 +25,6 @@ 3E8504C62C991A99004DC5CC /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 3E8504C92C991A99004DC5CC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 3E8504CB2C991A99004DC5CC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 3EB326C62C991D4900F5C862 /* AnnotationLabelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnnotationLabelView.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -44,7 +42,6 @@ 3E8504B12C991A98004DC5CC = { isa = PBXGroup; children = ( - 3EB326C52C991D3C00F5C862 /* View */, 3E8504BD2C991A98004DC5CC /* AppDelegate.swift */, 3E8504BF2C991A98004DC5CC /* SceneDelegate.swift */, 3E8504C12C991A98004DC5CC /* ViewController.swift */, @@ -64,14 +61,6 @@ name = Products; sourceTree = ""; }; - 3EB326C52C991D3C00F5C862 /* View */ = { - isa = PBXGroup; - children = ( - 3EB326C62C991D4900F5C862 /* AnnotationLabelView.swift */, - ); - path = View; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -150,7 +139,6 @@ buildActionMask = 2147483647; files = ( 3E8504C22C991A98004DC5CC /* ViewController.swift in Sources */, - 3EB326C72C991D4D00F5C862 /* AnnotationLabelView.swift in Sources */, 3E8504BE2C991A98004DC5CC /* AppDelegate.swift in Sources */, 3E8504C02C991A98004DC5CC /* SceneDelegate.swift in Sources */, ); diff --git a/DemoApp.UIKit/View/AnnotationLabelView.swift b/DemoApp.UIKit/View/AnnotationLabelView.swift deleted file mode 100644 index 3514307..0000000 --- a/DemoApp.UIKit/View/AnnotationLabelView.swift +++ /dev/null @@ -1,102 +0,0 @@ -// Created by Marcin Krzyzanowski -// https://github.com/krzyzanowskim/STTextView/blob/main/LICENSE.md - -import SwiftUI -import Foundation -import STTextView -import STAnnotationsPlugin - -struct AnnotationLabelView : View { - @Environment(\.colorScheme) private var colorScheme - - private let text: Text - private let annotation: STMessageLineAnnotation - private let textWidth: CGFloat - private let textHeight: CGFloat - - init(_ text: Text, annotation: STMessageLineAnnotation, textWidth: CGFloat, textHeight: CGFloat) { - self.text = text - self.annotation = annotation - self.textWidth = textWidth - self.textHeight = textHeight - } - - var body: some View { - Label { - text - .foregroundColor(.primary) - .frame(minWidth: textWidth, maxWidth: .infinity, alignment: .leading) - } icon: { - ZStack { - // the way it draws bothers me - // https://twitter.com/krzyzanowskim/status/1527723492002643969 - Image(systemName: "octagon") - .symbolVariant(.fill) - .foregroundStyle(.red) - - Image(systemName: "xmark.octagon") - .foregroundStyle(.white) - } - .shadow(color: annotation.kind.color, radius: 1) - } - .labelStyle( - AnnotationLabelStyle() - ) - .background( - ZStack { - ContainerRelativeShape() - .fill(annotation.kind.color) - .background(.background) - - ContainerRelativeShape() - .stroke(annotation.kind.color) - } - ) - .containerShape( - UnevenRoundedRectangle( - cornerRadii: RectangleCornerRadii(topLeading: 2, bottomLeading: 2), - style: .circular - ) - ) - } -} - -private struct AnnotationLabelStyle: LabelStyle { - @Environment(\.colorScheme) private var colorScheme - - func makeBody(configuration: Configuration) -> some View { - HStack(alignment: .center, spacing: 0) { - configuration.icon - .padding(.horizontal, 4) - .controlSize(.large) - .contentShape(Rectangle()) - - Rectangle() - .foregroundStyle(.background) - .frame(width: 1) - .frame(maxHeight: .infinity) - .padding(.vertical, 0.5) - - configuration.title - .padding(.leading, 4) - .padding(.trailing, 16) - .lineLimit(1) - .truncationMode(.tail) - .textSelection(.enabled) - } - } -} - -private extension AnnotationKind { - var color: Color { - switch self { - case .info: - Color.accentColor.opacity(0.2) - case .warning: - Color.yellow.opacity(0.2) - case .error: - Color.red.opacity(0.2) - } - } - -} diff --git a/DemoApp.UIKit/ViewController.swift b/DemoApp.UIKit/ViewController.swift index a70975f..82c60d7 100644 --- a/DemoApp.UIKit/ViewController.swift +++ b/DemoApp.UIKit/ViewController.swift @@ -3,6 +3,7 @@ import UIKit import STTextView import STAnnotationsPlugin +import STAnnotationsPluginShared class ViewController: UIViewController { @@ -105,8 +106,11 @@ extension ViewController: STAnnotationsDataSource { } return STAnnotationView(frame: proposedViewFrame) { - AnnotationLabelView(Text(lineAnnotation.message), annotation: lineAnnotation, textWidth: proposedViewFrame.width, textHeight: proposedViewFrame.height) - .font(.body) + STAnnotationLabelView(Text(lineAnnotation.message), annotation: lineAnnotation) { annotation in + // Remove annotation + self.annotations.removeAll(where: { $0.id == annotation.id }) + } + .font(.body) } } diff --git a/DemoApp.AppKit/View/AnnotationLabelView.swift b/Sources/STAnnotationsPluginShared/STAnnotationLabelView.swift similarity index 87% rename from DemoApp.AppKit/View/AnnotationLabelView.swift rename to Sources/STAnnotationsPluginShared/STAnnotationLabelView.swift index d1d064f..13e57b6 100644 --- a/DemoApp.AppKit/View/AnnotationLabelView.swift +++ b/Sources/STAnnotationsPluginShared/STAnnotationLabelView.swift @@ -4,22 +4,21 @@ import SwiftUI import Foundation import STTextView -import STAnnotationsPlugin -struct AnnotationLabelView : View { +public struct STAnnotationLabelView: View { @Environment(\.colorScheme) private var colorScheme private let text: Text private let annotation: STMessageLineAnnotation private let action: (STMessageLineAnnotation) -> Void - init(_ text: Text, annotation: STMessageLineAnnotation, action: @escaping (STMessageLineAnnotation) -> Void) { + public init(_ text: Text, annotation: STMessageLineAnnotation, action: @escaping (STMessageLineAnnotation) -> Void) { self.text = text self.action = action self.annotation = annotation } - var body: some View { + public var body: some View { Label { text .foregroundColor(.primary) @@ -56,10 +55,7 @@ struct AnnotationLabelView : View { } ) .containerShape( - UnevenRoundedRectangle( - cornerRadii: RectangleCornerRadii(topLeading: 2, bottomLeading: 2), - style: .circular - ) + RoundedRectangle(cornerRadius: 2, style: .circular) ) } }