From 088bc7b28c69a2fdcfd52422b22c39b99fa3a7b2 Mon Sep 17 00:00:00 2001 From: Mx-Iris Date: Fri, 9 Oct 2026 00:51:10 +0800 Subject: [PATCH 1/5] Sync LookinCore with the Swift names from LookInside-Server Mirrors LookInside-Server's refactor/swift-idiomatic-cleanup (330c5b5), where the Swift types and members lost their LK / LKS / Lookin prefixes and the implicitly unwrapped optionals became optionals. The Objective-C names, the archive format and the wire protocol are unchanged, so .lookin documents and connected servers keep working. The host follows the new names: LookinDisplayItem is DisplayItem, LookinAttributesGroup is AttributesGroup, lookin_bindObject(_:forKey:) is bindObject(_:forKey:), and so on. Where a model value is optional now, the host handles nil instead of trapping: an attribute section without an identifier is treated as hidden, an attribute without one encodes an empty identifier for MCP, and the dashboard looks up cards by `uniqueKey() ?? ""` as it already did elsewhere. Both DisplayItemDelegate implementations take the item non-optionally, as the protocol does now. Co-Authored-By: Claude Opus 5.5 --- LookInside/AppDelegate.swift | 6 +- .../LookinAttributesGroup+LookinClient.swift | 6 +- ...kinAutoLayoutConstraint+LookinClient.swift | 6 +- .../LookinDisplayItem+LookinClient.swift | 20 +- .../Category/LookinObject+LookinClient.swift | 4 +- LookInside/Base/LKBaseView.swift | 2 +- LookInside/Base/LKColorIndicatorLayer.swift | 6 +- LookInside/Base/LKDeviceIconProvider.swift | 2 +- LookInside/Base/LKProgressIndicatorView.swift | 2 +- LookInside/Base/LKTableRowView.swift | 2 +- LookInside/Base/LKTextsMenuView.swift | 2 +- LookInside/Base/LKTipsView.swift | 4 +- LookInside/Connection/LKAppsManager.swift | 10 +- LookInside/Connection/LKChannel.swift | 6 +- .../Connection/LKConnectionManager.swift | 18 +- .../Connection/LKConnectionRequest.swift | 2 +- LookInside/Connection/LKInspectableApp.swift | 28 +-- .../Connection/LKServerUpgradeHint.swift | 2 +- .../Connection/LookinLiveDocument.swift | 2 +- LookInside/Console/LKConsoleDataSource.swift | 16 +- .../LKConsoleSelectPopoverController.swift | 6 +- .../Console/LKConsoleViewController.swift | 4 +- .../LKConstraintPopoverController.swift | 22 +-- .../LKDashboardAttributeConstraintsView.swift | 24 +-- .../LKDashboardAttributeEnumsView.swift | 6 +- .../LKDashboardAttributeGeometryViews.swift | 8 +- .../LKDashboardAttributeNumberInputView.swift | 8 +- .../LKDashboardAttributeReadOnlyViews.swift | 2 +- .../LKDashboardAttributeStringArrayView.swift | 14 +- .../LKDashboardAttributeSwitchView.swift | 2 +- .../LKDashboardAttributeTextView.swift | 4 +- .../LKDashboardAttributeView.swift | 4 +- ...LKDashboardAccessoryWindowController.swift | 4 +- .../Dashboard/LKDashboardCardView.swift | 16 +- .../Dashboard/LKDashboardModification.swift | 20 +- .../Dashboard/LKDashboardSectionView.swift | 10 +- .../Dashboard/LKDashboardViewController.swift | 36 ++-- LookInside/Dashboard/LKEnumListRegistry.swift | 2 +- .../Search/LKDashboardSearchViews.swift | 20 +- .../DebugE2E/LKDebugE2EDumpWriter.swift | 2 +- LookInside/DebugE2E/LKDebugUISnapshots.swift | 4 +- .../DebugE2E/LookinSnapshotNormalizer.swift | 24 +-- LookInside/Export/LKExportManager.swift | 8 +- LookInside/Hierarchy/LKDanceUIAttrMaker.swift | 8 +- .../Hierarchy/LKHierarchyController.swift | 12 +- .../Hierarchy/LKHierarchyDataSource.swift | 136 ++++++------- ...LKHierarchyHandlersPopoverController.swift | 26 +-- LookInside/Hierarchy/LKHierarchyRowView.swift | 22 +-- LookInside/Hierarchy/LKHierarchyView.swift | 36 ++-- .../Device/LKAttachedDeviceMonitor.swift | 8 +- .../Device/LKDeviceControlClient.swift | 10 +- LookInside/Launch/LKLaunchAppView.swift | 2 +- .../Launch/LKLaunchViewController.swift | 8 +- .../LKMCPBridgeAttributeEncoder.swift | 18 +- .../LKMCPBridgeAttributeValueDecoder.swift | 4 +- .../MCPBridge/LKMCPBridgeDetailsService.swift | 16 +- .../LKMCPBridgeInspectionModels.swift | 18 +- .../LKMCPBridgeInspectionService.swift | 12 +- .../LKMCPBridgeInvocationService.swift | 2 +- .../LKMCPBridgeLiveDocumentLookup.swift | 20 +- .../LKMCPBridgeModificationService.swift | 18 +- .../LKMCPBridgeScreenshotService.swift | 24 +-- .../MCPBridge/LKMCPBridgeSearchQuery.swift | 2 +- .../MCPBridge/LKMCPBridgeSearchService.swift | 10 +- .../LKMCPBridgeSecureContentDetector.swift | 2 +- LookInside/Manager/LKHelper.swift | 4 +- LookInside/Manager/LKNavigationManager.swift | 2 +- LookInside/Measure/LKMeasureController.swift | 2 +- LookInside/Measure/LKMeasureResultView.swift | 10 +- .../LKPrivateDiscriminatorStore.swift | 30 +-- .../Read/LKReadHierarchyController.swift | 4 +- .../Read/LKReadHierarchyDataSource.swift | 2 +- LookInside/Read/LKReadViewController.swift | 2 +- LookInside/Read/LKReadWindowController.swift | 6 +- LookInside/Read/LookinArchiveCoding.swift | 10 +- LookInside/Read/LookinArchiveDocument.swift | 2 +- .../Static/LKStaticAsyncUpdateManager.swift | 64 +++---- LookInside/Static/LKStaticConstants.swift | 2 +- .../Static/LKStaticHierarchyController.swift | 4 +- .../Static/LKStaticHierarchyDataSource.swift | 16 +- .../Static/LKStaticViewController.swift | 6 +- .../Static/LKStaticWindowController.swift | 16 +- .../Static/Preview/LKDisplayItemNode.swift | 14 +- .../Static/Preview/LKPreviewController.swift | 4 +- LookInside/Static/Preview/LKPreviewView.swift | 18 +- .../Toolbar/LKWindowToolbarAppButton.swift | 4 +- .../Toolbar/LKWindowToolbarHelper.swift | 2 +- ...LKXcodeViewHierarchyAttributeCatalog.swift | 2 +- .../LKXcodeViewHierarchyAttributes.swift | 42 ++-- .../LKXcodeViewHierarchyConverter.swift | 80 ++++---- .../LKXcodeViewHierarchyDocument.swift | 10 +- ...tion.swift => AttributeModification.swift} | 12 +- ...butesGroup.swift => AttributesGroup.swift} | 36 ++-- ...sSection.swift => AttributesSection.swift} | 16 +- ...raint.swift => AutoLayoutConstraint.swift} | 34 ++-- .../Category/CALayer+Lookin.swift | 19 +- .../Category/Color+Lookin.swift | 14 +- .../Category/Image+Lookin.swift | 7 +- .../Category/NSArray+Lookin.swift | 154 ++++++++++++--- .../Category/NSObject+Lookin.swift | 160 +++++++++++----- .../Category/NSSet+Lookin.swift | 34 +++- .../Category/NSString+Lookin.swift | 92 ++++++--- .../Category/NSValue+Lookin.swift | 105 ++++++++-- ...hment.swift => ConnectionAttachment.swift} | 10 +- ...ift => ConnectionResponseAttachment.swift} | 8 +- ...wift => CustomAttributeModification.swift} | 8 +- ...Info.swift => CustomDisplayItemInfo.swift} | 6 +- ...=> DashboardBlueprint+AttributeInfo.swift} | 4 +- ....swift => DashboardBlueprint+Groups.swift} | 4 +- ...wift => DashboardBlueprint+Sections.swift} | 4 +- ...ueprint.swift => DashboardBlueprint.swift} | 70 +++---- Sources/LookinCoreImpl/Deprecated.swift | 181 ++++++++++++++++++ ...kinDisplayItem.swift => DisplayItem.swift} | 180 ++++++++--------- ...emDetail.swift => DisplayItemDetail.swift} | 40 ++-- ...er.swift => EventHandlerDescription.swift} | 22 +-- ...ierarchyFile.swift => HierarchyFile.swift} | 16 +- ...ierarchyInfo.swift => HierarchyInfo.swift} | 60 +++--- ...inAppInfo.swift => InspectedAppInfo.swift} | 104 +++++----- ...tribute.swift => InspectedAttribute.swift} | 20 +- ...okinObject.swift => InspectedObject.swift} | 52 ++--- ...race.swift => InstanceVariableTrace.swift} | 12 +- .../LookinCoreModelSupport.swift | 32 ++-- Sources/LookinCoreImpl/LookinDefines.swift | 72 +++---- ...apter.swift => MultiplatformAdapter.swift} | 34 ++-- ...Task.swift => StaticAsyncUpdateTask.swift} | 14 +- ...nFrameChannel.swift => FrameChannel.swift} | 30 +-- ...nFrameDecoder.swift => FrameDecoder.swift} | 28 +-- ...rameListener.swift => FrameListener.swift} | 18 +- ...okinSocket.swift => SocketConnector.swift} | 6 +- ...LookinFrame.swift => TransportFrame.swift} | 40 ++-- .../{LookinUSBMux.swift => USBMux.swift} | 58 +++--- ...nUSBMuxClient.swift => USBMuxClient.swift} | 55 +++--- .../{LookinTuple.swift => TwoTuple.swift} | 24 +-- ...eakContainer.swift => WeakContainer.swift} | 8 +- Sources/LookinServerBase/LookinIvarTrace.h | 2 +- .../LookinIvarTraceConstants.m | 2 +- Tests/Dashboard/LKDashboardTests.swift | 58 +++--- Tests/Read/LaunchToolbarReadTests.swift | 12 +- .../LKXcodeViewHierarchyConverterTests.swift | 54 +++--- 139 files changed, 1854 insertions(+), 1345 deletions(-) rename Sources/LookinCoreImpl/{LookinAttributeModification.swift => AttributeModification.swift} (87%) rename Sources/LookinCoreImpl/{LookinAttributesGroup.swift => AttributesGroup.swift} (73%) rename Sources/LookinCoreImpl/{LookinAttributesSection.swift => AttributesSection.swift} (77%) rename Sources/LookinCoreImpl/{LookinAutoLayoutConstraint.swift => AutoLayoutConstraint.swift} (86%) rename Sources/LookinCoreImpl/{LookinConnectionAttachment.swift => ConnectionAttachment.swift} (78%) rename Sources/LookinCoreImpl/{LookinConnectionResponseAttachment.swift => ConnectionResponseAttachment.swift} (93%) rename Sources/LookinCoreImpl/{LookinCustomAttrModification.swift => CustomAttributeModification.swift} (86%) rename Sources/LookinCoreImpl/{LookinCustomDisplayItemInfo.swift => CustomDisplayItemInfo.swift} (94%) rename Sources/LookinCoreImpl/{LookinDashboardBlueprint+AttrInfo.swift => DashboardBlueprint+AttributeInfo.swift} (99%) rename Sources/LookinCoreImpl/{LookinDashboardBlueprint+Groups.swift => DashboardBlueprint+Groups.swift} (99%) rename Sources/LookinCoreImpl/{LookinDashboardBlueprint+Sections.swift => DashboardBlueprint+Sections.swift} (99%) rename Sources/LookinCoreImpl/{LookinDashboardBlueprint.swift => DashboardBlueprint.swift} (81%) create mode 100644 Sources/LookinCoreImpl/Deprecated.swift rename Sources/LookinCoreImpl/{LookinDisplayItem.swift => DisplayItem.swift} (82%) rename Sources/LookinCoreImpl/{LookinDisplayItemDetail.swift => DisplayItemDetail.swift} (75%) rename Sources/LookinCoreImpl/{LookinEventHandler.swift => EventHandlerDescription.swift} (85%) rename Sources/LookinCoreImpl/{LookinHierarchyFile.swift => HierarchyFile.swift} (88%) rename Sources/LookinCoreImpl/{LookinHierarchyInfo.swift => HierarchyInfo.swift} (56%) rename Sources/LookinCoreImpl/{LookinAppInfo.swift => InspectedAppInfo.swift} (84%) rename Sources/LookinCoreImpl/{LookinAttribute.swift => InspectedAttribute.swift} (82%) rename Sources/LookinCoreImpl/{LookinObject.swift => InspectedObject.swift} (64%) rename Sources/LookinCoreImpl/{LookinIvarTrace.swift => InstanceVariableTrace.swift} (83%) rename Sources/LookinCoreImpl/{LKS_MultiplatformAdapter.swift => MultiplatformAdapter.swift} (87%) rename Sources/LookinCoreImpl/{LookinStaticAsyncUpdateTask.swift => StaticAsyncUpdateTask.swift} (90%) rename Sources/LookinCoreImpl/Transport/{LookinFrameChannel.swift => FrameChannel.swift} (91%) rename Sources/LookinCoreImpl/Transport/{LookinFrameDecoder.swift => FrameDecoder.swift} (86%) rename Sources/LookinCoreImpl/Transport/{LookinFrameListener.swift => FrameListener.swift} (90%) rename Sources/LookinCoreImpl/Transport/{LookinSocket.swift => SocketConnector.swift} (96%) rename Sources/LookinCoreImpl/Transport/{LookinFrame.swift => TransportFrame.swift} (75%) rename Sources/LookinCoreImpl/Transport/{LookinUSBMux.swift => USBMux.swift} (78%) rename Sources/LookinCoreImpl/Transport/{LookinUSBMuxClient.swift => USBMuxClient.swift} (86%) rename Sources/LookinCoreImpl/{LookinTuple.swift => TwoTuple.swift} (84%) rename Sources/LookinCoreImpl/{LookinWeakContainer.swift => WeakContainer.swift} (86%) diff --git a/LookInside/AppDelegate.swift b/LookInside/AppDelegate.swift index a3a8d401..a900d4f9 100644 --- a/LookInside/AppDelegate.swift +++ b/LookInside/AppDelegate.swift @@ -194,13 +194,13 @@ final class AppDelegate: NSObject, NSApplicationDelegate { /// The dashboard blueprint's group, section and attribute identifiers /// must each be unique. private static func checkDashboardBlueprintIdentifiers() { - let groupIDs = LookinDashboardBlueprint.groupIDs().map { $0 as String } + let groupIDs = DashboardBlueprint.groupIDs() assert(Set(groupIDs).count == groupIDs.count, "duplicate LookinAttrGroupIdentifier") - let sectionIDs = groupIDs.flatMap { LookinDashboardBlueprint.sectionIDs(forGroupID: $0).map { $0 as String } } + let sectionIDs = groupIDs.flatMap { DashboardBlueprint.sectionIDs(forGroupID: $0) ?? [] } assert(Set(sectionIDs).count == sectionIDs.count, "duplicate LookinAttrSectionIdentifier") - let attrIDs = sectionIDs.flatMap { LookinDashboardBlueprint.attrIDs(forSectionID: $0).map { $0 as String } } + let attrIDs = sectionIDs.flatMap { DashboardBlueprint.attrIDs(forSectionID: $0) ?? [] } assert(Set(attrIDs).count == attrIDs.count, "duplicate LookinAttrIdentifier") } #endif diff --git a/LookInside/Base/Category/LookinAttributesGroup+LookinClient.swift b/LookInside/Base/Category/LookinAttributesGroup+LookinClient.swift index 9c7c2dba..144b6dac 100644 --- a/LookInside/Base/Category/LookinAttributesGroup+LookinClient.swift +++ b/LookInside/Base/Category/LookinAttributesGroup+LookinClient.swift @@ -1,11 +1,11 @@ // -// LookinAttributesGroup+LookinClient.swift +// AttributesGroup+LookinClient.swift // LookInside // import Foundation -extension LookinAttributesGroup { +extension AttributesGroup { /// The group's card title. `isMacTarget` describes the inspected app, /// not the Host; it only changes the ViewLayer group, whose title names /// the view class (`NSView` vs `UIView`), and the layout guide group. @@ -25,6 +25,6 @@ extension LookinAttributesGroup { // platform's actual class. return isMacTarget ? "NSLayoutGuide" : "UILayoutGuide" } - return LookinDashboardBlueprint.groupTitle(withGroupID: identifier) ?? "" + return DashboardBlueprint.groupTitle(withGroupID: identifier) ?? "" } } diff --git a/LookInside/Base/Category/LookinAutoLayoutConstraint+LookinClient.swift b/LookInside/Base/Category/LookinAutoLayoutConstraint+LookinClient.swift index d66f8a5f..c1c8eb29 100644 --- a/LookInside/Base/Category/LookinAutoLayoutConstraint+LookinClient.swift +++ b/LookInside/Base/Category/LookinAutoLayoutConstraint+LookinClient.swift @@ -1,5 +1,5 @@ // -// LookinAutoLayoutConstraint+LookinClient.swift +// AutoLayoutConstraint+LookinClient.swift // LookInside // // How constraints are written in the Dashboard's constraint rows and @@ -10,9 +10,9 @@ import AppKit import LookInsideHostCore -extension LookinAutoLayoutConstraint { +extension AutoLayoutConstraint { @objc(descriptionWithItemObject:type:detailed:) - static func description(withItemObject object: LookinObject?, type: LookinConstraintItemType, detailed: Bool) -> String { + static func description(withItemObject object: InspectedObject?, type: LookinConstraintItemType, detailed: Bool) -> String { switch type { case .`nil`: return detailed ? "Nil" : "nil" diff --git a/LookInside/Base/Category/LookinDisplayItem+LookinClient.swift b/LookInside/Base/Category/LookinDisplayItem+LookinClient.swift index c8d03f31..6e137043 100644 --- a/LookInside/Base/Category/LookinDisplayItem+LookinClient.swift +++ b/LookInside/Base/Category/LookinDisplayItem+LookinClient.swift @@ -1,5 +1,5 @@ // -// LookinDisplayItem+LookinClient.swift +// DisplayItem+LookinClient.swift // LookInside // // Host-side display helpers on the LookinCore display item: the row title @@ -12,7 +12,7 @@ import AppKit import LookInsideHostCore -extension LookinDisplayItem { +extension DisplayItem { /// The row text in the hierarchy, usually the class name without module. @objc func title() -> String { let baseTitle: String? @@ -208,8 +208,8 @@ extension LookinDisplayItem { /// Visits this item, then each ancestor up to the root, until stopped. @objc(enumerateSelfAndAncestors:) - func enumerateSelfAndAncestors(_ block: (LookinDisplayItem, UnsafeMutablePointer) -> Void) { - var item: LookinDisplayItem? = self + func enumerateSelfAndAncestors(_ block: (DisplayItem, UnsafeMutablePointer) -> Void) { + var item: DisplayItem? = self while let current = item { var shouldStop: ObjCBool = false block(current, &shouldStop) @@ -221,13 +221,13 @@ extension LookinDisplayItem { } @objc(enumerateAncestors:) - func enumerateAncestors(_ block: (LookinDisplayItem, UnsafeMutablePointer) -> Void) { + func enumerateAncestors(_ block: (DisplayItem, UnsafeMutablePointer) -> Void) { self.`super`?.enumerateSelfAndAncestors(block) } /// Visits this item and then its whole subtree, depth first. @objc(enumerateSelfAndChildren:) - func enumerateSelfAndChildren(_ block: (LookinDisplayItem) -> Void) { + func enumerateSelfAndChildren(_ block: (DisplayItem) -> Void) { block(self) for subitem in subitems ?? [] { subitem.enumerateSelfAndChildren(block) @@ -253,7 +253,7 @@ extension LookinDisplayItem { // MARK: - SwiftUI @objc func lk_isSwiftUISupportRelated() -> Bool { - func looksLikeSwiftUISupport(_ object: LookinObject?) -> Bool { + func looksLikeSwiftUISupport(_ object: InspectedObject?) -> Bool { guard let object else { return false } if ClientDisplayText.looksLikeSwiftUISupport(object.rawClassName()) { return true @@ -365,7 +365,7 @@ extension LookinDisplayItem { // MARK: - Private - private var allAttributeGroups: [LookinAttributesGroup] { + private var allAttributeGroups: [AttributesGroup] { (attributesGroupList ?? []) + (customAttrGroupList ?? []) } @@ -394,9 +394,9 @@ extension LookinDisplayItem { } } -private extension LookinAttributesGroup { +private extension AttributesGroup { /// Every attribute of every section, in order. - var lk_allAttributes: [LookinAttribute] { + var lk_allAttributes: [InspectedAttribute] { (attrSections ?? []).flatMap { $0.attributes ?? [] } } } diff --git a/LookInside/Base/Category/LookinObject+LookinClient.swift b/LookInside/Base/Category/LookinObject+LookinClient.swift index 0b7af5b4..5cfa8529 100644 --- a/LookInside/Base/Category/LookinObject+LookinClient.swift +++ b/LookInside/Base/Category/LookinObject+LookinClient.swift @@ -1,12 +1,12 @@ // -// LookinObject+LookinClient.swift +// InspectedObject+LookinClient.swift // LookInside // import Foundation import LookInsideHostCore -extension LookinObject { +extension InspectedObject { /// The demangled class name, module prefix included. @objc func lk_completedDemangledClassName() -> String { LKSwiftDemangler.completedParse(input: rawClassName() ?? "") diff --git a/LookInside/Base/LKBaseView.swift b/LookInside/Base/LKBaseView.swift index a01c6184..9eb40acd 100644 --- a/LookInside/Base/LKBaseView.swift +++ b/LookInside/Base/LKBaseView.swift @@ -53,7 +53,7 @@ class LKBaseView: NSView, NSViewToolTipOwner { } if customBorderLayer == nil { let borderLayer = CALayer() - borderLayer.lookin_removeImplicitAnimations() + borderLayer.removeImplicitAnimations() customBorderLayer = borderLayer updateColors() layer?.addSublayer(borderLayer) diff --git a/LookInside/Base/LKColorIndicatorLayer.swift b/LookInside/Base/LKColorIndicatorLayer.swift index 43837884..3bd48bb1 100644 --- a/LookInside/Base/LKColorIndicatorLayer.swift +++ b/LookInside/Base/LKColorIndicatorLayer.swift @@ -19,11 +19,11 @@ class LKColorIndicatorLayer: CALayer { override init() { super.init() - lookin_removeImplicitAnimations() + removeImplicitAnimations() borderWidth = 1 let colorLayer = CALayer() colorLayer.backgroundColor = color?.cgColor - colorLayer.lookin_removeImplicitAnimations() + colorLayer.removeImplicitAnimations() addSublayer(colorLayer) self.colorLayer = colorLayer masksToBounds = true @@ -68,7 +68,7 @@ class LKColorIndicatorLayer: CALayer { private func createImageLayerIfNeeded() { guard imageLayer == nil else { return } let imageLayer = CALayer() - imageLayer.lookin_removeImplicitAnimations() + imageLayer.removeImplicitAnimations() insertSublayer(imageLayer, at: 0) self.imageLayer = imageLayer setNeedsLayout() diff --git a/LookInside/Base/LKDeviceIconProvider.swift b/LookInside/Base/LKDeviceIconProvider.swift index 85f126d7..2c83f9c0 100644 --- a/LookInside/Base/LKDeviceIconProvider.swift +++ b/LookInside/Base/LKDeviceIconProvider.swift @@ -37,7 +37,7 @@ final class LKDeviceIconProvider: NSObject { /// - appInfo: The inspected app's info, as reported by LookinServer. /// - pointSize: The height the icon is laid out at, in points. @objc(deviceIconForAppInfo:pointSize:) - static func deviceIcon(forAppInfo appInfo: LookinAppInfo?, pointSize: CGFloat) -> NSImage? { + static func deviceIcon(forAppInfo appInfo: InspectedAppInfo?, pointSize: CGFloat) -> NSImage? { guard let appInfo, let modelIdentifier = appInfo.deviceModelIdentifier, modelIdentifier.isEmpty == false diff --git a/LookInside/Base/LKProgressIndicatorView.swift b/LookInside/Base/LKProgressIndicatorView.swift index 472df691..f9ba4769 100644 --- a/LookInside/Base/LKProgressIndicatorView.swift +++ b/LookInside/Base/LKProgressIndicatorView.swift @@ -32,7 +32,7 @@ class LKProgressIndicatorView: LKBaseView { private func setUp() { fillLayer.backgroundColor = LKHelper.accentColor().cgColor layer?.addSublayer(fillLayer) - fillLayer.lookin_removeImplicitAnimations() + fillLayer.removeImplicitAnimations() progress = 0 } diff --git a/LookInside/Base/LKTableRowView.swift b/LookInside/Base/LKTableRowView.swift index 974e08e0..f93b6049 100644 --- a/LookInside/Base/LKTableRowView.swift +++ b/LookInside/Base/LKTableRowView.swift @@ -75,7 +75,7 @@ class LKTableRowView: NSTableRowView { super.init(frame: frameRect) wantsLayer = true - backgroundColorLayer.lookin_removeImplicitAnimations() + backgroundColorLayer.removeImplicitAnimations() layer?.addSublayer(backgroundColorLayer) titleLabel.lineBreakMode = .byTruncatingMiddle diff --git a/LookInside/Base/LKTextsMenuView.swift b/LookInside/Base/LKTextsMenuView.swift index ba9e3225..77231a1a 100644 --- a/LookInside/Base/LKTextsMenuView.swift +++ b/LookInside/Base/LKTextsMenuView.swift @@ -23,7 +23,7 @@ class LKTextsMenuView: LKBaseView { didSet { updateAlignments() } } - @objc var texts: [LookinStringTwoTuple] = [] { + @objc var texts: [StringTwoTuple] = [] { didSet { reloadLabels() } } diff --git a/LookInside/Base/LKTipsView.swift b/LookInside/Base/LKTipsView.swift index 45a39a4a..361284be 100644 --- a/LookInside/Base/LKTipsView.swift +++ b/LookInside/Base/LKTipsView.swift @@ -76,7 +76,7 @@ class LKTipsView: LKBaseView { button.isHidden = true addSubview(button) - sepLayer.lookin_removeImplicitAnimations() + sepLayer.removeImplicitAnimations() sepLayer.isHidden = true layer?.addSublayer(sepLayer) @@ -156,7 +156,7 @@ class LKTipsView: LKBaseView { /// Prefers the icon of the hardware model the app runs on, falling back /// to the device family's icon when the Server reports no model. @objc(setImageByAppInfo:) - func setImage(byAppInfo appInfo: LookinAppInfo?) { + func setImage(byAppInfo appInfo: InspectedAppInfo?) { if let deviceIcon = LKDeviceIconProvider.deviceIcon(forAppInfo: appInfo, pointSize: LKDeviceIconProvider.tipsPointSize) { image = deviceIcon return diff --git a/LookInside/Connection/LKAppsManager.swift b/LookInside/Connection/LKAppsManager.swift index 73a4c73e..5467b263 100644 --- a/LookInside/Connection/LKAppsManager.swift +++ b/LookInside/Connection/LKAppsManager.swift @@ -35,12 +35,12 @@ final class LKAppsManager: NSObject { /// `serverVersionError` and no channel. Apps in the background, which /// cannot answer, and apps that require a license for app info are left /// out. - func fetchAppInfos(needImages: Bool, localInfos: [LookinAppInfo]?) async -> [LKInspectableApp] { + func fetchAppInfos(needImages: Bool, localInfos: [InspectedAppInfo]?) async -> [LKInspectableApp] { await scanApps(needImages: needImages, localInfos: localInfos).apps } /// `fetchAppInfos` plus how many channels were connected. - func scanApps(needImages: Bool, localInfos: [LookinAppInfo]?) async -> (apps: [LKInspectableApp], channelCount: Int) { + func scanApps(needImages: Bool, localInfos: [InspectedAppInfo]?) async -> (apps: [LKInspectableApp], channelCount: Int) { let now = Date().timeIntervalSince1970 let validAppInfos = (localInfos ?? []).filter { AppInfoCachePolicy.isFresh(cachedTimestamp: $0.cachedTimestamp, now: now) @@ -65,7 +65,7 @@ final class LKAppsManager: NSObject { private enum AppInfoOutcome { /// The app is in the background or did not answer. case none - case response(LookinConnectionResponseAttachment?) + case response(ConnectionResponseAttachment?) case versionError(NSError) } @@ -112,7 +112,7 @@ final class LKAppsManager: NSObject { } } - private func makeApp(from outcome: AppInfoOutcome, channel: LKChannel, validAppInfos: [LookinAppInfo]) -> LKInspectableApp? { + private func makeApp(from outcome: AppInfoOutcome, channel: LKChannel, validAppInfos: [InspectedAppInfo]) -> LKInspectableApp? { switch outcome { case .none: return nil @@ -136,7 +136,7 @@ final class LKAppsManager: NSObject { app.channel = channel return app } - var receivedInfo = response?.data as? LookinAppInfo + var receivedInfo = response?.data as? InspectedAppInfo receivedInfo?.cachedTimestamp = Date().timeIntervalSince1970 if let info = receivedInfo, info.shouldUseCache, let localInfo = validAppInfos.first(where: { $0.appInfoIdentifier == info.appInfoIdentifier }) diff --git a/LookInside/Connection/LKChannel.swift b/LookInside/Connection/LKChannel.swift index e7e660b6..7c6abb98 100644 --- a/LookInside/Connection/LKChannel.swift +++ b/LookInside/Connection/LKChannel.swift @@ -2,7 +2,7 @@ // LKChannel.swift // LookInside // -// One connection to an inspected app's Server: a LookinFrameChannel on a +// One connection to an inspected app's Server: a FrameChannel on a // loopback TCP socket (Simulator and Mac apps) or a usbmuxd tunnel (USB // devices), plus the state the connection manager keeps for it. Frames, // send completions and the end arrive on the main queue. @@ -38,7 +38,7 @@ final class LKChannel: NSObject { /// released with the channel. let connectionState = LKChannelConnectionState() - private let frameChannel: LookinFrameChannel + private let frameChannel: FrameChannel /// True until the channel ends or is closed. var isConnected: Bool { @@ -53,7 +53,7 @@ final class LKChannel: NSObject { self.kind = kind // The Host takes any payload size, as Peertalk did: a hierarchy // response can be large. - frameChannel = LookinFrameChannel( + frameChannel = FrameChannel( fileDescriptor: fileDescriptor, queue: .main, maxPayloadSize: .max, diff --git a/LookInside/Connection/LKConnectionManager.swift b/LookInside/Connection/LKConnectionManager.swift index 707c46df..a7fe2f06 100644 --- a/LookInside/Connection/LKConnectionManager.swift +++ b/LookInside/Connection/LKConnectionManager.swift @@ -75,7 +75,7 @@ final class LKConnectionManager: NSObject { private let simulatorPorts: [LKConnectionPort] private let macPorts: [LKConnectionPort] private var usbPorts: [LKConnectionPort] = [] - private let usbMuxClient = LookinUSBMuxClient(queue: .main) + private let usbMuxClient = USBMuxClient(queue: .main) private let channelWillEndBroadcaster = AsyncBroadcaster() private let pushBroadcaster = AsyncBroadcaster() @@ -167,7 +167,7 @@ final class LKConnectionManager: NSObject { // A blocking connect: on loopback it succeeds or fails with // ECONNREFUSED at once, so the completion runs before this // returns. - guard let fd = try? LookinSocket.connectLoopback(port: UInt16(port.number)) else { + guard let fd = try? SocketConnector.connectLoopback(port: UInt16(port.number)) else { completion(nil) return } @@ -310,7 +310,7 @@ final class LKConnectionManager: NSObject { /// throws the transport error or, for a frame that cannot be decoded, /// `LookinErr_Inner`. Cancelling the consuming task stops the delivery; /// the request on the channel runs to its end or its timeout. - func responses(type: UInt32, data: NSObject?, channel: LKChannel) -> AsyncThrowingStream { + func responses(type: UInt32, data: NSObject?, channel: LKChannel) -> AsyncThrowingStream { AsyncThrowingStream { continuation in let sink = LKResponseSink { event in switch event { @@ -334,7 +334,7 @@ final class LKConnectionManager: NSObject { } /// The first response of a request that answers once. - func request(type: UInt32, data: NSObject?, channel: LKChannel) async throws -> LookinConnectionResponseAttachment { + func request(type: UInt32, data: NSObject?, channel: LKChannel) async throws -> ConnectionResponseAttachment { for try await attachment in responses(type: type, data: data, channel: channel) { return attachment } @@ -362,7 +362,7 @@ final class LKConnectionManager: NSObject { } } - private func serverVersionError(for pingResponse: LookinConnectionResponseAttachment?) -> NSError? { + private func serverVersionError(for pingResponse: ConnectionResponseAttachment?) -> NSError? { let serverVersion = Int(pingResponse?.lookinServerVersion ?? 0) let supported = Int(LOOKIN_SUPPORTED_SERVER_MIN) ... Int(LOOKIN_SUPPORTED_SERVER_MAX) switch ServerVersionCompatibility(serverVersion: serverVersion, supported: supported) { @@ -428,7 +428,7 @@ final class LKConnectionManager: NSObject { channel?.connectionState.remove(request) } - let attachment = LookinConnectionAttachment() + let attachment = ConnectionAttachment() attachment.data = data let payload = archivedPayload(rootObject: attachment) // Track the request before the write: the write completion and the @@ -482,7 +482,7 @@ final class LKConnectionManager: NSObject { // Wire compatibility with upstream Lookin and the LookInside Server // send path: the payload is a non-secure archive of - // LookinConnectionResponseAttachment whose `data` is an arbitrary + // ConnectionResponseAttachment whose `data` is an arbitrary // graph of Lookin models and Foundation collections. Secure coding // with NSObject as the allowed class warns on every frame, so the // receive path stays non-secure on purpose. @@ -530,13 +530,13 @@ final class LKConnectionManager: NSObject { } } - private static func unarchiveResponse(_ data: Data) -> LookinConnectionResponseAttachment? { + private static func unarchiveResponse(_ data: Data) -> ConnectionResponseAttachment? { guard let unarchiver = try? NSKeyedUnarchiver(forReadingFrom: data) else { return nil } unarchiver.requiresSecureCoding = false defer { unarchiver.finishDecoding() } - return unarchiver.decodeObject(forKey: NSKeyedArchiveRootObjectKey) as? LookinConnectionResponseAttachment + return unarchiver.decodeObject(forKey: NSKeyedArchiveRootObjectKey) as? ConnectionResponseAttachment } private func handlePush(type: UInt32, data: Any?, channel: LKChannel) { diff --git a/LookInside/Connection/LKConnectionRequest.swift b/LookInside/Connection/LKConnectionRequest.swift index 3024c87d..3531edbf 100644 --- a/LookInside/Connection/LKConnectionRequest.swift +++ b/LookInside/Connection/LKConnectionRequest.swift @@ -12,7 +12,7 @@ import LookInsideHostCore /// failure or a completion. enum LKResponseEvent { /// One response frame. `nil` when its payload could not be decoded. - case response(LookinConnectionResponseAttachment?) + case response(ConnectionResponseAttachment?) case failure(NSError) case completion } diff --git a/LookInside/Connection/LKInspectableApp.swift b/LookInside/Connection/LKInspectableApp.swift index 71bb7e39..a148587d 100644 --- a/LookInside/Connection/LKInspectableApp.swift +++ b/LookInside/Connection/LKInspectableApp.swift @@ -25,7 +25,7 @@ final class LKInspectableApp: NSObject { /// answered the app info request with another error. @objc dynamic var serverVersionError: NSError? - @objc dynamic var appInfo: LookinAppInfo? + @objc dynamic var appInfo: InspectedAppInfo? @objc dynamic weak var channel: LKChannel? @@ -193,25 +193,25 @@ final class LKInspectableApp: NSObject { extension LKInspectableApp { @MainActor - func hierarchy() async throws -> LookinHierarchyInfo { - try await response(type: UInt32(LookinRequestTypeHierarchy), data: Self.hierarchyRequestParameters(), as: LookinHierarchyInfo.self) + func hierarchy() async throws -> HierarchyInfo { + try await response(type: UInt32(LookinRequestTypeHierarchy), data: Self.hierarchyRequestParameters(), as: HierarchyInfo.self) } /// Returns the updated detail of the modified item. @MainActor - func submit(_ modification: LookinAttributeModification) async throws -> LookinDisplayItemDetail { - try await response(type: UInt32(LookinRequestTypeInbuiltAttrModification), data: modification, as: LookinDisplayItemDetail.self) + func submit(_ modification: AttributeModification) async throws -> DisplayItemDetail { + try await response(type: UInt32(LookinRequestTypeInbuiltAttrModification), data: modification, as: DisplayItemDetail.self) } @MainActor - func submit(_ modification: LookinCustomAttrModification) async throws -> Any? { + func submit(_ modification: CustomAttributeModification) async throws -> Any? { try await response(type: UInt32(LookinRequestTypeCustomAttrModification), data: modification, as: Any?.self) } /// One array of details per package the Server finished. @MainActor - func hierarchyDetails(packages: [LookinStaticAsyncUpdateTasksPackage]) -> AsyncThrowingStream<[LookinDisplayItemDetail], Error> { - typedResponses(type: UInt32(LookinRequestTypeHierarchyDetails), data: packages as NSArray, as: [LookinDisplayItemDetail].self) + func hierarchyDetails(packages: [StaticAsyncUpdateTasksPackage]) -> AsyncThrowingStream<[DisplayItemDetail], Error> { + typedResponses(type: UInt32(LookinRequestTypeHierarchyDetails), data: packages as NSArray, as: [DisplayItemDetail].self) } /// Stops the running hierarchy details request: it completes, and the @@ -225,20 +225,20 @@ extension LKInspectableApp { /// One detail per modified item, as the Server finishes them. @MainActor - func modificationPatch(tasks: [LookinStaticAsyncUpdateTask]) -> AsyncThrowingStream { - typedResponses(type: UInt32(LookinRequestTypeAttrModificationPatch), data: tasks as NSArray, as: LookinDisplayItemDetail.self) + func modificationPatch(tasks: [StaticAsyncUpdateTask]) -> AsyncThrowingStream { + typedResponses(type: UInt32(LookinRequestTypeAttrModificationPatch), data: tasks as NSArray, as: DisplayItemDetail.self) } @MainActor - func object(oid: UInt) async throws -> LookinObject { + func object(oid: UInt) async throws -> InspectedObject { guard oid != 0 else { throw LKConnectionError.inner } - return try await response(type: UInt32(LookinRequestTypeFetchObject), data: NSNumber(value: oid), as: LookinObject.self) + return try await response(type: UInt32(LookinRequestTypeFetchObject), data: NSNumber(value: oid), as: InspectedObject.self) } @MainActor - func attributeGroups(oid: UInt) async throws -> [LookinAttributesGroup] { + func attributeGroups(oid: UInt) async throws -> [AttributesGroup] { guard oid != 0 else { throw LKConnectionError.inner } - return try await response(type: UInt32(LookinRequestTypeAllAttrGroups), data: NSNumber(value: oid), as: [LookinAttributesGroup].self) + return try await response(type: UInt32(LookinRequestTypeAllAttrGroups), data: NSNumber(value: oid), as: [AttributesGroup].self) } @MainActor diff --git a/LookInside/Connection/LKServerUpgradeHint.swift b/LookInside/Connection/LKServerUpgradeHint.swift index e82e25c8..05a11d89 100644 --- a/LookInside/Connection/LKServerUpgradeHint.swift +++ b/LookInside/Connection/LKServerUpgradeHint.swift @@ -41,7 +41,7 @@ enum LKServerUpgradeHint { /// The app's bundle identifier, which stays the same across relaunches /// and reconnections of that app. - private static func appKey(for appInfo: LookinAppInfo?) -> String? { + private static func appKey(for appInfo: InspectedAppInfo?) -> String? { guard let bundleIdentifier = appInfo?.appBundleIdentifier, !bundleIdentifier.isEmpty else { return nil } diff --git a/LookInside/Connection/LookinLiveDocument.swift b/LookInside/Connection/LookinLiveDocument.swift index 870ed709..43f622fe 100644 --- a/LookInside/Connection/LookinLiveDocument.swift +++ b/LookInside/Connection/LookinLiveDocument.swift @@ -34,7 +34,7 @@ final class LookinLiveDocument: NSDocument { /// The app info from before the channel ended, matched against the /// apps found while reconnecting. - private var lastKnownAppInfo: LookinAppInfo? + private var lastKnownAppInfo: InspectedAppInfo? private var channelEndTask: Task? private var reconnectTask: Task? diff --git a/LookInside/Console/LKConsoleDataSource.swift b/LookInside/Console/LKConsoleDataSource.swift index 2bd733e3..f88a5c44 100644 --- a/LookInside/Console/LKConsoleDataSource.swift +++ b/LookInside/Console/LKConsoleDataSource.swift @@ -31,7 +31,7 @@ struct LKConsoleRowItem { final class LKConsoleDataSource { /// An object returned by a call, with the call that returned it. struct RecentObject { - var object: LookinObject + var object: InspectedObject var message: String } @@ -47,13 +47,13 @@ final class LKConsoleDataSource { } /// The object calls are sent to. - private(set) var currentObject: LookinObject? { + private(set) var currentObject: InspectedObject? { didSet { currentObjectDidChange?() } } /// The objects of the item selected in the hierarchy: its view /// controller, window controller, layer, view, window and kind object. - private(set) var selectedObjects: [LookinObject] = [] { + private(set) var selectedObjects: [InspectedObject] = [] { didSet { syncConsoleTargetIfNeeded() } } @@ -77,14 +77,14 @@ final class LKConsoleDataSource { } } - private nonisolated static func objects(of item: LookinDisplayItem?) -> [LookinObject] { + private nonisolated static func objects(of item: DisplayItem?) -> [InspectedObject] { guard let item else { return [] } return [item.hostViewControllerObject, item.hostWindowControllerObject, item.layerObject, item.viewObject, item.windowObject, item.kindObject].compactMap { $0 } } var currentObjectSelectorNames: [String] { - currentObject.flatMap { selectorNamesByClass[$0.rawClassName()] } ?? [] + currentObject?.rawClassName().flatMap { selectorNamesByClass[$0] } ?? [] } func submit(_ text: String) async throws { @@ -93,7 +93,7 @@ final class LKConsoleDataSource { /// Calls `text` on `object` and appends the call and its result to the /// transcript. An object it returns joins the recent objects. - func submit(object: LookinObject?, text: String) async throws { + func submit(object: InspectedObject?, text: String) async throws { guard currentObject != nil, let object else { throw LKConnectionError.inner } @@ -123,7 +123,7 @@ final class LKConsoleDataSource { let result = try await inspectableApp.invokeMethod(oid: object.oid, text: text) let returnDescription = result["description"] as? String - let returnObject = result["object"] as? LookinObject + let returnObject = result["object"] as? InspectedObject let target = "<\(object.lk_simpleDemangledClassName()): \(object.memoryAddress ?? "(null)")>" var rows = rowItems @@ -138,7 +138,7 @@ final class LKConsoleDataSource { } /// Makes `object` the call target, fetching its class's selector names first when needed. - func makeObjectCurrent(_ object: LookinObject?) async throws { + func makeObjectCurrent(_ object: InspectedObject?) async throws { guard let object, let className = object.rawClassName(), !className.isEmpty else { throw LKConnectionError.inner } diff --git a/LookInside/Console/LKConsoleSelectPopoverController.swift b/LookInside/Console/LKConsoleSelectPopoverController.swift index ffc94400..91c46bc7 100644 --- a/LookInside/Console/LKConsoleSelectPopoverController.swift +++ b/LookInside/Console/LKConsoleSelectPopoverController.swift @@ -65,7 +65,7 @@ final class LKConsoleSelectPopoverController: LKBaseViewController { } } - separatorLayer.lookin_removeImplicitAnimations() + separatorLayer.removeImplicitAnimations() view.layer?.addSublayer(separatorLayer) view.didChangeAppearanceBlock = { [weak self] _, isDarkMode in self?.separatorLayer.backgroundColor = isDarkMode @@ -168,7 +168,7 @@ final class LKConsoleSelectPopoverController: LKBaseViewController { view.needsLayout = true } - private static func title(of object: LookinObject) -> String { + private static func title(of object: InspectedObject) -> String { "<\(object.lk_simpleDemangledClassName()): \(object.memoryAddress ?? "(null)")>" } @@ -249,7 +249,7 @@ final class LKConsoleSelectPopoverItemControl: LKBaseControl { } } - var representedObject: LookinObject? { + var representedObject: InspectedObject? { didSet { titleLabel.textColor = representedObject == nil ? .secondaryLabelColor : .labelColor } diff --git a/LookInside/Console/LKConsoleViewController.swift b/LookInside/Console/LKConsoleViewController.swift index b670b6c3..8f086d84 100644 --- a/LookInside/Console/LKConsoleViewController.swift +++ b/LookInside/Console/LKConsoleViewController.swift @@ -70,7 +70,7 @@ final class LKConsoleViewController: LKBaseViewController, LKTableViewDelegate, clearButton.action = #selector(handleClearButton) containerView.addSubview(clearButton) - topBorderLayer.lookin_removeImplicitAnimations() + topBorderLayer.removeImplicitAnimations() containerView.layer?.addSublayer(topBorderLayer) containerView.didChangeAppearanceBlock = { [weak self] _, isDarkMode in self?.topBorderLayer.backgroundColor = isDarkMode @@ -120,7 +120,7 @@ final class LKConsoleViewController: LKBaseViewController, LKTableViewDelegate, /// Calls `text` on `obj` and adds the call to the transcript; errors are only logged. @objc(submitWithObj:text:) - func submit(with obj: LookinObject?, text: String) { + func submit(with obj: InspectedObject?, text: String) { Task { do { try await dataSource.submit(object: obj, text: text) diff --git a/LookInside/Dashboard/AttributeView/Constraint/LKConstraintPopoverController.swift b/LookInside/Dashboard/AttributeView/Constraint/LKConstraintPopoverController.swift index 6df8623f..a5b3f483 100644 --- a/LookInside/Dashboard/AttributeView/Constraint/LKConstraintPopoverController.swift +++ b/LookInside/Dashboard/AttributeView/Constraint/LKConstraintPopoverController.swift @@ -17,16 +17,16 @@ final class LKConstraintPopoverController: LKBaseViewController { private var titleView: LKTextFieldView? private let textsView = LKTextsMenuView() - private var jumpObjects: [ObjectIdentifier: LookinObject] = [:] + private var jumpObjects: [ObjectIdentifier: InspectedObject] = [:] /// Asked to jump to an item of the constraint. - var requestJumpingToObject: ((LookinObject) -> Void)? + var requestJumpingToObject: ((InspectedObject) -> Void)? /// `canJumpToObject` decides whether an item's jump button is enabled: /// the item can be missing from the current tree (released, not /// captured, or from data that predates object identity). Nil enables /// every button. - init(constraint: LookinAutoLayoutConstraint, canJumpToObject: ((LookinObject) -> Bool)?) { + init(constraint: AutoLayoutConstraint, canJumpToObject: ((InspectedObject) -> Bool)?) { super.init(containerView: nil) if !constraint.effective { @@ -48,15 +48,15 @@ final class LKConstraintPopoverController: LKBaseViewController { textsView.type = .center view.addSubview(textsView) - func tuple(_ first: String, _ second: String?) -> LookinStringTwoTuple { - LookinStringTwoTuple(first: first, second: second ?? "") + func tuple(_ first: String, _ second: String?) -> StringTwoTuple { + StringTwoTuple(first: first, second: second ?? "") } let texts = [ - tuple("FirstItem", LookinAutoLayoutConstraint.description(withItemObject: constraint.firstItem, type: constraint.firstItemType, detailed: true)), - tuple("FirstAttribute", (LookinAutoLayoutConstraint.description(withAttributeInt: constraint.firstAttribute) as NSString).lk_capitalizedString()), - tuple("Relation", LookinAutoLayoutConstraint.description(with: constraint.relation)), - tuple("SecondItem", LookinAutoLayoutConstraint.description(withItemObject: constraint.secondItem, type: constraint.secondItemType, detailed: true)), - tuple("SecondAttribute", (LookinAutoLayoutConstraint.description(withAttributeInt: constraint.secondAttribute) as NSString).lk_capitalizedString()), + tuple("FirstItem", AutoLayoutConstraint.description(withItemObject: constraint.firstItem, type: constraint.firstItemType, detailed: true)), + tuple("FirstAttribute", (AutoLayoutConstraint.description(withAttributeInt: constraint.firstAttribute) as NSString).lk_capitalizedString()), + tuple("Relation", AutoLayoutConstraint.description(with: constraint.relation)), + tuple("SecondItem", AutoLayoutConstraint.description(withItemObject: constraint.secondItem, type: constraint.secondItemType, detailed: true)), + tuple("SecondAttribute", (AutoLayoutConstraint.description(withAttributeInt: constraint.secondAttribute) as NSString).lk_capitalizedString()), tuple("Multiplier", "\(NSNumber(value: Double(constraint.multiplier)))"), tuple("Constant", "\(NSNumber(value: Double(constraint.constant)))"), tuple("Priority", "\(NSNumber(value: Double(constraint.priority)))"), @@ -98,7 +98,7 @@ final class LKConstraintPopoverController: LKBaseViewController { return resultSize } - private func jumpButton(for jumpObject: LookinObject, canJumpToObject: ((LookinObject) -> Bool)?) -> NSButton { + private func jumpButton(for jumpObject: InspectedObject, canJumpToObject: ((InspectedObject) -> Bool)?) -> NSButton { let button = NSButton.lk_button(with: LKDashboardStyle.image("Icon_JumpDisclosure"), target: self, action: #selector(handleJumpButton(_:))) jumpObjects[ObjectIdentifier(button)] = jumpObject if let canJumpToObject, !canJumpToObject(jumpObject) { diff --git a/LookInside/Dashboard/AttributeView/Constraint/LKDashboardAttributeConstraintsView.swift b/LookInside/Dashboard/AttributeView/Constraint/LKDashboardAttributeConstraintsView.swift index 62429b89..cf74e564 100644 --- a/LookInside/Dashboard/AttributeView/Constraint/LKDashboardAttributeConstraintsView.swift +++ b/LookInside/Dashboard/AttributeView/Constraint/LKDashboardAttributeConstraintsView.swift @@ -11,7 +11,7 @@ import AppKit /// One constraint as a line of text, such as "self.width = 100 @ 750". /// Constraints that do not affect the view are greyed out. final class LKDashboardAttributeConstraintsItemControl: LKTextControl { - var constraint: LookinAutoLayoutConstraint? { + var constraint: AutoLayoutConstraint? { didSet { label.stringValue = constraint.map(Self.string(from:)) ?? "" updateLabelColor() @@ -41,24 +41,24 @@ final class LKDashboardAttributeConstraintsItemControl: LKTextControl { } } - static func string(from constraint: LookinAutoLayoutConstraint) -> String { - let firstItem = LookinAutoLayoutConstraint.description(withItemObject: constraint.firstItem, type: constraint.firstItemType, detailed: false) - let firstAttribute = LookinAutoLayoutConstraint.description(withAttributeInt: constraint.firstAttribute) - let relation = LookinAutoLayoutConstraint.symbol(with: constraint.relation) + static func string(from constraint: AutoLayoutConstraint) -> String { + let firstItem = AutoLayoutConstraint.description(withItemObject: constraint.firstItem, type: constraint.firstItemType, detailed: false) + let firstAttribute = AutoLayoutConstraint.description(withAttributeInt: constraint.firstAttribute) + let relation = AutoLayoutConstraint.symbol(with: constraint.relation) var string = "\(firstItem).\(firstAttribute) \(relation)" if constraint.secondAttribute == 0 { - string += " " + NSString.lookin_string(from: Double(constraint.constant), decimal: 3) + string += " " + NSString.string(from: Double(constraint.constant), decimal: 3) } else { - let secondItem = LookinAutoLayoutConstraint.description(withItemObject: constraint.secondItem, type: constraint.secondItemType, detailed: false) - let secondAttribute = LookinAutoLayoutConstraint.description(withAttributeInt: constraint.secondAttribute) + let secondItem = AutoLayoutConstraint.description(withItemObject: constraint.secondItem, type: constraint.secondItemType, detailed: false) + let secondAttribute = AutoLayoutConstraint.description(withAttributeInt: constraint.secondAttribute) string += " \(secondItem).\(secondAttribute)" if constraint.multiplier != 1 { - string += " * " + NSString.lookin_string(from: Double(constraint.multiplier), decimal: 3) + string += " * " + NSString.string(from: Double(constraint.multiplier), decimal: 3) } if constraint.constant > 0 { - string += " + " + NSString.lookin_string(from: Double(constraint.constant), decimal: 3) + string += " + " + NSString.string(from: Double(constraint.constant), decimal: 3) } else if constraint.constant < 0 { - string += " - " + NSString.lookin_string(from: Double(-constraint.constant), decimal: 3) + string += " - " + NSString.string(from: Double(-constraint.constant), decimal: 3) } } if constraint.priority != 1000 { @@ -91,7 +91,7 @@ final class LKDashboardAttributeConstraintsView: LKDashboardAttributeView { override func renderWithAttribute() { super.renderWithAttribute() - let rawData = attribute?.value as? [LookinAutoLayoutConstraint] ?? [] + let rawData = attribute?.value as? [AutoLayoutConstraint] ?? [] let constraints = LKDashboardConstraintOrder.sorted(rawData) while textControls.count < constraints.count { diff --git a/LookInside/Dashboard/AttributeView/LKDashboardAttributeEnumsView.swift b/LookInside/Dashboard/AttributeView/LKDashboardAttributeEnumsView.swift index f272eb34..d259b5ec 100644 --- a/LookInside/Dashboard/AttributeView/LKDashboardAttributeEnumsView.swift +++ b/LookInside/Dashboard/AttributeView/LKDashboardAttributeEnumsView.swift @@ -69,7 +69,7 @@ final class LKDashboardAttributeEnumsView: LKDashboardAttributeView { override func renderWithAttribute() { guard let attribute else { return } // Known attributes show their short title above the value. - if !attribute.isUserCustom(), let briefTitle = LookinDashboardBlueprint.briefTitle(withAttrID: attribute.identifier), !briefTitle.isEmpty { + if !attribute.isUserCustom(), let briefTitle = DashboardBlueprint.briefTitle(withAttrID: attribute.identifier), !briefTitle.isEmpty { titleLabel.stringValue = briefTitle titleLabel.isHidden = false } else { @@ -84,7 +84,7 @@ final class LKDashboardAttributeEnumsView: LKDashboardAttributeView { textLabel.stringValue = text } else { let enumValue = (attribute.value as? NSNumber)?.intValue ?? 0 - let enumListName = LookinDashboardBlueprint.enumListName(withAttrID: attribute.identifier) + let enumListName = DashboardBlueprint.enumListName(withAttrID: attribute.identifier) textLabel.stringValue = LKEnumListRegistry.shared.desc(forEnumName: enumListName, value: enumValue) ?? "" } } @@ -104,7 +104,7 @@ final class LKDashboardAttributeEnumsView: LKDashboardAttributeView { let currentOSVersion = dashboardViewController?.currentDataSource()?.rawHierarchyInfo?.appInfo?.osMainVersion ?? 0 let menu = NSMenu() menu.autoenablesItems = false - let enumListName = LookinDashboardBlueprint.enumListName(withAttrID: attribute?.identifier) + let enumListName = DashboardBlueprint.enumListName(withAttrID: attribute?.identifier) let currentValue = (attribute?.value as? NSNumber)?.intValue ?? 0 let editable = canEdit() for enumItem in LKEnumListRegistry.shared.items(forEnumName: enumListName) ?? [] { diff --git a/LookInside/Dashboard/AttributeView/LKDashboardAttributeGeometryViews.swift b/LookInside/Dashboard/AttributeView/LKDashboardAttributeGeometryViews.swift index 51365fe6..77cf88cd 100644 --- a/LookInside/Dashboard/AttributeView/LKDashboardAttributeGeometryViews.swift +++ b/LookInside/Dashboard/AttributeView/LKDashboardAttributeGeometryViews.swift @@ -147,7 +147,7 @@ final class LKDashboardAttributeRectView: LKDashboardAttributeFieldsView { override func fieldStrings(for value: NSValue) -> [String] { let rect = value.rectValue return [rect.origin.x, rect.origin.y, rect.size.width, rect.size.height].map { - NSString.lookin_string(from: Double($0), decimal: 3) + NSString.string(from: Double($0), decimal: 3) } } @@ -201,7 +201,7 @@ final class LKDashboardAttributeInsetsView: LKDashboardAttributeFieldsView { override func fieldStrings(for value: NSValue) -> [String] { let insets = value.edgeInsetsValue return [insets.top, insets.left, insets.bottom, insets.right].map { - NSString.lookin_string(from: Double($0), decimal: 3) + NSString.string(from: Double($0), decimal: 3) } } @@ -224,7 +224,7 @@ final class LKDashboardAttributePointView: LKDashboardAttributeFieldsView { override func fieldStrings(for value: NSValue) -> [String] { let point = value.pointValue - return [point.x, point.y].map { NSString.lookin_string(from: Double($0), decimal: 3) } + return [point.x, point.y].map { NSString.string(from: Double($0), decimal: 3) } } override func editedValue(from value: NSValue, field index: Int, number: Double) -> NSValue? { @@ -254,7 +254,7 @@ final class LKDashboardAttributeSizeView: LKDashboardAttributeFieldsView { let size = value.sizeValue return [size.width, size.height].map { dimension in // Extremely large values (CGFLOAT_MAX, for example) read as "Max". - dimension >= 1e15 ? "Max" : NSString.lookin_string(from: Double(dimension), decimal: 3) + dimension >= 1e15 ? "Max" : NSString.string(from: Double(dimension), decimal: 3) } } diff --git a/LookInside/Dashboard/AttributeView/LKDashboardAttributeNumberInputView.swift b/LookInside/Dashboard/AttributeView/LKDashboardAttributeNumberInputView.swift index 47a10861..0eee8ac1 100644 --- a/LookInside/Dashboard/AttributeView/LKDashboardAttributeNumberInputView.swift +++ b/LookInside/Dashboard/AttributeView/LKDashboardAttributeNumberInputView.swift @@ -140,20 +140,20 @@ final class LKDashboardAttributeNumberInputView: LKDashboardAttributeView, NSTex if attribute.isUserCustom() { inputView.title = nil } else { - inputView.title = LookinDashboardBlueprint.briefTitle(withAttrID: attribute.identifier) + inputView.title = DashboardBlueprint.briefTitle(withAttrID: attribute.identifier) } let doubleValue = (attribute.value as? NSNumber)?.doubleValue ?? 0 if attribute.isUserCustom() { inputView.viewStyle = .horizontal - textField.stringValue = NSString.lookin_string(from: doubleValue, decimal: 6) + textField.stringValue = NSString.string(from: doubleValue, decimal: 6) } else if Self.horizontalAttrs.contains(attribute.identifier ?? "") { inputView.viewStyle = .horizontal - textField.stringValue = NSString.lookin_string(from: doubleValue, decimal: 3) + textField.stringValue = NSString.string(from: doubleValue, decimal: 3) } else { inputView.viewStyle = .vertical - textField.stringValue = NSString.lookin_string(from: doubleValue, decimal: 2) + textField.stringValue = NSString.string(from: doubleValue, decimal: 2) } } diff --git a/LookInside/Dashboard/AttributeView/LKDashboardAttributeReadOnlyViews.swift b/LookInside/Dashboard/AttributeView/LKDashboardAttributeReadOnlyViews.swift index d45f6ea0..90a81981 100644 --- a/LookInside/Dashboard/AttributeView/LKDashboardAttributeReadOnlyViews.swift +++ b/LookInside/Dashboard/AttributeView/LKDashboardAttributeReadOnlyViews.swift @@ -145,7 +145,7 @@ final class LKDashboardAttributeShadowView: LKDashboardAttributeView { } let strings = [opacityNumber.doubleValue, radiusNumber.doubleValue, Double(offset.width), Double(offset.height)].map { - NSString.lookin_string(from: $0, decimal: 2) ?? "" + NSString.string(from: $0, decimal: 2) } for (view, string) in zip(inputViews, strings) { view.textFieldView.textField.stringValue = string diff --git a/LookInside/Dashboard/AttributeView/LKDashboardAttributeStringArrayView.swift b/LookInside/Dashboard/AttributeView/LKDashboardAttributeStringArrayView.swift index 5f6e83d9..c15c7d3f 100644 --- a/LookInside/Dashboard/AttributeView/LKDashboardAttributeStringArrayView.swift +++ b/LookInside/Dashboard/AttributeView/LKDashboardAttributeStringArrayView.swift @@ -18,7 +18,7 @@ class LKDashboardAttributeStringArrayView: LKDashboardAttributeView { private var danceButton: NSButton? /// The texts to list. Subclasses must override. - func stringList(with _: LookinAttribute) -> [String] { + func stringList(with _: InspectedAttribute) -> [String] { assertionFailure("should implement by subclass") return [] } @@ -82,7 +82,7 @@ class LKDashboardAttributeStringArrayView: LKDashboardAttributeView { } while sepLayers.count < separatorCount { let sepLayer = CALayer() - sepLayer.lookin_removeImplicitAnimations() + sepLayer.removeImplicitAnimations() layer?.addSublayer(sepLayer) sepLayers.append(sepLayer) } @@ -108,7 +108,7 @@ class LKDashboardAttributeStringArrayView: LKDashboardAttributeView { } } - private func danceSource(of attribute: LookinAttribute?) -> String? { + private func danceSource(of attribute: InspectedAttribute?) -> String? { let item = attribute?.targetDisplayItem return item?.danceuiSource ?? item?.customInfo?.danceuiSource } @@ -132,7 +132,7 @@ class LKDashboardAttributeStringArrayView: LKDashboardAttributeView { /// The class chain of the object, one class list per entry, demangled. @objc(LKDashboardAttributeClassView) final class LKDashboardAttributeClassView: LKDashboardAttributeStringArrayView { - override func stringList(with attribute: LookinAttribute) -> [String] { + override func stringList(with attribute: InspectedAttribute) -> [String] { let lists = attribute.value as? [[String]] ?? [] return lists.map { rawClassList in rawClassList.map { LKSwiftDemangler.completedParse(input: $0) }.joined(separator: "\n") @@ -149,13 +149,13 @@ final class LKDashboardAttributeRelationView: LKDashboardAttributeStringArrayVie private static let memberRegex = try! NSRegularExpression(pattern: #"\(\s*(\w+)\s*:\s*(\w+)\s*\*\s*\)"#) private static let objectRegex = try! NSRegularExpression(pattern: #"\(\s*(\w+)\s*\*\s*\)"#) - override func stringList(with attribute: LookinAttribute) -> [String] { - if let cache = attribute.lookin_getBindObject(forKey: Self.cacheKey) as? [String] { + override func stringList(with attribute: InspectedAttribute) -> [String] { + if let cache = attribute.getBindObject(forKey: Self.cacheKey) as? [String] { return cache } let raw = attribute.value as? [String] ?? [] let demangled = raw.map(Self.demangle) - attribute.lookin_bindObject(demangled, forKey: Self.cacheKey) + attribute.bindObject(demangled, forKey: Self.cacheKey) return demangled } diff --git a/LookInside/Dashboard/AttributeView/LKDashboardAttributeSwitchView.swift b/LookInside/Dashboard/AttributeView/LKDashboardAttributeSwitchView.swift index 406987c6..20664bcc 100644 --- a/LookInside/Dashboard/AttributeView/LKDashboardAttributeSwitchView.swift +++ b/LookInside/Dashboard/AttributeView/LKDashboardAttributeSwitchView.swift @@ -38,7 +38,7 @@ final class LKDashboardAttributeSwitchView: LKDashboardAttributeView { if attribute.isUserCustom() { title = attribute.displayTitle } else { - title = LookinDashboardBlueprint.briefTitle(withAttrID: attribute.identifier) + title = DashboardBlueprint.briefTitle(withAttrID: attribute.identifier) } button.attributedTitle = LKDashboardText.attributed(title ?? "", color: NSColor(named: "DashboardCardValueColor")) diff --git a/LookInside/Dashboard/AttributeView/LKDashboardAttributeTextView.swift b/LookInside/Dashboard/AttributeView/LKDashboardAttributeTextView.swift index 7e79c1ed..27af321c 100644 --- a/LookInside/Dashboard/AttributeView/LKDashboardAttributeTextView.swift +++ b/LookInside/Dashboard/AttributeView/LKDashboardAttributeTextView.swift @@ -71,7 +71,7 @@ final class LKDashboardAttributeTextView: LKDashboardAttributeView, NSTextViewDe override func renderWithAttribute() { guard let attribute else { return } // Known attributes show their short title above the value. - if !attribute.isUserCustom(), let briefTitle = LookinDashboardBlueprint.briefTitle(withAttrID: attribute.identifier), !briefTitle.isEmpty { + if !attribute.isUserCustom(), let briefTitle = DashboardBlueprint.briefTitle(withAttrID: attribute.identifier), !briefTitle.isEmpty { titleLabel.stringValue = briefTitle titleLabel.isHidden = false } else { @@ -108,7 +108,7 @@ final class LKDashboardAttributeTextView: LKDashboardAttributeView, NSTextViewDe backgroundColorName = "DashboardCardValueBGColor" } - private func jumpTargetItem() -> LookinDisplayItem? { + private func jumpTargetItem() -> DisplayItem? { dashboardViewController?.currentDataSource()?.swiftUIJumpTarget(for: attribute) } diff --git a/LookInside/Dashboard/AttributeView/LKDashboardAttributeView.swift b/LookInside/Dashboard/AttributeView/LKDashboardAttributeView.swift index 71833588..74e39937 100644 --- a/LookInside/Dashboard/AttributeView/LKDashboardAttributeView.swift +++ b/LookInside/Dashboard/AttributeView/LKDashboardAttributeView.swift @@ -14,7 +14,7 @@ import AppKit @objc(LKDashboardAttributeView) class LKDashboardAttributeView: LKBaseView { /// Setting the attribute renders it. - @objc var attribute: LookinAttribute? { + @objc var attribute: InspectedAttribute? { didSet { renderWithAttribute() } } @@ -39,7 +39,7 @@ class LKDashboardAttributeView: LKBaseView { if attribute.isUserCustom() { return !(attribute.customSetterID ?? "").isEmpty } - let setter = LookinDashboardBlueprint.setter(withAttrID: attribute.identifier) + let setter = DashboardBlueprint.setter(withAttrID: attribute.identifier) return setter != nil && (dashboardViewController?.isStaticMode ?? false) } diff --git a/LookInside/Dashboard/LKDashboardAccessoryWindowController.swift b/LookInside/Dashboard/LKDashboardAccessoryWindowController.swift index c8db0760..ec8f0ad4 100644 --- a/LookInside/Dashboard/LKDashboardAccessoryWindowController.swift +++ b/LookInside/Dashboard/LKDashboardAccessoryWindowController.swift @@ -35,7 +35,7 @@ final class LKDashboardAccessoryWindowController: LKWindowController, NSWindowDe } /// Shows `sections` and returns the window size they need. - func render(attrSections sections: [LookinAttributesSection]) -> NSSize { + func render(attrSections sections: [AttributesSection]) -> NSSize { var needlessViews = Array(sectionViews.values) for (idx, section) in sections.enumerated() { @@ -60,7 +60,7 @@ final class LKDashboardAccessoryWindowController: LKWindowController, NSWindowDe let normalSectionWidth = LKDashboardMetrics.viewWidth - LKDashboardMetrics.horInset * 2 var y: CGFloat = 8 - for sectionID in LookinDashboardBlueprint.sectionIDs(forGroupID: groupID) ?? [] { + for sectionID in DashboardBlueprint.sectionIDs(forGroupID: groupID) ?? [] { guard let view = sectionViews[sectionID], !view.isHidden else { continue } view.dashboardLayout.x(LKDashboardMetrics.horInset).width(normalSectionWidth - LKDashboardMetrics.horInset * 2).heightToFit().y(y) y = view.frame.maxY + LKDashboardMetrics.sectionMarginTop diff --git a/LookInside/Dashboard/LKDashboardCardView.swift b/LookInside/Dashboard/LKDashboardCardView.swift index d44ede6b..fc30d54d 100644 --- a/LookInside/Dashboard/LKDashboardCardView.swift +++ b/LookInside/Dashboard/LKDashboardCardView.swift @@ -76,7 +76,7 @@ final class LKDashboardCardView: LKBaseView, LKUserActionManagerDelegate, LKDash weak var delegate: LKDashboardCardViewDelegate? /// The group to render; setting it does not render. - var attrGroup: LookinAttributesGroup? + var attrGroup: AttributesGroup? var isCollapsed = false { didSet { @@ -181,7 +181,7 @@ final class LKDashboardCardView: LKBaseView, LKUserActionManagerDelegate, LKDash sectionViewPool.recycleAll() for (idx, section) in (attrGroup.attrSections ?? []).enumerated() { - if !section.isUserCustom() && !LKPreferenceManager.shared.isSectionShowing(section.identifier) { + if !section.isUserCustom() && !(section.identifier.map { LKPreferenceManager.shared.isSectionShowing($0) } ?? false) { continue } let sectionView = sectionViewPool.dequeueView(for: section) @@ -206,7 +206,7 @@ final class LKDashboardCardView: LKBaseView, LKUserActionManagerDelegate, LKDash needsLayout = true } - func querySectionView(with section: LookinAttributesSection) -> LKDashboardSectionView? { + func querySectionView(with section: AttributesSection) -> LKDashboardSectionView? { sectionViews.first { $0.attrSection === section } } @@ -277,7 +277,7 @@ final class LKDashboardCardView: LKBaseView, LKUserActionManagerDelegate, LKDash /// `isSwiftUIGroup`: the SwiftUI groups are user-custom groups whose /// title begins with "SwiftUI" ("SwiftUI Type", "SwiftUI Layout"), which /// the upstream user-custom path never produces. Remove with v8 support. - static func looksLikeSwiftUI(_ group: LookinAttributesGroup) -> Bool { + static func looksLikeSwiftUI(_ group: AttributesGroup) -> Bool { group.isSwiftUIGroup || (group.userCustomTitle?.hasPrefix("SwiftUI") ?? false) } @@ -340,7 +340,7 @@ final class LKDashboardCardView: LKBaseView, LKUserActionManagerDelegate, LKDash // groups once shipped with a borrowed icon. This covers the groups // compiled for this platform; the iOS-only groups rely on the // per-lookup assertion. - for groupID in LookinDashboardBlueprint.groupIDs() ?? [] { + for groupID in DashboardBlueprint.groupIDs() { assert(names[groupID] != nil, "missing dashboard icon for group \(groupID)") } #endif @@ -351,7 +351,7 @@ final class LKDashboardCardView: LKBaseView, LKUserActionManagerDelegate, LKDash /// places: this table, the group title, the default sections and (when /// it has enums) the enum lists. An unregistered group falls back to a /// generic icon. - static func image(for group: LookinAttributesGroup) -> NSImage? { + static func image(for group: AttributesGroup) -> NSImage? { let name = groupIconNames[group.identifier ?? ""] assert(name != nil, "missing dashboard icon for group \(group.identifier ?? "nil")") return LKDashboardStyle.image(name ?? "dashboard_layer") @@ -445,7 +445,7 @@ final class LKDashboardCardView: LKBaseView, LKUserActionManagerDelegate, LKDash sectionViews.forEach { $0.manageState = .canRemove } - let allSectionIDs = LookinDashboardBlueprint.sectionIDs(forGroupID: attrGroup.identifier) ?? [] + let allSectionIDs = DashboardBlueprint.sectionIDs(forGroupID: attrGroup.identifier) ?? [] let hiddenSectionIDs = allSectionIDs.filter { !LKPreferenceManager.shared.isSectionShowing($0) } if hiddenSectionIDs.isEmpty { controller.window?.contentView?.isHidden = true @@ -487,7 +487,7 @@ final class LKDashboardCardView: LKBaseView, LKUserActionManagerDelegate, LKDash // The group's own section count, not the blueprint's: some groups // (Layout for NSWindow, for example) are built with fewer sections. let actualCount = attrGroup?.attrSections?.count ?? 0 - let blueprintCount = LookinDashboardBlueprint.sectionIDs(forGroupID: groupID)?.count ?? 0 + let blueprintCount = DashboardBlueprint.sectionIDs(forGroupID: groupID)?.count ?? 0 return min(actualCount, blueprintCount) > 1 } } diff --git a/LookInside/Dashboard/LKDashboardModification.swift b/LookInside/Dashboard/LKDashboardModification.swift index ee3cda0b..daeeb46c 100644 --- a/LookInside/Dashboard/LKDashboardModification.swift +++ b/LookInside/Dashboard/LKDashboardModification.swift @@ -15,11 +15,11 @@ enum LKDashboardModification { /// attribute's identifier, called on the object the attribute belongs /// to (view, layer, window or cell of the item). Nil when the /// identifier has no setter. - static func inbuilt(attribute: LookinAttribute, newValue: Any?, clientReadableVersion: String?) -> LookinAttributeModification? { - let modification = LookinAttributeModification() + static func inbuilt(attribute: InspectedAttribute, newValue: Any?, clientReadableVersion: String?) -> AttributeModification? { + let modification = AttributeModification() modification.clientReadableVersion = clientReadableVersion let item = attribute.targetDisplayItem - switch LookinDashboardBlueprint.targetKind(forAttrID: attribute.identifier) { + switch DashboardBlueprint.targetKind(forAttrID: attribute.identifier) { case .view: modification.targetOid = item?.viewObject?.oid ?? 0 case .window: @@ -31,7 +31,7 @@ enum LKDashboardModification { @unknown default: modification.targetOid = item?.layerObject?.oid ?? 0 } - guard let setter = LookinDashboardBlueprint.setter(withAttrID: attribute.identifier) else { + guard let setter = DashboardBlueprint.setter(withAttrID: attribute.identifier) else { return nil } modification.setterSelector = setter @@ -43,11 +43,11 @@ enum LKDashboardModification { /// The request for a user-custom attribute: its setter id with the new /// value. Nil when the attribute has no setter (read-only rows, such as /// the SwiftUI attributes). - static func custom(attribute: LookinAttribute, newValue: Any?) -> LookinCustomAttrModification? { + static func custom(attribute: InspectedAttribute, newValue: Any?) -> CustomAttributeModification? { guard let setterID = attribute.customSetterID, !setterID.isEmpty else { return nil } - let modification = LookinCustomAttrModification() + let modification = CustomAttributeModification() modification.customSetterID = setterID modification.attrType = attribute.attrType modification.value = newValue @@ -64,7 +64,7 @@ enum LKDashboardModification { /// The number to submit for a number attribute, or nil when it equals /// the current value (nothing to submit). - static func numberValue(_ parsed: NSNumber, for attribute: LookinAttribute) -> NSNumber? { + static func numberValue(_ parsed: NSNumber, for attribute: InspectedAttribute) -> NSNumber? { var value = parsed if clampedToUnitIdentifiers.contains(attribute.identifier ?? "") { value = NSNumber(value: max(min(parsed.doubleValue, 1), 0)) @@ -155,10 +155,10 @@ enum LKDashboardConstraintOrder { /// The order the constraints card lists constraints in: effective ones /// first, then by first item type and first attribute. The sort is /// stable, as `-sortedArrayUsingComparator:` is. - static func sorted(_ constraints: [LookinAutoLayoutConstraint]) -> [LookinAutoLayoutConstraint] { + static func sorted(_ constraints: [AutoLayoutConstraint]) -> [AutoLayoutConstraint] { let array = constraints as NSArray let sorted = array.sortedArray(options: .stable) { lhs, rhs in - guard let lhs = lhs as? LookinAutoLayoutConstraint, let rhs = rhs as? LookinAutoLayoutConstraint else { + guard let lhs = lhs as? AutoLayoutConstraint, let rhs = rhs as? AutoLayoutConstraint else { return .orderedSame } if lhs.effective != rhs.effective { @@ -172,6 +172,6 @@ enum LKDashboardConstraintOrder { } return .orderedSame } - return sorted.compactMap { $0 as? LookinAutoLayoutConstraint } + return sorted.compactMap { $0 as? AutoLayoutConstraint } } } diff --git a/LookInside/Dashboard/LKDashboardSectionView.swift b/LookInside/Dashboard/LKDashboardSectionView.swift index 05be5805..9204f930 100644 --- a/LookInside/Dashboard/LKDashboardSectionView.swift +++ b/LookInside/Dashboard/LKDashboardSectionView.swift @@ -34,7 +34,7 @@ final class LKDashboardSectionView: LKBaseView { // Lets the separator run past the right edge. layer?.masksToBounds = false - topSepLayer.lookin_removeImplicitAnimations() + topSepLayer.removeImplicitAnimations() layer?.addSublayer(topSepLayer) updateColors() @@ -44,7 +44,7 @@ final class LKDashboardSectionView: LKBaseView { fatalError("init(coder:) is not supported") } - var attrSection: LookinAttributesSection? { + var attrSection: AttributesSection? { didSet { renderSection() } } @@ -308,7 +308,7 @@ final class LKDashboardSectionView: LKBaseView { private func resolveSectionTitle() -> String? { guard let attrSection else { return nil } if !attrSection.isUserCustom() { - return LookinDashboardBlueprint.sectionTitle(withSectionID: attrSection.identifier) + return DashboardBlueprint.sectionTitle(withSectionID: attrSection.identifier) } guard let attr = attrSection.attributes?.first else { assertionFailure() @@ -372,7 +372,7 @@ final class LKDashboardSectionViewPool { dequeuedViews.removeAll() } - func dequeueView(for section: LookinAttributesSection) -> LKDashboardSectionView { + func dequeueView(for section: AttributesSection) -> LKDashboardSectionView { let key = Self.cacheKey(for: section) if let view = cache[key, default: []].first(where: { !dequeuedViews.contains(ObjectIdentifier($0)) }) { dequeuedViews.insert(ObjectIdentifier(view)) @@ -384,7 +384,7 @@ final class LKDashboardSectionViewPool { return view } - static func cacheKey(for section: LookinAttributesSection) -> String { + static func cacheKey(for section: AttributesSection) -> String { if !section.isUserCustom() { return section.identifier ?? "" } diff --git a/LookInside/Dashboard/LKDashboardViewController.swift b/LookInside/Dashboard/LKDashboardViewController.swift index 43581d1c..7fbe054a 100644 --- a/LookInside/Dashboard/LKDashboardViewController.swift +++ b/LookInside/Dashboard/LKDashboardViewController.swift @@ -21,8 +21,8 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView private var searchContainerView: LKBaseView! private var headerView: LKDashboardHeaderView! - private var groupList: [LookinAttributesGroup] = [] - /// Keyed by `LookinAttributesGroup.uniqueKey`. + private var groupList: [AttributesGroup] = [] + /// Keyed by `AttributesGroup.uniqueKey`. private var cardViews: [String: LKDashboardCardView] = [:] private var searchPropViews: [LKDashboardSearchPropView] = [] @@ -166,7 +166,7 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView cardContainerView.dashboardLayout.width(contentWidth).x(horInset).y(headerView.frame.maxY + verMargin) var y: CGFloat = 0 for group in groupList { - guard let view = cardViews[group.uniqueKey()], !view.isHidden else { continue } + guard let view = cardViews[group.uniqueKey() ?? ""], !view.isHidden else { continue } view.dashboardLayout.width(contentWidth).y(y).heightToFit() y = view.frame.maxY + verMargin } @@ -192,16 +192,16 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView // MARK: - Rendering - private func groupList(for item: LookinDisplayItem?) -> [LookinAttributesGroup] { + private func groupList(for item: DisplayItem?) -> [AttributesGroup] { guard let item else { return [] } - let groups = LKPrivateDiscriminatorStore.shared.appendingPrivateDiscriminatorGroup(to: item.queryAllAttrGroupList() ?? [], for: item) + let groups = LKPrivateDiscriminatorStore.shared.appendingPrivateDiscriminatorGroup(to: item.queryAllAttrGroupList(), for: item) // Cards are keyed by uniqueKey, so a duplicated key would lay the // shared card out twice and leave a blank gap. Servers 0.2.8 and // 0.2.9 sent a duplicate Layout group for UIWindowScene nodes. - return LookinAttributesGroup.groupsByKeepingFirstGroup(forEachUniqueKey: groups) ?? [] + return AttributesGroup.groupsByKeepingFirstGroup(forEachUniqueKey: groups) } - private func reload(groupList list: [LookinAttributesGroup]) { + private func reload(groupList list: [AttributesGroup]) { groupList = list if list.isEmpty { @@ -255,7 +255,7 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView /// whether a modification was made: a user-custom attribute without a /// setter (such as the SwiftUI attributes) is left alone. Failures are /// shown in the window, then thrown. - func modifyAttribute(_ attribute: LookinAttribute, newValue: Any?) async throws -> Bool { + func modifyAttribute(_ attribute: InspectedAttribute, newValue: Any?) async throws -> Bool { if attribute.isUserCustom() { // The attribute views already refuse edits of read-only // attributes; this keeps any other caller from sending one. @@ -274,7 +274,7 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView return error } - private func modifyCustomAttribute(_ attribute: LookinAttribute, newValue: Any?) async throws { + private func modifyCustomAttribute(_ attribute: InspectedAttribute, newValue: Any?) async throws { guard let modification = LKDashboardModification.custom(attribute: attribute, newValue: newValue) else { assertionFailure() throw failModification(LKConnectionError.inner) @@ -292,7 +292,7 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView attribute.value = newValue } - private func modifyInbuiltAttribute(_ attribute: LookinAttribute, newValue: Any?) async throws { + private func modifyInbuiltAttribute(_ attribute: InspectedAttribute, newValue: Any?) async throws { let modifyingItem = attribute.targetDisplayItem guard let modification = LKDashboardModification.inbuilt(attribute: attribute, newValue: newValue, clientReadableVersion: LKHelper.lookinReadableVersion()) else { assertionFailure() @@ -302,7 +302,7 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView guard let inspectableApp = liveDocument?.inspectableApp else { throw failModification(LKConnectionError.noConnect) } - let detail: LookinDisplayItemDetail + let detail: DisplayItemDetail do { detail = try await inspectableApp.submit(modification) } catch { @@ -321,7 +321,7 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView staticDataSource.modify(with: detail) LKDashboardTextControlEditingFlag.shared.shouldIgnoreTextEditingChangeEvent = false - if LookinDashboardBlueprint.needPatchAfterModification(withAttrID: attribute.identifier), let modifyingItem { + if DashboardBlueprint.needPatchAfterModification(withAttrID: attribute.identifier), let modifyingItem { _ = asyncUpdateManager?.perform(Selector(("updateAfterModifyingDisplayItem:")), with: modifyingItem) } } @@ -351,11 +351,11 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView let searchString = string.lowercased() // Attributes - var resultAttrs: [LookinAttribute] = [] + var resultAttrs: [InspectedAttribute] = [] for group in groupList(for: currentDataSource()?.selectedItem) { for section in group.attrSections ?? [] { for attr in section.attributes ?? [] { - let title = attr.isUserCustom() ? attr.displayTitle : LookinDashboardBlueprint.fullTitle(withAttrID: attr.identifier) + let title = attr.isUserCustom() ? attr.displayTitle : DashboardBlueprint.fullTitle(withAttrID: attr.identifier) if (title ?? "").lowercased().contains(searchString) { resultAttrs.append(attr) } @@ -462,15 +462,15 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView // MARK: - LKDashboardSearchPropViewDelegate - func dashboardSearchPropView(_: LKDashboardSearchPropView, didClickRevealAttribute clickedAttribute: LookinAttribute) { + func dashboardSearchPropView(_: LKDashboardSearchPropView, didClickRevealAttribute clickedAttribute: InspectedAttribute) { headerView.isActive = false - var target: (group: LookinAttributesGroup, section: LookinAttributesSection)? + var target: (group: AttributesGroup, section: AttributesSection)? search: for group in groupList(for: currentDataSource()?.selectedItem) { for section in group.attrSections ?? [] where (section.attributes ?? []).contains(where: { $0 === clickedAttribute }) { - if !LKPreferenceManager.shared.isSectionShowing(section.identifier) { + if let identifier = section.identifier, !LKPreferenceManager.shared.isSectionShowing(identifier) { // Adds the section to its card. - LKPreferenceManager.shared.showSection(section.identifier) + LKPreferenceManager.shared.showSection(identifier) } target = (group, section) break search diff --git a/LookInside/Dashboard/LKEnumListRegistry.swift b/LookInside/Dashboard/LKEnumListRegistry.swift index ca7e4940..5960f1a1 100644 --- a/LookInside/Dashboard/LKEnumListRegistry.swift +++ b/LookInside/Dashboard/LKEnumListRegistry.swift @@ -6,7 +6,7 @@ // https://lookin.work // // The values and names of every enum the Dashboard can show and edit, -// keyed by the enum list name `LookinDashboardBlueprint` gives an +// keyed by the enum list name `DashboardBlueprint` gives an // attribute. Foundation only, so the tests can compile it on its own. // diff --git a/LookInside/Dashboard/Search/LKDashboardSearchViews.swift b/LookInside/Dashboard/Search/LKDashboardSearchViews.swift index c038665b..90e57623 100644 --- a/LookInside/Dashboard/Search/LKDashboardSearchViews.swift +++ b/LookInside/Dashboard/Search/LKDashboardSearchViews.swift @@ -34,7 +34,7 @@ class LKDashboardSearchCardView: LKBaseView { } protocol LKDashboardSearchPropViewDelegate: AnyObject { - func dashboardSearchPropView(_ view: LKDashboardSearchPropView, didClickRevealAttribute attribute: LookinAttribute) + func dashboardSearchPropView(_ view: LKDashboardSearchPropView, didClickRevealAttribute attribute: InspectedAttribute) } /// One matching attribute: its title, its value as text, and a button that @@ -45,7 +45,7 @@ final class LKDashboardSearchPropView: LKDashboardSearchCardView { private let titleLabel = LKLabel() private let contentLabel = LKLabel() private let revealControl = LKTextControl() - private var attribute: LookinAttribute? + private var attribute: InspectedAttribute? weak var delegate: LKDashboardSearchPropViewDelegate? @@ -100,9 +100,9 @@ final class LKDashboardSearchPropView: LKDashboardSearchCardView { revealControl.label.attributedStringValue = text } - func render(attribute: LookinAttribute) { + func render(attribute: InspectedAttribute) { self.attribute = attribute - titleLabel.stringValue = attribute.displayTitle ?? LookinDashboardBlueprint.fullTitle(withAttrID: attribute.identifier) ?? "" + titleLabel.stringValue = attribute.displayTitle ?? DashboardBlueprint.fullTitle(withAttrID: attribute.identifier) ?? "" contentLabel.stringValue = Self.stringValue(of: attribute) needsLayout = true } @@ -113,7 +113,7 @@ final class LKDashboardSearchPropView: LKDashboardSearchCardView { } /// The attribute's value as one line of text. - static func stringValue(of attribute: LookinAttribute) -> String { + static func stringValue(of attribute: InspectedAttribute) -> String { switch attribute.attrType { case .none, .void, .customObj: assertionFailure() @@ -127,23 +127,23 @@ final class LKDashboardSearchPropView: LKDashboardSearchCardView { return (attribute.value as? NSNumber)?.boolValue == true ? "YES" : "NO" case .cgPoint: - return NSString.lookin_string(from: (attribute.value as? NSValue)?.pointValue ?? .zero) + return NSString.string(from: (attribute.value as? NSValue)?.pointValue ?? .zero) case .cgSize: - return NSString.lookin_string(from: (attribute.value as? NSValue)?.sizeValue ?? .zero) + return NSString.string(from: (attribute.value as? NSValue)?.sizeValue ?? .zero) case .cgRect: - return NSString.lookin_string(from: (attribute.value as? NSValue)?.rectValue ?? .zero) + return NSString.string(from: (attribute.value as? NSValue)?.rectValue ?? .zero) case .uiEdgeInsets: - return NSString.lookin_string(fromInset: (attribute.value as? NSValue)?.edgeInsetsValue ?? NSEdgeInsetsZero) + return NSString.string(fromInset: (attribute.value as? NSValue)?.edgeInsetsValue ?? NSEdgeInsetsZero) case .nsString, .enumString: return attribute.value as? String ?? "" case .enumInt, .enumLong: let enumValue = (attribute.value as? NSNumber)?.intValue ?? 0 - let enumListName = LookinDashboardBlueprint.enumListName(withAttrID: attribute.identifier) + let enumListName = DashboardBlueprint.enumListName(withAttrID: attribute.identifier) return LKEnumListRegistry.shared.desc(forEnumName: enumListName, value: enumValue) ?? "" case .uiColor: diff --git a/LookInside/DebugE2E/LKDebugE2EDumpWriter.swift b/LookInside/DebugE2E/LKDebugE2EDumpWriter.swift index c0c610a0..f4148ebd 100644 --- a/LookInside/DebugE2E/LKDebugE2EDumpWriter.swift +++ b/LookInside/DebugE2E/LKDebugE2EDumpWriter.swift @@ -144,7 +144,7 @@ /// `completion` runs on the main thread, after this method returns. @objc(fetchHierarchyForApp:completion:) @MainActor - static func fetchHierarchy(for app: LKInspectableApp, completion: @escaping (LookinHierarchyInfo?, Error?) -> Void) { + static func fetchHierarchy(for app: LKInspectableApp, completion: @escaping (HierarchyInfo?, Error?) -> Void) { Task { @MainActor in do { try completion(await app.hierarchy(), nil) diff --git a/LookInside/DebugE2E/LKDebugUISnapshots.swift b/LookInside/DebugE2E/LKDebugUISnapshots.swift index bd728208..555eef72 100644 --- a/LookInside/DebugE2E/LKDebugUISnapshots.swift +++ b/LookInside/DebugE2E/LKDebugUISnapshots.swift @@ -298,14 +298,14 @@ // MARK: - Driving the UI - private func node(_ id: String, in nodes: [LookinSnapshotNormalizer.Node]) throws -> LookinDisplayItem { + private func node(_ id: String, in nodes: [LookinSnapshotNormalizer.Node]) throws -> DisplayItem { guard let node = nodes.first(where: { $0.id == id }) else { throw LookinSnapshotError("no node \(id)") } return node.item } - private func select(_ item: LookinDisplayItem, in dataSource: LKHierarchyDataSource) { + private func select(_ item: DisplayItem, in dataSource: LKHierarchyDataSource) { // A fresh selection, so the dashboard renders its cards again // with the current collapsed-group preference. dataSource.selectedItem = nil diff --git a/LookInside/DebugE2E/LookinSnapshotNormalizer.swift b/LookInside/DebugE2E/LookinSnapshotNormalizer.swift index c54f7736..28a2006a 100644 --- a/LookInside/DebugE2E/LookinSnapshotNormalizer.swift +++ b/LookInside/DebugE2E/LookinSnapshotNormalizer.swift @@ -32,10 +32,10 @@ let id: String let parentID: String let depth: Int - let item: LookinDisplayItem + let item: DisplayItem } - static func className(of item: LookinDisplayItem) -> String { + static func className(of item: DisplayItem) -> String { for object in [item.viewObject, item.layerObject, item.windowObject, item.kindObject, item.cellObject] { if let object, let name = object.rawClassName(), !name.isEmpty { return name @@ -50,7 +50,7 @@ /// Depth-first nodes with stable ids: the class path from the root, /// each step suffixed with its index among same-class siblings. The /// ids survive oid / address churn. - static func collectNodes(roots: [LookinDisplayItem]) -> [Node] { + static func collectNodes(roots: [DisplayItem]) -> [Node] { var nodes: [Node] = [] for (index, root) in roots.enumerated() { collect(root, parentID: "", siblingIndex: index, siblings: roots, depth: 0, into: &nodes) @@ -59,10 +59,10 @@ } private static func collect( - _ item: LookinDisplayItem, + _ item: DisplayItem, parentID: String, siblingIndex: Int, - siblings: [LookinDisplayItem], + siblings: [DisplayItem], depth: Int, into nodes: inout [Node] ) { @@ -82,8 +82,8 @@ /// other sibling keeps its place. The Server does not keep the order /// of identical SwiftUI views stable from launch to launch (a /// ZStack's ForEach circles come back in either direction). - static func canonicalSiblingOrder(_ items: [LookinDisplayItem]) -> [LookinDisplayItem] { - func frameKey(_ item: LookinDisplayItem) -> [Double] { + static func canonicalSiblingOrder(_ items: [DisplayItem]) -> [DisplayItem] { + func frameKey(_ item: DisplayItem) -> [Double] { if let rect = item.customInfo?.frameInWindow?.rectValue { return [rect.origin.x, rect.origin.y, rect.size.width, rect.size.height].map(Double.init) } @@ -191,7 +191,7 @@ /// The oid the Host puts in the detail task for this node; mirrors /// -[LKStaticAsyncUpdateManager _taskFromDisplayItem:type:] with the /// backing-layer toggle off. - static func taskOid(for item: LookinDisplayItem, macTarget: Bool) -> UInt { + static func taskOid(for item: DisplayItem, macTarget: Bool) -> UInt { switch item.resolvedNodeKind() { case .window, .windowScene: return item.windowObject?.oid ?? 0 @@ -214,7 +214,7 @@ /// Windows always get a group screenshot: that is the picture of the /// whole UI. iOS reports a UIWindow as a plain view node under its scene. - static func isWindow(_ item: LookinDisplayItem) -> Bool { + static func isWindow(_ item: DisplayItem) -> Bool { if item.resolvedNodeKind() == .window { return true } @@ -224,12 +224,12 @@ // MARK: - Records - /// LookinAppInfo encodes its images under the short keys "1" (icon) + /// InspectedAppInfo encodes its images under the short keys "1" (icon) /// and "2" (screenshot). static let appImageNames = ["1": "appIcon", "2": "screenshot"] /// `appInfo` as JSON with the machine-identifying fields masked. - static func appInfoJSON(_ appInfo: LookinAppInfo, imageSink: @escaping LookinSnapshotWireJSON.ImageSink) -> [String: Any] { + static func appInfoJSON(_ appInfo: InspectedAppInfo, imageSink: @escaping LookinSnapshotWireJSON.ImageSink) -> [String: Any] { var json = LookinSnapshotWireJSON(imageSink: imageSink).record(appInfo, keyPath: []) // "3" = deviceDescription: on a Mac that is the computer name, and // the model identifier names the hardware. Neither belongs in a @@ -242,7 +242,7 @@ /// `hierarchy` as JSON without its display items ("1") and app info /// ("2"), which are recorded separately (LookinHierarchyInfo.m). - static func hierarchyJSON(_ hierarchy: LookinHierarchyInfo) -> [String: Any] { + static func hierarchyJSON(_ hierarchy: HierarchyInfo) -> [String: Any] { LookinSnapshotWireJSON(skippedKeys: ["LookinHierarchyInfo": ["1", "2"]]) { _, _ in ["$image": ""] }.record(hierarchy, keyPath: []) diff --git a/LookInside/Export/LKExportManager.swift b/LookInside/Export/LKExportManager.swift index 00f549ee..9be476f2 100644 --- a/LookInside/Export/LKExportManager.swift +++ b/LookInside/Export/LKExportManager.swift @@ -23,18 +23,18 @@ final class LKExportManager: NSObject { /// `compression` (clamped to 0.01...1). When `fileName` is given it /// receives the suggested file name. @objc(dataFromHierarchyInfo:imageCompression:fileName:) - func data(from info: LookinHierarchyInfo, + func data(from info: HierarchyInfo, imageCompression compression: CGFloat, fileName: AutoreleasingUnsafeMutablePointer?) -> Data? { - let file = LookinHierarchyFile() + let file = HierarchyFile() file.serverVersion = info.serverVersion file.hierarchyInfo = info var soloScreenshots: [NSNumber: Data] = [:] var groupScreenshots: [NSNumber: Data] = [:] let prefersViewOID = LKHelper.appInfoLooksLikeMacTarget(info.appInfo) - let allItems = LookinDisplayItem.flatItems(fromHierarchicalItems: info.displayItems ?? []) ?? [] + let allItems = DisplayItem.flatItems(fromHierarchicalItems: info.displayItems ?? []) for displayItem in allItems { let oid = displayItem.bestObjectOidPreferView(prefersViewOID) if oid == 0 { @@ -88,7 +88,7 @@ final class LKExportManager: NSObject { /// Asks where to save `displayItem`'s group screenshot and writes it as TIFF. @MainActor @objc(exportScreenshotWithDisplayItem:) - class func exportScreenshot(with displayItem: LookinDisplayItem) { + class func exportScreenshot(with displayItem: DisplayItem) { guard let image = displayItem.groupScreenshot, let imageData = image.tiffRepresentation(using: .lzw, factor: 1) else { diff --git a/LookInside/Hierarchy/LKDanceUIAttrMaker.swift b/LookInside/Hierarchy/LKDanceUIAttrMaker.swift index 0477ff60..1aceb8f8 100644 --- a/LookInside/Hierarchy/LKDanceUIAttrMaker.swift +++ b/LookInside/Hierarchy/LKDanceUIAttrMaker.swift @@ -12,7 +12,7 @@ import Foundation enum LKDanceUIAttrMaker { /// Gives `item` a Class group naming the type in `source` (DanceUI's /// JSON), unless it already has one. - static func makeDanceUIJumpAttribute(_ item: LookinDisplayItem, danceSource source: String) { + static func makeDanceUIJumpAttribute(_ item: DisplayItem, danceSource source: String) { guard let className = className(fromSource: source) else { return } @@ -20,16 +20,16 @@ enum LKDanceUIAttrMaker { if groups.contains(where: { $0.identifier == LookinAttrGroup_Class }) { return } - let attribute = LookinAttribute() + let attribute = InspectedAttribute() attribute.identifier = LookinAttr_Class_Class_Class attribute.attrType = .customObj attribute.value = [[className]] - let section = LookinAttributesSection() + let section = AttributesSection() section.identifier = LookinAttrSec_Class_Class section.attributes = [attribute] - let group = LookinAttributesGroup() + let group = AttributesGroup() group.identifier = LookinAttrGroup_Class group.attrSections = [section] diff --git a/LookInside/Hierarchy/LKHierarchyController.swift b/LookInside/Hierarchy/LKHierarchyController.swift index 6746e508..b5787164 100644 --- a/LookInside/Hierarchy/LKHierarchyController.swift +++ b/LookInside/Hierarchy/LKHierarchyController.swift @@ -49,12 +49,12 @@ class LKHierarchyController: LKBaseViewController, LKHierarchyViewDelegate { // MARK: - LKHierarchyViewDelegate @objc(hierarchyView:didSelectItem:) - func hierarchyView(_: LKHierarchyView!, didSelect item: LookinDisplayItem!) { + func hierarchyView(_: LKHierarchyView!, didSelect item: DisplayItem!) { dataSource.selectedItem = item } @objc(hierarchyView:didDoubleClickItem:) - func hierarchyView(_: LKHierarchyView!, didDoubleClick item: LookinDisplayItem!) { + func hierarchyView(_: LKHierarchyView!, didDoubleClick item: DisplayItem!) { switch LKPreferenceManager.shared.doubleClickBehavior { case .collapse: guard item.isExpandable else { @@ -74,22 +74,22 @@ class LKHierarchyController: LKBaseViewController, LKHierarchyViewDelegate { /// `item` is nil when the mouse leaves the rows. @objc(hierarchyView:didHoverAtItem:) - func hierarchyView(_: LKHierarchyView!, didHoverAt item: LookinDisplayItem!) { + func hierarchyView(_: LKHierarchyView!, didHoverAt item: DisplayItem!) { dataSource.hoveredItem = item } @objc(hierarchyView:needToCollapseItem:) - func hierarchyView(_: LKHierarchyView!, needToCollapse item: LookinDisplayItem!) { + func hierarchyView(_: LKHierarchyView!, needToCollapse item: DisplayItem!) { dataSource.collapse(item) } @objc(hierarchyView:needToCollapseChildrenOfItem:) - func hierarchyView(_: LKHierarchyView!, needToCollapseChildrenOf item: LookinDisplayItem!) { + func hierarchyView(_: LKHierarchyView!, needToCollapseChildrenOf item: DisplayItem!) { dataSource.collapseAllChildren(of: item) } @objc(hierarchyView:needToExpandItem:recursively:) - func hierarchyView(_: LKHierarchyView!, needToExpand item: LookinDisplayItem!, recursively: Bool) { + func hierarchyView(_: LKHierarchyView!, needToExpand item: DisplayItem!, recursively: Bool) { if recursively { dataSource.expandItemsRooted(by: item) } else { diff --git a/LookInside/Hierarchy/LKHierarchyDataSource.swift b/LookInside/Hierarchy/LKHierarchyDataSource.swift index ca4d7528..bf18d39f 100644 --- a/LookInside/Hierarchy/LKHierarchyDataSource.swift +++ b/LookInside/Hierarchy/LKHierarchyDataSource.swift @@ -23,12 +23,12 @@ enum LKHierarchyDataSourceEvent { case willReloadHierarchyInfo case didReloadHierarchyInfo case didReloadFlatItemsWithSearchOrFocus - case itemDidChangeHiddenAlphaValue(LookinDisplayItem) - case itemDidChangeAttrGroup(LookinDisplayItem) + case itemDidChangeHiddenAlphaValue(DisplayItem) + case itemDidChangeAttrGroup(DisplayItem) /// Sent with no item: the preview rebuilds from the whole tree. case itemDidChangeNoPreview /// Static (live) data sources only. - case itemDidChangeFrame(LookinDisplayItem) + case itemDidChangeFrame(DisplayItem) } /// Classes collapsed by the expansion presets, together with the @@ -70,7 +70,7 @@ private func rectsAlmostEqual(_ lhs: CGRect, _ rhs: CGRect) -> Bool { && abs(lhs.height - rhs.height) <= tolerance } -private func swiftUINode(_ item: LookinDisplayItem, matchesSourceTypes sourceTypes: [String]) -> Bool { +private func swiftUINode(_ item: DisplayItem, matchesSourceTypes sourceTypes: [String]) -> Bool { guard !sourceTypes.isEmpty else { return true } @@ -78,16 +78,16 @@ private func swiftUINode(_ item: LookinDisplayItem, matchesSourceTypes sourceTyp return sourceTypes.contains { itemTypes.contains($0) } } -private func ancestors(of item: LookinDisplayItem) -> [LookinDisplayItem] { - var result: [LookinDisplayItem] = [] +private func ancestors(of item: DisplayItem) -> [DisplayItem] { + var result: [DisplayItem] = [] item.enumerateAncestors { ancestor, _ in result.append(ancestor) } return result } -private func selfAndDescendants(of item: LookinDisplayItem) -> [LookinDisplayItem] { - var result: [LookinDisplayItem] = [] +private func selfAndDescendants(of item: DisplayItem) -> [DisplayItem] { + var result: [DisplayItem] = [] item.enumerateSelfAndChildren { node in result.append(node) } @@ -108,16 +108,16 @@ class LKHierarchyDataSource: NSObject { final let willReloadHierarchyInfo = LKSyncSignal() final let didReloadHierarchyInfo = LKSyncSignal() /// An item's `isHidden` or `alpha` changed. - final let itemDidChangeHiddenAlphaValue = LKSyncSignal() + final let itemDidChangeHiddenAlphaValue = LKSyncSignal() /// An item's attribute groups changed. - final let itemDidChangeAttrGroup = LKSyncSignal() + final let itemDidChangeAttrGroup = LKSyncSignal() /// The preview rebuilds from the whole tree. final let itemDidChangeNoPreview = LKSyncSignal() /// A search or focus changed `flatItems`. final let didReloadFlatItemsWithSearchOrFocus = LKSyncSignal() /// Every display item of the tree, visible or not. - @objc var rawFlatItems: [LookinDisplayItem]! { + @objc var rawFlatItems: [DisplayItem]! { get { storedRawFlatItems } set { storedRawFlatItems = newValue @@ -127,21 +127,21 @@ class LKHierarchyDataSource: NSObject { /// All items in normal state; the shown subset while searching or /// focusing. - @objc dynamic var flatItems: [LookinDisplayItem]! + @objc dynamic var flatItems: [DisplayItem]! /// The rows: the items of `flatItems` that no collapsed ancestor hides. /// KVO-observable. - @objc dynamic var displayingFlatItems: [LookinDisplayItem]! { + @objc dynamic var displayingFlatItems: [DisplayItem]! { storedDisplayingFlatItems } - @objc dynamic weak var selectedItem: LookinDisplayItem? { + @objc dynamic weak var selectedItem: DisplayItem? { didSet { selectedItemDidChange(from: oldValue) } } - @objc dynamic weak var hoveredItem: LookinDisplayItem? { + @objc dynamic weak var hoveredItem: DisplayItem? { didSet { hoveredItemDidChange(from: oldValue) } @@ -162,7 +162,7 @@ class LKHierarchyDataSource: NSObject { } /// KVO-observable. - @objc dynamic var rawHierarchyInfo: LookinHierarchyInfo! { + @objc dynamic var rawHierarchyInfo: HierarchyInfo! { storedRawHierarchyInfo } @@ -177,12 +177,12 @@ class LKHierarchyDataSource: NSObject { // Storage of the read-only properties. Writes go // through the setters below, which post the KVO notifications. private var storedState: LKHierarchyDataSourceState = .normal - private var storedDisplayingFlatItems: [LookinDisplayItem]? - private var storedRawHierarchyInfo: LookinHierarchyInfo? + private var storedDisplayingFlatItems: [DisplayItem]? + private var storedRawHierarchyInfo: HierarchyInfo? private var storedSelectColorMenu: NSMenu? private var storedServerSideIsSwiftProject = false - private var storedRawFlatItems: [LookinDisplayItem]? - private var oidToDisplayItem: [UInt: LookinDisplayItem] = [:] + private var storedRawFlatItems: [DisplayItem]? + private var oidToDisplayItem: [UInt: DisplayItem] = [:] /// Alias names by `rgbaString`. private var colorToAliasMap: [String: [String]] = [:] private var lastRGBAFormat: Bool? @@ -222,7 +222,7 @@ class LKHierarchyDataSource: NSObject { // MARK: - Reload @objc(reloadWithHierarchyInfo:keepState:) - func reload(with info: LookinHierarchyInfo!, keepState: Bool) { + func reload(with info: HierarchyInfo!, keepState: Bool) { // Path identifiers of the old items resolve their root index against // the old root items, so take them before replacing the info. let previousRootItems = rawHierarchyInfo?.displayItems ?? [] @@ -253,7 +253,7 @@ class LKHierarchyDataSource: NSObject { setUpColors() // Flatten the tree; this also sets every item's indentLevel. - rawFlatItems = LookinDisplayItem.flatItems(fromHierarchicalItems: info.displayItems ?? []) + rawFlatItems = DisplayItem.flatItems(fromHierarchicalItems: info.displayItems ?? []) let items = rawFlatItems ?? [] let collapsedClasses = classesPreferredToCollapse.union(info.collapsedClassList ?? []) @@ -290,7 +290,7 @@ class LKHierarchyDataSource: NSObject { flatItems = items - var itemToSelect: LookinDisplayItem? + var itemToSelect: DisplayItem? if keepState { itemToSelect = displayItem(withOid: previousSelectedOid) } @@ -318,7 +318,7 @@ class LKHierarchyDataSource: NSObject { } } if itemToSelect == nil { - var presetSelection: LookinDisplayItem? + var presetSelection: DisplayItem? adjustExpansion(by: expansionIndex, referenceDict: referenceDict, selectedItem: &presetSelection) itemToSelect = presetSelection } else { @@ -342,7 +342,7 @@ class LKHierarchyDataSource: NSObject { } @objc(itemAtRow:) - func item(atRow index: Int) -> LookinDisplayItem! { + func item(atRow index: Int) -> DisplayItem! { guard let rows = displayingFlatItems, rows.indices.contains(index) else { return nil } @@ -350,12 +350,12 @@ class LKHierarchyDataSource: NSObject { } @objc(rowForItem:) - func row(for item: LookinDisplayItem!) -> Int { + func row(for item: DisplayItem!) -> Int { displayingFlatItems?.firstIndex { $0 === item } ?? NSNotFound } @objc(displayItemWithOid:) - func displayItem(withOid oid: UInt) -> LookinDisplayItem! { + func displayItem(withOid oid: UInt) -> DisplayItem! { oidToDisplayItem[oid] } @@ -388,7 +388,7 @@ class LKHierarchyDataSource: NSObject { // MARK: - Selection - private func selectedItemDidChange(from previousItem: LookinDisplayItem?) { + private func selectedItemDidChange(from previousItem: DisplayItem?) { let item = selectedItem guard item !== previousItem else { return @@ -411,7 +411,7 @@ class LKHierarchyDataSource: NSObject { } } - private func hoveredItemDidChange(from previousItem: LookinDisplayItem?) { + private func hoveredItemDidChange(from previousItem: DisplayItem?) { let item = hoveredItem guard item !== previousItem else { return @@ -421,7 +421,7 @@ class LKHierarchyDataSource: NSObject { } @objc(selectAndRevealItem:) - func selectAndRevealItem(_ item: LookinDisplayItem!) { + func selectAndRevealItem(_ item: DisplayItem!) { guard let item else { return } @@ -444,7 +444,7 @@ class LKHierarchyDataSource: NSObject { selectedItem = item } - private func containsInFlatItems(_ item: LookinDisplayItem) -> Bool { + private func containsInFlatItems(_ item: DisplayItem) -> Bool { (flatItems ?? []).contains { $0 === item } } @@ -460,7 +460,7 @@ class LKHierarchyDataSource: NSObject { func adjustExpansion( by index: Int, referenceDict: [String: NSNumber]!, - selectedItem: AutoreleasingUnsafeMutablePointer! + selectedItem: AutoreleasingUnsafeMutablePointer! ) { var index = index if index < 0 || index > 4 { @@ -498,7 +498,7 @@ class LKHierarchyDataSource: NSObject { switch index { case 0: // Collapse everything down to the top-level windows. - var preferredSelection: LookinDisplayItem? + var preferredSelection: DisplayItem? for item in items where !item.hasDeterminedExpansion { item.isExpanded = false if item.representedAsKeyWindow { @@ -514,9 +514,9 @@ class LKHierarchyDataSource: NSObject { item.isExpanded = !item.inNoPreviewHierarchy } if let selectedItem { - var preferredSelection: LookinDisplayItem? + var preferredSelection: DisplayItem? if let keyWindowRoot = rootItems.first(where: { $0.representedAsKeyWindow }) { - let windowItems = LookinDisplayItem.flatItems(fromHierarchicalItems: [keyWindowRoot]) ?? [] + let windowItems = DisplayItem.flatItems(fromHierarchicalItems: [keyWindowRoot]) preferredSelection = windowItems.last { $0.hostViewControllerObject != nil || $0.hostWindowControllerObject != nil } @@ -543,15 +543,15 @@ class LKHierarchyDataSource: NSObject { /// Presets 1 to 3, built around the key window's view controllers. private func applyViewControllerPreset( index: Int, - keyWindowItem: LookinDisplayItem, - rootItems: [LookinDisplayItem], - selectedItem: AutoreleasingUnsafeMutablePointer?, + keyWindowItem: DisplayItem, + rootItems: [DisplayItem], + selectedItem: AutoreleasingUnsafeMutablePointer?, collapseUndetermined: () -> Void ) { // A scene container (window object only, no view or layer) holds the // real key window among its children; the UITransitionView search // runs on that one. - var actualKeyWindow: LookinDisplayItem? = keyWindowItem + var actualKeyWindow: DisplayItem? = keyWindowItem let keyWindowKind = keyWindowItem.resolvedNodeKind() if keyWindowKind == .window || keyWindowKind == .windowScene { let children = keyWindowItem.subitems ?? [] @@ -561,7 +561,7 @@ class LKHierarchyDataSource: NSObject { // Collapse every other window, overriding the reference state, so a // scene that is not key never stays open. for windowItem in rootItems where windowItem !== keyWindowItem { - for item in LookinDisplayItem.flatItems(fromHierarchicalItems: [windowItem]) ?? [] { + for item in DisplayItem.flatItems(fromHierarchicalItems: [windowItem]) { item.isExpanded = false item.hasDeterminedExpansion = true } @@ -574,12 +574,12 @@ class LKHierarchyDataSource: NSObject { item.hasDeterminedExpansion = true } - var viewControllerItems: [LookinDisplayItem] = [] + var viewControllerItems: [DisplayItem] = [] // The Objective-C version tested the show-hidden-items preference // attribute object, not its value; the object is never nil, so // hidden subtrees are not folded here. let showHiddenItems = true - for item in LookinDisplayItem.flatItems(fromHierarchicalItems: [keyWindowItem]) ?? [] { + for item in DisplayItem.flatItems(fromHierarchicalItems: [keyWindowItem]) { if item.hostViewControllerObject != nil || item.hostWindowControllerObject != nil { viewControllerItems.append(item) continue @@ -663,7 +663,7 @@ class LKHierarchyDataSource: NSObject { } @objc(collapseItem:) - func collapse(_ item: LookinDisplayItem!) { + func collapse(_ item: DisplayItem!) { guard let item, item.isExpandable, item.isExpanded else { return } @@ -673,7 +673,7 @@ class LKHierarchyDataSource: NSObject { } @objc(expandItem:) - func expand(_ item: LookinDisplayItem!) { + func expand(_ item: DisplayItem!) { guard let item, item.isExpandable, !item.isExpanded else { return } @@ -683,7 +683,7 @@ class LKHierarchyDataSource: NSObject { } @objc(expandToShowItem:) - func expand(toShow item: LookinDisplayItem!) { + func expand(toShow item: DisplayItem!) { var didChange = false item?.enumerateAncestors { ancestor, _ in guard !ancestor.isExpanded else { @@ -699,7 +699,7 @@ class LKHierarchyDataSource: NSObject { } @objc(expandItemsRootedByItem:) - func expandItemsRooted(by item: LookinDisplayItem!) { + func expandItemsRooted(by item: DisplayItem!) { let includePreferredCollapsed = item?.preferToBeCollapsed ?? false item?.enumerateSelfAndChildren { node in guard node.isExpandable, !node.isExpanded else { @@ -714,7 +714,7 @@ class LKHierarchyDataSource: NSObject { } @objc(collapseAllChildrenOfItem:) - func collapseAllChildren(of item: LookinDisplayItem!) { + func collapseAllChildren(of item: DisplayItem!) { item?.enumerateSelfAndChildren { node in guard node !== item, node.isExpandable, node.isExpanded else { return @@ -731,7 +731,7 @@ class LKHierarchyDataSource: NSObject { /// when a node of the chain has no class (UserCustom-only nodes), when /// a sibling index cannot be resolved, or when `rootItems` is empty. @objc(pathIdentifierForItem:inRootItems:) - class func pathIdentifier(for item: LookinDisplayItem!, inRootItems rootItems: [LookinDisplayItem]!) -> String! { + class func pathIdentifier(for item: DisplayItem!, inRootItems rootItems: [DisplayItem]!) -> String! { guard let item else { return nil } @@ -823,7 +823,7 @@ class LKHierarchyDataSource: NSObject { for item in rawFlatItems ?? [] { item.isInSearch = false item.highlightedSearchString = nil - item.isExpanded = item.lookin_getBindBOOL(forKey: expandedBeforeSearchOrFocusKey) + item.isExpanded = item.getBindBool(forKey: expandedBeforeSearchOrFocusKey) } // The item selected while searching stays selected and visible. selectedItem?.enumerateAncestors { item, _ in @@ -838,7 +838,7 @@ class LKHierarchyDataSource: NSObject { /// Entered from the normal or the search state. @objc(focusDisplayItem:) - func focus(_ item: LookinDisplayItem!) { + func focus(_ item: DisplayItem!) { guard let item else { assertionFailure("focusing nil") return @@ -868,7 +868,7 @@ class LKHierarchyDataSource: NSObject { setState(.normal) for item in rawFlatItems ?? [] { - item.isExpanded = item.lookin_getBindBOOL(forKey: expandedBeforeSearchOrFocusKey) + item.isExpanded = item.getBindBool(forKey: expandedBeforeSearchOrFocusKey) } flatItems = rawFlatItems @@ -876,9 +876,9 @@ class LKHierarchyDataSource: NSObject { buildDisplayingFlatItems() } - private func recordExpansionBeforeSearchOrFocus(_ items: [LookinDisplayItem]) { + private func recordExpansionBeforeSearchOrFocus(_ items: [DisplayItem]) { for item in items { - item.lookin_bindBOOL(item.isExpanded, forKey: expandedBeforeSearchOrFocusKey) + item.bindBool(item.isExpanded, forKey: expandedBeforeSearchOrFocusKey) } } @@ -886,12 +886,12 @@ class LKHierarchyDataSource: NSObject { /// SwiftUI node -> its matched CALayer nodes; empty when there is none. @objc(swiftUIBackingLayerItemsForItem:) - func swiftUIBackingLayerItems(for item: LookinDisplayItem!) -> [LookinDisplayItem]! { + func swiftUIBackingLayerItems(for item: DisplayItem!) -> [DisplayItem]! { guard let item else { return [] } - var result: [LookinDisplayItem] = [] - func add(_ candidate: LookinDisplayItem?) { + var result: [DisplayItem] = [] + func add(_ candidate: DisplayItem?) { if let candidate, !result.contains(where: { $0 === candidate }) { result.append(candidate) } @@ -907,7 +907,7 @@ class LKHierarchyDataSource: NSObject { /// CALayer node -> its SwiftUI node, or nil. @objc(swiftUISourceItemForLayerItem:) - func swiftUISourceItem(forLayerItem item: LookinDisplayItem!) -> LookinDisplayItem! { + func swiftUISourceItem(forLayerItem item: DisplayItem!) -> DisplayItem! { guard let item, let displayListID = item.lk_swiftUILayerDisplayListID() else { return nil } @@ -917,7 +917,7 @@ class LKHierarchyDataSource: NSObject { /// Dashboard row -> its SwiftUI / CALayer jump target, or nil when the /// row has none. @objc(swiftUIJumpTargetForAttribute:) - func swiftUIJumpTarget(for attribute: LookinAttribute!) -> LookinDisplayItem! { + func swiftUIJumpTarget(for attribute: InspectedAttribute!) -> DisplayItem! { guard let sourceItem = attribute?.targetDisplayItem, let value = attribute.value as? String else { return nil } @@ -928,10 +928,10 @@ class LKHierarchyDataSource: NSObject { if sourceIsSwiftUI { if title.hasSuffix("Backed By") { - return layerItem(withMemoryAddress: LookinDisplayItem.lk_memoryAddress(inObjectDescription: value)) + return layerItem(withMemoryAddress: DisplayItem.lk_memoryAddress(inObjectDescription: value)) } if title.hasSuffix("Display List ID") || title == "Identity IDs" { - for displayListID in LookinDisplayItem.lk_validSwiftUIDisplayListIDs(in: value) { + for displayListID in DisplayItem.lk_validSwiftUIDisplayListIDs(in: value) { if let target = layerItem(withDisplayListID: displayListID) { return target } @@ -945,14 +945,14 @@ class LKHierarchyDataSource: NSObject { } if sourceItem.layerObject != nil, title == "Display List ID" { - let displayListID = LookinDisplayItem.lk_validSwiftUIDisplayListIDs(in: value).first + let displayListID = DisplayItem.lk_validSwiftUIDisplayListIDs(in: value).first ?? sourceItem.lk_swiftUILayerDisplayListID() return swiftUIItem(withDisplayListID: displayListID) ?? swiftUIItemForLayerItemByFrameAndSource(sourceItem) } return nil } - private func layerItem(withMemoryAddress memoryAddress: String?) -> LookinDisplayItem? { + private func layerItem(withMemoryAddress memoryAddress: String?) -> DisplayItem? { guard let memoryAddress, !memoryAddress.isEmpty else { return nil } @@ -960,7 +960,7 @@ class LKHierarchyDataSource: NSObject { return (rawFlatItems ?? []).first { $0.layerObject?.memoryAddress?.lowercased() == normalized } } - private func layerItem(withDisplayListID displayListID: NSNumber?) -> LookinDisplayItem? { + private func layerItem(withDisplayListID displayListID: NSNumber?) -> DisplayItem? { guard let displayListID else { return nil } @@ -970,11 +970,11 @@ class LKHierarchyDataSource: NSObject { } /// The deepest SwiftUI node backed by `displayListID`. - private func swiftUIItem(withDisplayListID displayListID: NSNumber?) -> LookinDisplayItem? { + private func swiftUIItem(withDisplayListID displayListID: NSNumber?) -> DisplayItem? { guard let displayListID else { return nil } - var result: LookinDisplayItem? + var result: DisplayItem? for item in rawFlatItems ?? [] where item.lk_swiftUIBackingDisplayListIDs().contains(displayListID) { if result == nil || item.indentLevel() > result!.indentLevel() { result = item @@ -984,13 +984,13 @@ class LKHierarchyDataSource: NSObject { } /// The deepest SwiftUI node with the layer's frame and source type. - private func swiftUIItemForLayerItemByFrameAndSource(_ layerItem: LookinDisplayItem) -> LookinDisplayItem? { + private func swiftUIItemForLayerItemByFrameAndSource(_ layerItem: DisplayItem) -> DisplayItem? { guard layerItem.layerObject != nil else { return nil } let layerFrame = layerItem.calculateFrameToRoot() let sourceTypes = layerItem.lk_swiftUILayerSourceTypeNames() - var result: LookinDisplayItem? + var result: DisplayItem? for item in rawFlatItems ?? [] { guard item.customInfo?.isSwiftUI == true, item.hasValidFrameToRoot() else { continue @@ -1135,7 +1135,7 @@ class LKHierarchyDataSource: NSObject { } private func rebuildOidMap() { - var map: [UInt: LookinDisplayItem] = [:] + var map: [UInt: DisplayItem] = [:] map.reserveCapacity((storedRawFlatItems?.count ?? 0) * 2) for item in storedRawFlatItems ?? [] { for object in [item.viewObject, item.layerObject, item.windowObject, item.kindObject] { diff --git a/LookInside/Hierarchy/LKHierarchyHandlersPopoverController.swift b/LookInside/Hierarchy/LKHierarchyHandlersPopoverController.swift index ce3213f4..5bdb8b95 100644 --- a/LookInside/Hierarchy/LKHierarchyHandlersPopoverController.swift +++ b/LookInside/Hierarchy/LKHierarchyHandlersPopoverController.swift @@ -22,7 +22,7 @@ final class LKHierarchyHandlersPopoverController: LKBaseViewController { /// - Parameter editable: false in read mode, where a gesture recognizer /// cannot be switched on or off. - init(displayItem: LookinDisplayItem, editable: Bool) { + init(displayItem: DisplayItem, editable: Bool) { super.init(containerView: nil) let documentView = LKBaseView() scrollView.documentView = documentView @@ -85,7 +85,7 @@ final class LKHierarchyHandlersPopoverItemView: LKBaseView { } } - private let eventHandler: LookinEventHandler + private let eventHandler: EventHandlerDescription private let iconImageView = NSImageView() private let titleLabel = LKLabel() private var subtitleLabel: LKLabel? @@ -100,7 +100,7 @@ final class LKHierarchyHandlersPopoverItemView: LKBaseView { private let subtitleMarginTop: CGFloat = 3 /// - Parameter editable: false in read mode. - init(eventHandler: LookinEventHandler, editable: Bool) { + init(eventHandler: EventHandlerDescription, editable: Bool) { self.eventHandler = eventHandler super.init(frame: .zero) @@ -120,9 +120,9 @@ final class LKHierarchyHandlersPopoverItemView: LKBaseView { : NSColor(red: 0, green: 0, blue: 0, alpha: 0.12).cgColor let isGesture = eventHandler.handlerType == .gesture - var texts: [LookinStringTwoTuple] = [] + var texts: [StringTwoTuple] = [] if isGesture { - texts.append(LookinStringTwoTuple(first: NSLocalizedString("Enabled", comment: ""), second: "")) + texts.append(StringTwoTuple(first: NSLocalizedString("Enabled", comment: ""), second: "")) if editable { let button = NSButton() button.setButtonType(.switch) @@ -133,9 +133,9 @@ final class LKHierarchyHandlersPopoverItemView: LKBaseView { renderRecognizerEnabledButton() contentView.add(button, at: 0) } else { - texts.append(LookinStringTwoTuple(first: NSLocalizedString("Enabled", comment: ""), second: eventHandler.gestureRecognizerIsEnabled ? "YES" : "NO")) + texts.append(StringTwoTuple(first: NSLocalizedString("Enabled", comment: ""), second: eventHandler.gestureRecognizerIsEnabled ? "YES" : "NO")) } - texts.append(LookinStringTwoTuple(first: NSLocalizedString("Delegate", comment: ""), second: eventHandler.gestureRecognizerDelegator ?? "nil")) + texts.append(StringTwoTuple(first: NSLocalizedString("Delegate", comment: ""), second: eventHandler.gestureRecognizerDelegator ?? "nil")) // Gesture recognizer names are long; use a smaller title. titleLabel.font = .boldSystemFont(ofSize: 12) } else { @@ -145,15 +145,15 @@ final class LKHierarchyHandlersPopoverItemView: LKBaseView { let targetActions = eventHandler.targetActions ?? [] switch targetActions.count { case 0: - texts.append(LookinStringTwoTuple(first: NSLocalizedString("Target", comment: ""), second: "nil")) - texts.append(LookinStringTwoTuple(first: NSLocalizedString("Action", comment: ""), second: "NULL")) + texts.append(StringTwoTuple(first: NSLocalizedString("Target", comment: ""), second: "nil")) + texts.append(StringTwoTuple(first: NSLocalizedString("Action", comment: ""), second: "NULL")) case 1: - texts.append(LookinStringTwoTuple(first: NSLocalizedString("Target", comment: ""), second: targetActions[0].first)) - texts.append(LookinStringTwoTuple(first: NSLocalizedString("Action", comment: ""), second: targetActions[0].second)) + texts.append(StringTwoTuple(first: NSLocalizedString("Target", comment: ""), second: targetActions[0].first)) + texts.append(StringTwoTuple(first: NSLocalizedString("Action", comment: ""), second: targetActions[0].second)) default: for (index, tuple) in targetActions.enumerated() { - texts.append(LookinStringTwoTuple(first: String(format: NSLocalizedString("Target %lld", comment: ""), index + 1), second: tuple.first)) - texts.append(LookinStringTwoTuple(first: String(format: NSLocalizedString("Action %lld", comment: ""), index + 1), second: tuple.second)) + texts.append(StringTwoTuple(first: String(format: NSLocalizedString("Target %lld", comment: ""), index + 1), second: tuple.first)) + texts.append(StringTwoTuple(first: String(format: NSLocalizedString("Action %lld", comment: ""), index + 1), second: tuple.second)) } } contentView.texts = texts diff --git a/LookInside/Hierarchy/LKHierarchyRowView.swift b/LookInside/Hierarchy/LKHierarchyRowView.swift index d0b736b9..94051bba 100644 --- a/LookInside/Hierarchy/LKHierarchyRowView.swift +++ b/LookInside/Hierarchy/LKHierarchyRowView.swift @@ -59,7 +59,7 @@ private let classIconNames: [(className: String, imageName: String)] = [ /// Type"). LKS_CustomDisplayItemsMaker (lookin_customDebugInfos path) sets /// customInfo but never produces SwiftUI-prefixed groups, so this /// distinguishes correctly. Remove once v8 support is dropped. -private func displayItemLooksLikeSwiftUI(_ item: LookinDisplayItem) -> Bool { +private func displayItemLooksLikeSwiftUI(_ item: DisplayItem) -> Bool { if item.customInfo?.isSwiftUI == true { return true } @@ -76,7 +76,7 @@ class LKHierarchyRowView: LKOutlineRowView { /// Weak: the table keeps many row views around, and a strong reference /// would keep display items (and their screenshots) alive across /// hierarchy reloads. - weak var displayItem: LookinDisplayItem? { + weak var displayItem: DisplayItem? { didSet { displayItemDidChange(from: oldValue) } @@ -188,7 +188,7 @@ class LKHierarchyRowView: LKOutlineRowView { // MARK: - Rendering - private func displayItemDidChange(from previousItem: LookinDisplayItem?) { + private func displayItemDidChange(from previousItem: DisplayItem?) { // Even when the item is unchanged its rowViewDelegate may point at // another row: select a view, focus it, leave focus, and without this // the row could no longer be deselected. @@ -222,7 +222,7 @@ class LKHierarchyRowView: LKOutlineRowView { isHovered = (dataSource?.hoveredItem === displayItem) } - private func updateSwiftUIBadge(for item: LookinDisplayItem) { + private func updateSwiftUIBadge(for item: DisplayItem) { let isSwiftUINode = displayItemLooksLikeSwiftUI(item) if isSwiftUINode, swiftUIBadge == nil { let image = NSImage(systemSymbolName: "sparkles", accessibilityDescription: nil) @@ -237,7 +237,7 @@ class LKHierarchyRowView: LKOutlineRowView { toolTip = isSwiftUINode ? NSLocalizedString("LookInside Pro · Activated", comment: "") : nil } - private func updateLabelStringsAndImageViewAlpha(for item: LookinDisplayItem) { + private func updateLabelStringsAndImageViewAlpha(for item: DisplayItem) { let titleColor: NSColor let subtitleColor: NSColor if isSelected { @@ -312,7 +312,7 @@ class LKHierarchyRowView: LKOutlineRowView { layer = strikethroughLayer } else { layer = CALayer() - layer.lookin_removeImplicitAnimations() + layer.removeImplicitAnimations() self.layer?.addSublayer(layer) strikethroughLayer = layer } @@ -342,7 +342,7 @@ class LKHierarchyRowView: LKOutlineRowView { eventHandlerButtonColorLayer.cornerRadius = width / 2 } - private func updateLabelsFonts(for item: LookinDisplayItem) { + private func updateLabelsFonts(for item: DisplayItem) { let noImage = item.inNoPreviewHierarchy || item.inHiddenHierarchy let isPrivate = LKPrivateDiscriminatorStore.shared.isPrivateDisplayItem(item) if !item.isUserCustom(), noImage || isPrivate { @@ -363,7 +363,7 @@ class LKHierarchyRowView: LKOutlineRowView { status = item.isExpanded ? .expanded : .collapsed } - private func shouldFadeContent(of item: LookinDisplayItem) -> Bool { + private func shouldFadeContent(of item: DisplayItem) -> Bool { if item.isInSearch, (item.highlightedSearchString ?? "").isEmpty { return true } @@ -373,7 +373,7 @@ class LKHierarchyRowView: LKOutlineRowView { return item.inHiddenHierarchy || item.inNoPreviewHierarchy } - private func resolveIconImage(for item: LookinDisplayItem) -> NSImage? { + private func resolveIconImage(for item: DisplayItem) -> NSImage? { var imageName: String? if item.isUserCustom() { imageName = "hierarchy_custom" @@ -440,8 +440,8 @@ class LKHierarchyRowView: LKOutlineRowView { } } -extension LKHierarchyRowView: LookinDisplayItemDelegate { - func displayItem(_: LookinDisplayItem!, propertyDidChange property: LookinDisplayItemProperty) { +extension LKHierarchyRowView: DisplayItemDelegate { + func displayItem(_: DisplayItem, propertyDidChange property: LookinDisplayItemProperty) { if property == .isHovered { updateHoverState() } else { diff --git a/LookInside/Hierarchy/LKHierarchyView.swift b/LookInside/Hierarchy/LKHierarchyView.swift index 54eebce4..15dd72fc 100644 --- a/LookInside/Hierarchy/LKHierarchyView.swift +++ b/LookInside/Hierarchy/LKHierarchyView.swift @@ -42,22 +42,22 @@ private final class LKHierarchyDebouncer { @objc protocol LKHierarchyViewDelegate: NSObjectProtocol { @objc(hierarchyView:didSelectItem:) - func hierarchyView(_ view: LKHierarchyView!, didSelect item: LookinDisplayItem!) + func hierarchyView(_ view: LKHierarchyView!, didSelect item: DisplayItem!) @objc(hierarchyView:didDoubleClickItem:) - func hierarchyView(_ view: LKHierarchyView!, didDoubleClick item: LookinDisplayItem!) + func hierarchyView(_ view: LKHierarchyView!, didDoubleClick item: DisplayItem!) @objc(hierarchyView:didHoverAtItem:) - func hierarchyView(_ view: LKHierarchyView!, didHoverAt item: LookinDisplayItem!) + func hierarchyView(_ view: LKHierarchyView!, didHoverAt item: DisplayItem!) @objc(hierarchyView:needToExpandItem:recursively:) - func hierarchyView(_ view: LKHierarchyView!, needToExpand item: LookinDisplayItem!, recursively: Bool) + func hierarchyView(_ view: LKHierarchyView!, needToExpand item: DisplayItem!, recursively: Bool) @objc(hierarchyView:needToCollapseItem:) - func hierarchyView(_ view: LKHierarchyView!, needToCollapse item: LookinDisplayItem!) + func hierarchyView(_ view: LKHierarchyView!, needToCollapse item: DisplayItem!) @objc(hierarchyView:needToCollapseChildrenOfItem:) - func hierarchyView(_ view: LKHierarchyView!, needToCollapseChildrenOf item: LookinDisplayItem!) + func hierarchyView(_ view: LKHierarchyView!, needToCollapseChildrenOf item: DisplayItem!) /// 在底部的搜索框里输入了文字,string 可能为空字符串或 nil /// 当用户通过搜索框的关闭按钮、ESC 等方式手动结束搜索时,该方法同样会被调用,参数是 nil @@ -65,10 +65,10 @@ private final class LKHierarchyDebouncer { func hierarchyView(_ view: LKHierarchyView!, didInputSearch string: String!) @objc(hierarchyView:needToCancelPreviewOfItem:) - optional func hierarchyView(_ view: LKHierarchyView!, needToCancelPreviewOf item: LookinDisplayItem!) + optional func hierarchyView(_ view: LKHierarchyView!, needToCancelPreviewOf item: DisplayItem!) @objc(hierarchyView:needToShowPreviewOfItem:) - optional func hierarchyView(_ view: LKHierarchyView!, needToShowPreviewOf item: LookinDisplayItem!) + optional func hierarchyView(_ view: LKHierarchyView!, needToShowPreviewOf item: DisplayItem!) } @objc(LKHierarchyView) @@ -86,7 +86,7 @@ class LKHierarchyView: LKBaseView { private let backgroundEffectView = LKVisualEffectView() private let guidesShapeLayer = CAShapeLayer() private var emptyDataLabel: LKLabel? - private var displayItems: [LookinDisplayItem] = [] + private var displayItems: [DisplayItem] = [] private var minIndentLevel = 0 private var observations: [NSKeyValueObservation] = [] private var textChangeObserver: NSObjectProtocol? @@ -112,7 +112,7 @@ class LKHierarchyView: LKBaseView { guidesShapeLayer.lineWidth = 1 guidesShapeLayer.isHidden = true - guidesShapeLayer.lookin_removeImplicitAnimations() + guidesShapeLayer.removeImplicitAnimations() guidesShapeLayer.lineDashPattern = [2, 2] tableView.contentView.documentView?.layer?.addSublayer(guidesShapeLayer) @@ -154,7 +154,7 @@ class LKHierarchyView: LKBaseView { } @objc(scrollToMakeItemVisible:) - func scroll(toMakeItemVisible item: LookinDisplayItem!) { + func scroll(toMakeItemVisible item: DisplayItem!) { guard let item, let row = displayItems.firstIndex(where: { $0 === item }) else { return } @@ -230,7 +230,7 @@ class LKHierarchyView: LKBaseView { scroll(toMakeItemVisible: dataSource.selectedItem) }) - var lastHoveredItem: LookinDisplayItem? + var lastHoveredItem: DisplayItem? var hasHoveredItem = false observations.append(dataSource.observe(\.hoveredItem, options: [.initial]) { [weak self] dataSource, _ in let item = dataSource.hoveredItem @@ -270,7 +270,7 @@ class LKHierarchyView: LKBaseView { // MARK: - Rendering - private func render(_ items: [LookinDisplayItem]) { + private func render(_ items: [DisplayItem]) { displayItems = items minIndentLevel = items.map { $0.indentLevel() }.min() ?? 0 @@ -308,7 +308,7 @@ class LKHierarchyView: LKBaseView { // MARK: - Guides - func updateGuides(withHoveredItem item: LookinDisplayItem!) { + func updateGuides(withHoveredItem item: DisplayItem!) { guard let item, let rootItem = item.super, let rootRow = displayItems.firstIndex(where: { $0 === rootItem }) else { @@ -349,11 +349,11 @@ class LKHierarchyView: LKBaseView { tableView.contentView.documentView?.layer?.addSublayer(guidesShapeLayer) } - fileprivate func item(atRow row: Int) -> LookinDisplayItem? { + fileprivate func item(atRow row: Int) -> DisplayItem? { displayItems.indices.contains(row) ? displayItems[row] : nil } - fileprivate func displayItem(of menuItem: NSMenuItem) -> LookinDisplayItem? { + fileprivate func displayItem(of menuItem: NSMenuItem) -> DisplayItem? { (menuItem.menu as? LKHierarchyRowMenu)?.rowView?.displayItem } @@ -398,7 +398,7 @@ class LKHierarchyView: LKBaseView { } @objc fileprivate func handleJumpToDisplayItem(_ menuItem: NSMenuItem) { - dataSource.selectAndRevealItem(menuItem.representedObject as? LookinDisplayItem) + dataSource.selectAndRevealItem(menuItem.representedObject as? DisplayItem) } @objc fileprivate func handleShowPreview(_ menuItem: NSMenuItem) { @@ -448,7 +448,7 @@ class LKHierarchyView: LKBaseView { return item } - fileprivate func jumpMenuItem(_ title: String, target: LookinDisplayItem) -> NSMenuItem { + fileprivate func jumpMenuItem(_ title: String, target: DisplayItem) -> NSMenuItem { menuItem(title, action: #selector(handleJumpToDisplayItem(_:)), representedObject: target) } } diff --git a/LookInside/Injection/Device/LKAttachedDeviceMonitor.swift b/LookInside/Injection/Device/LKAttachedDeviceMonitor.swift index f9581b13..b1a1d592 100644 --- a/LookInside/Injection/Device/LKAttachedDeviceMonitor.swift +++ b/LookInside/Injection/Device/LKAttachedDeviceMonitor.swift @@ -6,7 +6,7 @@ import AppKit /// tracks the same attaches for a different purpose (it turns each one into /// five server ports to probe) and keeps the result private. /// -/// It runs its **own** `LookinUSBMuxClient`. usbmuxd answers a Listen request +/// It runs its **own** `USBMuxClient`. usbmuxd answers a Listen request /// with one Attached broadcast per device already connected, and only on the /// socket that sent it — so the connection manager's subscription, opened at /// launch, says nothing to an observer that arrives later. A private client @@ -26,12 +26,12 @@ final class LKAttachedDeviceMonitor { /// Attached devices, in the order they were reported. private(set) var devices: [Device] = [] - private let usbMuxClient = LookinUSBMuxClient(queue: .main) + private let usbMuxClient = USBMuxClient(queue: .main) private var hasStartedListening = false /// The usbmuxd client a control client should reach these devices /// through — the one that enumerated them. - var connectionClient: LookinUSBMuxClient { + var connectionClient: USBMuxClient { usbMuxClient } @@ -57,7 +57,7 @@ final class LKAttachedDeviceMonitor { try? await Task.sleep(nanoseconds: 300_000_000) } - private func handle(_ event: LookinUSBMuxClient.Event) { + private func handle(_ event: USBMuxClient.Event) { switch event { case let .attached(identifier, properties): // Deliberately **not** filtered by `ConnectionType`. A `Network` diff --git a/LookInside/Injection/Device/LKDeviceControlClient.swift b/LookInside/Injection/Device/LKDeviceControlClient.swift index 8ffed13b..39f08346 100644 --- a/LookInside/Injection/Device/LKDeviceControlClient.swift +++ b/LookInside/Injection/Device/LKDeviceControlClient.swift @@ -3,7 +3,7 @@ import Foundation /// Talks to the LookInside injector running on one attached iOS device. /// /// The transport is the one the host already uses to reach a LookInside server -/// on a device — a `LookinFrameChannel` over a usbmuxd tunnel — pointed at the +/// on a device — a `FrameChannel` over a usbmuxd tunnel — pointed at the /// injector's own port instead of the server's range. Nothing here touches a network /// interface: usbmuxd carries the bytes over the cable and dials 127.0.0.1 /// inside the device, so the feature needs no Wi-Fi, no pairing beyond what @@ -80,9 +80,9 @@ final class LKDeviceControlClient { /// The usbmuxd client the tunnel is opened through: the monitor's own, /// the one that enumerated the device (see `LKAttachedDeviceMonitor` for /// why it does not share the connection manager's). - private let usbMuxClient: LookinUSBMuxClient + private let usbMuxClient: USBMuxClient - private var channel: LookinFrameChannel? + private var channel: FrameChannel? /// Requests sent and not yet answered, by frame tag. private var pendingByFrameTag: [UInt32: (Result) -> Void] = [:] @@ -90,7 +90,7 @@ final class LKDeviceControlClient { /// Tags start at 1 because the frame format reserves 0 for "no tag". private var nextFrameTag: UInt32 = 1 - init(deviceIdentifier: Int, serialNumber: String, usbMuxClient: LookinUSBMuxClient) { + init(deviceIdentifier: Int, serialNumber: String, usbMuxClient: USBMuxClient) { self.deviceIdentifier = deviceIdentifier self.serialNumber = serialNumber self.usbMuxClient = usbMuxClient @@ -111,7 +111,7 @@ final class LKDeviceControlClient { } // Any payload size, as the server channel takes: a process list can // run long, and the device is the injector this build was paired with. - let newChannel = LookinFrameChannel( + let newChannel = FrameChannel( fileDescriptor: tunnel.fileDescriptor, queue: .main, maxPayloadSize: .max, diff --git a/LookInside/Launch/LKLaunchAppView.swift b/LookInside/Launch/LKLaunchAppView.swift index 11660f33..6ee1e52a 100644 --- a/LookInside/Launch/LKLaunchAppView.swift +++ b/LookInside/Launch/LKLaunchAppView.swift @@ -162,7 +162,7 @@ final class LKLaunchAppView: LKBaseControl { /// Prefer the icon of the actual hardware model the app runs on. Falls back to the /// per-family asset when the peer's LookinServer does not report a model identifier. - private static func deviceIcon(for appInfo: LookinAppInfo?) -> NSImage? { + private static func deviceIcon(for appInfo: InspectedAppInfo?) -> NSImage? { if let icon = LKDeviceIconProvider.deviceIcon(forAppInfo: appInfo, pointSize: LKDeviceIconProvider.launchPointSize) { return icon } diff --git a/LookInside/Launch/LKLaunchViewController.swift b/LookInside/Launch/LKLaunchViewController.swift index b25cfba5..ad00d5f9 100644 --- a/LookInside/Launch/LKLaunchViewController.swift +++ b/LookInside/Launch/LKLaunchViewController.swift @@ -37,7 +37,7 @@ final class LKLaunchViewController: LKBaseViewController { private var isEnteringApp = false /// The infos of the last scan, so an unchanged app does not send its /// images again. - private var appInfos: [LookinAppInfo]? + private var appInfos: [InspectedAppInfo]? @objc(initWithWindow:) convenience init(window: NSWindow?) { @@ -203,7 +203,7 @@ final class LKLaunchViewController: LKBaseViewController { LKPerformanceReporter.sharedInstance().willStartReload() Task { [weak self] in - let info: LookinHierarchyInfo + let info: HierarchyInfo do { info = try await app.hierarchy() } catch { @@ -218,13 +218,13 @@ final class LKLaunchViewController: LKBaseViewController { /// A successful pick opens a live document, which owns its own data /// source and update manager. The hierarchy just fetched primes the new /// document so its window opens populated. - private func didFetchHierarchy(_ info: LookinHierarchyInfo, of app: LKInspectableApp) { + private func didFetchHierarchy(_ info: HierarchyInfo, of app: LKInspectableApp) { bottomIndicatorView.finish { [weak self] in self?.openLiveDocument(for: app, priming: info) } } - private func openLiveDocument(for app: LKInspectableApp, priming info: LookinHierarchyInfo) { + private func openLiveDocument(for app: LKInspectableApp, priming info: HierarchyInfo) { let (document, alreadyOpen) = LookinLiveDocumentController.shared.openLiveDocument(for: app) if !alreadyOpen { document.hierarchyDataSource?.reload(with: info, keepState: false) diff --git a/LookInside/MCPBridge/LKMCPBridgeAttributeEncoder.swift b/LookInside/MCPBridge/LKMCPBridgeAttributeEncoder.swift index 34ac5016..17518192 100644 --- a/LookInside/MCPBridge/LKMCPBridgeAttributeEncoder.swift +++ b/LookInside/MCPBridge/LKMCPBridgeAttributeEncoder.swift @@ -1,6 +1,6 @@ // LKMCPBridgeAttributeEncoder.swift // -// Encodes a host-side `LookinAttribute` into the wire DTO +// Encodes a host-side `InspectedAttribute` into the wire DTO // `LKMCPBridgeAttribute` for the `attributes.read` MCPBridge method. // // The host represents an attribute's payload as a polymorphic `id value` @@ -22,7 +22,7 @@ import Foundation #endif enum LKMCPBridgeAttributeEncoder { - /// Encodes one host-side `LookinAttribute` into the wire DTO. + /// Encodes one host-side `InspectedAttribute` into the wire DTO. /// /// - Parameter redactingSecureContent: when `true`, string-valued kinds /// (`string`, `selector`, `class`, `enum` string variant) are replaced @@ -35,7 +35,7 @@ enum LKMCPBridgeAttributeEncoder { /// either its `text`, its `placeholder`, or any custom-attribute /// string the host might collect via `lookin_customDebugInfos`. static func encode( - _ attribute: LookinAttribute, + _ attribute: InspectedAttribute, redactingSecureContent: Bool ) -> LKMCPBridgeAttribute { let projection = projectValue(of: attribute) @@ -43,7 +43,7 @@ enum LKMCPBridgeAttributeEncoder { ? redactedIfString(projection) : projection return LKMCPBridgeAttribute( - identifier: attribute.identifier, + identifier: attribute.identifier ?? "", displayTitle: attribute.displayTitle, isUserCustom: attribute.isUserCustom(), kind: finalProjection.kind, @@ -81,7 +81,7 @@ enum LKMCPBridgeAttributeEncoder { let value: LKMCPBridgeJSONValue? } - private static func projectValue(of attribute: LookinAttribute) -> Projection { + private static func projectValue(of attribute: InspectedAttribute) -> Projection { let rawValue: Any? = attribute.value switch attribute.attrType { case .none, .void: @@ -153,7 +153,7 @@ enum LKMCPBridgeAttributeEncoder { return Projection(kind: "json", value: encodeArbitraryJSON(rawValue)) case .customObj: - if let constraints = rawValue as? [LookinAutoLayoutConstraint], constraints.isEmpty == false { + if let constraints = rawValue as? [AutoLayoutConstraint], constraints.isEmpty == false { return Projection(kind: "constraints", value: encodeConstraints(constraints)) } return Projection(kind: "custom", value: encodeCustomObject(rawValue)) @@ -165,7 +165,7 @@ enum LKMCPBridgeAttributeEncoder { // MARK: - extraValue - private static func encodeExtraValue(_ attribute: LookinAttribute) -> LKMCPBridgeJSONValue? { + private static func encodeExtraValue(_ attribute: InspectedAttribute) -> LKMCPBridgeJSONValue? { guard let extra = attribute.extraValue else { return nil } // For LookinAttrTypeEnumString, `extraValue` is the array of all // possible enum case names — surface it directly. Other attribute @@ -361,7 +361,7 @@ enum LKMCPBridgeAttributeEncoder { } } - private static func encodeConstraintEndpoint(_ endpointObject: LookinObject?, itemType: LookinConstraintItemType) -> LKMCPBridgeJSONValue { + private static func encodeConstraintEndpoint(_ endpointObject: InspectedObject?, itemType: LookinConstraintItemType) -> LKMCPBridgeJSONValue { var fields: [String: LKMCPBridgeJSONValue] = [ "itemType": .string(constraintItemTypeString(itemType)), ] @@ -379,7 +379,7 @@ enum LKMCPBridgeAttributeEncoder { /// The attribute numbers stay raw NSInteger values: UIKit and AppKit /// assign different numbers to NSLayoutAttribute cases, and the bridge /// does not know which platform produced the data. - private static func encodeConstraints(_ constraints: [LookinAutoLayoutConstraint]) -> LKMCPBridgeJSONValue { + private static func encodeConstraints(_ constraints: [AutoLayoutConstraint]) -> LKMCPBridgeJSONValue { let encodedConstraints: [LKMCPBridgeJSONValue] = constraints.map { constraint in var fields: [String: LKMCPBridgeJSONValue] = [ "firstItem": encodeConstraintEndpoint(constraint.firstItem, itemType: constraint.firstItemType), diff --git a/LookInside/MCPBridge/LKMCPBridgeAttributeValueDecoder.swift b/LookInside/MCPBridge/LKMCPBridgeAttributeValueDecoder.swift index 8babcae1..147b9318 100644 --- a/LookInside/MCPBridge/LKMCPBridgeAttributeValueDecoder.swift +++ b/LookInside/MCPBridge/LKMCPBridgeAttributeValueDecoder.swift @@ -3,7 +3,7 @@ // Symmetric inverse of LKMCPBridgeAttributeEncoder: turns the wire // `{ kind, data }` shape that a bridge client uses to express an // attribute write back into the polymorphic Objective-C value that -// LookinAttributeModification carries to the inspected server +// AttributeModification carries to the inspected server // (RPC 204). // // Layout: one entry point (`decode(wireKind:wireData:expectedAttrType:)`) @@ -46,7 +46,7 @@ enum LKMCPBridgeAttributeValueDecoder { // MARK: - Entry point /// Decodes a `(wireKind, wireData)` pair into the polymorphic id - /// value that `LookinAttributeModification.value` requires, + /// value that `AttributeModification.value` requires, /// validated against `expectedAttrType`. Throws on any /// inconsistency; the caller turns the throw into a structured /// bridge error. diff --git a/LookInside/MCPBridge/LKMCPBridgeDetailsService.swift b/LookInside/MCPBridge/LKMCPBridgeDetailsService.swift index d8b75bb6..1dc07e53 100644 --- a/LookInside/MCPBridge/LKMCPBridgeDetailsService.swift +++ b/LookInside/MCPBridge/LKMCPBridgeDetailsService.swift @@ -129,7 +129,7 @@ final class LKMCPBridgeDetailsService { // round-trip; the agent learns which oids vanished without the // request blowing up entirely. let roots = LKMCPBridgeLiveDocumentLookup.topLevelDisplayItems(in: document) - var resolvedItems: [(identifier: String, displayItem: LookinDisplayItem, nativeOid: UInt)] = [] + var resolvedItems: [(identifier: String, displayItem: DisplayItem, nativeOid: UInt)] = [] resolvedItems.reserveCapacity(requestedIdentifiers.count) var failedIdentifiers: [String] = [] @@ -163,8 +163,8 @@ final class LKMCPBridgeDetailsService { // cap the batch at 100 entries, so the host inspector's own // pixel/count packing thresholds never need to come into play. let clientReadableVersion = LKHelper.lookinReadableVersion() - let tasks = resolvedItems.map { resolved -> LookinStaticAsyncUpdateTask in - let task = LookinStaticAsyncUpdateTask() + let tasks = resolvedItems.map { resolved -> StaticAsyncUpdateTask in + let task = StaticAsyncUpdateTask() task.oid = resolved.nativeOid task.taskType = .noScreenshot task.attrRequest = .need @@ -173,7 +173,7 @@ final class LKMCPBridgeDetailsService { task.clientReadableVersion = clientReadableVersion return task } - let package = LookinStaticAsyncUpdateTasksPackage() + let package = StaticAsyncUpdateTasksPackage() package.tasks = tasks // RPC 203 streams one frame per package; with a single package we @@ -181,7 +181,7 @@ final class LKMCPBridgeDetailsService { // stays correct if batching here ever splits into packages. A // stream that ends without a frame leaves every requested // identifier in `failedIdentifiers` below. - var allDetails: [LookinDisplayItemDetail] = [] + var allDetails: [DisplayItemDetail] = [] allDetails.reserveCapacity(resolvedItems.count) do { for try await frame in document.inspectableApp.hierarchyDetails(packages: [package]) { @@ -202,14 +202,14 @@ final class LKMCPBridgeDetailsService { // matched by exact equality. Trapping on it anyway would turn a future // change in identifier syntax into a host crash, which is far worse // than serving the first of two equivalent entries. - let itemsByOid: [UInt: (identifier: String, displayItem: LookinDisplayItem, nativeOid: UInt)] = Dictionary( + let itemsByOid: [UInt: (identifier: String, displayItem: DisplayItem, nativeOid: UInt)] = Dictionary( resolvedItems.map { ($0.nativeOid, $0) }, uniquingKeysWith: { first, _ in first } ) // Resolve the concrete data source once. We thread it through // the per-detail loop rather than walking back from each - // display item, because LookinDisplayItem has no back-reference + // display item, because DisplayItem has no back-reference // to its owning document. let staticDataSource = document.hierarchyDataSource @@ -245,7 +245,7 @@ final class LKMCPBridgeDetailsService { // through the read-side encoder so the wire shape matches // attributes.read. let redactSecureContent = LKMCPBridgeSecureContentDetector.isSecure(displayItem: resolved.displayItem) - var rawGroups: [LookinAttributesGroup] = [] + var rawGroups: [AttributesGroup] = [] if let inbuiltGroups = detail.attributesGroupList { rawGroups.append(contentsOf: inbuiltGroups) } diff --git a/LookInside/MCPBridge/LKMCPBridgeInspectionModels.swift b/LookInside/MCPBridge/LKMCPBridgeInspectionModels.swift index bcced23c..d6351eac 100644 --- a/LookInside/MCPBridge/LKMCPBridgeInspectionModels.swift +++ b/LookInside/MCPBridge/LKMCPBridgeInspectionModels.swift @@ -7,7 +7,7 @@ // // The naming follows the wire vocabulary: a "target" is one inspection // session bound to a running app (one `LookinLiveDocument`); a "view node" -// is one row in a target's UI hierarchy (one `LookinDisplayItem`). +// is one row in a target's UI hierarchy (one `DisplayItem`). import CoreGraphics import Foundation @@ -45,7 +45,7 @@ struct LKMCPBridgeRect: Sendable, Codable, Equatable { /// (typically corresponding to one inspector window in the host UI). struct LKMCPBridgeTargetInfo: Sendable, Codable { /// Stable identifier for the duration of the inspection session. - /// Derived from `LookinAppInfo.appInfoIdentifier` (randomly generated per + /// Derived from `InspectedAppInfo.appInfoIdentifier` (randomly generated per /// app launch and reused across reconnects to the same app instance). let targetIdentifier: String @@ -82,11 +82,11 @@ struct LKMCPBridgeTargetInfo: Sendable, Codable { /// screenshot URIs live in separate methods to be added in subsequent /// commits. struct LKMCPBridgeViewNode: Sendable, Codable { - /// Hex-encoded `LookinObject.oid`, prefixed with `0x` (for example, + /// Hex-encoded `InspectedObject.oid`, prefixed with `0x` (for example, /// `0x600000abc123`). Stable within a single connected app instance. let objectIdentifier: String - /// Leaf Objective-C class name (head of `LookinObject.classChainList`), + /// Leaf Objective-C class name (head of `InspectedObject.classChainList`), /// e.g. "UIButton". May be empty if the underlying display item is /// configured by the in-app `lookin_customDebugInfos` hook without /// touching a real view / layer. @@ -174,7 +174,7 @@ struct LKMCPBridgeAttribute: Sendable, Codable { /// Auxiliary payload for select kinds. For `enum` types, this is the /// list of all enum case names the inspected object can hold (the - /// host calls these `extraValue` on `LookinAttribute`). + /// host calls these `extraValue` on `InspectedAttribute`). let extraValue: LKMCPBridgeJSONValue? /// Server-side identifier of a custom-attribute setter, present only @@ -189,11 +189,11 @@ struct LKMCPBridgeAttribute: Sendable, Codable { /// (RPC 206). The receiver of an `invoke.method` response may use /// `objectIdentifier` as a handle for a follow-up `invoke.method` call on /// the same object — but the identifier is a fresh server-registered -/// `LookinObject.oid` and is NOT guaranteed to appear in a subsequent +/// `InspectedObject.oid` and is NOT guaranteed to appear in a subsequent /// `hierarchy.read` (the hierarchy walks the view tree, not the server's /// general object registry). struct LKMCPBridgeReturnedObject: Sendable, Codable { - /// Hex-encoded `LookinObject.oid` for the returned object, prefixed + /// Hex-encoded `InspectedObject.oid` for the returned object, prefixed /// with `0x` (matches the form used everywhere else on the bridge). let objectIdentifier: String @@ -203,7 +203,7 @@ struct LKMCPBridgeReturnedObject: Sendable, Codable { /// Full class chain of the returned object (head is the leaf class, /// tail is `NSObject`). Identical shape to the - /// `LookinObject.classChainList` produced by the inspection routes. + /// `InspectedObject.classChainList` produced by the inspection routes. let classChainList: [String] /// Optional debug annotation that the in-app `lookin_specialTrace` @@ -259,7 +259,7 @@ struct LKMCPBridgeAttributeValueWire: Sendable, Codable { /// Result envelope for `attribute.modify`. Echoes the requested value, /// surfaces the post-layout effective attribute, and includes the /// host-visible side-effect snapshot (frame / bounds / hidden / alpha) -/// that the server captures in `LookinDisplayItemDetail` after the +/// that the server captures in `DisplayItemDetail` after the /// setter has run and a layout pass has completed. struct LKMCPBridgeModificationResult: Sendable, Codable { /// Echo of the attribute identifier the agent asked to modify. diff --git a/LookInside/MCPBridge/LKMCPBridgeInspectionService.swift b/LookInside/MCPBridge/LKMCPBridgeInspectionService.swift index 7fb7636e..3fb6e662 100644 --- a/LookInside/MCPBridge/LKMCPBridgeInspectionService.swift +++ b/LookInside/MCPBridge/LKMCPBridgeInspectionService.swift @@ -136,7 +136,7 @@ final class LKMCPBridgeInspectionService { ) } - let rootItems: [LookinDisplayItem] + let rootItems: [DisplayItem] if let rootObjectIdentifier { guard let scopedRoot = LKMCPBridgeLiveDocumentLookup.findDisplayItem( amongRoots: dataSource.rawFlatItems ?? [], @@ -165,7 +165,7 @@ final class LKMCPBridgeInspectionService { } } - private static func nodeKindString(for item: LookinDisplayItem) -> String { + private static func nodeKindString(for item: DisplayItem) -> String { switch item.resolvedNodeKind() { // The client's vocabulary has no separate kinds for these two; both // are layers. @@ -181,7 +181,7 @@ final class LKMCPBridgeInspectionService { } } - private func makeViewNode(from item: LookinDisplayItem, remainingDepth: Int?, includeLayoutGuides: Bool, includeCells: Bool) -> LKMCPBridgeViewNode { + private func makeViewNode(from item: DisplayItem, remainingDepth: Int?, includeLayoutGuides: Bool, includeCells: Bool) -> LKMCPBridgeViewNode { let identity = LKMCPBridgeLiveDocumentLookup.objectIdentifierString(for: item) let className = item.displayingObject()?.classChainList?.first ?? "" let frame = LKMCPBridgeRect(cgRect: LKMCPBridgeLiveDocumentLookup.rootSpaceFrame(for: item)) @@ -271,7 +271,7 @@ final class LKMCPBridgeInspectionService { ) } - var rawGroups: [LookinAttributesGroup] = [] + var rawGroups: [AttributesGroup] = [] if let inbuiltGroups = displayItem.attributesGroupList { rawGroups.append(contentsOf: inbuiltGroups) } @@ -312,7 +312,7 @@ final class LKMCPBridgeInspectionService { } private func encodeGroup( - _ group: LookinAttributesGroup, + _ group: AttributesGroup, redactingSecureContent: Bool ) -> LKMCPBridgeAttributeGroup { let identifier = group.userCustomTitle ?? group.identifier @@ -328,7 +328,7 @@ final class LKMCPBridgeInspectionService { } private func encodeSection( - _ section: LookinAttributesSection, + _ section: AttributesSection, redactingSecureContent: Bool ) -> LKMCPBridgeAttributeSection { let attributes = (section.attributes ?? []).map { attribute in diff --git a/LookInside/MCPBridge/LKMCPBridgeInvocationService.swift b/LookInside/MCPBridge/LKMCPBridgeInvocationService.swift index 3e74935d..dff54cd5 100644 --- a/LookInside/MCPBridge/LKMCPBridgeInvocationService.swift +++ b/LookInside/MCPBridge/LKMCPBridgeInvocationService.swift @@ -186,7 +186,7 @@ final class LKMCPBridgeInvocationService { } private func makeReturnedObject(from rawObject: Any?) -> LKMCPBridgeReturnedObject? { - guard let lookinObject = rawObject as? LookinObject else { return nil } + guard let lookinObject = rawObject as? InspectedObject else { return nil } let oidString = String(format: "0x%lx", lookinObject.oid) return LKMCPBridgeReturnedObject( objectIdentifier: oidString, diff --git a/LookInside/MCPBridge/LKMCPBridgeLiveDocumentLookup.swift b/LookInside/MCPBridge/LKMCPBridgeLiveDocumentLookup.swift index 3e7906c7..0064568b 100644 --- a/LookInside/MCPBridge/LKMCPBridgeLiveDocumentLookup.swift +++ b/LookInside/MCPBridge/LKMCPBridgeLiveDocumentLookup.swift @@ -2,7 +2,7 @@ // // Shared lookup helpers that translate the bridge wire identifiers // (`targetIdentifier`, `objectIdentifier`) into the host's live runtime -// objects (`LookinLiveDocument`, `LookinDisplayItem`). Both the inspection +// objects (`LookinLiveDocument`, `DisplayItem`). Both the inspection // service (read-only queries) and the invocation service (round-trips to // the server over the connection channel) share this surface so the wire shape — hex // `oid` strings, decimal `appInfoIdentifier` strings — stays one @@ -26,7 +26,7 @@ enum LKMCPBridgeLiveDocumentLookup { } /// Resolves a wire `targetIdentifier` (decimal string form of - /// `LookinAppInfo.appInfoIdentifier`) to the matching + /// `InspectedAppInfo.appInfoIdentifier`) to the matching /// `LookinLiveDocument`. Returns `nil` when the string is not a valid /// unsigned integer or no open live document carries that /// `appInfoIdentifier`. @@ -39,13 +39,13 @@ enum LKMCPBridgeLiveDocumentLookup { /// Breadth-first search across the supplied root display items for an /// item whose wire `objectIdentifier` matches `identifier`. The wire - /// form is the hex-encoded `LookinObject.oid`, prefixed with `0x` + /// form is the hex-encoded `InspectedObject.oid`, prefixed with `0x` /// (e.g. `0x600000abc123`). static func findDisplayItem( - amongRoots roots: [LookinDisplayItem], + amongRoots roots: [DisplayItem], matchingObjectIdentifier identifier: String - ) -> LookinDisplayItem? { - var queue: [LookinDisplayItem] = roots + ) -> DisplayItem? { + var queue: [DisplayItem] = roots while queue.isEmpty == false { let current = queue.removeFirst() if objectIdentifierString(for: current) == identifier { @@ -61,7 +61,7 @@ enum LKMCPBridgeLiveDocumentLookup { /// Top-level display items (windows / scenes) inside a live document. /// These are the seed points for `findDisplayItem(amongRoots:matchingObjectIdentifier:)` /// when the caller didn't pre-narrow the search space. - static func topLevelDisplayItems(in document: LookinLiveDocument) -> [LookinDisplayItem] { + static func topLevelDisplayItems(in document: LookinLiveDocument) -> [DisplayItem] { guard let dataSource = document.hierarchyDataSource, let flatItems = dataSource.rawFlatItems else { return [] } @@ -75,14 +75,14 @@ enum LKMCPBridgeLiveDocumentLookup { /// Canonical hex-encoded `objectIdentifier` string for a display item. /// Stays in sync with the form returned by `hierarchy.read` so /// callers can round-trip identifiers across bridge methods. - static func objectIdentifierString(for item: LookinDisplayItem) -> String { + static func objectIdentifierString(for item: DisplayItem) -> String { let oid = item.displayingObject()?.oid ?? 0 return String(format: "0x%lx", oid) } /// The item's rectangle in the root coordinate space. /// - /// `LookinDisplayItem.frame` is *parent*-relative -- `calculateFrameToRoot` + /// `DisplayItem.frame` is *parent*-relative -- `calculateFrameToRoot` /// exists precisely because composing it up the tree is non-trivial (it /// has to subtract each ancestor's `bounds` origin and flip for AppKit /// superitems). The bridge reports root-space rectangles so an agent can @@ -92,7 +92,7 @@ enum LKMCPBridgeLiveDocumentLookup { /// `hasValidFrameToRoot` is a check on `frame` itself, so in that case /// both values are equally meaningless and the raw one at least matches /// what the host inspector displays. - static func rootSpaceFrame(for item: LookinDisplayItem) -> CGRect { + static func rootSpaceFrame(for item: DisplayItem) -> CGRect { return item.hasValidFrameToRoot() ? item.calculateFrameToRoot() : item.frame } } diff --git a/LookInside/MCPBridge/LKMCPBridgeModificationService.swift b/LookInside/MCPBridge/LKMCPBridgeModificationService.swift index 88ed8c35..84c453f8 100644 --- a/LookInside/MCPBridge/LKMCPBridgeModificationService.swift +++ b/LookInside/MCPBridge/LKMCPBridgeModificationService.swift @@ -7,7 +7,7 @@ // // This is the second mutating bridge route (after `invoke.method`). // It shares the same round-trip plumbing — selector lookup -// happens against `LookinDashboardBlueprint`; the polymorphic wire +// happens against `DashboardBlueprint`; the polymorphic wire // value is decoded into the right ObjC type by // `LKMCPBridgeAttributeValueDecoder`; the round-trip awaits // `LKInspectableApp.submit(_:)`; @@ -15,7 +15,7 @@ // attribute so the caller can compare against what they sent. // // The bridge does NOT pre-compute settability — it asks -// `LookinDashboardBlueprint setterWithAttrID:` for the setter SEL and +// `DashboardBlueprint setterWithAttrID:` for the setter SEL and // surfaces `modify.readOnly` when the blueprint returns nil. This // matches the host inspector's existing modification gate. @@ -111,7 +111,7 @@ final class LKMCPBridgeModificationService { // Setter lookup. `setter(withAttrID:)` returns nil for read-only // attributes (e.g. computed Relation, class chain, AutoLayout // constraint summaries). - guard let setterSelector = LookinDashboardBlueprint.setter(withAttrID: attributeIdentifier) else { + guard let setterSelector = DashboardBlueprint.setter(withAttrID: attributeIdentifier) else { return .failure( identifier: identifier, error: LKMCPBridgeErrorPayload( @@ -132,7 +132,7 @@ final class LKMCPBridgeModificationService { ) } - // Decode wire value into the polymorphic id LookinAttributeModification expects. + // Decode wire value into the polymorphic id AttributeModification expects. let nativeValue: Any do { nativeValue = try LKMCPBridgeAttributeValueDecoder.decode( @@ -169,15 +169,15 @@ final class LKMCPBridgeModificationService { return .failure(identifier: identifier, error: .internalError) } - // Build the LookinAttributeModification. - let modification = LookinAttributeModification() + // Build the AttributeModification. + let modification = AttributeModification() modification.targetOid = nativeOid modification.setterSelector = setterSelector modification.attrType = attribute.attrType modification.value = nativeValue modification.clientReadableVersion = LKHelper.lookinReadableVersion() - let detail: LookinDisplayItemDetail + let detail: DisplayItemDetail do { detail = try await document.inspectableApp.submit(modification) } catch { @@ -259,8 +259,8 @@ final class LKMCPBridgeModificationService { private func findAttribute( withIdentifier identifier: String, - in groups: [LookinAttributesGroup] - ) -> LookinAttribute? { + in groups: [AttributesGroup] + ) -> InspectedAttribute? { for group in groups { for section in group.attrSections ?? [] { for attribute in section.attributes ?? [] { diff --git a/LookInside/MCPBridge/LKMCPBridgeScreenshotService.swift b/LookInside/MCPBridge/LKMCPBridgeScreenshotService.swift index 054019f8..e4bebbfc 100644 --- a/LookInside/MCPBridge/LKMCPBridgeScreenshotService.swift +++ b/LookInside/MCPBridge/LKMCPBridgeScreenshotService.swift @@ -6,7 +6,7 @@ // // Why every mode goes through RPC 203 rather than RPC 201 `App`: // RPC 201 with `needImages=YES` also carries a whole-app screenshot -// (`LookinAppInfo.screenshot`), but reaching it means driving +// (`InspectedAppInfo.screenshot`), but reaching it means driving // `LKAppsManager.fetchAppInfos(needImages:localInfos:)`, which re-scans // *every* Server port and rebuilds a fresh `LKInspectableApp` list // for all connected apps. That is a heavyweight, side-effecting @@ -18,7 +18,7 @@ // and get the key window's group screenshot. // // Caching: the host already holds `soloScreenshot` / `groupScreenshot` -// on `LookinDisplayItem` whenever the inspector UI has rendered that +// on `DisplayItem` whenever the inspector UI has rendered that // view. Those are served directly (`fromCache: true`) so repeat calls // stay cheap. On a miss the service issues RPC 203 with the matching // task type, merges the response back through @@ -63,7 +63,7 @@ final class LKMCPBridgeScreenshotService { // MARK: - Screenshot mode - /// Which of the two `LookinDisplayItemDetail` screenshot slots the + /// Which of the two `DisplayItemDetail` screenshot slots the /// caller wants. Mirrors `LookinStaticAsyncUpdateTaskType` minus its /// `NoScreenshot` case, which has no meaning on this route. private enum ScreenshotMode: String { @@ -79,14 +79,14 @@ final class LKMCPBridgeScreenshotService { } } - func cachedImage(on displayItem: LookinDisplayItem) -> NSImage? { + func cachedImage(on displayItem: DisplayItem) -> NSImage? { switch self { case .solo: return displayItem.soloScreenshot case .group: return displayItem.groupScreenshot } } - func image(in detail: LookinDisplayItemDetail) -> NSImage? { + func image(in detail: DisplayItemDetail) -> NSImage? { switch self { case .solo: return detail.soloScreenshot case .group: return detail.groupScreenshot @@ -186,7 +186,7 @@ final class LKMCPBridgeScreenshotService { // Resolve which display item to capture. let roots = LKMCPBridgeLiveDocumentLookup.topLevelDisplayItems(in: document) - let displayItem: LookinDisplayItem + let displayItem: DisplayItem if let requestedObjectIdentifier { guard let found = LKMCPBridgeLiveDocumentLookup.findDisplayItem( amongRoots: roots, @@ -249,7 +249,7 @@ final class LKMCPBridgeScreenshotService { ) } - let task = LookinStaticAsyncUpdateTask() + let task = StaticAsyncUpdateTask() task.oid = nativeObjectIdentifier task.taskType = mode.taskType // Attributes are `read_attributes` / `read_view_details` territory; @@ -260,11 +260,11 @@ final class LKMCPBridgeScreenshotService { task.needSubitems = false task.clientReadableVersion = LKHelper.lookinReadableVersion() - let package = LookinStaticAsyncUpdateTasksPackage() + let package = StaticAsyncUpdateTasksPackage() package.tasks = [task] // We sent exactly one task, so at most one detail can match. - var matchingDetail: LookinDisplayItemDetail? + var matchingDetail: DisplayItemDetail? do { for try await frame in document.inspectableApp.hierarchyDetails(packages: [package]) where matchingDetail == nil { matchingDetail = frame.first { $0.displayItemOid == nativeObjectIdentifier } @@ -330,7 +330,7 @@ final class LKMCPBridgeScreenshotService { image: NSImage, objectIdentifier: String, mode: ScreenshotMode, - displayItem: LookinDisplayItem, + displayItem: DisplayItem, maximumPixelDimension: Int, containsSecureContent: Bool, servedFromCache: Bool @@ -436,8 +436,8 @@ final class LKMCPBridgeScreenshotService { /// the secure-content detector flags. A `group` screenshot renders /// the whole subtree, so a secure field nested three levels down /// still ends up in the returned pixels. - private static func subtreeContainsSecureContent(rootDisplayItem: LookinDisplayItem) -> Bool { - var pendingItems: [LookinDisplayItem] = [rootDisplayItem] + private static func subtreeContainsSecureContent(rootDisplayItem: DisplayItem) -> Bool { + var pendingItems: [DisplayItem] = [rootDisplayItem] while pendingItems.isEmpty == false { let currentItem = pendingItems.removeFirst() if LKMCPBridgeSecureContentDetector.isSecure(displayItem: currentItem) { diff --git a/LookInside/MCPBridge/LKMCPBridgeSearchQuery.swift b/LookInside/MCPBridge/LKMCPBridgeSearchQuery.swift index 8ab1c2b7..e1df458e 100644 --- a/LookInside/MCPBridge/LKMCPBridgeSearchQuery.swift +++ b/LookInside/MCPBridge/LKMCPBridgeSearchQuery.swift @@ -50,7 +50,7 @@ struct LKMCPBridgeSearchQuery: Sendable { /// One hierarchy node reduced to the strings this type knows how to /// match. Built by the service layer so this type never touches - /// `LookinDisplayItem`. + /// `DisplayItem`. struct Candidate: Sendable { let className: String let classChain: [String] diff --git a/LookInside/MCPBridge/LKMCPBridgeSearchService.swift b/LookInside/MCPBridge/LKMCPBridgeSearchService.swift index f1477339..4bef81dc 100644 --- a/LookInside/MCPBridge/LKMCPBridgeSearchService.swift +++ b/LookInside/MCPBridge/LKMCPBridgeSearchService.swift @@ -167,7 +167,7 @@ final class LKMCPBridgeSearchService { ) } - let searchScope: [LookinDisplayItem] + let searchScope: [DisplayItem] if let scopeObjectIdentifier { guard let scopeRoot = LKMCPBridgeLiveDocumentLookup.findDisplayItem( amongRoots: allItems, @@ -181,7 +181,7 @@ final class LKMCPBridgeSearchService { ) ) } - var subtree: [LookinDisplayItem] = [] + var subtree: [DisplayItem] = [] scopeRoot.enumerateSelfAndChildren { subtree.append($0) } searchScope = subtree } else { @@ -232,7 +232,7 @@ final class LKMCPBridgeSearchService { // MARK: - Candidate / match construction - private func makeCandidate(from item: LookinDisplayItem) -> LKMCPBridgeSearchQuery.Candidate { + private func makeCandidate(from item: DisplayItem) -> LKMCPBridgeSearchQuery.Candidate { let displayingObject = item.displayingObject() let classChain = displayingObject?.classChainList ?? [] @@ -257,7 +257,7 @@ final class LKMCPBridgeSearchService { } private func makeMatch( - from item: LookinDisplayItem, + from item: DisplayItem, matchedFields: [LKMCPBridgeSearchQuery.Field] ) -> LKMCPBridgeSearchMatch { // Titles and subtitles can carry app-supplied strings through the @@ -299,7 +299,7 @@ final class LKMCPBridgeSearchService { /// Path components use the class name rather than the display title: /// the title can be an app-supplied custom string, and a path is for /// orientation, not for reading back app content. - private static func pathComponentTitle(for item: LookinDisplayItem) -> String { + private static func pathComponentTitle(for item: DisplayItem) -> String { let className = item.displayingObject()?.classChainList?.first ?? "" return className.isEmpty ? "?" : className } diff --git a/LookInside/MCPBridge/LKMCPBridgeSecureContentDetector.swift b/LookInside/MCPBridge/LKMCPBridgeSecureContentDetector.swift index c9cbdc47..dd3d86dd 100644 --- a/LookInside/MCPBridge/LKMCPBridgeSecureContentDetector.swift +++ b/LookInside/MCPBridge/LKMCPBridgeSecureContentDetector.swift @@ -30,7 +30,7 @@ enum LKMCPBridgeSecureContentDetector { /// callers must replace any user-visible text strings on the item's /// attributes with `null` (or a `kind: "redacted"` marker) before /// emitting them on the bridge socket. - static func isSecure(displayItem: LookinDisplayItem) -> Bool { + static func isSecure(displayItem: DisplayItem) -> Bool { guard let classChain = displayItem.viewObject?.classChainList else { return false } diff --git a/LookInside/Manager/LKHelper.swift b/LookInside/Manager/LKHelper.swift index 1c0ceee1..6a25f307 100644 --- a/LookInside/Manager/LKHelper.swift +++ b/LookInside/Manager/LKHelper.swift @@ -96,7 +96,7 @@ final class LKHelper { isEnglishLanguage } - static func appInfoLooksLikeMacTarget(_ appInfo: LookinAppInfo?) -> Bool { + static func appInfoLooksLikeMacTarget(_ appInfo: InspectedAppInfo?) -> Bool { guard let appInfo else { return false } @@ -126,7 +126,7 @@ final class LKHelper { } /// Convenience wrapper combining appInfoLooksLikeMacTarget(_:) and viewClassName(forMacTarget:). - static func viewClassName(for appInfo: LookinAppInfo?) -> String { + static func viewClassName(for appInfo: InspectedAppInfo?) -> String { viewClassName(forMacTarget: appInfoLooksLikeMacTarget(appInfo)) } diff --git a/LookInside/Manager/LKNavigationManager.swift b/LookInside/Manager/LKNavigationManager.swift index 7a66fde2..e121ad80 100644 --- a/LookInside/Manager/LKNavigationManager.swift +++ b/LookInside/Manager/LKNavigationManager.swift @@ -101,7 +101,7 @@ final class LKNavigationManager: NSObject, NSWindowDelegate { /// so it gets the same document life cycle (Save As, Versions, Recent on /// save) as a file-backed archive, and shows its window. @objc(showReaderWithHierarchyFile:title:) - func showReader(with file: LookinHierarchyFile?, title: String?) { + func showReader(with file: HierarchyFile?, title: String?) { let document = LookinArchiveDocument() document.hierarchyFile = file NSDocumentController.shared.addDocument(document) diff --git a/LookInside/Measure/LKMeasureController.swift b/LookInside/Measure/LKMeasureController.swift index 1fa9a049..2561967f 100644 --- a/LookInside/Measure/LKMeasureController.swift +++ b/LookInside/Measure/LKMeasureController.swift @@ -158,7 +158,7 @@ final class LKMeasureController: LKBaseViewController { let selectedFrame = selectedItem.calculateFrameToRoot() let hoveredFrame = hoveredItem.calculateFrameToRoot() - let invalid: (item: LookinDisplayItem, property: String)? = + let invalid: (item: DisplayItem, property: String)? = if selectedFrame.width <= 0 { (selectedItem, NSLocalizedString("width", comment: "")) } else if selectedFrame.height <= 0 { diff --git a/LookInside/Measure/LKMeasureResultView.swift b/LookInside/Measure/LKMeasureResultView.swift index 113a0ad3..c64ea17d 100644 --- a/LookInside/Measure/LKMeasureResultView.swift +++ b/LookInside/Measure/LKMeasureResultView.swift @@ -53,17 +53,17 @@ final class LKMeasureResultView: LKBaseView { for borderLayer in [mainImageViewBorderLayer, referImageViewBorderLayer] { borderLayer.borderWidth = 1 - borderLayer.lookin_removeImplicitAnimations() + borderLayer.removeImplicitAnimations() linesContainerView.layer?.addSublayer(borderLayer) } horizontalLinesLayer.lineWidth = 1 - horizontalLinesLayer.lookin_removeImplicitAnimations() + horizontalLinesLayer.removeImplicitAnimations() horizontalLinesLayer.strokeColor = Self.horizontalColor.cgColor linesContainerView.layer?.addSublayer(horizontalLinesLayer) verticalLinesLayer.lineWidth = 1 - verticalLinesLayer.lookin_removeImplicitAnimations() + verticalLinesLayer.removeImplicitAnimations() verticalLinesLayer.strokeColor = Self.verticalColor.cgColor linesContainerView.layer?.addSublayer(verticalLinesLayer) @@ -150,7 +150,7 @@ final class LKMeasureResultView: LKBaseView { let labelView = dequeueLabelView() labelView.backgroundColor = .systemBlue - labelView.textField.stringValue = NSString.lookin_string(from: Double(line.value), decimal: 2) + labelView.textField.stringValue = NSString.string(from: Double(line.value), decimal: 2) labelView.lkpSizeToFit() labelView.lkpSetHeight(Self.labelHeight) labelView.lkpSetMidX(line.startX + (line.endX - line.startX) / 2) @@ -169,7 +169,7 @@ final class LKMeasureResultView: LKBaseView { let labelView = dequeueLabelView() labelView.backgroundColor = Self.verticalColor - labelView.textField.stringValue = NSString.lookin_string(from: Double(line.value), decimal: 2) + labelView.textField.stringValue = NSString.string(from: Double(line.value), decimal: 2) labelView.lkpSizeToFit() labelView.lkpSetHeight(Self.labelHeight) labelView.lkpSetMidY(line.startY + (line.endY - line.startY) / 2) diff --git a/LookInside/PrivateDiscriminator/LKPrivateDiscriminatorStore.swift b/LookInside/PrivateDiscriminator/LKPrivateDiscriminatorStore.swift index a37ce1a9..0442622f 100644 --- a/LookInside/PrivateDiscriminator/LKPrivateDiscriminatorStore.swift +++ b/LookInside/PrivateDiscriminator/LKPrivateDiscriminatorStore.swift @@ -249,7 +249,7 @@ final class LKPrivateDiscriminatorStore: NSObject { } @objc(displayTitleForDisplayItem:fallback:) - func displayTitle(for _: LookinDisplayItem, fallback: String?) -> String? { + func displayTitle(for _: DisplayItem, fallback: String?) -> String? { guard featureEnabled, let fallback, !fallback.isEmpty else { return fallback } @@ -258,7 +258,7 @@ final class LKPrivateDiscriminatorStore: NSObject { } @objc(isPrivateDisplayItem:) - func isPrivateDisplayItem(_ item: LookinDisplayItem) -> Bool { + func isPrivateDisplayItem(_ item: DisplayItem) -> Bool { guard featureEnabled else { return false } @@ -266,7 +266,7 @@ final class LKPrivateDiscriminatorStore: NSObject { } @objc(appendingPrivateDiscriminatorGroupToGroups:forDisplayItem:) - func appendingPrivateDiscriminatorGroup(to groups: [LookinAttributesGroup], for item: LookinDisplayItem) -> [LookinAttributesGroup] { + func appendingPrivateDiscriminatorGroup(to groups: [AttributesGroup], for item: DisplayItem) -> [AttributesGroup] { guard featureEnabled, let descriptor = dashboardDescriptor(for: item) else { return groups } @@ -282,7 +282,7 @@ final class LKPrivateDiscriminatorStore: NSObject { } @objc(submitPrivateDiscriminatorForDisplayItem:module:filename:error:) - func submitPrivateDiscriminator(for item: LookinDisplayItem, module: String, filename: String, error: NSErrorPointer) -> Bool { + func submitPrivateDiscriminator(for item: DisplayItem, module: String, filename: String, error: NSErrorPointer) -> Bool { do { guard let parsed = parsedPrivateDiscriminator(for: item) else { throw LKPrivateDiscriminatorStoreError.missingPrivateDiscriminator @@ -308,7 +308,7 @@ final class LKPrivateDiscriminatorStore: NSObject { } @objc(importPrivateDiscriminatorFromCodebaseForDisplayItem:window:error:) - func importPrivateDiscriminatorFromCodebase(for item: LookinDisplayItem, window: NSWindow?, error: NSErrorPointer) -> Bool { + func importPrivateDiscriminatorFromCodebase(for item: DisplayItem, window: NSWindow?, error: NSErrorPointer) -> Bool { do { guard let parsed = parsedPrivateDiscriminator(for: item) else { throw LKPrivateDiscriminatorStoreError.missingPrivateDiscriminator @@ -342,7 +342,7 @@ final class LKPrivateDiscriminatorStore: NSObject { } @objc(beginSwiftPDGuessForDisplayItem:window:) - func beginSwiftPDGuess(for item: LookinDisplayItem, window: NSWindow?) { + func beginSwiftPDGuess(for item: DisplayItem, window: NSWindow?) { guard let parsed = parsedPrivateDiscriminator(for: item) else { return } @@ -409,7 +409,7 @@ final class LKPrivateDiscriminatorStore: NSObject { } @objc(cancelSwiftPDGuessForDisplayItem:) - func cancelSwiftPDGuess(for item: LookinDisplayItem) { + func cancelSwiftPDGuess(for item: DisplayItem) { guard let parsed = parsedPrivateDiscriminator(for: item), let task = activeGuessTasksByID[parsed.id] else { @@ -710,7 +710,7 @@ final class LKPrivateDiscriminatorStore: NSObject { postDashboardStateDidChange() } - private func dashboardDescriptor(for item: LookinDisplayItem) -> DashboardDescriptor? { + private func dashboardDescriptor(for item: DisplayItem) -> DashboardDescriptor? { guard let parsed = parsedPrivateDiscriminator(for: item) else { return nil } @@ -782,7 +782,7 @@ final class LKPrivateDiscriminatorStore: NSObject { return nil } - private func parsedPrivateDiscriminator(for item: LookinDisplayItem) -> ParsedDiscriminator? { + private func parsedPrivateDiscriminator(for item: DisplayItem) -> ParsedDiscriminator? { for text in candidateTexts(for: item) { guard let id = Self.privateDiscriminatorID(in: text) else { continue @@ -796,7 +796,7 @@ final class LKPrivateDiscriminatorStore: NSObject { return nil } - private func candidateTexts(for item: LookinDisplayItem) -> [String] { + private func candidateTexts(for item: DisplayItem) -> [String] { var texts: [String] = [] func append(_ value: String?) { @@ -825,7 +825,7 @@ final class LKPrivateDiscriminatorStore: NSObject { return texts } - private func appendTexts(from object: LookinObject?, into texts: inout [String]) { + private func appendTexts(from object: InspectedObject?, into texts: inout [String]) { guard let object else { return } @@ -863,19 +863,19 @@ final class LKPrivateDiscriminatorStore: NSObject { return nil } - private func makeDashboardGroup(for item: LookinDisplayItem, descriptor: DashboardDescriptor) -> LookinAttributesGroup { - let attribute = LookinAttribute() + private func makeDashboardGroup(for item: DisplayItem, descriptor: DashboardDescriptor) -> AttributesGroup { + let attribute = InspectedAttribute() attribute.identifier = Self.dashboardAttributeIdentifier attribute.displayTitle = NSLocalizedString("Discriminator Details", comment: "") attribute.attrType = .customObj attribute.value = LKPrivateDiscriminatorDashboardPayload(descriptor: descriptor) attribute.targetDisplayItem = item - let section = LookinAttributesSection() + let section = AttributesSection() section.identifier = LookinAttrSec_UserCustom section.attributes = [attribute] - let group = LookinAttributesGroup() + let group = AttributesGroup() group.identifier = LookinAttrGroup_UserCustom group.userCustomTitle = Self.dashboardTitle group.attrSections = [section] diff --git a/LookInside/Read/LKReadHierarchyController.swift b/LookInside/Read/LKReadHierarchyController.swift index debd3d54..6640c846 100644 --- a/LookInside/Read/LKReadHierarchyController.swift +++ b/LookInside/Read/LKReadHierarchyController.swift @@ -13,13 +13,13 @@ import AppKit @objc(LKReadHierarchyController) final class LKReadHierarchyController: LKHierarchyController { @objc(hierarchyView:needToCancelPreviewOfItem:) - func hierarchyView(_: LKHierarchyView?, needToCancelPreviewOf item: LookinDisplayItem?) { + func hierarchyView(_: LKHierarchyView?, needToCancelPreviewOf item: DisplayItem?) { item?.noPreview = true notifyNoPreviewDidChange() } @objc(hierarchyView:needToShowPreviewOfItem:) - func hierarchyView(_: LKHierarchyView?, needToShowPreviewOf item: LookinDisplayItem?) { + func hierarchyView(_: LKHierarchyView?, needToShowPreviewOf item: DisplayItem?) { // A preview shows only when none of its ancestors hides theirs. item?.enumerateSelfAndAncestors { item, _ in if item.noPreview { diff --git a/LookInside/Read/LKReadHierarchyDataSource.swift b/LookInside/Read/LKReadHierarchyDataSource.swift index 9e5b6757..f8aebc80 100644 --- a/LookInside/Read/LKReadHierarchyDataSource.swift +++ b/LookInside/Read/LKReadHierarchyDataSource.swift @@ -16,7 +16,7 @@ final class LKReadHierarchyDataSource: LKHierarchyDataSource { private let readPreferenceManager: LKPreferenceManager @objc(initWithFile:preferenceManager:) - init(file: LookinHierarchyFile, preferenceManager manager: LKPreferenceManager) { + init(file: HierarchyFile, preferenceManager manager: LKPreferenceManager) { readPreferenceManager = manager super.init() diff --git a/LookInside/Read/LKReadViewController.swift b/LookInside/Read/LKReadViewController.swift index edfe14c8..fc74b0a7 100644 --- a/LookInside/Read/LKReadViewController.swift +++ b/LookInside/Read/LKReadViewController.swift @@ -27,7 +27,7 @@ final class LKReadViewController: LKBaseViewController, NSSplitViewDelegate { private var stateObservation: NSKeyValueObservation? @objc(initWithFile:preferenceManager:) - init(file: LookinHierarchyFile, preferenceManager manager: LKPreferenceManager) { + init(file: HierarchyFile, preferenceManager manager: LKPreferenceManager) { let dataSource = LKReadHierarchyDataSource(file: file, preferenceManager: manager) hierarchyDataSource = dataSource hierarchyController = LKReadHierarchyController(dataSource: dataSource) diff --git a/LookInside/Read/LKReadWindowController.swift b/LookInside/Read/LKReadWindowController.swift index 5a3529c7..68f8a8ae 100644 --- a/LookInside/Read/LKReadWindowController.swift +++ b/LookInside/Read/LKReadWindowController.swift @@ -25,7 +25,7 @@ final class LKReadWindowController: LKWindowController, NSToolbarDelegate { private var toolbarItemsMap: [String: NSToolbarItem] = [:] private var hierarchyFileObservation: NSKeyValueObservation? private var selectedItemObservation: NSKeyValueObservation? - private weak var shownFile: LookinHierarchyFile? + private weak var shownFile: HierarchyFile? @objc(initWithDocument:) init(document: LookinArchiveDocument) { @@ -70,7 +70,7 @@ final class LKReadWindowController: LKWindowController, NSToolbarDelegate { fatalError("init(coder:) is not supported") } - private func hierarchyFileDidChange(_ file: LookinHierarchyFile?) { + private func hierarchyFileDidChange(_ file: HierarchyFile?) { // Each new file once; the same file set again is not a new reader. guard let file, file !== shownFile else { return } shownFile = file @@ -95,7 +95,7 @@ final class LKReadWindowController: LKWindowController, NSToolbarDelegate { /// Builds the reader for `file` in this window: the view controller, the /// measure button's enabled state, and the toolbar, whose items need the /// data source to exist. - private func showHierarchyFile(_ file: LookinHierarchyFile) { + private func showHierarchyFile(_ file: HierarchyFile) { guard let window else { return } let viewController = LKReadViewController(file: file, preferenceManager: preferenceManager) self.viewController = viewController diff --git a/LookInside/Read/LookinArchiveCoding.swift b/LookInside/Read/LookinArchiveCoding.swift index 38ecca84..b06cd0e6 100644 --- a/LookInside/Read/LookinArchiveCoding.swift +++ b/LookInside/Read/LookinArchiveCoding.swift @@ -2,7 +2,7 @@ // LookinArchiveCoding.swift // LookInside // -// Turns a `LookinHierarchyFile` into the bytes of a `.lookin` file and back. +// Turns a `HierarchyFile` into the bytes of a `.lookin` file and back. // The format is the keyed archive Lookin has always written: the class // names and coding keys belong to the LookinCore model and must not change, // so files written by older hosts open here and files written here open in @@ -16,7 +16,7 @@ enum LookinArchiveCoding { static let typeIdentifier = "com.lookin.lookin" /// Archives `file` with secure coding, as the Objective-C reader did. - static func data(of file: LookinHierarchyFile) throws -> Data { + static func data(of file: HierarchyFile) throws -> Data { try NSKeyedArchiver.archivedData(withRootObject: file, requiringSecureCoding: true) } @@ -27,7 +27,7 @@ enum LookinArchiveCoding { /// the log. A root object of another class fails the same way as an /// unreadable archive. A file outside the supported server versions /// fails with the version error from `+verifyHierarchyFile:`. - static func hierarchyFile(from data: Data) throws -> LookinHierarchyFile { + static func hierarchyFile(from data: Data) throws -> HierarchyFile { let unarchiver: NSKeyedUnarchiver do { unarchiver = try NSKeyedUnarchiver(forReadingFrom: data) @@ -37,10 +37,10 @@ enum LookinArchiveCoding { unarchiver.requiresSecureCoding = false let root = unarchiver.decodeObject(forKey: NSKeyedArchiveRootObjectKey) unarchiver.finishDecoding() - guard let file = root as? LookinHierarchyFile else { + guard let file = root as? HierarchyFile else { throw innerError } - if let verifyError = LookinHierarchyFile.verifyHierarchyFile(file) { + if let verifyError = HierarchyFile.verifyHierarchyFile(file) { throw verifyError } return file diff --git a/LookInside/Read/LookinArchiveDocument.swift b/LookInside/Read/LookinArchiveDocument.swift index 64a285c9..73dc5a1a 100644 --- a/LookInside/Read/LookinArchiveDocument.swift +++ b/LookInside/Read/LookinArchiveDocument.swift @@ -15,7 +15,7 @@ import AppKit class LookinArchiveDocument: NSDocument { /// The archive's hierarchy. The window controller observes it (KVO) and /// builds a reader for every file assigned. - @objc dynamic var hierarchyFile: LookinHierarchyFile? + @objc dynamic var hierarchyFile: HierarchyFile? override class var autosavesInPlace: Bool { false diff --git a/LookInside/Static/LKStaticAsyncUpdateManager.swift b/LookInside/Static/LKStaticAsyncUpdateManager.swift index 816a4b7a..1900aca5 100644 --- a/LookInside/Static/LKStaticAsyncUpdateManager.swift +++ b/LookInside/Static/LKStaticAsyncUpdateManager.swift @@ -114,14 +114,14 @@ final class LKStaticAsyncUpdateManager: NSObject { /// group screenshots of its ancestors after an attribute was modified. /// Progress goes to `modifyingUpdates`. @objc(updateAfterModifyingDisplayItem:) - func updateAfterModifyingDisplayItem(_ displayItem: LookinDisplayItem?) { + func updateAfterModifyingDisplayItem(_ displayItem: DisplayItem?) { guard let app = inspectableApp else { return } guard let displayItem else { assertionFailure() return } - var tasks: [LookinStaticAsyncUpdateTask] = [] + var tasks: [StaticAsyncUpdateTask] = [] displayItem.enumerateSelfAndAncestors { item, _ in guard item.doNotFetchScreenshotReason == .fetchScreenshotPermitted else { return } if item === displayItem, !(item.subitems ?? []).isEmpty, @@ -142,7 +142,7 @@ final class LKStaticAsyncUpdateManager: NSObject { guard let self else { return } switch event { case let .value(value): - guard let detail = value as? LookinDisplayItemDetail else { return } + guard let detail = value as? DisplayItemDetail else { return } dataSource?.modify(with: detail) if detail.groupScreenshot != nil { receivedScreenshotsCount += 1 @@ -162,7 +162,7 @@ final class LKStaticAsyncUpdateManager: NSObject { /// Fetches one item's screenshots and attributes again, not its sub items. @objc(reloadSingleDisplayItem:) - func reloadSingleDisplayItem(_ item: LookinDisplayItem?) { + func reloadSingleDisplayItem(_ item: DisplayItem?) { let tasks = makeReloadSingleItemTasks(item) guard !tasks.isEmpty else { return } send(tasks) @@ -170,7 +170,7 @@ final class LKStaticAsyncUpdateManager: NSObject { /// Fetches an item and its sub items again, then their details. @objc(reloadDisplayItemAndChildren:) - func reloadDisplayItemAndChildren(_ rootItem: LookinDisplayItem?) { + func reloadDisplayItemAndChildren(_ rootItem: DisplayItem?) { // First the root item's basis, attributes and sub items. let tasks = makeReloadItemAndChildrenTasks(rootItem) guard let rootItem, !tasks.isEmpty else { return } @@ -191,11 +191,11 @@ final class LKStaticAsyncUpdateManager: NSObject { // MARK: - Tasks - private func makeMaximumTasks() -> [LookinStaticAsyncUpdateTask] { + private func makeMaximumTasks() -> [StaticAsyncUpdateTask] { guard let dataSource else { return [] } // Order matters: earlier tasks are fetched first, so the visible // items go first. - var tasks: [LookinStaticAsyncUpdateTask] = (dataSource.displayingFlatItems ?? []).compactMap { item in + var tasks: [StaticAsyncUpdateTask] = (dataSource.displayingFlatItems ?? []).compactMap { item in if item.isUserCustom() { return nil } @@ -211,7 +211,7 @@ final class LKStaticAsyncUpdateManager: NSObject { return task(from: item, type: .noScreenshot) } - func appendIfNew(_ task: LookinStaticAsyncUpdateTask?) { + func appendIfNew(_ task: StaticAsyncUpdateTask?) { if let task, !tasks.contains(task) { tasks.append(task) } @@ -229,8 +229,8 @@ final class LKStaticAsyncUpdateManager: NSObject { return tasks } - private func makeMinimumTasks(for items: [LookinDisplayItem]) -> [LookinStaticAsyncUpdateTask] { - items.compactMap { item -> LookinStaticAsyncUpdateTask? in + private func makeMinimumTasks(for items: [DisplayItem]) -> [StaticAsyncUpdateTask] { + items.compactMap { item -> StaticAsyncUpdateTask? in if item.isUserCustom() { return nil } @@ -238,7 +238,7 @@ final class LKStaticAsyncUpdateManager: NSObject { // Has its image, and so its attributes too. return nil } - let newTask: LookinStaticAsyncUpdateTask? + let newTask: StaticAsyncUpdateTask? if item.doNotFetchScreenshotReason == .fetchScreenshotPermitted { // Should have an image but does not: fetch it. if item.isExpandable, item.isExpanded { @@ -265,13 +265,13 @@ final class LKStaticAsyncUpdateManager: NSObject { } } - private func updateAfterReloadingItemAndChildren(_ rootItem: LookinDisplayItem) { + private func updateAfterReloadingItemAndChildren(_ rootItem: DisplayItem) { // The root item's and its children's screenshots and attributes. if LKPreferenceManager.shared.fastMode.currentBOOLValue { updateForDisplayingItems() return } - var tasks: [LookinStaticAsyncUpdateTask] = [] + var tasks: [StaticAsyncUpdateTask] = [] rootItem.enumerateSelfAndChildren { item in guard !item.isUserCustom() else { return } if item.doNotFetchScreenshotReason == .fetchScreenshotPermitted { @@ -288,7 +288,7 @@ final class LKStaticAsyncUpdateManager: NSObject { send(tasks) } - private func task(from item: LookinDisplayItem, type: LookinStaticAsyncUpdateTaskType) -> LookinStaticAsyncUpdateTask? { + private func task(from item: DisplayItem, type: LookinStaticAsyncUpdateTaskType) -> StaticAsyncUpdateTask? { let appInfo = dataSource?.rawHierarchyInfo?.appInfo guard Self.allowsSwiftUISupportAccess(for: item, appInfo: appInfo) else { return nil @@ -325,7 +325,7 @@ final class LKStaticAsyncUpdateManager: NSObject { } guard oid != 0 else { return nil } - let task = LookinStaticAsyncUpdateTask() + let task = StaticAsyncUpdateTask() task.oid = oid task.frameSize = item.frame.size task.taskType = type @@ -334,17 +334,17 @@ final class LKStaticAsyncUpdateManager: NSObject { return task } - private static func allowsSwiftUISupportAccess(for item: LookinDisplayItem, appInfo: LookinAppInfo?) -> Bool { + private static func allowsSwiftUISupportAccess(for item: DisplayItem, appInfo: InspectedAppInfo?) -> Bool { guard LKHelper.appInfoLooksLikeMacTarget(appInfo), item.lk_isSwiftUISupportRelated() else { return true } return LKSwiftUISupportGatekeeper.sharedInstance().allowProtectedFeatureAccess(for: NSApplication.shared.keyWindow) } - private static func packages(from tasks: [LookinStaticAsyncUpdateTask]) -> [LookinStaticAsyncUpdateTasksPackage] { + private static func packages(from tasks: [StaticAsyncUpdateTask]) -> [StaticAsyncUpdateTasksPackage] { let areas = tasks.map { Double($0.frameSize.width * $0.frameSize.height) } return DetailTaskPackaging.packageRanges(areas: areas).map { range in - let package = LookinStaticAsyncUpdateTasksPackage() + let package = StaticAsyncUpdateTasksPackage() package.tasks = Array(tasks[range]) return package } @@ -371,13 +371,13 @@ final class LKStaticAsyncUpdateManager: NSObject { private func startRequest( app: LKInspectableApp, type: Int, - tasks: [LookinStaticAsyncUpdateTask], + tasks: [StaticAsyncUpdateTask], onEvent: @escaping (LKAppResponseEvent) -> Void ) { startRequest(app: app, type: type, tasks: tasks as NSArray, onEvent: onEvent) } - private func send(_ newTasks: [LookinStaticAsyncUpdateTask], completion: (() -> Void)? = nil) { + private func send(_ newTasks: [StaticAsyncUpdateTask], completion: (() -> Void)? = nil) { guard let app = inspectableApp, !newTasks.isEmpty else { return } // The same request cannot run twice at once: cancel the previous one. endUpdating() @@ -393,7 +393,7 @@ final class LKStaticAsyncUpdateManager: NSObject { guard let self else { return } switch event { case let .value(value): - receive(details: value as? [LookinDisplayItemDetail] ?? []) + receive(details: value as? [DisplayItemDetail] ?? []) case .failure: fail() case .completion: @@ -404,7 +404,7 @@ final class LKStaticAsyncUpdateManager: NSObject { } } - private func receive(details: [LookinDisplayItemDetail]) { + private func receive(details: [DisplayItemDetail]) { for detail in details { if detail.failureCode != LookinDisplayItemDetailFailureCode.none.rawValue { // ObjectGone is routine: the inspected app released the @@ -508,10 +508,10 @@ extension LKStaticAsyncUpdateManager { /// when it has children), or its attributes alone when it has no /// screenshot. Empty when the Server is too old or the item is a /// SwiftUI item the license does not cover. - fileprivate func makeReloadSingleItemTasks(_ item: LookinDisplayItem?) -> [LookinStaticAsyncUpdateTask] { + fileprivate func makeReloadSingleItemTasks(_ item: DisplayItem?) -> [StaticAsyncUpdateTask] { guard let item, canReload(item) else { return [] } let appInfo = inspectableApp?.appInfo - var tasks: [LookinStaticAsyncUpdateTask] = [] + var tasks: [StaticAsyncUpdateTask] = [] if item.doNotFetchScreenshotReason == .fetchScreenshotPermitted { if let task = Self.reloadTask(from: item, appInfo: appInfo) { task.taskType = .groupScreenshot @@ -531,7 +531,7 @@ extension LKStaticAsyncUpdateManager { /// The task that reloads an item's basis and sub items (no screenshot, /// no attributes). - fileprivate func makeReloadItemAndChildrenTasks(_ item: LookinDisplayItem?) -> [LookinStaticAsyncUpdateTask] { + fileprivate func makeReloadItemAndChildrenTasks(_ item: DisplayItem?) -> [StaticAsyncUpdateTask] { guard let item, canReload(item), let task = Self.reloadTask(from: item, appInfo: inspectableApp?.appInfo) else { @@ -547,7 +547,7 @@ extension LKStaticAsyncUpdateManager { /// Whether `item` may be reloaded: not while updating, not from a /// Server older than 1.2.7 (after an alert), and not for a SwiftUI item /// the license does not cover. - private func canReload(_ item: LookinDisplayItem) -> Bool { + private func canReload(_ item: DisplayItem) -> Bool { if isUpdating() { assertionFailure() return false @@ -570,10 +570,10 @@ extension LKStaticAsyncUpdateManager { return true } - private static func reloadTask(from item: LookinDisplayItem, appInfo: LookinAppInfo?) -> LookinStaticAsyncUpdateTask? { + private static func reloadTask(from item: DisplayItem, appInfo: InspectedAppInfo?) -> StaticAsyncUpdateTask? { let oid = item.bestObjectOidPreferView(LKHelper.appInfoLooksLikeMacTarget(appInfo)) guard oid != 0 else { return nil } - let task = LookinStaticAsyncUpdateTask() + let task = StaticAsyncUpdateTask() task.oid = oid task.frameSize = item.frame.size task.clientReadableVersion = LKHelper.lookinReadableVersion() @@ -585,13 +585,13 @@ extension LKStaticAsyncUpdateManager { /// One details request: its packages and how many of their tasks replied. private final class LKDetailUpdateRequest { - private(set) var packages: [LookinStaticAsyncUpdateTasksPackage] + private(set) var packages: [StaticAsyncUpdateTasksPackage] /// Tasks that received a reply, failed ones included. Which ones is not /// known, only how many. var finishedTasksCount = 0 var failedTasksCount = 0 - init(packages: [LookinStaticAsyncUpdateTasksPackage]) { + init(packages: [StaticAsyncUpdateTasksPackage]) { self.packages = packages } @@ -599,11 +599,11 @@ private final class LKDetailUpdateRequest { packages.reduce(0) { $0 + ($1.tasks?.count ?? 0) } } - func contains(_ task: LookinStaticAsyncUpdateTask) -> Bool { + func contains(_ task: StaticAsyncUpdateTask) -> Bool { packages.contains { ($0.tasks ?? []).contains(task) } } - func removeTasks(of item: LookinDisplayItem) { + func removeTasks(of item: DisplayItem) { let itemOids = Set(item.availableObjectOidsPreferView(false).map(\.uintValue)) for package in packages { package.tasks = (package.tasks ?? []).filter { !itemOids.contains($0.oid) } diff --git a/LookInside/Static/LKStaticConstants.swift b/LookInside/Static/LKStaticConstants.swift index 45a354b4..9f30862e 100644 --- a/LookInside/Static/LKStaticConstants.swift +++ b/LookInside/Static/LKStaticConstants.swift @@ -8,7 +8,7 @@ import CoreGraphics -/// Posted with a LookinDisplayItem as the object to show the console and +/// Posted with a DisplayItem as the object to show the console and /// print that item's view in it. let LKAppShowConsoleNotificationName = "LKAppShowConsoleNotificationName" diff --git a/LookInside/Static/LKStaticHierarchyController.swift b/LookInside/Static/LKStaticHierarchyController.swift index c8019953..d3a14416 100644 --- a/LookInside/Static/LKStaticHierarchyController.swift +++ b/LookInside/Static/LKStaticHierarchyController.swift @@ -14,13 +14,13 @@ final class LKStaticHierarchyController: LKHierarchyController { // MARK: - LKHierarchyViewDelegate @objc(hierarchyView:needToCancelPreviewOfItem:) - func hierarchyView(_: LKHierarchyView?, needToCancelPreviewOf item: LookinDisplayItem?) { + func hierarchyView(_: LKHierarchyView?, needToCancelPreviewOf item: DisplayItem?) { item?.noPreview = true dataSource?.itemDidChangeNoPreview.send() } @objc(hierarchyView:needToShowPreviewOfItem:) - func hierarchyView(_: LKHierarchyView?, needToShowPreviewOf item: LookinDisplayItem?) { + func hierarchyView(_: LKHierarchyView?, needToShowPreviewOf item: DisplayItem?) { item?.enumerateSelfAndAncestors { item, _ in if item.noPreview { item.noPreview = false diff --git a/LookInside/Static/LKStaticHierarchyDataSource.swift b/LookInside/Static/LKStaticHierarchyDataSource.swift index 1d1333a4..68024012 100644 --- a/LookInside/Static/LKStaticHierarchyDataSource.swift +++ b/LookInside/Static/LKStaticHierarchyDataSource.swift @@ -12,7 +12,7 @@ import AppKit /// tasks deliver and starts those tasks. @objc(LKStaticHierarchyDataSource) class LKStaticHierarchyDataSource: LKHierarchyDataSource { - @objc var appInfo: LookinAppInfo! { + @objc var appInfo: InspectedAppInfo! { storedAppInfo } @@ -21,12 +21,12 @@ class LKStaticHierarchyDataSource: LKHierarchyDataSource { /// Sends each item whose frame changed. Also reaches `events()` as /// `.itemDidChangeFrame`. - final let itemsDidChangeFrame = LKSyncSignal() + final let itemsDidChangeFrame = LKSyncSignal() /// Keeps a detail's subitems rebuild from starting a fast-mode update /// while the update task that delivered it is still running: update /// tasks must not overlap. - private var storedAppInfo: LookinAppInfo? + private var storedAppInfo: InspectedAppInfo? private var shouldIgnoreFastModeAutoUpdate = false private var isUsingDanceUI = false private var frameSubscription: LKSyncSubscription? @@ -42,7 +42,7 @@ class LKStaticHierarchyDataSource: LKHierarchyDataSource { // MARK: - Reload @objc(reloadWithHierarchyInfo:keepState:) - override func reload(with info: LookinHierarchyInfo!, keepState: Bool) { + override func reload(with info: HierarchyInfo!, keepState: Bool) { super.reload(with: info, keepState: keepState) storedAppInfo = info.appInfo @@ -77,7 +77,7 @@ class LKStaticHierarchyDataSource: LKHierarchyDataSource { } @objc(modifyWithDisplayItemDetail:) - func modify(with detail: LookinDisplayItemDetail!) { + func modify(with detail: DisplayItemDetail!) { guard let detail else { return } @@ -134,7 +134,7 @@ class LKStaticHierarchyDataSource: LKHierarchyDataSource { } } - private func replaceSubitems(of item: LookinDisplayItem, with subitems: [LookinDisplayItem]) { + private func replaceSubitems(of item: DisplayItem, with subitems: [DisplayItem]) { // Without this flag the buildDisplayingFlatItems below would start a // fast-mode update task while the current one is still running (it // is still in its subscription, not yet completed), and update tasks @@ -154,7 +154,7 @@ class LKStaticHierarchyDataSource: LKHierarchyDataSource { item.subitems = subitems // Flatten the tree again; this also sets every item's indentLevel. - rawFlatItems = LookinDisplayItem.flatItems(fromHierarchicalItems: rawHierarchyInfo?.displayItems ?? []) + rawFlatItems = DisplayItem.flatItems(fromHierarchicalItems: rawHierarchyInfo?.displayItems ?? []) flatItems = rawFlatItems didReloadHierarchyInfo.send() @@ -195,7 +195,7 @@ class LKStaticHierarchyDataSource: LKHierarchyDataSource { // MARK: - Private - private func modify(_ item: LookinDisplayItem, frame: CGRect, bounds: CGRect) { + private func modify(_ item: DisplayItem, frame: CGRect, bounds: CGRect) { if item.frame.equalTo(frame), item.bounds.equalTo(bounds) { return } diff --git a/LookInside/Static/LKStaticViewController.swift b/LookInside/Static/LKStaticViewController.swift index bb1637b8..2bf2c855 100644 --- a/LookInside/Static/LKStaticViewController.swift +++ b/LookInside/Static/LKStaticViewController.swift @@ -186,7 +186,7 @@ final class LKStaticViewController: LKBaseViewController, NSSplitViewDelegate { queue: nil ) { [weak self] note in MainActor.assumeIsolated { - self?.showConsoleAndPrint(note.object as? LookinDisplayItem) + self?.showConsoleAndPrint(note.object as? DisplayItem) } }) } @@ -380,7 +380,7 @@ final class LKStaticViewController: LKBaseViewController, NSSplitViewDelegate { // MARK: - Console - private func showConsoleAndPrint(_ item: LookinDisplayItem?) { + private func showConsoleAndPrint(_ item: DisplayItem?) { let isFirstTimeToShowConsole = consoleController == nil showConsole = true if isFirstTimeToShowConsole { @@ -497,7 +497,7 @@ final class LKStaticViewController: LKBaseViewController, NSSplitViewDelegate { } @objc private func handleNoPreviewTipView() { - hierarchyController.hierarchyView(nil, needToShowPreviewOf: noPreviewTipView.bindingObject as? LookinDisplayItem) + hierarchyController.hierarchyView(nil, needToShowPreviewOf: noPreviewTipView.bindingObject as? DisplayItem) } @objc private func handleCustomViewTipsView() { diff --git a/LookInside/Static/LKStaticWindowController.swift b/LookInside/Static/LKStaticWindowController.swift index 108bd783..b21384c9 100644 --- a/LookInside/Static/LKStaticWindowController.swift +++ b/LookInside/Static/LKStaticWindowController.swift @@ -58,7 +58,7 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr /// What one hierarchy request sent first. private enum HierarchyFetchResult { /// Its first value; nil when that value is not a hierarchy. - case info(LookinHierarchyInfo?) + case info(HierarchyInfo?) /// It ended without sending a value. case noResponse } @@ -213,7 +213,7 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr data: LKInspectableApp.hierarchyRequestParameters() ) for try await value in responses { - return .info(value as? LookinHierarchyInfo) + return .info(value as? HierarchyInfo) } return .noResponse } @@ -361,7 +361,7 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr /// reported before this returns. private func reloadHierarchy( initiator: ReloadInitiator = .host, - completion: @escaping (Result) -> Void + completion: @escaping (Result) -> Void ) { if isFetchingHierarchy { completion(.failure(ReloadError.make( @@ -434,7 +434,7 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr /// `reloadHierarchy(completion:)` for callers outside the UI: no error /// sheet, and the error is thrown instead. - func reloadHierarchy(initiator: ReloadInitiator) async throws -> LookinHierarchyInfo? { + func reloadHierarchy(initiator: ReloadInitiator) async throws -> HierarchyInfo? { try await withCheckedThrowingContinuation { continuation in reloadHierarchy(initiator: initiator) { result in continuation.resume(with: result) @@ -752,8 +752,8 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr } @objc func appMenuManagerDidSelectOpenInNewWindow() { - let newHierarchyInfo = hierarchyDataSource.rawHierarchyInfo?.copy() as? LookinHierarchyInfo - let file = LookinHierarchyFile() + let newHierarchyInfo = hierarchyDataSource.rawHierarchyInfo?.copy() as? HierarchyInfo + let file = HierarchyFile() file.serverVersion = newHierarchyInfo?.serverVersion ?? 0 file.hierarchyInfo = newHierarchyInfo LKNavigationManager.shared.showReader(with: file, title: nil) @@ -797,7 +797,7 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr /// Binds `app` to this window and loads `info`. Every same-window /// reload (auto-connect, toolbar same app, SwiftUI mode) goes through /// here. - private func applyHierarchyInfo(_ info: LookinHierarchyInfo?, for app: LKInspectableApp, keepState: Bool) { + private func applyHierarchyInfo(_ info: HierarchyInfo?, for app: LKInspectableApp, keepState: Bool) { viewController.progressView.finish(completion: nil) inspectableApp = app asyncUpdateManager.inspectableApp = app @@ -855,7 +855,7 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr /// A transient toast that fades out after 2 seconds. Not an alert /// sheet: a modal sheet would block switching the segmented control /// again until dismissed. - private func showSelectionMigratedToast(for item: LookinDisplayItem) { + private func showSelectionMigratedToast(for item: DisplayItem) { let typeName = item.customInfo?.title ?? NSLocalizedString("SwiftUI item", comment: "Fallback name of a SwiftUI node in the selection-moved toast") let message = String( format: NSLocalizedString( diff --git a/LookInside/Static/Preview/LKDisplayItemNode.swift b/LookInside/Static/Preview/LKDisplayItemNode.swift index c173ef2d..d11aae54 100644 --- a/LookInside/Static/Preview/LKDisplayItemNode.swift +++ b/LookInside/Static/Preview/LKDisplayItemNode.swift @@ -12,7 +12,7 @@ import SceneKit /// One item's plane in the 3D preview: the screenshot (or background /// colour), a tint mask for hover and selection, and an outline. @objc(LKDisplayItemNode) -final class LKDisplayItemNode: SCNNode, LookinDisplayItemDelegate { +final class LKDisplayItemNode: SCNNode, DisplayItemDelegate { /// Rendering order added to a coplanar overlay node's border so it draws /// after every ordinary node. Paired with a depth-test-free material, /// this puts the highlight box on top of whatever the owning view has @@ -30,7 +30,7 @@ final class LKDisplayItemNode: SCNNode, LookinDisplayItemDelegate { private let contentPlane = SCNPlane() private let contentNode: SCNNode /// Shows the screenshot when it covers only a region of the node (see - /// LookinDisplayItem.groupScreenshotRegion). The content plane stays the + /// DisplayItem.groupScreenshotRegion). The content plane stays the /// size of the whole node underneath it — it is the plane hit-testing /// selects by — and shows the background colour, or nothing. private let regionPlane = SCNPlane() @@ -68,7 +68,7 @@ final class LKDisplayItemNode: SCNNode, LookinDisplayItemDelegate { } } - var displayItem: LookinDisplayItem? { + var displayItem: DisplayItem? { didSet { // Never set the contents to nil: some scenes then render the // wrong content. @@ -351,13 +351,13 @@ final class LKDisplayItemNode: SCNNode, LookinDisplayItemDelegate { NSColor(red: red / 255, green: green / 255, blue: blue / 255, alpha: alpha) } - // MARK: - LookinDisplayItemDelegate + // MARK: - DisplayItemDelegate - func displayItem(_ displayItem: LookinDisplayItem!, propertyDidChange property: LookinDisplayItemProperty) { + func displayItem(_ displayItem: DisplayItem, propertyDidChange property: LookinDisplayItemProperty) { render(displayItem, changedProperty: property) } - private func render(_ displayItem: LookinDisplayItem, changedProperty property: LookinDisplayItemProperty) { + private func render(_ displayItem: DisplayItem, changedProperty property: LookinDisplayItemProperty) { if property == .none || property == .frameToRoot { let frameToRoot = displayItem.calculateFrameToRoot() let width = frameToRoot.size.width @@ -408,7 +408,7 @@ final class LKDisplayItemNode: SCNNode, LookinDisplayItemDelegate { } } -extension LookinDisplayItem { +extension DisplayItem { /// `-appropriateScreenshot`, which returns nil for an item without a /// screenshot although its header (inside NS_ASSUME_NONNULL) says it /// never does; read through the runtime so Swift sees the nil. diff --git a/LookInside/Static/Preview/LKPreviewController.swift b/LookInside/Static/Preview/LKPreviewController.swift index 9112b78a..a4917176 100644 --- a/LookInside/Static/Preview/LKPreviewController.swift +++ b/LookInside/Static/Preview/LKPreviewController.swift @@ -28,7 +28,7 @@ final class LKPreviewController: LKBaseViewController, NSGestureRecognizerDelega private var rightClickRecognizer: NSClickGestureRecognizer! private let rightClickMenu = NSMenu() - private var rightClickingDisplayItem: LookinDisplayItem? + private var rightClickingDisplayItem: DisplayItem? private var eventMonitors: [Any] = [] private var notificationObservers: [NSObjectProtocol] = [] @@ -40,7 +40,7 @@ final class LKPreviewController: LKBaseViewController, NSGestureRecognizerDelega private var rotationBeforeFlattening: CGPoint = .zero /// The hierarchy shown before the current one, to tell whether the /// app's screen size changed. - private var previousHierarchyInfo: LookinHierarchyInfo? + private var previousHierarchyInfo: HierarchyInfo? /// While space is held, panning moves the preview. private var isKeyingDownSpace = false { diff --git a/LookInside/Static/Preview/LKPreviewView.swift b/LookInside/Static/Preview/LKPreviewView.swift index e769782c..0916fcb6 100644 --- a/LookInside/Static/Preview/LKPreviewView.swift +++ b/LookInside/Static/Preview/LKPreviewView.swift @@ -25,7 +25,7 @@ final class LKPreviewView: SCNView { private let rightLightNode = SCNNode() private let leftLightNode = SCNNode() - private var flatDisplayItems: [LookinDisplayItem] = [] + private var flatDisplayItems: [DisplayItem] = [] private var displayItemNodes: [LKDisplayItemNode] = [] /// The frameToRoot point at the 3D origin: the centre of the largest @@ -160,8 +160,8 @@ final class LKPreviewView: SCNView { /// top-level windows, and iOS / Catalyst's scene → window), the one with /// the largest frameToRoot and returns its centre. Falls back to the /// centre of the app's screen. - private func referenceCenter(for items: [LookinDisplayItem]) -> CGPoint { - var largestItem: LookinDisplayItem? + private func referenceCenter(for items: [DisplayItem]) -> CGPoint { + var largestItem: DisplayItem? var largestArea: CGFloat = 0 for item in items where item.super == nil { for candidate in [item] + (item.subitems ?? []) { @@ -184,7 +184,7 @@ final class LKPreviewView: SCNView { /// `noPreview` is set. With `discardCache`, nodes this render does not /// use are dropped; otherwise they are only removed from the scene and /// kept for later renders. - func render(displayItems items: [LookinDisplayItem], discardCache: Bool) { + func render(displayItems items: [DisplayItem], discardCache: Bool) { NSLog("LKPreviewView - render %@ items", NSNumber(value: items.count)) flatDisplayItems = items @@ -251,7 +251,7 @@ final class LKPreviewView: SCNView { SCNTransaction.commit() } - private func updateZIndex(for item: LookinDisplayItem) { + private func updateZIndex(for item: DisplayItem) { item.previewZIndex = -1 // A pixelless overlay node (layout guide, cell) marks out a region of // the node that owns it, so it belongs on that node's plane rather @@ -291,14 +291,14 @@ final class LKPreviewView: SCNView { /// The item, among those visible in the preview and earlier in /// flatDisplayItems (lower in the hierarchy) whose frameToRoot overlaps /// `item`'s, with the highest z index; nil when there is none. - private func highestOverlappedItem(below item: LookinDisplayItem) -> LookinDisplayItem? { + private func highestOverlappedItem(below item: DisplayItem) -> DisplayItem? { guard let itemIndex = flatDisplayItems.firstIndex(where: { $0 == item }) else { assertionFailure() return nil } guard itemIndex > 0 else { return nil } let itemFrameToRoot = item.calculateFrameToRoot() - var target: LookinDisplayItem? + var target: DisplayItem? for other in flatDisplayItems[.. LookinDisplayItem? { + func displayItem(at point: CGPoint) -> DisplayItem? { let results = hitTest(point, options: [ .categoryBitMask: Int(LookinPreviewBitMask.selectable.rawValue), .searchMode: SCNHitTestSearchMode.closest.rawValue, diff --git a/LookInside/Toolbar/LKWindowToolbarAppButton.swift b/LookInside/Toolbar/LKWindowToolbarAppButton.swift index c9609a6c..13d1623e 100644 --- a/LookInside/Toolbar/LKWindowToolbarAppButton.swift +++ b/LookInside/Toolbar/LKWindowToolbarAppButton.swift @@ -56,7 +56,7 @@ final class LKWindowToolbarAppButton: NSButton { LKTwoColors(colorInLightMode: NSColor(red: 65 / 255.0, green: 65 / 255.0, blue: 65 / 255.0, alpha: 1), colorInDarkMode: .labelColor) } - @objc var appInfo: LookinAppInfo? { + @objc var appInfo: InspectedAppInfo? { didSet { appInfoDidChange() } } @@ -89,7 +89,7 @@ final class LKWindowToolbarAppButton: NSButton { needsLayout = true } - private static func familyIcon(for appInfo: LookinAppInfo) -> NSImage? { + private static func familyIcon(for appInfo: InspectedAppInfo) -> NSImage? { if LKHelper.appInfoLooksLikeMacTarget(appInfo) { return NSImage(named: "icon_mac_small") } diff --git a/LookInside/Toolbar/LKWindowToolbarHelper.swift b/LookInside/Toolbar/LKWindowToolbarHelper.swift index f054ad50..4d2bb2f6 100644 --- a/LookInside/Toolbar/LKWindowToolbarHelper.swift +++ b/LookInside/Toolbar/LKWindowToolbarHelper.swift @@ -140,7 +140,7 @@ final class LKWindowToolbarHelper: NSObject { /// The reader's app item, showing `appInfo`. @objc(makeAppInReadModeItemWithAppInfo:) - func makeAppInReadModeItem(with appInfo: LookinAppInfo?) -> NSToolbarItem { + func makeAppInReadModeItem(with appInfo: InspectedAppInfo?) -> NSToolbarItem { let button = LKWindowToolbarAppButton() button.bezelStyle = .texturedRounded button.appInfo = appInfo diff --git a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyAttributeCatalog.swift b/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyAttributeCatalog.swift index e64bc8ae..73d4a77a 100644 --- a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyAttributeCatalog.swift +++ b/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyAttributeCatalog.swift @@ -3,7 +3,7 @@ // Which dashboard rows an imported capture can fill, and where in the capture // each one's value lives. // -// The dashboard's cards are described by `LookinDashboardBlueprint`: groups, +// The dashboard's cards are described by `DashboardBlueprint`: groups, // their sections, the attributes in each, and per attribute the type, the // enum list and whether a nil value hides the row. A live session walks that // blueprint on the server and reads each attribute through its getter. An diff --git a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyAttributes.swift b/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyAttributes.swift index d3a509b2..38eecaf1 100644 --- a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyAttributes.swift +++ b/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyAttributes.swift @@ -149,11 +149,11 @@ enum LKXcodeViewHierarchyAttributes { layerNode: LKXcodeViewHierarchyNode?, graph: LKXcodeViewHierarchyObjectGraph, context: LKXcodeViewHierarchyAttributeContext - ) -> [LookinAttributesGroup] { + ) -> [AttributesGroup] { let classChain = graph.classChain(forClassName: node.className ?? "NSObject") - var groups: [LookinAttributesGroup] = [] + var groups: [AttributesGroup] = [] for catalogGroup in Catalog.groups { - var sections: [LookinAttributesSection] = [] + var sections: [AttributesSection] = [] for catalogSection in catalogGroup.sections { let attributes = catalogSection.attributes.compactMap { identifier in makingAttribute( @@ -187,7 +187,7 @@ enum LKXcodeViewHierarchyAttributes { classChain: [String], graph: LKXcodeViewHierarchyObjectGraph, context: LKXcodeViewHierarchyAttributeContext - ) -> LookinAttribute? { + ) -> InspectedAttribute? { switch identifier { case LookinAttr_Class_Class_Class: let chains = relatedClassChains(classChain, graph: graph, context: context) @@ -237,12 +237,12 @@ enum LKXcodeViewHierarchyAttributes { classChain: [String], graph: LKXcodeViewHierarchyObjectGraph, context: LKXcodeViewHierarchyAttributeContext - ) -> LookinAttribute? { + ) -> InspectedAttribute? { guard let specification = Catalog.specifications[identifier] else { return nil } if context.role == .layer { // A hostless layer answers only the rows the blueprint aims at a // CALayer; the view rows have no object to read from. - guard LookinDashboardBlueprint.targetKind(forAttrID: identifier) == .layer else { return nil } + guard DashboardBlueprint.targetKind(forAttrID: identifier) == .layer else { return nil } } else { guard specification.classNames.isEmpty || specification.classNames.contains(where: classChain.contains) else { return nil } @@ -252,13 +252,13 @@ enum LKXcodeViewHierarchyAttributes { if case .absent = property.value { // A captured nil: shown as nil where the blueprint wants it shown. - guard !LookinDashboardBlueprint.hideIfNil(withAttrID: identifier), + guard !DashboardBlueprint.hideIfNil(withAttrID: identifier), let attrType = nilCapableAttrType(for: specification.kind) else { return nil } return makingAttribute(identifier, attrType, nil) } - let isEnumeration = LookinDashboardBlueprint.enumListName(withAttrID: identifier) != nil + let isEnumeration = DashboardBlueprint.enumListName(withAttrID: identifier) != nil guard let converted = makingValue(property.value, kind: specification.kind, isEnumeration: isEnumeration) else { return nil } return makingAttribute(identifier, converted.attrType, converted.value) @@ -545,7 +545,7 @@ enum LKXcodeViewHierarchyAttributes { for node: LKXcodeViewHierarchyNode, graph: LKXcodeViewHierarchyObjectGraph, context: LKXcodeViewHierarchyAttributeContext - ) -> [LookinAutoLayoutConstraint] { + ) -> [AutoLayoutConstraint] { let effectiveIdentifiers = affectingConstraintIdentifiers(of: node) let constraintIdentifiers = context.environment.constraintIndex.constraintIdentifiers(involving: node.objectIdentifier) return constraintIdentifiers.compactMap { constraintIdentifier in @@ -565,7 +565,7 @@ enum LKXcodeViewHierarchyAttributes { let first = endpoint(of: constraintNode, propertyName: ConstraintProperty.firstItem, for: node, graph: graph, context: context) let second = endpoint(of: constraintNode, propertyName: ConstraintProperty.secondItem, for: node, graph: graph, context: context) - let constraint = LookinAutoLayoutConstraint() + let constraint = AutoLayoutConstraint() constraint.effective = effectiveIdentifiers.contains(constraintIdentifier) constraint.active = true constraint.firstItem = first.object @@ -585,7 +585,7 @@ enum LKXcodeViewHierarchyAttributes { } } - /// `LookinAutoLayoutConstraint` asserts on attributes in 21...31 or above + /// `AutoLayoutConstraint` asserts on attributes in 21...31 or above /// 37 — private ones it has no name for. Captures so far use 32, 33, 36 /// and 37 among the private values, all of which it accepts. private static func isRepresentableAttribute(_ attribute: Int) -> Bool { @@ -619,11 +619,11 @@ enum LKXcodeViewHierarchyAttributes { for node: LKXcodeViewHierarchyNode, graph: LKXcodeViewHierarchyObjectGraph, context: LKXcodeViewHierarchyAttributeContext - ) -> (object: LookinObject?, type: LookinConstraintItemType) { + ) -> (object: InspectedObject?, type: LookinConstraintItemType) { guard case let .objectReference(reference)? = constraintNode.property(named: propertyName)?.value else { return (nil, .`nil`) } - let object = LookinObject() + let object = InspectedObject() object.oid = LKXcodeViewHierarchyConverter.objectIdentifierValue(reference.objectIdentifier) object.memoryAddress = reference.objectIdentifier object.classChainList = graph.classChain(forClassName: reference.className) @@ -647,9 +647,9 @@ enum LKXcodeViewHierarchyAttributes { private static func makingGroup( _ identifier: String, - _ sections: [LookinAttributesSection] - ) -> LookinAttributesGroup { - let group = LookinAttributesGroup() + _ sections: [AttributesSection] + ) -> AttributesGroup { + let group = AttributesGroup() group.identifier = identifier group.attrSections = sections return group @@ -657,9 +657,9 @@ enum LKXcodeViewHierarchyAttributes { private static func makingSection( _ identifier: String, - _ attributes: [LookinAttribute] - ) -> LookinAttributesSection { - let section = LookinAttributesSection() + _ attributes: [InspectedAttribute] + ) -> AttributesSection { + let section = AttributesSection() section.identifier = identifier section.attributes = attributes return section @@ -669,8 +669,8 @@ enum LKXcodeViewHierarchyAttributes { _ identifier: String, _ attrType: LookinAttrType, _ value: Any? - ) -> LookinAttribute { - let attribute = LookinAttribute() + ) -> InspectedAttribute { + let attribute = InspectedAttribute() attribute.identifier = identifier attribute.attrType = attrType attribute.value = value diff --git a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyConverter.swift b/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyConverter.swift index 490e830a..1e922f9e 100644 --- a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyConverter.swift +++ b/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyConverter.swift @@ -1,7 +1,7 @@ // LKXcodeViewHierarchyConverter.swift // // Turns a decoded `.viewhierarchy` capture into the model the inspector -// already knows how to display: a `LookinHierarchyFile`, which the existing +// already knows how to display: a `HierarchyFile`, which the existing // read path opens exactly as it opens a `.lookin` archive. // // The whole point of producing that type rather than a new one is that no RPC @@ -138,7 +138,7 @@ enum LKXcodeViewHierarchyConverter { from bundle: LKXcodeViewHierarchyBundle, screenshots: LKXcodeViewHierarchyScreenshots, showingBackingLayers: Bool = false - ) throws -> LookinHierarchyFile { + ) throws -> HierarchyFile { let graph = bundle.graph let vocabulary = graph.rootGroups.contains { $0.groupingIdentifier.hasPrefix("com.apple.AppKit.") } ? Vocabulary.appKit @@ -150,12 +150,12 @@ enum LKXcodeViewHierarchyConverter { let displayItems = makingRootDisplayItems(session: session) guard !displayItems.isEmpty else { throw LKXcodeViewHierarchyConversionError.noWindowsOrRootViews } - let hierarchyInfo = LookinHierarchyInfo() + let hierarchyInfo = HierarchyInfo() hierarchyInfo.displayItems = displayItems hierarchyInfo.serverVersion = Int32(LOOKIN_SERVER_VERSION) hierarchyInfo.appInfo = makingAppInfo(from: bundle, vocabulary: vocabulary) - let file = LookinHierarchyFile() + let file = HierarchyFile() file.serverVersion = Int32(LOOKIN_SERVER_VERSION) file.hierarchyInfo = hierarchyInfo file.soloScreenshots = session.soloScreenshotsByOid @@ -218,7 +218,7 @@ enum LKXcodeViewHierarchyConverter { groupOf groupIdentifier: String?, excludingHostedViews: Bool, under keyIdentifier: String, - onto item: LookinDisplayItem + onto item: DisplayItem ) { let oid = LKXcodeViewHierarchyConverter.objectIdentifierValue(keyIdentifier) guard oid != 0 else { return } @@ -270,7 +270,7 @@ enum LKXcodeViewHierarchyConverter { /// controller's view that is currently detached from any window, say. /// Xcode only shows those in its other outline mode ("View Controller /// Containment"), which the inspector has no counterpart for. - private static func makingRootDisplayItems(session: ConversionSession) -> [LookinDisplayItem] { + private static func makingRootDisplayItems(session: ConversionSession) -> [DisplayItem] { let graph = session.graph let vocabulary = session.vocabulary let environment = session.environment @@ -306,7 +306,7 @@ enum LKXcodeViewHierarchyConverter { } } - var rootItems: [LookinDisplayItem] = [] + var rootItems: [DisplayItem] = [] for ownerIdentifier in ownerIdentifiers { let ownedWindowIdentifiers = windowIdentifiersByOwner[ownerIdentifier] ?? [] let windowItems = ownedWindowIdentifiers.compactMap { windowIdentifier in @@ -483,10 +483,10 @@ enum LKXcodeViewHierarchyConverter { private static func makingSceneItem( sceneNode: LKXcodeViewHierarchyNode, windowNodes: [LKXcodeViewHierarchyNode], - windowItems: [LookinDisplayItem], + windowItems: [DisplayItem], graph: LKXcodeViewHierarchyObjectGraph, environment: LKXcodeViewHierarchyAttributeEnvironment - ) -> LookinDisplayItem { + ) -> DisplayItem { let item = makingDisplayItem(kind: .windowScene) item.windowObject = makingLookinObject(for: sceneNode, graph: graph) item.alpha = 1 @@ -529,7 +529,7 @@ enum LKXcodeViewHierarchyConverter { environment: LKXcodeViewHierarchyAttributeEnvironment, session: ConversionSession, convertedViewIdentifiers: inout Set - ) -> LookinDisplayItem? { + ) -> DisplayItem? { guard let windowNode = graph.node(windowIdentifier) else { return nil } let item = makingDisplayItem(kind: .window) @@ -579,7 +579,7 @@ enum LKXcodeViewHierarchyConverter { } rootViewIdentifiers.append(contentsOf: windowNode.associatedIdentifiers(inGroup: vocabulary.viewGroup)) - var rootViewItems: [LookinDisplayItem] = [] + var rootViewItems: [DisplayItem] = [] for rootViewIdentifier in rootViewIdentifiers { guard let viewItem = makingViewItem( viewIdentifier: rootViewIdentifier, @@ -626,7 +626,7 @@ enum LKXcodeViewHierarchyConverter { environment: LKXcodeViewHierarchyAttributeEnvironment, session: ConversionSession, convertedViewIdentifiers: inout Set - ) -> LookinDisplayItem? { + ) -> DisplayItem? { // The capture is a graph, not a tree: a view reachable twice would // otherwise be converted twice and appear twice. guard convertedViewIdentifiers.insert(viewIdentifier).inserted, @@ -664,7 +664,7 @@ enum LKXcodeViewHierarchyConverter { for: viewNode, layerNode: associatedLayerNode(of: viewNode, graph: graph), graph: graph, context: context ) - var subviewItems: [LookinDisplayItem] = [] + var subviewItems: [DisplayItem] = [] for childIdentifier in viewNode.childIdentifiers { guard let childItem = makingViewItem( viewIdentifier: childIdentifier, @@ -757,21 +757,21 @@ enum LKXcodeViewHierarchyConverter { /// view renders as a wireframe, while the group keeps the folded look. private static func assemblingLayerAwareChildren( ownerIdentifier: String, - ownerItem: LookinDisplayItem, + ownerItem: DisplayItem, ownedLayers: OwnedLayers, - subviewItems: [LookinDisplayItem], + subviewItems: [DisplayItem], session: ConversionSession - ) -> [LookinDisplayItem] { + ) -> [DisplayItem] { let backingIdentifier = ownedLayers.backingNode.objectIdentifier if session.showsBackingLayers { session.filing( soloOf: nil, groupOf: backingIdentifier, excludingHostedViews: false, under: ownerIdentifier, onto: ownerItem ) - var children: [LookinDisplayItem] = [] + var children: [DisplayItem] = [] if let outerNode = ownedLayers.outerNode { // Xcode's nesting for a wrapped view: view → wrapper → backing layer. let outerItem = makingOuterLayerItem(outerNode, session: session) - var outerChildren: [LookinDisplayItem] = [] + var outerChildren: [DisplayItem] = [] for sublayerIdentifier in outerNode.childIdentifiers { if sublayerIdentifier == backingIdentifier { outerChildren.append(makingBackingLayerItem(ownedLayers.backingNode, session: session)) @@ -818,12 +818,12 @@ enum LKXcodeViewHierarchyConverter { /// layer is not below the backing layer at all keep their own order at /// the end. private static func interleaving( - _ subviewItems: [LookinDisplayItem], + _ subviewItems: [DisplayItem], amongSublayersOf backingNode: LKXcodeViewHierarchyNode, session: ConversionSession - ) -> [LookinDisplayItem] { - var anchoredItems: [String: [LookinDisplayItem]] = [:] - var unanchoredItems: [LookinDisplayItem] = [] + ) -> [DisplayItem] { + var anchoredItems: [String: [DisplayItem]] = [:] + var unanchoredItems: [DisplayItem] = [] for subviewItem in subviewItems { guard let subviewIdentifier = subviewItem.viewObject?.memoryAddress, let subviewNode = session.graph.node(subviewIdentifier), @@ -838,7 +838,7 @@ enum LKXcodeViewHierarchyConverter { anchoredItems[anchorIdentifier, default: []].append(subviewItem) } - var orderedItems: [LookinDisplayItem] = [] + var orderedItems: [DisplayItem] = [] for sublayerIdentifier in backingNode.childIdentifiers { if let anchored = anchoredItems[sublayerIdentifier] { // A container layer wrapping subviews sits at this z position @@ -863,7 +863,7 @@ enum LKXcodeViewHierarchyConverter { private static func makingLayerItem( _ layerIdentifier: String, session: ConversionSession - ) -> LookinDisplayItem? { + ) -> DisplayItem? { guard !session.topology.isHosted(layerIdentifier), let layerNode = session.graph.node(layerIdentifier) else { return nil } @@ -892,7 +892,7 @@ enum LKXcodeViewHierarchyConverter { private static func makingBackingLayerItem( _ backingNode: LKXcodeViewHierarchyNode, session: ConversionSession - ) -> LookinDisplayItem { + ) -> DisplayItem { session.convertedLayerIdentifiers.insert(backingNode.objectIdentifier) let item = makingDisplayItem(kind: .backingLayer) item.layerObject = makingLookinObject(for: backingNode, graph: session.graph) @@ -921,7 +921,7 @@ enum LKXcodeViewHierarchyConverter { private static func makingOuterLayerItem( _ outerNode: LKXcodeViewHierarchyNode, session: ConversionSession - ) -> LookinDisplayItem { + ) -> DisplayItem { session.convertedLayerIdentifiers.insert(outerNode.objectIdentifier) let item = makingDisplayItem(kind: .viewOuterLayer) item.layerObject = makingLookinObject(for: outerNode, graph: session.graph) @@ -935,7 +935,7 @@ enum LKXcodeViewHierarchyConverter { private static func makingLayerAttributeGroups( for layerNode: LKXcodeViewHierarchyNode, session: ConversionSession - ) -> [LookinAttributesGroup] { + ) -> [AttributesGroup] { let context = LKXcodeViewHierarchyAttributeContext(role: .layer, environment: session.environment) return LKXcodeViewHierarchyAttributes.makingGroups( for: layerNode, layerNode: layerNode, graph: session.graph, context: context @@ -965,12 +965,12 @@ enum LKXcodeViewHierarchyConverter { /// A layer node covering its parent node edge to edge: origin zero, the /// layer's own size (the server's shape for backing and wrapper nodes). - private static func applyingCoveringGeometry(from layerNode: LKXcodeViewHierarchyNode, to item: LookinDisplayItem) { + private static func applyingCoveringGeometry(from layerNode: LKXcodeViewHierarchyNode, to item: DisplayItem) { applyingGeometry(from: layerNode, to: item) item.frame = CGRect(origin: .zero, size: item.bounds.size) } - private static func applyingLayerVisibility(from layerNode: LKXcodeViewHierarchyNode, to item: LookinDisplayItem) { + private static func applyingLayerVisibility(from layerNode: LKXcodeViewHierarchyNode, to item: DisplayItem) { applyingVisibility(from: layerNode, to: item) // The server reads a layer node's flip off the layer itself. item.isFlipped = layerNode.property(named: "geometryFlipped")?.value.boolValue ?? false @@ -983,7 +983,7 @@ enum LKXcodeViewHierarchyConverter { graph: LKXcodeViewHierarchyObjectGraph, vocabulary: Vocabulary, environment: LKXcodeViewHierarchyAttributeEnvironment - ) -> [LookinDisplayItem] { + ) -> [DisplayItem] { var context = LKXcodeViewHierarchyAttributeContext(role: .layoutGuide, environment: environment) context.ownerNode = owner return owner.associatedIdentifiers(inGroup: vocabulary.layoutGuideGroup).compactMap { guideIdentifier in @@ -1012,7 +1012,7 @@ enum LKXcodeViewHierarchyConverter { cellGroup: String, graph: LKXcodeViewHierarchyObjectGraph, environment: LKXcodeViewHierarchyAttributeEnvironment - ) -> [LookinDisplayItem] { + ) -> [DisplayItem] { var context = LKXcodeViewHierarchyAttributeContext(role: .cell, environment: environment) context.ownerNode = owner return owner.associatedIdentifiers(inGroup: cellGroup).compactMap { cellIdentifier in @@ -1051,8 +1051,8 @@ enum LKXcodeViewHierarchyConverter { /// `noPreview` — the preview then receives nothing (node-model-internals, /// trap 1). The server sets the flag per kind and the archive decoder /// defaults an absent key to YES; an in-memory producer gets neither. - private static func makingDisplayItem(kind: LookinDisplayItemNodeKind) -> LookinDisplayItem { - let item = LookinDisplayItem() + private static func makingDisplayItem(kind: LookinDisplayItemNodeKind) -> DisplayItem { + let item = DisplayItem() item.nodeKind = kind item.shouldCaptureImage = true return item @@ -1081,8 +1081,8 @@ enum LKXcodeViewHierarchyConverter { private static func makingLookinObject( for node: LKXcodeViewHierarchyNode, graph: LKXcodeViewHierarchyObjectGraph - ) -> LookinObject { - let object = LookinObject() + ) -> InspectedObject { + let object = InspectedObject() object.oid = objectIdentifierValue(node.objectIdentifier) object.memoryAddress = node.objectIdentifier let className = node.className ?? "NSObject" @@ -1093,7 +1093,7 @@ enum LKXcodeViewHierarchyConverter { private static func applyingGeometry( from node: LKXcodeViewHierarchyNode, fallback fallbackNode: LKXcodeViewHierarchyNode? = nil, - to item: LookinDisplayItem + to item: DisplayItem ) { if let frameComponents = node.property(named: "frame")?.value.numericComponents(expectedCount: 4) { item.frame = rect(from: frameComponents) @@ -1113,7 +1113,7 @@ enum LKXcodeViewHierarchyConverter { } } - private static func applyingVisibility(from node: LKXcodeViewHierarchyNode, to item: LookinDisplayItem) { + private static func applyingVisibility(from node: LKXcodeViewHierarchyNode, to item: DisplayItem) { item.isHidden = node.property(named: "hidden")?.value.boolValue ?? false if let alpha = node.property(named: "alpha")?.value.doubleValue { item.alpha = Float(alpha) @@ -1126,7 +1126,7 @@ enum LKXcodeViewHierarchyConverter { /// The inspector paints this before a screenshot is available, so a node /// with no recovered pixels still reads as something rather than a hole. - private static func applyingBackgroundColor(from layerNode: LKXcodeViewHierarchyNode, to item: LookinDisplayItem) { + private static func applyingBackgroundColor(from layerNode: LKXcodeViewHierarchyNode, to item: DisplayItem) { guard case let .color(color)? = layerNode.property(named: "backgroundColor")?.value, color.components.count >= 3 else { return } @@ -1159,8 +1159,8 @@ enum LKXcodeViewHierarchyConverter { private static func makingAppInfo( from bundle: LKXcodeViewHierarchyBundle, vocabulary: Vocabulary - ) -> LookinAppInfo { - let appInfo = LookinAppInfo() + ) -> InspectedAppInfo { + let appInfo = InspectedAppInfo() appInfo.appName = bundle.metadata.runnableDisplayName ?? NSLocalizedString("Xcode Capture", comment: "") appInfo.serverVersion = Int32(LOOKIN_SERVER_VERSION) // The inspector keys view-versus-layer identifier preference off this, diff --git a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyDocument.swift b/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyDocument.swift index 1867e7da..4b77fd2d 100644 --- a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyDocument.swift +++ b/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyDocument.swift @@ -6,7 +6,7 @@ // It subclasses `LookinArchiveDocument` rather than `NSDocument` directly so // that the entire reader — window controller, hierarchy tree, preview, // dashboard — is reused untouched. Once the import lands, the document holds -// an ordinary `LookinHierarchyFile`, indistinguishable from one that came out +// an ordinary `HierarchyFile`, indistinguishable from one that came out // of a `.lookin` archive, and everything downstream stays unaware that Xcode // produced it. // @@ -60,7 +60,7 @@ enum LKXcodeViewHierarchyImporter { static func makingHierarchyFile( from capture: LKXcodeViewHierarchyImportedCapture, showingBackingLayers: Bool - ) throws -> LookinHierarchyFile { + ) throws -> HierarchyFile { try LKXcodeViewHierarchyConverter.makingHierarchyFile( from: capture.bundle, screenshots: capture.screenshots, showingBackingLayers: showingBackingLayers ) @@ -71,7 +71,7 @@ enum LKXcodeViewHierarchyImporter { at url: URL, showingBackingLayers: Bool = false, isCancelled: () -> Bool = { false } - ) throws -> LookinHierarchyFile { + ) throws -> HierarchyFile { let capture = try importingCapture(at: url, isCancelled: isCancelled) if isCancelled() { throw CancellationError() @@ -126,7 +126,7 @@ final class LKXcodeViewHierarchyDocument: LookinArchiveDocument { guard let importedCapture else { return } rebuildTask?.cancel() rebuildTask = Task.detached(priority: .userInitiated) { [weak self] in - let outcome: Result + let outcome: Result do { outcome = try .success(LKXcodeViewHierarchyImporter.makingHierarchyFile( from: importedCapture, showingBackingLayers: showingBackingLayers @@ -168,7 +168,7 @@ final class LKXcodeViewHierarchyDocument: LookinArchiveDocument { } @MainActor - private func finishingRebuild(with outcome: Result) { + private func finishingRebuild(with outcome: Result) { rebuildTask = nil switch outcome { case let .success(file): diff --git a/Sources/LookinCoreImpl/LookinAttributeModification.swift b/Sources/LookinCoreImpl/AttributeModification.swift similarity index 87% rename from Sources/LookinCoreImpl/LookinAttributeModification.swift rename to Sources/LookinCoreImpl/AttributeModification.swift index 51a23c05..03feb2f4 100644 --- a/Sources/LookinCoreImpl/LookinAttributeModification.swift +++ b/Sources/LookinCoreImpl/AttributeModification.swift @@ -1,5 +1,5 @@ // -// LookinAttributeModification.swift +// AttributeModification.swift // Lookin // // Was LookinAttributeModification.m. The coding keys and value encodings are @@ -14,20 +14,20 @@ #endif @objc(LookinAttributeModification) - public class LookinAttributeModification: NSObject, NSCoding, NSSecureCoding { + public class AttributeModification: NSObject, NSCoding, NSSecureCoding { @objc(targetOid) public var targetOid: UInt = 0 @objc(setterSelector) - public var setterSelector: Selector! + public var setterSelector: Selector? /// Not archived. @objc(getterSelector) - public var getterSelector: Selector! + public var getterSelector: Selector? @objc(attrType) public var attrType: LookinAttrType = .none @objc(value) - public var value: Any! + public var value: Any? @objc(clientReadableVersion) - public var clientReadableVersion: String! + public var clientReadableVersion: String? override public init() { super.init() diff --git a/Sources/LookinCoreImpl/LookinAttributesGroup.swift b/Sources/LookinCoreImpl/AttributesGroup.swift similarity index 73% rename from Sources/LookinCoreImpl/LookinAttributesGroup.swift rename to Sources/LookinCoreImpl/AttributesGroup.swift index 9d41f53a..10ade0d5 100644 --- a/Sources/LookinCoreImpl/LookinAttributesGroup.swift +++ b/Sources/LookinCoreImpl/AttributesGroup.swift @@ -1,5 +1,5 @@ // -// LookinAttributesGroup.swift +// AttributesGroup.swift // Lookin // // Was LookinAttributesGroup.m. The coding keys are pinned by @@ -14,13 +14,13 @@ #endif @objc(LookinAttributesGroup) - public class LookinAttributesGroup: NSObject, NSCoding, NSSecureCoding, NSCopying { + public class AttributesGroup: NSObject, NSCoding, NSSecureCoding, NSCopying { @objc(userCustomTitle) - public var userCustomTitle: String! + public var userCustomTitle: String? @objc(identifier) - public var identifier: String! + public var identifier: String? @objc(attrSections) - public var attrSections: [LookinAttributesSection]! + public var attrSections: [AttributesSection]? @objc(isSwiftUIGroup) public var isSwiftUIGroup: Bool = false @@ -32,10 +32,10 @@ @objc(copyWithZone:) public func copy(with _: NSZone? = nil) -> Any { - let newGroup = LookinAttributesGroup() + let newGroup = AttributesGroup() newGroup.userCustomTitle = userCustomTitle newGroup.identifier = identifier - newGroup.attrSections = attrSections?.map { $0.copy() as! LookinAttributesSection } + newGroup.attrSections = attrSections?.map { $0.copy() as! AttributesSection } newGroup.isSwiftUIGroup = isSwiftUIGroup return newGroup } @@ -54,7 +54,7 @@ super.init() userCustomTitle = aDecoder.decodeObject(forKey: "userCustomTitle") as? String identifier = aDecoder.decodeObject(forKey: "identifier") as? String - attrSections = aDecoder.decodeObject(forKey: "attrSections") as? [LookinAttributesSection] + attrSections = aDecoder.decodeObject(forKey: "attrSections") as? [AttributesSection] isSwiftUIGroup = aDecoder.decodeBool(forKey: "isSwiftUIGroup") } @@ -66,28 +66,28 @@ // MARK: Equality override open var hash: Int { - lookinStringHash(uniqueKey()) + stringHash(uniqueKey()) } override open func isEqual(_ object: Any?) -> Bool { if let object = object as? NSObject, object === self { return true } - guard let targetObject = object as? LookinAttributesGroup else { + guard let targetObject = object as? AttributesGroup else { return false } - if !lookinStringsEqual(identifier, targetObject.identifier) { + if !stringsEqual(identifier, targetObject.identifier) { return false } - if lookinStringsEqual(identifier, LookinAttrGroup_UserCustom) { - return lookinStringsEqual(userCustomTitle, targetObject.userCustomTitle) + if stringsEqual(identifier, LookinAttrGroup_UserCustom) { + return stringsEqual(userCustomTitle, targetObject.userCustomTitle) } return true } @objc(uniqueKey) - public func uniqueKey() -> String! { - if lookinStringsEqual(identifier, LookinAttrGroup_UserCustom) { + public func uniqueKey() -> String? { + if stringsEqual(identifier, LookinAttrGroup_UserCustom) { return userCustomTitle } return identifier @@ -95,14 +95,14 @@ @objc(isUserCustom) public func isUserCustom() -> Bool { - lookinStringsEqual(identifier, LookinAttrGroup_UserCustom) + stringsEqual(identifier, LookinAttrGroup_UserCustom) } @objc(groupsByKeepingFirstGroupForEachUniqueKey:) - public class func groupsByKeepingFirstGroup(forEachUniqueKey groups: [LookinAttributesGroup]?) -> [LookinAttributesGroup]! { + public class func groupsByKeepingFirstGroup(forEachUniqueKey groups: [AttributesGroup]?) -> [AttributesGroup] { // NSMutableSet compares through -isEqual: / -hash, like the original. let seenUniqueKeys = NSMutableSet() - var deduplicatedGroups: [LookinAttributesGroup] = [] + var deduplicatedGroups: [AttributesGroup] = [] for group in groups ?? [] { if let uniqueKey = group.uniqueKey() { if seenUniqueKeys.contains(uniqueKey) { diff --git a/Sources/LookinCoreImpl/LookinAttributesSection.swift b/Sources/LookinCoreImpl/AttributesSection.swift similarity index 77% rename from Sources/LookinCoreImpl/LookinAttributesSection.swift rename to Sources/LookinCoreImpl/AttributesSection.swift index dfc9c695..980a7314 100644 --- a/Sources/LookinCoreImpl/LookinAttributesSection.swift +++ b/Sources/LookinCoreImpl/AttributesSection.swift @@ -1,5 +1,5 @@ // -// LookinAttributesSection.swift +// AttributesSection.swift // Lookin // // Was LookinAttributesSection.m. The coding keys are pinned by @@ -14,11 +14,11 @@ #endif @objc(LookinAttributesSection) - public class LookinAttributesSection: NSObject, NSCoding, NSSecureCoding, NSCopying { + public class AttributesSection: NSObject, NSCoding, NSSecureCoding, NSCopying { @objc(identifier) - public var identifier: String! + public var identifier: String? @objc(attributes) - public var attributes: [LookinAttribute]! + public var attributes: [InspectedAttribute]? override public init() { super.init() @@ -28,9 +28,9 @@ @objc(copyWithZone:) public func copy(with _: NSZone? = nil) -> Any { - let newSection = LookinAttributesSection() + let newSection = AttributesSection() newSection.identifier = identifier - newSection.attributes = attributes?.map { $0.copy() as! LookinAttribute } + newSection.attributes = attributes?.map { $0.copy() as! InspectedAttribute } return newSection } @@ -45,7 +45,7 @@ public required init?(coder aDecoder: NSCoder) { super.init() identifier = aDecoder.decodeObject(forKey: "identifier") as? String - attributes = aDecoder.decodeObject(forKey: "attributes") as? [LookinAttribute] + attributes = aDecoder.decodeObject(forKey: "attributes") as? [InspectedAttribute] } @objc(supportsSecureCoding) @@ -55,7 +55,7 @@ @objc(isUserCustom) public func isUserCustom() -> Bool { - lookinStringsEqual(identifier, LookinAttrSec_UserCustom) + stringsEqual(identifier, LookinAttrSec_UserCustom) } } diff --git a/Sources/LookinCoreImpl/LookinAutoLayoutConstraint.swift b/Sources/LookinCoreImpl/AutoLayoutConstraint.swift similarity index 86% rename from Sources/LookinCoreImpl/LookinAutoLayoutConstraint.swift rename to Sources/LookinCoreImpl/AutoLayoutConstraint.swift index 0f14d1de..a3faa61a 100644 --- a/Sources/LookinCoreImpl/LookinAutoLayoutConstraint.swift +++ b/Sources/LookinCoreImpl/AutoLayoutConstraint.swift @@ -1,5 +1,5 @@ // -// LookinAutoLayoutConstraint.swift +// AutoLayoutConstraint.swift // Lookin // // Was LookinAutoLayoutConstraint.m. The coding keys and scalar encodings are @@ -20,13 +20,13 @@ /// View endpoints have always had a node to land on; layout guide /// endpoints gained one when guides entered the hierarchy tree. - private func LookinConstraintItemTypeIsJumpable(_ itemType: LookinConstraintItemType) -> Bool { + private func isJumpableConstraintItemType(_ itemType: LookinConstraintItemType) -> Bool { itemType == .view || itemType == .layoutGuide } /// The asserts help find attributes private to the system; the original /// notes they should go before a release. - private func lookinAssertUnknownAttribute(_ attribute: Int) { + private func assertUnknownAttribute(_ attribute: Int) { if attribute > 20, attribute < 32 { assertionFailure() } @@ -36,7 +36,7 @@ } @objc(LookinAutoLayoutConstraint) - public class LookinAutoLayoutConstraint: NSObject, NSCoding, NSSecureCoding { + public class AutoLayoutConstraint: NSObject, NSCoding, NSSecureCoding { @objc(effective) public var effective: Bool = false @objc(active) @@ -44,26 +44,26 @@ @objc(shouldBeArchived) public var shouldBeArchived: Bool = false @objc(firstItem) - public var firstItem: LookinObject! + public var firstItem: InspectedObject? @objc(firstItemType) public var firstItemType: LookinConstraintItemType = .unknown @objc(firstAttribute) public var firstAttribute: Int = 0 { didSet { - lookinAssertUnknownAttribute(firstAttribute) + assertUnknownAttribute(firstAttribute) } } @objc(relation) public var relation: NSLayoutConstraint.Relation = .equal @objc(secondItem) - public var secondItem: LookinObject! + public var secondItem: InspectedObject? @objc(secondItemType) public var secondItemType: LookinConstraintItemType = .unknown @objc(secondAttribute) public var secondAttribute: Int = 0 { didSet { - lookinAssertUnknownAttribute(secondAttribute) + assertUnknownAttribute(secondAttribute) } } @@ -74,23 +74,23 @@ @objc(priority) public var priority: CGFloat = 0 @objc(identifier) - public var identifier: String! + public var identifier: String? @objc(constraintOid) public var constraintOid: UInt = 0 /// `+instanceFromNSConstraint:isEffective:firstItemType:secondItemType:`. /// An Objective-C factory must be a class method here. @objc(instanceFromNSConstraint:isEffective:firstItemType:secondItemType:) - public class func instance(fromNSConstraint constraint: NSLayoutConstraint?, isEffective: Bool, firstItemType: LookinConstraintItemType, secondItemType: LookinConstraintItemType) -> Self! { + public class func instance(fromNSConstraint constraint: NSLayoutConstraint?, isEffective: Bool, firstItemType: LookinConstraintItemType, secondItemType: LookinConstraintItemType) -> Self { let instance = unsafeDowncast((self as NSObject.Type).init(), to: self) instance.effective = isEffective instance.active = constraint?.isActive ?? false instance.shouldBeArchived = constraint?.shouldBeArchived ?? false - instance.firstItem = LookinObject.instance(with: constraint?.firstItem as? NSObject) + instance.firstItem = InspectedObject.instance(with: constraint?.firstItem as? NSObject) instance.firstItemType = firstItemType instance.firstAttribute = constraint?.firstAttribute.rawValue ?? 0 instance.relation = constraint?.relation ?? NSLayoutConstraint.Relation(rawValue: 0)! - instance.secondItem = LookinObject.instance(with: constraint?.secondItem as? NSObject) + instance.secondItem = InspectedObject.instance(with: constraint?.secondItem as? NSObject) instance.secondItemType = secondItemType instance.secondAttribute = constraint?.secondAttribute.rawValue ?? 0 instance.multiplier = constraint?.multiplier ?? 0 @@ -135,11 +135,11 @@ effective = aDecoder.decodeBool(forKey: "effective") active = aDecoder.decodeBool(forKey: "active") shouldBeArchived = aDecoder.decodeBool(forKey: "shouldBeArchived") - firstItem = aDecoder.decodeObject(forKey: "firstItem") as? LookinObject + firstItem = aDecoder.decodeObject(forKey: "firstItem") as? InspectedObject firstItemType = LookinConstraintItemType(rawValue: aDecoder.decodeInteger(forKey: "firstItemType")) ?? .unknown firstAttribute = aDecoder.decodeInteger(forKey: "firstAttribute") relation = NSLayoutConstraint.Relation(rawValue: aDecoder.decodeInteger(forKey: "relation")) ?? .equal - secondItem = aDecoder.decodeObject(forKey: "secondItem") as? LookinObject + secondItem = aDecoder.decodeObject(forKey: "secondItem") as? InspectedObject secondItemType = LookinConstraintItemType(rawValue: aDecoder.decodeInteger(forKey: "secondItemType")) ?? .unknown secondAttribute = aDecoder.decodeInteger(forKey: "secondAttribute") multiplier = CGFloat(aDecoder.decodeDouble(forKey: "multiplier")) @@ -152,12 +152,12 @@ } @objc(jumpableItemObjectForEndpoint:) - public func jumpableItemObject(for endpoint: LookinConstraintEndpoint) -> LookinObject! { + public func jumpableItemObject(for endpoint: LookinConstraintEndpoint) -> InspectedObject? { switch endpoint { case .first: - return LookinConstraintItemTypeIsJumpable(firstItemType) ? firstItem : nil + return isJumpableConstraintItemType(firstItemType) ? firstItem : nil case .second: - return LookinConstraintItemTypeIsJumpable(secondItemType) ? secondItem : nil + return isJumpableConstraintItemType(secondItemType) ? secondItem : nil @unknown default: return nil } diff --git a/Sources/LookinCoreImpl/Category/CALayer+Lookin.swift b/Sources/LookinCoreImpl/Category/CALayer+Lookin.swift index 3d52aec3..e9940c36 100644 --- a/Sources/LookinCoreImpl/Category/CALayer+Lookin.swift +++ b/Sources/LookinCoreImpl/Category/CALayer+Lookin.swift @@ -15,28 +15,33 @@ public extension CALayer { @objc(lookin_removeImplicitAnimations) - func lookin_removeImplicitAnimations() { + func removeImplicitAnimations() { // The keys are the property names the Objective-C original spelled // as NSStringFromSelector(@selector(...)). var actions: [String: any CAAction] = [:] - for key in lookinLayerActionKeys { + for key in layerActionKeys { actions[key] = NSNull() } if isKind(of: CAShapeLayer.self) { - for key in lookinShapeLayerActionKeys { + for key in shapeLayerActionKeys { actions[key] = NSNull() } } if isKind(of: CAGradientLayer.self) { - for key in lookinGradientLayerActionKeys { + for key in gradientLayerActionKeys { actions[key] = NSNull() } } self.actions = actions } + + @available(*, deprecated, renamed: "removeImplicitAnimations()") + func lookin_removeImplicitAnimations() { + removeImplicitAnimations() + } } - private let lookinLayerActionKeys = [ + private let layerActionKeys = [ "bounds", "position", "zPosition", @@ -67,7 +72,7 @@ "shadowPath", ] - private let lookinShapeLayerActionKeys = [ + private let shapeLayerActionKeys = [ "path", "fillColor", "strokeColor", @@ -78,7 +83,7 @@ "lineDashPhase", ] - private let lookinGradientLayerActionKeys = [ + private let gradientLayerActionKeys = [ "colors", "locations", "startPoint", diff --git a/Sources/LookinCoreImpl/Category/Color+Lookin.swift b/Sources/LookinCoreImpl/Category/Color+Lookin.swift index 641f8155..d1742f94 100644 --- a/Sources/LookinCoreImpl/Category/Color+Lookin.swift +++ b/Sources/LookinCoreImpl/Category/Color+Lookin.swift @@ -16,7 +16,7 @@ public extension NSColor { @objc(lookin_colorFromRGBAComponents:) - class func lookin_color(fromRGBAComponents components: [NSNumber]?) -> Self! { + class func sRGBColor(fromRGBAComponents components: [NSNumber]?) -> Self? { guard let components else { return nil } @@ -35,8 +35,13 @@ return unsafeDowncast(color, to: self) } + @available(*, deprecated, renamed: "sRGBColor(fromRGBAComponents:)") + class func lookin_color(fromRGBAComponents components: [NSNumber]?) -> Self? { + sRGBColor(fromRGBAComponents: components) + } + @objc(lookin_rgbaComponents) - func lookin_rgbaComponents() -> [NSNumber]! { + func sRGBAComponents() -> [NSNumber] { // Messaging a nil sRGB conversion left the components unset; read // them as 0 here. var r: CGFloat = 0 @@ -51,6 +56,11 @@ NSNumber(value: Double(a)), ] } + + @available(*, deprecated, renamed: "sRGBAComponents()") + func lookin_rgbaComponents() -> [NSNumber] { + sRGBAComponents() + } } #endif diff --git a/Sources/LookinCoreImpl/Category/Image+Lookin.swift b/Sources/LookinCoreImpl/Category/Image+Lookin.swift index ead68e22..619eb6d8 100644 --- a/Sources/LookinCoreImpl/Category/Image+Lookin.swift +++ b/Sources/LookinCoreImpl/Category/Image+Lookin.swift @@ -16,7 +16,7 @@ public extension NSImage { @objc(lookin_data) - func lookin_data() -> Data! { + func encodedData() -> Data? { if representations.isEmpty { return nil } @@ -32,6 +32,11 @@ let bitmapRep = NSBitmapImageRep(cgImage: cgImage) return bitmapRep.representation(using: .png, properties: [:]) } + + @available(*, deprecated, renamed: "encodedData()") + func lookin_data() -> Data? { + encodedData() + } } #endif diff --git a/Sources/LookinCoreImpl/Category/NSArray+Lookin.swift b/Sources/LookinCoreImpl/Category/NSArray+Lookin.swift index 38ade6a9..db0437d6 100644 --- a/Sources/LookinCoreImpl/Category/NSArray+Lookin.swift +++ b/Sources/LookinCoreImpl/Category/NSArray+Lookin.swift @@ -16,12 +16,12 @@ public extension NSArray { @objc(lookin_resizeWithCount:add:remove:doNext:) - func lookin_resize( + func resized( withCount count: UInt, add addBlock: ((UInt) -> Any?)?, remove removeBlock: ((UInt, Any?) -> Void)?, doNext doBlock: ((UInt, Any?) -> Void)? - ) -> [Any]! { + ) -> [Any] { let resultArray = NSMutableArray(capacity: Int(count)) for i in 0 ..< count { if UInt(self.count) > i { @@ -46,11 +46,21 @@ } } - return lookinBridgedArray(resultArray) + return bridgedArray(resultArray) + } + + @available(*, deprecated, renamed: "resized(withCount:add:remove:doNext:)") + func lookin_resize( + withCount count: UInt, + add addBlock: ((UInt) -> Any?)?, + remove removeBlock: ((UInt, Any?) -> Void)?, + doNext doBlock: ((UInt, Any?) -> Void)? + ) -> [Any] { + resized(withCount: count, add: addBlock, remove: removeBlock, doNext: doBlock) } @objc(lookin_arrayWithCount:block:) - class func lookin_array(withCount count: UInt, block: ((UInt) -> Any?)?) -> [Any]! { + class func array(withCount count: UInt, block: ((UInt) -> Any?)?) -> [Any] { let array = NSMutableArray(capacity: Int(count)) for i in 0 ..< count { // Calling a nil block crashed in Objective-C as well. @@ -58,19 +68,29 @@ array.add(obj) } } - return lookinBridgedArray(array) + return bridgedArray(array) + } + + @available(*, deprecated, renamed: "array(withCount:block:)") + class func lookin_array(withCount count: UInt, block: ((UInt) -> Any?)?) -> [Any] { + array(withCount: count, block: block) } @objc(lookin_hasIndex:) - func lookin_hasIndex(_ index: Int) -> Bool { + func hasIndex(_ index: Int) -> Bool { if index == NSNotFound || index < 0 { return false } return count > index } + @available(*, deprecated, renamed: "hasIndex(_:)") + func lookin_hasIndex(_ index: Int) -> Bool { + hasIndex(index) + } + @objc(lookin_map:) - func lookin_map(_ block: ((UInt, Any?) -> Any?)?) -> [Any]! { + func mappedObjects(_ block: ((UInt, Any?) -> Any?)?) -> [Any]? { guard let block else { assertionFailure("") return nil @@ -81,11 +101,16 @@ array.add(newObj) } } - return lookinBridgedArray(array) + return bridgedArray(array) + } + + @available(*, deprecated, renamed: "mappedObjects(_:)") + func lookin_map(_ block: ((UInt, Any?) -> Any?)?) -> [Any]? { + mappedObjects(block) } @objc(lookin_filter:) - func lookin_filter(_ block: ((Any?) -> Bool)?) -> [Any]! { + func filteredObjects(_ block: ((Any?) -> Bool)?) -> [Any]? { guard let block else { assertionFailure("") return nil @@ -96,11 +121,16 @@ mArray.add(obj) } } - return lookinBridgedArray(mArray) + return bridgedArray(mArray) + } + + @available(*, deprecated, renamed: "filteredObjects(_:)") + func lookin_filter(_ block: ((Any?) -> Bool)?) -> [Any]? { + filteredObjects(block) } @objc(lookin_firstFiltered:) - func lookin_firstFiltered(_ block: ((Any?) -> Bool)?) -> Any! { + func firstFiltered(_ block: ((Any?) -> Bool)?) -> Any? { guard let block else { assertionFailure("") return nil @@ -115,8 +145,13 @@ return targetObj } + @available(*, deprecated, renamed: "firstFiltered(_:)") + func lookin_firstFiltered(_ block: ((Any?) -> Bool)?) -> Any? { + firstFiltered(block) + } + @objc(lookin_lastFiltered:) - func lookin_lastFiltered(_ block: ((Any?) -> Bool)?) -> Any! { + func lastFiltered(_ block: ((Any?) -> Bool)?) -> Any? { guard let block else { assertionFailure("") return nil @@ -131,8 +166,13 @@ return targetObj } + @available(*, deprecated, renamed: "lastFiltered(_:)") + func lookin_lastFiltered(_ block: ((Any?) -> Bool)?) -> Any? { + lastFiltered(block) + } + @objc(lookin_reduce:) - func lookin_reduce(_ block: ((Any?, UInt, Any?) -> Any?)?) -> Any! { + func reduceObjects(_ block: ((Any?, UInt, Any?) -> Any?)?) -> Any? { guard let block else { assertionFailure("") return nil @@ -144,8 +184,13 @@ return accumulator } + @available(*, deprecated, renamed: "reduceObjects(_:)") + func lookin_reduce(_ block: ((Any?, UInt, Any?) -> Any?)?) -> Any? { + reduceObjects(block) + } + @objc(lookin_reduceCGFloat:initialAccumlator:) - func lookin_reduceCGFloat(_ block: ((CGFloat, UInt, Any?) -> CGFloat)?, initialAccumlator: CGFloat) -> CGFloat { + func reduceCGFloat(_ block: ((CGFloat, UInt, Any?) -> CGFloat)?, initialAccumlator: CGFloat) -> CGFloat { guard let block else { assertionFailure("") return initialAccumlator @@ -157,8 +202,13 @@ return accumulator } + @available(*, deprecated, renamed: "reduceCGFloat(_:initialAccumlator:)") + func lookin_reduceCGFloat(_ block: ((CGFloat, UInt, Any?) -> CGFloat)?, initialAccumlator: CGFloat) -> CGFloat { + reduceCGFloat(block, initialAccumlator: initialAccumlator) + } + @objc(lookin_reduceInteger:initialAccumlator:) - func lookin_reduceInteger(_ block: ((Int, UInt, Any?) -> Int)?, initialAccumlator: Int) -> Int { + func reduceInteger(_ block: ((Int, UInt, Any?) -> Int)?, initialAccumlator: Int) -> Int { guard let block else { assertionFailure("") return initialAccumlator @@ -170,8 +220,13 @@ return accumulator } + @available(*, deprecated, renamed: "reduceInteger(_:initialAccumlator:)") + func lookin_reduceInteger(_ block: ((Int, UInt, Any?) -> Int)?, initialAccumlator: Int) -> Int { + reduceInteger(block, initialAccumlator: initialAccumlator) + } + @objc(lookin_all:) - func lookin_all(_ block: ((Any?) -> Bool)?) -> Bool { + func allObjectsPass(_ block: ((Any?) -> Bool)?) -> Bool { guard let block else { assertionFailure("") return false @@ -186,8 +241,13 @@ return allPass } + @available(*, deprecated, renamed: "allObjectsPass(_:)") + func lookin_all(_ block: ((Any?) -> Bool)?) -> Bool { + allObjectsPass(block) + } + @objc(lookin_any:) - func lookin_any(_ block: ((Any?) -> Bool)?) -> Bool { + func anyObjectPasses(_ block: ((Any?) -> Bool)?) -> Bool { guard let block else { assertionFailure("") return false @@ -202,24 +262,39 @@ return anyPass } + @available(*, deprecated, renamed: "anyObjectPasses(_:)") + func lookin_any(_ block: ((Any?) -> Bool)?) -> Bool { + anyObjectPasses(block) + } + @objc(lookin_arrayByRemovingObject:) - func lookin_array(byRemoving obj: Any?) -> [Any]! { + func array(byRemoving obj: Any?) -> [Any] { guard let obj, contains(obj) else { - return lookinBridgedArray(self) + return bridgedArray(self) } let mutableArray = mutableCopy() as! NSMutableArray mutableArray.remove(obj) - return lookinBridgedArray(mutableArray) + return bridgedArray(mutableArray) + } + + @available(*, deprecated, renamed: "array(byRemoving:)") + func lookin_array(byRemoving obj: Any?) -> [Any] { + array(byRemoving: obj) } @objc(lookin_nonredundantArray) - func lookin_nonredundant() -> [Any]! { + func nonredundantArray() -> [Any] { let set = NSSet(array: self as! [Any]) return set.allObjects } + @available(*, deprecated, renamed: "nonredundantArray()") + func lookin_nonredundant() -> [Any] { + nonredundantArray() + } + @objc(lookin_safeObjectAtIndex:) - func lookin_safeObject(at idx: Int) -> Any! { + func safeObject(at idx: Int) -> Any? { if idx == NSNotFound || idx < 0 { return nil } @@ -229,8 +304,13 @@ return object(at: idx) } + @available(*, deprecated, renamed: "safeObject(at:)") + func lookin_safeObject(at idx: Int) -> Any? { + safeObject(at: idx) + } + @objc(lookin_sortedArrayByStringLength) - func lookin_sortedArrayByStringLength() -> [Any]! { + func sortedArrayByStringLength() -> [Any] { return sortedArray(comparator: { obj1, obj2 in let length1 = (obj1 as! NSString).length let length2 = (obj2 as! NSString).length @@ -243,18 +323,23 @@ } }) } + + @available(*, deprecated, renamed: "sortedArrayByStringLength()") + func lookin_sortedArrayByStringLength() -> [Any] { + sortedArrayByStringLength() + } } public extension NSMutableArray { @objc(lookin_dequeueWithCount:add:notDequeued:doNext:) - func lookin_dequeue( + func dequeue( withCount count: UInt, add addBlock: ((UInt) -> Any?)?, notDequeued notDequeuedBlock: ((UInt, Any?) -> Void)?, doNext doBlock: ((UInt, Any?) -> Void)? ) { for i in 0 ..< count { - if lookin_hasIndex(Int(i)) { + if hasIndex(Int(i)) { let obj = object(at: Int(i)) doBlock?(i, obj) } else if let addBlock { @@ -276,8 +361,18 @@ } } + @available(*, deprecated, renamed: "dequeue(withCount:add:notDequeued:doNext:)") + func lookin_dequeue( + withCount count: UInt, + add addBlock: ((UInt) -> Any?)?, + notDequeued notDequeuedBlock: ((UInt, Any?) -> Void)?, + doNext doBlock: ((UInt, Any?) -> Void)? + ) { + dequeue(withCount: count, add: addBlock, notDequeued: notDequeuedBlock, doNext: doBlock) + } + @objc(lookin_removeObjectsPassingTest:) - func lookin_removeObjects(passingTest block: ((UInt, Any?) -> Bool)?) { + func removeObjects(passingTest block: ((UInt, Any?) -> Bool)?) { guard let block else { return } @@ -289,12 +384,17 @@ } removeObjects(at: indexSet as IndexSet) } + + @available(*, deprecated, renamed: "removeObjects(passingTest:)") + func lookin_removeObjects(passingTest block: ((UInt, Any?) -> Bool)?) { + removeObjects(passingTest: block) + } } /// An immutable copy of `array`, handed to Objective-C without copying its /// elements: bridging an immutable NSArray to `[Any]` and back returns the /// same NSArray. - private func lookinBridgedArray(_ array: NSArray) -> [Any] { + private func bridgedArray(_ array: NSArray) -> [Any] { array.copy() as! [Any] } diff --git a/Sources/LookinCoreImpl/Category/NSObject+Lookin.swift b/Sources/LookinCoreImpl/Category/NSObject+Lookin.swift index 5c446e06..3b764681 100644 --- a/Sources/LookinCoreImpl/Category/NSObject+Lookin.swift +++ b/Sources/LookinCoreImpl/Category/NSObject+Lookin.swift @@ -4,8 +4,8 @@ // // Was NSObject+Lookin.m: the // associated-object bindings and the color / image coding that -// LookinConnectionAttachment uses on the wire (pinned by -// Tests/WireFormatGolden, LookinConnectionAttachment-color and -image). +// ConnectionAttachment uses on the wire (pinned by +// Tests/WireFormatGolden, ConnectionAttachment-color and -image). // // Plain `@objc` extension members with the original selectors: the runtime // registers them as a category when the image loads, as it did the @@ -30,7 +30,7 @@ // MARK: - Data Bind @objc(lookin_bindObject:forKey:) - func lookin_bindObject(_ object: Any?, forKey key: String?) { + func bindObject(_ object: Any?, forKey key: String?) { guard let key, !key.isEmpty else { assertionFailure("") return @@ -40,93 +40,143 @@ objc_sync_enter(self) defer { objc_sync_exit(self) } if let object { - lookinAllBindObjects(self).setObject(object, forKey: key as NSString) + allBindObjects(self).setObject(object, forKey: key as NSString) } else { - lookinAllBindObjects(self).removeObject(forKey: key as NSString) + allBindObjects(self).removeObject(forKey: key as NSString) } } + @available(*, deprecated, renamed: "bindObject(_:forKey:)") + func lookin_bindObject(_ object: Any?, forKey key: String?) { + bindObject(object, forKey: key) + } + @objc(lookin_bindObjectWeakly:forKey:) - func lookin_bindObjectWeakly(_ object: Any?, forKey key: String?) { + func bindObjectWeakly(_ object: Any?, forKey key: String?) { guard let key, !key.isEmpty else { assertionFailure("") return } if let object { - let container = LookinWeakContainer() + let container = WeakContainer() container.object = object as AnyObject - lookin_bindObject(container, forKey: key) + bindObject(container, forKey: key) } else { - lookin_bindObject(nil, forKey: key) + bindObject(nil, forKey: key) } } + @available(*, deprecated, renamed: "bindObjectWeakly(_:forKey:)") + func lookin_bindObjectWeakly(_ object: Any?, forKey key: String?) { + bindObjectWeakly(object, forKey: key) + } + @objc(lookin_getBindObjectForKey:) - func lookin_getBindObject(forKey key: String?) -> Any? { + func getBindObject(forKey key: String?) -> Any? { guard let key, !key.isEmpty else { assertionFailure("") return nil } objc_sync_enter(self) defer { objc_sync_exit(self) } - let storedObj = lookinAllBindObjects(self).object(forKey: key as NSString) - if let container = storedObj as? LookinWeakContainer { + let storedObj = allBindObjects(self).object(forKey: key as NSString) + if let container = storedObj as? WeakContainer { return container.object } return storedObj } + @available(*, deprecated, renamed: "getBindObject(forKey:)") + func lookin_getBindObject(forKey key: String?) -> Any? { + getBindObject(forKey: key) + } + @objc(lookin_bindDouble:forKey:) + func bindDouble(_ doubleValue: Double, forKey key: String?) { + bindObject(NSNumber(value: doubleValue), forKey: key) + } + + @available(*, deprecated, renamed: "bindDouble(_:forKey:)") func lookin_bindDouble(_ doubleValue: Double, forKey key: String?) { - lookin_bindObject(NSNumber(value: doubleValue), forKey: key) + bindDouble(doubleValue, forKey: key) } @objc(lookin_getBindDoubleForKey:) - func lookin_getBindDouble(forKey key: String?) -> Double { - guard let number = lookin_getBindObject(forKey: key) as? NSNumber else { + func getBindDouble(forKey key: String?) -> Double { + guard let number = getBindObject(forKey: key) as? NSNumber else { return 0.0 } return number.doubleValue } + @available(*, deprecated, renamed: "getBindDouble(forKey:)") + func lookin_getBindDouble(forKey key: String?) -> Double { + getBindDouble(forKey: key) + } + @objc(lookin_bindBOOL:forKey:) + func bindBool(_ boolValue: Bool, forKey key: String?) { + bindObject(NSNumber(value: boolValue), forKey: key) + } + + @available(*, deprecated, renamed: "bindBool(_:forKey:)") func lookin_bindBOOL(_ boolValue: Bool, forKey key: String?) { - lookin_bindObject(NSNumber(value: boolValue), forKey: key) + bindBool(boolValue, forKey: key) } @objc(lookin_getBindBOOLForKey:) - func lookin_getBindBOOL(forKey key: String?) -> Bool { - guard let number = lookin_getBindObject(forKey: key) as? NSNumber else { + func getBindBool(forKey key: String?) -> Bool { + guard let number = getBindObject(forKey: key) as? NSNumber else { return false } return number.boolValue } + @available(*, deprecated, renamed: "getBindBool(forKey:)") + func lookin_getBindBOOL(forKey key: String?) -> Bool { + getBindBool(forKey: key) + } + @objc(lookin_bindLong:forKey:) + func bindLong(_ longValue: Int, forKey key: String?) { + bindObject(NSNumber(value: longValue), forKey: key) + } + + @available(*, deprecated, renamed: "bindLong(_:forKey:)") func lookin_bindLong(_ longValue: Int, forKey key: String?) { - lookin_bindObject(NSNumber(value: longValue), forKey: key) + bindLong(longValue, forKey: key) } @objc(lookin_getBindLongForKey:) - func lookin_getBindLong(forKey key: String?) -> Int { - guard let number = lookin_getBindObject(forKey: key) as? NSNumber else { + func getBindLong(forKey key: String?) -> Int { + guard let number = getBindObject(forKey: key) as? NSNumber else { return 0 } return number.intValue } + @available(*, deprecated, renamed: "getBindLong(forKey:)") + func lookin_getBindLong(forKey key: String?) -> Int { + getBindLong(forKey: key) + } + @objc(lookin_bindPoint:forKey:) - func lookin_bindPoint(_ pointValue: CGPoint, forKey key: String?) { + func bindPoint(_ pointValue: CGPoint, forKey key: String?) { #if canImport(UIKit) - lookin_bindObject(NSValue(cgPoint: pointValue), forKey: key) + bindObject(NSValue(cgPoint: pointValue), forKey: key) #elseif os(macOS) - lookin_bindObject(NSValue(point: pointValue), forKey: key) + bindObject(NSValue(point: pointValue), forKey: key) #endif } + @available(*, deprecated, renamed: "bindPoint(_:forKey:)") + func lookin_bindPoint(_ pointValue: CGPoint, forKey key: String?) { + bindPoint(pointValue, forKey: key) + } + @objc(lookin_getBindPointForKey:) - func lookin_getBindPoint(forKey key: String?) -> CGPoint { - guard let value = lookin_getBindObject(forKey: key) as? NSValue else { + func getBindPoint(forKey key: String?) -> CGPoint { + guard let value = getBindObject(forKey: key) as? NSValue else { return .zero } #if canImport(UIKit) @@ -136,18 +186,28 @@ #endif } + @available(*, deprecated, renamed: "getBindPoint(forKey:)") + func lookin_getBindPoint(forKey key: String?) -> CGPoint { + getBindPoint(forKey: key) + } + @objc(lookin_clearBindForKey:) + func clearBind(forKey key: String?) { + bindObject(nil, forKey: key) + } + + @available(*, deprecated, renamed: "clearBind(forKey:)") func lookin_clearBind(forKey key: String?) { - lookin_bindObject(nil, forKey: key) + clearBind(forKey: key) } } public extension NSObject { @objc(lookin_encodedObjectWithType:) - func lookin_encodedObject(with type: LookinCodingValueType) -> Any? { + func encodedObject(with type: LookinCodingValueType) -> Any? { switch type { case .color: - guard isKind(of: LookinColor.self) else { + guard isKind(of: PlatformColor.self) else { assertionFailure("") return nil } @@ -190,13 +250,13 @@ assertionFailure("") return nil } - return lookinPNGRepresentation(unsafeDowncast(self, to: UIImage.self)) + return pngRepresentation(unsafeDowncast(self, to: UIImage.self)) #elseif os(macOS) guard isKind(of: NSImage.self) else { assertionFailure("") return nil } - return unsafeDowncast(self, to: NSImage.self).lookin_data().map { $0 as NSData } + return unsafeDowncast(self, to: NSImage.self).encodedData().map { $0 as NSData } #endif default: @@ -204,8 +264,13 @@ } } + @available(*, deprecated, renamed: "encodedObject(with:)") + func lookin_encodedObject(with type: LookinCodingValueType) -> Any? { + encodedObject(with: type) + } + @objc(lookin_decodedObjectWithType:) - func lookin_decodedObject(with type: LookinCodingValueType) -> Any? { + func decodedObject(with type: LookinCodingValueType) -> Any? { switch type { case .color: guard isKind(of: NSArray.self) else { @@ -213,23 +278,28 @@ return nil } let rgba = unsafeDowncast(self, to: NSArray.self) - let r = lookinDoubleValue(rgba.object(at: 0)) - let g = lookinDoubleValue(rgba.object(at: 1)) - let b = lookinDoubleValue(rgba.object(at: 2)) - let a = lookinDoubleValue(rgba.object(at: 3)) - return LookinColor(red: r, green: g, blue: b, alpha: a) + let r = cgFloatValue(rgba.object(at: 0)) + let g = cgFloatValue(rgba.object(at: 1)) + let b = cgFloatValue(rgba.object(at: 2)) + let a = cgFloatValue(rgba.object(at: 3)) + return PlatformColor(red: r, green: g, blue: b, alpha: a) case .image: guard isKind(of: NSData.self) else { assertionFailure("") return nil } - return LookinImage(data: unsafeDowncast(self, to: NSData.self) as Data) + return PlatformImage(data: unsafeDowncast(self, to: NSData.self) as Data) default: return self } } + + @available(*, deprecated, renamed: "decodedObject(with:)") + func lookin_decodedObject(with type: LookinCodingValueType) -> Any? { + decodedObject(with: type) + } } // MARK: - Helpers @@ -238,9 +308,9 @@ /// `UIImagePNGRepresentation(image)` itself, looked up at run time: Swift /// only offers `pngData()`, whose `Data` bridges back as a different /// NSData class than the NSMutableData UIKit returns, and the class name - /// is archived on the wire (Tests/WireFormatGolden, LookinDisplayItem and - /// LookinConnectionAttachment-image). - private let lookinUIImagePNGRepresentation: (@convention(c) (UIImage) -> Unmanaged?)? = { + /// is archived on the wire (Tests/WireFormatGolden, DisplayItem and + /// ConnectionAttachment-image). + private let uiImagePNGRepresentation: (@convention(c) (UIImage) -> Unmanaged?)? = { // RTLD_DEFAULT guard let symbol = dlsym(UnsafeMutableRawPointer(bitPattern: -2), "UIImagePNGRepresentation") else { return nil @@ -248,8 +318,8 @@ return unsafeBitCast(symbol, to: (@convention(c) (UIImage) -> Unmanaged?).self) }() - private func lookinPNGRepresentation(_ image: UIImage) -> NSData? { - if let function = lookinUIImagePNGRepresentation { + private func pngRepresentation(_ image: UIImage) -> NSData? { + if let function = uiImagePNGRepresentation { return function(image)?.takeUnretainedValue() } return image.pngData().map { $0 as NSData } @@ -260,7 +330,7 @@ /// `-lookin_allBindObjects`: the mutable dictionary every binding lives in, /// created on first use. - private func lookinAllBindObjects(_ object: NSObject) -> NSMutableDictionary { + private func allBindObjects(_ object: NSObject) -> NSMutableDictionary { if let dict = objc_getAssociatedObject(object, &kAssociatedObjectKey_LookinAllBindObjects) as? NSMutableDictionary { return dict } @@ -272,7 +342,7 @@ /// `[value doubleValue]` for an archived rgba element. NSNumber and NSString /// answer it; any other object gets the same unrecognized-selector /// exception the message send raised. - private func lookinDoubleValue(_ value: Any) -> CGFloat { + private func cgFloatValue(_ value: Any) -> CGFloat { if let number = value as? NSNumber { return CGFloat(number.doubleValue) } diff --git a/Sources/LookinCoreImpl/Category/NSSet+Lookin.swift b/Sources/LookinCoreImpl/Category/NSSet+Lookin.swift index 16f120a4..e2893f0f 100644 --- a/Sources/LookinCoreImpl/Category/NSSet+Lookin.swift +++ b/Sources/LookinCoreImpl/Category/NSSet+Lookin.swift @@ -15,7 +15,7 @@ public extension NSSet { @objc(lookin_map:) - func lookin_map(_ block: ((Any?) -> Any?)?) -> Set! { + func mappedObjects(_ block: ((Any?) -> Any?)?) -> Set? { guard let block else { assertionFailure("") return nil @@ -26,11 +26,16 @@ newSet.add(newObj) } } - return lookinBridgedSet(newSet) + return bridgedSet(newSet) + } + + @available(*, deprecated, renamed: "mappedObjects(_:)") + func lookin_map(_ block: ((Any?) -> Any?)?) -> Set? { + mappedObjects(block) } @objc(lookin_firstFiltered:) - func lookin_firstFiltered(_ block: ((Any?) -> Bool)?) -> Any! { + func firstFiltered(_ block: ((Any?) -> Bool)?) -> Any? { guard let block else { assertionFailure("") return nil @@ -45,8 +50,13 @@ return targetObj } + @available(*, deprecated, renamed: "firstFiltered(_:)") + func lookin_firstFiltered(_ block: ((Any?) -> Bool)?) -> Any? { + firstFiltered(block) + } + @objc(lookin_filter:) - func lookin_filter(_ block: ((Any?) -> Bool)?) -> Set! { + func filteredObjects(_ block: ((Any?) -> Bool)?) -> Set? { guard let block else { assertionFailure("") return nil @@ -57,11 +67,16 @@ mSet.add(obj) } } - return lookinBridgedSet(mSet) + return bridgedSet(mSet) + } + + @available(*, deprecated, renamed: "filteredObjects(_:)") + func lookin_filter(_ block: ((Any?) -> Bool)?) -> Set? { + filteredObjects(block) } @objc(lookin_any:) - func lookin_any(_ block: ((Any?) -> Bool)?) -> Bool { + func anyObjectPasses(_ block: ((Any?) -> Bool)?) -> Bool { guard let block else { assertionFailure("") return false @@ -75,12 +90,17 @@ } return boolValue } + + @available(*, deprecated, renamed: "anyObjectPasses(_:)") + func lookin_any(_ block: ((Any?) -> Bool)?) -> Bool { + anyObjectPasses(block) + } } /// An immutable copy of `set`, handed to Objective-C without copying its /// elements: bridging an immutable NSSet to `Set` and back returns the same /// NSSet. - private func lookinBridgedSet(_ set: NSSet) -> Set { + private func bridgedSet(_ set: NSSet) -> Set { set.copy() as! Set } diff --git a/Sources/LookinCoreImpl/Category/NSString+Lookin.swift b/Sources/LookinCoreImpl/Category/NSString+Lookin.swift index 7aab963d..dc1b3064 100644 --- a/Sources/LookinCoreImpl/Category/NSString+Lookin.swift +++ b/Sources/LookinCoreImpl/Category/NSString+Lookin.swift @@ -21,7 +21,7 @@ public extension NSString { @objc(lookin_stringFromDouble:decimal:) - class func lookin_string(from doubleValue: Double, decimal: UInt) -> String! { + class func string(from doubleValue: Double, decimal: UInt) -> String { let formatString = NSString(format: "%%.%@f", NSNumber(value: decimal)) var string = NSString(format: formatString, doubleValue) // A zero-length string would raise in -substringFromIndex: in the @@ -37,45 +37,70 @@ return string as String } + @available(*, deprecated, renamed: "string(from:decimal:)") + class func lookin_string(from doubleValue: Double, decimal: UInt) -> String { + string(from: doubleValue, decimal: decimal) + } + @objc(lookin_stringFromRect:) - class func lookin_string(from rect: CGRect) -> String! { + class func string(from rect: CGRect) -> String { String(format: "{%@, %@, %@, %@}", - lookinString(rect.origin.x), - lookinString(rect.origin.y), - lookinString(rect.size.width), - lookinString(rect.size.height)) + twoDecimalString(rect.origin.x), + twoDecimalString(rect.origin.y), + twoDecimalString(rect.size.width), + twoDecimalString(rect.size.height)) + } + + @available(*, deprecated, renamed: "string(from:)") + class func lookin_string(from rect: CGRect) -> String { + string(from: rect) } @objc(lookin_stringFromInset:) - class func lookin_string(fromInset insets: LookinInsets) -> String! { + class func string(fromInset insets: PlatformEdgeInsets) -> String { String(format: "{%@, %@, %@, %@}", - lookinString(insets.top), - lookinString(insets.left), - lookinString(insets.bottom), - lookinString(insets.right)) + twoDecimalString(insets.top), + twoDecimalString(insets.left), + twoDecimalString(insets.bottom), + twoDecimalString(insets.right)) + } + + @available(*, deprecated, renamed: "string(fromInset:)") + class func lookin_string(fromInset insets: PlatformEdgeInsets) -> String { + string(fromInset: insets) } @objc(lookin_stringFromSize:) - class func lookin_string(from size: CGSize) -> String! { + class func string(from size: CGSize) -> String { String(format: "{%@, %@}", - lookinString(size.width), - lookinString(size.height)) + twoDecimalString(size.width), + twoDecimalString(size.height)) + } + + @available(*, deprecated, renamed: "string(from:)") + class func lookin_string(from size: CGSize) -> String { + string(from: size) } @objc(lookin_stringFromPoint:) - class func lookin_string(from point: CGPoint) -> String! { + class func string(from point: CGPoint) -> String { String(format: "{%@, %@}", - lookinString(point.x), - lookinString(point.y)) + twoDecimalString(point.x), + twoDecimalString(point.y)) + } + + @available(*, deprecated, renamed: "string(from:)") + class func lookin_string(from point: CGPoint) -> String { + string(from: point) } @objc(lookin_rgbaStringFromColor:) - class func lookin_rgbaString(from color: LookinColor?) -> String! { + class func rgbaString(from color: PlatformColor?) -> String { guard let color else { return "nil" } #if canImport(UIKit) - let rgbColor: LookinColor? = color + let rgbColor: PlatformColor? = color #elseif os(macOS) let rgbColor = color.usingColorSpace(.sRGB) #endif @@ -93,11 +118,16 @@ } return String(format: "(%.0f, %.0f, %.0f, %@)", Double(r * 255), Double(g * 255), Double(b * 255), - NSString.lookin_string(from: Double(a), decimal: 2)! as NSString) + NSString.string(from: Double(a), decimal: 2) as NSString) + } + + @available(*, deprecated, renamed: "rgbaString(from:)") + class func lookin_rgbaString(from color: PlatformColor?) -> String { + rgbaString(from: color) } @objc(lookin_safeInitWithUTF8String:) - func lookin_safeInit(withUTF8String string: UnsafePointer?) -> String! { + func safeInit(withUTF8String string: UnsafePointer?) -> String? { // `[[NSString alloc] lookin_safeInitWithUTF8String:]`: the receiver // is the class's placeholder; -initWithUTF8String: on a fresh // NSString gives the same string, nil for invalid UTF-8. @@ -107,8 +137,13 @@ return NSString(utf8String: string) as String? } + @available(*, deprecated, renamed: "safeInit(withUTF8String:)") + func lookin_safeInit(withUTF8String string: UnsafePointer?) -> String? { + safeInit(withUTF8String: string) + } + @objc(lookin_numbericOSVersion) - func lookin_numbericOSVersion() -> Int { + func numericOSVersion() -> Int { if length == 0 { return 0 } @@ -125,18 +160,23 @@ // NSInteger += NSInteger * double: computed in double, then // converted back to NSInteger. let component = Double((versionArr[pos] as NSString).integerValue) - numbericOSVersion = lookinIntegerFromDouble(Double(numbericOSVersion) + component * pow(10, Double(4 - pos * 2))) + numbericOSVersion = integerFromDouble(Double(numbericOSVersion) + component * pow(10, Double(4 - pos * 2))) pos += 1 } return numbericOSVersion } + + @available(*, deprecated, renamed: "numericOSVersion()") + func lookin_numbericOSVersion() -> Int { + numericOSVersion() + } } /// The C double-to-NSInteger conversion as arm64 performs it: truncate /// toward zero, saturate out-of-range values, NaN becomes 0. Swift's /// `Int(_:)` traps instead, and the version strings come from the peer. - private func lookinIntegerFromDouble(_ value: Double) -> Int { + private func integerFromDouble(_ value: Double) -> Int { if value.isNaN { return 0 } @@ -151,8 +191,8 @@ /// `[NSString lookin_stringFromDouble:value decimal:2]` as an NSString /// format argument. - private func lookinString(_ value: CGFloat) -> NSString { - NSString.lookin_string(from: Double(value), decimal: 2)! as NSString + private func twoDecimalString(_ value: CGFloat) -> NSString { + NSString.string(from: Double(value), decimal: 2) as NSString } #endif diff --git a/Sources/LookinCoreImpl/Category/NSValue+Lookin.swift b/Sources/LookinCoreImpl/Category/NSValue+Lookin.swift index 07fa75f9..4a10f812 100644 --- a/Sources/LookinCoreImpl/Category/NSValue+Lookin.swift +++ b/Sources/LookinCoreImpl/Category/NSValue+Lookin.swift @@ -30,46 +30,86 @@ #if os(macOS) @_cdecl("NSStringFromInsets") - public func lookin_NSStringFromInsets(_ insets: NSEdgeInsets) -> NSString { + public func exportedNSStringFromInsets(_ insets: NSEdgeInsets) -> NSString { NSString(format: "{%.*g, %.*g, %.*g, %.*g}", precision17, insets.top, precision17, insets.left, precision17, insets.bottom, precision17, insets.right) } + @available(*, deprecated, renamed: "NSStringFromInsets(_:)") + public func lookin_NSStringFromInsets(_ insets: NSEdgeInsets) -> NSString { + exportedNSStringFromInsets(insets) + } + @_cdecl("NSStringFromCGAffineTransform") - public func lookin_NSStringFromCGAffineTransform(_ transform: CGAffineTransform) -> NSString { + public func exportedNSStringFromCGAffineTransform(_ transform: CGAffineTransform) -> NSString { NSString(format: "[%.*g, %.*g, %.*g, %.*g, %.*g, %.*g]", precision17, transform.a, precision17, transform.b, precision17, transform.c, precision17, transform.d, precision17, transform.tx, precision17, transform.ty) } + @available(*, deprecated, renamed: "NSStringFromCGAffineTransform(_:)") + public func lookin_NSStringFromCGAffineTransform(_ transform: CGAffineTransform) -> NSString { + exportedNSStringFromCGAffineTransform(transform) + } + @_cdecl("NSStringFromCGVector") - public func lookin_NSStringFromCGVector(_ vector: CGVector) -> NSString { + public func exportedNSStringFromCGVector(_ vector: CGVector) -> NSString { NSString(format: "{%.*g, %.*g}", precision17, vector.dx, precision17, vector.dy) } + @available(*, deprecated, renamed: "NSStringFromCGVector(_:)") + public func lookin_NSStringFromCGVector(_ vector: CGVector) -> NSString { + exportedNSStringFromCGVector(vector) + } + @_cdecl("NSStringFromCGRect") - public func lookin_NSStringFromCGRect(_ rect: CGRect) -> NSString { + public func exportedNSStringFromCGRect(_ rect: CGRect) -> NSString { NSStringFromRect(rect) as NSString } + @available(*, deprecated, renamed: "NSStringFromCGRect(_:)") + public func lookin_NSStringFromCGRect(_ rect: CGRect) -> NSString { + exportedNSStringFromCGRect(rect) + } + @_cdecl("NSStringFromCGPoint") - public func lookin_NSStringFromCGPoint(_ point: CGPoint) -> NSString { + public func exportedNSStringFromCGPoint(_ point: CGPoint) -> NSString { NSStringFromPoint(point) as NSString } + @available(*, deprecated, renamed: "NSStringFromCGPoint(_:)") + public func lookin_NSStringFromCGPoint(_ point: CGPoint) -> NSString { + exportedNSStringFromCGPoint(point) + } + @_cdecl("NSStringFromCGSize") - public func lookin_NSStringFromCGSize(_ size: CGSize) -> NSString { + public func exportedNSStringFromCGSize(_ size: CGSize) -> NSString { NSStringFromSize(size) as NSString } + @available(*, deprecated, renamed: "NSStringFromCGSize(_:)") + public func lookin_NSStringFromCGSize(_ size: CGSize) -> NSString { + exportedNSStringFromCGSize(size) + } + @_cdecl("NSStringFromDirectionalEdgeInsets") - public func lookin_NSStringFromDirectionalEdgeInsets(_ insets: NSDirectionalEdgeInsets) -> NSString { + public func exportedNSStringFromDirectionalEdgeInsets(_ insets: NSDirectionalEdgeInsets) -> NSString { NSString(format: "{%.*g, %.*g, %.*g, %.*g}", precision17, insets.top, precision17, insets.leading, precision17, insets.bottom, precision17, insets.trailing) } + + @available(*, deprecated, renamed: "NSStringFromDirectionalEdgeInsets(_:)") + public func lookin_NSStringFromDirectionalEdgeInsets(_ insets: NSDirectionalEdgeInsets) -> NSString { + exportedNSStringFromDirectionalEdgeInsets(insets) + } #else @_cdecl("NSStringFromInsets") - public func lookin_NSStringFromInsets(_ insets: UIEdgeInsets) -> NSString { + public func exportedNSStringFromInsets(_ insets: UIEdgeInsets) -> NSString { NSString(format: "{%.*g, %.*g, %.*g, %.*g}", precision17, insets.top, precision17, insets.left, precision17, insets.bottom, precision17, insets.right) } + + @available(*, deprecated, renamed: "NSStringFromInsets(_:)") + public func lookin_NSStringFromInsets(_ insets: UIEdgeInsets) -> NSString { + exportedNSStringFromInsets(insets) + } #endif // MARK: - NSValue (Lookin) @@ -77,32 +117,57 @@ public extension NSValue { #if os(macOS) @objc(valueWithCGVector:) - class func lookin_value(cgVector vector: CGVector) -> NSValue { + class func value(cgVector vector: CGVector) -> NSValue { var vector = vector return NSValue(bytes: &vector, objCType: LookinEncoding(.cgVector)) } + @available(*, deprecated, renamed: "value(cgVector:)") + class func lookin_value(cgVector vector: CGVector) -> NSValue { + value(cgVector: vector) + } + @objc(valueWithCGRect:) - class func lookin_value(cgRect rect: CGRect) -> NSValue { + class func value(cgRect rect: CGRect) -> NSValue { NSValue(rect: rect) } + @available(*, deprecated, renamed: "value(cgRect:)") + class func lookin_value(cgRect rect: CGRect) -> NSValue { + value(cgRect: rect) + } + @objc(valueWithCGPoint:) - class func lookin_value(cgPoint point: CGPoint) -> NSValue { + class func value(cgPoint point: CGPoint) -> NSValue { NSValue(point: point) } + @available(*, deprecated, renamed: "value(cgPoint:)") + class func lookin_value(cgPoint point: CGPoint) -> NSValue { + value(cgPoint: point) + } + @objc(valueWithCGSize:) - class func lookin_value(cgSize size: CGSize) -> NSValue { + class func value(cgSize size: CGSize) -> NSValue { NSValue(size: size) } + @available(*, deprecated, renamed: "value(cgSize:)") + class func lookin_value(cgSize size: CGSize) -> NSValue { + value(cgSize: size) + } + @objc(valueWithCGAffineTransform:) - class func lookin_value(cgAffineTransform transform: CGAffineTransform) -> NSValue { + class func value(cgAffineTransform transform: CGAffineTransform) -> NSValue { var transform = transform return NSValue(bytes: &transform, objCType: LookinEncoding(.cgAffineTransform)) } + @available(*, deprecated, renamed: "value(cgAffineTransform:)") + class func lookin_value(cgAffineTransform transform: CGAffineTransform) -> NSValue { + value(cgAffineTransform: transform) + } + @objc(CGAffineTransformValue) func cgAffineTransform() -> CGAffineTransform { var transform = CGAffineTransform() @@ -133,20 +198,30 @@ } @objc(valueWithInsets:) - class func lookin_value(insets: NSEdgeInsets) -> NSValue { + class func value(insets: NSEdgeInsets) -> NSValue { NSValue(edgeInsets: insets) } + @available(*, deprecated, renamed: "value(insets:)") + class func lookin_value(insets: NSEdgeInsets) -> NSValue { + value(insets: insets) + } + @objc(InsetsValue) func insetsValue() -> NSEdgeInsets { edgeInsetsValue } #else @objc(valueWithInsets:) - class func lookin_value(insets: UIEdgeInsets) -> NSValue { + class func value(insets: UIEdgeInsets) -> NSValue { NSValue(uiEdgeInsets: insets) } + @available(*, deprecated, renamed: "value(insets:)") + class func lookin_value(insets: UIEdgeInsets) -> NSValue { + value(insets: insets) + } + @objc(InsetsValue) func insetsValue() -> UIEdgeInsets { uiEdgeInsetsValue diff --git a/Sources/LookinCoreImpl/LookinConnectionAttachment.swift b/Sources/LookinCoreImpl/ConnectionAttachment.swift similarity index 78% rename from Sources/LookinCoreImpl/LookinConnectionAttachment.swift rename to Sources/LookinCoreImpl/ConnectionAttachment.swift index 7f6e3322..51979c34 100644 --- a/Sources/LookinCoreImpl/LookinConnectionAttachment.swift +++ b/Sources/LookinCoreImpl/ConnectionAttachment.swift @@ -1,5 +1,5 @@ // -// LookinConnectionAttachment.swift +// ConnectionAttachment.swift // Lookin // // Was LookinConnectionAttachment.m. Every request body travels in one of these; @@ -17,11 +17,11 @@ private let Key_DataType = "1" @objc(LookinConnectionAttachment) - public class LookinConnectionAttachment: NSObject, NSCoding, NSSecureCoding { + public class ConnectionAttachment: NSObject, NSCoding, NSSecureCoding { @objc(dataType) public var dataType: LookinCodingValueType = .unknown @objc(data) - public var data: Any! + public var data: Any? override public init() { super.init() @@ -31,14 +31,14 @@ @objc(encodeWithCoder:) public func encode(with aCoder: NSCoder) { - aCoder.encode((data as? NSObject)?.lookin_encodedObject(with: dataType), forKey: Key_Data) + aCoder.encode((data as? NSObject)?.encodedObject(with: dataType), forKey: Key_Data) aCoder.encode(dataType.rawValue, forKey: Key_DataType) } public required init?(coder aDecoder: NSCoder) { super.init() dataType = LookinCodingValueType(rawValue: aDecoder.decodeInteger(forKey: Key_DataType)) ?? .unknown - data = (aDecoder.decodeObject(forKey: Key_Data) as? NSObject)?.lookin_decodedObject(with: dataType) + data = (aDecoder.decodeObject(forKey: Key_Data) as? NSObject)?.decodedObject(with: dataType) } public class var supportsSecureCoding: Bool { diff --git a/Sources/LookinCoreImpl/LookinConnectionResponseAttachment.swift b/Sources/LookinCoreImpl/ConnectionResponseAttachment.swift similarity index 93% rename from Sources/LookinCoreImpl/LookinConnectionResponseAttachment.swift rename to Sources/LookinCoreImpl/ConnectionResponseAttachment.swift index bbddb325..f675adda 100644 --- a/Sources/LookinCoreImpl/LookinConnectionResponseAttachment.swift +++ b/Sources/LookinCoreImpl/ConnectionResponseAttachment.swift @@ -1,5 +1,5 @@ // -// LookinConnectionResponseAttachment.swift +// ConnectionResponseAttachment.swift // Lookin // // Was LookinConnectionResponseAttachment.m. Every reply travels in one of these; @@ -15,11 +15,11 @@ #endif @objc(LookinConnectionResponseAttachment) - public class LookinConnectionResponseAttachment: LookinConnectionAttachment { + public class ConnectionResponseAttachment: ConnectionAttachment { @objc(lookinServerVersion) public var lookinServerVersion: Int32 = 0 @objc(error) - public var error: (any Error)! + public var error: (any Error)? @objc(appIsInBackground) public var appIsInBackground: Bool = false @objc(dataTotalCount) @@ -31,7 +31,7 @@ /// method here: implemented as a Swift initializer it compiles but /// registers no class method. @objc(attachmentWithError:) - public class func attachment(error: (any Error)?) -> Self! { + public class func attachment(error: (any Error)?) -> Self { let attachment = unsafeDowncast((self as NSObject.Type).init(), to: self) attachment.error = error return attachment diff --git a/Sources/LookinCoreImpl/LookinCustomAttrModification.swift b/Sources/LookinCoreImpl/CustomAttributeModification.swift similarity index 86% rename from Sources/LookinCoreImpl/LookinCustomAttrModification.swift rename to Sources/LookinCoreImpl/CustomAttributeModification.swift index 32276d7b..d0d4289d 100644 --- a/Sources/LookinCoreImpl/LookinCustomAttrModification.swift +++ b/Sources/LookinCoreImpl/CustomAttributeModification.swift @@ -1,5 +1,5 @@ // -// LookinCustomAttrModification.swift +// CustomAttributeModification.swift // LookinShared // // Was LookinCustomAttrModification.m. The coding keys and value encodings are @@ -14,13 +14,13 @@ #endif @objc(LookinCustomAttrModification) - public class LookinCustomAttrModification: NSObject, NSCoding, NSSecureCoding { + public class CustomAttributeModification: NSObject, NSCoding, NSSecureCoding { @objc(attrType) public var attrType: LookinAttrType = .none @objc(customSetterID) - public var customSetterID: String! + public var customSetterID: String? @objc(value) - public var value: Any! + public var value: Any? override public init() { super.init() diff --git a/Sources/LookinCoreImpl/LookinCustomDisplayItemInfo.swift b/Sources/LookinCoreImpl/CustomDisplayItemInfo.swift similarity index 94% rename from Sources/LookinCoreImpl/LookinCustomDisplayItemInfo.swift rename to Sources/LookinCoreImpl/CustomDisplayItemInfo.swift index f7193992..63ba1f00 100644 --- a/Sources/LookinCoreImpl/LookinCustomDisplayItemInfo.swift +++ b/Sources/LookinCoreImpl/CustomDisplayItemInfo.swift @@ -1,5 +1,5 @@ // -// LookinCustomDisplayItemInfo.swift +// CustomDisplayItemInfo.swift // LookinServer // // Was LookinCustomDisplayItemInfo.m. The coding keys are pinned by @@ -19,7 +19,7 @@ #endif @objc(LookinCustomDisplayItemInfo) - public class LookinCustomDisplayItemInfo: NSObject, NSCoding, NSSecureCoding, NSCopying { + public class CustomDisplayItemInfo: NSObject, NSCoding, NSSecureCoding, NSCopying { @objc(frameInWindow) public var frameInWindow: NSValue? @objc(title) @@ -41,7 +41,7 @@ @objc(copyWithZone:) public func copy(with _: NSZone? = nil) -> Any { - let newInstance = LookinCustomDisplayItemInfo() + let newInstance = CustomDisplayItemInfo() if let frameInWindow { #if canImport(UIKit) newInstance.frameInWindow = NSValue(cgRect: frameInWindow.cgRectValue) diff --git a/Sources/LookinCoreImpl/LookinDashboardBlueprint+AttrInfo.swift b/Sources/LookinCoreImpl/DashboardBlueprint+AttributeInfo.swift similarity index 99% rename from Sources/LookinCoreImpl/LookinDashboardBlueprint+AttrInfo.swift rename to Sources/LookinCoreImpl/DashboardBlueprint+AttributeInfo.swift index 1975a8dc..2ab5fd2e 100644 --- a/Sources/LookinCoreImpl/LookinDashboardBlueprint+AttrInfo.swift +++ b/Sources/LookinCoreImpl/DashboardBlueprint+AttributeInfo.swift @@ -1,5 +1,5 @@ // -// LookinDashboardBlueprint+AttrInfo.swift +// DashboardBlueprint+AttributeInfo.swift // LookinCore // // Class, titles, accessors and flags of every attribute. @@ -15,7 +15,7 @@ import LookinCore #endif - extension LookinDashboardBlueprintTables { + extension DashboardBlueprintTables { /// The per-attribute information behind the attribute queries. See /// `AttrInfo` for what each field means. static let attrInfo: [String: AttrInfo] = { diff --git a/Sources/LookinCoreImpl/LookinDashboardBlueprint+Groups.swift b/Sources/LookinCoreImpl/DashboardBlueprint+Groups.swift similarity index 99% rename from Sources/LookinCoreImpl/LookinDashboardBlueprint+Groups.swift rename to Sources/LookinCoreImpl/DashboardBlueprint+Groups.swift index 43fe06ed..7c7512c5 100644 --- a/Sources/LookinCoreImpl/LookinDashboardBlueprint+Groups.swift +++ b/Sources/LookinCoreImpl/DashboardBlueprint+Groups.swift @@ -1,5 +1,5 @@ // -// LookinDashboardBlueprint+Groups.swift +// DashboardBlueprint+Groups.swift // LookinCore // // Group order, the sections of each group, and group and section titles. @@ -15,7 +15,7 @@ import LookinCore #endif - extension LookinDashboardBlueprintTables { + extension DashboardBlueprintTables { /// `+groupIDs`, in display order. static let groupIDs: [String] = { var ids: [String] = [] diff --git a/Sources/LookinCoreImpl/LookinDashboardBlueprint+Sections.swift b/Sources/LookinCoreImpl/DashboardBlueprint+Sections.swift similarity index 99% rename from Sources/LookinCoreImpl/LookinDashboardBlueprint+Sections.swift rename to Sources/LookinCoreImpl/DashboardBlueprint+Sections.swift index 07094502..ae4b5d76 100644 --- a/Sources/LookinCoreImpl/LookinDashboardBlueprint+Sections.swift +++ b/Sources/LookinCoreImpl/DashboardBlueprint+Sections.swift @@ -1,5 +1,5 @@ // -// LookinDashboardBlueprint+Sections.swift +// DashboardBlueprint+Sections.swift // LookinCore // // The attributes of each section. @@ -15,7 +15,7 @@ import LookinCore #endif - extension LookinDashboardBlueprintTables { + extension DashboardBlueprintTables { /// `+attrIDsForSectionID:`, in display order. static let attrIDsBySectionID: [String: [String]] = { var table: [String: [String]] = [:] diff --git a/Sources/LookinCoreImpl/LookinDashboardBlueprint.swift b/Sources/LookinCoreImpl/DashboardBlueprint.swift similarity index 81% rename from Sources/LookinCoreImpl/LookinDashboardBlueprint.swift rename to Sources/LookinCoreImpl/DashboardBlueprint.swift index d0d90745..f692d7c5 100644 --- a/Sources/LookinCoreImpl/LookinDashboardBlueprint.swift +++ b/Sources/LookinCoreImpl/DashboardBlueprint.swift @@ -1,9 +1,9 @@ // -// LookinDashboardBlueprint.swift +// DashboardBlueprint.swift // LookinCore // // Was LookinDashboardBlueprint.m. The tables -// live in LookinDashboardBlueprint+Groups.swift, +Sections.swift and +// live in DashboardBlueprint+Groups.swift, +Sections.swift and // +AttrInfo.swift; the output of every class method below is pinned by // Tests/LookinServerHierarchyTests/BlueprintEquivalenceTests. // @@ -17,7 +17,7 @@ /// Namespace for the blueprint's static tables. Each table is built once, /// on first use, like the `dispatch_once` dictionaries it replaces. - enum LookinDashboardBlueprintTables { + enum DashboardBlueprintTables { // Class name of an attribute that lives on the platform view. #if canImport(UIKit) static let viewClassName = "UIView" @@ -90,26 +90,26 @@ } @objc(LookinDashboardBlueprint) - public class LookinDashboardBlueprint: NSObject { + public class DashboardBlueprint: NSObject { @objc(groupIDs) - public class func groupIDs() -> [String]! { - LookinDashboardBlueprintTables.groupIDs + public class func groupIDs() -> [String] { + DashboardBlueprintTables.groupIDs } @objc(sectionIDsForGroupID:) - public class func sectionIDs(forGroupID groupID: String?) -> [String]! { + public class func sectionIDs(forGroupID groupID: String?) -> [String]? { guard let groupID else { return nil } - return LookinDashboardBlueprintTables.sectionIDsByGroupID[groupID] + return DashboardBlueprintTables.sectionIDsByGroupID[groupID] } @objc(attrIDsForSectionID:) - public class func attrIDs(forSectionID sectionID: String?) -> [String]! { + public class func attrIDs(forSectionID sectionID: String?) -> [String]? { guard let sectionID else { return nil } - return LookinDashboardBlueprintTables.attrIDsBySectionID[sectionID] + return DashboardBlueprintTables.attrIDsBySectionID[sectionID] } @objc(getHostGroupID:sectionID:fromAttrID:) @@ -120,7 +120,7 @@ ) { var targetGroupID: String? var targetSectionID: String? - search: for candidateGroupID in groupIDs() ?? [] { + search: for candidateGroupID in groupIDs() { for candidateSectionID in sectionIDs(forGroupID: candidateGroupID) ?? [] { for attrID in attrIDs(forSectionID: candidateSectionID) ?? [] where attrID == targetAttrID { targetGroupID = candidateGroupID @@ -138,25 +138,25 @@ } @objc(groupTitleWithGroupID:) - public class func groupTitle(withGroupID groupID: String?) -> String! { - let title = groupID.flatMap { LookinDashboardBlueprintTables.groupTitles[$0] } + public class func groupTitle(withGroupID groupID: String?) -> String? { + let title = groupID.flatMap { DashboardBlueprintTables.groupTitles[$0] } blueprintAssert(!(title ?? "").isEmpty, method: #selector(groupTitle(withGroupID:))) return title } @objc(sectionTitleWithSectionID:) - public class func sectionTitle(withSectionID secID: String?) -> String! { - secID.flatMap { LookinDashboardBlueprintTables.sectionTitles[$0] } + public class func sectionTitle(withSectionID secID: String?) -> String? { + secID.flatMap { DashboardBlueprintTables.sectionTitles[$0] } } @objc(objectAttrTypeWithAttrID:) public class func objectAttrType(withAttrID attrID: String?) -> LookinAttrType { - LookinDashboardBlueprintTables.info(attrID)?.typeIfObj ?? LookinAttrType.none + DashboardBlueprintTables.info(attrID)?.typeIfObj ?? LookinAttrType.none } @objc(classNameWithAttrID:) - public class func className(withAttrID attrID: String?) -> String! { - let className = LookinDashboardBlueprintTables.info(attrID)?.className + public class func className(withAttrID attrID: String?) -> String? { + let className = DashboardBlueprintTables.info(attrID)?.className blueprintAssert(!(className ?? "").isEmpty, method: #selector(className(withAttrID:))) return className } @@ -186,29 +186,29 @@ } @objc(enumListNameWithAttrID:) - public class func enumListName(withAttrID attrID: String?) -> String! { - LookinDashboardBlueprintTables.info(attrID)?.enumList + public class func enumListName(withAttrID attrID: String?) -> String? { + DashboardBlueprintTables.info(attrID)?.enumList } @objc(needPatchAfterModificationWithAttrID:) public class func needPatchAfterModification(withAttrID attrID: String?) -> Bool { - LookinDashboardBlueprintTables.info(attrID)?.patch ?? false + DashboardBlueprintTables.info(attrID)?.patch ?? false } @objc(fullTitleWithAttrID:) - public class func fullTitle(withAttrID attrID: String?) -> String! { - LookinDashboardBlueprintTables.info(attrID)?.fullTitle + public class func fullTitle(withAttrID attrID: String?) -> String? { + DashboardBlueprintTables.info(attrID)?.fullTitle } @objc(briefTitleWithAttrID:) - public class func briefTitle(withAttrID attrID: String?) -> String! { - let info = LookinDashboardBlueprintTables.info(attrID) + public class func briefTitle(withAttrID attrID: String?) -> String? { + let info = DashboardBlueprintTables.info(attrID) return info?.briefTitle ?? info?.fullTitle } @objc(getterWithAttrID:) - public class func getter(withAttrID attrID: String?) -> Selector! { - let info = LookinDashboardBlueprintTables.info(attrID) + public class func getter(withAttrID attrID: String?) -> Selector? { + let info = DashboardBlueprintTables.info(attrID) if let getterString = info?.getterString { // An empty string (for example image_open_open) pins the // value to nil. @@ -217,14 +217,14 @@ let fullTitle = info?.fullTitle blueprintAssert(!(fullTitle ?? "").isEmpty, method: #selector(getter(withAttrID:))) return NSSelectorFromString( - LookinDashboardBlueprintTables.formatted(fullTitle?.prefix(1).lowercased()) + - LookinDashboardBlueprintTables.formatted(fullTitle.map { String($0.dropFirst()) }) + DashboardBlueprintTables.formatted(fullTitle?.prefix(1).lowercased()) + + DashboardBlueprintTables.formatted(fullTitle.map { String($0.dropFirst()) }) ) } @objc(setterWithAttrID:) - public class func setter(withAttrID attrID: String?) -> Selector! { - let info = LookinDashboardBlueprintTables.info(attrID) + public class func setter(withAttrID attrID: String?) -> Selector? { + let info = DashboardBlueprintTables.info(attrID) if let setterString = info?.setterString { // An empty string means the client cannot modify the // attribute. @@ -233,19 +233,19 @@ let fullTitle = info?.fullTitle blueprintAssert(!(fullTitle ?? "").isEmpty, method: #selector(setter(withAttrID:))) return NSSelectorFromString( - "set" + LookinDashboardBlueprintTables.formatted(fullTitle?.prefix(1).uppercased()) + - LookinDashboardBlueprintTables.formatted(fullTitle.map { String($0.dropFirst()) }) + ":" + "set" + DashboardBlueprintTables.formatted(fullTitle?.prefix(1).uppercased()) + + DashboardBlueprintTables.formatted(fullTitle.map { String($0.dropFirst()) }) + ":" ) } @objc(hideIfNilWithAttrID:) public class func hideIfNil(withAttrID attrID: String?) -> Bool { - LookinDashboardBlueprintTables.info(attrID)?.hideIfNil ?? false + DashboardBlueprintTables.info(attrID)?.hideIfNil ?? false } @objc(minAvailableOSVersionWithAttrID:) public class func minAvailableOSVersion(withAttrID attrID: String?) -> Int { - LookinDashboardBlueprintTables.info(attrID)?.osVersion ?? 0 + DashboardBlueprintTables.info(attrID)?.osVersion ?? 0 } } diff --git a/Sources/LookinCoreImpl/Deprecated.swift b/Sources/LookinCoreImpl/Deprecated.swift new file mode 100644 index 00000000..40cdfc35 --- /dev/null +++ b/Sources/LookinCoreImpl/Deprecated.swift @@ -0,0 +1,181 @@ +// +// Deprecated.swift +// LookinCoreImpl +// +// The type names from before the LK / LKS / Lookin prefixes were dropped, +// kept so that client code still compiles. Removed in 2.0.0. +// + +#if SHOULD_COMPILE_LOOKIN_SERVER + + @available(*, deprecated, renamed: "MultiplatformAdapter") + public typealias LKS_MultiplatformAdapter = MultiplatformAdapter + + @available(*, deprecated, renamed: "InspectedAppInfo") + public typealias LookinAppInfo = InspectedAppInfo + + @available(*, deprecated, renamed: "InspectedAttribute") + public typealias LookinAttribute = InspectedAttribute + + @available(*, deprecated, renamed: "AttributeModification") + public typealias LookinAttributeModification = AttributeModification + + @available(*, deprecated, renamed: "AttributesGroup") + public typealias LookinAttributesGroup = AttributesGroup + + @available(*, deprecated, renamed: "AttributesSection") + public typealias LookinAttributesSection = AttributesSection + + @available(*, deprecated, renamed: "AutoLayoutConstraint") + public typealias LookinAutoLayoutConstraint = AutoLayoutConstraint + + @available(*, deprecated, renamed: "ConnectionAttachment") + public typealias LookinConnectionAttachment = ConnectionAttachment + + @available(*, deprecated, renamed: "ConnectionResponseAttachment") + public typealias LookinConnectionResponseAttachment = ConnectionResponseAttachment + + @available(*, deprecated, renamed: "CustomAttributeModification") + public typealias LookinCustomAttrModification = CustomAttributeModification + + @available(*, deprecated, renamed: "CustomDisplayItemInfo") + public typealias LookinCustomDisplayItemInfo = CustomDisplayItemInfo + + @available(*, deprecated, renamed: "DashboardBlueprint") + public typealias LookinDashboardBlueprint = DashboardBlueprint + + @available(*, deprecated, renamed: "DisplayItem") + public typealias LookinDisplayItem = DisplayItem + + @available(*, deprecated, renamed: "DisplayItemDelegate") + public typealias LookinDisplayItemDelegate = DisplayItemDelegate + + @available(*, deprecated, renamed: "DisplayItemDetail") + public typealias LookinDisplayItemDetail = DisplayItemDetail + + @available(*, deprecated, renamed: "EventHandlerDescription") + public typealias LookinEventHandler = EventHandlerDescription + + @available(*, deprecated, renamed: "TransportFrame") + public typealias LookinFrame = TransportFrame + + @available(*, deprecated, renamed: "FrameChannel") + public typealias LookinFrameChannel = FrameChannel + + @available(*, deprecated, renamed: "FrameDecoder") + public typealias LookinFrameDecoder = FrameDecoder + + @available(*, deprecated, renamed: "FrameError") + public typealias LookinFrameError = FrameError + + @available(*, deprecated, renamed: "FrameHeader") + public typealias LookinFrameHeader = FrameHeader + + @available(*, deprecated, renamed: "FrameListener") + public typealias LookinFrameListener = FrameListener + + @available(*, deprecated, renamed: "FrameProtocolConstants") + public typealias LookinFrameProtocol = FrameProtocolConstants + + @available(*, deprecated, renamed: "HierarchyFile") + public typealias LookinHierarchyFile = HierarchyFile + + @available(*, deprecated, renamed: "HierarchyInfo") + public typealias LookinHierarchyInfo = HierarchyInfo + + @available(*, deprecated, renamed: "InstanceVariableTrace") + public typealias LookinIvarTrace = InstanceVariableTrace + + @available(*, deprecated, renamed: "InspectedObject") + public typealias LookinObject = InspectedObject + + @available(*, deprecated, renamed: "SocketConnector") + public typealias LookinSocket = SocketConnector + + @available(*, deprecated, renamed: "StaticAsyncUpdateTask") + public typealias LookinStaticAsyncUpdateTask = StaticAsyncUpdateTask + + @available(*, deprecated, renamed: "StaticAsyncUpdateTasksPackage") + public typealias LookinStaticAsyncUpdateTasksPackage = StaticAsyncUpdateTasksPackage + + @available(*, deprecated, renamed: "StringTwoTuple") + public typealias LookinStringTwoTuple = StringTwoTuple + + @available(*, deprecated, renamed: "TwoTuple") + public typealias LookinTwoTuple = TwoTuple + + @available(*, deprecated, renamed: "USBMux") + public typealias LookinUSBMux = USBMux + + @available(*, deprecated, renamed: "USBMuxDecoder") + public typealias LookinUSBMuxDecoder = USBMuxDecoder + + @available(*, deprecated, renamed: "USBMuxError") + public typealias LookinUSBMuxError = USBMuxError + + @available(*, deprecated, renamed: "USBMuxPacket") + public typealias LookinUSBMuxPacket = USBMuxPacket + + @available(*, deprecated, renamed: "WeakContainer") + public typealias LookinWeakContainer = WeakContainer + + #if canImport(UIKit) || os(macOS) + + @available(*, deprecated, renamed: "PlatformApplication") + public typealias LookinApplication = PlatformApplication + + @available(*, deprecated, renamed: "PlatformCollectionView") + public typealias LookinCollectionView = PlatformCollectionView + + @available(*, deprecated, renamed: "PlatformColor") + public typealias LookinColor = PlatformColor + + @available(*, deprecated, renamed: "PlatformControl") + public typealias LookinControl = PlatformControl + + @available(*, deprecated, renamed: "PlatformFont") + public typealias LookinFont = PlatformFont + + @available(*, deprecated, renamed: "PlatformGestureRecognizer") + public typealias LookinGestureRecognizer = PlatformGestureRecognizer + + @available(*, deprecated, renamed: "PlatformImage") + public typealias LookinImage = PlatformImage + + @available(*, deprecated, renamed: "PlatformImageView") + public typealias LookinImageView = PlatformImageView + + @available(*, deprecated, renamed: "PlatformEdgeInsets") + public typealias LookinInsets = PlatformEdgeInsets + + @available(*, deprecated, renamed: "PlatformLayoutGuide") + public typealias LookinLayoutGuide = PlatformLayoutGuide + + @available(*, deprecated, renamed: "PlatformResponder") + public typealias LookinResponder = PlatformResponder + + @available(*, deprecated, renamed: "PlatformTextField") + public typealias LookinTextField = PlatformTextField + + @available(*, deprecated, renamed: "PlatformTextView") + public typealias LookinTextView = PlatformTextView + + @available(*, deprecated, renamed: "PlatformView") + public typealias LookinView = PlatformView + + @available(*, deprecated, renamed: "PlatformViewController") + public typealias LookinViewController = PlatformViewController + + @available(*, deprecated, renamed: "PlatformWindow") + public typealias LookinWindow = PlatformWindow + + #endif + + #if os(macOS) + + @available(*, deprecated, renamed: "USBMuxClient") + public typealias LookinUSBMuxClient = USBMuxClient + + #endif + +#endif diff --git a/Sources/LookinCoreImpl/LookinDisplayItem.swift b/Sources/LookinCoreImpl/DisplayItem.swift similarity index 82% rename from Sources/LookinCoreImpl/LookinDisplayItem.swift rename to Sources/LookinCoreImpl/DisplayItem.swift index 39818e85..e06417bf 100644 --- a/Sources/LookinCoreImpl/LookinDisplayItem.swift +++ b/Sources/LookinCoreImpl/DisplayItem.swift @@ -1,5 +1,5 @@ // -// LookinDisplayItem.swift +// DisplayItem.swift // qmuidemo // // Was LookinDisplayItem.m: one @@ -30,54 +30,54 @@ /// lks_colorFromRGBAComponents:]` live in LookinServer /// (UIColor+LookinServer.h); LookinCore does not link against the /// server, so they are sent dynamically, as the original's import did. - @objc private protocol LookinDisplayItemColorBridge { - func lks_rgbaComponents() -> NSArray? - func lks_colorFromRGBAComponents(_ components: AnyObject?) -> AnyObject? + @objc private protocol DisplayItemColorBridge { + @objc(lks_rgbaComponents) func rgbaComponents() -> NSArray? + @objc(lks_colorFromRGBAComponents:) func colorFromRGBAComponents(_ components: AnyObject?) -> AnyObject? } - private func lookinRGBAComponents(of color: LookinColor?) -> NSArray? { + private func rgbaComponents(of color: PlatformColor?) -> NSArray? { guard let color else { return nil } - return unsafeBitCast(color, to: LookinDisplayItemColorBridge.self).lks_rgbaComponents() + return unsafeBitCast(color, to: DisplayItemColorBridge.self).rgbaComponents() } - private func lookinColor(fromRGBAComponents components: Any?) -> LookinColor? { + private func platformColor(fromRGBAComponents components: Any?) -> PlatformColor? { let colorClass: AnyObject = UIColor.self - return unsafeBitCast(colorClass, to: LookinDisplayItemColorBridge.self).lks_colorFromRGBAComponents(components as AnyObject?) as? LookinColor + return unsafeBitCast(colorClass, to: DisplayItemColorBridge.self).colorFromRGBAComponents(components as AnyObject?) as? PlatformColor } #elseif os(macOS) /// `-[NSColor lookin_rgbaComponents]` and `+[NSColor /// lookin_colorFromRGBAComponents:]` (Color+Lookin.h), sent the same way /// so the arrays are not bridged. - @objc private protocol LookinDisplayItemColorBridge { - func lookin_rgbaComponents() -> NSArray? - func lookin_colorFromRGBAComponents(_ components: AnyObject?) -> AnyObject? + @objc private protocol DisplayItemColorBridge { + @objc(lookin_rgbaComponents) func sRGBAComponents() -> NSArray? + @objc(lookin_colorFromRGBAComponents:) func sRGBColorFromRGBAComponents(_ components: AnyObject?) -> AnyObject? } - private func lookinRGBAComponents(of color: LookinColor?) -> NSArray? { + private func rgbaComponents(of color: PlatformColor?) -> NSArray? { guard let color else { return nil } - return unsafeBitCast(color, to: LookinDisplayItemColorBridge.self).lookin_rgbaComponents() + return unsafeBitCast(color, to: DisplayItemColorBridge.self).sRGBAComponents() } - private func lookinColor(fromRGBAComponents components: Any?) -> LookinColor? { + private func platformColor(fromRGBAComponents components: Any?) -> PlatformColor? { let colorClass: AnyObject = NSColor.self - return unsafeBitCast(colorClass, to: LookinDisplayItemColorBridge.self).lookin_colorFromRGBAComponents(components as AnyObject?) as? LookinColor + return unsafeBitCast(colorClass, to: DisplayItemColorBridge.self).sRGBColorFromRGBAComponents(components as AnyObject?) as? PlatformColor } #endif /// The screenshot decode of -initWithCoder:: PNG/TIFF data, or the image /// object itself. - private func lookinDecodedScreenshot(_ screenshotObj: Any?) -> LookinImage?? { + private func decodedScreenshot(_ screenshotObj: Any?) -> PlatformImage?? { guard let screenshotObj = screenshotObj as? NSObject else { return .none } if screenshotObj.isKind(of: NSData.self) { - return .some(screenshotObj.lookin_decodedObject(with: .image) as? LookinImage) + return .some(screenshotObj.decodedObject(with: .image) as? PlatformImage) } - if let image = screenshotObj as? LookinImage { + if let image = screenshotObj as? PlatformImage { return .some(image) } assertionFailure() @@ -86,24 +86,24 @@ /// Was declared in LookinDisplayItem.h; same runtime name and selector. @objc(LookinDisplayItemDelegate) - public protocol LookinDisplayItemDelegate: NSObjectProtocol { + public protocol DisplayItemDelegate: NSObjectProtocol { @objc(displayItem:propertyDidChange:) - func displayItem(_ displayItem: LookinDisplayItem!, propertyDidChange property: LookinDisplayItemProperty) + func displayItem(_ displayItem: DisplayItem, propertyDidChange property: LookinDisplayItemProperty) } @objc(LookinDisplayItem) - public class LookinDisplayItem: NSObject, NSCoding, NSSecureCoding, NSCopying { + public class DisplayItem: NSObject, NSCoding, NSSecureCoding, NSCopying { // MARK: Storage behind the setters with side effects - private var _subitems: [LookinDisplayItem]? + private var _subitems: [DisplayItem]? private var _isHidden: Bool = false private var _alpha: Float = 0 private var _frame: CGRect = .zero private var _bounds: CGRect = .zero - private var _soloScreenshot: LookinImage? - private var _groupScreenshot: LookinImage? - private var _attributesGroupList: [LookinAttributesGroup]? - private var _customAttrGroupList: [LookinAttributesGroup]? + private var _soloScreenshot: PlatformImage? + private var _groupScreenshot: PlatformImage? + private var _attributesGroupList: [AttributesGroup]? + private var _customAttrGroupList: [AttributesGroup]? private var _isExpanded: Bool = false private var _isExpandable: Bool = false private var _displayingInHierarchy: Bool = false @@ -121,44 +121,44 @@ // MARK: Plain properties @objc(customInfo) - public var customInfo: LookinCustomDisplayItemInfo! + public var customInfo: CustomDisplayItemInfo? @objc(nodeKind) public var nodeKind: LookinDisplayItemNodeKind = .unspecified @objc(kindObject) - public var kindObject: LookinObject! + public var kindObject: InspectedObject? @objc(representsSystemManagedNode) public var representsSystemManagedNode: Bool = false @objc(cellObject) - public var cellObject: LookinObject! + public var cellObject: InspectedObject? @objc(soloScreenshotRegion) public var soloScreenshotRegion: CGRect = .zero @objc(groupScreenshotRegion) public var groupScreenshotRegion: CGRect = .zero @objc(windowObject) - public var windowObject: LookinObject! + public var windowObject: InspectedObject? @objc(viewObject) - public var viewObject: LookinObject! + public var viewObject: InspectedObject? @objc(layerObject) - public var layerObject: LookinObject! + public var layerObject: InspectedObject? @objc(hostViewControllerObject) - public var hostViewControllerObject: LookinObject! + public var hostViewControllerObject: InspectedObject? @objc(hostWindowControllerObject) - public var hostWindowControllerObject: LookinObject! + public var hostWindowControllerObject: InspectedObject? @objc(eventHandlers) - public var eventHandlers: [LookinEventHandler]! + public var eventHandlers: [EventHandlerDescription]? @objc(representedAsKeyWindow) public var representedAsKeyWindow: Bool = false @objc(backgroundColor) - public var backgroundColor: LookinColor! + public var backgroundColor: PlatformColor? @objc(shouldCaptureImage) public var shouldCaptureImage: Bool = false @objc(customDisplayTitle) - public var customDisplayTitle: String! + public var customDisplayTitle: String? @objc(danceuiSource) - public var danceuiSource: String! + public var danceuiSource: String? /// `superItem` in Objective-C; `super` in Swift, the name the old /// header's import gave it. - @objc(superItem) public weak var `super`: LookinDisplayItem? + @objc(superItem) public weak var `super`: DisplayItem? @objc(screenshotEncodeType) public var screenshotEncodeType: LookinDisplayItemImageEncodeType = .none // `previewLayer` and `previewNode` keep their Objective-C accessors @@ -194,9 +194,9 @@ @objc(copyWithZone:) public func copy(with _: NSZone? = nil) -> Any { - let newDisplayItem = LookinDisplayItem() - newDisplayItem.subitems = subitems?.map { $0.copy() as! LookinDisplayItem } - newDisplayItem.customInfo = customInfo?.copy() as? LookinCustomDisplayItemInfo + let newDisplayItem = DisplayItem() + newDisplayItem.subitems = subitems?.map { $0.copy() as! DisplayItem } + newDisplayItem.customInfo = customInfo?.copy() as? CustomDisplayItemInfo newDisplayItem.isHidden = isHidden newDisplayItem.alpha = alpha newDisplayItem.frame = frame @@ -208,18 +208,18 @@ newDisplayItem.groupScreenshot = groupScreenshot newDisplayItem.soloScreenshotRegion = soloScreenshotRegion newDisplayItem.groupScreenshotRegion = groupScreenshotRegion - newDisplayItem.viewObject = viewObject?.copy() as? LookinObject - newDisplayItem.layerObject = layerObject?.copy() as? LookinObject - newDisplayItem.windowObject = windowObject?.copy() as? LookinObject + newDisplayItem.viewObject = viewObject?.copy() as? InspectedObject + newDisplayItem.layerObject = layerObject?.copy() as? InspectedObject + newDisplayItem.windowObject = windowObject?.copy() as? InspectedObject newDisplayItem.nodeKind = nodeKind - newDisplayItem.kindObject = kindObject?.copy() as? LookinObject + newDisplayItem.kindObject = kindObject?.copy() as? InspectedObject newDisplayItem.representsSystemManagedNode = representsSystemManagedNode - newDisplayItem.cellObject = cellObject?.copy() as? LookinObject - newDisplayItem.hostViewControllerObject = hostViewControllerObject?.copy() as? LookinObject - newDisplayItem.hostWindowControllerObject = hostWindowControllerObject?.copy() as? LookinObject - newDisplayItem.attributesGroupList = attributesGroupList?.map { $0.copy() as! LookinAttributesGroup } - newDisplayItem.customAttrGroupList = customAttrGroupList?.map { $0.copy() as! LookinAttributesGroup } - newDisplayItem.eventHandlers = eventHandlers?.map { ($0 as NSObject).copy() as! LookinEventHandler } + newDisplayItem.cellObject = cellObject?.copy() as? InspectedObject + newDisplayItem.hostViewControllerObject = hostViewControllerObject?.copy() as? InspectedObject + newDisplayItem.hostWindowControllerObject = hostWindowControllerObject?.copy() as? InspectedObject + newDisplayItem.attributesGroupList = attributesGroupList?.map { $0.copy() as! AttributesGroup } + newDisplayItem.customAttrGroupList = customAttrGroupList?.map { $0.copy() as! AttributesGroup } + newDisplayItem.eventHandlers = eventHandlers?.map { ($0 as NSObject).copy() as! EventHandlerDescription } newDisplayItem.shouldCaptureImage = shouldCaptureImage newDisplayItem.representedAsKeyWindow = representedAsKeyWindow newDisplayItem.customDisplayTitle = customDisplayTitle @@ -254,8 +254,8 @@ aCoder.encode(eventHandlers, forKey: "eventHandlers") aCoder.encode(shouldCaptureImage, forKey: "shouldCaptureImage") if screenshotEncodeType == .nsData { - aCoder.encode(soloScreenshot?.lookin_encodedObject(with: .image), forKey: "soloScreenshot") - aCoder.encode(groupScreenshot?.lookin_encodedObject(with: .image), forKey: "groupScreenshot") + aCoder.encode(soloScreenshot?.encodedObject(with: .image), forKey: "soloScreenshot") + aCoder.encode(groupScreenshot?.encodedObject(with: .image), forKey: "groupScreenshot") } else if screenshotEncodeType == .image { aCoder.encode(soloScreenshot, forKey: "soloScreenshot") aCoder.encode(groupScreenshot, forKey: "groupScreenshot") @@ -277,42 +277,42 @@ aCoder.encode(soloScreenshotRegion as NSRect, forKey: "soloScreenshotRegion") aCoder.encode(groupScreenshotRegion as NSRect, forKey: "groupScreenshotRegion") #endif - aCoder.encode(lookinRGBAComponents(of: backgroundColor), forKey: "backgroundColor") + aCoder.encode(rgbaComponents(of: backgroundColor), forKey: "backgroundColor") } public required init?(coder aDecoder: NSCoder) { super.init() - customInfo = aDecoder.decodeObject(forKey: "customInfo") as? LookinCustomDisplayItemInfo - subitems = aDecoder.decodeObject(forKey: "subitems") as? [LookinDisplayItem] + customInfo = aDecoder.decodeObject(forKey: "customInfo") as? CustomDisplayItemInfo + subitems = aDecoder.decodeObject(forKey: "subitems") as? [DisplayItem] isHidden = aDecoder.decodeBool(forKey: "hidden") alpha = aDecoder.decodeFloat(forKey: "alpha") #if os(macOS) isFlipped = aDecoder.decodeBool(forKey: "isFlipped") #endif - windowObject = aDecoder.decodeObject(forKey: "windowObject") as? LookinObject - viewObject = aDecoder.decodeObject(forKey: "viewObject") as? LookinObject - layerObject = aDecoder.decodeObject(forKey: "layerObject") as? LookinObject + windowObject = aDecoder.decodeObject(forKey: "windowObject") as? InspectedObject + viewObject = aDecoder.decodeObject(forKey: "viewObject") as? InspectedObject + layerObject = aDecoder.decodeObject(forKey: "layerObject") as? InspectedObject // These fields exist since the nodeKind mechanism landed; absent keys // decode to Unspecified / nil / NO, which is exactly the legacy-data // contract resolvedNodeKind derives from. nodeKind = aDecoder.containsValue(forKey: "nodeKind") ? (LookinDisplayItemNodeKind(rawValue: aDecoder.decodeInteger(forKey: "nodeKind")) ?? .unspecified) : .unspecified - kindObject = aDecoder.decodeObject(forKey: "kindObject") as? LookinObject + kindObject = aDecoder.decodeObject(forKey: "kindObject") as? InspectedObject representsSystemManagedNode = aDecoder.decodeBool(forKey: "representsSystemManagedNode") - cellObject = aDecoder.decodeObject(forKey: "cellObject") as? LookinObject - hostViewControllerObject = aDecoder.decodeObject(forKey: "hostViewControllerObject") as? LookinObject - hostWindowControllerObject = aDecoder.decodeObject(forKey: "hostWindowControllerObject") as? LookinObject - attributesGroupList = aDecoder.decodeObject(forKey: "attributesGroupList") as? [LookinAttributesGroup] - customAttrGroupList = aDecoder.decodeObject(forKey: "customAttrGroupList") as? [LookinAttributesGroup] + cellObject = aDecoder.decodeObject(forKey: "cellObject") as? InspectedObject + hostViewControllerObject = aDecoder.decodeObject(forKey: "hostViewControllerObject") as? InspectedObject + hostWindowControllerObject = aDecoder.decodeObject(forKey: "hostWindowControllerObject") as? InspectedObject + attributesGroupList = aDecoder.decodeObject(forKey: "attributesGroupList") as? [AttributesGroup] + customAttrGroupList = aDecoder.decodeObject(forKey: "customAttrGroupList") as? [AttributesGroup] representedAsKeyWindow = aDecoder.decodeBool(forKey: "representedAsKeyWindow") - if case let .some(decoded) = lookinDecodedScreenshot(aDecoder.decodeObject(forKey: "soloScreenshot")) { + if case let .some(decoded) = decodedScreenshot(aDecoder.decodeObject(forKey: "soloScreenshot")) { soloScreenshot = decoded } - if case let .some(decoded) = lookinDecodedScreenshot(aDecoder.decodeObject(forKey: "groupScreenshot")) { + if case let .some(decoded) = decodedScreenshot(aDecoder.decodeObject(forKey: "groupScreenshot")) { groupScreenshot = decoded } - eventHandlers = aDecoder.decodeObject(forKey: "eventHandlers") as? [LookinEventHandler] + eventHandlers = aDecoder.decodeObject(forKey: "eventHandlers") as? [EventHandlerDescription] // Added in LookinServer 1.1.3. shouldCaptureImage = aDecoder.containsValue(forKey: "shouldCaptureImage") ? aDecoder.decodeBool(forKey: "shouldCaptureImage") : true customDisplayTitle = aDecoder.decodeObject(forKey: "customDisplayTitle") as? String @@ -330,7 +330,7 @@ soloScreenshotRegion = aDecoder.decodeRect(forKey: "soloScreenshotRegion") groupScreenshotRegion = aDecoder.decodeRect(forKey: "groupScreenshotRegion") #endif - backgroundColor = lookinColor(fromRGBAComponents: aDecoder.decodeObject(forKey: "backgroundColor")) + backgroundColor = platformColor(fromRGBAComponents: aDecoder.decodeObject(forKey: "backgroundColor")) _updateDisplayingInHierarchyProperty() } @@ -342,7 +342,7 @@ // MARK: Node kind @objc(displayingObject) - public func displayingObject() -> LookinObject! { + public func displayingObject() -> InspectedObject? { kindObject ?? windowObject ?? viewObject ?? layerObject } @@ -359,7 +359,7 @@ return .custom } if let windowObject, viewObject == nil, layerObject == nil { - let representsWindowScene = (windowObject.classChainList ?? []).contains { lookinStringsEqual($0, "UIWindowScene") } + let representsWindowScene = (windowObject.classChainList ?? []).contains { stringsEqual($0, "UIWindowScene") } return representsWindowScene ? .windowScene : .window } if viewObject != nil { @@ -490,27 +490,27 @@ // MARK: Attributes @objc(attributesGroupList) - public var attributesGroupList: [LookinAttributesGroup]! { + public var attributesGroupList: [AttributesGroup]? { get { _attributesGroupList } set { _attributesGroupList = newValue - lookinAssignTargetDisplayItem(self, in: newValue) + assignTargetDisplayItem(self, in: newValue) } } @objc(customAttrGroupList) - public var customAttrGroupList: [LookinAttributesGroup]! { + public var customAttrGroupList: [AttributesGroup]? { get { _customAttrGroupList } set { _customAttrGroupList = newValue // Already sorted when it is passed in. - lookinAssignTargetDisplayItem(self, in: newValue) + assignTargetDisplayItem(self, in: newValue) } } @objc(queryAllAttrGroupList) - public func queryAllAttrGroupList() -> [LookinAttributesGroup]! { - var array: [LookinAttributesGroup] = [] + public func queryAllAttrGroupList() -> [AttributesGroup] { + var array: [AttributesGroup] = [] if let attributesGroupList { array.append(contentsOf: attributesGroupList) } @@ -523,7 +523,7 @@ // MARK: Tree @objc(subitems) - public var subitems: [LookinDisplayItem]! { + public var subitems: [DisplayItem]? { get { _subitems } set { for obj in _subitems ?? [] { @@ -603,8 +603,8 @@ } @objc(flatItemsFromHierarchicalItems:) - public class func flatItems(fromHierarchicalItems items: [LookinDisplayItem]?) -> [LookinDisplayItem]! { - var resultArray: [LookinDisplayItem] = [] + public class func flatItems(fromHierarchicalItems items: [DisplayItem]?) -> [DisplayItem] { + var resultArray: [DisplayItem] = [] for obj in items ?? [] { if let superItem = obj.super { @@ -612,7 +612,7 @@ } resultArray.append(obj) if let subitems = obj.subitems, !subitems.isEmpty { - resultArray.append(contentsOf: flatItems(fromHierarchicalItems: subitems) ?? []) + resultArray.append(contentsOf: flatItems(fromHierarchicalItems: subitems)) } } @@ -702,7 +702,7 @@ // MARK: Screenshots @objc(soloScreenshot) - public var soloScreenshot: LookinImage! { + public var soloScreenshot: PlatformImage? { get { _soloScreenshot } set { if _soloScreenshot === newValue { @@ -714,7 +714,7 @@ } @objc(groupScreenshot) - public var groupScreenshot: LookinImage! { + public var groupScreenshot: PlatformImage? { get { _groupScreenshot } set { if _groupScreenshot === newValue { @@ -740,9 +740,9 @@ // MARK: Delegates @objc(previewItemDelegate) - public weak var previewItemDelegate: (any LookinDisplayItemDelegate)? { + public weak var previewItemDelegate: (any DisplayItemDelegate)? { didSet { - guard let previewItemDelegate, previewItemDelegate.responds(to: #selector(LookinDisplayItemDelegate.displayItem(_:propertyDidChange:))) else { + guard let previewItemDelegate, previewItemDelegate.responds(to: #selector(DisplayItemDelegate.displayItem(_:propertyDidChange:))) else { assertionFailure() previewItemDelegate = nil return @@ -752,13 +752,13 @@ } @objc(rowViewDelegate) - public weak var rowViewDelegate: (any LookinDisplayItemDelegate)? { + public weak var rowViewDelegate: (any DisplayItemDelegate)? { didSet { // The original returned before assigning an identical delegate. if oldValue === rowViewDelegate { return } - guard let rowViewDelegate, rowViewDelegate.responds(to: #selector(LookinDisplayItemDelegate.displayItem(_:propertyDidChange:))) else { + guard let rowViewDelegate, rowViewDelegate.responds(to: #selector(DisplayItemDelegate.displayItem(_:propertyDidChange:))) else { assertionFailure() rowViewDelegate = nil return @@ -794,7 +794,7 @@ } @objc(highlightedSearchString) - public var highlightedSearchString: String! { + public var highlightedSearchString: String? { get { _highlightedSearchString } set { _highlightedSearchString = newValue @@ -821,7 +821,7 @@ /// Points every attribute of `groups` back at `item` (the original's /// nested enumeration in the two group-list setters). - private func lookinAssignTargetDisplayItem(_ item: LookinDisplayItem, in groups: [LookinAttributesGroup]?) { + private func assignTargetDisplayItem(_ item: DisplayItem, in groups: [AttributesGroup]?) { for group in groups ?? [] { for section in group.attrSections ?? [] { for attr in section.attributes ?? [] { diff --git a/Sources/LookinCoreImpl/LookinDisplayItemDetail.swift b/Sources/LookinCoreImpl/DisplayItemDetail.swift similarity index 75% rename from Sources/LookinCoreImpl/LookinDisplayItemDetail.swift rename to Sources/LookinCoreImpl/DisplayItemDetail.swift index 61c894a4..e4eeebd6 100644 --- a/Sources/LookinCoreImpl/LookinDisplayItemDetail.swift +++ b/Sources/LookinCoreImpl/DisplayItemDetail.swift @@ -1,5 +1,5 @@ // -// LookinDisplayItemDetail.swift +// DisplayItemDetail.swift // Lookin // // Was LookinDisplayItemDetail.m: the 203 reply. The coding keys, the @@ -20,31 +20,31 @@ #endif @objc(LookinDisplayItemDetail) - public class LookinDisplayItemDetail: NSObject, NSCoding, NSSecureCoding { + public class DisplayItemDetail: NSObject, NSCoding, NSSecureCoding { @objc(displayItemOid) public var displayItemOid: UInt = 0 @objc(groupScreenshot) - public var groupScreenshot: LookinImage! + public var groupScreenshot: PlatformImage? @objc(soloScreenshot) - public var soloScreenshot: LookinImage! + public var soloScreenshot: PlatformImage? @objc(frameValue) - public var frameValue: NSValue! + public var frameValue: NSValue? @objc(boundsValue) - public var boundsValue: NSValue! + public var boundsValue: NSValue? @objc(hiddenValue) - public var hiddenValue: NSNumber! + public var hiddenValue: NSNumber? @objc(alphaValue) - public var alphaValue: NSNumber! + public var alphaValue: NSNumber? @objc(customDisplayTitle) - public var customDisplayTitle: String! + public var customDisplayTitle: String? @objc(danceUISource) - public var danceUISource: String! + public var danceUISource: String? @objc(attributesGroupList) - public var attributesGroupList: [LookinAttributesGroup]! + public var attributesGroupList: [AttributesGroup]? @objc(customAttrGroupList) - public var customAttrGroupList: [LookinAttributesGroup]! + public var customAttrGroupList: [AttributesGroup]? @objc(subitems) - public var subitems: [LookinDisplayItem]! + public var subitems: [DisplayItem]? @objc(failureCode) public var failureCode: Int = 0 @@ -57,8 +57,8 @@ @objc(encodeWithCoder:) public func encode(with aCoder: NSCoder) { aCoder.encode(NSNumber(value: displayItemOid), forKey: "displayItemOid") - aCoder.encode(lookinScreenshotData(groupScreenshot), forKey: "groupScreenshot") - aCoder.encode(lookinScreenshotData(soloScreenshot), forKey: "soloScreenshot") + aCoder.encode(screenshotData(groupScreenshot), forKey: "groupScreenshot") + aCoder.encode(screenshotData(soloScreenshot), forKey: "soloScreenshot") aCoder.encode(frameValue, forKey: "frameValue") aCoder.encode(boundsValue, forKey: "boundsValue") aCoder.encode(hiddenValue, forKey: "hiddenValue") @@ -76,14 +76,14 @@ public required init?(coder aDecoder: NSCoder) { super.init() displayItemOid = (aDecoder.decodeObject(forKey: "displayItemOid") as? NSNumber)?.uintValue ?? 0 - groupScreenshot = (aDecoder.decodeObject(forKey: "groupScreenshot") as? Data).flatMap { LookinImage(data: $0) } - soloScreenshot = (aDecoder.decodeObject(forKey: "soloScreenshot") as? Data).flatMap { LookinImage(data: $0) } + groupScreenshot = (aDecoder.decodeObject(forKey: "groupScreenshot") as? Data).flatMap { PlatformImage(data: $0) } + soloScreenshot = (aDecoder.decodeObject(forKey: "soloScreenshot") as? Data).flatMap { PlatformImage(data: $0) } frameValue = aDecoder.decodeObject(forKey: "frameValue") as? NSValue boundsValue = aDecoder.decodeObject(forKey: "boundsValue") as? NSValue hiddenValue = aDecoder.decodeObject(forKey: "hiddenValue") as? NSNumber alphaValue = aDecoder.decodeObject(forKey: "alphaValue") as? NSNumber - attributesGroupList = aDecoder.decodeObject(forKey: "attributesGroupList") as? [LookinAttributesGroup] - customAttrGroupList = aDecoder.decodeObject(forKey: "customAttrGroupList") as? [LookinAttributesGroup] + attributesGroupList = aDecoder.decodeObject(forKey: "attributesGroupList") as? [AttributesGroup] + customAttrGroupList = aDecoder.decodeObject(forKey: "customAttrGroupList") as? [AttributesGroup] customDisplayTitle = aDecoder.decodeObject(forKey: "customDisplayTitle") as? String danceUISource = aDecoder.decodeObject(forKey: "danceUISource") as? String @@ -94,7 +94,7 @@ } if aDecoder.containsValue(forKey: "subitems") { - subitems = aDecoder.decodeObject(forKey: "subitems") as? [LookinDisplayItem] + subitems = aDecoder.decodeObject(forKey: "subitems") as? [DisplayItem] } } diff --git a/Sources/LookinCoreImpl/LookinEventHandler.swift b/Sources/LookinCoreImpl/EventHandlerDescription.swift similarity index 85% rename from Sources/LookinCoreImpl/LookinEventHandler.swift rename to Sources/LookinCoreImpl/EventHandlerDescription.swift index 03eca7ae..6710e88e 100644 --- a/Sources/LookinCoreImpl/LookinEventHandler.swift +++ b/Sources/LookinCoreImpl/EventHandlerDescription.swift @@ -1,5 +1,5 @@ // -// LookinEventHandler.swift +// EventHandlerDescription.swift // Lookin // // Was LookinEventHandler.m. @@ -14,21 +14,21 @@ #endif @objc(LookinEventHandler) - public class LookinEventHandler: NSObject, NSCoding, NSSecureCoding { + public class EventHandlerDescription: NSObject, NSCoding, NSSecureCoding { @objc(handlerType) public var handlerType: LookinEventHandlerType = .targetAction @objc(eventName) - public var eventName: String! + public var eventName: String? @objc(targetActions) - public var targetActions: [LookinStringTwoTuple]! + public var targetActions: [StringTwoTuple]? @objc(inheritedRecognizerName) - public var inheritedRecognizerName: String! + public var inheritedRecognizerName: String? @objc(gestureRecognizerIsEnabled) public var gestureRecognizerIsEnabled: Bool = false @objc(gestureRecognizerDelegator) - public var gestureRecognizerDelegator: String! + public var gestureRecognizerDelegator: String? @objc(recognizerIvarTraces) - public var recognizerIvarTraces: [String]! + public var recognizerIvarTraces: [String]? @objc(recognizerOid) public var recognizerOid: UInt64 = 0 @@ -39,13 +39,13 @@ // MARK: NSCopying /// The class does not adopt NSCopying, but the original implemented - /// -copyWithZone: (LookinDisplayItem copies its handlers with -copy). + /// -copyWithZone: (DisplayItem copies its handlers with -copy). @objc(copyWithZone:) final func copy(with _: NSZone? = nil) -> Any { - let newHandler = LookinEventHandler() + let newHandler = EventHandlerDescription() newHandler.handlerType = handlerType newHandler.eventName = eventName - newHandler.targetActions = targetActions?.map { $0.copy() as! LookinStringTwoTuple } + newHandler.targetActions = targetActions?.map { $0.copy() as! StringTwoTuple } newHandler.gestureRecognizerIsEnabled = gestureRecognizerIsEnabled newHandler.gestureRecognizerDelegator = gestureRecognizerDelegator newHandler.inheritedRecognizerName = inheritedRecognizerName @@ -74,7 +74,7 @@ gestureRecognizerIsEnabled = aDecoder.decodeBool(forKey: "gestureRecognizerIsEnabled") eventName = aDecoder.decodeObject(forKey: "eventName") as? String gestureRecognizerDelegator = aDecoder.decodeObject(forKey: "gestureRecognizerDelegator") as? String - targetActions = aDecoder.decodeObject(forKey: "targetActions") as? [LookinStringTwoTuple] + targetActions = aDecoder.decodeObject(forKey: "targetActions") as? [StringTwoTuple] inheritedRecognizerName = aDecoder.decodeObject(forKey: "inheritedRecognizerName") as? String recognizerIvarTraces = aDecoder.decodeObject(forKey: "recognizerIvarTraces") as? [String] // The original read it back through -unsignedLongValue. diff --git a/Sources/LookinCoreImpl/LookinHierarchyFile.swift b/Sources/LookinCoreImpl/HierarchyFile.swift similarity index 88% rename from Sources/LookinCoreImpl/LookinHierarchyFile.swift rename to Sources/LookinCoreImpl/HierarchyFile.swift index a274cd10..259d344a 100644 --- a/Sources/LookinCoreImpl/LookinHierarchyFile.swift +++ b/Sources/LookinCoreImpl/HierarchyFile.swift @@ -1,5 +1,5 @@ // -// LookinHierarchyFile.swift +// HierarchyFile.swift // Lookin // // Was LookinHierarchyFile.m, @@ -15,11 +15,11 @@ #endif @objc(LookinHierarchyFile) - public class LookinHierarchyFile: NSObject, NSCoding, NSSecureCoding { + public class HierarchyFile: NSObject, NSCoding, NSSecureCoding { @objc(serverVersion) public var serverVersion: Int32 = 0 @objc(hierarchyInfo) - public var hierarchyInfo: LookinHierarchyInfo! + public var hierarchyInfo: HierarchyInfo? /// The screenshot dictionaries are kept as the Foundation objects they /// were set or decoded as. Bridging them through `[NSNumber: Data]` /// would turn the NSMutableData values a .lookin document holds into @@ -29,13 +29,13 @@ private var _groupScreenshots: NSDictionary? @objc(soloScreenshots) - public var soloScreenshots: [NSNumber: Data]! { + public var soloScreenshots: [NSNumber: Data]? { get { _soloScreenshots as? [NSNumber: Data] } set { _soloScreenshots = newValue.map { $0 as NSDictionary } } } @objc(groupScreenshots) - public var groupScreenshots: [NSNumber: Data]! { + public var groupScreenshots: [NSNumber: Data]? { get { _groupScreenshots as? [NSNumber: Data] } set { _groupScreenshots = newValue.map { $0 as NSDictionary } } } @@ -57,7 +57,7 @@ public required init?(coder aDecoder: NSCoder) { super.init() serverVersion = aDecoder.decodeCInt(forKey: "serverVersion") - hierarchyInfo = aDecoder.decodeObject(forKey: "hierarchyInfo") as? LookinHierarchyInfo + hierarchyInfo = aDecoder.decodeObject(forKey: "hierarchyInfo") as? HierarchyInfo _soloScreenshots = aDecoder.decodeObject(forKey: "soloScreenshots") as? NSDictionary _groupScreenshots = aDecoder.decodeObject(forKey: "groupScreenshots") as? NSDictionary } @@ -68,8 +68,8 @@ } @objc(verifyHierarchyFile:) - public class func verifyHierarchyFile(_ hierarchyFile: LookinHierarchyFile?) -> (any Error)! { - guard let hierarchyFile, hierarchyFile.isKind(of: LookinHierarchyFile.self) else { + public class func verifyHierarchyFile(_ hierarchyFile: HierarchyFile?) -> (any Error)? { + guard let hierarchyFile, hierarchyFile.isKind(of: HierarchyFile.self) else { return LookinErr_Inner } diff --git a/Sources/LookinCoreImpl/LookinHierarchyInfo.swift b/Sources/LookinCoreImpl/HierarchyInfo.swift similarity index 56% rename from Sources/LookinCoreImpl/LookinHierarchyInfo.swift rename to Sources/LookinCoreImpl/HierarchyInfo.swift index b0f76c0a..e291e1d0 100644 --- a/Sources/LookinCoreImpl/LookinHierarchyInfo.swift +++ b/Sources/LookinCoreImpl/HierarchyInfo.swift @@ -1,5 +1,5 @@ // -// LookinHierarchyInfo.swift +// HierarchyInfo.swift // WeRead // // Was LookinHierarchyInfo.m: @@ -14,51 +14,51 @@ import LookinCore #endif - private let LookinHierarchyInfoCodingKey_DisplayItems = "1" - private let LookinHierarchyInfoCodingKey_AppInfo = "2" - private let LookinHierarchyInfoCodingKey_ColorAlias = "3" - private let LookinHierarchyInfoCodingKey_CollapsedClassList = "4" + private let displayItemsCodingKey = "1" + private let appInfoCodingKey = "2" + private let colorAliasCodingKey = "3" + private let collapsedClassListCodingKey = "4" /// `+[LKS_HierarchyDisplayItemsMaker itemsWithScreenshots:attrList:lowImageQuality:readCustomInfo:saveCustomSetter:]`. /// LookinCore does not link against the server, so the maker is looked up /// and called through the runtime; without it (the host) the list is empty. - private func lookinDisplayItems(screenshots hasScreenshots: Bool, attrList hasAttrList: Bool, lowImageQuality lowQuality: Bool, readCustomInfo: Bool, saveCustomSetter: Bool) -> [LookinDisplayItem] { + private func makeDisplayItems(screenshots hasScreenshots: Bool, attrList hasAttrList: Bool, lowImageQuality lowQuality: Bool, readCustomInfo: Bool, saveCustomSetter: Bool) -> [DisplayItem] { let selector = NSSelectorFromString("itemsWithScreenshots:attrList:lowImageQuality:readCustomInfo:saveCustomSetter:") guard let makerClass = NSClassFromString("LKS_HierarchyDisplayItemsMaker"), (makerClass as AnyObject).responds(to: selector) else { return [] } let arguments = [hasScreenshots, hasAttrList, lowQuality, readCustomInfo, saveCustomSetter].map { NSNumber(value: $0) } let items = LookinInvoke(makerClass, selector, arguments, nil) - return (items as? [LookinDisplayItem]) ?? [] + return (items as? [DisplayItem]) ?? [] } @objc(LookinHierarchyInfo) - public class LookinHierarchyInfo: NSObject, NSCoding, NSSecureCoding, NSCopying { + public class HierarchyInfo: NSObject, NSCoding, NSSecureCoding, NSCopying { @objc(displayItems) - public var displayItems: [LookinDisplayItem]! + public var displayItems: [DisplayItem]? @objc(colorAlias) - public var colorAlias: [String: Any]! + public var colorAlias: [String: Any]? @objc(collapsedClassList) - public var collapsedClassList: [String]! + public var collapsedClassList: [String]? @objc(appInfo) - public var appInfo: LookinAppInfo! + public var appInfo: InspectedAppInfo? @objc(serverVersion) public var serverVersion: Int32 = 0 /// `+staticInfoWithLookinVersion:`. `version` is nil for clients older /// than 1.0.4. An Objective-C factory must be a class method here. @objc(staticInfoWithLookinVersion:) - public class func staticInfo(withLookinVersion version: String?) -> Self! { + public class func staticInfo(withLookinVersion version: String?) -> Self { var readCustomInfo = false // Clients support customInfo from 1.0.4 on. - if let version, (version as NSString).lookin_numbericOSVersion() >= 10004 { + if let version, (version as NSString).numericOSVersion() >= 10004 { readCustomInfo = true } let info = unsafeDowncast((self as NSObject.Type).init(), to: self) info.serverVersion = Int32(LOOKIN_SERVER_VERSION) - info.displayItems = lookinDisplayItems(screenshots: false, attrList: false, lowImageQuality: false, readCustomInfo: readCustomInfo, saveCustomSetter: true) - info.appInfo = LookinAppInfo.currentInfo(withScreenshot: false, icon: true, localIdentifiers: nil) + info.displayItems = makeDisplayItems(screenshots: false, attrList: false, lowImageQuality: false, readCustomInfo: readCustomInfo, saveCustomSetter: true) + info.appInfo = InspectedAppInfo.currentInfo(withScreenshot: false, icon: true, localIdentifiers: nil) info.collapsedClassList = [] info.colorAlias = [:] return info @@ -66,11 +66,11 @@ /// `+exportedInfo`. @objc(exportedInfo) - public class func exported() -> Self! { + public class func exported() -> Self { let info = unsafeDowncast((self as NSObject.Type).init(), to: self) info.serverVersion = Int32(LOOKIN_SERVER_VERSION) - info.displayItems = lookinDisplayItems(screenshots: true, attrList: true, lowImageQuality: true, readCustomInfo: true, saveCustomSetter: false) - info.appInfo = LookinAppInfo.currentInfo(withScreenshot: false, icon: true, localIdentifiers: nil) + info.displayItems = makeDisplayItems(screenshots: true, attrList: true, lowImageQuality: true, readCustomInfo: true, saveCustomSetter: false) + info.appInfo = InspectedAppInfo.currentInfo(withScreenshot: false, icon: true, localIdentifiers: nil) info.collapsedClassList = [] info.colorAlias = [:] return info @@ -84,19 +84,19 @@ @objc(encodeWithCoder:) public func encode(with aCoder: NSCoder) { - aCoder.encode(displayItems, forKey: LookinHierarchyInfoCodingKey_DisplayItems) - aCoder.encode(colorAlias, forKey: LookinHierarchyInfoCodingKey_ColorAlias) - aCoder.encode(collapsedClassList, forKey: LookinHierarchyInfoCodingKey_CollapsedClassList) - aCoder.encode(appInfo, forKey: LookinHierarchyInfoCodingKey_AppInfo) + aCoder.encode(displayItems, forKey: displayItemsCodingKey) + aCoder.encode(colorAlias, forKey: colorAliasCodingKey) + aCoder.encode(collapsedClassList, forKey: collapsedClassListCodingKey) + aCoder.encode(appInfo, forKey: appInfoCodingKey) aCoder.encodeCInt(serverVersion, forKey: "serverVersion") } public required init?(coder aDecoder: NSCoder) { super.init() - displayItems = aDecoder.decodeObject(forKey: LookinHierarchyInfoCodingKey_DisplayItems) as? [LookinDisplayItem] - colorAlias = aDecoder.decodeObject(forKey: LookinHierarchyInfoCodingKey_ColorAlias) as? [String: Any] - collapsedClassList = aDecoder.decodeObject(forKey: LookinHierarchyInfoCodingKey_CollapsedClassList) as? [String] - appInfo = aDecoder.decodeObject(forKey: LookinHierarchyInfoCodingKey_AppInfo) as? LookinAppInfo + displayItems = aDecoder.decodeObject(forKey: displayItemsCodingKey) as? [DisplayItem] + colorAlias = aDecoder.decodeObject(forKey: colorAliasCodingKey) as? [String: Any] + collapsedClassList = aDecoder.decodeObject(forKey: collapsedClassListCodingKey) as? [String] + appInfo = aDecoder.decodeObject(forKey: appInfoCodingKey) as? InspectedAppInfo serverVersion = aDecoder.decodeCInt(forKey: "serverVersion") } @@ -109,12 +109,12 @@ @objc(copyWithZone:) public func copy(with _: NSZone? = nil) -> Any { - let newAppInfo = LookinHierarchyInfo() + let newAppInfo = HierarchyInfo() newAppInfo.serverVersion = serverVersion - newAppInfo.appInfo = appInfo?.copy() as? LookinAppInfo + newAppInfo.appInfo = appInfo?.copy() as? InspectedAppInfo newAppInfo.collapsedClassList = collapsedClassList newAppInfo.colorAlias = colorAlias - newAppInfo.displayItems = displayItems?.map { $0.copy() as! LookinDisplayItem } + newAppInfo.displayItems = displayItems?.map { $0.copy() as! DisplayItem } return newAppInfo } } diff --git a/Sources/LookinCoreImpl/LookinAppInfo.swift b/Sources/LookinCoreImpl/InspectedAppInfo.swift similarity index 84% rename from Sources/LookinCoreImpl/LookinAppInfo.swift rename to Sources/LookinCoreImpl/InspectedAppInfo.swift index 244a8799..1788e6b1 100644 --- a/Sources/LookinCoreImpl/LookinAppInfo.swift +++ b/Sources/LookinCoreImpl/InspectedAppInfo.swift @@ -1,5 +1,5 @@ // -// LookinAppInfo.swift +// InspectedAppInfo.swift // qmuidemo // // Was LookinAppInfo.m: the 201 @@ -29,7 +29,7 @@ private let CodingKey_DeviceType = "8" /// Reads a sysctl entry as a string, or nil when it is unavailable or empty. - private func LookinAppInfoSysctlStringValue(_ sysctlName: String) -> String? { + private func sysctlStringValue(_ sysctlName: String) -> String? { var valueSize = 0 if sysctlbyname(sysctlName, nil, &valueSize, nil, 0) != 0 || valueSize == 0 { return nil @@ -52,7 +52,7 @@ /// Needed because -[UIDevice name] answers the literal string "iPad" on /// Catalyst. That names a device family, not this machine, so it /// identifies nothing to the person reading the host's device label. - private func LookinAppInfoMacHostLocalizedName() -> String? { + private func macHostLocalizedName() -> String? { let currentHostSelector = NSSelectorFromString("currentHost") guard let hostClass = NSClassFromString("NSHost"), (hostClass as AnyObject).responds(to: currentHostSelector) else { return nil @@ -76,7 +76,7 @@ /// `+getAppInfoIdentifier`: random per launch, stable until the app is /// killed. - private let LookinAppInfoIdentifier: Int = { + private let processAppInfoIdentifier: Int = { let nowMicros = UInt64(Date().timeIntervalSince1970 * 1_000_000.0) let processID = UInt64(ProcessInfo.processInfo.processIdentifier) let randomBits = UInt64(arc4random()) @@ -90,7 +90,7 @@ /// `+currentDeviceModelIdentifier`: the hardware model identifier of the /// device this process runs on, e.g. "iPhone16,2". Nil when it cannot be /// determined, which callers must tolerate. - private let LookinAppInfoDeviceModelIdentifier: String? = { + private let currentDeviceModelIdentifier: String? = { #if targetEnvironment(simulator) // hw.machine reports the *host* Mac's architecture ("arm64") inside a // simulator, which identifies no device at all. The simulated model is @@ -99,14 +99,14 @@ #elseif os(macOS) || targetEnvironment(macCatalyst) // On macOS hw.machine is the CPU architecture; the Mac model lives in // hw.model. - return LookinAppInfoSysctlStringValue("hw.model") + return sysctlStringValue("hw.model") #else - return LookinAppInfoSysctlStringValue("hw.machine") + return sysctlStringValue("hw.machine") #endif }() /// `+isSimulator`. - private func LookinAppInfoIsSimulator() -> Bool { + private func isRunningInSimulator() -> Bool { #if targetEnvironment(simulator) return true #else @@ -114,7 +114,7 @@ #endif } - private func LookinAppInfoAppName() -> String { + private func currentAppName() -> String { let info = Bundle.main.infoDictionary if let displayName = info?["CFBundleDisplayName"] as? NSString, displayName.length > 0 { return displayName as String @@ -125,7 +125,7 @@ return ProcessInfo.processInfo.processName } - private func LookinAppInfoAppIcon() -> LookinImage? { + private func currentAppIcon() -> PlatformImage? { #if os(tvOS) return nil #elseif canImport(UIKit) @@ -150,10 +150,10 @@ #endif } - private func LookinAppInfoScreenshotImage() -> LookinImage? { + private func currentScreenshotImage() -> PlatformImage? { // The old header declared +keyWindow nonnull, but it answers nil whenever // no window is key; read it through the runtime so Swift sees the nil. - var window = (LKS_MultiplatformAdapter.self as AnyObject).perform(NSSelectorFromString("keyWindow"))?.takeUnretainedValue() as? LookinWindow + var window = (MultiplatformAdapter.self as AnyObject).perform(NSSelectorFromString("keyWindow"))?.takeUnretainedValue() as? PlatformWindow #if os(macOS) // keyWindow is nil on macOS while the app is inactive or in the // background. Fall back to the main window, then to any window. @@ -183,7 +183,7 @@ // ScreenCaptureKit is async and prompts for screen recording // permission; the synchronous CGWindowListCreateImage is enough to // capture this app's own window thumbnail. - guard let cgImage = LookinAppInfoWindowListImage(CGWindowID(window.windowNumber)) else { + guard let cgImage = windowListImage(CGWindowID(window.windowNumber)) else { return nil } return NSImage(cgImage: cgImage, size: window.frame.size) @@ -192,17 +192,17 @@ #if os(macOS) @available(macOS, deprecated: 14.0) - private func LookinAppInfoDeprecatedWindowListImage(_ windowID: CGWindowID) -> CGImage? { + private func deprecatedWindowListImage(_ windowID: CGWindowID) -> CGImage? { CGWindowListCreateImage(.zero, .optionIncludingWindow, windowID, .boundsIgnoreFraming) } /// Calls the deprecated CGWindowListCreateImage without a warning at /// every use site (the original silenced -Wdeprecated-declarations). - private let LookinAppInfoWindowListImage: (CGWindowID) -> CGImage? = LookinAppInfoDeprecatedWindowListImage + private let windowListImage: (CGWindowID) -> CGImage? = deprecatedWindowListImage #endif @objc(LookinAppInfo) - public class LookinAppInfo: NSObject, NSCoding, NSSecureCoding, NSCopying { + public class InspectedAppInfo: NSObject, NSCoding, NSSecureCoding, NSCopying { @objc(appInfoIdentifier) public var appInfoIdentifier: UInt = 0 @objc(shouldUseCache) @@ -212,23 +212,23 @@ /// Declared `assign` before the Swift rewrite (a dangling-pointer risk); /// strong now, with no change on the wire. @objc(serverReadableVersion) - public var serverReadableVersion: String! + public var serverReadableVersion: String? @objc(swiftEnabledInLookinServer) public var swiftEnabledInLookinServer: Int32 = 0 @objc(screenshot) - public var screenshot: LookinImage! + public var screenshot: PlatformImage? @objc(appIcon) - public var appIcon: LookinImage! + public var appIcon: PlatformImage? @objc(appName) - public var appName: String! + public var appName: String? @objc(appBundleIdentifier) - public var appBundleIdentifier: String! + public var appBundleIdentifier: String? @objc(deviceDescription) - public var deviceDescription: String! + public var deviceDescription: String? @objc(deviceModelIdentifier) - public var deviceModelIdentifier: String! + public var deviceModelIdentifier: String? @objc(osDescription) - public var osDescription: String! + public var osDescription: String? @objc(osMainVersion) public var osMainVersion: UInt = 0 @objc(deviceType) @@ -253,7 +253,7 @@ @objc(copyWithZone:) public func copy(with _: NSZone? = nil) -> Any { - let newAppInfo = LookinAppInfo() + let newAppInfo = InspectedAppInfo() newAppInfo.appIcon = appIcon newAppInfo.gestureDebugProtocolVersion = gestureDebugProtocolVersion newAppInfo.appName = appName @@ -279,10 +279,10 @@ swiftEnabledInLookinServer = aDecoder.decodeCInt(forKey: "swiftEnabledInLookinServer") gestureDebugProtocolVersion = UInt(bitPattern: aDecoder.decodeInteger(forKey: "gestureDebugProtocolVersion")) let screenshotData = aDecoder.decodeObject(forKey: CodingKey_Screenshot) as? Data - screenshot = screenshotData.flatMap { LookinImage(data: $0) } + screenshot = screenshotData.flatMap { PlatformImage(data: $0) } let appIconData = aDecoder.decodeObject(forKey: CodingKey_AppIcon) as? Data - appIcon = appIconData.flatMap { LookinImage(data: $0) } + appIcon = appIconData.flatMap { PlatformImage(data: $0) } appName = aDecoder.decodeObject(forKey: CodingKey_AppName) as? String appBundleIdentifier = aDecoder.decodeObject(forKey: "appBundleIdentifier") as? String @@ -306,16 +306,16 @@ aCoder.encode(Int(bitPattern: gestureDebugProtocolVersion), forKey: "gestureDebugProtocolVersion") #if canImport(UIKit) - let screenshotData = lookinPNGRepresentation(screenshot) + let screenshotData = pngRepresentation(screenshot) aCoder.encode(screenshotData, forKey: CodingKey_Screenshot) - let appIconData = lookinPNGRepresentation(appIcon) + let appIconData = pngRepresentation(appIcon) aCoder.encode(appIconData, forKey: CodingKey_AppIcon) #elseif os(macOS) - let screenshotData = lookinTIFFRepresentation(screenshot) + let screenshotData = tiffRepresentation(screenshot) aCoder.encode(screenshotData, forKey: CodingKey_Screenshot) - let appIconData = lookinTIFFRepresentation(appIcon) + let appIconData = tiffRepresentation(appIcon) aCoder.encode(appIconData, forKey: CodingKey_AppIcon) #endif @@ -344,40 +344,40 @@ if let object = object as? NSObject, object === self { return true } - guard let object = object as? LookinAppInfo else { + guard let object = object as? InspectedAppInfo else { return false } return isEqual(to: object) } override open var hash: Int { - lookinStringHash(appName) ^ lookinStringHash(deviceDescription) ^ lookinStringHash(osDescription) ^ deviceType.rawValue + stringHash(appName) ^ stringHash(deviceDescription) ^ stringHash(osDescription) ^ deviceType.rawValue } @objc(isEqualToAppInfo:) - public func isEqual(to info: LookinAppInfo?) -> Bool { + public func isEqual(to info: InspectedAppInfo?) -> Bool { guard let info else { return false } - return lookinStringsEqual(appName, info.appName) - && lookinStringsEqual(deviceDescription, info.deviceDescription) - && lookinStringsEqual(osDescription, info.osDescription) + return stringsEqual(appName, info.appName) + && stringsEqual(deviceDescription, info.deviceDescription) + && stringsEqual(osDescription, info.osDescription) && deviceType == info.deviceType } // MARK: Current app @objc(currentInfoWithScreenshot:icon:localIdentifiers:) - public class func currentInfo(withScreenshot hasScreenshot: Bool, icon hasIcon: Bool, localIdentifiers: [NSNumber]?) -> LookinAppInfo! { - let selfIdentifier = LookinAppInfoIdentifier + public class func currentInfo(withScreenshot hasScreenshot: Bool, icon hasIcon: Bool, localIdentifiers: [NSNumber]?) -> InspectedAppInfo { + let selfIdentifier = processAppInfoIdentifier if let localIdentifiers, (localIdentifiers as NSArray).contains(NSNumber(value: selfIdentifier)) { - let info = LookinAppInfo() + let info = InspectedAppInfo() info.appInfoIdentifier = UInt(bitPattern: selfIdentifier) info.shouldUseCache = true return info } - let info = LookinAppInfo() + let info = InspectedAppInfo() if #available(iOS 16.0, macOS 13.0, tvOS 16.0, *) { info.gestureDebugProtocolVersion = NSClassFromString("LKS_GestureDebugService") != nil ? 1 : 0 } @@ -394,29 +394,29 @@ info.swiftEnabledInLookinServer = -1 #endif info.appInfoIdentifier = UInt(bitPattern: selfIdentifier) - info.appName = LookinAppInfoAppName() + info.appName = currentAppName() #if targetEnvironment(macCatalyst) // Ask the Mac for its own name. -[UIDevice name] is still consulted // as a last resort so the field is never empty, but on Catalyst it // only ever answers "iPad". - info.deviceDescription = LookinAppInfoMacHostLocalizedName() ?? UIDevice.current.name + info.deviceDescription = macHostLocalizedName() ?? UIDevice.current.name #elseif canImport(UIKit) info.deviceDescription = UIDevice.current.name #elseif os(macOS) info.deviceDescription = Host.current().localizedName #endif - info.deviceModelIdentifier = LookinAppInfoDeviceModelIdentifier + info.deviceModelIdentifier = currentDeviceModelIdentifier info.appBundleIdentifier = Bundle.main.bundleIdentifier - if LookinAppInfoIsSimulator() { + if isRunningInSimulator() { info.deviceType = .simulator - } else if LKS_MultiplatformAdapter.isMacCatalyst() { + } else if MultiplatformAdapter.isMacCatalyst() { // Must precede the iPad check: -[UIDevice model] reports "iPad" on // Catalyst, so +isiPad matches a Catalyst build too and would // otherwise claim it first. +isMac never fires here either. info.deviceType = .macCatalyst - } else if LKS_MultiplatformAdapter.isiPad() { + } else if MultiplatformAdapter.isiPad() { info.deviceType = .iPad - } else if LKS_MultiplatformAdapter.isMac() { + } else if MultiplatformAdapter.isMac() { info.deviceType = .mac } else { info.deviceType = .others @@ -443,16 +443,16 @@ info.osMainVersion = UInt(bitPattern: operatingSystemVersion.majorVersion) #endif - let screenSize = LKS_MultiplatformAdapter.mainScreenBounds().size + let screenSize = MultiplatformAdapter.mainScreenBounds().size info.screenWidth = Double(screenSize.width) info.screenHeight = Double(screenSize.height) - info.screenScale = Double(LKS_MultiplatformAdapter.mainScreenScale()) + info.screenScale = Double(MultiplatformAdapter.mainScreenScale()) if hasScreenshot { - info.screenshot = LookinAppInfoScreenshotImage() + info.screenshot = currentScreenshotImage() } if hasIcon { - info.appIcon = LookinAppInfoAppIcon() + info.appIcon = currentAppIcon() } return info diff --git a/Sources/LookinCoreImpl/LookinAttribute.swift b/Sources/LookinCoreImpl/InspectedAttribute.swift similarity index 82% rename from Sources/LookinCoreImpl/LookinAttribute.swift rename to Sources/LookinCoreImpl/InspectedAttribute.swift index a6837af0..30b7ee0c 100644 --- a/Sources/LookinCoreImpl/LookinAttribute.swift +++ b/Sources/LookinCoreImpl/InspectedAttribute.swift @@ -1,5 +1,5 @@ // -// LookinAttribute.swift +// InspectedAttribute.swift // qmuidemo // // Was LookinAttribute.m. The @@ -14,21 +14,21 @@ #endif @objc(LookinAttribute) - public class LookinAttribute: NSObject, NSCoding, NSSecureCoding, NSCopying { + public class InspectedAttribute: NSObject, NSCoding, NSSecureCoding, NSCopying { @objc(identifier) - public var identifier: String! + public var identifier: String? @objc(displayTitle) - public var displayTitle: String! + public var displayTitle: String? @objc(attrType) public var attrType: LookinAttrType = .none @objc(value) - public var value: Any! + public var value: Any? @objc(extraValue) - public var extraValue: Any! + public var extraValue: Any? @objc(customSetterID) - public var customSetterID: String! + public var customSetterID: String? @objc(targetDisplayItem) - public weak var targetDisplayItem: LookinDisplayItem? + public weak var targetDisplayItem: DisplayItem? override public init() { super.init() @@ -38,7 +38,7 @@ @objc(copyWithZone:) public func copy(with _: NSZone? = nil) -> Any { - let newAttr = LookinAttribute() + let newAttr = InspectedAttribute() newAttr.identifier = identifier newAttr.displayTitle = displayTitle newAttr.value = value @@ -77,7 +77,7 @@ @objc(isUserCustom) public func isUserCustom() -> Bool { - lookinStringsEqual(identifier, LookinAttr_UserCustom) + stringsEqual(identifier, LookinAttr_UserCustom) } } diff --git a/Sources/LookinCoreImpl/LookinObject.swift b/Sources/LookinCoreImpl/InspectedObject.swift similarity index 64% rename from Sources/LookinCoreImpl/LookinObject.swift rename to Sources/LookinCoreImpl/InspectedObject.swift index 066b8004..6c155c99 100644 --- a/Sources/LookinCoreImpl/LookinObject.swift +++ b/Sources/LookinCoreImpl/InspectedObject.swift @@ -1,5 +1,5 @@ // -// LookinObject.swift +// InspectedObject.swift // Lookin // // Was LookinObject.m. The coding @@ -18,46 +18,46 @@ /// not link against the server, so they are sent dynamically, exactly as /// the original's forward declaration did: a missing method raises /// "unrecognized selector" as before. - @objc private protocol LookinObjectServerBridge { - func lks_registerOid() -> UInt - func lks_classChainList() -> [String]? - var lks_specialTrace: String? { get } - var lks_ivarTraces: [LookinIvarTrace]? { get } + @objc private protocol ObjectServerBridge { + @objc(lks_registerOid) func registerOid() -> UInt + @objc(lks_classChainList) func classChainList() -> [String]? + @objc(lks_specialTrace) var associatedSpecialTrace: String? { get } + @objc(lks_ivarTraces) var instanceVariableTraces: [InstanceVariableTrace]? { get } } @objc(LookinObject) - public class LookinObject: NSObject, NSCoding, NSSecureCoding, NSCopying { + public class InspectedObject: NSObject, NSCoding, NSSecureCoding, NSCopying { @objc(oid) public var oid: UInt = 0 @objc(memoryAddress) - public var memoryAddress: String! + public var memoryAddress: String? @objc(classChainList) - public var classChainList: [String]! + public var classChainList: [String]? @objc(specialTrace) - public var specialTrace: String! + public var specialTrace: String? @objc(ivarTraces) - public var ivarTraces: [LookinIvarTrace]! + public var ivarTraces: [InstanceVariableTrace]? /// `+instanceWithObject:`. An Objective-C factory must be a class /// method here. @objc(instanceWithObject:) - public class func instance(with object: NSObject?) -> Self! { - let lookinObj = unsafeDowncast((self as NSObject.Type).init(), to: self) + public class func instance(with object: NSObject?) -> Self { + let inspectedObject = unsafeDowncast((self as NSObject.Type).init(), to: self) guard let object else { // Messages to nil answer 0 / nil; "%p" of nil is "0x0". - lookinObj.memoryAddress = "0x0" - return lookinObj + inspectedObject.memoryAddress = "0x0" + return inspectedObject } - let bridged = unsafeBitCast(object, to: LookinObjectServerBridge.self) - lookinObj.oid = bridged.lks_registerOid() + let bridged = unsafeBitCast(object, to: ObjectServerBridge.self) + inspectedObject.oid = bridged.registerOid() - lookinObj.memoryAddress = String(format: "%p", OpaquePointer(Unmanaged.passUnretained(object).toOpaque())) - lookinObj.classChainList = bridged.lks_classChainList() + inspectedObject.memoryAddress = String(format: "%p", OpaquePointer(Unmanaged.passUnretained(object).toOpaque())) + inspectedObject.classChainList = bridged.classChainList() - lookinObj.specialTrace = bridged.lks_specialTrace - lookinObj.ivarTraces = bridged.lks_ivarTraces + inspectedObject.specialTrace = bridged.associatedSpecialTrace + inspectedObject.ivarTraces = bridged.instanceVariableTraces - return lookinObj + return inspectedObject } override public init() { @@ -68,12 +68,12 @@ @objc(copyWithZone:) public func copy(with _: NSZone? = nil) -> Any { - let newObject = LookinObject() + let newObject = InspectedObject() newObject.oid = oid newObject.memoryAddress = memoryAddress newObject.classChainList = classChainList newObject.specialTrace = specialTrace - newObject.ivarTraces = ivarTraces?.map { $0.copy() as! LookinIvarTrace } + newObject.ivarTraces = ivarTraces?.map { $0.copy() as! InstanceVariableTrace } return newObject } @@ -94,7 +94,7 @@ memoryAddress = aDecoder.decodeObject(forKey: "memoryAddress") as? String classChainList = aDecoder.decodeObject(forKey: "classChainList") as? [String] specialTrace = aDecoder.decodeObject(forKey: "specialTrace") as? String - ivarTraces = aDecoder.decodeObject(forKey: "ivarTraces") as? [LookinIvarTrace] + ivarTraces = aDecoder.decodeObject(forKey: "ivarTraces") as? [InstanceVariableTrace] } @objc(supportsSecureCoding) @@ -103,7 +103,7 @@ } @objc(rawClassName) - public func rawClassName() -> String! { + public func rawClassName() -> String? { classChainList?.first } } diff --git a/Sources/LookinCoreImpl/LookinIvarTrace.swift b/Sources/LookinCoreImpl/InstanceVariableTrace.swift similarity index 83% rename from Sources/LookinCoreImpl/LookinIvarTrace.swift rename to Sources/LookinCoreImpl/InstanceVariableTrace.swift index c195a0db..f95f4540 100644 --- a/Sources/LookinCoreImpl/LookinIvarTrace.swift +++ b/Sources/LookinCoreImpl/InstanceVariableTrace.swift @@ -1,5 +1,5 @@ // -// LookinIvarTrace.swift +// InstanceVariableTrace.swift // Lookin // // Was LookinIvarTrace.m. The exported LookinIvarTraceRelationValue_Self stays in @@ -16,7 +16,7 @@ #endif @objc(LookinIvarTrace) - public class LookinIvarTrace: NSObject, NSCoding, NSSecureCoding, NSCopying { + public class InstanceVariableTrace: NSObject, NSCoding, NSSecureCoding, NSCopying { @objc(relation) public var relation: String? @objc(hostClassName) @@ -33,24 +33,24 @@ // MARK: Equality override open var hash: Int { - lookinStringHash(hostClassName) ^ lookinStringHash(ivarName) + stringHash(hostClassName) ^ stringHash(ivarName) } override open func isEqual(_ object: Any?) -> Bool { if let object = object as? NSObject, object === self { return true } - guard let compared = object as? LookinIvarTrace else { + guard let compared = object as? InstanceVariableTrace else { return false } - return lookinStringsEqual(hostClassName, compared.hostClassName) && lookinStringsEqual(ivarName, compared.ivarName) + return stringsEqual(hostClassName, compared.hostClassName) && stringsEqual(ivarName, compared.ivarName) } // MARK: NSCopying @objc(copyWithZone:) public func copy(with _: NSZone? = nil) -> Any { - let newTrace = LookinIvarTrace() + let newTrace = InstanceVariableTrace() newTrace.relation = relation newTrace.hostClassName = hostClassName newTrace.ivarName = ivarName diff --git a/Sources/LookinCoreImpl/LookinCoreModelSupport.swift b/Sources/LookinCoreImpl/LookinCoreModelSupport.swift index f94e1ab3..47327c37 100644 --- a/Sources/LookinCoreImpl/LookinCoreModelSupport.swift +++ b/Sources/LookinCoreImpl/LookinCoreModelSupport.swift @@ -27,7 +27,7 @@ // so these go through NSString explicitly. /// `[lhs isEqualToString:rhs]`: NO when either side is nil. - func lookinStringsEqual(_ lhs: String?, _ rhs: String?) -> Bool { + func stringsEqual(_ lhs: String?, _ rhs: String?) -> Bool { guard let lhs, let rhs else { return false } @@ -35,7 +35,7 @@ } /// `string.hash`: -[NSString hash], or 0 for nil. - func lookinStringHash(_ string: String?) -> Int { + func stringHash(_ string: String?) -> Int { guard let string else { return 0 } @@ -55,49 +55,49 @@ /// and LookinCore does not link against the server, so it is sent /// dynamically, as the original's import did; `-[NSImage lookin_data]` /// (Image+Lookin.h) goes the same way so it is not bridged to Data. - @objc private protocol LookinScreenshotDataBridge { - func lookin_data() -> NSData? + @objc private protocol ScreenshotDataBridge { + @objc(lookin_data) func encodedData() -> NSData? } - /// `image.lookin_data` (PNG on iOS, TIFF on macOS); nil for a nil image. - func lookinScreenshotData(_ image: LookinImage?) -> NSData? { + /// `image.encodedData` (PNG on iOS, TIFF on macOS); nil for a nil image. + func screenshotData(_ image: PlatformImage?) -> NSData? { guard let image else { return nil } - return unsafeBitCast(image, to: LookinScreenshotDataBridge.self).lookin_data() + return unsafeBitCast(image, to: ScreenshotDataBridge.self).encodedData() } #if canImport(UIKit) - private typealias LookinPNGRepresentationFunction = @convention(c) (UIImage) -> Unmanaged? + private typealias PNGRepresentationFunction = @convention(c) (UIImage) -> Unmanaged? /// `UIImagePNGRepresentation`, which Swift imports returning Data. - private let LookinPNGRepresentationFunctionPointer: LookinPNGRepresentationFunction? = { + private let pngRepresentationFunctionPointer: PNGRepresentationFunction? = { // RTLD_DEFAULT, which Swift does not import on every platform. let defaultHandle = UnsafeMutableRawPointer(bitPattern: -2) guard let symbol = dlsym(defaultHandle, "UIImagePNGRepresentation") else { return nil } - return unsafeBitCast(symbol, to: LookinPNGRepresentationFunction.self) + return unsafeBitCast(symbol, to: PNGRepresentationFunction.self) }() /// `UIImagePNGRepresentation(image)`; nil for a nil image. - func lookinPNGRepresentation(_ image: UIImage?) -> NSData? { - guard let image, let function = LookinPNGRepresentationFunctionPointer else { + func pngRepresentation(_ image: UIImage?) -> NSData? { + guard let image, let function = pngRepresentationFunctionPointer else { return nil } return function(image)?.takeUnretainedValue() } #elseif os(macOS) - @objc private protocol LookinTIFFRepresentationBridge { - @objc(TIFFRepresentation) var lookinTIFFRepresentation: NSData? { get } + @objc private protocol TIFFRepresentationBridge { + @objc(TIFFRepresentation) var tiffRepresentation: NSData? { get } } /// `image.TIFFRepresentation`; nil for a nil image. - func lookinTIFFRepresentation(_ image: NSImage?) -> NSData? { + func tiffRepresentation(_ image: NSImage?) -> NSData? { guard let image else { return nil } - return unsafeBitCast(image, to: LookinTIFFRepresentationBridge.self).lookinTIFFRepresentation + return unsafeBitCast(image, to: TIFFRepresentationBridge.self).tiffRepresentation } #endif diff --git a/Sources/LookinCoreImpl/LookinDefines.swift b/Sources/LookinCoreImpl/LookinDefines.swift index 3773e2c0..e69df648 100644 --- a/Sources/LookinCoreImpl/LookinDefines.swift +++ b/Sources/LookinCoreImpl/LookinDefines.swift @@ -22,22 +22,22 @@ #if canImport(UIKit) import UIKit - public typealias LookinColor = UIColor - public typealias LookinInsets = UIEdgeInsets - public typealias LookinImage = UIImage - public typealias LookinWindow = UIWindow - public typealias LookinApplication = UIApplication - public typealias LookinImageView = UIImageView - public typealias LookinView = UIView - public typealias LookinViewController = UIViewController - public typealias LookinFont = UIFont - public typealias LookinResponder = UIResponder - public typealias LookinLayoutGuide = UILayoutGuide - public typealias LookinGestureRecognizer = UIGestureRecognizer - public typealias LookinControl = UIControl - public typealias LookinCollectionView = UICollectionView - public typealias LookinTextField = UITextField - public typealias LookinTextView = UITextView + public typealias PlatformColor = UIColor + public typealias PlatformEdgeInsets = UIEdgeInsets + public typealias PlatformImage = UIImage + public typealias PlatformWindow = UIWindow + public typealias PlatformApplication = UIApplication + public typealias PlatformImageView = UIImageView + public typealias PlatformView = UIView + public typealias PlatformViewController = UIViewController + public typealias PlatformFont = UIFont + public typealias PlatformResponder = UIResponder + public typealias PlatformLayoutGuide = UILayoutGuide + public typealias PlatformGestureRecognizer = UIGestureRecognizer + public typealias PlatformControl = UIControl + public typealias PlatformCollectionView = UICollectionView + public typealias PlatformTextField = UITextField + public typealias PlatformTextView = UITextView public let LookinLayoutConstraintAxisHorizontal = NSLayoutConstraint.Axis.horizontal public let LookinLayoutConstraintAxisVertical = NSLayoutConstraint.Axis.vertical public let LookinCollectionElementKindSectionHeader = UICollectionView.elementKindSectionHeader @@ -47,22 +47,22 @@ #elseif os(macOS) import AppKit - public typealias LookinColor = NSColor - public typealias LookinInsets = NSEdgeInsets - public typealias LookinImage = NSImage - public typealias LookinWindow = NSWindow - public typealias LookinApplication = NSApplication - public typealias LookinImageView = NSImageView - public typealias LookinView = NSView - public typealias LookinViewController = NSViewController - public typealias LookinFont = NSFont - public typealias LookinResponder = NSResponder - public typealias LookinLayoutGuide = NSLayoutGuide - public typealias LookinGestureRecognizer = NSGestureRecognizer - public typealias LookinControl = NSControl - public typealias LookinCollectionView = NSCollectionView - public typealias LookinTextField = NSTextField - public typealias LookinTextView = NSTextView + public typealias PlatformColor = NSColor + public typealias PlatformEdgeInsets = NSEdgeInsets + public typealias PlatformImage = NSImage + public typealias PlatformWindow = NSWindow + public typealias PlatformApplication = NSApplication + public typealias PlatformImageView = NSImageView + public typealias PlatformView = NSView + public typealias PlatformViewController = NSViewController + public typealias PlatformFont = NSFont + public typealias PlatformResponder = NSResponder + public typealias PlatformLayoutGuide = NSLayoutGuide + public typealias PlatformGestureRecognizer = NSGestureRecognizer + public typealias PlatformControl = NSControl + public typealias PlatformCollectionView = NSCollectionView + public typealias PlatformTextField = NSTextField + public typealias PlatformTextView = NSTextView public let LookinLayoutConstraintAxisHorizontal = NSLayoutConstraint.Orientation.horizontal public let LookinLayoutConstraintAxisVertical = NSLayoutConstraint.Orientation.vertical public let LookinCollectionElementKindSectionHeader = NSCollectionView.elementKindSectionHeader @@ -111,13 +111,13 @@ // MARK: - Colors /// `LookinColorRGBAMake(r, g, b, a)`: components in 0...255, alpha in 0...1. - public func LookinColorRGBAMake(_ r: CGFloat, _ g: CGFloat, _ b: CGFloat, _ a: CGFloat) -> LookinColor { - LookinColor(red: r / 255.0, green: g / 255.0, blue: b / 255.0, alpha: a) + public func LookinColorRGBAMake(_ r: CGFloat, _ g: CGFloat, _ b: CGFloat, _ a: CGFloat) -> PlatformColor { + PlatformColor(red: r / 255.0, green: g / 255.0, blue: b / 255.0, alpha: a) } /// `LookinColorMake(r, g, b)`. - public func LookinColorMake(_ r: CGFloat, _ g: CGFloat, _ b: CGFloat) -> LookinColor { - LookinColor(red: r / 255.0, green: g / 255.0, blue: b / 255.0, alpha: 1) + public func LookinColorMake(_ r: CGFloat, _ g: CGFloat, _ b: CGFloat) -> PlatformColor { + PlatformColor(red: r / 255.0, green: g / 255.0, blue: b / 255.0, alpha: 1) } #endif diff --git a/Sources/LookinCoreImpl/LKS_MultiplatformAdapter.swift b/Sources/LookinCoreImpl/MultiplatformAdapter.swift similarity index 87% rename from Sources/LookinCoreImpl/LKS_MultiplatformAdapter.swift rename to Sources/LookinCoreImpl/MultiplatformAdapter.swift index eb09be2e..ef4dd2db 100644 --- a/Sources/LookinCoreImpl/LKS_MultiplatformAdapter.swift +++ b/Sources/LookinCoreImpl/MultiplatformAdapter.swift @@ -1,5 +1,5 @@ // -// LKS_MultiplatformAdapter.swift +// MultiplatformAdapter.swift // LookinCore // // Was LKS_MultiplatformAdapter.m. @@ -18,11 +18,11 @@ #endif @objc(LKS_MultiplatformAdapter) - public class LKS_MultiplatformAdapter: NSObject { + public class MultiplatformAdapter: NSObject { @objc(isiPad) public class func isiPad() -> Bool { #if canImport(UIKit) - return lookinIsiPad + return cachedIsPad #else return false #endif @@ -49,7 +49,7 @@ @objc(mainScreenBounds) public class func mainScreenBounds() -> CGRect { #if os(visionOS) || targetEnvironment(macCatalyst) - return lookinFirstActiveWindowScene()?.coordinateSpace.bounds ?? .zero + return firstActiveWindowScene()?.coordinateSpace.bounds ?? .zero #elseif canImport(UIKit) return UIScreen.main.bounds #elseif os(macOS) @@ -84,18 +84,18 @@ } @objc(keyWindow) - public class func keyWindow() -> LookinWindow? { + public class func keyWindow() -> PlatformWindow? { #if os(visionOS) - return lookinFirstActiveWindowScene()?.keyWindow + return firstActiveWindowScene()?.keyWindow #elseif canImport(UIKit) - return lookinSharedApplication()?.keyWindow + return sharedApplication()?.keyWindow #elseif os(macOS) return NSApplication.shared.keyWindow #endif } @objc(allWindows) - public class func allWindows() -> [LookinWindow] { + public class func allWindows() -> [PlatformWindow] { #if canImport(UIKit) let scenes = allWindowScenes() if !scenes.isEmpty { @@ -112,21 +112,21 @@ // scene.keyWindow (iOS 15+). if #available(iOS 15.0, tvOS 15.0, macCatalyst 15.0, *) { if let sceneKeyWindow = windowScene.keyWindow, !windows.contains(sceneKeyWindow) { - if !NSStringFromClass(lookinObjCClass(of: sceneKeyWindow)).contains("HUD") { + if !NSStringFromClass(objCClass(of: sceneKeyWindow)).contains("HUD") { windows.add(sceneKeyWindow) } } } } if windows.count > 0 { - return windows.copy() as! [LookinWindow] + return windows.copy() as! [PlatformWindow] } } #if os(visionOS) // visionOS has no global window list to fall back to. return [] #else - return lookinSharedApplication()?.windows ?? [] + return sharedApplication()?.windows ?? [] #endif #else return NSApplication.shared.windows @@ -149,7 +149,7 @@ } } if allScenes.isEmpty { - if let connectedScenes = lookinSharedApplication()?.connectedScenes { + if let connectedScenes = sharedApplication()?.connectedScenes { allScenes = (connectedScenes as NSSet).allObjects as! [UIScene] } } @@ -194,17 +194,17 @@ /// (an XCTest bundle, an extension); the Objective-C messages to it then /// answered nil. `UIApplication.shared` is implicitly unwrapped and /// would trap instead. - private func lookinSharedApplication() -> UIApplication? { + private func sharedApplication() -> UIApplication? { return UIApplication.shared } /// `+isiPad`'s dispatch_once value; a global `let` is initialized once, /// thread-safely, on first use. - private let lookinIsiPad: Bool = UIDevice.current.model.hasPrefix("iPad") + private let cachedIsPad: Bool = UIDevice.current.model.hasPrefix("iPad") /// `[object class]`, not `type(of:)`: for a KVO-observed object the /// former is the original class. - private func lookinObjCClass(of object: NSObject) -> AnyClass { + private func objCClass(of object: NSObject) -> AnyClass { object.perform(NSSelectorFromString("class")) .map { $0.takeUnretainedValue() as! AnyClass } ?? type(of: object) } @@ -213,8 +213,8 @@ #if os(visionOS) || targetEnvironment(macCatalyst) /// `+getFirstActiveWindowScene`: the first foreground-active window /// scene. - private func lookinFirstActiveWindowScene() -> UIWindowScene? { - for scene in lookinSharedApplication()?.connectedScenes ?? [] { + private func firstActiveWindowScene() -> UIWindowScene? { + for scene in sharedApplication()?.connectedScenes ?? [] { guard let windowScene = scene as? UIWindowScene else { continue } diff --git a/Sources/LookinCoreImpl/LookinStaticAsyncUpdateTask.swift b/Sources/LookinCoreImpl/StaticAsyncUpdateTask.swift similarity index 90% rename from Sources/LookinCoreImpl/LookinStaticAsyncUpdateTask.swift rename to Sources/LookinCoreImpl/StaticAsyncUpdateTask.swift index d75286b5..5e82b705 100644 --- a/Sources/LookinCoreImpl/LookinStaticAsyncUpdateTask.swift +++ b/Sources/LookinCoreImpl/StaticAsyncUpdateTask.swift @@ -1,5 +1,5 @@ // -// LookinStaticAsyncUpdateTask.swift +// StaticAsyncUpdateTask.swift // Lookin // // Was LookinStaticAsyncUpdateTask.m: the 203 request's tasks. The coding keys, @@ -14,7 +14,7 @@ #endif @objc(LookinStaticAsyncUpdateTask) - public class LookinStaticAsyncUpdateTask: NSObject, NSCoding, NSSecureCoding { + public class StaticAsyncUpdateTask: NSObject, NSCoding, NSSecureCoding { @objc(oid) public var oid: UInt = 0 @objc(taskType) @@ -26,7 +26,7 @@ @objc(needSubitems) public var needSubitems: Bool = false @objc(clientReadableVersion) - public var clientReadableVersion: String! + public var clientReadableVersion: String? /// Not archived. @objc(frameSize) public var frameSize: CGSize = .zero @@ -91,7 +91,7 @@ if let object = object as? NSObject, object === self { return true } - guard let targetTask = object as? LookinStaticAsyncUpdateTask else { + guard let targetTask = object as? StaticAsyncUpdateTask else { return false } return oid == targetTask.oid @@ -103,9 +103,9 @@ } @objc(LookinStaticAsyncUpdateTasksPackage) - public class LookinStaticAsyncUpdateTasksPackage: NSObject, NSCoding, NSSecureCoding { + public class StaticAsyncUpdateTasksPackage: NSObject, NSCoding, NSSecureCoding { @objc(tasks) - public var tasks: [LookinStaticAsyncUpdateTask]! + public var tasks: [StaticAsyncUpdateTask]? override public init() { super.init() @@ -118,7 +118,7 @@ public required init?(coder aDecoder: NSCoder) { super.init() - tasks = aDecoder.decodeObject(forKey: "tasks") as? [LookinStaticAsyncUpdateTask] + tasks = aDecoder.decodeObject(forKey: "tasks") as? [StaticAsyncUpdateTask] } @objc(supportsSecureCoding) diff --git a/Sources/LookinCoreImpl/Transport/LookinFrameChannel.swift b/Sources/LookinCoreImpl/Transport/FrameChannel.swift similarity index 91% rename from Sources/LookinCoreImpl/Transport/LookinFrameChannel.swift rename to Sources/LookinCoreImpl/Transport/FrameChannel.swift index 182f13af..450d8088 100644 --- a/Sources/LookinCoreImpl/Transport/LookinFrameChannel.swift +++ b/Sources/LookinCoreImpl/Transport/FrameChannel.swift @@ -1,5 +1,5 @@ // -// LookinFrameChannel.swift +// FrameChannel.swift // LookinCore // // A connected stream socket that carries Lookin frames, shared by the @@ -31,35 +31,35 @@ import Darwin import Foundation - public final class LookinFrameChannel: @unchecked Sendable { + public final class FrameChannel: @unchecked Sendable { /// Why the channel ended, when it did not end cleanly. public enum EndError: Error, Equatable { /// A POSIX error from the socket. case posix(Int32) /// The byte stream is not a valid frame stream. - case frame(LookinFrameError) + case frame(FrameError) } public let queue: DispatchQueue /// Decides on each header before its payload is read; nil accepts /// every frame. Set before `start()`. - public var shouldAcceptFrame: ((LookinFrameHeader) -> Bool)? + public var shouldAcceptFrame: ((FrameHeader) -> Bool)? /// Each accepted frame, payload complete. Set before `start()`. - public var onFrame: ((LookinFrame) -> Void)? + public var onFrame: ((TransportFrame) -> Void)? /// Runs once, after the socket is closed: nil for an orderly end (the /// peer closed, a type-0 frame, `close()` or `cancel()`). Set before /// `start()`. public var onEnd: ((EndError?) -> Void)? private let io: DispatchIO - private var decoder: LookinFrameDecoder + private var decoder: FrameDecoder private var pendingBytes: Data private var endError: EndError? private var started = false private var ended = false /// Holds the channel until `onEnd` has run. - private var keepAlive: LookinFrameChannel? + private var keepAlive: FrameChannel? private let stateLock = NSLock() private var open = true @@ -80,12 +80,12 @@ /// /// - Parameters: /// - maxPayloadSize: the largest payload an accepted frame may - /// announce (see `LookinFrameDecoder`). + /// announce (see `FrameDecoder`). /// - initialBytes: bytes already read from the socket that belong /// to the frame stream (after a usbmuxd Connect result). public init(fileDescriptor: Int32, queue: DispatchQueue, maxPayloadSize: UInt32 = .max, initialBytes: Data = Data()) { self.queue = queue - decoder = LookinFrameDecoder(maxPayloadSize: maxPayloadSize) + decoder = FrameDecoder(maxPayloadSize: maxPayloadSize) pendingBytes = initialBytes var on: Int32 = 1 setsockopt(fileDescriptor, SOL_SOCKET, SO_NOSIGPIPE, &on, socklen_t(MemoryLayout.size)) @@ -106,7 +106,7 @@ } private final class WeakBox: @unchecked Sendable { - weak var channel: LookinFrameChannel? + weak var channel: FrameChannel? } /// Starts reading. Frames and the end arrive on `queue`. @@ -129,11 +129,11 @@ /// Sends one frame. `completion` (on `queue`) gets nil once it is /// fully written, or the error; a closed channel fails with EPERM, as /// Peertalk did. - public func send(_ frame: LookinFrame, completion: ((EndError?) -> Void)? = nil) { + public func send(_ frame: TransportFrame, completion: ((EndError?) -> Void)? = nil) { let bytes: Data do { bytes = try frame.encoded() - } catch let error as LookinFrameError { + } catch let error as FrameError { queue.async { completion?(.frame(error)) } return } catch { @@ -166,7 +166,7 @@ } public func send(type: UInt32, tag: UInt32, payload: Data = Data(), completion: ((EndError?) -> Void)? = nil) { - send(LookinFrame(type: type, tag: tag, payload: payload), completion: completion) + send(TransportFrame(type: type, tag: tag, payload: payload), completion: completion) } /// Ends the channel now; queued writes are dropped. @@ -228,10 +228,10 @@ private func receive(_ bytes: Data) { decoder.append(bytes) while isConnected { - let output: LookinFrameDecoder.Output? + let output: FrameDecoder.Output? do { output = try decoder.next(accepting: { [self] header in shouldAcceptFrame?(header) ?? true }) - } catch let error as LookinFrameError { + } catch let error as FrameError { endError = .frame(error) close() return diff --git a/Sources/LookinCoreImpl/Transport/LookinFrameDecoder.swift b/Sources/LookinCoreImpl/Transport/FrameDecoder.swift similarity index 86% rename from Sources/LookinCoreImpl/Transport/LookinFrameDecoder.swift rename to Sources/LookinCoreImpl/Transport/FrameDecoder.swift index c2e730a5..264e8caf 100644 --- a/Sources/LookinCoreImpl/Transport/LookinFrameDecoder.swift +++ b/Sources/LookinCoreImpl/Transport/FrameDecoder.swift @@ -1,5 +1,5 @@ // -// LookinFrameDecoder.swift +// FrameDecoder.swift // LookinCore // // Turns a byte stream into frames, however the bytes are split or joined @@ -20,10 +20,10 @@ import Foundation - public struct LookinFrameDecoder { + public struct FrameDecoder { public enum Output: Equatable { /// An accepted frame, payload complete. - case frame(LookinFrame) + case frame(TransportFrame) /// A type-0 header arrived: the stream is over. case endOfStream } @@ -40,13 +40,13 @@ private enum State { case header - case payload(LookinFrameHeader) + case payload(FrameHeader) case discarding(remaining: Int) case finished } /// The largest payload an accepted frame may announce; a larger one - /// throws `LookinFrameError.payloadTooLarge`. `UInt32.max`, the + /// throws `FrameError.payloadTooLarge`. `UInt32.max`, the /// default, accepts every frame, as Peertalk did. public let maxPayloadSize: UInt32 @@ -107,9 +107,9 @@ /// - Parameter accepting: decides on each header once, before its /// payload is read; a rejected frame is skipped. Not called for a /// type-0 header. - /// - Throws: `LookinFrameError.unsupportedVersion` or + /// - Throws: `FrameError.unsupportedVersion` or /// `.payloadTooLarge`; the decoder is finished afterwards. - public mutating func next(accepting: (LookinFrameHeader) -> Bool = { _ in true }) throws -> Output? { + public mutating func next(accepting: (FrameHeader) -> Bool = { _ in true }) throws -> Output? { while true { switch state { case .finished: @@ -125,18 +125,18 @@ state = .header case .header: - guard bufferedByteCount >= LookinFrameProtocol.headerSize else { + guard bufferedByteCount >= FrameProtocolConstants.headerSize else { return nil } - let header: LookinFrameHeader + let header: FrameHeader do { - header = try LookinFrameHeader.decode(buffer[readIndex ..< readIndex + LookinFrameProtocol.headerSize]) + header = try FrameHeader.decode(buffer[readIndex ..< readIndex + FrameProtocolConstants.headerSize]) } catch { state = .finished throw error } - readIndex += LookinFrameProtocol.headerSize - if header.type == LookinFrameProtocol.endOfStreamType { + readIndex += FrameProtocolConstants.headerSize + if header.type == FrameProtocolConstants.endOfStreamType { state = .finished buffer = Data() readIndex = buffer.startIndex @@ -148,7 +148,7 @@ } guard header.payloadSize <= maxPayloadSize else { state = .finished - throw LookinFrameError.payloadTooLarge(size: header.payloadSize, limit: maxPayloadSize) + throw FrameError.payloadTooLarge(size: header.payloadSize, limit: maxPayloadSize) } state = .payload(header) @@ -160,7 +160,7 @@ let payload = size > 0 ? Data(buffer[readIndex ..< readIndex + size]) : Data() readIndex += size state = .header - return .frame(LookinFrame(type: header.type, tag: header.tag, payload: payload)) + return .frame(TransportFrame(type: header.type, tag: header.tag, payload: payload)) } } } diff --git a/Sources/LookinCoreImpl/Transport/LookinFrameListener.swift b/Sources/LookinCoreImpl/Transport/FrameListener.swift similarity index 90% rename from Sources/LookinCoreImpl/Transport/LookinFrameListener.swift rename to Sources/LookinCoreImpl/Transport/FrameListener.swift index b5999996..f34b7ff9 100644 --- a/Sources/LookinCoreImpl/Transport/LookinFrameListener.swift +++ b/Sources/LookinCoreImpl/Transport/FrameListener.swift @@ -1,5 +1,5 @@ // -// LookinFrameListener.swift +// FrameListener.swift // LookinCore // // The Server's listening socket, the way Peertalk's @@ -15,7 +15,7 @@ // connections the event announced (Peertalk behaved the same way when the // first accepted connection cancelled its listener). // -// A failed setup step throws `LookinSocket.Error` with its errno; EADDRINUSE +// A failed setup step throws `SocketConnector.Error` with its errno; EADDRINUSE // (48) means another process (or another listener) holds the port. // @@ -24,7 +24,7 @@ import Darwin import Foundation - public final class LookinFrameListener: @unchecked Sendable { + public final class FrameListener: @unchecked Sendable { /// The bound port (the kernel's choice when listening on port 0). public let port: UInt16 @@ -46,14 +46,14 @@ /// Listens on 127.0.0.1:`port`; `onAccept` runs on `queue` with each /// accepted socket, which it then owns. - public static func listen(port: UInt16, queue: DispatchQueue, onAccept: @escaping (Int32) -> Void) throws -> LookinFrameListener { + public static func listen(port: UInt16, queue: DispatchQueue, onAccept: @escaping (Int32) -> Void) throws -> FrameListener { let fd = socket(AF_INET, SOCK_STREAM, 0) - guard fd != -1 else { throw LookinSocket.Error(code: errno) } + guard fd != -1 else { throw SocketConnector.Error(code: errno) } - func fail() -> LookinSocket.Error { + func fail() -> SocketConnector.Error { let code = errno Darwin.close(fd) - return LookinSocket.Error(code: code) + return SocketConnector.Error(code: code) } var on: Int32 = 1 @@ -104,7 +104,7 @@ Darwin.close(fd) } source.resume() - return LookinFrameListener(port: boundPort, source: source) + return FrameListener(port: boundPort, source: source) } /// One accept(); nil when it fails (EAGAIN included) or the socket @@ -118,7 +118,7 @@ } } guard fd != -1 else { return nil } - LookinSocket.disableSIGPIPE(fd) + SocketConnector.disableSIGPIPE(fd) let flags = fcntl(fd, F_GETFL) guard flags != -1, fcntl(fd, F_SETFL, flags | O_NONBLOCK) != -1 else { Darwin.close(fd) diff --git a/Sources/LookinCoreImpl/Transport/LookinSocket.swift b/Sources/LookinCoreImpl/Transport/SocketConnector.swift similarity index 96% rename from Sources/LookinCoreImpl/Transport/LookinSocket.swift rename to Sources/LookinCoreImpl/Transport/SocketConnector.swift index e39f7cd5..79b3bde5 100644 --- a/Sources/LookinCoreImpl/Transport/LookinSocket.swift +++ b/Sources/LookinCoreImpl/Transport/SocketConnector.swift @@ -1,5 +1,5 @@ // -// LookinSocket.swift +// SocketConnector.swift // LookinCore // // The two blocking connects the transport needs, shared by the Host, the @@ -13,7 +13,7 @@ // - `connectUnix(path:)`: a stream connection to a Unix socket, for // /var/run/usbmuxd (Peertalk's USB channel did the same). // -// The returned descriptor is blocking; LookinFrameChannel switches it to +// The returned descriptor is blocking; FrameChannel switches it to // non-blocking when it takes it over. // @@ -22,7 +22,7 @@ import Darwin import Foundation - public enum LookinSocket { + public enum SocketConnector { /// A failed socket call, with its errno (ECONNREFUSED when nothing /// listens on the port, ENOENT when the Unix socket does not exist). public struct Error: Swift.Error, Equatable, CustomStringConvertible { diff --git a/Sources/LookinCoreImpl/Transport/LookinFrame.swift b/Sources/LookinCoreImpl/Transport/TransportFrame.swift similarity index 75% rename from Sources/LookinCoreImpl/Transport/LookinFrame.swift rename to Sources/LookinCoreImpl/Transport/TransportFrame.swift index 779a0167..ee1c79cc 100644 --- a/Sources/LookinCoreImpl/Transport/LookinFrame.swift +++ b/Sources/LookinCoreImpl/Transport/TransportFrame.swift @@ -1,5 +1,5 @@ // -// LookinFrame.swift +// TransportFrame.swift // LookinCore // // The frame format the Host and the Server exchange, byte for byte the one @@ -17,7 +17,7 @@ // tag 0. There is no ping, close or handshake frame at this layer: ping is // the application request 200, and a connection ends by closing the socket. // A received frame of type 0 is Peertalk's end-of-stream marker and ends the -// stream (see LookinFrameDecoder). Pinned by Tests/LookinTransportTests, +// stream (see FrameDecoder). Pinned by Tests/LookinTransportTests, // whose fixtures were recorded from Peertalk. // @@ -26,7 +26,7 @@ import Foundation /// Constants of the frame protocol. - public enum LookinFrameProtocol { + public enum FrameProtocolConstants { /// The only protocol version; a frame with another version ends the /// connection with an error. public static let version: UInt32 = 1 @@ -40,8 +40,8 @@ } /// Why a byte stream is not a valid frame stream. - public enum LookinFrameError: Error, Equatable { - /// The header's version is not `LookinFrameProtocol.version`. + public enum FrameError: Error, Equatable { + /// The header's version is not `FrameProtocolConstants.version`. case unsupportedVersion(UInt32) /// An accepted frame announces a payload above the decoder's limit. case payloadTooLarge(size: UInt32, limit: UInt32) @@ -52,7 +52,7 @@ } /// The 16-byte frame header. - public struct LookinFrameHeader: Equatable, Sendable { + public struct FrameHeader: Equatable, Sendable { public var type: UInt32 public var tag: UInt32 public var payloadSize: UInt32 @@ -65,8 +65,8 @@ /// The header bytes (version 1, every field big-endian). public var encoded: Data { - var data = Data(capacity: LookinFrameProtocol.headerSize) - for field in [LookinFrameProtocol.version, type, tag, payloadSize] { + var data = Data(capacity: FrameProtocolConstants.headerSize) + for field in [FrameProtocolConstants.version, type, tag, payloadSize] { withUnsafeBytes(of: field.bigEndian) { data.append(contentsOf: $0) } } return data @@ -74,11 +74,11 @@ /// Reads a header from the first 16 bytes of `bytes`. /// - /// - Throws: `LookinFrameError.truncatedHeader` for fewer than 16 + /// - Throws: `FrameError.truncatedHeader` for fewer than 16 /// bytes, `.unsupportedVersion` for a version other than 1. - public static func decode(_ bytes: Bytes) throws -> LookinFrameHeader where Bytes.Element == UInt8 { - guard bytes.count >= LookinFrameProtocol.headerSize else { - throw LookinFrameError.truncatedHeader + public static func decode(_ bytes: Bytes) throws -> FrameHeader where Bytes.Element == UInt8 { + guard bytes.count >= FrameProtocolConstants.headerSize else { + throw FrameError.truncatedHeader } var fields = [UInt32]() fields.reserveCapacity(4) @@ -91,16 +91,16 @@ } fields.append(value) } - guard fields[0] == LookinFrameProtocol.version else { - throw LookinFrameError.unsupportedVersion(fields[0]) + guard fields[0] == FrameProtocolConstants.version else { + throw FrameError.unsupportedVersion(fields[0]) } - return LookinFrameHeader(type: fields[1], tag: fields[2], payloadSize: fields[3]) + return FrameHeader(type: fields[1], tag: fields[2], payloadSize: fields[3]) } } /// One frame. An empty payload is what Peertalk delivered as a nil /// payload: the header says 0 and no payload bytes follow. - public struct LookinFrame: Equatable, Sendable { + public struct TransportFrame: Equatable, Sendable { public var type: UInt32 public var tag: UInt32 public var payload: Data @@ -111,17 +111,17 @@ self.payload = payload } - public var header: LookinFrameHeader { - LookinFrameHeader(type: type, tag: tag, payloadSize: UInt32(truncatingIfNeeded: payload.count)) + public var header: FrameHeader { + FrameHeader(type: type, tag: tag, payloadSize: UInt32(truncatingIfNeeded: payload.count)) } /// The frame's wire bytes: header, then payload. /// - /// - Throws: `LookinFrameError.payloadSizeOverflow` for a payload of + /// - Throws: `FrameError.payloadSizeOverflow` for a payload of /// 4 GiB or more (Peertalk asserted instead). public func encoded() throws -> Data { guard payload.count <= Int(UInt32.max) else { - throw LookinFrameError.payloadSizeOverflow(payload.count) + throw FrameError.payloadSizeOverflow(payload.count) } var data = header.encoded data.append(payload) diff --git a/Sources/LookinCoreImpl/Transport/LookinUSBMux.swift b/Sources/LookinCoreImpl/Transport/USBMux.swift similarity index 78% rename from Sources/LookinCoreImpl/Transport/LookinUSBMux.swift rename to Sources/LookinCoreImpl/Transport/USBMux.swift index 41f20a48..5686843b 100644 --- a/Sources/LookinCoreImpl/Transport/LookinUSBMux.swift +++ b/Sources/LookinCoreImpl/Transport/USBMux.swift @@ -1,5 +1,5 @@ // -// LookinUSBMux.swift +// USBMux.swift // LookinCore // // The usbmuxd client messages the Host sends to reach a Server on a USB @@ -18,7 +18,7 @@ // order. After a Result with Number 0 the same socket is a byte stream to // that port on the device, carrying Lookin frames. // -// Only the encoding lives here; the socket is LookinUSBMuxClient's +// Only the encoding lives here; the socket is USBMuxClient's // (Host-side, macOS). // @@ -26,7 +26,7 @@ import Foundation - public enum LookinUSBMux { + public enum USBMux { /// The usbmuxd socket on macOS. public static let socketPath = "/var/run/usbmuxd" public static let headerSize = 16 @@ -98,7 +98,7 @@ /// Why usbmuxd turned a request down, or why its reply is unusable. /// `domain` and `code` are Peertalk's (`PTUSBHubError`), so log lines read /// the same. - public struct LookinUSBMuxError: Error, Equatable, CustomStringConvertible { + public struct USBMuxError: Error, Equatable, CustomStringConvertible { public static let domain = "PTUSBHubError" /// usbmuxd's `Number` (1 bad command, 2 bad device, 3 connection @@ -112,18 +112,18 @@ } /// The error a Result reply carries, or nil for `Number` 0. - public static func fromResult(_ reply: [String: Any]) -> LookinUSBMuxError? { + public static func fromResult(_ reply: [String: Any]) -> USBMuxError? { guard let number = reply["Number"] as? NSNumber else { - return LookinUSBMuxError(code: 0, message: "Result without a Number") + return USBMuxError(code: 0, message: "Result without a Number") } let code = number.intValue switch code { case 0: return nil - case 1: return LookinUSBMuxError(code: code, message: "illegal command") - case 2: return LookinUSBMuxError(code: code, message: "unknown device") - case 3: return LookinUSBMuxError(code: code, message: "connection refused") - case 6: return LookinUSBMuxError(code: code, message: "invalid version") - default: return LookinUSBMuxError(code: code, message: "Unspecified error") + case 1: return USBMuxError(code: code, message: "illegal command") + case 2: return USBMuxError(code: code, message: "unknown device") + case 3: return USBMuxError(code: code, message: "connection refused") + case 6: return USBMuxError(code: code, message: "invalid version") + default: return USBMuxError(code: code, message: "Unspecified error") } } @@ -133,7 +133,7 @@ } /// One usbmuxd message. - public struct LookinUSBMuxPacket: Equatable { + public struct USBMuxPacket: Equatable { public var version: UInt32 public var messageType: UInt32 public var tag: UInt32 @@ -149,13 +149,13 @@ /// A plist message: `dictionary` as an XML property list. public init(plist dictionary: [String: Any], tag: UInt32) throws { let payload = try PropertyListSerialization.data(fromPropertyList: dictionary, format: .xml, options: 0) - self.init(version: LookinUSBMux.plistVersion, messageType: LookinUSBMux.plistMessageType, tag: tag, payload: payload) + self.init(version: USBMux.plistVersion, messageType: USBMux.plistMessageType, tag: tag, payload: payload) } /// The wire bytes: little-endian header, then the payload. public var encoded: Data { - var data = Data(capacity: LookinUSBMux.headerSize + payload.count) - let size = UInt32(truncatingIfNeeded: LookinUSBMux.headerSize + payload.count) + var data = Data(capacity: USBMux.headerSize + payload.count) + let size = UInt32(truncatingIfNeeded: USBMux.headerSize + payload.count) for field in [size, version, messageType, tag] { withUnsafeBytes(of: field.littleEndian) { data.append(contentsOf: $0) } } @@ -170,21 +170,21 @@ /// The payload as a property-list dictionary. /// - /// - Throws: `LookinUSBMuxError` (code 0) for a non-plist message, or + /// - Throws: `USBMuxError` (code 0) for a non-plist message, or /// the property-list error. public func plistDictionary() throws -> [String: Any] { - guard version == LookinUSBMux.plistVersion else { - throw LookinUSBMuxError(code: 0, message: "Unexpected package protocol") + guard version == USBMux.plistVersion else { + throw USBMuxError(code: 0, message: "Unexpected package protocol") } - guard messageType == LookinUSBMux.plistMessageType else { - throw LookinUSBMuxError(code: 0, message: "Unexpected package type") + guard messageType == USBMux.plistMessageType else { + throw USBMuxError(code: 0, message: "Unexpected package type") } if payload.isEmpty { return [:] } let object = try PropertyListSerialization.propertyList(from: payload, options: [], format: nil) guard let dictionary = object as? [String: Any] else { - throw LookinUSBMuxError(code: 0, message: "Unexpected property list") + throw USBMuxError(code: 0, message: "Unexpected property list") } return dictionary } @@ -193,7 +193,7 @@ /// Splits the bytes read from a usbmuxd socket into messages. After a /// successful Connect, `takeRemainingBytes()` hands the bytes that /// followed the Result (the device's first frames) to the frame channel. - public struct LookinUSBMuxDecoder { + public struct USBMuxDecoder { /// usbmuxd's own messages are small; anything bigger is not usbmuxd. public static let maxPacketSize = 16 * 1024 * 1024 @@ -207,10 +207,10 @@ /// The next complete message, or nil when more bytes are needed. /// - /// - Throws: `LookinUSBMuxError` for a size below 16 or above + /// - Throws: `USBMuxError` for a size below 16 or above /// `maxPacketSize`. - public mutating func next() throws -> LookinUSBMuxPacket? { - guard buffer.count >= LookinUSBMux.headerSize else { return nil } + public mutating func next() throws -> USBMuxPacket? { + guard buffer.count >= USBMux.headerSize else { return nil } let fields = (0 ..< 4).map { field -> UInt32 in var value: UInt32 = 0 for byte in (0 ..< 4).reversed() { @@ -219,14 +219,14 @@ return value } let size = Int(fields[0]) - guard size >= LookinUSBMux.headerSize, size <= Self.maxPacketSize else { - throw LookinUSBMuxError(code: 1, message: "Received a packet that is too large") + guard size >= USBMux.headerSize, size <= Self.maxPacketSize else { + throw USBMuxError(code: 1, message: "Received a packet that is too large") } guard buffer.count >= size else { return nil } let start = buffer.startIndex - let payload = Data(buffer[start + LookinUSBMux.headerSize ..< start + size]) + let payload = Data(buffer[start + USBMux.headerSize ..< start + size]) buffer = Data(buffer[(start + size)...]) - return LookinUSBMuxPacket(version: fields[1], messageType: fields[2], tag: fields[3], payload: payload) + return USBMuxPacket(version: fields[1], messageType: fields[2], tag: fields[3], payload: payload) } /// The bytes after the last decoded message; empties the decoder. diff --git a/Sources/LookinCoreImpl/Transport/LookinUSBMuxClient.swift b/Sources/LookinCoreImpl/Transport/USBMuxClient.swift similarity index 86% rename from Sources/LookinCoreImpl/Transport/LookinUSBMuxClient.swift rename to Sources/LookinCoreImpl/Transport/USBMuxClient.swift index 1f265a31..8c0ef2da 100644 --- a/Sources/LookinCoreImpl/Transport/LookinUSBMuxClient.swift +++ b/Sources/LookinCoreImpl/Transport/USBMuxClient.swift @@ -1,10 +1,10 @@ // -// LookinUSBMuxClient.swift +// USBMuxClient.swift // LookinCore // // The Host's usbmuxd client (macOS only), shared by the Host and // lookin-probe. It replaces the vendored Peertalk's USB hub and sends the same -// bytes (LookinUSBMux builds them): +// bytes (USBMux builds them): // // - `startListening` keeps one socket open with a Listen request (tag 1) // and reports usbmuxd's Attached / Detached broadcasts (tag 0). Devices @@ -26,8 +26,11 @@ import Darwin import Foundation + #if SWIFT_PACKAGE + import LookinServerBase + #endif - public final class LookinUSBMuxClient: @unchecked Sendable { + public final class USBMuxClient: @unchecked Sendable { public enum Event { /// `properties` is the whole Attached message, DeviceID /// included (what Peertalk posted as the notification's @@ -45,7 +48,7 @@ private static let firstTag: UInt32 = 1 public let queue: DispatchQueue - public let identity: LookinUSBMux.ClientIdentity + public let identity: USBMux.ClientIdentity public let socketPath: String private let ioQueue = DispatchQueue(label: "lookin.usbmux.io", attributes: .concurrent) @@ -62,8 +65,8 @@ public init( queue: DispatchQueue, - identity: LookinUSBMux.ClientIdentity = .mainBundle, - socketPath: String = LookinUSBMux.socketPath + identity: USBMux.ClientIdentity = .mainBundle, + socketPath: String = USBMux.socketPath ) { self.queue = queue self.identity = identity @@ -133,11 +136,11 @@ deliver(event) } if isCurrent(generation) { - NSLog("LookinUSBMux - the usbmuxd listen connection ended") + LookInsideServerLogger.log(with: .default, message: "LookinUSBMux - the usbmuxd listen connection ended") } } catch { if isCurrent(generation) { - NSLog("LookinUSBMux - listening to usbmuxd failed: %@", String(describing: error)) + LookInsideServerLogger.log(with: .error, message: "LookinUSBMux - listening to usbmuxd failed: \(error)") } } for deviceID in knownDevices { @@ -163,7 +166,7 @@ /// socket ends; throws when it cannot be opened, the Result is /// an error or the stream is invalid. private func listenSession(generation: Int, onEvent: (Event) -> Void) throws { - let fd = try LookinSocket.connectUnix(path: socketPath) + let fd = try SocketConnector.connectUnix(path: socketPath) listenCondition.lock() guard isListening, listenGeneration == generation else { listenCondition.unlock() @@ -179,10 +182,10 @@ Darwin.close(fd) } - let request = try LookinUSBMuxPacket(plist: LookinUSBMux.listenRequest(identity: identity), tag: Self.firstTag) + let request = try USBMuxPacket(plist: USBMux.listenRequest(identity: identity), tag: Self.firstTag) try Self.writeAll(fd, request.encoded) - var decoder = LookinUSBMuxDecoder() + var decoder = USBMuxDecoder() var listening = false while true { while let packet = try decoder.next() { @@ -190,12 +193,12 @@ if packet.isBroadcast { handleBroadcast(message, onEvent: onEvent) } else if !listening, packet.tag == Self.firstTag { - if let error = LookinUSBMuxError.fromResult(message) { + if let error = USBMuxError.fromResult(message) { throw error } listening = true } else { - NSLog("LookinUSBMux - ignoring a usbmuxd reply with tag %@", NSNumber(value: packet.tag)) + LookInsideServerLogger.log(with: .warning, message: "LookinUSBMux - ignoring a usbmuxd reply with tag \(packet.tag)") } } guard let bytes = try Self.readSome(fd) else { return } @@ -206,7 +209,7 @@ private func handleBroadcast(_ message: [String: Any], onEvent: (Event) -> Void) { let messageType = message["MessageType"] as? String guard let deviceID = (message["DeviceID"] as? NSNumber)?.intValue else { - NSLog("LookinUSBMux - ignoring a usbmuxd broadcast without a DeviceID: %@", messageType ?? "(null)") + LookInsideServerLogger.log(with: .warning, message: "LookinUSBMux - ignoring a usbmuxd broadcast without a DeviceID: \(messageType ?? "(null)")") return } switch messageType { @@ -215,7 +218,7 @@ case "Detached": onEvent(.detached(deviceID: deviceID)) default: - NSLog("LookinUSBMux - ignoring a usbmuxd broadcast: %@", messageType ?? "(null)") + LookInsideServerLogger.log(with: .warning, message: "LookinUSBMux - ignoring a usbmuxd broadcast: \(messageType ?? "(null)")") } } @@ -224,9 +227,9 @@ /// Opens a byte stream to `port` on the device `deviceID`. /// `completion` runs once on `queue` with the connected socket /// (blocking; the caller owns it) and the bytes already read past - /// the Result, or with the error: `LookinUSBMuxError` for a + /// the Result, or with the error: `USBMuxError` for a /// refused Connect (code 3 when nothing listens on the port), - /// `LookinSocket.Error` for a socket failure (ETIMEDOUT after + /// `SocketConnector.Error` for a socket failure (ETIMEDOUT after /// `timeout`). public func connect( deviceID: Int, @@ -242,13 +245,13 @@ let result: Result<(fileDescriptor: Int32, initialBytes: Data), Error> var fd: Int32 = -1 do { - fd = try LookinSocket.connectUnix(path: socketPath) + fd = try SocketConnector.connectUnix(path: socketPath) guard attempt.register(fd) else { Darwin.close(fd) return } - let request = try LookinUSBMuxPacket( - plist: LookinUSBMux.connectRequest(deviceID: deviceID, port: port, identity: identity), + let request = try USBMuxPacket( + plist: USBMux.connectRequest(deviceID: deviceID, port: port, identity: identity), tag: Self.firstTag ) try Self.writeAll(fd, request.encoded) @@ -270,22 +273,22 @@ } ioQueue.asyncAfter(deadline: .now() + timeout) { guard attempt.timeOut() else { return } - finish(.failure(LookinSocket.Error(code: ETIMEDOUT))) + finish(.failure(SocketConnector.Error(code: ETIMEDOUT))) } } /// Reads one reply and returns the bytes after it. private static func readConnectResult(_ fd: Int32) throws -> Data { - var decoder = LookinUSBMuxDecoder() + var decoder = USBMuxDecoder() while true { if let packet = try decoder.next() { - if let error = try LookinUSBMuxError.fromResult(packet.plistDictionary()) { + if let error = try USBMuxError.fromResult(packet.plistDictionary()) { throw error } return decoder.takeRemainingBytes() } guard let bytes = try readSome(fd) else { - throw LookinSocket.Error(code: ECONNRESET) + throw SocketConnector.Error(code: ECONNRESET) } decoder.append(bytes) } @@ -339,7 +342,7 @@ if errno == EINTR { continue } - throw LookinSocket.Error(code: errno) + throw SocketConnector.Error(code: errno) } offset += written } @@ -360,7 +363,7 @@ if errno == EINTR { continue } - throw LookinSocket.Error(code: errno) + throw SocketConnector.Error(code: errno) } } } diff --git a/Sources/LookinCoreImpl/LookinTuple.swift b/Sources/LookinCoreImpl/TwoTuple.swift similarity index 84% rename from Sources/LookinCoreImpl/LookinTuple.swift rename to Sources/LookinCoreImpl/TwoTuple.swift index 885022a5..ff6dea01 100644 --- a/Sources/LookinCoreImpl/LookinTuple.swift +++ b/Sources/LookinCoreImpl/TwoTuple.swift @@ -1,5 +1,5 @@ // -// LookinTuple.swift +// TwoTuple.swift // LookinCore // // Was LookinTuple.m. The archived class names, coding keys and value types @@ -14,11 +14,11 @@ #endif @objc(LookinTwoTuple) - public class LookinTwoTuple: NSObject, NSCoding, NSSecureCoding { + public class TwoTuple: NSObject, NSCoding, NSSecureCoding { @objc(first) - public var first: NSObject! + public var first: NSObject? @objc(second) - public var second: NSObject! + public var second: NSObject? // MARK: NSSecureCoding @@ -53,7 +53,7 @@ if let object = object as? NSObject, object === self { return true } - guard let compared = object as? LookinTwoTuple else { + guard let compared = object as? TwoTuple else { return false } // [nil isEqual:] is NO in Objective-C, so two nil members never match. @@ -65,17 +65,17 @@ } @objc(LookinStringTwoTuple) - public class LookinStringTwoTuple: NSObject, NSCoding, NSSecureCoding, NSCopying { + public class StringTwoTuple: NSObject, NSCoding, NSSecureCoding, NSCopying { @objc(first) - public var first: String! + public var first: String? @objc(second) - public var second: String! + public var second: String? /// `+tupleWithFirst:second:`. An Objective-C factory must be a class /// method here: implemented as a Swift initializer it compiles but /// registers no class method. @objc(tupleWithFirst:second:) - public class func tuple(first firstString: String?, second secondString: String?) -> Self! { + public class func tuple(first firstString: String?, second secondString: String?) -> Self { let tuple = unsafeDowncast((self as NSObject.Type).init(), to: self) tuple.first = firstString tuple.second = secondString @@ -90,7 +90,7 @@ @objc(copyWithZone:) public func copy(with _: NSZone? = nil) -> Any { - let tuple = LookinStringTwoTuple() + let tuple = StringTwoTuple() tuple.first = first tuple.second = second return tuple @@ -118,8 +118,8 @@ /// Swift spelling the Host has always used; the factory class method is /// `tuple(first:second:)`. - public extension LookinStringTwoTuple { - convenience init(first firstString: String, second secondString: String) { + public extension StringTwoTuple { + convenience init(first firstString: String?, second secondString: String?) { self.init() first = firstString second = secondString diff --git a/Sources/LookinCoreImpl/LookinWeakContainer.swift b/Sources/LookinCoreImpl/WeakContainer.swift similarity index 86% rename from Sources/LookinCoreImpl/LookinWeakContainer.swift rename to Sources/LookinCoreImpl/WeakContainer.swift index 8b5daa80..071df0a8 100644 --- a/Sources/LookinCoreImpl/LookinWeakContainer.swift +++ b/Sources/LookinCoreImpl/WeakContainer.swift @@ -1,5 +1,5 @@ // -// LookinWeakContainer.swift +// WeakContainer.swift // Lookin // // Was LookinWeakContainer.m. @@ -13,7 +13,7 @@ #endif @objc(LookinWeakContainer) - public class LookinWeakContainer: NSObject { + public class WeakContainer: NSObject { @objc(object) public weak var object: AnyObject? @@ -21,7 +21,7 @@ /// method here: implemented as a Swift initializer it compiles but /// registers no class method. @objc(containerWithObject:) - public class func container(object: Any?) -> Self! { + public class func container(object: Any?) -> Self { let container = unsafeDowncast((self as NSObject.Type).init(), to: self) container.object = object as AnyObject? return container @@ -41,7 +41,7 @@ if let object = object as? NSObject, object === self { return true } - guard let compared = object as? LookinWeakContainer else { + guard let compared = object as? WeakContainer else { return false } // [nil isEqual:] is NO. diff --git a/Sources/LookinServerBase/LookinIvarTrace.h b/Sources/LookinServerBase/LookinIvarTrace.h index c25108f4..9526bec6 100644 --- a/Sources/LookinServerBase/LookinIvarTrace.h +++ b/Sources/LookinServerBase/LookinIvarTrace.h @@ -10,7 +10,7 @@ // Created by Li Kai on 2019/4/30. // https://lookin.work // -// The LookinIvarTrace class is plain Swift (LookinCoreImpl/LookinIvarTrace.swift, +// The LookinIvarTrace class is plain Swift (LookinCoreImpl/InstanceVariableTrace.swift, // `@objc(LookinIvarTrace)`); `-[NSObject lks_ivarTraces]` is a Swift `@objc` // extension member in LookinServerImpl. Only the exported C constant stays // here (defined in LookinIvarTraceConstants.m). diff --git a/Sources/LookinServerBase/LookinIvarTraceConstants.m b/Sources/LookinServerBase/LookinIvarTraceConstants.m index 2b44e310..4c9930cd 100644 --- a/Sources/LookinServerBase/LookinIvarTraceConstants.m +++ b/Sources/LookinServerBase/LookinIvarTraceConstants.m @@ -5,7 +5,7 @@ // Lookin // // The exported string constant declared in LookinIvarTrace.h. The class is -// implemented in Swift (LookinCoreImpl/LookinIvarTrace.swift); Swift cannot +// implemented in Swift (LookinCoreImpl/InstanceVariableTrace.swift); Swift cannot // define a C global, so the constant stays here. // diff --git a/Tests/Dashboard/LKDashboardTests.swift b/Tests/Dashboard/LKDashboardTests.swift index 55b53155..c592508d 100644 --- a/Tests/Dashboard/LKDashboardTests.swift +++ b/Tests/Dashboard/LKDashboardTests.swift @@ -31,13 +31,13 @@ struct LKDashboardTests { private static let clientVersion = "2.4.0" - private static func makeItem() -> LookinDisplayItem { - func object(_ oid: UInt) -> LookinObject { - let object = LookinObject() + private static func makeItem() -> DisplayItem { + func object(_ oid: UInt) -> InspectedObject { + let object = InspectedObject() object.oid = oid return object } - let item = LookinDisplayItem() + let item = DisplayItem() item.viewObject = object(11) item.layerObject = object(22) item.windowObject = object(33) @@ -47,23 +47,23 @@ struct LKDashboardTests { /// `-[LKDashboardViewController modifyInbuiltAttribute:newValue:]` /// before the rewrite. - private static func objectiveCInbuiltPayload(attribute: LookinAttribute, newValue: Any?) -> LookinAttributeModification { + private static func objectiveCInbuiltPayload(attribute: InspectedAttribute, newValue: Any?) -> AttributeModification { let modifyingItem = attribute.targetDisplayItem! - let modification = LookinAttributeModification() + let modification = AttributeModification() modification.clientReadableVersion = clientVersion - switch LookinDashboardBlueprint.targetKind(forAttrID: attribute.identifier) { + switch DashboardBlueprint.targetKind(forAttrID: attribute.identifier) { case .view: - modification.targetOid = modifyingItem.viewObject.oid + modification.targetOid = modifyingItem.viewObject?.oid ?? 0 case .window: - modification.targetOid = modifyingItem.windowObject.oid + modification.targetOid = modifyingItem.windowObject?.oid ?? 0 case .cell: - modification.targetOid = modifyingItem.cellObject.oid + modification.targetOid = modifyingItem.cellObject?.oid ?? 0 case .layer: - modification.targetOid = modifyingItem.layerObject.oid + modification.targetOid = modifyingItem.layerObject?.oid ?? 0 @unknown default: fail("unknown target kind") } - modification.setterSelector = LookinDashboardBlueprint.setter(withAttrID: attribute.identifier) + modification.setterSelector = DashboardBlueprint.setter(withAttrID: attribute.identifier) modification.attrType = attribute.attrType modification.value = newValue return modification @@ -98,13 +98,13 @@ struct LKDashboardTests { defer { withExtendedLifetime(item) {} } var checked = 0 var kinds = Set() - for groupID in LookinDashboardBlueprint.groupIDs() ?? [] { - for sectionID in LookinDashboardBlueprint.sectionIDs(forGroupID: groupID) ?? [] { - for attrID in LookinDashboardBlueprint.attrIDs(forSectionID: sectionID) ?? [] { - guard LookinDashboardBlueprint.setter(withAttrID: attrID) != nil else { continue } - let attribute = LookinAttribute() + for groupID in DashboardBlueprint.groupIDs() ?? [] { + for sectionID in DashboardBlueprint.sectionIDs(forGroupID: groupID) ?? [] { + for attrID in DashboardBlueprint.attrIDs(forSectionID: sectionID) ?? [] { + guard DashboardBlueprint.setter(withAttrID: attrID) != nil else { continue } + let attribute = InspectedAttribute() attribute.identifier = attrID - attribute.attrType = LookinDashboardBlueprint.objectAttrType(withAttrID: attrID) + attribute.attrType = DashboardBlueprint.objectAttrType(withAttrID: attrID) attribute.targetDisplayItem = item let newValue = sampleValue(for: attribute.attrType) @@ -114,7 +114,7 @@ struct LKDashboardTests { let expected = objectiveCInbuiltPayload(attribute: attribute, newValue: newValue) expect(archive(payload) == archive(expected), "\(attrID): payload differs from the Objective-C one") expect(payload.targetOid != 0, "\(attrID): no target object") - kinds.insert(LookinDashboardBlueprint.targetKind(forAttrID: attrID).rawValue) + kinds.insert(DashboardBlueprint.targetKind(forAttrID: attrID).rawValue) checked += 1 } } @@ -125,7 +125,7 @@ struct LKDashboardTests { } private static func testInbuiltPayloadWithoutSetter() { - let attribute = LookinAttribute() + let attribute = InspectedAttribute() attribute.identifier = LookinAttr_Class_Class_Class attribute.attrType = .customObj attribute.targetDisplayItem = makeItem() @@ -134,7 +134,7 @@ struct LKDashboardTests { } private static func testCustomPayload() { - let attribute = LookinAttribute() + let attribute = InspectedAttribute() attribute.identifier = LookinAttr_UserCustom attribute.attrType = .double attribute.customSetterID = "setter-7" @@ -144,7 +144,7 @@ struct LKDashboardTests { fail("a custom attribute with a setter has no payload") } // -[LKDashboardViewController modifyCustomAttribute:newValue:] - let expected = LookinCustomAttrModification() + let expected = CustomAttributeModification() expected.customSetterID = attribute.customSetterID expected.attrType = attribute.attrType expected.value = newValue @@ -152,7 +152,7 @@ struct LKDashboardTests { } private static func testCustomPayloadWithoutSetter() { - let attribute = LookinAttribute() + let attribute = InspectedAttribute() attribute.identifier = LookinAttr_UserCustom attribute.attrType = .nsString expect(LKDashboardModification.custom(attribute: attribute, newValue: "x") == nil, @@ -186,7 +186,7 @@ struct LKDashboardTests { // The attribute holds its item weakly; keep the item alive. let item = makeItem() withExtendedLifetime(item) { - let attribute = LookinAttribute() + let attribute = InspectedAttribute() attribute.identifier = LookinAttr_Layout_Frame_Frame attribute.attrType = .cgRect attribute.targetDisplayItem = item @@ -202,19 +202,19 @@ struct LKDashboardTests { } private static func testNumberValueClampsOpacity() { - let opacity = LookinAttribute() + let opacity = InspectedAttribute() opacity.identifier = LookinAttr_ViewLayer_Visibility_Opacity opacity.value = NSNumber(value: 0.5) expect(LKDashboardModification.numberValue(NSNumber(value: 1.7), for: opacity) == NSNumber(value: 1.0), "opacity above 1") expect(LKDashboardModification.numberValue(NSNumber(value: -0.2), for: opacity) == NSNumber(value: 0.0), "opacity below 0") expect(LKDashboardModification.numberValue(NSNumber(value: 0.5), for: opacity) == nil, "unchanged opacity") - let shadowOpacity = LookinAttribute() + let shadowOpacity = InspectedAttribute() shadowOpacity.identifier = LookinAttr_ViewLayer_Shadow_Opacity shadowOpacity.value = NSNumber(value: 1.0) expect(LKDashboardModification.numberValue(NSNumber(value: 4), for: shadowOpacity) == nil, "shadow opacity clamps to the unchanged 1") - let radius = LookinAttribute() + let radius = InspectedAttribute() radius.identifier = LookinAttr_ViewLayer_Corner_Radius radius.value = NSNumber(value: 4) expect(LKDashboardModification.numberValue(NSNumber(value: 12), for: radius) == NSNumber(value: 12), "radius is not clamped") @@ -233,8 +233,8 @@ struct LKDashboardTests { // MARK: - Constraints private static func testConstraintOrder() { - func constraint(effective: Bool, type: LookinConstraintItemType, attribute: Int, constant: CGFloat) -> LookinAutoLayoutConstraint { - let constraint = LookinAutoLayoutConstraint() + func constraint(effective: Bool, type: LookinConstraintItemType, attribute: Int, constant: CGFloat) -> AutoLayoutConstraint { + let constraint = AutoLayoutConstraint() constraint.effective = effective constraint.firstItemType = type constraint.firstAttribute = attribute diff --git a/Tests/Read/LaunchToolbarReadTests.swift b/Tests/Read/LaunchToolbarReadTests.swift index bb6447af..8a80e28f 100644 --- a/Tests/Read/LaunchToolbarReadTests.swift +++ b/Tests/Read/LaunchToolbarReadTests.swift @@ -115,14 +115,14 @@ struct LaunchToolbarReadTests { (LOOKIN_SUPPORTED_SERVER_MIN - 1, LookinErrCode_ServerVersionTooLow), (LOOKIN_SUPPORTED_SERVER_MAX + 1, LookinErrCode_ServerVersionTooHigh), ] { - let file = LookinHierarchyFile() + let file = HierarchyFile() file.serverVersion = version - file.hierarchyInfo = LookinHierarchyInfo() + file.hierarchyInfo = HierarchyInfo() expectError(encode(file), code: code, "server version \(version)") } - let file = LookinHierarchyFile() + let file = HierarchyFile() file.serverVersion = LOOKIN_SUPPORTED_SERVER_MIN - file.hierarchyInfo = LookinHierarchyInfo() + file.hierarchyInfo = HierarchyInfo() expect(decode(encode(file)).serverVersion == LOOKIN_SUPPORTED_SERVER_MIN, "oldest supported version opens") } @@ -215,7 +215,7 @@ struct LaunchToolbarReadTests { // MARK: - Helpers - private static func decode(_ data: Data) -> LookinHierarchyFile { + private static func decode(_ data: Data) -> HierarchyFile { do { return try LookinArchiveCoding.hierarchyFile(from: data) } catch { @@ -223,7 +223,7 @@ struct LaunchToolbarReadTests { } } - private static func encode(_ file: LookinHierarchyFile) -> Data { + private static func encode(_ file: HierarchyFile) -> Data { do { return try LookinArchiveCoding.data(of: file) } catch { diff --git a/Tests/XcodeViewHierarchy/LKXcodeViewHierarchyConverterTests.swift b/Tests/XcodeViewHierarchy/LKXcodeViewHierarchyConverterTests.swift index acfe5674..38cd31ee 100644 --- a/Tests/XcodeViewHierarchy/LKXcodeViewHierarchyConverterTests.swift +++ b/Tests/XcodeViewHierarchy/LKXcodeViewHierarchyConverterTests.swift @@ -3,7 +3,7 @@ import Foundation /// Coverage for turning a decoded capture into the inspector's model. /// -/// The converter is the one place that builds `LookinDisplayItem` trees in +/// The converter is the one place that builds `DisplayItem` trees in /// memory: outside the server, which sets every field explicitly, and outside /// the archive decoder, which supplies compatibility defaults for absent keys. /// Any field whose Objective-C default differs from what the reader expects is @@ -37,11 +37,11 @@ struct LKXcodeViewHierarchyConverterTests { private static func testColorAttributesCarryRGBAComponents() { let file = convertedFixture() var colorAttributes: [(identifier: String, value: Any?)] = [] - walk(file.hierarchyInfo.displayItems) { item in + walk(file.hierarchyInfo?.displayItems ?? []) { item in for group in item.attributesGroupList ?? [] { for section in group.attrSections ?? [] { for attribute in section.attributes ?? [] where attribute.attrType == .uiColor { - colorAttributes.append((attribute.identifier, attribute.value)) + colorAttributes.append((attribute.identifier ?? "", attribute.value)) } } } @@ -54,7 +54,7 @@ struct LKXcodeViewHierarchyConverterTests { fail("\(identifier) carries \(value.map { "\(type(of: $0))" } ?? "nil") rather than an RGBA NSNumber array") } expect(components.count == 4, "\(identifier) needs 4 components, got \(components.count)") - expect(NSColor.lookin_color(fromRGBAComponents: components) != nil, + expect(NSColor.sRGBColor(fromRGBAComponents: components) != nil, "\(identifier) does not decode as a colour") } @@ -75,7 +75,7 @@ struct LKXcodeViewHierarchyConverterTests { private static func testEveryConvertedNodeOptsIntoScreenshots() { let file = convertedFixture() var kindsSeen: Set = [] - walk(file.hierarchyInfo.displayItems) { item in + walk(file.hierarchyInfo?.displayItems ?? []) { item in kindsSeen.insert(item.nodeKind) expect(item.shouldCaptureImage, "\(item) (nodeKind \(item.nodeKind.rawValue)) would be dropped from the preview: shouldCaptureImage is NO") @@ -97,7 +97,7 @@ struct LKXcodeViewHierarchyConverterTests { /// views this rule now drops. private static func testAppKitTopLevelFollowsXcodeSidebar() { let file = convert(appKitSidebarFixture()) - let rootItems = file.hierarchyInfo.displayItems ?? [] + let rootItems = file.hierarchyInfo?.displayItems ?? [] expect(rootItems.map(displayedObjectIdentifier) == [0x3, 0x1, 0x2, 0x4, 0x60], "top level should be key window's controller, other controller, unowned windows, touch bar; got \(rootItems.map(displayedObjectIdentifier).map { String($0, radix: 16) })") @@ -130,7 +130,7 @@ struct LKXcodeViewHierarchyConverterTests { /// remote keyboard window never earns the exception. private static func testUIKitTopLevelFollowsXcodeSidebar() { let file = convert(uiKitSidebarFixture()) - let rootItems = file.hierarchyInfo.displayItems ?? [] + let rootItems = file.hierarchyInfo?.displayItems ?? [] expect(rootItems.map(displayedObjectIdentifier) == [0xF2, 0xF1, 0x4], "top level should be the key window's scene, the other scene, then the sceneless window; got \(rootItems.map(displayedObjectIdentifier).map { String($0, radix: 16) })") @@ -170,7 +170,7 @@ struct LKXcodeViewHierarchyConverterTests { /// in `classInformation` never reached the dashboard. private static func testClassCardListsRelatedClassChains() { let uiKit = convert(uiKitCardsFixture()) - let scene = uiKit.hierarchyInfo.displayItems?.first + let scene = uiKit.hierarchyInfo?.displayItems?.first expect(classChains(of: scene) == [["UIWindowScene", "UIScene"]], "a scene's chain stops at UIScene; got \(String(describing: classChains(of: scene)))") let window = scene?.subitems?.first @@ -188,7 +188,7 @@ struct LKXcodeViewHierarchyConverterTests { "a layout guide's chain stops at UILayoutGuide; got \(String(describing: classChains(of: guide)))") let appKit = convert(appKitCardsFixture()) - let panel = appKit.hierarchyInfo.displayItems?.first + let panel = appKit.hierarchyInfo?.displayItems?.first expect(classChains(of: panel) == [["NSPanel", "NSWindow"], ["MyWindowController", "NSWindowController"]], "an AppKit window lists its chain to NSWindow and its controller's; got \(String(describing: classChains(of: panel)))") expect(relations(of: panel) == ["(MyWindowController *).window", "(MyDelegate *) delegate"], @@ -247,7 +247,7 @@ struct LKXcodeViewHierarchyConverterTests { expectAttribute(LookinAttr_UIStackView_Axis_Axis, of: stackView, type: .enumLong, equals: NSNumber(value: 1)) expectAttribute(LookinAttr_UIStackView_Spacing_Spacing, of: stackView, type: .double, equals: NSNumber(value: 8)) - let scene = file.hierarchyInfo.displayItems?.first + let scene = file.hierarchyInfo?.displayItems?.first expectAttribute(LookinAttr_UIWindowScene_Title_Title, of: scene, type: .nsString, equals: "Main" as NSString) expectAttribute(LookinAttr_UIWindowScene_State_ActivationState, of: scene, type: .enumLong, equals: NSNumber(value: 0)) expectAttribute(LookinAttr_UIWindowScene_Windows_WindowCount, of: scene, type: .long, equals: NSNumber(value: 1)) @@ -268,7 +268,7 @@ struct LKXcodeViewHierarchyConverterTests { private static func testAppKitCardsReadTheCell() { let file = convert(appKitCardsFixture()) - let panel = file.hierarchyInfo.displayItems?.first + let panel = file.hierarchyInfo?.displayItems?.first expect(groupIdentifiers(of: panel) == [LookinAttrGroup_Class, LookinAttrGroup_Relation, LookinAttrGroup_Layout, LookinAttrGroup_NSWindow], "a window's cards: class, relation, layout, window; got \(groupIdentifiers(of: panel))") expectAttribute(LookinAttr_NSWindow_Title_Title, of: panel, type: .nsString, equals: "Inspector" as NSString) @@ -314,7 +314,7 @@ struct LKXcodeViewHierarchyConverterTests { let button = item(withObjectIdentifier: 0x11, in: file) guard let constraintsAttribute = attribute(LookinAttr_AutoLayout_Constraints_Constraints, of: button), constraintsAttribute.attrType == .customObj, - let constraints = constraintsAttribute.value as? [LookinAutoLayoutConstraint] + let constraints = constraintsAttribute.value as? [AutoLayoutConstraint] else { fail("a view with constraints gets a constraints row carrying LookinAutoLayoutConstraint values") } expect(constraints.map(\.constraintOid) == [0xD1, 0xD2, 0xD4], @@ -337,7 +337,7 @@ struct LKXcodeViewHierarchyConverterTests { expect(hugging?.attrType == .double && (hugging?.value as? NSNumber)?.doubleValue == 250, "sizing priorities ride along once the card exists") let rootView = item(withObjectIdentifier: 0x10, in: file) - expect((attribute(LookinAttr_AutoLayout_Constraints_Constraints, of: rootView)?.value as? [LookinAutoLayoutConstraint])? + expect((attribute(LookinAttr_AutoLayout_Constraints_Constraints, of: rootView)?.value as? [AutoLayoutConstraint])? .map(\.constraintOid) == [0xD2], "the superview lists the same constraint from its own side") } @@ -448,7 +448,7 @@ struct LKXcodeViewHierarchyConverterTests { } /// The kinds and objects of a node's children, e.g. `["layer:0x101", "view:0x11"]`. - private static func childShape(of item: LookinDisplayItem) -> [String] { + private static func childShape(of item: DisplayItem) -> [String] { (item.subitems ?? []).map { subitem in let kindName: String switch subitem.nodeKind { @@ -979,9 +979,9 @@ struct LKXcodeViewHierarchyConverterTests { // MARK: - Card helpers - private static func item(withObjectIdentifier identifier: UInt, in file: LookinHierarchyFile) -> LookinDisplayItem { - var found: LookinDisplayItem? - walk(file.hierarchyInfo.displayItems ?? []) { item in + private static func item(withObjectIdentifier identifier: UInt, in file: HierarchyFile) -> DisplayItem { + var found: DisplayItem? + walk(file.hierarchyInfo?.displayItems ?? []) { item in if found == nil, displayedObjectIdentifier(item) == identifier { found = item } @@ -990,7 +990,7 @@ struct LKXcodeViewHierarchyConverterTests { return found } - private static func attribute(_ identifier: String, of item: LookinDisplayItem?) -> LookinAttribute? { + private static func attribute(_ identifier: String, of item: DisplayItem?) -> InspectedAttribute? { for group in item?.attributesGroupList ?? [] { for section in group.attrSections ?? [] { if let attribute = section.attributes?.first(where: { $0.identifier == identifier }) { @@ -1003,7 +1003,7 @@ struct LKXcodeViewHierarchyConverterTests { private static func expectAttribute( _ identifier: String, - of item: LookinDisplayItem?, + of item: DisplayItem?, type attrType: LookinAttrType, equals expected: NSObject ) { @@ -1013,27 +1013,27 @@ struct LKXcodeViewHierarchyConverterTests { "\(identifier) is \(String(describing: attribute.value)), expected \(expected)") } - private static func groupIdentifiers(of item: LookinDisplayItem?) -> [String] { + private static func groupIdentifiers(of item: DisplayItem?) -> [String] { (item?.attributesGroupList ?? []).compactMap(\.identifier) } - private static func classChains(of item: LookinDisplayItem?) -> [[String]]? { + private static func classChains(of item: DisplayItem?) -> [[String]]? { attribute(LookinAttr_Class_Class_Class, of: item)?.value as? [[String]] } - private static func relations(of item: LookinDisplayItem?) -> [String]? { + private static func relations(of item: DisplayItem?) -> [String]? { attribute(LookinAttr_Relation_Relation_Relation, of: item)?.value as? [String] } /// The object a row stands for, whichever slot its kind rides. - private static func displayedObjectIdentifier(_ item: LookinDisplayItem) -> UInt { + private static func displayedObjectIdentifier(_ item: DisplayItem) -> UInt { (item.kindObject ?? item.windowObject ?? item.viewObject ?? item.layerObject)?.oid ?? 0 } /// An AppKit capture: one window whose content view owns a layer carrying /// background and border colours and a layout guide, plus a control /// subview with a cell. Every node kind the converter emits appears once. - private static func convertedFixture() -> LookinHierarchyFile { + private static func convertedFixture() -> HierarchyFile { let builder = LKXcodeViewHierarchyObjectGraphBuilder() builder.ingesting(response: response(groups: [ group("com.apple.AppKit.NSWindow", objects: [ @@ -1075,7 +1075,7 @@ struct LKXcodeViewHierarchyConverterTests { } /// Runs the converter over a graph with no recovered pixels. - private static func convert(_ graph: LKXcodeViewHierarchyObjectGraph) -> LookinHierarchyFile { + private static func convert(_ graph: LKXcodeViewHierarchyObjectGraph) -> HierarchyFile { convert( graph, screenshots: LKXcodeViewHierarchyScreenshots( @@ -1089,7 +1089,7 @@ struct LKXcodeViewHierarchyConverterTests { _ graph: LKXcodeViewHierarchyObjectGraph, screenshots: LKXcodeViewHierarchyScreenshots, showingBackingLayers: Bool - ) -> LookinHierarchyFile { + ) -> HierarchyFile { let bundle = LKXcodeViewHierarchyBundle( metadata: LKXcodeViewHierarchyBundleMetadata( documentVersion: "1", runnableDisplayName: "Fixture", runnableProcessIdentifier: 1 @@ -1238,7 +1238,7 @@ struct LKXcodeViewHierarchyConverterTests { // MARK: - Helpers - private static func walk(_ items: [LookinDisplayItem], _ visit: (LookinDisplayItem) -> Void) { + private static func walk(_ items: [DisplayItem], _ visit: (DisplayItem) -> Void) { for item in items { visit(item) walk(item.subitems ?? [], visit) From 43c34d8d46602b3ff717e59f0b1b19acb04580f9 Mon Sep 17 00:00:00 2001 From: Mx-Iris Date: Fri, 9 Oct 2026 00:59:16 +0800 Subject: [PATCH 2/5] Drop the LK / Lookin prefixes from the host's Swift type names The host's own types follow the same rules as LookinCore's: the prefix goes (LKHierarchyView -> HierarchyView, LookinLiveDocument -> LiveDocument), a name that would be too generic or clash with SwiftUI gets a descriptive one (LKLabel -> TextLabel, LKWindow -> AppWindow, LKChannel -> ServerChannel, LKHelper -> AppHelper), abbreviations are spelled out (LKDashboardAttributeJsonView -> DashboardAttributeJSONView, LookinMsgAttribute -> MessageAttribute), and LookinPreferredAppeanranceType is PreferredAppearanceType. Files follow their main type, including the category files named after a LookinCore type (LookinDisplayItem+LookinClient.swift -> DisplayItem+LookinClient.swift); the target's membershipExceptions list and the test scripts that compile host files by path follow the file names. The @objc(...) names stay as they are in this commit, so the three document classes Info.plist names and every runtime lookup keep working. The custom object encoder of the MCP bridge reports NSStringFromClass now: the LookinCore model classes kept their Objective-C names, so the class names it sends are the same as before. Also mirrors LookInside-Server 53abf34, where DisplayItem types its previewNode with the renamed DisplayItemNode. Co-Authored-By: Claude Opus 5.5 --- LookInside.xcodeproj/project.pbxproj | 350 +++++++++--------- ...ller.swift => AboutWindowController.swift} | 36 +- LookInside/AppDelegate.swift | 36 +- .../Base/{LKWindow.swift => AppWindow.swift} | 6 +- ...{LKBaseControl.swift => BaseControl.swift} | 6 +- .../Base/{LKBaseView.swift => BaseView.swift} | 22 +- ...troller.swift => BaseViewController.swift} | 20 +- ...ift => AttributesGroup+LookinClient.swift} | 2 +- ...> AutoLayoutConstraint+LookinClient.swift} | 0 ...t.swift => DisplayItem+LookinClient.swift} | 2 +- ...ift => InspectedObject+LookinClient.swift} | 4 +- ...rLayer.swift => ColorIndicatorLayer.swift} | 8 +- ...ding.swift => ConnectionTipsBinding.swift} | 8 +- ...rovider.swift => DeviceIconProvider.swift} | 2 +- ...{LKFrameLayout.swift => FrameLayout.swift} | 110 +++--- ...mageTextView.swift => ImageTextView.swift} | 6 +- ...SearchView.swift => InputSearchView.swift} | 46 +-- .../NSView+LKPeripheralLayout.swift | 10 +- ...Attribute.swift => MessageAttribute.swift} | 42 +-- ...ralAlerts.swift => PeripheralAlerts.swift} | 4 +- ...rInputView.swift => NumberInputView.swift} | 12 +- ...lineRowView.swift => OutlineRowView.swift} | 20 +- ...porter.swift => PerformanceReporter.swift} | 8 +- .../Base/{LKPopPanel.swift => PopPanel.swift} | 6 +- ...View.swift => ProgressIndicatorView.swift} | 6 +- .../{LKSplitView.swift => SplitView.swift} | 6 +- ...ftDemangler.swift => SwiftDemangler.swift} | 4 +- ...KTableRowView.swift => TableRowView.swift} | 22 +- .../{LKTableView.swift => TableView.swift} | 46 +-- ...bleViewHorizontalScrollWidthManager.swift} | 4 +- ...{LKTextControl.swift => TextControl.swift} | 6 +- ...extFieldView.swift => TextFieldView.swift} | 14 +- .../Base/{LKLabel.swift => TextLabel.swift} | 8 +- ...extsMenuView.swift => TextsMenuView.swift} | 16 +- .../Base/{LKTipsView.swift => TipsView.swift} | 16 +- .../{LKTwoColors.swift => TwoColors.swift} | 8 +- ...nManager.swift => UserActionManager.swift} | 22 +- ...ontroller.swift => WindowController.swift} | 4 +- ....swift => InstallerArchiveExtractor.swift} | 4 +- ...tion.swift => InstallerCancellation.swift} | 6 +- ...ure.swift => InstallerCodeSignature.swift} | 6 +- ...loader.swift => InstallerDownloader.swift} | 20 +- ...system.swift => InstallerFilesystem.swift} | 2 +- ...llerLogger.swift => InstallerLogger.swift} | 2 +- ...> InstallerProgressWindowController.swift} | 2 +- ...{LKAppsManager.swift => AppsManager.swift} | 28 +- ....swift => ConnectionManager+License.swift} | 40 +- ...nManager.swift => ConnectionManager.swift} | 128 +++---- ...nRequest.swift => ConnectionRequest.swift} | 22 +- ...pectableApp.swift => InspectableApp.swift} | 50 +-- .../Connection/LKConnectionErrors.swift | 2 +- ...nLiveDocument.swift => LiveDocument.swift} | 40 +- ...ler.swift => LiveDocumentController.swift} | 22 +- .../{LKChannel.swift => ServerChannel.swift} | 22 +- ...radeHint.swift => ServerUpgradeHint.swift} | 8 +- ...taSource.swift => ConsoleDataSource.swift} | 36 +- ...t => ConsoleSelectPopoverController.swift} | 48 +-- ...ller.swift => ConsoleViewController.swift} | 36 +- LookInside/Console/LKConsoleRowViews.swift | 34 +- .../DanceScript/DanceScriptManager.swift | 14 +- ...wift => ConstraintPopoverController.swift} | 26 +- ...> DashboardAttributeConstraintsView.swift} | 22 +- ...wift => DashboardAttributeColorView.swift} | 32 +- ...wift => DashboardAttributeEnumsView.swift} | 22 +- ...> DashboardAttributeNumberInputView.swift} | 16 +- ...rdAttributePrivateDiscriminatorView.swift} | 82 ++-- ...> DashboardAttributeStringArrayView.swift} | 26 +- ...ift => DashboardAttributeSwitchView.swift} | 12 +- ...swift => DashboardAttributeTextView.swift} | 20 +- ...iew.swift => DashboardAttributeView.swift} | 10 +- ...buteItem.swift => JSONAttributeItem.swift} | 16 +- .../JSON/LKJSONAttributeViews.swift | 72 ++-- .../LKDashboardAttributeGeometryViews.swift | 40 +- .../LKDashboardAttributeReadOnlyViews.swift | 68 ++-- ... DashboardAccessoryWindowController.swift} | 28 +- ...CardView.swift => DashboardCardView.swift} | 84 ++--- ...oardLayout.swift => DashboardLayout.swift} | 30 +- ...tion.swift => DashboardModification.swift} | 6 +- ...nView.swift => DashboardSectionView.swift} | 100 ++--- ...er.swift => DashboardViewController.swift} | 116 +++--- ...tRegistry.swift => EnumListRegistry.swift} | 20 +- ...erView.swift => DashboardHeaderView.swift} | 26 +- .../Search/LKDashboardSearchViews.swift | 82 ++-- ...KDebugE2EDump.swift => DebugE2EDump.swift} | 56 +-- ...pWriter.swift => DebugE2EDumpWriter.swift} | 46 +-- ...Snapshots.swift => DebugUISnapshots.swift} | 100 ++--- ...ndowImage.swift => DebugWindowImage.swift} | 6 +- ...malizer.swift => SnapshotNormalizer.swift} | 36 +- ...ryView.swift => ExportAccessoryView.swift} | 12 +- ...xportManager.swift => ExportManager.swift} | 18 +- ...ession.swift => GestureDebugSession.swift} | 36 +- ...DebugView.swift => GestureDebugView.swift} | 16 +- ...ift => GestureDebugWindowController.swift} | 10 +- ...View.swift => GestureNodeDetailView.swift} | 6 +- ...w.swift => HitTargetSuggestionsView.swift} | 10 +- .../GestureDebug/LKGestureCaptureModels.swift | 70 ++-- LookInside/GestureDebug/LKSuggestions.swift | 28 +- ...wift => NativeInteractionDetailView.swift} | 6 +- ...aker.swift => DanceUIAttributeMaker.swift} | 4 +- ...roller.swift => HierarchyController.swift} | 32 +- ...wift => HierarchyDataSource+KeyDown.swift} | 4 +- ...Source.swift => HierarchyDataSource.swift} | 68 ++-- ...ayout.swift => HierarchyFrameLayout.swift} | 10 +- ... HierarchyHandlersPopoverController.swift} | 48 +-- ...hyRowView.swift => HierarchyRowView.swift} | 34 +- ...ierarchyView.swift => HierarchyView.swift} | 118 +++--- .../{LKSyncSignal.swift => SyncSignal.swift} | 20 +- ...itor.swift => AttachedDeviceMonitor.swift} | 8 +- ...Client.swift => DeviceControlClient.swift} | 34 +- ...trolWire.swift => DeviceControlWire.swift} | 22 +- ...onFlow.swift => DeviceInjectionFlow.swift} | 48 +-- ...ift => InjectableFrameworkInstaller.swift} | 140 +++---- ...njectionFlow.swift => InjectionFlow.swift} | 58 +-- ...onService.swift => InjectionService.swift} | 36 +- ...artGate.swift => InjectionStartGate.swift} | 14 +- ...cker.swift => InjectionTargetPicker.swift} | 2 +- ...aunchAppView.swift => LaunchAppView.swift} | 50 +-- ...{LKLaunchRules.swift => LaunchRules.swift} | 4 +- ...oller.swift => LaunchViewController.swift} | 62 ++-- ...ler.swift => LaunchWindowController.swift} | 10 +- LookInside/MCPBridge/LKMCPBridgeFrame.swift | 52 +-- .../LKMCPBridgeInspectionModels.swift | 76 ++-- ....swift => MCPBridgeAttributeEncoder.swift} | 68 ++-- ...t => MCPBridgeAttributeValueDecoder.swift} | 40 +- ...ection.swift => MCPBridgeConnection.swift} | 28 +- ...ce.swift => MCPBridgeDetailsService.swift} | 70 ++-- ...er.swift => MCPBridgeEventPublisher.swift} | 66 ++-- ...swift => MCPBridgeInspectionService.swift} | 80 ++-- ...swift => MCPBridgeInvocationService.swift} | 66 ++-- ...cket.swift => MCPBridgeListenSocket.swift} | 24 +- ...wift => MCPBridgeLiveDocumentLookup.swift} | 20 +- ...ift => MCPBridgeModificationService.swift} | 90 ++--- ...ft => MCPBridgeObjectIdentifierList.swift} | 10 +- ...ce.swift => MCPBridgeRefreshService.swift} | 52 +-- ...swift => MCPBridgeScreenshotService.swift} | 72 ++-- ...Query.swift => MCPBridgeSearchQuery.swift} | 8 +- ...ice.swift => MCPBridgeSearchService.swift} | 70 ++-- ...t => MCPBridgeSecureContentDetector.swift} | 4 +- ...e.swift => MCPBridgeSelectorService.swift} | 46 +-- ...idgeServer.swift => MCPBridgeServer.swift} | 98 ++--- .../{LKHelper.swift => AppHelper.swift} | 8 +- ...MenuManager.swift => AppMenuManager.swift} | 74 ++-- ...nManager.swift => NavigationManager.swift} | 32 +- ...eManager.swift => PreferenceManager.swift} | 90 ++--- ...ntroller.swift => MeasureController.swift} | 34 +- ...sultView.swift => MeasureResultView.swift} | 16 +- ...onComparer.swift => VersionComparer.swift} | 4 +- LookInside/Preference/LKPreferenceView.swift | 24 +- ...swift => PreferenceWindowController.swift} | 14 +- ...scriminatorSettingsWindowController.swift} | 14 +- ....swift => PrivateDiscriminatorStore.swift} | 58 +-- ...rchiveCoding.swift => ArchiveCoding.swift} | 6 +- ...veDocument.swift => ArchiveDocument.swift} | 16 +- ...er.swift => ReadHierarchyController.swift} | 8 +- ...ce.swift => ReadHierarchyDataSource.swift} | 14 +- ...ookup.swift => ReadScreenshotLookup.swift} | 4 +- ...troller.swift => ReadViewController.swift} | 50 +-- ...oller.swift => ReadWindowController.swift} | 68 ++-- LookInside/Static/LKStaticConstants.swift | 6 +- ...sageManager.swift => MessageManager.swift} | 8 +- ...ayItemNode.swift => DisplayItemNode.swift} | 16 +- ...ntroller.swift => PreviewController.swift} | 70 ++-- ...StageView.swift => PreviewStageView.swift} | 14 +- ...{LKPreviewView.swift => PreviewView.swift} | 26 +- ...r.swift => StaticAsyncUpdateManager.swift} | 84 ++--- ....swift => StaticHierarchyController.swift} | 10 +- ....swift => StaticHierarchyDataSource.swift} | 24 +- ...KStaticLayout.swift => StaticLayout.swift} | 8 +- ...oller.swift => StaticViewController.swift} | 134 +++---- ...ler.swift => StaticWindowController.swift} | 124 +++---- ...wift => SwiftUIHierarchyDisplayMode.swift} | 14 +- ...r.swift => SwiftUISupportGatekeeper.swift} | 48 +-- ...ogger.swift => SwiftUISupportLogger.swift} | 2 +- ...ft => MenuPopoverAppsListController.swift} | 34 +- ...ift => MenuPopoverSettingController.swift} | 32 +- ...KToolbarRules.swift => ToolbarRules.swift} | 4 +- ...rameLayout.swift => ViewFrameLayout.swift} | 12 +- ...ton.swift => WindowToolbarAppButton.swift} | 26 +- ...Helper.swift => WindowToolbarHelper.swift} | 66 ++-- ...iew.swift => WindowToolbarScaleView.swift} | 20 +- ... XcodeViewHierarchyAttributeCatalog.swift} | 12 +- ...ift => XcodeViewHierarchyAttributes.swift} | 122 +++--- ...t => XcodeViewHierarchyBundleReader.swift} | 40 +- ...wift => XcodeViewHierarchyConverter.swift} | 156 ++++---- ...swift => XcodeViewHierarchyDocument.swift} | 44 +-- ...zip.swift => XcodeViewHierarchyGzip.swift} | 26 +- ...t => XcodeViewHierarchyLayerArchive.swift} | 28 +- ... => XcodeViewHierarchyLayerTopology.swift} | 8 +- ...ft => XcodeViewHierarchyObjectGraph.swift} | 46 +-- ... => XcodeViewHierarchyPixelRecovery.swift} | 20 +- ...ue.swift => XcodeViewHierarchyValue.swift} | 84 ++--- Scripts/test-dashboard.sh | 8 +- Scripts/test-gesture-models.sh | 2 +- Scripts/test-launch-toolbar-read.sh | 8 +- Scripts/test-mcp-bridge.sh | 12 +- Scripts/test-security-gates.sh | 4 +- Scripts/test-xcode-viewhierarchy.sh | 48 +-- Sources/LookinCoreImpl/DisplayItem.swift | 6 +- ...hboardTests.swift => DashboardTests.swift} | 76 ++-- ....swift => GestureCaptureModelsTests.swift} | 62 ++-- ...swift => MCPBridgeListenSocketTests.swift} | 28 +- ... MCPBridgeObjectIdentifierListTests.swift} | 30 +- ....swift => MCPBridgeSearchQueryTests.swift} | 50 +-- Tests/Read/LaunchToolbarReadTests.swift | 60 +-- ...ts.swift => InjectionStartGateTests.swift} | 16 +- ...=> XcodeViewHierarchyConverterTests.swift} | 48 +-- ...wift => XcodeViewHierarchyGzipTests.swift} | 16 +- ... XcodeViewHierarchyObjectGraphTests.swift} | 34 +- ...codeViewHierarchyPixelRecoveryTests.swift} | 46 +-- ...ift => XcodeViewHierarchyValueTests.swift} | 20 +- 210 files changed, 3638 insertions(+), 3636 deletions(-) rename LookInside/About/{LKAboutWindowController.swift => AboutWindowController.swift} (88%) rename LookInside/Base/{LKWindow.swift => AppWindow.swift} (89%) rename LookInside/Base/{LKBaseControl.swift => BaseControl.swift} (94%) rename LookInside/Base/{LKBaseView.swift => BaseView.swift} (91%) rename LookInside/Base/{LKBaseViewController.swift => BaseViewController.swift} (84%) rename LookInside/Base/Category/{LookinAttributesGroup+LookinClient.swift => AttributesGroup+LookinClient.swift} (93%) rename LookInside/Base/Category/{LookinAutoLayoutConstraint+LookinClient.swift => AutoLayoutConstraint+LookinClient.swift} (100%) rename LookInside/Base/Category/{LookinDisplayItem+LookinClient.swift => DisplayItem+LookinClient.swift} (99%) rename LookInside/Base/Category/{LookinObject+LookinClient.swift => InspectedObject+LookinClient.swift} (70%) rename LookInside/Base/{LKColorIndicatorLayer.swift => ColorIndicatorLayer.swift} (94%) rename LookInside/Base/{LKConnectionTipsBinding.swift => ConnectionTipsBinding.swift} (87%) rename LookInside/Base/{LKDeviceIconProvider.swift => DeviceIconProvider.swift} (99%) rename LookInside/Base/{LKFrameLayout.swift => FrameLayout.swift} (81%) rename LookInside/Base/{LKImageTextView.swift => ImageTextView.swift} (92%) rename LookInside/Base/InputSearch/{LKInputSearchView.swift => InputSearchView.swift} (87%) rename LookInside/Base/Message/{LookinMsgAttribute.swift => MessageAttribute.swift} (81%) rename LookInside/Base/Message/{LKPeripheralAlerts.swift => PeripheralAlerts.swift} (96%) rename LookInside/Base/{LKNumberInputView.swift => NumberInputView.swift} (95%) rename LookInside/Base/{LKOutlineRowView.swift => OutlineRowView.swift} (83%) rename LookInside/Base/{LKPerformanceReporter.swift => PerformanceReporter.swift} (73%) rename LookInside/Base/{LKPopPanel.swift => PopPanel.swift} (92%) rename LookInside/Base/{LKProgressIndicatorView.swift => ProgressIndicatorView.swift} (94%) rename LookInside/Base/{LKSplitView.swift => SplitView.swift} (79%) rename LookInside/Base/{LKSwiftDemangler.swift => SwiftDemangler.swift} (94%) rename LookInside/Base/{LKTableRowView.swift => TableRowView.swift} (83%) rename LookInside/Base/{LKTableView.swift => TableView.swift} (86%) rename LookInside/Base/{LKTableViewHorizontalScrollWidthManager.swift => TableViewHorizontalScrollWidthManager.swift} (82%) rename LookInside/Base/{LKTextControl.swift => TextControl.swift} (96%) rename LookInside/Base/{LKTextFieldView.swift => TextFieldView.swift} (93%) rename LookInside/Base/{LKLabel.swift => TextLabel.swift} (90%) rename LookInside/Base/{LKTextsMenuView.swift => TextsMenuView.swift} (95%) rename LookInside/Base/{LKTipsView.swift => TipsView.swift} (95%) rename LookInside/Base/{LKTwoColors.swift => TwoColors.swift} (87%) rename LookInside/Base/{LKUserActionManager.swift => UserActionManager.swift} (66%) rename LookInside/Base/{LKWindowController.swift => WindowController.swift} (66%) rename LookInside/Common/Installer/{LKInstallerArchiveExtractor.swift => InstallerArchiveExtractor.swift} (93%) rename LookInside/Common/Installer/{LKInstallerCancellation.swift => InstallerCancellation.swift} (90%) rename LookInside/Common/Installer/{LKInstallerCodeSignature.swift => InstallerCodeSignature.swift} (96%) rename LookInside/Common/Installer/{LKInstallerDownloader.swift => InstallerDownloader.swift} (83%) rename LookInside/Common/Installer/{LKInstallerFilesystem.swift => InstallerFilesystem.swift} (96%) rename LookInside/Common/Installer/{LKInstallerLogger.swift => InstallerLogger.swift} (92%) rename LookInside/Common/Installer/{LKInstallerProgressWindowController.swift => InstallerProgressWindowController.swift} (97%) rename LookInside/Connection/{LKAppsManager.swift => AppsManager.swift} (88%) rename LookInside/Connection/{LKConnectionManager+License.swift => ConnectionManager+License.swift} (85%) rename LookInside/Connection/{LKConnectionManager.swift => ConnectionManager.swift} (82%) rename LookInside/Connection/{LKConnectionRequest.swift => ConnectionRequest.swift} (82%) rename LookInside/Connection/{LKInspectableApp.swift => InspectableApp.swift} (87%) rename LookInside/Connection/{LookinLiveDocument.swift => LiveDocument.swift} (84%) rename LookInside/Connection/{LookinLiveDocumentController.swift => LiveDocumentController.swift} (71%) rename LookInside/Connection/{LKChannel.swift => ServerChannel.swift} (83%) rename LookInside/Connection/{LKServerUpgradeHint.swift => ServerUpgradeHint.swift} (92%) rename LookInside/Console/{LKConsoleDataSource.swift => ConsoleDataSource.swift} (84%) rename LookInside/Console/{LKConsoleSelectPopoverController.swift => ConsoleSelectPopoverController.swift} (88%) rename LookInside/Console/{LKConsoleViewController.swift => ConsoleViewController.swift} (85%) rename LookInside/Dashboard/AttributeView/Constraint/{LKConstraintPopoverController.swift => ConstraintPopoverController.swift} (81%) rename LookInside/Dashboard/AttributeView/Constraint/{LKDashboardAttributeConstraintsView.swift => DashboardAttributeConstraintsView.swift} (87%) rename LookInside/Dashboard/AttributeView/{LKDashboardAttributeColorView.swift => DashboardAttributeColorView.swift} (85%) rename LookInside/Dashboard/AttributeView/{LKDashboardAttributeEnumsView.swift => DashboardAttributeEnumsView.swift} (88%) rename LookInside/Dashboard/AttributeView/{LKDashboardAttributeNumberInputView.swift => DashboardAttributeNumberInputView.swift} (91%) rename LookInside/Dashboard/AttributeView/{LKDashboardAttributePrivateDiscriminatorView.swift => DashboardAttributePrivateDiscriminatorView.swift} (87%) rename LookInside/Dashboard/AttributeView/{LKDashboardAttributeStringArrayView.swift => DashboardAttributeStringArrayView.swift} (85%) rename LookInside/Dashboard/AttributeView/{LKDashboardAttributeSwitchView.swift => DashboardAttributeSwitchView.swift} (83%) rename LookInside/Dashboard/AttributeView/{LKDashboardAttributeTextView.swift => DashboardAttributeTextView.swift} (85%) rename LookInside/Dashboard/AttributeView/{LKDashboardAttributeView.swift => DashboardAttributeView.swift} (92%) rename LookInside/Dashboard/AttributeView/JSON/{LKJSONAttributeItem.swift => JSONAttributeItem.swift} (79%) rename LookInside/Dashboard/{LKDashboardAccessoryWindowController.swift => DashboardAccessoryWindowController.swift} (65%) rename LookInside/Dashboard/{LKDashboardCardView.swift => DashboardCardView.swift} (83%) rename LookInside/Dashboard/{LKDashboardLayout.swift => DashboardLayout.swift} (95%) rename LookInside/Dashboard/{LKDashboardModification.swift => DashboardModification.swift} (98%) rename LookInside/Dashboard/{LKDashboardSectionView.swift => DashboardSectionView.swift} (79%) rename LookInside/Dashboard/{LKDashboardViewController.swift => DashboardViewController.swift} (80%) rename LookInside/Dashboard/{LKEnumListRegistry.swift => EnumListRegistry.swift} (97%) rename LookInside/Dashboard/Search/{LKDashboardHeaderView.swift => DashboardHeaderView.swift} (83%) rename LookInside/DebugE2E/{LKDebugE2EDump.swift => DebugE2EDump.swift} (88%) rename LookInside/DebugE2E/{LKDebugE2EDumpWriter.swift => DebugE2EDumpWriter.swift} (78%) rename LookInside/DebugE2E/{LKDebugUISnapshots.swift => DebugUISnapshots.swift} (85%) rename LookInside/DebugE2E/{LKDebugWindowImage.swift => DebugWindowImage.swift} (96%) rename LookInside/DebugE2E/{LookinSnapshotNormalizer.swift => SnapshotNormalizer.swift} (95%) rename LookInside/Export/{LKExportAccessoryView.swift => ExportAccessoryView.swift} (89%) rename LookInside/Export/{LKExportManager.swift => ExportManager.swift} (89%) rename LookInside/GestureDebug/{LKGestureDebugSession.swift => GestureDebugSession.swift} (89%) rename LookInside/GestureDebug/{LKGestureDebugView.swift => GestureDebugView.swift} (95%) rename LookInside/GestureDebug/{LKGestureDebugWindowController.swift => GestureDebugWindowController.swift} (88%) rename LookInside/GestureDebug/{LKGestureNodeDetailView.swift => GestureNodeDetailView.swift} (96%) rename LookInside/GestureDebug/{LKSuggestionsView.swift => HitTargetSuggestionsView.swift} (94%) rename LookInside/GestureDebug/{LKNativeInteractionDetailView.swift => NativeInteractionDetailView.swift} (96%) rename LookInside/Hierarchy/{LKDanceUIAttrMaker.swift => DanceUIAttributeMaker.swift} (96%) rename LookInside/Hierarchy/{LKHierarchyController.swift => HierarchyController.swift} (70%) rename LookInside/Hierarchy/{LKHierarchyDataSource+KeyDown.swift => HierarchyDataSource+KeyDown.swift} (94%) rename LookInside/Hierarchy/{LKHierarchyDataSource.swift => HierarchyDataSource.swift} (94%) rename LookInside/Hierarchy/{LKHierarchyFrameLayout.swift => HierarchyFrameLayout.swift} (96%) rename LookInside/Hierarchy/{LKHierarchyHandlersPopoverController.swift => HierarchyHandlersPopoverController.swift} (84%) rename LookInside/Hierarchy/{LKHierarchyRowView.swift => HierarchyRowView.swift} (93%) rename LookInside/Hierarchy/{LKHierarchyView.swift => HierarchyView.swift} (85%) rename LookInside/Hierarchy/{LKSyncSignal.swift => SyncSignal.swift} (77%) rename LookInside/Injection/Device/{LKAttachedDeviceMonitor.swift => AttachedDeviceMonitor.swift} (93%) rename LookInside/Injection/Device/{LKDeviceControlClient.swift => DeviceControlClient.swift} (89%) rename LookInside/Injection/Device/{LKDeviceControlWire.swift => DeviceControlWire.swift} (94%) rename LookInside/Injection/Device/{LKDeviceInjectionFlow.swift => DeviceInjectionFlow.swift} (91%) rename LookInside/Injection/{LKInjectableFrameworkInstaller.swift => InjectableFrameworkInstaller.swift} (75%) rename LookInside/Injection/{LKInjectionFlow.swift => InjectionFlow.swift} (75%) rename LookInside/Injection/{LKInjectionService.swift => InjectionService.swift} (87%) rename LookInside/Injection/{LKInjectionStartGate.swift => InjectionStartGate.swift} (79%) rename LookInside/Injection/{LKInjectionTargetPicker.swift => InjectionTargetPicker.swift} (98%) rename LookInside/Launch/{LKLaunchAppView.swift => LaunchAppView.swift} (81%) rename LookInside/Launch/{LKLaunchRules.swift => LaunchRules.swift} (97%) rename LookInside/Launch/{LKLaunchViewController.swift => LaunchViewController.swift} (79%) rename LookInside/Launch/{LKLaunchWindowController.swift => LaunchWindowController.swift} (78%) rename LookInside/MCPBridge/{LKMCPBridgeAttributeEncoder.swift => MCPBridgeAttributeEncoder.swift} (88%) rename LookInside/MCPBridge/{LKMCPBridgeAttributeValueDecoder.swift => MCPBridgeAttributeValueDecoder.swift} (95%) rename LookInside/MCPBridge/{LKMCPBridgeConnection.swift => MCPBridgeConnection.swift} (90%) rename LookInside/MCPBridge/{LKMCPBridgeDetailsService.swift => MCPBridgeDetailsService.swift} (87%) rename LookInside/MCPBridge/{LKMCPBridgeEventPublisher.swift => MCPBridgeEventPublisher.swift} (81%) rename LookInside/MCPBridge/{LKMCPBridgeInspectionService.swift => MCPBridgeInspectionService.swift} (82%) rename LookInside/MCPBridge/{LKMCPBridgeInvocationService.swift => MCPBridgeInvocationService.swift} (81%) rename LookInside/MCPBridge/{LKMCPBridgeListenSocket.swift => MCPBridgeListenSocket.swift} (89%) rename LookInside/MCPBridge/{LKMCPBridgeLiveDocumentLookup.swift => MCPBridgeLiveDocumentLookup.swift} (85%) rename LookInside/MCPBridge/{LKMCPBridgeModificationService.swift => MCPBridgeModificationService.swift} (82%) rename LookInside/MCPBridge/{LKMCPBridgeObjectIdentifierList.swift => MCPBridgeObjectIdentifierList.swift} (92%) rename LookInside/MCPBridge/{LKMCPBridgeRefreshService.swift => MCPBridgeRefreshService.swift} (84%) rename LookInside/MCPBridge/{LKMCPBridgeScreenshotService.swift => MCPBridgeScreenshotService.swift} (89%) rename LookInside/MCPBridge/{LKMCPBridgeSearchQuery.swift => MCPBridgeSearchQuery.swift} (96%) rename LookInside/MCPBridge/{LKMCPBridgeSearchService.swift => MCPBridgeSearchService.swift} (82%) rename LookInside/MCPBridge/{LKMCPBridgeSecureContentDetector.swift => MCPBridgeSecureContentDetector.swift} (96%) rename LookInside/MCPBridge/{LKMCPBridgeSelectorService.swift => MCPBridgeSelectorService.swift} (89%) rename LookInside/MCPBridge/{LKMCPBridgeServer.swift => MCPBridgeServer.swift} (81%) rename LookInside/Manager/{LKHelper.swift => AppHelper.swift} (98%) rename LookInside/Manager/{LKAppMenuManager.swift => AppMenuManager.swift} (88%) rename LookInside/Manager/{LKNavigationManager.swift => NavigationManager.swift} (77%) rename LookInside/Manager/{LKPreferenceManager.swift => PreferenceManager.swift} (89%) rename LookInside/Measure/{LKMeasureController.swift => MeasureController.swift} (89%) rename LookInside/Measure/{LKMeasureResultView.swift => MeasureResultView.swift} (95%) rename LookInside/Other/{LKVersionComparer.swift => VersionComparer.swift} (94%) rename LookInside/Preference/{LKPreferenceWindowController.swift => PreferenceWindowController.swift} (79%) rename LookInside/PrivateDiscriminator/{LKPrivateDiscriminatorSettingsWindowController.swift => PrivateDiscriminatorSettingsWindowController.swift} (96%) rename LookInside/PrivateDiscriminator/{LKPrivateDiscriminatorStore.swift => PrivateDiscriminatorStore.swift} (96%) rename LookInside/Read/{LookinArchiveCoding.swift => ArchiveCoding.swift} (94%) rename LookInside/Read/{LookinArchiveDocument.swift => ArchiveDocument.swift} (81%) rename LookInside/Read/{LKReadHierarchyController.swift => ReadHierarchyController.swift} (76%) rename LookInside/Read/{LKReadHierarchyDataSource.swift => ReadHierarchyDataSource.swift} (72%) rename LookInside/Read/{LKReadScreenshotLookup.swift => ReadScreenshotLookup.swift} (93%) rename LookInside/Read/{LKReadViewController.swift => ReadViewController.swift} (68%) rename LookInside/Read/{LKReadWindowController.swift => ReadWindowController.swift} (81%) rename LookInside/Static/{LKMessageManager.swift => MessageManager.swift} (88%) rename LookInside/Static/Preview/{LKDisplayItemNode.swift => DisplayItemNode.swift} (97%) rename LookInside/Static/Preview/{LKPreviewController.swift => PreviewController.swift} (91%) rename LookInside/Static/Preview/{LKPreviewStageView.swift => PreviewStageView.swift} (76%) rename LookInside/Static/Preview/{LKPreviewView.swift => PreviewView.swift} (94%) rename LookInside/Static/{LKStaticAsyncUpdateManager.swift => StaticAsyncUpdateManager.swift} (89%) rename LookInside/Static/{LKStaticHierarchyController.swift => StaticHierarchyController.swift} (67%) rename LookInside/Static/{LKStaticHierarchyDataSource.swift => StaticHierarchyDataSource.swift} (89%) rename LookInside/Static/{LKStaticLayout.swift => StaticLayout.swift} (93%) rename LookInside/Static/{LKStaticViewController.swift => StaticViewController.swift} (82%) rename LookInside/Static/{LKStaticWindowController.swift => StaticWindowController.swift} (87%) rename LookInside/SwiftUISupport/{LKSwiftUIHierarchyDisplayMode.swift => SwiftUIHierarchyDisplayMode.swift} (75%) rename LookInside/SwiftUISupport/{LKSwiftUISupportGatekeeper.swift => SwiftUISupportGatekeeper.swift} (94%) rename LookInside/SwiftUISupport/{LKSwiftUISupportLogger.swift => SwiftUISupportLogger.swift} (84%) rename LookInside/Toolbar/{LKMenuPopoverAppsListController.swift => MenuPopoverAppsListController.swift} (78%) rename LookInside/Toolbar/{LKMenuPopoverSettingController.swift => MenuPopoverSettingController.swift} (77%) rename LookInside/Toolbar/{LKToolbarRules.swift => ToolbarRules.swift} (98%) rename LookInside/Toolbar/{LKViewFrameLayout.swift => ViewFrameLayout.swift} (95%) rename LookInside/Toolbar/{LKWindowToolbarAppButton.swift => WindowToolbarAppButton.swift} (78%) rename LookInside/Toolbar/{LKWindowToolbarHelper.swift => WindowToolbarHelper.swift} (80%) rename LookInside/Toolbar/{LKWindowToolbarScaleView.swift => WindowToolbarScaleView.swift} (55%) rename LookInside/XcodeViewHierarchy/{LKXcodeViewHierarchyAttributeCatalog.swift => XcodeViewHierarchyAttributeCatalog.swift} (99%) rename LookInside/XcodeViewHierarchy/{LKXcodeViewHierarchyAttributes.swift => XcodeViewHierarchyAttributes.swift} (89%) rename LookInside/XcodeViewHierarchy/{LKXcodeViewHierarchyBundleReader.swift => XcodeViewHierarchyBundleReader.swift} (83%) rename LookInside/XcodeViewHierarchy/{LKXcodeViewHierarchyConverter.swift => XcodeViewHierarchyConverter.swift} (91%) rename LookInside/XcodeViewHierarchy/{LKXcodeViewHierarchyDocument.swift => XcodeViewHierarchyDocument.swift} (80%) rename LookInside/XcodeViewHierarchy/{LKXcodeViewHierarchyGzip.swift => XcodeViewHierarchyGzip.swift} (83%) rename LookInside/XcodeViewHierarchy/{LKXcodeViewHierarchyLayerArchive.swift => XcodeViewHierarchyLayerArchive.swift} (92%) rename LookInside/XcodeViewHierarchy/{LKXcodeViewHierarchyLayerTopology.swift => XcodeViewHierarchyLayerTopology.swift} (95%) rename LookInside/XcodeViewHierarchy/{LKXcodeViewHierarchyObjectGraph.swift => XcodeViewHierarchyObjectGraph.swift} (93%) rename LookInside/XcodeViewHierarchy/{LKXcodeViewHierarchyPixelRecovery.swift => XcodeViewHierarchyPixelRecovery.swift} (96%) rename LookInside/XcodeViewHierarchy/{LKXcodeViewHierarchyValue.swift => XcodeViewHierarchyValue.swift} (84%) rename Tests/Dashboard/{LKDashboardTests.swift => DashboardTests.swift} (75%) rename Tests/GestureDebug/{LKGestureCaptureModelsTests.swift => GestureCaptureModelsTests.swift} (52%) rename Tests/MCPBridge/{LKMCPBridgeListenSocketTests.swift => MCPBridgeListenSocketTests.swift} (87%) rename Tests/MCPBridge/{LKMCPBridgeObjectIdentifierListTests.swift => MCPBridgeObjectIdentifierListTests.swift} (82%) rename Tests/MCPBridge/{LKMCPBridgeSearchQueryTests.swift => MCPBridgeSearchQueryTests.swift} (78%) rename Tests/Security/{LKInjectionStartGateTests.swift => InjectionStartGateTests.swift} (76%) rename Tests/XcodeViewHierarchy/{LKXcodeViewHierarchyConverterTests.swift => XcodeViewHierarchyConverterTests.swift} (98%) rename Tests/XcodeViewHierarchy/{LKXcodeViewHierarchyGzipTests.swift => XcodeViewHierarchyGzipTests.swift} (92%) rename Tests/XcodeViewHierarchy/{LKXcodeViewHierarchyObjectGraphTests.swift => XcodeViewHierarchyObjectGraphTests.swift} (95%) rename Tests/XcodeViewHierarchy/{LKXcodeViewHierarchyPixelRecoveryTests.swift => XcodeViewHierarchyPixelRecoveryTests.swift} (94%) rename Tests/XcodeViewHierarchy/{LKXcodeViewHierarchyValueTests.swift => XcodeViewHierarchyValueTests.swift} (95%) diff --git a/LookInside.xcodeproj/project.pbxproj b/LookInside.xcodeproj/project.pbxproj index 27a5b2e7..979230f2 100644 --- a/LookInside.xcodeproj/project.pbxproj +++ b/LookInside.xcodeproj/project.pbxproj @@ -42,14 +42,14 @@ 50EAE1F32F71C01A00EBE063 /* Exceptions for "LookInside" folder in "LookInside" target */ = { isa = PBXFileSystemSynchronizedBuildFileExceptionSet; membershipExceptions = ( - About/LKAboutWindowController.swift, + About/AboutWindowController.swift, AppDelegate.swift, AppIcon.icon, Assets.xcassets, - "Base/Category/LookinAttributesGroup+LookinClient.swift", - "Base/Category/LookinAutoLayoutConstraint+LookinClient.swift", - "Base/Category/LookinDisplayItem+LookinClient.swift", - "Base/Category/LookinObject+LookinClient.swift", + "Base/Category/AttributesGroup+LookinClient.swift", + "Base/Category/AutoLayoutConstraint+LookinClient.swift", + "Base/Category/DisplayItem+LookinClient.swift", + "Base/Category/InspectedObject+LookinClient.swift", "Base/Category/NSAppearance+LookinClient.swift", "Base/Category/NSArray+LookinClient.swift", "Base/Category/NSButton+LookinClient.swift", @@ -57,193 +57,193 @@ "Base/Category/NSControl+LookinClient.swift", "Base/Category/NSString+LookinClient.swift", "Base/Category/NSView+LookinClient.swift", - Base/InputSearch/LKInputSearchView.swift, + Base/InputSearch/InputSearchView.swift, "Base/InputSearch/NSView+LKPeripheralLayout.swift", - Base/LKBaseControl.swift, - Base/LKBaseView.swift, - Base/LKBaseViewController.swift, - Base/LKColorIndicatorLayer.swift, - Base/LKConnectionTipsBinding.swift, - Base/LKDeviceIconProvider.swift, - Base/LKFrameLayout.swift, - Base/LKImageTextView.swift, - Base/LKLabel.swift, - Base/LKNumberInputView.swift, - Base/LKOutlineRowView.swift, - Base/LKPerformanceReporter.swift, - Base/LKPopPanel.swift, - Base/LKProgressIndicatorView.swift, - Base/LKSplitView.swift, - Base/LKSwiftDemangler.swift, - Base/LKTableRowView.swift, - Base/LKTableView.swift, - Base/LKTableViewHorizontalScrollWidthManager.swift, - Base/LKTextControl.swift, - Base/LKTextFieldView.swift, - Base/LKTextsMenuView.swift, - Base/LKTipsView.swift, - Base/LKTwoColors.swift, - Base/LKUserActionManager.swift, - Base/LKWindow.swift, - Base/LKWindowController.swift, - Base/Message/LKPeripheralAlerts.swift, - Base/Message/LookinMsgAttribute.swift, - Common/Installer/LKInstallerArchiveExtractor.swift, - Common/Installer/LKInstallerCancellation.swift, - Common/Installer/LKInstallerCodeSignature.swift, - Common/Installer/LKInstallerDownloader.swift, - Common/Installer/LKInstallerFilesystem.swift, - Common/Installer/LKInstallerLogger.swift, - Common/Installer/LKInstallerProgressWindowController.swift, - "Connection/LKConnectionManager+License.swift", - Connection/LKAppsManager.swift, - Connection/LKChannel.swift, + Base/BaseControl.swift, + Base/BaseView.swift, + Base/BaseViewController.swift, + Base/ColorIndicatorLayer.swift, + Base/ConnectionTipsBinding.swift, + Base/DeviceIconProvider.swift, + Base/FrameLayout.swift, + Base/ImageTextView.swift, + Base/TextLabel.swift, + Base/NumberInputView.swift, + Base/OutlineRowView.swift, + Base/PerformanceReporter.swift, + Base/PopPanel.swift, + Base/ProgressIndicatorView.swift, + Base/SplitView.swift, + Base/SwiftDemangler.swift, + Base/TableRowView.swift, + Base/TableView.swift, + Base/TableViewHorizontalScrollWidthManager.swift, + Base/TextControl.swift, + Base/TextFieldView.swift, + Base/TextsMenuView.swift, + Base/TipsView.swift, + Base/TwoColors.swift, + Base/UserActionManager.swift, + Base/AppWindow.swift, + Base/WindowController.swift, + Base/Message/PeripheralAlerts.swift, + Base/Message/MessageAttribute.swift, + Common/Installer/InstallerArchiveExtractor.swift, + Common/Installer/InstallerCancellation.swift, + Common/Installer/InstallerCodeSignature.swift, + Common/Installer/InstallerDownloader.swift, + Common/Installer/InstallerFilesystem.swift, + Common/Installer/InstallerLogger.swift, + Common/Installer/InstallerProgressWindowController.swift, + "Connection/ConnectionManager+License.swift", + Connection/AppsManager.swift, + Connection/ServerChannel.swift, Connection/LKConnectionErrors.swift, - Connection/LKConnectionManager.swift, - Connection/LKConnectionRequest.swift, - Connection/LKInspectableApp.swift, - Connection/LKServerUpgradeHint.swift, - Connection/LookinLiveDocument.swift, - Connection/LookinLiveDocumentController.swift, - Console/LKConsoleDataSource.swift, + Connection/ConnectionManager.swift, + Connection/ConnectionRequest.swift, + Connection/InspectableApp.swift, + Connection/ServerUpgradeHint.swift, + Connection/LiveDocument.swift, + Connection/LiveDocumentController.swift, + Console/ConsoleDataSource.swift, Console/LKConsoleRowViews.swift, - Console/LKConsoleSelectPopoverController.swift, - Console/LKConsoleViewController.swift, + Console/ConsoleSelectPopoverController.swift, + Console/ConsoleViewController.swift, DanceScript/DanceScriptManager.swift, - Dashboard/AttributeView/Constraint/LKConstraintPopoverController.swift, - Dashboard/AttributeView/Constraint/LKDashboardAttributeConstraintsView.swift, - Dashboard/AttributeView/JSON/LKJSONAttributeItem.swift, + Dashboard/AttributeView/Constraint/ConstraintPopoverController.swift, + Dashboard/AttributeView/Constraint/DashboardAttributeConstraintsView.swift, + Dashboard/AttributeView/JSON/JSONAttributeItem.swift, Dashboard/AttributeView/JSON/LKJSONAttributeViews.swift, - Dashboard/AttributeView/LKDashboardAttributeColorView.swift, - Dashboard/AttributeView/LKDashboardAttributeEnumsView.swift, + Dashboard/AttributeView/DashboardAttributeColorView.swift, + Dashboard/AttributeView/DashboardAttributeEnumsView.swift, Dashboard/AttributeView/LKDashboardAttributeGeometryViews.swift, - Dashboard/AttributeView/LKDashboardAttributeNumberInputView.swift, - Dashboard/AttributeView/LKDashboardAttributePrivateDiscriminatorView.swift, + Dashboard/AttributeView/DashboardAttributeNumberInputView.swift, + Dashboard/AttributeView/DashboardAttributePrivateDiscriminatorView.swift, Dashboard/AttributeView/LKDashboardAttributeReadOnlyViews.swift, - Dashboard/AttributeView/LKDashboardAttributeStringArrayView.swift, - Dashboard/AttributeView/LKDashboardAttributeSwitchView.swift, - Dashboard/AttributeView/LKDashboardAttributeTextView.swift, - Dashboard/AttributeView/LKDashboardAttributeView.swift, - Dashboard/LKDashboardAccessoryWindowController.swift, - Dashboard/LKDashboardCardView.swift, - Dashboard/LKDashboardLayout.swift, - Dashboard/LKDashboardModification.swift, - Dashboard/LKDashboardSectionView.swift, - Dashboard/LKDashboardViewController.swift, - Dashboard/LKEnumListRegistry.swift, - Dashboard/Search/LKDashboardHeaderView.swift, + Dashboard/AttributeView/DashboardAttributeStringArrayView.swift, + Dashboard/AttributeView/DashboardAttributeSwitchView.swift, + Dashboard/AttributeView/DashboardAttributeTextView.swift, + Dashboard/AttributeView/DashboardAttributeView.swift, + Dashboard/DashboardAccessoryWindowController.swift, + Dashboard/DashboardCardView.swift, + Dashboard/DashboardLayout.swift, + Dashboard/DashboardModification.swift, + Dashboard/DashboardSectionView.swift, + Dashboard/DashboardViewController.swift, + Dashboard/EnumListRegistry.swift, + Dashboard/Search/DashboardHeaderView.swift, Dashboard/Search/LKDashboardSearchViews.swift, - DebugE2E/LKDebugE2EDump.swift, - DebugE2E/LKDebugE2EDumpWriter.swift, - DebugE2E/LKDebugUISnapshots.swift, - DebugE2E/LKDebugWindowImage.swift, - DebugE2E/LookinSnapshotNormalizer.swift, - Export/LKExportAccessoryView.swift, - Export/LKExportManager.swift, - Hierarchy/LKDanceUIAttrMaker.swift, - Hierarchy/LKHierarchyController.swift, - "Hierarchy/LKHierarchyDataSource+KeyDown.swift", - Hierarchy/LKHierarchyDataSource.swift, - Hierarchy/LKHierarchyFrameLayout.swift, - Hierarchy/LKHierarchyHandlersPopoverController.swift, - Hierarchy/LKHierarchyRowView.swift, - Hierarchy/LKHierarchyView.swift, - Hierarchy/LKSyncSignal.swift, + DebugE2E/DebugE2EDump.swift, + DebugE2E/DebugE2EDumpWriter.swift, + DebugE2E/DebugUISnapshots.swift, + DebugE2E/DebugWindowImage.swift, + DebugE2E/SnapshotNormalizer.swift, + Export/ExportAccessoryView.swift, + Export/ExportManager.swift, + Hierarchy/DanceUIAttributeMaker.swift, + Hierarchy/HierarchyController.swift, + "Hierarchy/HierarchyDataSource+KeyDown.swift", + Hierarchy/HierarchyDataSource.swift, + Hierarchy/HierarchyFrameLayout.swift, + Hierarchy/HierarchyHandlersPopoverController.swift, + Hierarchy/HierarchyRowView.swift, + Hierarchy/HierarchyView.swift, + Hierarchy/SyncSignal.swift, GestureDebug/LKGestureCaptureModels.swift, - GestureDebug/LKGestureDebugSession.swift, - GestureDebug/LKGestureDebugView.swift, - GestureDebug/LKGestureDebugWindowController.swift, - GestureDebug/LKGestureNodeDetailView.swift, - GestureDebug/LKNativeInteractionDetailView.swift, + GestureDebug/GestureDebugSession.swift, + GestureDebug/GestureDebugView.swift, + GestureDebug/GestureDebugWindowController.swift, + GestureDebug/GestureNodeDetailView.swift, + GestureDebug/NativeInteractionDetailView.swift, GestureDebug/LKSuggestions.swift, - GestureDebug/LKSuggestionsView.swift, + GestureDebug/HitTargetSuggestionsView.swift, InfoPlist.xcstrings, - Injection/Device/LKAttachedDeviceMonitor.swift, - Injection/Device/LKDeviceControlClient.swift, - Injection/Device/LKDeviceControlWire.swift, - Injection/Device/LKDeviceInjectionFlow.swift, - Injection/LKInjectableFrameworkInstaller.swift, - Injection/LKInjectionFlow.swift, - Injection/LKInjectionService.swift, - Injection/LKInjectionStartGate.swift, - Injection/LKInjectionTargetPicker.swift, - Launch/LKLaunchAppView.swift, - Launch/LKLaunchRules.swift, - Launch/LKLaunchViewController.swift, - Launch/LKLaunchWindowController.swift, + Injection/Device/AttachedDeviceMonitor.swift, + Injection/Device/DeviceControlClient.swift, + Injection/Device/DeviceControlWire.swift, + Injection/Device/DeviceInjectionFlow.swift, + Injection/InjectableFrameworkInstaller.swift, + Injection/InjectionFlow.swift, + Injection/InjectionService.swift, + Injection/InjectionStartGate.swift, + Injection/InjectionTargetPicker.swift, + Launch/LaunchAppView.swift, + Launch/LaunchRules.swift, + Launch/LaunchViewController.swift, + Launch/LaunchWindowController.swift, Localizable.xcstrings, LookinArchiveIcon.icns, - MCPBridge/LKMCPBridgeAttributeEncoder.swift, - MCPBridge/LKMCPBridgeAttributeValueDecoder.swift, - MCPBridge/LKMCPBridgeConnection.swift, - MCPBridge/LKMCPBridgeDetailsService.swift, - MCPBridge/LKMCPBridgeEventPublisher.swift, + MCPBridge/MCPBridgeAttributeEncoder.swift, + MCPBridge/MCPBridgeAttributeValueDecoder.swift, + MCPBridge/MCPBridgeConnection.swift, + MCPBridge/MCPBridgeDetailsService.swift, + MCPBridge/MCPBridgeEventPublisher.swift, MCPBridge/LKMCPBridgeFrame.swift, MCPBridge/LKMCPBridgeInspectionModels.swift, - MCPBridge/LKMCPBridgeInspectionService.swift, - MCPBridge/LKMCPBridgeInvocationService.swift, - MCPBridge/LKMCPBridgeListenSocket.swift, - MCPBridge/LKMCPBridgeLiveDocumentLookup.swift, - MCPBridge/LKMCPBridgeModificationService.swift, - MCPBridge/LKMCPBridgeObjectIdentifierList.swift, - MCPBridge/LKMCPBridgeRefreshService.swift, - MCPBridge/LKMCPBridgeScreenshotService.swift, - MCPBridge/LKMCPBridgeSearchQuery.swift, - MCPBridge/LKMCPBridgeSearchService.swift, - MCPBridge/LKMCPBridgeSecureContentDetector.swift, - MCPBridge/LKMCPBridgeSelectorService.swift, - MCPBridge/LKMCPBridgeServer.swift, - Manager/LKAppMenuManager.swift, - Manager/LKHelper.swift, - Manager/LKNavigationManager.swift, - Manager/LKPreferenceManager.swift, - Measure/LKMeasureController.swift, - Measure/LKMeasureResultView.swift, - Other/LKVersionComparer.swift, + MCPBridge/MCPBridgeInspectionService.swift, + MCPBridge/MCPBridgeInvocationService.swift, + MCPBridge/MCPBridgeListenSocket.swift, + MCPBridge/MCPBridgeLiveDocumentLookup.swift, + MCPBridge/MCPBridgeModificationService.swift, + MCPBridge/MCPBridgeObjectIdentifierList.swift, + MCPBridge/MCPBridgeRefreshService.swift, + MCPBridge/MCPBridgeScreenshotService.swift, + MCPBridge/MCPBridgeSearchQuery.swift, + MCPBridge/MCPBridgeSearchService.swift, + MCPBridge/MCPBridgeSecureContentDetector.swift, + MCPBridge/MCPBridgeSelectorService.swift, + MCPBridge/MCPBridgeServer.swift, + Manager/AppMenuManager.swift, + Manager/AppHelper.swift, + Manager/NavigationManager.swift, + Manager/PreferenceManager.swift, + Measure/MeasureController.swift, + Measure/MeasureResultView.swift, + Other/VersionComparer.swift, Preference/LKPreferenceView.swift, - Preference/LKPreferenceWindowController.swift, - PrivateDiscriminator/LKPrivateDiscriminatorSettingsWindowController.swift, - PrivateDiscriminator/LKPrivateDiscriminatorStore.swift, - Read/LKReadHierarchyController.swift, - Read/LKReadHierarchyDataSource.swift, - Read/LKReadScreenshotLookup.swift, - Read/LKReadViewController.swift, - Read/LKReadWindowController.swift, - Read/LookinArchiveCoding.swift, - Read/LookinArchiveDocument.swift, - Static/LKMessageManager.swift, - Static/LKStaticAsyncUpdateManager.swift, + Preference/PreferenceWindowController.swift, + PrivateDiscriminator/PrivateDiscriminatorSettingsWindowController.swift, + PrivateDiscriminator/PrivateDiscriminatorStore.swift, + Read/ReadHierarchyController.swift, + Read/ReadHierarchyDataSource.swift, + Read/ReadScreenshotLookup.swift, + Read/ReadViewController.swift, + Read/ReadWindowController.swift, + Read/ArchiveCoding.swift, + Read/ArchiveDocument.swift, + Static/MessageManager.swift, + Static/StaticAsyncUpdateManager.swift, Static/LKStaticConstants.swift, - Static/LKStaticHierarchyController.swift, - Static/LKStaticHierarchyDataSource.swift, - Static/LKStaticLayout.swift, - Static/LKStaticViewController.swift, - Static/LKStaticWindowController.swift, - Static/Preview/LKDisplayItemNode.swift, - Static/Preview/LKPreviewController.swift, - Static/Preview/LKPreviewStageView.swift, - Static/Preview/LKPreviewView.swift, - SwiftUISupport/LKSwiftUIHierarchyDisplayMode.swift, - SwiftUISupport/LKSwiftUISupportGatekeeper.swift, - SwiftUISupport/LKSwiftUISupportLogger.swift, - Toolbar/LKMenuPopoverAppsListController.swift, - Toolbar/LKMenuPopoverSettingController.swift, - Toolbar/LKToolbarRules.swift, - Toolbar/LKViewFrameLayout.swift, - Toolbar/LKWindowToolbarAppButton.swift, - Toolbar/LKWindowToolbarHelper.swift, - Toolbar/LKWindowToolbarScaleView.swift, - XcodeViewHierarchy/LKXcodeViewHierarchyAttributeCatalog.swift, - XcodeViewHierarchy/LKXcodeViewHierarchyAttributes.swift, - XcodeViewHierarchy/LKXcodeViewHierarchyBundleReader.swift, - XcodeViewHierarchy/LKXcodeViewHierarchyConverter.swift, - XcodeViewHierarchy/LKXcodeViewHierarchyDocument.swift, - XcodeViewHierarchy/LKXcodeViewHierarchyGzip.swift, - XcodeViewHierarchy/LKXcodeViewHierarchyLayerArchive.swift, - XcodeViewHierarchy/LKXcodeViewHierarchyLayerTopology.swift, - XcodeViewHierarchy/LKXcodeViewHierarchyObjectGraph.swift, - XcodeViewHierarchy/LKXcodeViewHierarchyPixelRecovery.swift, - XcodeViewHierarchy/LKXcodeViewHierarchyValue.swift, + Static/StaticHierarchyController.swift, + Static/StaticHierarchyDataSource.swift, + Static/StaticLayout.swift, + Static/StaticViewController.swift, + Static/StaticWindowController.swift, + Static/Preview/DisplayItemNode.swift, + Static/Preview/PreviewController.swift, + Static/Preview/PreviewStageView.swift, + Static/Preview/PreviewView.swift, + SwiftUISupport/SwiftUIHierarchyDisplayMode.swift, + SwiftUISupport/SwiftUISupportGatekeeper.swift, + SwiftUISupport/SwiftUISupportLogger.swift, + Toolbar/MenuPopoverAppsListController.swift, + Toolbar/MenuPopoverSettingController.swift, + Toolbar/ToolbarRules.swift, + Toolbar/ViewFrameLayout.swift, + Toolbar/WindowToolbarAppButton.swift, + Toolbar/WindowToolbarHelper.swift, + Toolbar/WindowToolbarScaleView.swift, + XcodeViewHierarchy/XcodeViewHierarchyAttributeCatalog.swift, + XcodeViewHierarchy/XcodeViewHierarchyAttributes.swift, + XcodeViewHierarchy/XcodeViewHierarchyBundleReader.swift, + XcodeViewHierarchy/XcodeViewHierarchyConverter.swift, + XcodeViewHierarchy/XcodeViewHierarchyDocument.swift, + XcodeViewHierarchy/XcodeViewHierarchyGzip.swift, + XcodeViewHierarchy/XcodeViewHierarchyLayerArchive.swift, + XcodeViewHierarchy/XcodeViewHierarchyLayerTopology.swift, + XcodeViewHierarchy/XcodeViewHierarchyObjectGraph.swift, + XcodeViewHierarchy/XcodeViewHierarchyPixelRecovery.swift, + XcodeViewHierarchy/XcodeViewHierarchyValue.swift, ); target = AA48F29A21CC0CA50032EC2C /* LookInside */; }; diff --git a/LookInside/About/LKAboutWindowController.swift b/LookInside/About/AboutWindowController.swift similarity index 88% rename from LookInside/About/LKAboutWindowController.swift rename to LookInside/About/AboutWindowController.swift index aa930b02..4446d822 100644 --- a/LookInside/About/LKAboutWindowController.swift +++ b/LookInside/About/AboutWindowController.swift @@ -1,5 +1,5 @@ // -// LKAboutWindowController.swift +// AboutWindowController.swift // LookInside // // The About window: app icon, name, version, tagline and the license line @@ -9,9 +9,9 @@ import AppKit @objc(LKAboutWindowController) -final class LKAboutWindowController: LKWindowController { +final class AboutWindowController: WindowController { @objc init() { - let window = LKWindow(contentRect: NSRect(x: 0, y: 0, width: 480, height: 460), + let window = AppWindow(contentRect: NSRect(x: 0, y: 0, width: 480, height: 460), styleMask: [.titled, .closable, .fullSizeContentView], backing: .buffered, defer: true) window.isMovableByWindowBackground = true @@ -22,7 +22,7 @@ final class LKAboutWindowController: LKWindowController { window.center() super.init(window: window) - let viewController = LKAboutViewController() + let viewController = AboutViewController() window.contentView = viewController.view contentViewController = viewController } @@ -34,13 +34,13 @@ final class LKAboutWindowController: LKWindowController { } @objc(LKAboutViewController) -final class LKAboutViewController: LKBaseViewController { +final class AboutViewController: BaseViewController { private static let upstreamURL = "https://github.com/QMUI/LookinServer" private static let homeURL = "https://lookinside-app.com" private static let padding: CGFloat = 16 - private var backgroundImageView: LKBaseView? - private var paperOverlayView: LKBaseView? + private var backgroundImageView: BaseView? + private var paperOverlayView: BaseView? private var contentStackView: NSStackView? private var legalTextView: NSTextView? @@ -54,13 +54,13 @@ final class LKAboutViewController: LKBaseViewController { } override func makeContainerView() -> NSView { - let containerView = LKBaseView() - containerView.backgroundColors = LKTwoColors( + let containerView = BaseView() + containerView.backgroundColors = TwoColors( colorInLightMode: NSColor(calibratedRed: 0.99, green: 0.97, blue: 0.93, alpha: 1), colorInDarkMode: NSColor(calibratedWhite: 0.10, alpha: 1) ) - let backgroundImageView = LKBaseView() + let backgroundImageView = BaseView() backgroundImageView.wantsLayer = true backgroundImageView.layer?.contents = NSImage(named: "aboutHeroBg") backgroundImageView.layer?.contentsGravity = .resizeAspectFill @@ -69,8 +69,8 @@ final class LKAboutViewController: LKBaseViewController { containerView.addSubview(backgroundImageView) self.backgroundImageView = backgroundImageView - let paperOverlayView = LKBaseView() - paperOverlayView.backgroundColors = LKTwoColors( + let paperOverlayView = BaseView() + paperOverlayView.backgroundColors = TwoColors( colorInLightMode: NSColor(calibratedRed: 0.99, green: 0.97, blue: 0.93, alpha: 0.55), colorInDarkMode: NSColor(calibratedWhite: 0.10, alpha: 0.55) ) @@ -88,31 +88,31 @@ final class LKAboutViewController: LKBaseViewController { ?? NSFont.systemFont(ofSize: 30, weight: .regular) let footnoteFont = NSFont.preferredFont(forTextStyle: .footnote, options: [:]) - let titleLabel = LKLabel() + let titleLabel = TextLabel() titleLabel.stringValue = "LookInside" - titleLabel.textColors = LKTwoColors(colorInLightMode: NSColor(calibratedWhite: 0.12, alpha: 1), + titleLabel.textColors = TwoColors(colorInLightMode: NSColor(calibratedWhite: 0.12, alpha: 1), colorInDarkMode: NSColor(calibratedWhite: 0.96, alpha: 1)) titleLabel.font = titleFont let info = Bundle.main.infoDictionary let dotVersion = info?["CFBundleShortVersionString"] as? String ?? "(null)" let numberVersion = info?["CFBundleVersion"] as? String ?? "(null)" - let versionLabel = LKLabel() + let versionLabel = TextLabel() versionLabel.stringValue = String( format: NSLocalizedString("Version %1$@ (%2$@)", comment: "About window version line: marketing version, build number"), dotVersion, numberVersion ) - versionLabel.textColors = LKTwoColors(colorInLightMode: NSColor(calibratedWhite: 0.35, alpha: 1), + versionLabel.textColors = TwoColors(colorInLightMode: NSColor(calibratedWhite: 0.35, alpha: 1), colorInDarkMode: NSColor(calibratedWhite: 0.78, alpha: 1)) versionLabel.font = footnoteFont - let taglineLabel = LKLabel() + let taglineLabel = TextLabel() taglineLabel.stringValue = NSLocalizedString( "A SwiftUI- and UIKit-aware view debugger.\nWalk every layer. Read every modifier.", comment: "About window tagline, two lines" ) - taglineLabel.textColors = LKTwoColors(colorInLightMode: NSColor(calibratedWhite: 0.30, alpha: 1), + taglineLabel.textColors = TwoColors(colorInLightMode: NSColor(calibratedWhite: 0.30, alpha: 1), colorInDarkMode: NSColor(calibratedWhite: 0.82, alpha: 1)) taglineLabel.font = footnoteFont taglineLabel.alignment = .center diff --git a/LookInside/AppDelegate.swift b/LookInside/AppDelegate.swift index a900d4f9..daf99284 100644 --- a/LookInside/AppDelegate.swift +++ b/LookInside/AppDelegate.swift @@ -23,7 +23,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate { #if DEBUG // Before the delegate is set, so the dump observes the end of // launching ahead of it, as its Objective-C +load did. - LKDebugE2EDump.installIfRequested() + DebugE2EDump.installIfRequested() #endif let delegate = AppDelegate() NSApplication.shared.delegate = delegate @@ -33,16 +33,16 @@ final class AppDelegate: NSObject, NSApplicationDelegate { } func applicationWillFinishLaunching(_: Notification) { - LKAppMenuManager.shared.setup() + AppMenuManager.shared.setup() - appearanceObservation = LKPreferenceManager.shared.observe(\.appearanceType, options: [.initial, .new]) { manager, _ in + appearanceObservation = PreferenceManager.shared.observe(\.appearanceType, options: [.initial, .new]) { manager, _ in MainActor.assumeIsolated { Self.applyAppearance(manager.appearanceType) } } } - private static func applyAppearance(_ type: LookinPreferredAppeanranceType) { + private static func applyAppearance(_ type: PreferredAppearanceType) { switch type { case .dark: NSApp.appearance = NSAppearance(named: .darkAqua) @@ -54,20 +54,20 @@ final class AppDelegate: NSObject, NSApplicationDelegate { } func applicationDidFinishLaunching(_: Notification) { - _ = LKConnectionManager.shared - LKMCPBridgeServer.sharedInstance.start() + _ = ConnectionManager.shared + MCPBridgeServer.sharedInstance.start() // Documents opened during launch (Finder double-click, Open With…) // are registered with NSDocumentController by now, so "no documents // ⇒ show Launch" covers both cold-start cases. if NSDocumentController.shared.documents.isEmpty { var allowAutoEnter = true #if DEBUG - // The end-to-end dump (LKDebugE2EDump.swift) opens the app itself; an + // The end-to-end dump (DebugE2EDump.swift) opens the app itself; an // activated Host's auto-enter would fetch the same hierarchy // alongside it. allowAutoEnter = (ProcessInfo.processInfo.environment["LOOKINSIDE_DEBUG_E2E_DUMP_DIR"] ?? "").isEmpty #endif - LKNavigationManager.shared.showLaunch(allowingAutoEnter: allowAutoEnter) + NavigationManager.shared.showLaunch(allowingAutoEnter: allowAutoEnter) } installActivationStateObserver() @@ -88,13 +88,13 @@ final class AppDelegate: NSObject, NSApplicationDelegate { @objc private func handleWindowWillClose(_ notification: Notification) { guard let closingWindow = notification.object as? NSWindow, - closingWindow.windowController is LKWindowController + closingWindow.windowController is WindowController else { return } // Closing the Launch window itself shouldn't re-spawn Launch; only // document (live / archive) windows trigger the "no docs left" reopen. - if closingWindow == LKNavigationManager.shared.launchWindowController?.window { + if closingWindow == NavigationManager.shared.launchWindowController?.window { return } // Defer one tick so NSDocumentController has finished removing the doc. @@ -107,20 +107,20 @@ final class AppDelegate: NSObject, NSApplicationDelegate { guard NSDocumentController.shared.documents.isEmpty else { return } - if LKNavigationManager.shared.launchWindowController?.window?.isVisible == true { + if NavigationManager.shared.launchWindowController?.window?.isVisible == true { return } - LKNavigationManager.shared.showLaunch() + NavigationManager.shared.showLaunch() } private func installActivationStateObserver() { - let gatekeeper = LKSwiftUISupportGatekeeper.sharedInstance() + let gatekeeper = SwiftUISupportGatekeeper.sharedInstance() NSLog("[LK-Activation] initial state=%ld (re-evaluated every 60s in process)", gatekeeper.activationState.rawValue) NotificationCenter.default.addObserver( self, selector: #selector(activationStateDidChange(_:)), - name: NSNotification.Name(LKSwiftUISupportGatekeeper.activationStateDidChangeNotificationName as String), + name: NSNotification.Name(SwiftUISupportGatekeeper.activationStateDidChangeNotificationName as String), object: nil ) } @@ -128,7 +128,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate { @objc private func activationStateDidChange(_ notification: Notification) { let state = notification.userInfo?["activationState"] as? NSNumber let label: String - switch state.flatMap({ LKSwiftUISupportActivationState(rawValue: $0.intValue) }) { + switch state.flatMap({ SwiftUISupportActivationState(rawValue: $0.intValue) }) { case .unknown: label = "unknown" case .notActivated: label = "notActivated" case .activated: label = "activated" @@ -176,11 +176,11 @@ final class AppDelegate: NSObject, NSApplicationDelegate { } func applicationShouldTerminate(_: NSApplication) -> NSApplication.TerminateReply { - LKSwiftUISupportGatekeeper.sharedInstance().shutdownRuntime() - LKMCPBridgeServer.sharedInstance.stop() + SwiftUISupportGatekeeper.sharedInstance().shutdownRuntime() + MCPBridgeServer.sharedInstance.stop() // 清理打开 UIImageView 的图片时创建的临时文件 - for path in LKHelper.sharedInstance().tempImageFiles { + for path in AppHelper.sharedInstance().tempImageFiles { do { try FileManager.default.removeItem(atPath: path) } catch { diff --git a/LookInside/Base/LKWindow.swift b/LookInside/Base/AppWindow.swift similarity index 89% rename from LookInside/Base/LKWindow.swift rename to LookInside/Base/AppWindow.swift index cd981b5e..07a66521 100644 --- a/LookInside/Base/LKWindow.swift +++ b/LookInside/Base/AppWindow.swift @@ -1,5 +1,5 @@ // -// LKWindow.swift +// AppWindow.swift // LookInside // @@ -7,7 +7,7 @@ import AppKit /// The app's window class: dropping a file onto it opens it in the reader. @objc(LKWindow) -class LKWindow: NSWindow { +class AppWindow: NSWindow { override init(contentRect: NSRect, styleMask style: NSWindow.StyleMask, backing backingStoreType: NSWindow.BackingStoreType, defer flag: Bool) { super.init(contentRect: contentRect, styleMask: style, backing: backingStoreType, defer: flag) registerForDraggedTypes([.fileURL]) @@ -22,7 +22,7 @@ class LKWindow: NSWindow { return false } do { - try LKNavigationManager.shared.showReader(withFilePath: path) + try NavigationManager.shared.showReader(withFilePath: path) return true } catch { let nsError = error as NSError diff --git a/LookInside/Base/LKBaseControl.swift b/LookInside/Base/BaseControl.swift similarity index 94% rename from LookInside/Base/LKBaseControl.swift rename to LookInside/Base/BaseControl.swift index 06123f69..548e94b6 100644 --- a/LookInside/Base/LKBaseControl.swift +++ b/LookInside/Base/BaseControl.swift @@ -1,5 +1,5 @@ // -// LKBaseControl.swift +// BaseControl.swift // Lookin // // Created by Li Kai on 2018/8/28. @@ -9,12 +9,12 @@ import AppKit @objc(LKBaseControl) -class LKBaseControl: NSControl { +class BaseControl: NSControl { @objc var clickAction: Selector? @objc var adjustAlphaWhenClick = false - @objc var didChangeAppearance: ((LKBaseControl?, Bool) -> Void)? { + @objc var didChangeAppearance: ((BaseControl?, Bool) -> Void)? { didSet { triggerDidChangeAppearanceBlock() } diff --git a/LookInside/Base/LKBaseView.swift b/LookInside/Base/BaseView.swift similarity index 91% rename from LookInside/Base/LKBaseView.swift rename to LookInside/Base/BaseView.swift index 9eb40acd..cdfccbdc 100644 --- a/LookInside/Base/LKBaseView.swift +++ b/LookInside/Base/BaseView.swift @@ -1,5 +1,5 @@ // -// LKBaseView.swift +// BaseView.swift // Lookin // // Created by Li Kai on 2018/8/4. @@ -10,7 +10,7 @@ import AppKit private let effectiveAppearanceContext = UnsafeMutableRawPointer.allocate(byteCount: 1, alignment: 1) -@objc enum LKViewBorderPosition: Int { +@objc enum ViewBorderPosition: Int { case none case top case left @@ -20,7 +20,7 @@ private let effectiveAppearanceContext = UnsafeMutableRawPointer.allocate(byteCo @objc(LKBaseView) @objcMembers -class LKBaseView: NSView, NSViewToolTipOwner { +class BaseView: NSView, NSViewToolTipOwner { var tooltipString: String? { didSet { if tooltipString != nil { @@ -37,7 +37,7 @@ class LKBaseView: NSView, NSViewToolTipOwner { } } - var backgroundColors: LKTwoColors? { + var backgroundColors: TwoColors? { didSet { updateColors() } @@ -45,7 +45,7 @@ class LKBaseView: NSView, NSViewToolTipOwner { /// 可以单独设置某一条边有 border,颜色由 borderColors 属性决定,注意通过这个属性设置了单边 border 后,就不要再使用系统的 layer.border 接口来设置四边 border 了 /// 默认为 .none - var borderPosition: LKViewBorderPosition = .none { + var borderPosition: ViewBorderPosition = .none { didSet { if borderPosition == .none { customBorderLayer?.removeFromSuperlayer() @@ -64,14 +64,14 @@ class LKBaseView: NSView, NSViewToolTipOwner { /// 通过系统的 layer.border 接口和上面的 borderPosition 接口设置的 border 均可被该属性影响到 /// 默认为 SeparatorLightModeColor / SeparatorDarkModeColor - var borderColors: LKTwoColors? { + var borderColors: TwoColors? { didSet { updateColors() } } /// 当设置该 block 之后,该 block 会立即被调用一次 - var didChangeAppearanceBlock: ((LKBaseView?, Bool) -> Void)? { + var didChangeAppearanceBlock: ((BaseView?, Bool) -> Void)? { didSet { triggerDidChangeAppearanceBlock() } @@ -86,7 +86,7 @@ class LKBaseView: NSView, NSViewToolTipOwner { if backgroundEffectView != nil { return } - let effectView = LKVisualEffectView() + let effectView = VisualEffectView() effectView.blendingMode = .withinWindow effectView.state = .active backgroundEffectView = effectView @@ -100,14 +100,14 @@ class LKBaseView: NSView, NSViewToolTipOwner { } private var customBorderLayer: CALayer? - private var backgroundEffectView: LKVisualEffectView? + private var backgroundEffectView: VisualEffectView? private var isObservingEffectiveAppearance = false override init(frame frameRect: NSRect) { super.init(frame: frameRect) wantsLayer = true - borderColors = LKTwoColors(colorInLightMode: .lkBaseRGB(215, 215, 215), colorInDarkMode: .lkBaseRGB(67, 67, 69)) + borderColors = TwoColors(colorInLightMode: .lkBaseRGB(215, 215, 215), colorInDarkMode: .lkBaseRGB(67, 67, 69)) beginObservingAppearanceIfNeeded() } @@ -228,7 +228,7 @@ class LKBaseView: NSView, NSViewToolTipOwner { } @objc(LKVisualEffectView) -class LKVisualEffectView: NSVisualEffectView { +class VisualEffectView: NSVisualEffectView { override var isFlipped: Bool { true } diff --git a/LookInside/Base/LKBaseViewController.swift b/LookInside/Base/BaseViewController.swift similarity index 84% rename from LookInside/Base/LKBaseViewController.swift rename to LookInside/Base/BaseViewController.swift index 6a7b7efd..235edb7c 100644 --- a/LookInside/Base/LKBaseViewController.swift +++ b/LookInside/Base/BaseViewController.swift @@ -1,5 +1,5 @@ // -// LKBaseViewController.swift +// BaseViewController.swift // Lookin // // Created by Li Kai on 2018/8/28. @@ -10,12 +10,12 @@ import AppKit @objc(LKBaseViewController) @objcMembers -class LKBaseViewController: NSViewController { +class BaseViewController: NSViewController { private(set) var isViewAppeared = false - private(set) var connectionTipsView: LKRedTipsView? + private(set) var connectionTipsView: RedTipsView? - private var connectionTipsBinding: LKConnectionTipsBinding? + private var connectionTipsBinding: ConnectionTipsBinding? /// 如果使用该初始化方法,则 controller.view 会被赋值为传入的 view。 /// 如果使用普通的 init 方法,或该方法传入 nil,则 controller 会自动创建一个 view,即 makeContainerView() @@ -48,7 +48,7 @@ class LKBaseViewController: NSViewController { set { super.view = newValue if shouldShowConnectionTips() { - let tipsView = LKRedTipsView() + let tipsView = RedTipsView() tipsView.isHidden = true tipsView.title = NSLocalizedString("Reconnecting…", comment: "") tipsView.buttonText = NSLocalizedString("Change App", comment: "") @@ -69,18 +69,18 @@ class LKBaseViewController: NSViewController { // when Phase D auto-reconnect succeeds). The lookup happens once // here because the window↔doc binding is fixed for this controller's // lifetime once the doc has called `-makeWindowControllers`. - guard let document = LookinLiveDocument.document(in: view.window) else { + guard let document = LiveDocument.document(in: view.window) else { return } // The binding also follows inspectableApp swaps (Phase D auto-reconnect) // so the banner image stays in sync with the currently-bound app. - connectionTipsBinding = LKConnectionTipsBinding(document: document, tipsView: connectionTipsView, viewController: self) + connectionTipsBinding = ConnectionTipsBinding(document: document, tipsView: connectionTipsView, viewController: self) } override func viewDidLayout() { super.viewDidLayout() if let connectionTipsView, connectionTipsView.isVisible { - let windowTitleHeight = LKNavigationManager.shared.windowTitleBarHeight + let windowTitleHeight = NavigationManager.shared.windowTitleBarHeight connectionTipsView.lkLayout.sizeToFit().horAlign().y(windowTitleHeight + 10) } } @@ -90,7 +90,7 @@ class LKBaseViewController: NSViewController { // "Change App" pill on this window's banner pops up the picker on // *this* window (rather than routing through a global Static // workspace singleton). - if let windowController = view.window?.windowController as? LKStaticWindowController { + if let windowController = view.window?.windowController as? StaticWindowController { windowController.popupAllInspectableApps(with: .noConnectionTips) } } @@ -98,7 +98,7 @@ class LKBaseViewController: NSViewController { // MARK: - Subclassing hooks func makeContainerView() -> NSView { - LKBaseView() + BaseView() } /// 是否在连接断开时显示 tips,默认为 NO diff --git a/LookInside/Base/Category/LookinAttributesGroup+LookinClient.swift b/LookInside/Base/Category/AttributesGroup+LookinClient.swift similarity index 93% rename from LookInside/Base/Category/LookinAttributesGroup+LookinClient.swift rename to LookInside/Base/Category/AttributesGroup+LookinClient.swift index 144b6dac..470a4c46 100644 --- a/LookInside/Base/Category/LookinAttributesGroup+LookinClient.swift +++ b/LookInside/Base/Category/AttributesGroup+LookinClient.swift @@ -18,7 +18,7 @@ extension AttributesGroup { // +groupTitleWithGroupID: picks this title with TARGET_OS_IPHONE, // which is always 0 in the Host, so it would say "NSView" even // for an iOS target. - return "CALayer / \(LKHelper.viewClassName(forMacTarget: isMacTarget))" + return "CALayer / \(AppHelper.viewClassName(forMacTarget: isMacTarget))" } if identifier == LookinAttrGroup_LayoutGuide { // The group ID is platform-neutral; the title names the inspected diff --git a/LookInside/Base/Category/LookinAutoLayoutConstraint+LookinClient.swift b/LookInside/Base/Category/AutoLayoutConstraint+LookinClient.swift similarity index 100% rename from LookInside/Base/Category/LookinAutoLayoutConstraint+LookinClient.swift rename to LookInside/Base/Category/AutoLayoutConstraint+LookinClient.swift diff --git a/LookInside/Base/Category/LookinDisplayItem+LookinClient.swift b/LookInside/Base/Category/DisplayItem+LookinClient.swift similarity index 99% rename from LookInside/Base/Category/LookinDisplayItem+LookinClient.swift rename to LookInside/Base/Category/DisplayItem+LookinClient.swift index 6e137043..72188223 100644 --- a/LookInside/Base/Category/LookinDisplayItem+LookinClient.swift +++ b/LookInside/Base/Category/DisplayItem+LookinClient.swift @@ -23,7 +23,7 @@ extension DisplayItem { } else { baseTitle = displayingObject()?.lk_simpleDemangledClassName() } - return LKPrivateDiscriminatorStore.shared.displayTitle(for: self, fallback: baseTitle) ?? "" + return PrivateDiscriminatorStore.shared.displayTitle(for: self, fallback: baseTitle) ?? "" } /// The owning window or view controller, a special trace, or the ivar diff --git a/LookInside/Base/Category/LookinObject+LookinClient.swift b/LookInside/Base/Category/InspectedObject+LookinClient.swift similarity index 70% rename from LookInside/Base/Category/LookinObject+LookinClient.swift rename to LookInside/Base/Category/InspectedObject+LookinClient.swift index 5cfa8529..fd4af35e 100644 --- a/LookInside/Base/Category/LookinObject+LookinClient.swift +++ b/LookInside/Base/Category/InspectedObject+LookinClient.swift @@ -9,12 +9,12 @@ import LookInsideHostCore extension InspectedObject { /// The demangled class name, module prefix included. @objc func lk_completedDemangledClassName() -> String { - LKSwiftDemangler.completedParse(input: rawClassName() ?? "") + SwiftDemangler.completedParse(input: rawClassName() ?? "") } /// The demangled class name without its module prefix; generic /// arguments keep theirs. @objc func lk_simpleDemangledClassName() -> String { - ClientDisplayText.removingModulePrefix(LKSwiftDemangler.simpleParse(input: rawClassName() ?? "")) + ClientDisplayText.removingModulePrefix(SwiftDemangler.simpleParse(input: rawClassName() ?? "")) } } diff --git a/LookInside/Base/LKColorIndicatorLayer.swift b/LookInside/Base/ColorIndicatorLayer.swift similarity index 94% rename from LookInside/Base/LKColorIndicatorLayer.swift rename to LookInside/Base/ColorIndicatorLayer.swift index 3bd48bb1..c03adbdf 100644 --- a/LookInside/Base/LKColorIndicatorLayer.swift +++ b/LookInside/Base/ColorIndicatorLayer.swift @@ -1,5 +1,5 @@ // -// LKColorIndicatorLayer.swift +// ColorIndicatorLayer.swift // LookInside // @@ -8,7 +8,7 @@ import AppKit /// A round colour swatch: a checkerboard behind translucent colours, a /// "no colour" image for nil, and a contrasting border. @objc(LKColorIndicatorLayer) -class LKColorIndicatorLayer: CALayer { +class ColorIndicatorLayer: CALayer { private var colorLayer: CALayer? private var imageLayer: CALayer? @@ -76,11 +76,11 @@ class LKColorIndicatorLayer: CALayer { override func layoutSublayers() { super.layoutSublayers() - LKFrameLayout([imageLayer, colorLayer]).visibles().fullFrame() + FrameLayout([imageLayer, colorLayer]).visibles().fullFrame() cornerRadius = min(frame.width, frame.height) / 2 } - private static let renderingLayer = LKColorIndicatorLayer() + private static let renderingLayer = ColorIndicatorLayer() /// The swatch drawn into an image of `shapeSize` plus `insets`. @objc(imageWithColor:shapeSize:insets:) diff --git a/LookInside/Base/LKConnectionTipsBinding.swift b/LookInside/Base/ConnectionTipsBinding.swift similarity index 87% rename from LookInside/Base/LKConnectionTipsBinding.swift rename to LookInside/Base/ConnectionTipsBinding.swift index 79628a5d..652877ac 100644 --- a/LookInside/Base/LKConnectionTipsBinding.swift +++ b/LookInside/Base/ConnectionTipsBinding.swift @@ -1,25 +1,25 @@ // -// LKConnectionTipsBinding.swift +// ConnectionTipsBinding.swift // LookInside // // Drives a view controller's "Reconnecting…" banner from its live // document: the banner shows (and pulses) while the document has a // connection-loss message and follows the document's current app icon. -// Used by LKBaseViewController, which stays Objective-C while ObjC view +// Used by BaseViewController, which stays Objective-C while ObjC view // controllers still subclass it. // import AppKit @objc(LKConnectionTipsBinding) -final class LKConnectionTipsBinding: NSObject { +final class ConnectionTipsBinding: NSObject { private var observations: [NSKeyValueObservation] = [] /// Starts observing right away and applies the current state. Holds the /// tips view and view controller weakly; observation stops when the /// binding is released. @objc(initWithDocument:tipsView:viewController:) - init(document: LookinLiveDocument, tipsView: LKRedTipsView, viewController: NSViewController) { + init(document: LiveDocument, tipsView: RedTipsView, viewController: NSViewController) { super.init() observations = [ document.observe(\.connectionLossBannerMessage, options: [.initial, .new]) { [weak tipsView, weak viewController] document, _ in diff --git a/LookInside/Base/LKDeviceIconProvider.swift b/LookInside/Base/DeviceIconProvider.swift similarity index 99% rename from LookInside/Base/LKDeviceIconProvider.swift rename to LookInside/Base/DeviceIconProvider.swift index 2c83f9c0..3dbf0ae2 100644 --- a/LookInside/Base/LKDeviceIconProvider.swift +++ b/LookInside/Base/DeviceIconProvider.swift @@ -14,7 +14,7 @@ import UIFoundationToolbox /// `deviceModelIdentifier`, for a host appInfo cached before this field existed, and for /// a model this macOS does not declare (hardware newer than the host OS, or a VM). @objc(LKDeviceIconProvider) -final class LKDeviceIconProvider: NSObject { +final class DeviceIconProvider: NSObject { /// Height of the device icon in the window toolbar, matching the legacy /// `icon_*_small` assets (32 pixels at 2x). @objc static let toolbarPointSize: CGFloat = 16 diff --git a/LookInside/Base/LKFrameLayout.swift b/LookInside/Base/FrameLayout.swift similarity index 81% rename from LookInside/Base/LKFrameLayout.swift rename to LookInside/Base/FrameLayout.swift index fb0d6760..489933f3 100644 --- a/LookInside/Base/LKFrameLayout.swift +++ b/LookInside/Base/FrameLayout.swift @@ -1,5 +1,5 @@ // -// LKFrameLayout.swift +// FrameLayout.swift // LookInside // // Frame arithmetic for views and layers laid out by hand. It replaces @@ -12,7 +12,7 @@ import AppKit @objc(LKFrameLayout) -final class LKFrameLayout: NSObject { +final class FrameLayout: NSObject { private enum Target { case view(NSView) case layer(CALayer) @@ -92,14 +92,14 @@ final class LKFrameLayout: NSObject { /// ObjC entry point: `[LKFrameLayout of:view]`. @objc(of:) - static func of(_ object: AnyObject?) -> LKFrameLayout { - LKFrameLayout([object]) + static func of(_ object: AnyObject?) -> FrameLayout { + FrameLayout([object]) } /// ObjC entry point for several views or layers at once. @objc(ofAll:) - static func ofAll(_ objects: [AnyObject]) -> LKFrameLayout { - LKFrameLayout(objects) + static func ofAll(_ objects: [AnyObject]) -> FrameLayout { + FrameLayout(objects) } /// Rounds up to the main screen's pixel grid. `CGFLOAT_MIN` and @@ -127,14 +127,14 @@ final class LKFrameLayout: NSObject { // MARK: - Sizing - /// Sizes an LKBaseView or NSControl to `sizeThatFits:` of an unlimited + /// Sizes an BaseView or NSControl to `sizeThatFits:` of an unlimited /// size; other views and layers are left alone. @objc @discardableResult - func sizeToFit() -> LKFrameLayout { + func sizeToFit() -> FrameLayout { each { target in guard case let .view(view) = target else { return } let unlimited = NSSize(width: CGFloat.greatestFiniteMagnitude, height: .greatestFiniteMagnitude) - if let baseView = view as? LKBaseView { + if let baseView = view as? BaseView { var rect = baseView.frame rect.size = baseView.sizeThatFits(unlimited) baseView.frame = rect @@ -154,14 +154,14 @@ final class LKFrameLayout: NSObject { return self } - /// Sets an LKBaseView's or NSControl's height to what it needs at its + /// Sets an BaseView's or NSControl's height to what it needs at its /// current width. @objc @discardableResult - func heightToFit() -> LKFrameLayout { + func heightToFit() -> FrameLayout { each { target in guard case let .view(view) = target else { return } let height: CGFloat - if let baseView = view as? LKBaseView { + if let baseView = view as? BaseView { height = baseView.sizeThatFits(NSSize(width: baseView.bounds.width, height: .greatestFiniteMagnitude)).height } else if let control = view as? NSControl { height = control.sizeThatFits(NSSize(width: control.bounds.width, height: .greatestFiniteMagnitude)).height @@ -176,27 +176,27 @@ final class LKFrameLayout: NSObject { } @objc(width:) @discardableResult - func width(_ value: CGFloat) -> LKFrameLayout { + func width(_ value: CGFloat) -> FrameLayout { let value = Self.checked(value) each { $0.frame.size.width = Self.snapToPixel(value) } return self } @objc(height:) @discardableResult - func height(_ value: CGFloat) -> LKFrameLayout { + func height(_ value: CGFloat) -> FrameLayout { let value = Self.checked(value) each { $0.frame.size.height = Self.snapToPixel(value) } return self } @objc(size:) @discardableResult - func size(_ value: NSSize) -> LKFrameLayout { + func size(_ value: NSSize) -> FrameLayout { width(value.width).height(value.height) } /// Grows the width to `value` when it is narrower; never snaps. @objc(minWidth:) @discardableResult - func minWidth(_ value: CGFloat) -> LKFrameLayout { + func minWidth(_ value: CGFloat) -> FrameLayout { if value.isNaN { assertionFailure("NaN passed to minWidth") return self @@ -212,30 +212,30 @@ final class LKFrameLayout: NSObject { // MARK: - Position @objc(x:) @discardableResult - func x(_ value: CGFloat) -> LKFrameLayout { + func x(_ value: CGFloat) -> FrameLayout { let value = Self.checked(value) each { $0.frame.origin.x = Self.snapToPixel(value) } return self } @objc(y:) @discardableResult - func y(_ value: CGFloat) -> LKFrameLayout { + func y(_ value: CGFloat) -> FrameLayout { let value = Self.checked(value) each { $0.frame.origin.y = Self.snapToPixel(value) } return self } @objc(offsetX:) @discardableResult - func offsetX(_ value: CGFloat) -> LKFrameLayout { + func offsetX(_ value: CGFloat) -> FrameLayout { offset(x: value, y: 0) } @objc(offsetY:) @discardableResult - func offsetY(_ value: CGFloat) -> LKFrameLayout { + func offsetY(_ value: CGFloat) -> FrameLayout { offset(x: 0, y: value) } - private func offset(x: CGFloat, y: CGFloat) -> LKFrameLayout { + private func offset(x: CGFloat, y: CGFloat) -> FrameLayout { let x = Self.checked(x) let y = Self.checked(y) each { target in @@ -248,43 +248,43 @@ final class LKFrameLayout: NSObject { } @objc(midX:) @discardableResult - func midX(_ value: CGFloat) -> LKFrameLayout { + func midX(_ value: CGFloat) -> FrameLayout { let value = Self.checked(value) - each { LKFrameLayout(targets: [$0]).x(value - $0.bounds.width / 2) } + each { FrameLayout(targets: [$0]).x(value - $0.bounds.width / 2) } return self } @objc(maxX:) @discardableResult - func maxX(_ value: CGFloat) -> LKFrameLayout { + func maxX(_ value: CGFloat) -> FrameLayout { let value = Self.checked(value) - each { LKFrameLayout(targets: [$0]).x(value - $0.bounds.width) } + each { FrameLayout(targets: [$0]).x(value - $0.bounds.width) } return self } @objc(midY:) @discardableResult - func midY(_ value: CGFloat) -> LKFrameLayout { + func midY(_ value: CGFloat) -> FrameLayout { let value = Self.checked(value) - each { LKFrameLayout(targets: [$0]).y(value - $0.bounds.height / 2) } + each { FrameLayout(targets: [$0]).y(value - $0.bounds.height / 2) } return self } @objc(maxY:) @discardableResult - func maxY(_ value: CGFloat) -> LKFrameLayout { + func maxY(_ value: CGFloat) -> FrameLayout { let value = Self.checked(value) - each { LKFrameLayout(targets: [$0]).y(value - $0.bounds.height) } + each { FrameLayout(targets: [$0]).y(value - $0.bounds.height) } return self } /// Puts the right edge `value` points from the parent's right edge. @objc(right:) @discardableResult - func right(_ value: CGFloat) -> LKFrameLayout { + func right(_ value: CGFloat) -> FrameLayout { let value = Self.checked(value) each { target in guard let parentBounds = target.parentBounds else { assertionFailure("right: needs a superview or superlayer") return } - LKFrameLayout(targets: [target]).maxX(parentBounds.width - value) + FrameLayout(targets: [target]).maxX(parentBounds.width - value) } return self } @@ -292,7 +292,7 @@ final class LKFrameLayout: NSObject { /// Puts the bottom edge `value` points from the parent's bottom edge, /// in the parent's own (possibly unflipped) coordinates. @objc(bottom:) @discardableResult - func bottom(_ value: CGFloat) -> LKFrameLayout { + func bottom(_ value: CGFloat) -> FrameLayout { let value = Self.checked(value) each { target in guard let parentBounds = target.parentBounds else { @@ -300,34 +300,34 @@ final class LKFrameLayout: NSObject { return } if target.parentIsFlipped { - LKFrameLayout(targets: [target]).maxY(parentBounds.height - value) + FrameLayout(targets: [target]).maxY(parentBounds.height - value) } else { - LKFrameLayout(targets: [target]).y(value) + FrameLayout(targets: [target]).y(value) } } return self } @objc @discardableResult - func horAlign() -> LKFrameLayout { + func horAlign() -> FrameLayout { each { target in guard let parentBounds = target.parentBounds else { assertionFailure("horAlign needs a superview or superlayer") return } - LKFrameLayout(targets: [target]).midX(parentBounds.width / 2) + FrameLayout(targets: [target]).midX(parentBounds.width / 2) } return self } @objc @discardableResult - func verAlign() -> LKFrameLayout { + func verAlign() -> FrameLayout { each { target in guard let parentBounds = target.parentBounds else { assertionFailure("verAlign needs a superview or superlayer") return } - LKFrameLayout(targets: [target]).midY(parentBounds.height / 2) + FrameLayout(targets: [target]).midY(parentBounds.height / 2) } return self } @@ -335,31 +335,31 @@ final class LKFrameLayout: NSObject { // MARK: - Filling the parent @objc @discardableResult - func fullWidth() -> LKFrameLayout { + func fullWidth() -> FrameLayout { x(0).toRight(0) } @objc @discardableResult - func fullHeight() -> LKFrameLayout { + func fullHeight() -> FrameLayout { each { target in guard let parentBounds = target.parentBounds else { assertionFailure("fullHeight needs a superview or superlayer") return } - LKFrameLayout(targets: [target]).height(parentBounds.height).y(0) + FrameLayout(targets: [target]).height(parentBounds.height).y(0) } return self } @objc @discardableResult - func fullFrame() -> LKFrameLayout { + func fullFrame() -> FrameLayout { fullWidth().fullHeight() } /// Stretches the width so the right edge sits `value` points from the /// parent's right edge; never negative. @objc(toRight:) @discardableResult - func toRight(_ value: CGFloat) -> LKFrameLayout { + func toRight(_ value: CGFloat) -> FrameLayout { let value = Self.checked(value) each { target in let parentWidth = target.parentBounds?.width ?? 0 @@ -373,7 +373,7 @@ final class LKFrameLayout: NSObject { /// Stretches the width so the right edge sits at `value`, never past the /// left edge. @objc(toMaxX:) @discardableResult - func toMaxX(_ value: CGFloat) -> LKFrameLayout { + func toMaxX(_ value: CGFloat) -> FrameLayout { let value = Self.checked(value) each { target in var rect = target.frame @@ -387,7 +387,7 @@ final class LKFrameLayout: NSObject { /// Stretches the height so the bottom edge sits at `value`, never above /// the top edge. @objc(toMaxY:) @discardableResult - func toMaxY(_ value: CGFloat) -> LKFrameLayout { + func toMaxY(_ value: CGFloat) -> FrameLayout { let value = Self.checked(value) each { target in var rect = target.frame @@ -400,7 +400,7 @@ final class LKFrameLayout: NSObject { /// Moves the top edge to `value` keeping the bottom edge in place. @objc(toY:) @discardableResult - func toY(_ value: CGFloat) -> LKFrameLayout { + func toY(_ value: CGFloat) -> FrameLayout { let value = Self.checked(value) each { target in var rect = target.frame @@ -415,7 +415,7 @@ final class LKFrameLayout: NSObject { /// Stretches the height so the bottom edge sits `value` points from the /// parent's bottom edge. @objc(toBottom:) @discardableResult - func toBottom(_ value: CGFloat) -> LKFrameLayout { + func toBottom(_ value: CGFloat) -> FrameLayout { let value = Self.checked(value) each { target in guard let parentBounds = target.parentBounds else { @@ -423,9 +423,9 @@ final class LKFrameLayout: NSObject { return } if target.parentIsFlipped { - LKFrameLayout(targets: [target]).toMaxY(parentBounds.height - value) + FrameLayout(targets: [target]).toMaxY(parentBounds.height - value) } else { - LKFrameLayout(targets: [target]).toY(value) + FrameLayout(targets: [target]).toY(value) } } return self @@ -436,7 +436,7 @@ final class LKFrameLayout: NSObject { /// Keeps only the visible views and layers: not hidden, attached, and at /// least 1% opaque. @objc @discardableResult - func visibles() -> LKFrameLayout { + func visibles() -> FrameLayout { targets = targets.filter(\.isVisible) return self } @@ -445,7 +445,7 @@ final class LKFrameLayout: NSObject { /// every member by the same amount. Does nothing when the members do /// not share a parent. @objc @discardableResult - func groupHorAlign() -> LKFrameLayout { + func groupHorAlign() -> FrameLayout { guard let first = targets.first, let parent = first.parent else { if !targets.isEmpty { assertionFailure("groupHorAlign needs a shared superview or superlayer") @@ -466,14 +466,14 @@ final class LKFrameLayout: NSObject { extension NSView { /// Frame layout for this view, replacing ShortCocoa's `$(view)`. - var lkLayout: LKFrameLayout { - LKFrameLayout([self]) + var lkLayout: FrameLayout { + FrameLayout([self]) } } extension CALayer { /// Frame layout for this layer, replacing ShortCocoa's `$(layer)`. - var lkLayout: LKFrameLayout { - LKFrameLayout([self]) + var lkLayout: FrameLayout { + FrameLayout([self]) } } diff --git a/LookInside/Base/LKImageTextView.swift b/LookInside/Base/ImageTextView.swift similarity index 92% rename from LookInside/Base/LKImageTextView.swift rename to LookInside/Base/ImageTextView.swift index 5d3571b2..b3857cd9 100644 --- a/LookInside/Base/LKImageTextView.swift +++ b/LookInside/Base/ImageTextView.swift @@ -1,5 +1,5 @@ // -// LKImageTextView.swift +// ImageTextView.swift // LookInside // @@ -7,9 +7,9 @@ import AppKit /// An image followed by a one-line label, centred vertically. @objc(LKImageTextView) -class LKImageTextView: LKBaseView { +class ImageTextView: BaseView { @objc let imageView = NSImageView() - @objc let label = LKLabel() + @objc let label = TextLabel() var imageMargins = HorizontalMargins(left: 0, right: 0) diff --git a/LookInside/Base/InputSearch/LKInputSearchView.swift b/LookInside/Base/InputSearch/InputSearchView.swift similarity index 87% rename from LookInside/Base/InputSearch/LKInputSearchView.swift rename to LookInside/Base/InputSearch/InputSearchView.swift index 67074702..a8b0a3f6 100644 --- a/LookInside/Base/InputSearch/LKInputSearchView.swift +++ b/LookInside/Base/InputSearch/InputSearchView.swift @@ -1,5 +1,5 @@ // -// LKInputSearchView.swift +// InputSearchView.swift // LookInside // // A single-line text field with a floating suggestion list, used by the @@ -19,18 +19,18 @@ extension NSAppearance { } } -final class LKInputSearchSuggestionItem: NSObject { +final class InputSearchSuggestionItem: NSObject { var image: NSImage? var text: String? } -protocol LKInputSearchViewDelegate: AnyObject { - func inputSearchView(_ view: LKInputSearchView, suggestionsFor string: String) -> [LKInputSearchSuggestionItem]? - func inputSearchView(_ view: LKInputSearchView, submitText text: String) +protocol InputSearchViewDelegate: AnyObject { + func inputSearchView(_ view: InputSearchView, suggestionsFor string: String) -> [InputSearchSuggestionItem]? + func inputSearchView(_ view: InputSearchView, submitText text: String) } -final class LKInputSearchView: LKBaseView, NSTextFieldDelegate { - weak var delegate: LKInputSearchViewDelegate? +final class InputSearchView: BaseView, NSTextFieldDelegate { + weak var delegate: InputSearchViewDelegate? var horizontalInset: CGFloat = 0 @@ -39,8 +39,8 @@ final class LKInputSearchView: LKBaseView, NSTextFieldDelegate { } private let throttleTime: TimeInterval - private let textFieldView = LKTextFieldView() - private let suggestionWindowController = LKInputSearchSuggestionWindowController() + private let textFieldView = TextFieldView() + private let suggestionWindowController = InputSearchSuggestionWindowController() private var previousInput: String? private var pendingSuggestionUpdate: DispatchWorkItem? @@ -180,11 +180,11 @@ final class LKInputSearchView: LKBaseView, NSTextFieldDelegate { } /// The floating panel that shows the suggestion list. -final class LKInputSearchSuggestionWindowController: LKWindowController { - let suggestionsView: LKInputSearchSuggestionsContentView +final class InputSearchSuggestionWindowController: WindowController { + let suggestionsView: InputSearchSuggestionsContentView init() { - let view = LKInputSearchSuggestionsContentView() + let view = InputSearchSuggestionsContentView() suggestionsView = view let panel = NSPanel(contentRect: NSRect(x: 0, y: 0, width: 400, height: 100), @@ -202,17 +202,17 @@ final class LKInputSearchSuggestionWindowController: LKWindowController { } } -final class LKInputSearchSuggestionsContentView: LKBaseView, NSTableViewDelegate, NSTableViewDataSource { +final class InputSearchSuggestionsContentView: BaseView, NSTableViewDelegate, NSTableViewDataSource { private static let rowHeight: CGFloat = 28 - var items: [LKInputSearchSuggestionItem] = [] { + var items: [InputSearchSuggestionItem] = [] { didSet { tableView.reloadData() } } let tableView = NSTableView() - private let backgroundEffectView = LKVisualEffectView() - private lazy var measuringRowView = LKInputSearchSuggestionsRowView() + private let backgroundEffectView = VisualEffectView() + private lazy var measuringRowView = InputSearchSuggestionsRowView() override init(frame frameRect: NSRect) { super.init(frame: frameRect) @@ -244,7 +244,7 @@ final class LKInputSearchSuggestionsContentView: LKBaseView, NSTableViewDelegate tableView.lkpFullFrame() } - func currentSelectedItem() -> LKInputSearchSuggestionItem? { + func currentSelectedItem() -> InputSearchSuggestionItem? { let row = tableView.selectedRow return items.indices.contains(row) ? items[row] : nil } @@ -271,13 +271,13 @@ final class LKInputSearchSuggestionsContentView: LKBaseView, NSTableViewDelegate func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? { guard items.indices.contains(row) else { - return LKInputSearchSuggestionsRowView() + return InputSearchSuggestionsRowView() } let item = items[row] let identifier = NSUserInterfaceItemIdentifier("cell") - let view = tableView.makeView(withIdentifier: identifier, owner: self) as? LKInputSearchSuggestionsRowView + let view = tableView.makeView(withIdentifier: identifier, owner: self) as? InputSearchSuggestionsRowView ?? { - let view = LKInputSearchSuggestionsRowView() + let view = InputSearchSuggestionsRowView() view.identifier = identifier return view }() @@ -292,11 +292,11 @@ final class LKInputSearchSuggestionsContentView: LKBaseView, NSTableViewDelegate } } -final class LKInputSearchSuggestionsRowView: NSTableRowView { +final class InputSearchSuggestionsRowView: NSTableRowView { private static let horizontalInset: CGFloat = 10 private static let titleLeft: CGFloat = 5 - let titleLabel = LKLabel() + let titleLabel = TextLabel() let imageView = NSImageView() override init(frame frameRect: NSRect) { @@ -334,7 +334,7 @@ final class LKInputSearchSuggestionsRowView: NSTableRowView { override func drawSelection(in _: NSRect) { guard selectionHighlightStyle != .none else { return } - let color = effectiveAppearance.lkpIsDarkMode ? LKHelper.accentColor() : NSColor(red: 0, green: 0, blue: 0, alpha: 0.24) + let color = effectiveAppearance.lkpIsDarkMode ? AppHelper.accentColor() : NSColor(red: 0, green: 0, blue: 0, alpha: 0.24) color.setFill() NSBezierPath(rect: bounds).fill() } diff --git a/LookInside/Base/InputSearch/NSView+LKPeripheralLayout.swift b/LookInside/Base/InputSearch/NSView+LKPeripheralLayout.swift index 0e69f802..0af727cb 100644 --- a/LookInside/Base/InputSearch/NSView+LKPeripheralLayout.swift +++ b/LookInside/Base/InputSearch/NSView+LKPeripheralLayout.swift @@ -5,7 +5,7 @@ // Frame helpers for the Swift peripheral modules (About, Console, Export, // Measure, Preference, InputSearch). They keep the arithmetic of the // ShortCocoa calls they replace: setters snap to the main screen's pixel -// grid, `lkpSizeToFit` / `lkpHeightToFit` only size LKBaseView and NSControl +// grid, `lkpSizeToFit` / `lkpHeightToFit` only size BaseView and NSControl // instances, and edges are measured against the superview's bounds. // @@ -129,9 +129,9 @@ extension NSView { } } - /// Sizes LKBaseView and NSControl instances to their fitting size; other views stay as they are. + /// Sizes BaseView and NSControl instances to their fitting size; other views stay as they are. func lkpSizeToFit() { - if let view = self as? LKBaseView { + if let view = self as? BaseView { view.setFrameSize(view.sizeThatFits(lkpMaxSize)) } else if let control = self as? NSControl { var size = control.sizeThatFits(lkpMaxSize) @@ -145,10 +145,10 @@ extension NSView { } } - /// Sets the fitting height for the current width (LKBaseView and NSControl only). + /// Sets the fitting height for the current width (BaseView and NSControl only). func lkpHeightToFit() { let limit = NSSize(width: bounds.width, height: .greatestFiniteMagnitude) - if let view = self as? LKBaseView { + if let view = self as? BaseView { frame.size.height = view.sizeThatFits(limit).height } else if let control = self as? NSControl { frame.size.height = control.sizeThatFits(limit).height diff --git a/LookInside/Base/Message/LookinMsgAttribute.swift b/LookInside/Base/Message/MessageAttribute.swift similarity index 81% rename from LookInside/Base/Message/LookinMsgAttribute.swift rename to LookInside/Base/Message/MessageAttribute.swift index f2214e89..d3fa4840 100644 --- a/LookInside/Base/Message/LookinMsgAttribute.swift +++ b/LookInside/Base/Message/MessageAttribute.swift @@ -1,14 +1,14 @@ // -// LookinMsgAttribute.swift +// MessageAttribute.swift // LookInside // // A value with target-action subscribers. Setting a different value sends the // subscribers' actions through `NSApp.sendAction(_:to:from:)` with a -// `LookinMsgActionParams` as the sender. Targets and related objects are held +// `MessageActionParameters` as the sender. Targets and related objects are held // weakly; subscribers whose target is gone are dropped on the next change. // // The class names and selectors are the ones the Objective-C version had: -// `LKPreferenceManager` and the inspector controllers still call them. +// `PreferenceManager` and the inspector controllers still call them. // import AppKit @@ -16,14 +16,14 @@ import AppKit /// The sender of a subscriber's action. @objc(LookinMsgActionParams) @objcMembers -final class LookinMsgActionParams: NSObject { +final class MessageActionParameters: NSObject { var value: Any? weak var relatedObject: AnyObject? var userInfo: Any? var doubleValue: Double { guard let number = value as? NSNumber else { - assertionFailure("LookinMsgActionParams.value is not a number") + assertionFailure("MessageActionParameters.value is not a number") return 0 } return number.doubleValue @@ -31,7 +31,7 @@ final class LookinMsgActionParams: NSObject { var integerValue: Int { guard let number = value as? NSNumber else { - assertionFailure("LookinMsgActionParams.value is not a number") + assertionFailure("MessageActionParameters.value is not a number") return 0 } return number.intValue @@ -39,7 +39,7 @@ final class LookinMsgActionParams: NSObject { var boolValue: Bool { guard let number = value as? NSNumber else { - assertionFailure("LookinMsgActionParams.value is not a number") + assertionFailure("MessageActionParameters.value is not a number") return false } return number.boolValue @@ -48,7 +48,7 @@ final class LookinMsgActionParams: NSObject { @objc(LookinMsgAttribute) @objcMembers -class LookinMsgAttribute: NSObject { +class MessageAttribute: NSObject { /// One target-action pair. Two subscriptions are the same when the target /// and the related object are the same objects and the action has the same name. private final class Subscriber { @@ -82,8 +82,8 @@ class LookinMsgAttribute: NSObject { } @objc(attributeWithValue:) - class func attribute(withValue value: Any?) -> LookinMsgAttribute { - LookinMsgAttribute(value: value) + class func attribute(withValue value: Any?) -> MessageAttribute { + MessageAttribute(value: value) } /// Stores `value` and sends every subscriber's action, except the subscriber @@ -101,7 +101,7 @@ class LookinMsgAttribute: NSObject { guard let target = subscriber.target, target !== ignored else { continue } - let params = LookinMsgActionParams() + let params = MessageActionParameters() params.userInfo = userInfo params.value = value params.relatedObject = subscriber.relatedObject @@ -128,7 +128,7 @@ class LookinMsgAttribute: NSObject { subscribers.append(Subscriber(target: target, action: action, relatedObject: related)) if sendAtOnce { - let params = LookinMsgActionParams() + let params = MessageActionParameters() params.value = currentValue params.relatedObject = related NSApp.sendAction(action, to: target, from: params) @@ -138,14 +138,14 @@ class LookinMsgAttribute: NSObject { @objc(LookinDoubleMsgAttribute) @objcMembers -final class LookinDoubleMsgAttribute: LookinMsgAttribute { +final class DoubleMessageAttribute: MessageAttribute { convenience init(double value: Double) { self.init(value: NSNumber(value: value)) } @objc(attributeWithDouble:) - class func attribute(withDouble value: Double) -> LookinDoubleMsgAttribute { - LookinDoubleMsgAttribute(double: value) + class func attribute(withDouble value: Double) -> DoubleMessageAttribute { + DoubleMessageAttribute(double: value) } var currentDoubleValue: Double { @@ -159,14 +159,14 @@ final class LookinDoubleMsgAttribute: LookinMsgAttribute { @objc(LookinIntegerMsgAttribute) @objcMembers -final class LookinIntegerMsgAttribute: LookinMsgAttribute { +final class IntegerMessageAttribute: MessageAttribute { convenience init(integer value: Int) { self.init(value: NSNumber(value: value)) } @objc(attributeWithInteger:) - class func attribute(withInteger value: Int) -> LookinIntegerMsgAttribute { - LookinIntegerMsgAttribute(integer: value) + class func attribute(withInteger value: Int) -> IntegerMessageAttribute { + IntegerMessageAttribute(integer: value) } var currentIntegerValue: Int { @@ -180,14 +180,14 @@ final class LookinIntegerMsgAttribute: LookinMsgAttribute { @objc(LookinBOOLMsgAttribute) @objcMembers -final class LookinBOOLMsgAttribute: LookinMsgAttribute { +final class BoolMessageAttribute: MessageAttribute { convenience init(bool value: Bool) { self.init(value: NSNumber(value: value)) } @objc(attributeWithBOOL:) - class func attribute(withBOOL value: Bool) -> LookinBOOLMsgAttribute { - LookinBOOLMsgAttribute(bool: value) + class func attribute(withBOOL value: Bool) -> BoolMessageAttribute { + BoolMessageAttribute(bool: value) } var currentBOOLValue: Bool { diff --git a/LookInside/Base/Message/LKPeripheralAlerts.swift b/LookInside/Base/Message/PeripheralAlerts.swift similarity index 96% rename from LookInside/Base/Message/LKPeripheralAlerts.swift rename to LookInside/Base/Message/PeripheralAlerts.swift index 830dbb01..7e5e3168 100644 --- a/LookInside/Base/Message/LKPeripheralAlerts.swift +++ b/LookInside/Base/Message/PeripheralAlerts.swift @@ -1,5 +1,5 @@ // -// LKPeripheralAlerts.swift +// PeripheralAlerts.swift // LookInside // // Swift counterparts of the `LookinErrorMake`, `AlertError` and @@ -8,7 +8,7 @@ import AppKit -enum LKPeripheralAlerts { +enum PeripheralAlerts { /// `LookinErrorMake(title, detail)`: a default-code Lookin error. static func error(title: String, detail: String) -> NSError { NSError(domain: LookinErrorDomain, code: LookinErrCode_Default, userInfo: [ diff --git a/LookInside/Base/LKNumberInputView.swift b/LookInside/Base/NumberInputView.swift similarity index 95% rename from LookInside/Base/LKNumberInputView.swift rename to LookInside/Base/NumberInputView.swift index 2051cff9..09ddba3b 100644 --- a/LookInside/Base/LKNumberInputView.swift +++ b/LookInside/Base/NumberInputView.swift @@ -1,5 +1,5 @@ // -// LKNumberInputView.swift +// NumberInputView.swift // LookInside // @@ -8,7 +8,7 @@ import AppKit let LKNumberInputHorizontalHeight: CGFloat = 21 let LKNumberInputVerticalHeight: CGFloat = 38 -@objc enum LKNumberInputViewStyle: UInt { +@objc enum NumberInputViewStyle: UInt { /// The title sits inside the field, on its right. case horizontal /// The title sits under the field. @@ -17,11 +17,11 @@ let LKNumberInputVerticalHeight: CGFloat = 38 /// A Dashboard number field with a short title. @objc(LKNumberInputView) -class LKNumberInputView: LKBaseView { - @objc let textFieldView = LKTextFieldView() - private let titleLabel = LKLabel() +class NumberInputView: BaseView { + @objc let textFieldView = TextFieldView() + private let titleLabel = TextLabel() - @objc var viewStyle: LKNumberInputViewStyle = .horizontal { + @objc var viewStyle: NumberInputViewStyle = .horizontal { didSet { applyViewStyle() } } diff --git a/LookInside/Base/LKOutlineRowView.swift b/LookInside/Base/OutlineRowView.swift similarity index 83% rename from LookInside/Base/LKOutlineRowView.swift rename to LookInside/Base/OutlineRowView.swift index 17362c1d..c2f0152c 100644 --- a/LookInside/Base/LKOutlineRowView.swift +++ b/LookInside/Base/OutlineRowView.swift @@ -1,5 +1,5 @@ // -// LKOutlineRowView.swift +// OutlineRowView.swift // LookInside // // Created by Li Kai on 2019/4/20. @@ -11,7 +11,7 @@ import AppKit private let indentUnitWidth: CGFloat = 14 private let disclosureWidth: CGFloat = 16 -@objc enum LKOutlineRowViewStatus: UInt { +@objc enum OutlineRowViewStatus: UInt { case notExpandable case expanded case collapsed @@ -19,7 +19,7 @@ private let disclosureWidth: CGFloat = 16 @objc(LKOutlineRowView) @objcMembers -class LKOutlineRowView: LKTableRowView { +class OutlineRowView: TableRowView { let disclosureButton: NSButton! let imageView: NSImageView! @@ -31,7 +31,7 @@ class LKOutlineRowView: LKTableRowView { } } - var status: LKOutlineRowViewStatus = .notExpandable { + var status: OutlineRowViewStatus = .notExpandable { didSet { updateDisclosureButton() } @@ -70,13 +70,13 @@ class LKOutlineRowView: LKTableRowView { } required init?(coder _: NSCoder) { - fatalError("LKOutlineRowView is not loaded from archives") + fatalError("OutlineRowView is not loaded from archives") } override func layout() { super.layout() - LKHierarchyFrameLayout(disclosureButton) + HierarchyFrameLayout(disclosureButton) .width(disclosureWidth) .fullHeight() .midX(Self.dislosureMidX(withIndentLevel: indentLevel)) @@ -84,19 +84,19 @@ class LKOutlineRowView: LKTableRowView { var x = disclosureButton.frame.maxX if !imageView.isHidden, imageView.alphaValue > 0 { - LKHierarchyFrameLayout(imageView).sizeToFit().verAlign().x(x + imageLeft) + HierarchyFrameLayout(imageView).sizeToFit().verAlign().x(x + imageLeft) x = imageView.frame.maxX + imageRight } - LKHierarchyFrameLayout(titleLabel).sizeToFit().x(x + titleLeft).verAlign() + HierarchyFrameLayout(titleLabel).sizeToFit().x(x + titleLeft).verAlign() var maxX = titleLabel.frame.maxX if !subtitleLabel.isHidden, subtitleLabel.alphaValue > 0 { - LKHierarchyFrameLayout(subtitleLabel).sizeToFit().x(titleLabel.frame.maxX + subtitleLeft).verAlign() + HierarchyFrameLayout(subtitleLabel).sizeToFit().x(titleLabel.frame.maxX + subtitleLeft).verAlign() maxX = subtitleLabel.frame.maxX } for view: NSView in [disclosureButton!, titleLabel!, subtitleLabel!] where view.lkHierarchyIsLaidOutVisible { - LKHierarchyFrameLayout(view).offsetY(-1) + HierarchyFrameLayout(view).offsetY(-1) } horizontalScrollWidthManager?.rowDidLayout(withWidth: maxX) diff --git a/LookInside/Base/LKPerformanceReporter.swift b/LookInside/Base/PerformanceReporter.swift similarity index 73% rename from LookInside/Base/LKPerformanceReporter.swift rename to LookInside/Base/PerformanceReporter.swift index 72223260..82147f81 100644 --- a/LookInside/Base/LKPerformanceReporter.swift +++ b/LookInside/Base/PerformanceReporter.swift @@ -1,5 +1,5 @@ // -// LKPerformanceReporter.swift +// PerformanceReporter.swift // LookInside // @@ -8,10 +8,10 @@ import QuartzCore /// Timestamps of the current hierarchy reload. Nothing reads them yet; the /// hooks stay so reload timing can be reported again. @objc(LKPerformanceReporter) -final class LKPerformanceReporter: NSObject { - private static let shared = LKPerformanceReporter() +final class PerformanceReporter: NSObject { + private static let shared = PerformanceReporter() - @objc static func sharedInstance() -> LKPerformanceReporter { + @objc static func sharedInstance() -> PerformanceReporter { shared } diff --git a/LookInside/Base/LKPopPanel.swift b/LookInside/Base/PopPanel.swift similarity index 92% rename from LookInside/Base/LKPopPanel.swift rename to LookInside/Base/PopPanel.swift index 84e4978c..f592724c 100644 --- a/LookInside/Base/LKPopPanel.swift +++ b/LookInside/Base/PopPanel.swift @@ -1,5 +1,5 @@ // -// LKPopPanel.swift +// PopPanel.swift // LookInside // @@ -7,13 +7,13 @@ import AppKit /// A borderless rounded panel for small editors that pop up over a window. @objc(LKPopPanel) -class LKPopPanel: NSPanel { +class PopPanel: NSPanel { @objc(initWithSize:) init(size: NSSize) { // Without NSWindowStyleMaskNonactivatingPanel, clicking another app // while the panel is shown hides every LookInside window. super.init(contentRect: NSRect(origin: .zero, size: size), styleMask: .nonactivatingPanel, backing: .buffered, defer: true) - let contentView = LKBaseView() + let contentView = BaseView() contentView.layer?.cornerRadius = 6 contentView.layer?.borderWidth = 1 contentView.didChangeAppearanceBlock = { view, isDarkMode in diff --git a/LookInside/Base/LKProgressIndicatorView.swift b/LookInside/Base/ProgressIndicatorView.swift similarity index 94% rename from LookInside/Base/LKProgressIndicatorView.swift rename to LookInside/Base/ProgressIndicatorView.swift index f9ba4769..07fb5c79 100644 --- a/LookInside/Base/LKProgressIndicatorView.swift +++ b/LookInside/Base/ProgressIndicatorView.swift @@ -1,5 +1,5 @@ // -// LKProgressIndicatorView.swift +// ProgressIndicatorView.swift // LookInside // @@ -11,7 +11,7 @@ let InitialIndicatorProgressWhenFetchHierarchy: CGFloat = 0.7 /// A thin accent-coloured bar that fills from the left. @objc(LKProgressIndicatorView) -class LKProgressIndicatorView: LKBaseView { +class ProgressIndicatorView: BaseView { private let fillLayer = CALayer() /// 0...1. Animatable through `animator()`. @@ -30,7 +30,7 @@ class LKProgressIndicatorView: LKBaseView { } private func setUp() { - fillLayer.backgroundColor = LKHelper.accentColor().cgColor + fillLayer.backgroundColor = AppHelper.accentColor().cgColor layer?.addSublayer(fillLayer) fillLayer.removeImplicitAnimations() progress = 0 diff --git a/LookInside/Base/LKSplitView.swift b/LookInside/Base/SplitView.swift similarity index 79% rename from LookInside/Base/LKSplitView.swift rename to LookInside/Base/SplitView.swift index 74c6e23d..f7becc65 100644 --- a/LookInside/Base/LKSplitView.swift +++ b/LookInside/Base/SplitView.swift @@ -1,5 +1,5 @@ // -// LKSplitView.swift +// SplitView.swift // LookInside // @@ -7,9 +7,9 @@ import AppKit /// A split view without visible dividers that reports its first layout. @objc(LKSplitView) -class LKSplitView: NSSplitView { +class SplitView: NSSplitView { /// Called once, after the first `layout`. - @objc var didFinishFirstLayout: ((LKSplitView) -> Void)? + @objc var didFinishFirstLayout: ((SplitView) -> Void)? private var hasLaidOut = false diff --git a/LookInside/Base/LKSwiftDemangler.swift b/LookInside/Base/SwiftDemangler.swift similarity index 94% rename from LookInside/Base/LKSwiftDemangler.swift rename to LookInside/Base/SwiftDemangler.swift index b0f77aa1..5b7bc5d8 100644 --- a/LookInside/Base/LKSwiftDemangler.swift +++ b/LookInside/Base/SwiftDemangler.swift @@ -1,5 +1,5 @@ // -// LKSwiftDemangler.swift +// SwiftDemangler.swift // LookinClient // // Created by likai.123 on 2024/1/14. @@ -9,7 +9,7 @@ import Demangling import Foundation -public class LKSwiftDemangler: NSObject { +public class SwiftDemangler: NSObject { private static var simpleCache: [String: String] = [:] private static var completedCache: [String: String] = [:] diff --git a/LookInside/Base/LKTableRowView.swift b/LookInside/Base/TableRowView.swift similarity index 83% rename from LookInside/Base/LKTableRowView.swift rename to LookInside/Base/TableRowView.swift index f93b6049..9dba9d99 100644 --- a/LookInside/Base/LKTableRowView.swift +++ b/LookInside/Base/TableRowView.swift @@ -1,5 +1,5 @@ // -// LKTableRowView.swift +// TableRowView.swift // Lookin // // Created by Li Kai on 2019/4/20. @@ -10,11 +10,11 @@ import AppKit @objc(LKTableRowView) @objcMembers -class LKTableRowView: NSTableRowView { - let titleLabel: LKLabel! - let subtitleLabel: LKLabel! +class TableRowView: NSTableRowView { + let titleLabel: TextLabel! + let subtitleLabel: TextLabel! - /// The selection LKTableView draws. NSTableView's own row selection + /// The selection TableView draws. NSTableView's own row selection /// (setSelected:) does not change it, but isSelected reports this value. var isRowSelected: Bool { get { @@ -62,7 +62,7 @@ class LKTableRowView: NSTableRowView { darkModeState = isDarkMode } - weak var horizontalScrollWidthManager: LKTableViewHorizontalScrollWidthManager? + weak var horizontalScrollWidthManager: TableViewHorizontalScrollWidthManager? private let backgroundColorLayer = CALayer() private var selectedState = false @@ -70,8 +70,8 @@ class LKTableRowView: NSTableRowView { private var darkModeState = false override init(frame frameRect: NSRect) { - titleLabel = LKLabel() - subtitleLabel = LKLabel() + titleLabel = TextLabel() + subtitleLabel = TextLabel() super.init(frame: frameRect) wantsLayer = true @@ -90,7 +90,7 @@ class LKTableRowView: NSTableRowView { } required init?(coder _: NSCoder) { - fatalError("LKTableRowView is not loaded from archives") + fatalError("TableRowView is not loaded from archives") } override func layout() { @@ -110,7 +110,7 @@ class LKTableRowView: NSTableRowView { private func updateBackgroundLayerColor() { if isRowSelected { - backgroundColorLayer.backgroundColor = LKHelper.accentColor().cgColor + backgroundColorLayer.backgroundColor = AppHelper.accentColor().cgColor } else if isHovered { backgroundColorLayer.backgroundColor = isDarkMode ? NSColor.lkBaseRGB(255, 255, 255, 0.15).cgColor : NSColor.lkBaseRGB(0, 0, 0, 0.1).cgColor } else { @@ -120,4 +120,4 @@ class LKTableRowView: NSTableRowView { } @objc(LKTableBlankRowView) -final class LKTableBlankRowView: LKTableRowView {} +final class TableBlankRowView: TableRowView {} diff --git a/LookInside/Base/LKTableView.swift b/LookInside/Base/TableView.swift similarity index 86% rename from LookInside/Base/LKTableView.swift rename to LookInside/Base/TableView.swift index 57be84ac..87bded8b 100644 --- a/LookInside/Base/LKTableView.swift +++ b/LookInside/Base/TableView.swift @@ -1,5 +1,5 @@ // -// LKTableView.swift +// TableView.swift // LookInside // // Created by Li Kai on 2019/4/20. @@ -8,9 +8,9 @@ import AppKit -/// The table inside an `LKTableView`. Arrow keys go to the scroll view's +/// The table inside an `TableView`. Arrow keys go to the scroll view's /// responder chain instead of moving NSTableView's own selection. -private final class LKKeyForwardingTableView: NSTableView { +private final class KeyForwardingTableView: NSTableView { weak var responder: NSResponder? override func keyDown(with event: NSEvent) { @@ -20,23 +20,23 @@ private final class LKKeyForwardingTableView: NSTableView { /// Every row argument may be -1. @objc(LKTableViewDelegate) -protocol LKTableViewDelegate: NSTableViewDelegate { +protocol TableViewDelegate: NSTableViewDelegate { @objc(tableView:didSelectRow:) - optional func tableView(_ tableView: LKTableView!, didSelectRow row: Int) + optional func tableView(_ tableView: TableView!, didSelectRow row: Int) @objc(tableView:didHoverAtRow:) - optional func tableView(_ tableView: LKTableView!, didHoverAtRow row: Int) + optional func tableView(_ tableView: TableView!, didHoverAtRow row: Int) @objc(tableView:didDoubleClickAtRow:) - optional func tableView(_ tableView: LKTableView!, didDoubleClickAtRow row: Int) + optional func tableView(_ tableView: TableView!, didDoubleClickAtRow row: Int) /// A click on the blank area below the rows. @objc(tableViewDidClickBlankArea:) - optional func tableViewDidClickBlankArea(_ tableView: LKTableView!) + optional func tableViewDidClickBlankArea(_ tableView: TableView!) } @objc(LKTableViewDataSource) -protocol LKTableViewDataSource: NSTableViewDataSource {} +protocol TableViewDataSource: NSTableViewDataSource {} @objc(LKTableView) -class LKTableView: NSScrollView { +class TableView: NSScrollView { @objc let tableView: NSTableView! /// Defaults to true. @@ -49,15 +49,15 @@ class LKTableView: NSScrollView { } } - @objc weak var delegate: LKTableViewDelegate? - @objc weak var dataSource: LKTableViewDataSource? + @objc weak var delegate: TableViewDelegate? + @objc weak var dataSource: TableViewDataSource? /// Defaults to true. @objc var adjustsSelectionAutomatically: Bool = true /// Defaults to true. @objc var adjustsHoverAutomatically: Bool = true - private var horizontalScrollWidthManager: LKTableViewHorizontalScrollWidthManager? + private var horizontalScrollWidthManager: TableViewHorizontalScrollWidthManager? /// -1 when no row is hovered. private var hoveredRow: Int = -1 { @@ -73,7 +73,7 @@ class LKTableView: NSScrollView { private var selectedRow: Int = -1 @objc override init(frame frameRect: NSRect) { - let tableView = LKKeyForwardingTableView() + let tableView = KeyForwardingTableView() self.tableView = tableView super.init(frame: frameRect) @@ -105,12 +105,12 @@ class LKTableView: NSScrollView { } required init?(coder _: NSCoder) { - fatalError("LKTableView is not loaded from archives") + fatalError("TableView is not loaded from archives") } override func layout() { super.layout() - let tableLayout = LKHierarchyFrameLayout(tableView) + let tableLayout = HierarchyFrameLayout(tableView) guard canScrollHorizontally, let manager = horizontalScrollWidthManager else { tableLayout.fullWidth() return @@ -127,7 +127,7 @@ class LKTableView: NSScrollView { horizontalScrollWidthManager = nil if canScrollHorizontally { - let manager = LKTableViewHorizontalScrollWidthManager() + let manager = TableViewHorizontalScrollWidthManager() manager.didReachNewMaxWidth = { [weak self] in self?.handleRowViewMaxWidthChange() } @@ -158,7 +158,7 @@ class LKTableView: NSScrollView { guard manager.maxRowWidth > frame.width else { return } - LKHierarchyFrameLayout(tableView).width(manager.maxRowWidth + 20) + HierarchyFrameLayout(tableView).width(manager.maxRowWidth + 20) } // MARK: - Event handlers @@ -167,7 +167,7 @@ class LKTableView: NSScrollView { /// mouse-down. @objc private func handleTableViewDefaultAction() { let clickedRow = tableView.clickedRow - if clickedRow < 0, let delegate, delegate.responds(to: #selector(LKTableViewDelegate.tableViewDidClickBlankArea(_:))) { + if clickedRow < 0, let delegate, delegate.responds(to: #selector(TableViewDelegate.tableViewDidClickBlankArea(_:))) { delegate.tableViewDidClickBlankArea?(self) } } @@ -215,11 +215,11 @@ class LKTableView: NSScrollView { // MARK: - Hover and selection - private func lkRowView(at row: Int) -> LKTableRowView? { + private func lkRowView(at row: Int) -> TableRowView? { guard row >= 0, row < tableView.numberOfRows else { return nil } - return tableView.rowView(atRow: row, makeIfNecessary: false) as? LKTableRowView + return tableView.rowView(atRow: row, makeIfNecessary: false) as? TableRowView } private func hoveredRowDidChange(from previousRow: Int) { @@ -252,7 +252,7 @@ class LKTableView: NSScrollView { // MARK: - NSTableViewDataSource / NSTableViewDelegate -extension LKTableView: NSTableViewDataSource, NSTableViewDelegate { +extension TableView: NSTableViewDataSource, NSTableViewDelegate { func numberOfRows(in tableView: NSTableView) -> Int { // Asks the delegate whether it answers, then asks the data source, // as the Objective-C version did; both are the same object for every @@ -272,7 +272,7 @@ extension LKTableView: NSTableViewDataSource, NSTableViewDelegate { return nil } let rowView = delegate.tableView?(tableView, rowViewForRow: row) - if let rowView = rowView as? LKTableRowView { + if let rowView = rowView as? TableRowView { rowView.isHovered = (hoveredRow == row) if adjustsSelectionAutomatically { rowView.isRowSelected = (selectedRow == row) diff --git a/LookInside/Base/LKTableViewHorizontalScrollWidthManager.swift b/LookInside/Base/TableViewHorizontalScrollWidthManager.swift similarity index 82% rename from LookInside/Base/LKTableViewHorizontalScrollWidthManager.swift rename to LookInside/Base/TableViewHorizontalScrollWidthManager.swift index ce05da24..18a41334 100644 --- a/LookInside/Base/LKTableViewHorizontalScrollWidthManager.swift +++ b/LookInside/Base/TableViewHorizontalScrollWidthManager.swift @@ -1,5 +1,5 @@ // -// LKTableViewHorizontalScrollWidthManager.swift +// TableViewHorizontalScrollWidthManager.swift // LookInside // // Created by likaimacbookhome on 2023/12/17. @@ -9,7 +9,7 @@ import Foundation @objc(LKTableViewHorizontalScrollWidthManager) -class LKTableViewHorizontalScrollWidthManager: NSObject { +class TableViewHorizontalScrollWidthManager: NSObject { @objc var maxRowWidth: CGFloat = 0 @objc var didReachNewMaxWidth: (() -> Void)? diff --git a/LookInside/Base/LKTextControl.swift b/LookInside/Base/TextControl.swift similarity index 96% rename from LookInside/Base/LKTextControl.swift rename to LookInside/Base/TextControl.swift index 7efb8085..eafd003e 100644 --- a/LookInside/Base/LKTextControl.swift +++ b/LookInside/Base/TextControl.swift @@ -1,5 +1,5 @@ // -// LKTextControl.swift +// TextControl.swift // Lookin // // Created by Li Kai on 2019/3/12. @@ -9,8 +9,8 @@ import AppKit @objc(LKTextControl) -class LKTextControl: LKBaseControl { - @objc let label = LKLabel() +class TextControl: BaseControl { + @objc let label = TextLabel() @objc var insets = NSEdgeInsets() { didSet { diff --git a/LookInside/Base/LKTextFieldView.swift b/LookInside/Base/TextFieldView.swift similarity index 93% rename from LookInside/Base/LKTextFieldView.swift rename to LookInside/Base/TextFieldView.swift index d54a5e90..5c1d15c0 100644 --- a/LookInside/Base/LKTextFieldView.swift +++ b/LookInside/Base/TextFieldView.swift @@ -1,5 +1,5 @@ // -// LKTextFieldView.swift +// TextFieldView.swift // LookInside // @@ -8,14 +8,14 @@ import AppKit /// A text field with insets, an optional leading image and an optional /// trailing button that clears a search. @objc(LKTextFieldView) -class LKTextFieldView: LKBaseView { +class TextFieldView: BaseView { @objc let textField = NSTextField() @objc var insets = NSEdgeInsetsZero { didSet { needsLayout = true } } - @objc var textColors: LKTwoColors? { + @objc var textColors: TwoColors? { didSet { updateColors() } } @@ -31,8 +31,8 @@ class LKTextFieldView: LKBaseView { private var stringValueObservation: NSKeyValueObservation? /// A read-only, borderless label. - @objc(labelView) static func label() -> LKTextFieldView { - let view = LKTextFieldView() + @objc(labelView) static func label() -> TextFieldView { + let view = TextFieldView() view.textField.wantsLayer = true view.textField.backgroundColor = .clear view.textField.isBezeled = false @@ -72,9 +72,9 @@ class LKTextFieldView: LKBaseView { } } else { // A plain label, like the constraint popover's title. - LKFrameLayout([imageView, textField]).sizeToFit().verAlign() + FrameLayout([imageView, textField]).sizeToFit().verAlign() textField.lkLayout.x(imageView.frame.maxX) - LKFrameLayout([imageView, textField]).groupHorAlign() + FrameLayout([imageView, textField]).groupHorAlign() } } else { textField.lkLayout.x(insets.left).toRight(insets.right).heightToFit().verAlign().offsetY(insets.top - insets.bottom) diff --git a/LookInside/Base/LKLabel.swift b/LookInside/Base/TextLabel.swift similarity index 90% rename from LookInside/Base/LKLabel.swift rename to LookInside/Base/TextLabel.swift index d4635106..71acd688 100644 --- a/LookInside/Base/LKLabel.swift +++ b/LookInside/Base/TextLabel.swift @@ -1,5 +1,5 @@ // -// LKLabel.swift +// TextLabel.swift // Lookin // // Created by Li Kai on 2018/8/4. @@ -9,16 +9,16 @@ import AppKit @objc(LKLabel) -class LKLabel: NSTextField { +class TextLabel: NSTextField { /// 默认为 nil - @objc var textColors: LKTwoColors? { + @objc var textColors: TwoColors? { didSet { updateColors() } } /// 默认为 nil - @objc var backgroundColors: LKTwoColors? { + @objc var backgroundColors: TwoColors? { didSet { updateColors() } diff --git a/LookInside/Base/LKTextsMenuView.swift b/LookInside/Base/TextsMenuView.swift similarity index 95% rename from LookInside/Base/LKTextsMenuView.swift rename to LookInside/Base/TextsMenuView.swift index 77231a1a..61f87afc 100644 --- a/LookInside/Base/LKTextsMenuView.swift +++ b/LookInside/Base/TextsMenuView.swift @@ -1,11 +1,11 @@ // -// LKTextsMenuView.swift +// TextsMenuView.swift // LookInside // import AppKit -@objc enum LKTextsMenuViewType: Int { +@objc enum TextsMenuViewType: Int { /// Left column left-aligned, right column right-aligned. case justified /// Both columns meet in the middle. @@ -15,11 +15,11 @@ import AppKit /// Two columns of key / value labels, optionally with a button after a /// value. @objc(LKTextsMenuView) -class LKTextsMenuView: LKBaseView { +class TextsMenuView: BaseView { /// Defaults to {0, 3, 0, 5}. @objc var insets = NSEdgeInsets(top: 0, left: 3, bottom: 0, right: 5) - @objc var type: LKTextsMenuViewType = .justified { + @objc var type: TextsMenuViewType = .justified { didSet { updateAlignments() } } @@ -34,8 +34,8 @@ class LKTextsMenuView: LKBaseView { /// Defaults to 10. @objc var horSpace: CGFloat = 10 - private var leftLabels: [LKLabel] = [] - private var rightLabels: [LKLabel] = [] + private var leftLabels: [TextLabel] = [] + private var rightLabels: [TextLabel] = [] private var buttons: [Int: NSButton] = [:] private let buttonMarginLeft: CGFloat = 4 @@ -79,8 +79,8 @@ class LKTextsMenuView: LKBaseView { } } - private func makeLabel() -> LKLabel { - let label = LKLabel() + private func makeLabel() -> TextLabel { + let label = TextLabel() label.isSelectable = true label.font = font label.maximumNumberOfLines = 1 diff --git a/LookInside/Base/LKTipsView.swift b/LookInside/Base/TipsView.swift similarity index 95% rename from LookInside/Base/LKTipsView.swift rename to LookInside/Base/TipsView.swift index 361284be..432067ac 100644 --- a/LookInside/Base/LKTipsView.swift +++ b/LookInside/Base/TipsView.swift @@ -1,5 +1,5 @@ // -// LKTipsView.swift +// TipsView.swift // LookInside // @@ -8,7 +8,7 @@ import AppKit /// A pill-shaped notice: optional image, a title, and an optional button /// after a separator. @objc(LKTipsView) -class LKTipsView: LKBaseView { +class TipsView: BaseView { @objc weak var bindingObject: AnyObject? @objc var title: String? { @@ -36,9 +36,9 @@ class LKTipsView: LKBaseView { @objc weak var target: AnyObject? @objc var clickAction: Selector? - @objc var didClick: ((LKTipsView) -> Void)? + @objc var didClick: ((TipsView) -> Void)? - let titleLabel = LKLabel() + let titleLabel = TextLabel() private let imageView = NSImageView() let sepLayer = CALayer() @@ -157,11 +157,11 @@ class LKTipsView: LKBaseView { /// to the device family's icon when the Server reports no model. @objc(setImageByAppInfo:) func setImage(byAppInfo appInfo: InspectedAppInfo?) { - if let deviceIcon = LKDeviceIconProvider.deviceIcon(forAppInfo: appInfo, pointSize: LKDeviceIconProvider.tipsPointSize) { + if let deviceIcon = DeviceIconProvider.deviceIcon(forAppInfo: appInfo, pointSize: DeviceIconProvider.tipsPointSize) { image = deviceIcon return } - if LKHelper.appInfoLooksLikeMacTarget(appInfo) { + if AppHelper.appInfoLooksLikeMacTarget(appInfo) { image = NSImage(named: "icon_mac_big") return } @@ -210,7 +210,7 @@ class LKTipsView: LKBaseView { /// An orange notice that can pulse. @objc(LKYellowTipsView) -class LKYellowTipsView: LKTipsView { +class YellowTipsView: TipsView { private var isAnimating = false @objc func startAnimation() { @@ -250,7 +250,7 @@ class LKYellowTipsView: LKTipsView { /// A red notice that pulses, used for connection loss. @objc(LKRedTipsView) -class LKRedTipsView: LKTipsView { +class RedTipsView: TipsView { @objc func startAnimation() { let animation = CABasicAnimation(keyPath: "backgroundColor") animation.fromValue = NSColor.lkBaseRGB(208, 2, 27, 0.9).cgColor diff --git a/LookInside/Base/LKTwoColors.swift b/LookInside/Base/TwoColors.swift similarity index 87% rename from LookInside/Base/LKTwoColors.swift rename to LookInside/Base/TwoColors.swift index ad2c8562..0131f3bb 100644 --- a/LookInside/Base/LKTwoColors.swift +++ b/LookInside/Base/TwoColors.swift @@ -1,5 +1,5 @@ // -// LKTwoColors.swift +// TwoColors.swift // LookInside // @@ -7,13 +7,13 @@ import AppKit /// A colour pair resolved against the app's current appearance. @objc(LKTwoColors) -final class LKTwoColors: NSObject { +final class TwoColors: NSObject { @objc var colorInLightMode: NSColor? @objc var colorInDarkMode: NSColor? @objc(colorsWithColorInLightMode:colorInDarkMode:) - static func colors(inLightMode colorInLightMode: NSColor?, inDarkMode colorInDarkMode: NSColor?) -> LKTwoColors { - let colors = LKTwoColors() + static func colors(inLightMode colorInLightMode: NSColor?, inDarkMode colorInDarkMode: NSColor?) -> TwoColors { + let colors = TwoColors() colors.colorInLightMode = colorInLightMode colors.colorInDarkMode = colorInDarkMode return colors diff --git a/LookInside/Base/LKUserActionManager.swift b/LookInside/Base/UserActionManager.swift similarity index 66% rename from LookInside/Base/LKUserActionManager.swift rename to LookInside/Base/UserActionManager.swift index 8f6e9adc..f2a15740 100644 --- a/LookInside/Base/LKUserActionManager.swift +++ b/LookInside/Base/UserActionManager.swift @@ -1,11 +1,11 @@ // -// LKUserActionManager.swift +// UserActionManager.swift // LookInside // import Foundation -@objc enum LKUserActionType: Int { +@objc enum UserActionType: Int { @objc(LKUserActionType_None) case none /// A click, double click, pan or similar in the preview. @objc(LKUserActionType_PreviewOperation) case previewOperation @@ -15,19 +15,19 @@ import Foundation @objc(LKUserActionType_SelectedItemChange) case selectedItemChange } -@objc protocol LKUserActionManagerDelegate: NSObjectProtocol { +@objc protocol UserActionManagerDelegate: NSObjectProtocol { /// Called for every `sendAction:`. @objc(LKUserActionManager:didAct:) - func lkUserActionManager(_ manager: LKUserActionManager, didAct type: LKUserActionType) + func lkUserActionManager(_ manager: UserActionManager, didAct type: UserActionType) } /// Broadcasts user actions (preview gestures, Dashboard clicks) to weakly /// held delegates, for example so an open Dashboard editor can close. @objc(LKUserActionManager) -final class LKUserActionManager: NSObject { - private static let shared = LKUserActionManager() +final class UserActionManager: NSObject { + private static let shared = UserActionManager() - @objc static func sharedInstance() -> LKUserActionManager { + @objc static func sharedInstance() -> UserActionManager { shared } @@ -36,7 +36,7 @@ final class LKUserActionManager: NSObject { /// Delegates are held weakly and need no removal; adding one twice /// keeps a single entry. @objc(addDelegate:) - func add(_ delegate: LKUserActionManagerDelegate) { + func add(_ delegate: UserActionManagerDelegate) { if delegates.allObjects.contains(where: { ($0 as AnyObject) === delegate }) { return } @@ -44,13 +44,13 @@ final class LKUserActionManager: NSObject { } @objc(sendAction:) - func send(_ type: LKUserActionType) { + func send(_ type: UserActionType) { guard type != .none else { assertionFailure("sendAction: needs an action") return } - for case let delegate as LKUserActionManagerDelegate in delegates.allObjects - where delegate.responds(to: #selector(LKUserActionManagerDelegate.lkUserActionManager(_:didAct:))) + for case let delegate as UserActionManagerDelegate in delegates.allObjects + where delegate.responds(to: #selector(UserActionManagerDelegate.lkUserActionManager(_:didAct:))) { delegate.lkUserActionManager(self, didAct: type) } diff --git a/LookInside/Base/LKWindowController.swift b/LookInside/Base/WindowController.swift similarity index 66% rename from LookInside/Base/LKWindowController.swift rename to LookInside/Base/WindowController.swift index 405f62da..d9f824a8 100644 --- a/LookInside/Base/LKWindowController.swift +++ b/LookInside/Base/WindowController.swift @@ -1,5 +1,5 @@ // -// LKWindowController.swift +// WindowController.swift // Lookin // // Created by Li Kai on 2019/4/18. @@ -9,7 +9,7 @@ import AppKit @objc(LKWindowController) -class LKWindowController: NSWindowController, LKAppMenuManagerDelegate { +class WindowController: NSWindowController, AppMenuManagerDelegate { deinit { NSLog("%@ dealloc", NSStringFromClass(type(of: self))) } diff --git a/LookInside/Common/Installer/LKInstallerArchiveExtractor.swift b/LookInside/Common/Installer/InstallerArchiveExtractor.swift similarity index 93% rename from LookInside/Common/Installer/LKInstallerArchiveExtractor.swift rename to LookInside/Common/Installer/InstallerArchiveExtractor.swift index 1f9b29cb..2c2c4b89 100644 --- a/LookInside/Common/Installer/LKInstallerArchiveExtractor.swift +++ b/LookInside/Common/Installer/InstallerArchiveExtractor.swift @@ -1,10 +1,10 @@ import Foundation -enum LKInstallerArchiveExtractor { +enum InstallerArchiveExtractor { static func unzip( _ zipURL: URL, into destination: URL, - cancellation: LKInstallerCancellation, + cancellation: InstallerCancellation, errorBuilder: (String) -> Error ) throws { try cancellation.checkCancellation() diff --git a/LookInside/Common/Installer/LKInstallerCancellation.swift b/LookInside/Common/Installer/InstallerCancellation.swift similarity index 90% rename from LookInside/Common/Installer/LKInstallerCancellation.swift rename to LookInside/Common/Installer/InstallerCancellation.swift index d56a70b3..92963d3a 100644 --- a/LookInside/Common/Installer/LKInstallerCancellation.swift +++ b/LookInside/Common/Installer/InstallerCancellation.swift @@ -1,12 +1,12 @@ import Foundation -struct LKInstallerCancelled: Error, LocalizedError { +struct InstallerCancelled: Error, LocalizedError { var errorDescription: String? { NSLocalizedString("Installation was cancelled.", comment: "") } } -final class LKInstallerCancellation { +final class InstallerCancellation { private let lock = NSLock() private var cancelled = false private weak var downloadTask: URLSessionDownloadTask? @@ -53,7 +53,7 @@ final class LKInstallerCancellation { func checkCancellation() throws { if isCancelled { - throw LKInstallerCancelled() + throw InstallerCancelled() } } } diff --git a/LookInside/Common/Installer/LKInstallerCodeSignature.swift b/LookInside/Common/Installer/InstallerCodeSignature.swift similarity index 96% rename from LookInside/Common/Installer/LKInstallerCodeSignature.swift rename to LookInside/Common/Installer/InstallerCodeSignature.swift index 58b0becb..12151797 100644 --- a/LookInside/Common/Installer/LKInstallerCodeSignature.swift +++ b/LookInside/Common/Installer/InstallerCodeSignature.swift @@ -1,7 +1,7 @@ import Foundation import Security -enum LKInstallerCodeSignature { +enum InstallerCodeSignature { struct TeamIdentifierMismatch: LocalizedError { let expected: String let found: String @@ -72,7 +72,7 @@ enum LKInstallerCodeSignature { ) throws { let hostTeamID = try? teamIdentifier(atPath: Bundle.main.bundlePath) guard let hostTeamID, hostTeamID.isEmpty == false else { - LKInstallerLogger.installer.info( + InstallerLogger.installer.info( "verifyTeamIdentifierMatchesHost: host has no team identifier (dev build); skipping target team check at \(targetURL.path, privacy: .public)" ) return @@ -87,7 +87,7 @@ enum LKInstallerCodeSignature { guard hostTeamID == targetTeamID else { throw mismatchErrorBuilder(hostTeamID, targetTeamID) } - LKInstallerLogger.installer.info( + InstallerLogger.installer.info( "verifyTeamIdentifierMatchesHost: host=\(hostTeamID, privacy: .public) matches target at \(targetURL.path, privacy: .public)" ) } diff --git a/LookInside/Common/Installer/LKInstallerDownloader.swift b/LookInside/Common/Installer/InstallerDownloader.swift similarity index 83% rename from LookInside/Common/Installer/LKInstallerDownloader.swift rename to LookInside/Common/Installer/InstallerDownloader.swift index 22d2dc11..c7bdfafc 100644 --- a/LookInside/Common/Installer/LKInstallerDownloader.swift +++ b/LookInside/Common/Installer/InstallerDownloader.swift @@ -1,16 +1,16 @@ import Foundation -enum LKInstallerDownloader { +enum InstallerDownloader { static func download( from url: URL, to destination: URL, - cancellation: LKInstallerCancellation, + cancellation: InstallerCancellation, timeout: TimeInterval = 30, errorBuilder: @escaping (String) -> Error ) throws { try cancellation.checkCancellation() - LKInstallerLogger.installer.info( + InstallerLogger.installer.info( "downloader: start url=\(url.absoluteString, privacy: .public) timeout=\(timeout)" ) @@ -25,19 +25,19 @@ enum LKInstallerDownloader { let task = URLSession.shared.downloadTask(with: request) { tempURL, response, error in defer { semaphore.signal() } let status = (response as? HTTPURLResponse)?.statusCode ?? -1 - LKInstallerLogger.installer.info( + InstallerLogger.installer.info( "downloader: completion status=\(status) error=\(error?.localizedDescription ?? "nil", privacy: .public)" ) if let error { if cancellation.isCancelled || (error as NSError).code == NSURLErrorCancelled { - capturedError = LKInstallerCancelled() + capturedError = InstallerCancelled() } else { capturedError = errorBuilder(error.localizedDescription) } return } guard cancellation.isCancelled == false else { - capturedError = LKInstallerCancelled() + capturedError = InstallerCancelled() return } guard let httpResponse = response as? HTTPURLResponse else { @@ -58,7 +58,7 @@ enum LKInstallerDownloader { } try FileManager.default.moveItem(at: tempURL, to: destination) let movedSize = (try? FileManager.default.attributesOfItem(atPath: destination.path)[.size] as? Int) ?? -1 - LKInstallerLogger.installer.info("downloader: moved to destination bytes=\(movedSize)") + InstallerLogger.installer.info("downloader: moved to destination bytes=\(movedSize)") downloadedToDestination = true } catch { capturedError = errorBuilder(error.localizedDescription) @@ -66,14 +66,14 @@ enum LKInstallerDownloader { } cancellation.register(downloadTask: task) task.resume() - LKInstallerLogger.installer.info("downloader: task.resume() called, waiting on semaphore") + InstallerLogger.installer.info("downloader: task.resume() called, waiting on semaphore") semaphore.wait() - LKInstallerLogger.installer.info("downloader: semaphore released") + InstallerLogger.installer.info("downloader: semaphore released") cancellation.register(downloadTask: nil) try cancellation.checkCancellation() if let capturedError { - LKInstallerLogger.installer.error( + InstallerLogger.installer.error( "downloader: throwing error=\(capturedError.localizedDescription, privacy: .public)" ) throw capturedError diff --git a/LookInside/Common/Installer/LKInstallerFilesystem.swift b/LookInside/Common/Installer/InstallerFilesystem.swift similarity index 96% rename from LookInside/Common/Installer/LKInstallerFilesystem.swift rename to LookInside/Common/Installer/InstallerFilesystem.swift index db8e7549..6957cf12 100644 --- a/LookInside/Common/Installer/LKInstallerFilesystem.swift +++ b/LookInside/Common/Installer/InstallerFilesystem.swift @@ -1,6 +1,6 @@ import Foundation -enum LKInstallerFilesystem { +enum InstallerFilesystem { /// Ensures the executable bit is set on `url`. No-op if already executable. static func ensureExecutableBit(at url: URL, errorBuilder: (String) -> Error) throws { let fileManager = FileManager.default diff --git a/LookInside/Common/Installer/LKInstallerLogger.swift b/LookInside/Common/Installer/InstallerLogger.swift similarity index 92% rename from LookInside/Common/Installer/LKInstallerLogger.swift rename to LookInside/Common/Installer/InstallerLogger.swift index 7ab5be76..13e3b807 100644 --- a/LookInside/Common/Installer/LKInstallerLogger.swift +++ b/LookInside/Common/Installer/InstallerLogger.swift @@ -1,7 +1,7 @@ import Foundation import os -enum LKInstallerLogger { +enum InstallerLogger { static let installer = Logger(subsystem: subsystem, category: "Installer") private static let subsystem = "com.lookinside.app" diff --git a/LookInside/Common/Installer/LKInstallerProgressWindowController.swift b/LookInside/Common/Installer/InstallerProgressWindowController.swift similarity index 97% rename from LookInside/Common/Installer/LKInstallerProgressWindowController.swift rename to LookInside/Common/Installer/InstallerProgressWindowController.swift index 1d468c1f..36c39e54 100644 --- a/LookInside/Common/Installer/LKInstallerProgressWindowController.swift +++ b/LookInside/Common/Installer/InstallerProgressWindowController.swift @@ -1,6 +1,6 @@ import AppKit -final class LKInstallerProgressWindowController: NSWindowController, NSWindowDelegate { +final class InstallerProgressWindowController: NSWindowController, NSWindowDelegate { private let titleLabel = NSTextField(labelWithString: "") private let statusLabel = NSTextField(labelWithString: "") private let progressIndicator = NSProgressIndicator() diff --git a/LookInside/Connection/LKAppsManager.swift b/LookInside/Connection/AppsManager.swift similarity index 88% rename from LookInside/Connection/LKAppsManager.swift rename to LookInside/Connection/AppsManager.swift index 5467b263..0464c2ff 100644 --- a/LookInside/Connection/LKAppsManager.swift +++ b/LookInside/Connection/AppsManager.swift @@ -1,12 +1,12 @@ // -// LKAppsManager.swift +// AppsManager.swift // LookInside // // Created by Li Kai on 2018/11/3. // https://lookin.work // // Finds the apps the Host can inspect. It keeps no state: each live -// document follows its own app across reconnects (LookinLiveDocument). +// document follows its own app across reconnects (LiveDocument). // import Foundation @@ -14,9 +14,9 @@ import LookInsideHostCore @objc(LKAppsManager) @MainActor -final class LKAppsManager: NSObject { +final class AppsManager: NSObject { @objc(sharedInstance) - static let shared = LKAppsManager() + static let shared = AppsManager() override private init() { super.init() @@ -35,12 +35,12 @@ final class LKAppsManager: NSObject { /// `serverVersionError` and no channel. Apps in the background, which /// cannot answer, and apps that require a license for app info are left /// out. - func fetchAppInfos(needImages: Bool, localInfos: [InspectedAppInfo]?) async -> [LKInspectableApp] { + func fetchAppInfos(needImages: Bool, localInfos: [InspectedAppInfo]?) async -> [InspectableApp] { await scanApps(needImages: needImages, localInfos: localInfos).apps } /// `fetchAppInfos` plus how many channels were connected. - func scanApps(needImages: Bool, localInfos: [InspectedAppInfo]?) async -> (apps: [LKInspectableApp], channelCount: Int) { + func scanApps(needImages: Bool, localInfos: [InspectedAppInfo]?) async -> (apps: [InspectableApp], channelCount: Int) { let now = Date().timeIntervalSince1970 let validAppInfos = (localInfos ?? []).filter { AppInfoCachePolicy.isFresh(cachedTimestamp: $0.cachedTimestamp, now: now) @@ -51,7 +51,7 @@ final class LKAppsManager: NSObject { forKeys: ["needImages" as NSString, "local" as NSString] ) - let channels = await LKConnectionManager.shared.connectAllPorts() + let channels = await ConnectionManager.shared.connectAllPorts() guard !channels.isEmpty else { return ([], 0) } @@ -71,7 +71,7 @@ final class LKAppsManager: NSObject { /// Sends the app info request on every channel at once, in channel /// order, and waits for all of them. - private func requestAppInfos(parameters: NSDictionary, channels: [LKChannel]) async -> [AppInfoOutcome] { + private func requestAppInfos(parameters: NSDictionary, channels: [ServerChannel]) async -> [AppInfoOutcome] { await withCheckedContinuation { continuation in var outcomes = [AppInfoOutcome](repeating: .none, count: channels.count) var remaining = channels.count @@ -86,7 +86,7 @@ final class LKAppsManager: NSObject { continuation.resume(returning: outcomes) } } - let sink = LKResponseSink { event in + let sink = ResponseSink { event in switch event { case let .response(attachment): settle(.response(attachment)) @@ -102,7 +102,7 @@ final class LKAppsManager: NSObject { settle(.none) } } - LKConnectionManager.shared.request( + ConnectionManager.shared.request( type: UInt32(LookinRequestTypeApp), data: parameters, channel: channel, @@ -112,12 +112,12 @@ final class LKAppsManager: NSObject { } } - private func makeApp(from outcome: AppInfoOutcome, channel: LKChannel, validAppInfos: [InspectedAppInfo]) -> LKInspectableApp? { + private func makeApp(from outcome: AppInfoOutcome, channel: ServerChannel, validAppInfos: [InspectedAppInfo]) -> InspectableApp? { switch outcome { case .none: return nil case let .versionError(error): - let app = LKInspectableApp() + let app = InspectableApp() app.serverVersionError = error return app case let .response(response): @@ -131,7 +131,7 @@ final class LKAppsManager: NSObject { if error.code == LookinErrCode_LicenseRequired { return nil } - let app = LKInspectableApp() + let app = InspectableApp() app.serverVersionError = error app.channel = channel return app @@ -144,7 +144,7 @@ final class LKAppsManager: NSObject { // The Server's info did not change; keep the one with images. receivedInfo = localInfo } - let app = LKInspectableApp() + let app = InspectableApp() app.appInfo = receivedInfo app.channel = channel return app diff --git a/LookInside/Connection/LKConnectionManager+License.swift b/LookInside/Connection/ConnectionManager+License.swift similarity index 85% rename from LookInside/Connection/LKConnectionManager+License.swift rename to LookInside/Connection/ConnectionManager+License.swift index 53f11ca4..4cee48e8 100644 --- a/LookInside/Connection/LKConnectionManager+License.swift +++ b/LookInside/Connection/ConnectionManager+License.swift @@ -1,5 +1,5 @@ // -// LKConnectionManager+License.swift +// ConnectionManager+License.swift // LookInside // // The 220 LicenseChallenge / 221 LicenseVerify handshake that unlocks the @@ -10,20 +10,20 @@ import Foundation import LookInsideHostCore -extension LKConnectionManager { +extension ConnectionManager { /// Makes sure the license handshake has run on `channel`, then calls /// `completion` with whether the channel is licensed. Concurrent callers /// share one handshake. /// /// - Parameter force: run a new handshake even when the channel is /// already licensed (the activation changed). - func ensureLicenseHandshake(on channel: LKChannel?, force: Bool, completion: ((Bool) -> Void)?) { + func ensureLicenseHandshake(on channel: ServerChannel?, force: Bool, completion: ((Bool) -> Void)?) { guard let channel, channel.isConnected else { completion?(false) return } let state = channel.connectionState - let gatekeeper = LKSwiftUISupportGatekeeper.sharedInstance() + let gatekeeper = SwiftUISupportGatekeeper.sharedInstance() let admission = state.licenseHandshake.admit( force: force, isActivated: gatekeeper.activationState == .activated, @@ -41,10 +41,10 @@ extension LKConnectionManager { } state.licenseHandshake.markStarted() - let environment = LKChannelLicenseEnvironment(channel: channel, manager: self) + let environment = ServerChannelLicenseEnvironment(channel: channel, manager: self) LicenseHandshakeFlow.run(in: environment, channelDescription: String(format: "%p", channel)) { failure in if let failure { - let error = LKConnectionError.licenseHandshakeError(failure) + let error = ConnectionError.licenseHandshakeError(failure) NSLog( "LookinClient - license handshake failed, domain:%@, code:%@, description:%@", error.domain, @@ -63,7 +63,7 @@ extension LKConnectionManager { /// runs a new handshake. func handleActivationStateDidChange() { let channels = connectedChannels() - guard LKSwiftUISupportGatekeeper.sharedInstance().activationState == .activated else { + guard SwiftUISupportGatekeeper.sharedInstance().activationState == .activated else { for channel in channels { channel.connectionState.licenseHandshake.revokeVerification() } @@ -82,7 +82,7 @@ extension LKConnectionManager { /// channel that is not licensed tries once, through the policy; channels /// that are already licensed are left alone. func handleLicenseHandshakeAvailabilityDidChange() { - guard LKSwiftUISupportGatekeeper.sharedInstance().activationState == .activated else { return } + guard SwiftUISupportGatekeeper.sharedInstance().activationState == .activated else { return } for channel in connectedChannels() { ensureLicenseHandshake(on: channel, force: false) { verified in NSLog("LookinClient - resumed license handshake finished, verified:%@", NSNumber(value: verified)) @@ -95,17 +95,17 @@ extension LKConnectionManager { /// frames through the connection manager, and the activation runtime's /// signing policy and license key through the gatekeeper. @MainActor -private final class LKChannelLicenseEnvironment: LicenseHandshakeEnvironment { - private let channel: LKChannel - private let manager: LKConnectionManager +private final class ServerChannelLicenseEnvironment: LicenseHandshakeEnvironment { + private let channel: ServerChannel + private let manager: ConnectionManager private let channelID: String private let timeoutInterval: TimeInterval - init(channel: LKChannel, manager: LKConnectionManager) { + init(channel: ServerChannel, manager: ConnectionManager) { self.channel = channel self.manager = manager channelID = channel.connectionState.licenseChannelID - timeoutInterval = LKPreferenceManager.shared.licenseHandshakeTimeoutInterval + timeoutInterval = PreferenceManager.shared.licenseHandshakeTimeoutInterval } var isChannelConnected: Bool { @@ -117,11 +117,11 @@ private final class LKChannelLicenseEnvironment: LicenseHandshakeEnvironment { } func shouldStartHandshake() -> Bool { - LKSwiftUISupportGatekeeper.sharedInstance().shouldStartLicenseHandshake(onChannel: channelID) + SwiftUISupportGatekeeper.sharedInstance().shouldStartLicenseHandshake(onChannel: channelID) } func noteHandshakeFailed() { - LKSwiftUISupportGatekeeper.sharedInstance().noteLicenseHandshakeFailed(onChannel: channelID) + SwiftUISupportGatekeeper.sharedInstance().noteLicenseHandshakeFailed(onChannel: channelID) } func sendChallenge(completion: @escaping (LicenseExchangeResult) -> Void) { @@ -158,7 +158,7 @@ private final class LKChannelLicenseEnvironment: LicenseHandshakeEnvironment { /// possibly behind a prompt, so it runs off the main thread. func sign(_ challenge: LicenseChallenge, completion: @escaping (LicenseSigning) -> Void) { let channelID = channelID - let signed = LKMainThreadCallback(completion) + let signed = MainThreadCallback(completion) DispatchQueue.global(qos: .userInitiated).async { let signing = Self.signChallenge(challenge, channelID: channelID) DispatchQueue.main.async { @@ -170,7 +170,7 @@ private final class LKChannelLicenseEnvironment: LicenseHandshakeEnvironment { } func noteServerRelease(_ release: ServerRelease) { - LKServerUpgradeHint.noteRelease(release, on: channel) + ServerUpgradeHint.noteRelease(release, on: channel) } func log(_ message: String) { @@ -178,7 +178,7 @@ private final class LKChannelLicenseEnvironment: LicenseHandshakeEnvironment { } private func send(type: UInt32, data: NSObject?, completion: @escaping (LicenseExchangeResult) -> Void) { - let sink = LKResponseSink { event in + let sink = ResponseSink { event in switch event { case let .response(attachment): completion(.response(error: attachment?.error as NSError?, payload: attachment?.data)) @@ -198,7 +198,7 @@ private final class LKChannelLicenseEnvironment: LicenseHandshakeEnvironment { var keyUseDuration: TimeInterval = 0 var failureDescription: String? do { - try LKSwiftUISupportGatekeeper.sharedInstance().signChallenge( + try SwiftUISupportGatekeeper.sharedInstance().signChallenge( nonce: challenge.nonce, serverInstanceID: challenge.serverInstanceID, channelID: channelID, @@ -224,7 +224,7 @@ private final class LKChannelLicenseEnvironment: LicenseHandshakeEnvironment { /// Carries a main-actor callback through a background hop. @MainActor -private final class LKMainThreadCallback { +private final class MainThreadCallback { let callback: (Value) -> Void init(_ callback: @escaping (Value) -> Void) { diff --git a/LookInside/Connection/LKConnectionManager.swift b/LookInside/Connection/ConnectionManager.swift similarity index 82% rename from LookInside/Connection/LKConnectionManager.swift rename to LookInside/Connection/ConnectionManager.swift index a7fe2f06..c42b4b30 100644 --- a/LookInside/Connection/LKConnectionManager.swift +++ b/LookInside/Connection/ConnectionManager.swift @@ -1,5 +1,5 @@ // -// LKConnectionManager.swift +// ConnectionManager.swift // LookInside // // Created by Li Kai on 2018/11/2. @@ -25,17 +25,17 @@ import AppKit import LookInsideHostCore /// A push frame the Server sent without a request. -struct LKConnectionPush { - let channel: LKChannel +struct ConnectionPush { + let channel: ServerChannel let type: UInt32 let data: Any? } /// Connection state the manager keeps for one channel. @MainActor -final class LKChannelConnectionState { +final class ServerChannelConnectionState { /// Requests sent on this channel whose responses have not all arrived. - var activeRequests: [LKConnectionRequest] = [] + var activeRequests: [ConnectionRequest] = [] let licenseHandshake = LicenseHandshakeGate() /// Identifies this channel to the activation runtime's signing policy, /// which remembers a failed handshake per channel. @@ -44,23 +44,23 @@ final class LKChannelConnectionState { /// the first handshake. Drives the upgrade hint only. var serverRelease: ServerRelease? - func activeRequest(type: UInt32, tag: UInt32) -> LKConnectionRequest? { + func activeRequest(type: UInt32, tag: UInt32) -> ConnectionRequest? { activeRequests.first { $0.type == type && $0.tag == tag } } - func remove(_ request: LKConnectionRequest) { + func remove(_ request: ConnectionRequest) { activeRequests.removeAll { $0 === request } } } /// One port the Host tries, and the channel connected on it. @MainActor -private final class LKConnectionPort { +private final class ConnectionPort { let number: Int32 - let kind: LKChannelKind - var connectedChannel: LKChannel? + let kind: ServerChannelKind + var connectedChannel: ServerChannel? - init(number: Int32, kind: LKChannelKind) { + init(number: Int32, kind: ServerChannelKind) { self.number = number self.kind = kind } @@ -68,17 +68,17 @@ private final class LKConnectionPort { @objc(LKConnectionManager) @MainActor -final class LKConnectionManager: NSObject { +final class ConnectionManager: NSObject { @objc(sharedInstance) - static let shared = LKConnectionManager() + static let shared = ConnectionManager() - private let simulatorPorts: [LKConnectionPort] - private let macPorts: [LKConnectionPort] - private var usbPorts: [LKConnectionPort] = [] + private let simulatorPorts: [ConnectionPort] + private let macPorts: [ConnectionPort] + private var usbPorts: [ConnectionPort] = [] private let usbMuxClient = USBMuxClient(queue: .main) - private let channelWillEndBroadcaster = AsyncBroadcaster() - private let pushBroadcaster = AsyncBroadcaster() + private let channelWillEndBroadcaster = AsyncBroadcaster() + private let pushBroadcaster = AsyncBroadcaster() /// Totals for the log line of a large multi-frame response. private var receivedResponseBytes = 0 @@ -86,24 +86,24 @@ final class LKConnectionManager: NSObject { override private init() { simulatorPorts = (Int32(LookinSimulatorIPv4PortNumberStart) ... Int32(LookinSimulatorIPv4PortNumberEnd)).map { - LKConnectionPort(number: $0, kind: .simulator) + ConnectionPort(number: $0, kind: .simulator) } macPorts = (Int32(LookinMacIPv4PortNumberStart) ... Int32(LookinMacIPv4PortNumberEnd)).map { - LKConnectionPort(number: $0, kind: .mac) + ConnectionPort(number: $0, kind: .mac) } super.init() startListeningForUSBDevices() let center = NotificationCenter.default center.addObserver( - forName: LKSwiftUISupportGatekeeper.activationStateDidChangeNotification, + forName: SwiftUISupportGatekeeper.activationStateDidChangeNotification, object: nil, queue: nil ) { [weak self] _ in lkRunOnMain { self?.handleActivationStateDidChange() } } center.addObserver( - forName: LKSwiftUISupportGatekeeper.licenseHandshakeAvailabilityDidChangeNotification, + forName: SwiftUISupportGatekeeper.licenseHandshakeAvailabilityDidChangeNotification, object: nil, queue: .main ) { [weak self] _ in @@ -115,12 +115,12 @@ final class LKConnectionManager: NSObject { /// Channels that ended (the app was killed, the USB cable unplugged, or /// the Host closed the channel), delivered once the socket is closed. - func channelWillEndEvents() -> AsyncStream { + func channelWillEndEvents() -> AsyncStream { channelWillEndBroadcaster.subscribe() } /// Push frames from the Server. - func pushEvents() -> AsyncStream { + func pushEvents() -> AsyncStream { pushBroadcaster.subscribe() } @@ -130,7 +130,7 @@ final class LKConnectionManager: NSObject { /// channels: Simulator ports first, then Mac ports, then USB ports. A /// channel can be connected although its app is in the background and /// cannot answer. - func connectAllPorts() async -> [LKChannel] { + func connectAllPorts() async -> [ServerChannel] { await withCheckedContinuation { continuation in connectAllPorts { continuation.resume(returning: $0) } } @@ -138,9 +138,9 @@ final class LKConnectionManager: NSObject { /// Callback form of `connectAllPorts()`. A TCP connect finishes before /// it returns, so with no USB device the completion runs synchronously. - func connectAllPorts(completion: @escaping ([LKChannel]) -> Void) { + func connectAllPorts(completion: @escaping ([ServerChannel]) -> Void) { let ports = simulatorPorts + macPorts + usbPorts - var channels = [LKChannel?](repeating: nil, count: ports.count) + var channels = [ServerChannel?](repeating: nil, count: ports.count) var remaining = ports.count guard remaining > 0 else { completion([]) @@ -157,7 +157,7 @@ final class LKConnectionManager: NSObject { } } - private func connect(_ port: LKConnectionPort, completion: @escaping (LKChannel?) -> Void) { + private func connect(_ port: ConnectionPort, completion: @escaping (ServerChannel?) -> Void) { if let connected = port.connectedChannel { completion(connected) return @@ -192,8 +192,8 @@ final class LKConnectionManager: NSObject { } } - private func attachChannel(fileDescriptor: Int32, initialBytes: Data, to port: LKConnectionPort) -> LKChannel { - let channel = LKChannel( + private func attachChannel(fileDescriptor: Int32, initialBytes: Data, to port: ConnectionPort) -> ServerChannel { + let channel = ServerChannel( fileDescriptor: fileDescriptor, initialBytes: initialBytes, port: port.number, @@ -204,7 +204,7 @@ final class LKConnectionManager: NSObject { return channel } - func connectedChannels() -> [LKChannel] { + func connectedChannels() -> [ServerChannel] { (simulatorPorts + macPorts + usbPorts).compactMap { port in guard let channel = port.connectedChannel, channel.isConnected else { return nil } return channel @@ -221,7 +221,7 @@ final class LKConnectionManager: NSObject { case let .attached(deviceID, _): // Each device has its own port range; see the file comment. for number in Int32(LookinUSBDeviceIPv4PortNumberStart) ... Int32(LookinUSBDeviceIPv4PortNumberEnd) { - self.usbPorts.append(LKConnectionPort(number: number, kind: .usb(deviceID: deviceID))) + self.usbPorts.append(ConnectionPort(number: number, kind: .usb(deviceID: deviceID))) } NSLog("Lookin - USB device attached, DeviceID: %@", NSNumber(value: deviceID)) case let .detached(deviceID): @@ -241,7 +241,7 @@ final class LKConnectionManager: NSObject { /// Sends a push frame, which the Server does not answer. The Server may /// miss it while its app is in the background or stopped at a breakpoint. - func push(type: UInt32, data: NSObject?, channel: LKChannel?) { + func push(type: UInt32, data: NSObject?, channel: ServerChannel?) { guard let channel, channel.isConnected else { return } let payload = archivedPayload(rootObject: data) NSLog("LookinClient - pushData, type:%@", NSNumber(value: type)) @@ -254,12 +254,12 @@ final class LKConnectionManager: NSObject { /// /// An older request of the same type still waiting on this channel fails /// with `LookinErrCode_Discard` when this one is sent. - func request(type: UInt32, data: NSObject?, channel: LKChannel, sink: LKResponseSink) { + func request(type: UInt32, data: NSObject?, channel: ServerChannel, sink: ResponseSink) { // An app in the background keeps its channel but cannot answer; a // long ping timeout would hold up the launch window's app list. let pingTimeout: TimeInterval = type == UInt32(LookinRequestTypeApp) ? 0.5 : 2 - let pingSink = LKResponseSink { [weak self] event in + let pingSink = ResponseSink { [weak self] event in guard let self else { return } switch event { case let .response(pingResponse): @@ -294,7 +294,7 @@ final class LKConnectionManager: NSObject { /// Ends the waiting request of `type` on `channel` and reports it as /// completed. - func cancelRequest(type: UInt32, channel: LKChannel?) { + func cancelRequest(type: UInt32, channel: ServerChannel?) { guard let state = channel?.connectionState, let request = state.activeRequests.first(where: { $0.type == type }) else { @@ -310,15 +310,15 @@ final class LKConnectionManager: NSObject { /// throws the transport error or, for a frame that cannot be decoded, /// `LookinErr_Inner`. Cancelling the consuming task stops the delivery; /// the request on the channel runs to its end or its timeout. - func responses(type: UInt32, data: NSObject?, channel: LKChannel) -> AsyncThrowingStream { + func responses(type: UInt32, data: NSObject?, channel: ServerChannel) -> AsyncThrowingStream { AsyncThrowingStream { continuation in - let sink = LKResponseSink { event in + let sink = ResponseSink { event in switch event { case let .response(attachment): if let attachment { continuation.yield(attachment) } else { - continuation.finish(throwing: LKConnectionError.inner) + continuation.finish(throwing: ConnectionError.inner) } case let .failure(error): continuation.finish(throwing: error) @@ -334,11 +334,11 @@ final class LKConnectionManager: NSObject { } /// The first response of a request that answers once. - func request(type: UInt32, data: NSObject?, channel: LKChannel) async throws -> ConnectionResponseAttachment { + func request(type: UInt32, data: NSObject?, channel: ServerChannel) async throws -> ConnectionResponseAttachment { for try await attachment in responses(type: type, data: data, channel: channel) { return attachment } - throw LKConnectionError.inner + throw ConnectionError.inner } // MARK: - Request policy @@ -356,7 +356,7 @@ final class LKConnectionManager: NSObject { static func timeoutInterval(forRequestType type: UInt32) -> TimeInterval { switch Int(type) { case LookinRequestTypeHierarchy, LookinRequestTypeHierarchyDetails: - LKPreferenceManager.shared.hierarchyRequestTimeoutInterval + PreferenceManager.shared.hierarchyRequestTimeoutInterval default: 5 } @@ -369,9 +369,9 @@ final class LKConnectionManager: NSObject { case .compatible: return nil case .serverTooOld: - return LKConnectionError.serverVersionTooLow + return ConnectionError.serverVersionTooLow case .serverTooNew: - return LKConnectionError.serverVersionTooHigh + return ConnectionError.serverVersionTooHigh } } @@ -405,9 +405,9 @@ final class LKConnectionManager: NSObject { /// Sends one frame and tracks it until its last response, a failure or /// its timeout. - func sendFrame(type: UInt32, channel: LKChannel, data: NSObject?, timeoutInterval: TimeInterval, sink: LKResponseSink) { + func sendFrame(type: UInt32, channel: ServerChannel, data: NSObject?, timeoutInterval: TimeInterval, sink: ResponseSink) { guard channel.isConnected else { - sink.send(.failure(LKConnectionError.noConnect)) + sink.send(.failure(ConnectionError.noConnect)) return } let state = channel.connectionState @@ -415,7 +415,7 @@ final class LKConnectionManager: NSObject { // A newer request replaces an older one of the same type, which // fails. for discarded in state.activeRequests where discarded.type == type { - discarded.sink.send(.failure(LKConnectionError.discarded)) + discarded.sink.send(.failure(ConnectionError.discarded)) discarded.endTimeoutCount() state.remove(discarded) NSLog("LookinClient - will discard request, type:%@, tag:%@", NSNumber(value: discarded.type), NSNumber(value: discarded.tag)) @@ -423,8 +423,8 @@ final class LKConnectionManager: NSObject { } let tag = UInt32(truncatingIfNeeded: Int64(Date().timeIntervalSince1970)) - let request = LKConnectionRequest(type: type, tag: tag, timeoutInterval: timeoutInterval, sink: sink) { [weak channel] request in - request.sink.send(.failure(LKConnectionError.timeout)) + let request = ConnectionRequest(type: type, tag: tag, timeoutInterval: timeoutInterval, sink: sink) { [weak channel] request in + request.sink.send(.failure(ConnectionError.timeout)) channel?.connectionState.remove(request) } @@ -441,7 +441,7 @@ final class LKConnectionManager: NSObject { guard error != nil, state.activeRequests.contains(where: { $0 === request }) else { return } request.endTimeoutCount() state.remove(request) - sink.send(.failure(LKConnectionError.transport)) + sink.send(.failure(ConnectionError.transport)) } } @@ -452,7 +452,7 @@ final class LKConnectionManager: NSObject { UInt32(LookinPush_GestureDebug), ] - private func shouldAcceptFrame(on channel: LKChannel, type: UInt32, tag: UInt32) -> Bool { + private func shouldAcceptFrame(on channel: ServerChannel, type: UInt32, tag: UInt32) -> Bool { if Self.pushFrameTypes.contains(type) { return true } @@ -463,13 +463,13 @@ final class LKConnectionManager: NSObject { return false } - private func didReceiveFrame(on channel: LKChannel, type: UInt32, tag: UInt32, data: Data) { + private func didReceiveFrame(on channel: ServerChannel, type: UInt32, tag: UInt32, data: Data) { if Self.pushFrameTypes.contains(type) { let unarchived = try? NSKeyedUnarchiver.unarchivedObject( ofClasses: [NSString.self, NSDictionary.self, NSArray.self, NSNumber.self, NSData.self, NSNull.self], from: data ) - pushBroadcaster.yield(LKConnectionPush(channel: channel, type: type, data: unarchived)) + pushBroadcaster.yield(ConnectionPush(channel: channel, type: type, data: unarchived)) handlePush(type: type, data: unarchived, channel: channel) return } @@ -491,7 +491,7 @@ final class LKConnectionManager: NSObject { if attachment?.appIsInBackground == true { request.endTimeoutCount() state.remove(request) - request.sink.send(.failure(LKConnectionError.appInBackground)) + request.sink.send(.failure(ConnectionError.appInBackground)) NSLog("Lookin - the iOS app reported that it is in the background; request failed") return } @@ -539,42 +539,42 @@ final class LKConnectionManager: NSObject { return unarchiver.decodeObject(forKey: NSKeyedArchiveRootObjectKey) as? ConnectionResponseAttachment } - private func handlePush(type: UInt32, data: Any?, channel: LKChannel) { + private func handlePush(type: UInt32, data: Any?, channel: ServerChannel) { guard type == UInt32(LookinPush_SwiftUISupportDetected) else { return } NSLog("LookinClient - received SwiftUI support detection push from channel:%@ data:%@", channel, data.map { String(describing: $0) } ?? "(null)") DispatchQueue.main.async { - let gatekeeper = LKSwiftUISupportGatekeeper.sharedInstance() + let gatekeeper = SwiftUISupportGatekeeper.sharedInstance() gatekeeper.noteDetectedSwiftUISupport() let keyWindow = NSApplication.shared.keyWindow - let launchWindow = LKNavigationManager.shared.launchWindowController?.window + let launchWindow = NavigationManager.shared.launchWindowController?.window if let keyWindow, keyWindow !== launchWindow { gatekeeper.promptForPendingDetectedSwiftUISupportIfNeeded(window: keyWindow) } } } - private func endChannel(_ channel: LKChannel) { + private func endChannel(_ channel: ServerChannel) { for port in simulatorPorts + macPorts + usbPorts where port.connectedChannel === channel { port.connectedChannel = nil } channelWillEndBroadcaster.yield(channel) - LKSwiftUISupportGatekeeper.sharedInstance().licenseHandshakeChannelDidEnd(channel.connectionState.licenseChannelID) + SwiftUISupportGatekeeper.sharedInstance().licenseHandshakeChannelDidEnd(channel.connectionState.licenseChannelID) channel.close() } } -// MARK: - LKChannelDelegate +// MARK: - ServerChannelDelegate -extension LKConnectionManager: LKChannelDelegate { - func channel(_ channel: LKChannel, shouldAcceptFrameOfType type: UInt32, tag: UInt32) -> Bool { +extension ConnectionManager: ServerChannelDelegate { + func channel(_ channel: ServerChannel, shouldAcceptFrameOfType type: UInt32, tag: UInt32) -> Bool { shouldAcceptFrame(on: channel, type: type, tag: tag) } - func channel(_ channel: LKChannel, didReceiveFrameOfType type: UInt32, tag: UInt32, payload: Data) { + func channel(_ channel: ServerChannel, didReceiveFrameOfType type: UInt32, tag: UInt32, payload: Data) { didReceiveFrame(on: channel, type: type, tag: tag, data: payload) } - func channelDidEnd(_ channel: LKChannel) { + func channelDidEnd(_ channel: ServerChannel) { endChannel(channel) } } diff --git a/LookInside/Connection/LKConnectionRequest.swift b/LookInside/Connection/ConnectionRequest.swift similarity index 82% rename from LookInside/Connection/LKConnectionRequest.swift rename to LookInside/Connection/ConnectionRequest.swift index 3531edbf..0c7517be 100644 --- a/LookInside/Connection/LKConnectionRequest.swift +++ b/LookInside/Connection/ConnectionRequest.swift @@ -1,5 +1,5 @@ // -// LKConnectionRequest.swift +// ConnectionRequest.swift // LookInside // // One request the Host sent on a channel and has not heard the end of. @@ -10,7 +10,7 @@ import LookInsideHostCore /// What a request reports, in order: zero or more responses, then either a /// failure or a completion. -enum LKResponseEvent { +enum ResponseEvent { /// One response frame. `nil` when its payload could not be decoded. case response(ConnectionResponseAttachment?) case failure(NSError) @@ -21,10 +21,10 @@ enum LKResponseEvent { /// detached or a failure or completion ends it. Detaching stops the /// delivery only; the request itself runs to its end. @MainActor -final class LKResponseSink { - private var onEvent: ((LKResponseEvent) -> Void)? +final class ResponseSink { + private var onEvent: ((ResponseEvent) -> Void)? - init(_ onEvent: @escaping (LKResponseEvent) -> Void) { + init(_ onEvent: @escaping (ResponseEvent) -> Void) { self.onEvent = onEvent } @@ -32,7 +32,7 @@ final class LKResponseSink { onEvent == nil } - func send(_ event: LKResponseEvent) { + func send(_ event: ResponseEvent) { guard let onEvent else { return } switch event { case .response: @@ -52,22 +52,22 @@ final class LKResponseSink { /// `-performSelector:withObject:afterDelay:` like the Objective-C class it /// replaces, so it fires on the main run loop in the default mode only. @MainActor -final class LKConnectionRequest: NSObject { +final class ConnectionRequest: NSObject { let type: UInt32 let tag: UInt32 - let sink: LKResponseSink + let sink: ResponseSink var frameProgress = ResponseFrameProgress() /// Must be positive. private let timeoutInterval: TimeInterval - private let onTimeout: (LKConnectionRequest) -> Void + private let onTimeout: (ConnectionRequest) -> Void init( type: UInt32, tag: UInt32, timeoutInterval: TimeInterval, - sink: LKResponseSink, - onTimeout: @escaping (LKConnectionRequest) -> Void + sink: ResponseSink, + onTimeout: @escaping (ConnectionRequest) -> Void ) { self.type = type self.tag = tag diff --git a/LookInside/Connection/LKInspectableApp.swift b/LookInside/Connection/InspectableApp.swift similarity index 87% rename from LookInside/Connection/LKInspectableApp.swift rename to LookInside/Connection/InspectableApp.swift index a148587d..e7b845f9 100644 --- a/LookInside/Connection/LKInspectableApp.swift +++ b/LookInside/Connection/InspectableApp.swift @@ -1,5 +1,5 @@ // -// LKInspectableApp.swift +// InspectableApp.swift // LookInside // // Created by Li Kai on 2018/11/3. @@ -13,21 +13,21 @@ import Foundation /// What a request to the inspected app reports: zero or more values (the /// `data` of each response), then a failure or a completion. -enum LKAppResponseEvent { +enum AppResponseEvent { case value(Any?) case failure(NSError) case completion } @objc(LKInspectableApp) -final class LKInspectableApp: NSObject { +final class InspectableApp: NSObject { /// Set when the app's Server is too old or too new for this Host, or /// answered the app info request with another error. @objc dynamic var serverVersionError: NSError? @objc dynamic var appInfo: InspectedAppInfo? - @objc dynamic weak var channel: LKChannel? + @objc dynamic weak var channel: ServerChannel? // MARK: - Requests @@ -37,20 +37,20 @@ final class LKInspectableApp: NSObject { /// The returned sink stops the delivery when detached. @MainActor static func startRequest( - on channel: LKChannel, + on channel: ServerChannel, type: UInt32, data: NSObject?, transform: ((Any?) -> Any?)? = nil, - onEvent: @escaping (LKAppResponseEvent) -> Void - ) -> LKResponseSink { + onEvent: @escaping (AppResponseEvent) -> Void + ) -> ResponseSink { var hasEnded = false - let sink = LKResponseSink { event in + let sink = ResponseSink { event in guard !hasEnded else { return } switch event { case let .response(attachment): if let serverError = attachment?.error { hasEnded = true - onEvent(.failure(LKConnectionError.localized(serverError as NSError))) + onEvent(.failure(ConnectionError.localized(serverError as NSError))) } else { let value = attachment?.data onEvent(.value(transform.map { $0(value) } ?? value)) @@ -63,7 +63,7 @@ final class LKInspectableApp: NSObject { onEvent(.completion) } } - LKConnectionManager.shared.request(type: type, data: data, channel: channel, sink: sink) + ConnectionManager.shared.request(type: type, data: data, channel: channel, sink: sink) return sink } @@ -72,7 +72,7 @@ final class LKInspectableApp: NSObject { func responses(type: UInt32, data: NSObject?, transform: ((Any?) -> Any?)? = nil) -> AsyncThrowingStream { AsyncThrowingStream { continuation in guard let channel else { - continuation.finish(throwing: LKConnectionError.noConnect) + continuation.finish(throwing: ConnectionError.noConnect) return } let sink = Self.startRequest(on: channel, type: type, data: data, transform: transform) { event in @@ -101,7 +101,7 @@ final class LKInspectableApp: NSObject { do { for try await value in untyped { guard let typed = value as? Value else { - throw LKConnectionError.inner + throw ConnectionError.inner } continuation.yield(typed) } @@ -121,25 +121,25 @@ final class LKInspectableApp: NSObject { func response(type: UInt32, data: NSObject?, as _: Value.Type, transform: ((Any?) -> Any?)? = nil) async throws -> Value { for try await value in responses(type: type, data: data, transform: transform) { guard let typed = value as? Value else { - throw LKConnectionError.inner + throw ConnectionError.inner } return typed } - throw LKConnectionError.inner + throw ConnectionError.inner } /// Sends a push frame; nothing when the channel is gone. @MainActor func push(type: UInt32, data: NSObject?) { guard let channel else { return } - LKConnectionManager.shared.push(type: type, data: data, channel: channel) + ConnectionManager.shared.push(type: type, data: data, channel: channel) } /// Ends the waiting request of `type` and reports it as completed. @MainActor func cancelRequest(type: UInt32) { guard let channel else { return } - LKConnectionManager.shared.cancelRequest(type: type, channel: channel) + ConnectionManager.shared.cancelRequest(type: type, channel: channel) } // MARK: - Request payloads @@ -148,9 +148,9 @@ final class LKInspectableApp: NSObject { /// 1.0.4), the SwiftUI display mode, and whether to include backing /// layers (old Servers ignore the keys they do not know). static func hierarchyRequestParameters() -> NSDictionary { - let parameters = NSMutableDictionary(dictionary: ["clientVersion": LKHelper.lookinReadableVersion() as NSString]) - parameters[LookinParam_SwiftUIDisplayMode] = NSNumber(value: LKSwiftUIHierarchyDisplayModeStore.currentMode().rawValue) - parameters["showBackingLayers"] = NSNumber(value: LKPreferenceManager.shared.showBackingLayers.currentBOOLValue) + let parameters = NSMutableDictionary(dictionary: ["clientVersion": AppHelper.lookinReadableVersion() as NSString]) + parameters[LookinParam_SwiftUIDisplayMode] = NSNumber(value: SwiftUIHierarchyDisplayModeStore.currentMode().rawValue) + parameters["showBackingLayers"] = NSNumber(value: PreferenceManager.shared.showBackingLayers.currentBOOLValue) return parameters } @@ -191,7 +191,7 @@ final class LKInspectableApp: NSObject { // MARK: - Async API -extension LKInspectableApp { +extension InspectableApp { @MainActor func hierarchy() async throws -> HierarchyInfo { try await response(type: UInt32(LookinRequestTypeHierarchy), data: Self.hierarchyRequestParameters(), as: HierarchyInfo.self) @@ -231,13 +231,13 @@ extension LKInspectableApp { @MainActor func object(oid: UInt) async throws -> InspectedObject { - guard oid != 0 else { throw LKConnectionError.inner } + guard oid != 0 else { throw ConnectionError.inner } return try await response(type: UInt32(LookinRequestTypeFetchObject), data: NSNumber(value: oid), as: InspectedObject.self) } @MainActor func attributeGroups(oid: UInt) async throws -> [AttributesGroup] { - guard oid != 0 else { throw LKConnectionError.inner } + guard oid != 0 else { throw ConnectionError.inner } return try await response(type: UInt32(LookinRequestTypeAllAttrGroups), data: NSNumber(value: oid), as: [AttributesGroup].self) } @@ -253,7 +253,7 @@ extension LKInspectableApp { /// The Server's result dictionary (`description` and related keys). @MainActor func invokeMethod(oid: UInt, text: String) async throws -> NSDictionary { - guard oid != 0, !text.isEmpty else { throw LKConnectionError.inner } + guard oid != 0, !text.isEmpty else { throw ConnectionError.inner } return try await response( type: UInt32(LookinRequestTypeInvokeMethod), data: Self.invokeMethodParameters(oid: oid, text: text), @@ -265,7 +265,7 @@ extension LKInspectableApp { /// The image of the image view `oid`, as encoded image data. @MainActor func image(imageViewOid oid: UInt) async throws -> Data? { - guard oid != 0 else { throw LKConnectionError.inner } + guard oid != 0 else { throw ConnectionError.inner } return try await response(type: UInt32(LookinRequestTypeFetchImageViewImage), data: NSNumber(value: oid), as: Data?.self) } @@ -278,7 +278,7 @@ extension LKInspectableApp { /// Returns whether the recognizer is enabled afterwards. @MainActor func setGestureRecognizer(oid: UInt, enabled: Bool) async throws -> Bool { - guard oid != 0 else { throw LKConnectionError.inner } + guard oid != 0 else { throw ConnectionError.inner } return try await response( type: UInt32(LookinRequestTypeModifyRecognizerEnable), data: Self.gestureRecognizerParameters(oid: oid, enabled: enabled), diff --git a/LookInside/Connection/LKConnectionErrors.swift b/LookInside/Connection/LKConnectionErrors.swift index f3b8f004..6d591b03 100644 --- a/LookInside/Connection/LKConnectionErrors.swift +++ b/LookInside/Connection/LKConnectionErrors.swift @@ -10,7 +10,7 @@ import Foundation import LookInsideHostCore -enum LKConnectionError { +enum ConnectionError { private static func make(_ code: Int, _ description: String, recovery: String? = nil) -> NSError { var userInfo: [String: Any] = [NSLocalizedDescriptionKey: description] if let recovery { diff --git a/LookInside/Connection/LookinLiveDocument.swift b/LookInside/Connection/LiveDocument.swift similarity index 84% rename from LookInside/Connection/LookinLiveDocument.swift rename to LookInside/Connection/LiveDocument.swift index 43f622fe..850eb658 100644 --- a/LookInside/Connection/LookinLiveDocument.swift +++ b/LookInside/Connection/LiveDocument.swift @@ -1,5 +1,5 @@ // -// LookinLiveDocument.swift +// LiveDocument.swift // LookInside // // The document of one live inspection session against one inspectable @@ -12,8 +12,8 @@ import AppKit @objc(LookinLiveDocument) -final class LookinLiveDocument: NSDocument { - /// Posted (object: the document) once `LookinLiveDocumentController` +final class LiveDocument: NSDocument { + /// Posted (object: the document) once `LiveDocumentController` /// added the document and made its window controllers, so observers can /// read `inspectableApp` and `hierarchyDataSource` at once. /// `NSDocumentController` has no such notification of its own. @@ -23,10 +23,10 @@ final class LookinLiveDocument: NSDocument { /// document is still whole. static let willCloseNotification = Notification.Name("LookinLiveDocumentWillCloseNotification") - /// The app this document inspects. Replaced by a new `LKInspectableApp` + /// The app this document inspects. Replaced by a new `InspectableApp` /// (new channel and app info) when the app reconnects. Observable with /// KVO. - @objc private(set) dynamic var inspectableApp: LKInspectableApp + @objc private(set) dynamic var inspectableApp: InspectableApp /// Why the connection was lost, or nil while connected. Observable with /// KVO; the window shows it as a banner. @@ -38,7 +38,7 @@ final class LookinLiveDocument: NSDocument { private var channelEndTask: Task? private var reconnectTask: Task? - init(inspectableApp: LKInspectableApp) { + init(inspectableApp: InspectableApp) { self.inspectableApp = inspectableApp super.init() subscribeChannelLifecycle() @@ -55,23 +55,23 @@ final class LookinLiveDocument: NSDocument { /// The live document whose window is `window`, or nil. @objc(documentInWindow:) - static func document(in window: NSWindow?) -> LookinLiveDocument? { + static func document(in window: NSWindow?) -> LiveDocument? { guard let window else { return nil } - return NSDocumentController.shared.document(for: window) as? LookinLiveDocument + return NSDocumentController.shared.document(for: window) as? LiveDocument } /// Nil before `makeWindowControllers()` ran. - var staticWindowController: LKStaticWindowController? { - windowControllers.first as? LKStaticWindowController + var staticWindowController: StaticWindowController? { + windowControllers.first as? StaticWindowController } /// Nil before `makeWindowControllers()` ran. - @objc var hierarchyDataSource: LKStaticHierarchyDataSource? { + @objc var hierarchyDataSource: StaticHierarchyDataSource? { staticWindowController?.hierarchyDataSource } /// Nil before `makeWindowControllers()` ran. - @objc var asyncUpdateManager: LKStaticAsyncUpdateManager? { + @objc var asyncUpdateManager: StaticAsyncUpdateManager? { staticWindowController?.asyncUpdateManager } @@ -125,15 +125,15 @@ final class LookinLiveDocument: NSDocument { override func data(ofType typeName: String) throws -> Data { guard typeName == "com.lookin.lookin", let info = hierarchyDataSource?.rawHierarchyInfo, - let data = LKExportManager.sharedInstance().data(from: info, imageCompression: 1.0, fileName: nil) + let data = ExportManager.sharedInstance().data(from: info, imageCompression: 1.0, fileName: nil) else { - throw LKConnectionError.inner + throw ConnectionError.inner } return data } override func makeWindowControllers() { - addWindowController(LKStaticWindowController(inspectableApp: inspectableApp)) + addWindowController(StaticWindowController(inspectableApp: inspectableApp)) } override func close() { @@ -157,7 +157,7 @@ final class LookinLiveDocument: NSDocument { return } channelEndTask?.cancel() - let endedChannels = LKConnectionManager.shared.channelWillEndEvents() + let endedChannels = ConnectionManager.shared.channelWillEndEvents() channelEndTask = Task { [weak self] in for await channel in endedChannels { guard let self else { return } @@ -198,12 +198,12 @@ final class LookinLiveDocument: NSDocument { /// The hierarchy is not fetched again here; the next reload uses the /// new channel. - private func adoptReconnectedApp(_ newApp: LKInspectableApp) { + private func adoptReconnectedApp(_ newApp: InspectableApp) { inspectableApp = newApp // The window controller and its async update manager hold the app // weakly and rely on this document to keep it alive; replacing it // here would leave them with nil, so they get the new app too. - for case let windowController as LKStaticWindowController in windowControllers { + for case let windowController as StaticWindowController in windowControllers { windowController.inspectableApp = newApp windowController.asyncUpdateManager?.inspectableApp = newApp } @@ -212,9 +212,9 @@ final class LookinLiveDocument: NSDocument { subscribeChannelLifecycle() } - private func fetchInspectableAppMatchingLastKnown() async -> LKInspectableApp? { + private func fetchInspectableAppMatchingLastKnown() async -> InspectableApp? { guard let targetInfo = lastKnownAppInfo else { return nil } - let apps = await LKAppsManager.shared.fetchAppInfos(needImages: false, localInfos: nil) + let apps = await AppsManager.shared.fetchAppInfos(needImages: false, localInfos: nil) guard let match = apps.first(where: { targetInfo.isEqual(to: $0.appInfo) }) else { return nil } diff --git a/LookInside/Connection/LookinLiveDocumentController.swift b/LookInside/Connection/LiveDocumentController.swift similarity index 71% rename from LookInside/Connection/LookinLiveDocumentController.swift rename to LookInside/Connection/LiveDocumentController.swift index 2daeecd4..5a6e53f0 100644 --- a/LookInside/Connection/LookinLiveDocumentController.swift +++ b/LookInside/Connection/LiveDocumentController.swift @@ -1,5 +1,5 @@ // -// LookinLiveDocumentController.swift +// LiveDocumentController.swift // LookInside // // The one place that opens a live document for an inspectable app: the @@ -13,9 +13,9 @@ import AppKit @objc(LookinLiveDocumentController) @MainActor -final class LookinLiveDocumentController: NSObject { +final class LiveDocumentController: NSObject { @objc(sharedInstance) - static let shared = LookinLiveDocumentController() + static let shared = LiveDocumentController() override private init() { super.init() @@ -25,18 +25,18 @@ final class LookinLiveDocumentController: NSObject { /// open on the same channel. /// /// - Returns: the document, and whether it was already open. - func openLiveDocument(for app: LKInspectableApp) -> (document: LookinLiveDocument, alreadyOpen: Bool) { + func openLiveDocument(for app: InspectableApp) -> (document: LiveDocument, alreadyOpen: Bool) { if let existing = liveDocument(for: app.channel) { existing.showWindows() return (existing, true) } - let document = LookinLiveDocument(inspectableApp: app) + let document = LiveDocument(inspectableApp: app) NSDocumentController.shared.addDocument(document) document.makeWindowControllers() document.showWindows() // After makeWindowControllers(), so observers can reach the data // source, which lives on the window controller. - NotificationCenter.default.post(name: LookinLiveDocument.didOpenNotification, object: document) + NotificationCenter.default.post(name: LiveDocument.didOpenNotification, object: document) return (document, false) } @@ -45,11 +45,11 @@ final class LookinLiveDocumentController: NSObject { /// `LookinErr_Inner` and no document. @objc(openLiveDocumentForInspectableApp:completion:) func openLiveDocument( - for app: LKInspectableApp?, - completion: ((LookinLiveDocument?, Bool, NSError?) -> Void)? + for app: InspectableApp?, + completion: ((LiveDocument?, Bool, NSError?) -> Void)? ) { guard let app else { - completion?(nil, false, LKConnectionError.inner) + completion?(nil, false, ConnectionError.inner) return } let (document, alreadyOpen) = openLiveDocument(for: app) @@ -58,10 +58,10 @@ final class LookinLiveDocumentController: NSObject { /// The live document whose app uses `channel`, or nil. @objc(liveDocumentForChannel:) - func liveDocument(for channel: LKChannel?) -> LookinLiveDocument? { + func liveDocument(for channel: ServerChannel?) -> LiveDocument? { guard let channel else { return nil } return NSDocumentController.shared.documents - .compactMap { $0 as? LookinLiveDocument } + .compactMap { $0 as? LiveDocument } .first { $0.inspectableApp.channel === channel } } } diff --git a/LookInside/Connection/LKChannel.swift b/LookInside/Connection/ServerChannel.swift similarity index 83% rename from LookInside/Connection/LKChannel.swift rename to LookInside/Connection/ServerChannel.swift index 7c6abb98..06c8799b 100644 --- a/LookInside/Connection/LKChannel.swift +++ b/LookInside/Connection/ServerChannel.swift @@ -1,5 +1,5 @@ // -// LKChannel.swift +// ServerChannel.swift // LookInside // // One connection to an inspected app's Server: a FrameChannel on a @@ -11,7 +11,7 @@ import Foundation /// Where a channel's Server runs. -enum LKChannelKind { +enum ServerChannelKind { case simulator case mac case usb(deviceID: Int) @@ -19,24 +19,24 @@ enum LKChannelKind { /// Receives a channel's frames and its end, on the main actor. @MainActor -protocol LKChannelDelegate: AnyObject { +protocol ServerChannelDelegate: AnyObject { /// Decides on each frame header before its payload is read; a rejected /// frame's payload is skipped. - func channel(_ channel: LKChannel, shouldAcceptFrameOfType type: UInt32, tag: UInt32) -> Bool + func channel(_ channel: ServerChannel, shouldAcceptFrameOfType type: UInt32, tag: UInt32) -> Bool /// An accepted frame; an empty payload is `Data()`. - func channel(_ channel: LKChannel, didReceiveFrameOfType type: UInt32, tag: UInt32, payload: Data) + func channel(_ channel: ServerChannel, didReceiveFrameOfType type: UInt32, tag: UInt32, payload: Data) /// The channel ended: the Server closed it, the stream was invalid, or /// the Host closed it. Runs once, after the socket is closed. - func channelDidEnd(_ channel: LKChannel) + func channelDidEnd(_ channel: ServerChannel) } @MainActor -final class LKChannel: NSObject { +final class ServerChannel: NSObject { let port: Int32 - let kind: LKChannelKind + let kind: ServerChannelKind /// Requests, license handshake and Server release of this connection; /// released with the channel. - let connectionState = LKChannelConnectionState() + let connectionState = ServerChannelConnectionState() private let frameChannel: FrameChannel @@ -48,7 +48,7 @@ final class LKChannel: NSObject { /// Takes over `fileDescriptor`, a connected socket, and starts reading. /// `initialBytes` are frame bytes read before the channel existed (after /// a usbmuxd Connect result). The channel stays alive until it ends. - init(fileDescriptor: Int32, initialBytes: Data = Data(), port: Int32, kind: LKChannelKind, delegate: LKChannelDelegate) { + init(fileDescriptor: Int32, initialBytes: Data = Data(), port: Int32, kind: ServerChannelKind, delegate: ServerChannelDelegate) { self.port = port self.kind = kind // The Host takes any payload size, as Peertalk did: a hierarchy @@ -100,6 +100,6 @@ final class LKChannel: NSObject { } override nonisolated var description: String { - String(format: "", UInt(bitPattern: Unmanaged.passUnretained(self).toOpaque()), port) + String(format: "", UInt(bitPattern: Unmanaged.passUnretained(self).toOpaque()), port) } } diff --git a/LookInside/Connection/LKServerUpgradeHint.swift b/LookInside/Connection/ServerUpgradeHint.swift similarity index 92% rename from LookInside/Connection/LKServerUpgradeHint.swift rename to LookInside/Connection/ServerUpgradeHint.swift index 05a11d89..9d9847ed 100644 --- a/LookInside/Connection/LKServerUpgradeHint.swift +++ b/LookInside/Connection/ServerUpgradeHint.swift @@ -1,5 +1,5 @@ // -// LKServerUpgradeHint.swift +// ServerUpgradeHint.swift // LookInside // // The one-time hint that the inspected app's Server is old (0.2.9 or @@ -13,7 +13,7 @@ import Foundation import LookInsideHostCore @MainActor -enum LKServerUpgradeHint { +enum ServerUpgradeHint { /// Posted on the main thread when a channel's 220 reply arrived; the /// object is the channel. static let releaseDidArriveNotification = Notification.Name("LKServerUpgradeHintReleaseDidArrive") @@ -21,7 +21,7 @@ enum LKServerUpgradeHint { private static let ledger = ServerUpgradeHintLedger() /// Records the release `channel`'s Server reported. - static func noteRelease(_ release: ServerRelease, on channel: LKChannel) { + static func noteRelease(_ release: ServerRelease, on channel: ServerChannel) { channel.connectionState.serverRelease = release NotificationCenter.default.post(name: releaseDidArriveNotification, object: channel) } @@ -29,7 +29,7 @@ enum LKServerUpgradeHint { /// `true` when the hint should be shown now for `app`: its Server /// reported an old release and no window showed the hint for this app /// during this launch. Answering `true` records the hint as shown. - static func shouldShowHint(for app: LKInspectableApp?) -> Bool { + static func shouldShowHint(for app: InspectableApp?) -> Bool { guard let app, let release = app.channel?.connectionState.serverRelease, let appKey = appKey(for: app.appInfo) diff --git a/LookInside/Console/LKConsoleDataSource.swift b/LookInside/Console/ConsoleDataSource.swift similarity index 84% rename from LookInside/Console/LKConsoleDataSource.swift rename to LookInside/Console/ConsoleDataSource.swift index f88a5c44..14afc725 100644 --- a/LookInside/Console/LKConsoleDataSource.swift +++ b/LookInside/Console/ConsoleDataSource.swift @@ -1,18 +1,18 @@ // -// LKConsoleDataSource.swift +// ConsoleDataSource.swift // LookInside // // The Console's state: the transcript rows, the target object, the objects // highlighted in the hierarchy and the objects recent calls returned. It // calls methods on the inspected app through the live document's -// LKInspectableApp. +// InspectableApp. // import AppKit import LookInsideHostCore /// One transcript row. -struct LKConsoleRowItem { +struct ConsoleRowItem { enum Kind { /// The input field, always the last row. case input @@ -28,21 +28,21 @@ struct LKConsoleRowItem { } @MainActor -final class LKConsoleDataSource { +final class ConsoleDataSource { /// An object returned by a call, with the call that returned it. struct RecentObject { var object: InspectedObject var message: String } - weak var liveDocument: LookinLiveDocument? + weak var liveDocument: LiveDocument? /// Called after `rowItems` changes. var rowItemsDidChange: (() -> Void)? /// Called after `currentObject` changes. var currentObjectDidChange: (() -> Void)? - private(set) var rowItems: [LKConsoleRowItem] = [LKConsoleRowItem(kind: .input)] { + private(set) var rowItems: [ConsoleRowItem] = [ConsoleRowItem(kind: .input)] { didSet { rowItemsDidChange?() } } @@ -67,7 +67,7 @@ final class LKConsoleDataSource { private var selectorNamesByClass: [String: [String]] = [:] private var selectionObservation: NSKeyValueObservation? - init(hierarchyDataSource: LKHierarchyDataSource) { + init(hierarchyDataSource: HierarchyDataSource) { selectionObservation = hierarchyDataSource.observe(\.selectedItem, options: [.initial, .new]) { [weak self] dataSource, _ in let objects = Self.objects(of: dataSource.selectedItem) @@ -95,25 +95,25 @@ final class LKConsoleDataSource { /// transcript. An object it returns joins the recent objects. func submit(object: InspectedObject?, text: String) async throws { guard currentObject != nil, let object else { - throw LKConnectionError.inner + throw ConnectionError.inner } let check = ConsoleInputCheck(text) if check == .empty { - throw LKPeripheralAlerts.error(title: NSLocalizedString("Content is empty.", comment: ""), detail: "") + throw PeripheralAlerts.error(title: NSLocalizedString("Content is empty.", comment: ""), detail: "") } guard let inspectableApp = liveDocument?.inspectableApp else { - throw LKConnectionError.noConnect + throw ConnectionError.noConnect } switch check { case .hasArguments: let format = NSLocalizedString("You can click \"Pause\" button near the bottom-left corner in Xcode to pause your iOS app, and input in Xcode console like the contents below:\nexpr [((%@ *)%@) %@]", comment: "") let detail = String(format: format, object.rawClassName() ?? "(null)", object.memoryAddress ?? "(null)", text) - throw LKPeripheralAlerts.error( + throw PeripheralAlerts.error( title: NSLocalizedString("LookInside doesn't support invoking methods with arguments yet.", comment: ""), detail: detail ) case .unsupportedSyntax: - throw LKPeripheralAlerts.error( + throw PeripheralAlerts.error( title: NSLocalizedString("LookInside doesn't support this syntax yet. Please input a method or property name.", comment: ""), detail: "" ) @@ -127,9 +127,9 @@ final class LKConsoleDataSource { let target = "<\(object.lk_simpleDemangledClassName()): \(object.memoryAddress ?? "(null)")>" var rows = rowItems - rows.insert(LKConsoleRowItem(kind: .submit, highlightText: target, normalText: text), at: rows.count - 1) + rows.insert(ConsoleRowItem(kind: .submit, highlightText: target, normalText: text), at: rows.count - 1) if let returnDescription, !returnDescription.isEmpty { - rows.insert(LKConsoleRowItem(kind: .returnValue, normalText: returnDescription), at: rows.count - 1) + rows.insert(ConsoleRowItem(kind: .returnValue, normalText: returnDescription), at: rows.count - 1) } if let returnObject { recentObjects.insert(RecentObject(object: returnObject, message: "\(target) => \(text)"), id: returnObject.oid) @@ -140,10 +140,10 @@ final class LKConsoleDataSource { /// Makes `object` the call target, fetching its class's selector names first when needed. func makeObjectCurrent(_ object: InspectedObject?) async throws { guard let object, let className = object.rawClassName(), !className.isEmpty else { - throw LKConnectionError.inner + throw ConnectionError.inner } guard let inspectableApp = liveDocument?.inspectableApp else { - throw LKConnectionError.noConnect + throw ConnectionError.noConnect } if selectorNamesByClass[className] != nil { currentObject = object @@ -155,12 +155,12 @@ final class LKConsoleDataSource { } func clearHistoryContents() { - rowItems = [LKConsoleRowItem(kind: .input)] + rowItems = [ConsoleRowItem(kind: .input)] } private func syncConsoleTargetIfNeeded() { guard isShowingConsole, let lastSelected = selectedObjects.last else { return } - if LKPreferenceManager.shared.syncConsoleTarget || currentObject == nil { + if PreferenceManager.shared.syncConsoleTarget || currentObject == nil { Task { try? await makeObjectCurrent(lastSelected) } diff --git a/LookInside/Console/LKConsoleSelectPopoverController.swift b/LookInside/Console/ConsoleSelectPopoverController.swift similarity index 88% rename from LookInside/Console/LKConsoleSelectPopoverController.swift rename to LookInside/Console/ConsoleSelectPopoverController.swift index 91c46bc7..773caa23 100644 --- a/LookInside/Console/LKConsoleSelectPopoverController.swift +++ b/LookInside/Console/ConsoleSelectPopoverController.swift @@ -1,5 +1,5 @@ // -// LKConsoleSelectPopoverController.swift +// ConsoleSelectPopoverController.swift // LookInside // // The Console's target picker: objects recent calls returned, objects of @@ -9,7 +9,7 @@ import AppKit -final class LKConsoleSelectPopoverController: LKBaseViewController { +final class ConsoleSelectPopoverController: BaseViewController { private static let insets = NSEdgeInsets(top: 8, left: 12, bottom: 8, right: 12) private static let titleMarginTop: CGFloat = 16 private static let itemControlMarginTop: CGFloat = 5 @@ -18,16 +18,16 @@ final class LKConsoleSelectPopoverController: LKBaseViewController { var needShowError: ((Error) -> Void)? var needClose: (() -> Void)? - private let dataSource: LKConsoleDataSource - private let historyTitleView = LKImageTextView() - private let highlightTitleView = LKImageTextView() + private let dataSource: ConsoleDataSource + private let historyTitleView = ImageTextView() + private let highlightTitleView = ImageTextView() private let toggleButton = NSButton() private let separatorLayer = CALayer() - private var historyControls: [LKConsoleSelectPopoverItemControl] = [] - private var highlightControls: [LKConsoleSelectPopoverItemControl] = [] + private var historyControls: [ConsoleSelectPopoverItemControl] = [] + private var highlightControls: [ConsoleSelectPopoverItemControl] = [] private var syncObservation: NSKeyValueObservation? - init(dataSource: LKConsoleDataSource) { + init(dataSource: ConsoleDataSource) { self.dataSource = dataSource super.init(containerView: nil) } @@ -38,7 +38,7 @@ final class LKConsoleSelectPopoverController: LKBaseViewController { } override func makeContainerView() -> NSView { - let view = LKBaseView() + let view = BaseView() historyTitleView.imageMargins = HorizontalMargins(left: 0, right: 5) historyTitleView.imageView.image = NSImage(named: "console_history") @@ -57,7 +57,7 @@ final class LKConsoleSelectPopoverController: LKBaseViewController { toggleButton.action = #selector(handleToggleSyncButton) view.addSubview(toggleButton) - syncObservation = LKPreferenceManager.shared.observe(\.syncConsoleTarget, options: [.initial, .new]) { + syncObservation = PreferenceManager.shared.observe(\.syncConsoleTarget, options: [.initial, .new]) { [weak self] manager, _ in let isOn = manager.syncConsoleTarget MainActor.assumeIsolated { @@ -80,7 +80,7 @@ final class LKConsoleSelectPopoverController: LKBaseViewController { let insets = Self.insets var y = insets.top - func layoutControls(_ controls: [LKConsoleSelectPopoverItemControl]) { + func layoutControls(_ controls: [ConsoleSelectPopoverItemControl]) { for control in controls { control.lkpSetX(insets.left) control.lkpToRight(insets.right) @@ -175,17 +175,17 @@ final class LKConsoleSelectPopoverController: LKBaseViewController { /// Keeps the first `count` controls, adds new ones as needed, removes the /// rest, and configures each kept or added control. private func resizedControls( - _ controls: [LKConsoleSelectPopoverItemControl], + _ controls: [ConsoleSelectPopoverItemControl], count: Int, - configure: (Int, LKConsoleSelectPopoverItemControl) -> Void - ) -> [LKConsoleSelectPopoverItemControl] { - var result: [LKConsoleSelectPopoverItemControl] = [] + configure: (Int, ConsoleSelectPopoverItemControl) -> Void + ) -> [ConsoleSelectPopoverItemControl] { + var result: [ConsoleSelectPopoverItemControl] = [] for index in 0 ..< count { - let control: LKConsoleSelectPopoverItemControl + let control: ConsoleSelectPopoverItemControl if index < controls.count { control = controls[index] } else { - control = LKConsoleSelectPopoverItemControl() + control = ConsoleSelectPopoverItemControl() control.addTarget(self, clickAction: #selector(handleControl(_:))) view.addSubview(control) } @@ -198,23 +198,23 @@ final class LKConsoleSelectPopoverController: LKBaseViewController { return result } - @objc private func handleControl(_ control: LKConsoleSelectPopoverItemControl) { + @objc private func handleControl(_ control: ConsoleSelectPopoverItemControl) { guard let object = control.representedObject else { return } Task { do { try await dataSource.makeObjectCurrent(object) if object.oid != dataSource.selectedObjects.last?.oid { - LKPreferenceManager.shared.syncConsoleTarget = false + PreferenceManager.shared.syncConsoleTarget = false } needClose?() } catch { - needShowError?(LKConnectionError.noConnect) + needShowError?(ConnectionError.noConnect) } } } @objc private func handleToggleSyncButton() { - let manager = LKPreferenceManager.shared + let manager = PreferenceManager.shared manager.syncConsoleTarget = !manager.syncConsoleTarget guard manager.syncConsoleTarget else { return } Task { @@ -227,7 +227,7 @@ final class LKConsoleSelectPopoverController: LKBaseViewController { /// One object in the target picker: a check mark when it is the target, its /// class and address, and optionally the call that returned it. -final class LKConsoleSelectPopoverItemControl: LKBaseControl { +final class ConsoleSelectPopoverItemControl: BaseControl { private static let subtitleMarginTop: CGFloat = 0 var isChecked = false { @@ -256,8 +256,8 @@ final class LKConsoleSelectPopoverItemControl: LKBaseControl { } private let imageView = NSImageView() - private let titleLabel = LKLabel() - private let subtitleLabel = LKLabel() + private let titleLabel = TextLabel() + private let subtitleLabel = TextLabel() override init(frame frameRect: NSRect) { super.init(frame: frameRect) diff --git a/LookInside/Console/LKConsoleViewController.swift b/LookInside/Console/ConsoleViewController.swift similarity index 85% rename from LookInside/Console/LKConsoleViewController.swift rename to LookInside/Console/ConsoleViewController.swift index 8f086d84..c8338b59 100644 --- a/LookInside/Console/LKConsoleViewController.swift +++ b/LookInside/Console/ConsoleViewController.swift @@ -1,5 +1,5 @@ // -// LKConsoleViewController.swift +// ConsoleViewController.swift // LookInside // // The Console below the inspector: a transcript of method calls on the @@ -10,16 +10,16 @@ import AppKit @objc(LKConsoleViewController) -final class LKConsoleViewController: LKBaseViewController, LKTableViewDelegate, LKTableViewDataSource { - private let dataSource: LKConsoleDataSource - private let tableView = LKTableView() +final class ConsoleViewController: BaseViewController, TableViewDelegate, TableViewDataSource { + private let dataSource: ConsoleDataSource + private let tableView = TableView() private let clearButton = NSButton() - private let inputRowView: LKConsoleInputRowView + private let inputRowView: ConsoleInputRowView private let topBorderLayer = CALayer() - private lazy var measuringReturnRowView = LKConsoleReturnRowView() + private lazy var measuringReturnRowView = ConsoleReturnRowView() private var previousWidth: CGFloat = 0 - @objc weak var liveDocument: LookinLiveDocument? { + @objc weak var liveDocument: LiveDocument? { didSet { dataSource.liveDocument = liveDocument } } @@ -31,9 +31,9 @@ final class LKConsoleViewController: LKBaseViewController, LKTableViewDelegate, } @objc(initWithHierarchyDataSource:) - init(hierarchyDataSource: LKHierarchyDataSource) { - dataSource = LKConsoleDataSource(hierarchyDataSource: hierarchyDataSource) - inputRowView = LKConsoleInputRowView(dataSource: dataSource) + init(hierarchyDataSource: HierarchyDataSource) { + dataSource = ConsoleDataSource(hierarchyDataSource: hierarchyDataSource) + inputRowView = ConsoleInputRowView(dataSource: dataSource) super.init(containerView: nil) dataSource.rowItemsDidChange = { [weak self] in @@ -48,7 +48,7 @@ final class LKConsoleViewController: LKBaseViewController, LKTableViewDelegate, } override func makeContainerView() -> NSView { - let containerView = LKBaseView() + let containerView = BaseView() containerView.layer?.backgroundColor = NSColor(named: "ConsoleBackgroundColor")?.cgColor tableView.drawsBackground = false @@ -130,7 +130,7 @@ final class LKConsoleViewController: LKBaseViewController, LKTableViewDelegate, } } - // MARK: - LKTableViewDelegate, LKTableViewDataSource + // MARK: - TableViewDelegate, TableViewDataSource func numberOfRows(in _: NSTableView) -> Int { dataSource.rowItems.count @@ -151,7 +151,7 @@ final class LKConsoleViewController: LKBaseViewController, LKTableViewDelegate, func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? { guard dataSource.rowItems.indices.contains(row) else { - return LKTableBlankRowView() + return TableBlankRowView() } let item = dataSource.rowItems[row] switch item.kind { @@ -159,9 +159,9 @@ final class LKConsoleViewController: LKBaseViewController, LKTableViewDelegate, return inputRowView case .submit: let identifier = NSUserInterfaceItemIdentifier("submit") - let view = tableView.makeView(withIdentifier: identifier, owner: self) as? LKConsoleSubmitRowView + let view = tableView.makeView(withIdentifier: identifier, owner: self) as? ConsoleSubmitRowView ?? { - let view = LKConsoleSubmitRowView() + let view = ConsoleSubmitRowView() view.identifier = identifier return view }() @@ -171,9 +171,9 @@ final class LKConsoleViewController: LKBaseViewController, LKTableViewDelegate, return view case .returnValue: let identifier = NSUserInterfaceItemIdentifier("return") - let view = tableView.makeView(withIdentifier: identifier, owner: self) as? LKConsoleReturnRowView + let view = tableView.makeView(withIdentifier: identifier, owner: self) as? ConsoleReturnRowView ?? { - let view = LKConsoleReturnRowView() + let view = ConsoleReturnRowView() view.identifier = identifier return view }() @@ -183,7 +183,7 @@ final class LKConsoleViewController: LKBaseViewController, LKTableViewDelegate, } } - func tableViewDidClickBlankArea(_: LKTableView) { + func tableViewDidClickBlankArea(_: TableView) { inputRowView.makeTextFieldFirstResponder() } } diff --git a/LookInside/Console/LKConsoleRowViews.swift b/LookInside/Console/LKConsoleRowViews.swift index e6d45e8c..c3257490 100644 --- a/LookInside/Console/LKConsoleRowViews.swift +++ b/LookInside/Console/LKConsoleRowViews.swift @@ -16,19 +16,19 @@ private func lkpConsoleTargetColor(isDarkMode: Bool) -> NSColor { /// The last transcript row: a button showing the call target (it opens the /// target picker) and the input field with selector suggestions. -final class LKConsoleInputRowView: LKTableRowView, LKInputSearchViewDelegate { - private let dataSource: LKConsoleDataSource +final class ConsoleInputRowView: TableRowView, InputSearchViewDelegate { + private let dataSource: ConsoleDataSource private let selectButton = NSButton() - private let inputView = LKInputSearchView(throttleTime: 0.15) - private let selectPopoverController: LKConsoleSelectPopoverController + private let inputView = InputSearchView(throttleTime: 0.15) + private let selectPopoverController: ConsoleSelectPopoverController - init(dataSource: LKConsoleDataSource) { + init(dataSource: ConsoleDataSource) { self.dataSource = dataSource - selectPopoverController = LKConsoleSelectPopoverController(dataSource: dataSource) + selectPopoverController = ConsoleSelectPopoverController(dataSource: dataSource) super.init(frame: .zero) selectPopoverController.needShowError = { [weak self] error in - LKPeripheralAlerts.show(error, in: self?.window) + PeripheralAlerts.show(error, in: self?.window) } selectButton.font = .systemFont(ofSize: 13) @@ -84,7 +84,7 @@ final class LKConsoleInputRowView: LKTableRowView, LKInputSearchViewDelegate { let popover = NSPopover() popover.animates = false popover.behavior = .transient - popover.contentSize = NSSize(width: LKHelper.isEnglish() ? 465 : 400, + popover.contentSize = NSSize(width: AppHelper.isEnglish() ? 465 : 400, height: selectPopoverController.bestHeight()) popover.contentViewController = selectPopoverController popover.show(relativeTo: NSRect(origin: .zero, size: selectButton.bounds.size), @@ -95,7 +95,7 @@ final class LKConsoleInputRowView: LKTableRowView, LKInputSearchViewDelegate { } private func handleCurrentObjectDidChange() { - // Called from LKTableRowView's initializer through setIsDarkMode + // Called from TableRowView's initializer through setIsDarkMode // before this row is set up; the init call repeats it. guard selectButton.target != nil else { return } inputView.clearContentAndSuggestions() @@ -115,35 +115,35 @@ final class LKConsoleInputRowView: LKTableRowView, LKInputSearchViewDelegate { needsLayout = true } - // MARK: - LKInputSearchViewDelegate + // MARK: - InputSearchViewDelegate - func inputSearchView(_: LKInputSearchView, suggestionsFor string: String) -> [LKInputSearchSuggestionItem]? { + func inputSearchView(_: InputSearchView, suggestionsFor string: String) -> [InputSearchSuggestionItem]? { guard string.count >= 3 else { return nil } - let matches = LKHelper.bestMatches(inCandidates: dataSource.currentObjectSelectorNames, input: string, + let matches = AppHelper.bestMatches(inCandidates: dataSource.currentObjectSelectorNames, input: string, maxResultsCount: 8) return matches.map { name in - let item = LKInputSearchSuggestionItem() + let item = InputSearchSuggestionItem() item.image = NSImage(named: "icon_method") item.text = name return item } } - func inputSearchView(_ view: LKInputSearchView, submitText text: String) { + func inputSearchView(_ view: InputSearchView, submitText text: String) { Task { [weak self, weak view] in guard let self else { return } do { try await dataSource.submit(text) view?.clearContentAndSuggestions() } catch { - LKPeripheralAlerts.show(error, in: window) + PeripheralAlerts.show(error, in: window) } } } } /// A submitted call: the target in green, then the method name. -final class LKConsoleSubmitRowView: LKTableRowView { +final class ConsoleSubmitRowView: TableRowView { override init(frame frameRect: NSRect) { super.init(frame: frameRect) titleLabel.isSelectable = true @@ -181,7 +181,7 @@ final class LKConsoleSubmitRowView: LKTableRowView { } /// A returned description, wrapped to the row width. -final class LKConsoleReturnRowView: LKTableRowView { +final class ConsoleReturnRowView: TableRowView { private static let insets = NSEdgeInsets(top: 0, left: ConsoleInsetLeft, bottom: 5, right: ConsoleInsetRight) override init(frame frameRect: NSRect) { diff --git a/LookInside/DanceScript/DanceScriptManager.swift b/LookInside/DanceScript/DanceScriptManager.swift index 5058c6b4..7d6a33d0 100644 --- a/LookInside/DanceScript/DanceScriptManager.swift +++ b/LookInside/DanceScript/DanceScriptManager.swift @@ -50,17 +50,17 @@ final class DanceScriptManager: NSObject { @objc(handleText:) func handleText(_ json: String?) { guard let json else { - LKPeripheralAlerts.show(LKConnectionError.inner, in: LKPeripheralAlerts.keyWindow) + PeripheralAlerts.show(ConnectionError.inner, in: PeripheralAlerts.keyWindow) return } switch Self.parse(json) { case let .success(request): execute(request) case .failure(.invalidJSON): - LKPeripheralAlerts.show(title: NSLocalizedString("Unable to Run Script", comment: ""), detail: String(format: NSLocalizedString("Unable to parse the request: %@", comment: ""), json), in: LKPeripheralAlerts.keyWindow) + PeripheralAlerts.show(title: NSLocalizedString("Unable to Run Script", comment: ""), detail: String(format: NSLocalizedString("Unable to parse the request: %@", comment: ""), json), in: PeripheralAlerts.keyWindow) assertionFailure("DanceScript payload is not JSON") case .failure(.unexpectedFormat): - LKPeripheralAlerts.show(title: NSLocalizedString("Unable to Run Script", comment: ""), detail: String(format: NSLocalizedString("Unexpected request format: %@", comment: ""), json), in: LKPeripheralAlerts.keyWindow) + PeripheralAlerts.show(title: NSLocalizedString("Unable to Run Script", comment: ""), detail: String(format: NSLocalizedString("Unexpected request format: %@", comment: ""), json), in: PeripheralAlerts.keyWindow) } } @@ -73,18 +73,18 @@ final class DanceScriptManager: NSObject { } let scriptPath = Bundle.main.url(forResource: "DanceScript", withExtension: "sh")?.relativePath guard let scriptPath, fileManager.fileExists(atPath: scriptPath) else { - LKPeripheralAlerts.show(title: NSLocalizedString("Unable to Run Script", comment: ""), detail: String(format: NSLocalizedString("Unable to find the script at %@.", comment: ""), scriptPath ?? "(null)"), - in: LKPeripheralAlerts.keyWindow) + PeripheralAlerts.show(title: NSLocalizedString("Unable to Run Script", comment: ""), detail: String(format: NSLocalizedString("Unable to find the script at %@.", comment: ""), scriptPath ?? "(null)"), + in: PeripheralAlerts.keyWindow) return nil } let copied = (try? fileManager.copyItem(atPath: scriptPath, toPath: newScriptPath)) != nil try? fileManager.setAttributes([.posixPermissions: NSNumber(value: Int16(0o755))], ofItemAtPath: newScriptPath) guard copied else { - LKPeripheralAlerts.show(title: NSLocalizedString("Unable to Run Script", comment: ""), detail: NSLocalizedString("Unable to copy the script.", comment: ""), in: LKPeripheralAlerts.keyWindow) + PeripheralAlerts.show(title: NSLocalizedString("Unable to Run Script", comment: ""), detail: NSLocalizedString("Unable to copy the script.", comment: ""), in: PeripheralAlerts.keyWindow) return nil } guard fileManager.fileExists(atPath: newScriptPath) else { - LKPeripheralAlerts.show(title: NSLocalizedString("Unable to Run Script", comment: ""), detail: NSLocalizedString("The copied script is missing.", comment: ""), in: LKPeripheralAlerts.keyWindow) + PeripheralAlerts.show(title: NSLocalizedString("Unable to Run Script", comment: ""), detail: NSLocalizedString("The copied script is missing.", comment: ""), in: PeripheralAlerts.keyWindow) return nil } return newScriptPath diff --git a/LookInside/Dashboard/AttributeView/Constraint/LKConstraintPopoverController.swift b/LookInside/Dashboard/AttributeView/Constraint/ConstraintPopoverController.swift similarity index 81% rename from LookInside/Dashboard/AttributeView/Constraint/LKConstraintPopoverController.swift rename to LookInside/Dashboard/AttributeView/Constraint/ConstraintPopoverController.swift index a5b3f483..e431b075 100644 --- a/LookInside/Dashboard/AttributeView/Constraint/LKConstraintPopoverController.swift +++ b/LookInside/Dashboard/AttributeView/Constraint/ConstraintPopoverController.swift @@ -1,5 +1,5 @@ // -// LKConstraintPopoverController.swift +// ConstraintPopoverController.swift // LookInside // // Created by Li Kai on 2019/9/28. @@ -9,14 +9,14 @@ import AppKit /// Every field of one constraint, with buttons that jump to its items. -final class LKConstraintPopoverController: LKBaseViewController { +final class ConstraintPopoverController: BaseViewController { private let horInset: CGFloat = 5 private let insetBottom: CGFloat = 10 private let titleHeight: CGFloat = 26 private let textsViewMarginTop: CGFloat = 10 - private var titleView: LKTextFieldView? - private let textsView = LKTextsMenuView() + private var titleView: TextFieldView? + private let textsView = TextsMenuView() private var jumpObjects: [ObjectIdentifier: InspectedObject] = [:] /// Asked to jump to an item of the constraint. @@ -30,13 +30,13 @@ final class LKConstraintPopoverController: LKBaseViewController { super.init(containerView: nil) if !constraint.effective { - let titleView = LKTextFieldView.label() - titleView.textField.font = LKDashboardStyle.font(LKHelper.isEnglish() ? 12 : 13) - titleView.textColors = LKTwoColors(colorInLightMode: LKDashboardStyle.rgb(53, 60, 70), colorInDarkMode: LKDashboardStyle.rgb(216, 220, 228)) + let titleView = TextFieldView.label() + titleView.textField.font = DashboardStyle.font(AppHelper.isEnglish() ? 12 : 13) + titleView.textColors = TwoColors(colorInLightMode: DashboardStyle.rgb(53, 60, 70), colorInDarkMode: DashboardStyle.rgb(216, 220, 228)) titleView.textField.alignment = .center titleView.textField.stringValue = NSLocalizedString("The layout of selected view is not affected by this constraint.", comment: "") - titleView.backgroundColors = LKTwoColors(colorInLightMode: LKDashboardStyle.rgb(0, 0, 0, 0.1), colorInDarkMode: LKDashboardStyle.rgb(0, 0, 0, 0.2)) - titleView.image = LKDashboardStyle.image("Constraint_Popover_Info") + titleView.backgroundColors = TwoColors(colorInLightMode: DashboardStyle.rgb(0, 0, 0, 0.1), colorInDarkMode: DashboardStyle.rgb(0, 0, 0, 0.2)) + titleView.image = DashboardStyle.image("Constraint_Popover_Info") titleView.insets = NSEdgeInsets(top: 0, left: horInset, bottom: 0, right: horInset) view.addSubview(titleView) self.titleView = titleView @@ -44,7 +44,7 @@ final class LKConstraintPopoverController: LKBaseViewController { textsView.verSpace = 8 textsView.horSpace = 4 - textsView.font = LKDashboardStyle.font(13) + textsView.font = DashboardStyle.font(13) textsView.type = .center view.addSubview(textsView) @@ -87,9 +87,9 @@ final class LKConstraintPopoverController: LKBaseViewController { } func contentSize() -> NSSize { - var resultSize = textsView.sizeThatFits(LKDashboardMetrics.maxSize) + var resultSize = textsView.sizeThatFits(DashboardMetrics.maxSize) if let titleView { - let titleWidth = titleView.sizeThatFits(LKDashboardMetrics.maxSize).width + let titleWidth = titleView.sizeThatFits(DashboardMetrics.maxSize).width resultSize.width = max(titleWidth, resultSize.width) resultSize.height += titleHeight } @@ -99,7 +99,7 @@ final class LKConstraintPopoverController: LKBaseViewController { } private func jumpButton(for jumpObject: InspectedObject, canJumpToObject: ((InspectedObject) -> Bool)?) -> NSButton { - let button = NSButton.lk_button(with: LKDashboardStyle.image("Icon_JumpDisclosure"), target: self, action: #selector(handleJumpButton(_:))) + let button = NSButton.lk_button(with: DashboardStyle.image("Icon_JumpDisclosure"), target: self, action: #selector(handleJumpButton(_:))) jumpObjects[ObjectIdentifier(button)] = jumpObject if let canJumpToObject, !canJumpToObject(jumpObject) { button.isEnabled = false diff --git a/LookInside/Dashboard/AttributeView/Constraint/LKDashboardAttributeConstraintsView.swift b/LookInside/Dashboard/AttributeView/Constraint/DashboardAttributeConstraintsView.swift similarity index 87% rename from LookInside/Dashboard/AttributeView/Constraint/LKDashboardAttributeConstraintsView.swift rename to LookInside/Dashboard/AttributeView/Constraint/DashboardAttributeConstraintsView.swift index cf74e564..0d04ed04 100644 --- a/LookInside/Dashboard/AttributeView/Constraint/LKDashboardAttributeConstraintsView.swift +++ b/LookInside/Dashboard/AttributeView/Constraint/DashboardAttributeConstraintsView.swift @@ -1,5 +1,5 @@ // -// LKDashboardAttributeConstraintsView.swift +// DashboardAttributeConstraintsView.swift // LookInside // // Created by Li Kai on 2019/9/12. @@ -10,7 +10,7 @@ import AppKit /// One constraint as a line of text, such as "self.width = 100 @ 750". /// Constraints that do not affect the view are greyed out. -final class LKDashboardAttributeConstraintsItemControl: LKTextControl { +final class DashboardAttributeConstraintsItemControl: TextControl { var constraint: AutoLayoutConstraint? { didSet { label.stringValue = constraint.map(Self.string(from:)) ?? "" @@ -21,7 +21,7 @@ final class LKDashboardAttributeConstraintsItemControl: LKTextControl { override init(frame frameRect: NSRect) { super.init(frame: frameRect) label.alignment = .left - label.font = LKDashboardStyle.font(12) + label.font = DashboardStyle.font(12) didChangeAppearance = { [weak self] _, _ in self?.updateLabelColor() } @@ -35,9 +35,9 @@ final class LKDashboardAttributeConstraintsItemControl: LKTextControl { if constraint?.effective == true { label.textColor = .labelColor } else if effectiveAppearance.lk_isDarkMode { - label.textColor = LKDashboardStyle.rgb(130, 131, 132) + label.textColor = DashboardStyle.rgb(130, 131, 132) } else { - label.textColor = LKDashboardStyle.rgb(150, 151, 152) + label.textColor = DashboardStyle.rgb(150, 151, 152) } } @@ -85,17 +85,17 @@ final class LKDashboardAttributeConstraintsItemControl: LKTextControl { /// The constraints that affect (or mention) the view; a click shows the /// details of one. @objc(LKDashboardAttributeConstraintsView) -final class LKDashboardAttributeConstraintsView: LKDashboardAttributeView { +final class DashboardAttributeConstraintsView: DashboardAttributeView { private let verInterSpace: CGFloat = 8 - private var textControls: [LKDashboardAttributeConstraintsItemControl] = [] + private var textControls: [DashboardAttributeConstraintsItemControl] = [] override func renderWithAttribute() { super.renderWithAttribute() let rawData = attribute?.value as? [AutoLayoutConstraint] ?? [] - let constraints = LKDashboardConstraintOrder.sorted(rawData) + let constraints = DashboardConstraintOrder.sorted(rawData) while textControls.count < constraints.count { - let control = LKDashboardAttributeConstraintsItemControl() + let control = DashboardAttributeConstraintsItemControl() control.addTarget(self, clickAction: #selector(handleClickItem(_:))) addSubview(control) textControls.append(control) @@ -134,10 +134,10 @@ final class LKDashboardAttributeConstraintsView: LKDashboardAttributeView { return size } - @objc private func handleClickItem(_ control: LKDashboardAttributeConstraintsItemControl) { + @objc private func handleClickItem(_ control: DashboardAttributeConstraintsItemControl) { guard let constraint = control.constraint else { return } let jumpDataSource = dashboardViewController?.currentDataSource() - let viewController = LKConstraintPopoverController(constraint: constraint) { lookinObject in + let viewController = ConstraintPopoverController(constraint: constraint) { lookinObject in lookinObject.oid != 0 && jumpDataSource?.displayItem(withOid: lookinObject.oid) != nil } diff --git a/LookInside/Dashboard/AttributeView/LKDashboardAttributeColorView.swift b/LookInside/Dashboard/AttributeView/DashboardAttributeColorView.swift similarity index 85% rename from LookInside/Dashboard/AttributeView/LKDashboardAttributeColorView.swift rename to LookInside/Dashboard/AttributeView/DashboardAttributeColorView.swift index f9c582d5..4c74c9f9 100644 --- a/LookInside/Dashboard/AttributeView/LKDashboardAttributeColorView.swift +++ b/LookInside/Dashboard/AttributeView/DashboardAttributeColorView.swift @@ -1,5 +1,5 @@ // -// LKDashboardAttributeColorView.swift +// DashboardAttributeColorView.swift // LookInside // // Created by Li Kai on 2019/2/21. @@ -9,7 +9,7 @@ import AppKit /// The rounded box of a colour attribute; a click opens the colour menu. -private final class LKDashboardAttributeColorContainerView: LKBaseView { +private final class DashboardAttributeColorContainerView: BaseView { var onMouseDown: ((NSEvent) -> Void)? override func mouseDown(with event: NSEvent) { @@ -21,7 +21,7 @@ private final class LKDashboardAttributeColorContainerView: LKBaseView { /// A colour: swatch, hex or RGBA text, and the colour's alias names from /// the app's colour configuration. @objc(LKDashboardAttributeColorView) -final class LKDashboardAttributeColorView: LKDashboardAttributeView, NSMenuDelegate { +final class DashboardAttributeColorView: DashboardAttributeView, NSMenuDelegate { private let mainContainerHeight: CGFloat = 30 private let aliasLabelMarginTop: CGFloat = 1 private let labelX: CGFloat = 28 @@ -32,16 +32,16 @@ final class LKDashboardAttributeColorView: LKDashboardAttributeView, NSMenuDeleg LookinAttr_ViewLayer_Shadow_Color, ] - private let containerView = LKDashboardAttributeColorContainerView() - private let indicatorLayer = LKColorIndicatorLayer() + private let containerView = DashboardAttributeColorContainerView() + private let indicatorLayer = ColorIndicatorLayer() private let iconImageView = NSImageView() - private let descLabel = LKLabel() - private var aliasLabel: LKLabel? + private let descLabel = TextLabel() + private var aliasLabel: TextLabel? private var rgbaFormatObservation: NSKeyValueObservation? required init(frame frameRect: NSRect) { super.init(frame: frameRect) - containerView.layer?.cornerRadius = LKDashboardMetrics.cardControlCornerRadius + containerView.layer?.cornerRadius = DashboardMetrics.cardControlCornerRadius containerView.onMouseDown = { [weak self] event in self?.handleClick(event) } @@ -49,15 +49,15 @@ final class LKDashboardAttributeColorView: LKDashboardAttributeView, NSMenuDeleg containerView.layer?.addSublayer(indicatorLayer) - iconImageView.image = LKDashboardStyle.image("Icon_ArrowUpDown") + iconImageView.image = DashboardStyle.image("Icon_ArrowUpDown") containerView.addSubview(iconImageView) descLabel.textColor = NSColor(named: "DashboardCardValueColor") - descLabel.font = LKDashboardStyle.font(13) + descLabel.font = DashboardStyle.font(13) containerView.addSubview(descLabel) // Re-render when the user switches between hex and RGBA. - rgbaFormatObservation = LKPreferenceManager.shared.observe(\.rgbaFormat, options: [.new]) { [weak self] _, _ in + rgbaFormatObservation = PreferenceManager.shared.observe(\.rgbaFormat, options: [.new]) { [weak self] _, _ in lkRunOnMain { self?.renderWithAttribute() } } } @@ -84,7 +84,7 @@ final class LKDashboardAttributeColorView: LKDashboardAttributeView, NSMenuDeleg indicatorLayer.color = color if let color { - descLabel.stringValue = LKPreferenceManager.shared.rgbaFormat ? color.rgbaString() : color.hexString() + descLabel.stringValue = PreferenceManager.shared.rgbaFormat ? color.rgbaString() : color.hexString() } else { descLabel.stringValue = "nil" } @@ -92,17 +92,17 @@ final class LKDashboardAttributeColorView: LKDashboardAttributeView, NSMenuDeleg let dataSource = dashboardViewController?.currentDataSource() let alias = dataSource?.alias(for: color) if let alias, !identifiersToHideAlias.contains(attribute?.identifier ?? "") { - let label: LKLabel + let label: TextLabel if let aliasLabel { label = aliasLabel } else { - label = LKLabel() + label = TextLabel() label.textColor = NSColor(named: "DashboardCardValueColor") addSubview(label) aliasLabel = label } label.isHidden = false - label.attributedStringValue = LKDashboardText.attributed(alias.joined(separator: "\n"), font: LKDashboardStyle.font(11), lineHeight: 18) + label.attributedStringValue = DashboardText.attributed(alias.joined(separator: "\n"), font: DashboardStyle.font(11), lineHeight: 18) } else { aliasLabel?.isHidden = true } @@ -190,7 +190,7 @@ final class LKDashboardAttributeColorView: LKDashboardAttributeView, NSMenuDeleg } @objc private func handleToggleColorFormatMenuItem() { - let manager = LKPreferenceManager.shared + let manager = PreferenceManager.shared manager.rgbaFormat = !manager.rgbaFormat } diff --git a/LookInside/Dashboard/AttributeView/LKDashboardAttributeEnumsView.swift b/LookInside/Dashboard/AttributeView/DashboardAttributeEnumsView.swift similarity index 88% rename from LookInside/Dashboard/AttributeView/LKDashboardAttributeEnumsView.swift rename to LookInside/Dashboard/AttributeView/DashboardAttributeEnumsView.swift index d259b5ec..06e7c764 100644 --- a/LookInside/Dashboard/AttributeView/LKDashboardAttributeEnumsView.swift +++ b/LookInside/Dashboard/AttributeView/DashboardAttributeEnumsView.swift @@ -1,5 +1,5 @@ // -// LKDashboardAttributeEnumsView.swift +// DashboardAttributeEnumsView.swift // LookInside // // Created by Li Kai on 2019/2/21. @@ -10,29 +10,29 @@ import AppKit /// An enum attribute: the case name, and a menu of the cases on click. @objc(LKDashboardAttributeEnumsView) -final class LKDashboardAttributeEnumsView: LKDashboardAttributeView { +final class DashboardAttributeEnumsView: DashboardAttributeView { private let labelX: CGFloat = 5 private let labelRight: CGFloat = 20 private let iconImageView = NSImageView() - private let titleLabel = LKLabel() - private let textLabel = LKLabel() + private let titleLabel = TextLabel() + private let textLabel = TextLabel() required init(frame frameRect: NSRect) { super.init(frame: frameRect) - layer?.cornerRadius = LKDashboardMetrics.cardControlCornerRadius + layer?.cornerRadius = DashboardMetrics.cardControlCornerRadius titleLabel.textColor = NSColor(named: "DashboardInputAccessoryColor") - titleLabel.font = LKDashboardStyle.font(10) + titleLabel.font = DashboardStyle.font(10) titleLabel.maximumNumberOfLines = 1 addSubview(titleLabel) textLabel.textColor = NSColor(named: "DashboardCardValueColor") textLabel.maximumNumberOfLines = 0 - textLabel.font = LKDashboardStyle.font(12) + textLabel.font = DashboardStyle.font(12) addSubview(textLabel) - iconImageView.image = LKDashboardStyle.image("Icon_ArrowUpDown") + iconImageView.image = DashboardStyle.image("Icon_ArrowUpDown") addSubview(iconImageView) } @@ -46,7 +46,7 @@ final class LKDashboardAttributeEnumsView: LKDashboardAttributeView { if titleLabel.isHidden { textLabel.dashboardLayout.x(labelX).toRight(labelRight).heightToFit().verAlign() } else { - let titleHeight = titleLabel.sizeThatFits(LKDashboardMetrics.maxSize).height + let titleHeight = titleLabel.sizeThatFits(DashboardMetrics.maxSize).height let titleY: CGFloat = 3 titleLabel.dashboardLayout.x(labelX).toRight(labelRight).height(titleHeight).y(titleY) textLabel.dashboardLayout.x(labelX).toRight(labelRight).heightToFit().y(titleY + titleHeight + 1) @@ -85,7 +85,7 @@ final class LKDashboardAttributeEnumsView: LKDashboardAttributeView { } else { let enumValue = (attribute.value as? NSNumber)?.intValue ?? 0 let enumListName = DashboardBlueprint.enumListName(withAttrID: attribute.identifier) - textLabel.stringValue = LKEnumListRegistry.shared.desc(forEnumName: enumListName, value: enumValue) ?? "" + textLabel.stringValue = EnumListRegistry.shared.desc(forEnumName: enumListName, value: enumValue) ?? "" } } @@ -107,7 +107,7 @@ final class LKDashboardAttributeEnumsView: LKDashboardAttributeView { let enumListName = DashboardBlueprint.enumListName(withAttrID: attribute?.identifier) let currentValue = (attribute?.value as? NSNumber)?.intValue ?? 0 let editable = canEdit() - for enumItem in LKEnumListRegistry.shared.items(forEnumName: enumListName) ?? [] { + for enumItem in EnumListRegistry.shared.items(forEnumName: enumListName) ?? [] { let validOSVersion = currentOSVersion >= enumItem.availableOSVersion let item = NSMenuItem() item.image = NSImage(size: NSSize(width: 1, height: 22)) diff --git a/LookInside/Dashboard/AttributeView/LKDashboardAttributeNumberInputView.swift b/LookInside/Dashboard/AttributeView/DashboardAttributeNumberInputView.swift similarity index 91% rename from LookInside/Dashboard/AttributeView/LKDashboardAttributeNumberInputView.swift rename to LookInside/Dashboard/AttributeView/DashboardAttributeNumberInputView.swift index 0eee8ac1..aec1e0d6 100644 --- a/LookInside/Dashboard/AttributeView/LKDashboardAttributeNumberInputView.swift +++ b/LookInside/Dashboard/AttributeView/DashboardAttributeNumberInputView.swift @@ -1,5 +1,5 @@ // -// LKDashboardAttributeNumberInputView.swift +// DashboardAttributeNumberInputView.swift // LookInside // // Created by Li Kai on 2019/2/21. @@ -10,8 +10,8 @@ import AppKit /// A single number: opacity, corner radius, font size and the like. @objc(LKDashboardAttributeNumberInputView) -final class LKDashboardAttributeNumberInputView: LKDashboardAttributeView, NSTextFieldDelegate { - @objc let inputView = LKNumberInputView() +final class DashboardAttributeNumberInputView: DashboardAttributeView, NSTextFieldDelegate { + @objc let inputView = NumberInputView() /// Laid out horizontally (title inside the field) with three decimals; /// everything else is vertical (title below) with two. @@ -123,9 +123,9 @@ final class LKDashboardAttributeNumberInputView: LKDashboardAttributeView, NSTex var size = limitedSize switch inputView.viewStyle { case .horizontal: - size.height = LKDashboardMetrics.numberInputHorizontalHeight + size.height = DashboardMetrics.numberInputHorizontalHeight case .vertical: - size.height = LKDashboardMetrics.numberInputVerticalHeight + size.height = DashboardMetrics.numberInputVerticalHeight @unknown default: assertionFailure() } @@ -178,16 +178,16 @@ final class LKDashboardAttributeNumberInputView: LKDashboardAttributeView, NSTex // notification when the field leaves the window or its editable // flag changes, although textShouldBeginEditing refused input. guard canEdit(), let attribute else { return } - if LKDashboardTextControlEditingFlag.shared.shouldIgnoreTextEditingChangeEvent { + if DashboardTextControlEditingFlag.shared.shouldIgnoreTextEditingChangeEvent { NSLog("忽略 controlTextDidEndEditing 事件,驳回") return } - guard let parsed = LKNumberInputView.parsedValue(with: inputView.textFieldView.textField.stringValue, attrType: attribute.attrType) as? NSNumber else { + guard let parsed = NumberInputView.parsedValue(with: inputView.textFieldView.textField.stringValue, attrType: attribute.attrType) as? NSNumber else { NSLog("输入格式校验不通过,驳回") renderWithAttribute() return } - guard let expectedValue = LKDashboardModification.numberValue(parsed, for: attribute) else { + guard let expectedValue = DashboardModification.numberValue(parsed, for: attribute) else { NSLog("修改没有变化,不做任何提交") renderWithAttribute() return diff --git a/LookInside/Dashboard/AttributeView/LKDashboardAttributePrivateDiscriminatorView.swift b/LookInside/Dashboard/AttributeView/DashboardAttributePrivateDiscriminatorView.swift similarity index 87% rename from LookInside/Dashboard/AttributeView/LKDashboardAttributePrivateDiscriminatorView.swift rename to LookInside/Dashboard/AttributeView/DashboardAttributePrivateDiscriminatorView.swift index 0cbef9b6..0a9d7f00 100644 --- a/LookInside/Dashboard/AttributeView/LKDashboardAttributePrivateDiscriminatorView.swift +++ b/LookInside/Dashboard/AttributeView/DashboardAttributePrivateDiscriminatorView.swift @@ -1,5 +1,5 @@ // -// LKDashboardAttributePrivateDiscriminatorView.swift +// DashboardAttributePrivateDiscriminatorView.swift // LookInside // // The Swift private-discriminator card: the hash ID, and its module and @@ -9,7 +9,7 @@ import AppKit -private enum LKPrivateDiscriminatorMetrics { +private enum PrivateDiscriminatorMetrics { static let rowTitleWidth: CGFloat = 64 static let cardPaddingLeft: CGFloat = 8 static let cardPaddingRight: CGFloat = 4 @@ -21,13 +21,13 @@ private enum LKPrivateDiscriminatorMetrics { } /// A value that copies itself when clicked. -private final class LKPrivateDiscriminatorCopyLabel: LKLabel { +private final class PrivateDiscriminatorCopyLabel: TextLabel { var fieldName: String? - var onCopy: ((LKPrivateDiscriminatorCopyLabel) -> Void)? + var onCopy: ((PrivateDiscriminatorCopyLabel) -> Void)? override init(frame frameRect: NSRect) { super.init(frame: frameRect) - font = LKDashboardStyle.font(12) + font = DashboardStyle.font(12) textColor = NSColor(named: "DashboardCardValueColor") lineBreakMode = .byCharWrapping maximumNumberOfLines = 0 @@ -53,40 +53,40 @@ private final class LKPrivateDiscriminatorCopyLabel: LKLabel { } @objc(LKDashboardAttributePrivateDiscriminatorView) -final class LKDashboardAttributePrivateDiscriminatorView: LKDashboardAttributeView { - private typealias Metrics = LKPrivateDiscriminatorMetrics +final class DashboardAttributePrivateDiscriminatorView: DashboardAttributeView { + private typealias Metrics = PrivateDiscriminatorMetrics private static let dashboardStateDidChangeNotification = Notification.Name("LKPrivateDiscriminatorDashboardStateDidChange") - private let idCard = LKBaseView() - private let idTitleLabel = LKLabel() - private let idValueLabel = LKPrivateDiscriminatorCopyLabel() + private let idCard = BaseView() + private let idTitleLabel = TextLabel() + private let idValueLabel = PrivateDiscriminatorCopyLabel() private var idCopyButton: NSButton! - private let moduleCard = LKBaseView() - private let moduleTitleLabel = LKLabel() + private let moduleCard = BaseView() + private let moduleTitleLabel = TextLabel() private let moduleField = NSTextField() - private let moduleValueLabel = LKPrivateDiscriminatorCopyLabel() + private let moduleValueLabel = PrivateDiscriminatorCopyLabel() private var moduleCopyButton: NSButton! - private let filenameCard = LKBaseView() - private let filenameTitleLabel = LKLabel() + private let filenameCard = BaseView() + private let filenameTitleLabel = TextLabel() private let filenameField = NSTextField() - private let filenameValueLabel = LKPrivateDiscriminatorCopyLabel() + private let filenameValueLabel = PrivateDiscriminatorCopyLabel() private var filenameCopyButton: NSButton! - private let sourceLabel = LKLabel() - private let messageLabel = LKLabel() + private let sourceLabel = TextLabel() + private let messageLabel = TextLabel() private var importButton: NSButton! private var guessButton: NSButton! private var cancelButton: NSButton! - private let toastView = LKBaseView() - private let toastLabel = LKLabel() + private let toastView = BaseView() + private let toastLabel = TextLabel() private var hideToastWorkItem: DispatchWorkItem? - private var payload: LKPrivateDiscriminatorDashboardPayload? + private var payload: PrivateDiscriminatorDashboardPayload? private var localMessage: String? private var localMessageIsError = false private var stateObserver: NSObjectProtocol? @@ -120,25 +120,25 @@ final class LKDashboardAttributePrivateDiscriminatorView: LKDashboardAttributeVi filenameCard.addSubview(filenameValueLabel) filenameCard.addSubview(filenameCopyButton) - sourceLabel.font = LKDashboardStyle.font(11) + sourceLabel.font = DashboardStyle.font(11) sourceLabel.textColor = NSColor(named: "DashboardInputAccessoryColor") sourceLabel.maximumNumberOfLines = 0 sourceLabel.lineBreakMode = .byWordWrapping - messageLabel.font = LKDashboardStyle.font(11) + messageLabel.font = DashboardStyle.font(11) messageLabel.maximumNumberOfLines = 0 messageLabel.lineBreakMode = .byWordWrapping importButton = NSButton.lk_normalButton(withTitle: NSLocalizedString("Import from your codebase", comment: ""), target: self, action: #selector(handleImportButton(_:))) - importButton.font = LKDashboardStyle.font(12) + importButton.font = DashboardStyle.font(12) guessButton = NSButton.lk_normalButton(withTitle: NSLocalizedString("Guess by swift-pd-guess", comment: ""), target: self, action: #selector(handleGuessButton(_:))) - guessButton.font = LKDashboardStyle.font(12) + guessButton.font = DashboardStyle.font(12) cancelButton = NSButton.lk_normalButton(withTitle: NSLocalizedString("Cancel", comment: ""), target: self, action: #selector(handleCancelButton(_:))) - cancelButton.font = LKDashboardStyle.font(12) + cancelButton.font = DashboardStyle.font(12) - toastView.layer?.cornerRadius = LKDashboardMetrics.cardControlCornerRadius + toastView.layer?.cornerRadius = DashboardMetrics.cardControlCornerRadius toastView.isHidden = true toastView.alphaValue = 0 @@ -181,7 +181,7 @@ final class LKDashboardAttributePrivateDiscriminatorView: LKDashboardAttributeVi override func renderWithAttribute() { super.renderWithAttribute() - payload = attribute?.value as? LKPrivateDiscriminatorDashboardPayload + payload = attribute?.value as? PrivateDiscriminatorDashboardPayload idValueLabel.stringValue = payload?.discriminatorID ?? "" moduleField.stringValue = payload?.module ?? "" @@ -233,7 +233,7 @@ final class LKDashboardAttributePrivateDiscriminatorView: LKDashboardAttributeVi return max(width, 1) } - private func cardHeight(for label: LKPrivateDiscriminatorCopyLabel, cardWidth: CGFloat, copyHidden: Bool) -> CGFloat { + private func cardHeight(for label: PrivateDiscriminatorCopyLabel, cardWidth: CGFloat, copyHidden: Bool) -> CGFloat { let width = valueWidth(forCardWidth: cardWidth, copyHidden: copyHidden) let valueHeight = max(18, label.sizeThatFits(NSSize(width: width, height: .greatestFiniteMagnitude)).height) return max(valueHeight + Metrics.cardVerticalPadding * 2, Metrics.rowMinHeight) @@ -257,7 +257,7 @@ final class LKDashboardAttributePrivateDiscriminatorView: LKDashboardAttributeVi super.layout() let width = max(frame.width, 1) - let verSpacing = LKDashboardMetrics.attrItemVerInterspace + let verSpacing = DashboardMetrics.attrItemVerInterspace var y: CGFloat = 0 let idHeight = cardHeight(for: idValueLabel, cardWidth: width, copyHidden: idCopyButton.isHidden) @@ -300,7 +300,7 @@ final class LKDashboardAttributePrivateDiscriminatorView: LKDashboardAttributeVi } } - private func layoutCard(_ card: LKBaseView, titleLabel: LKLabel, field: NSTextField?, valueLabel: LKPrivateDiscriminatorCopyLabel, copyButton: NSButton) { + private func layoutCard(_ card: BaseView, titleLabel: TextLabel, field: NSTextField?, valueLabel: PrivateDiscriminatorCopyLabel, copyButton: NSButton) { let cardWidth = card.frame.width let cardHeight = card.frame.height let fieldVisible = field.map { !$0.isHidden } ?? false @@ -333,7 +333,7 @@ final class LKDashboardAttributePrivateDiscriminatorView: LKDashboardAttributeVi override func sizeThatFits(_ limitedSize: NSSize) -> NSSize { let width = max(limitedSize.width, 1) - let verSpacing = LKDashboardMetrics.attrItemVerInterspace + let verSpacing = DashboardMetrics.attrItemVerInterspace var height: CGFloat = 0 height += cardHeight(for: idValueLabel, cardWidth: width, copyHidden: idCopyButton.isHidden) @@ -378,7 +378,7 @@ final class LKDashboardAttributePrivateDiscriminatorView: LKDashboardAttributeVi @objc private func submitManualValue(_: Any?) { guard let payload, !payload.isMatched, let item = attribute?.targetDisplayItem else { return } var error: NSError? - let saved = LKPrivateDiscriminatorStore.shared.submitPrivateDiscriminator(for: item, module: moduleField.stringValue, filename: filenameField.stringValue, error: &error) + let saved = PrivateDiscriminatorStore.shared.submitPrivateDiscriminator(for: item, module: moduleField.stringValue, filename: filenameField.stringValue, error: &error) if saved { localMessage = NSLocalizedString("Saved.", comment: "") localMessageIsError = false @@ -395,7 +395,7 @@ final class LKDashboardAttributePrivateDiscriminatorView: LKDashboardAttributeVi @objc private func handleImportButton(_: NSButton) { guard let item = attribute?.targetDisplayItem else { return } var error: NSError? - let imported = LKPrivateDiscriminatorStore.shared.importPrivateDiscriminatorFromCodebase(for: item, window: window, error: &error) + let imported = PrivateDiscriminatorStore.shared.importPrivateDiscriminatorFromCodebase(for: item, window: window, error: &error) if imported { localMessage = nil dashboardViewController?.reloadCurrentDisplayItem() @@ -409,13 +409,13 @@ final class LKDashboardAttributePrivateDiscriminatorView: LKDashboardAttributeVi @objc private func handleGuessButton(_: NSButton) { guard let item = attribute?.targetDisplayItem else { return } - LKPrivateDiscriminatorStore.shared.beginSwiftPDGuess(for: item, window: window) + PrivateDiscriminatorStore.shared.beginSwiftPDGuess(for: item, window: window) dashboardViewController?.reloadCurrentDisplayItem() } @objc private func handleCancelButton(_: NSButton) { guard let item = attribute?.targetDisplayItem else { return } - LKPrivateDiscriminatorStore.shared.cancelSwiftPDGuess(for: item) + PrivateDiscriminatorStore.shared.cancelSwiftPDGuess(for: item) } @objc private func handleCopyButton(_ button: NSButton) { @@ -439,15 +439,15 @@ final class LKDashboardAttributePrivateDiscriminatorView: LKDashboardAttributeVi // MARK: - Views - private func setUpCard(_ card: LKBaseView, titleLabel: LKLabel, title: String) { - card.layer?.cornerRadius = LKDashboardMetrics.cardControlCornerRadius + private func setUpCard(_ card: BaseView, titleLabel: TextLabel, title: String) { + card.layer?.cornerRadius = DashboardMetrics.cardControlCornerRadius card.backgroundColorName = "DashboardCardValueBGColor" titleLabel.stringValue = title - titleLabel.font = LKDashboardStyle.font(11) + titleLabel.font = DashboardStyle.font(11) titleLabel.textColor = NSColor(named: "DashboardInputAccessoryColor") } - private func setUpCopyLabel(_ label: LKPrivateDiscriminatorCopyLabel, name: String) { + private func setUpCopyLabel(_ label: PrivateDiscriminatorCopyLabel, name: String) { label.fieldName = name label.onCopy = { [weak self] label in self?.copy(label.stringValue, sourceView: label) @@ -465,7 +465,7 @@ final class LKDashboardAttributePrivateDiscriminatorView: LKDashboardAttributeVi private func setUpTextField(_ field: NSTextField, placeholder: String) { field.placeholderString = placeholder - field.font = LKDashboardStyle.font(12) + field.font = DashboardStyle.font(12) field.isBezeled = false field.drawsBackground = false field.textColor = NSColor(named: "DashboardCardValueColor") diff --git a/LookInside/Dashboard/AttributeView/LKDashboardAttributeStringArrayView.swift b/LookInside/Dashboard/AttributeView/DashboardAttributeStringArrayView.swift similarity index 85% rename from LookInside/Dashboard/AttributeView/LKDashboardAttributeStringArrayView.swift rename to LookInside/Dashboard/AttributeView/DashboardAttributeStringArrayView.swift index c15c7d3f..fb776393 100644 --- a/LookInside/Dashboard/AttributeView/LKDashboardAttributeStringArrayView.swift +++ b/LookInside/Dashboard/AttributeView/DashboardAttributeStringArrayView.swift @@ -1,5 +1,5 @@ // -// LKDashboardAttributeStringArrayView.swift +// DashboardAttributeStringArrayView.swift // LookInside // // Created by Li Kai on 2019/6/15. @@ -10,10 +10,10 @@ import AppKit /// A list of selectable texts separated by hairlines: the class chain and /// the relations of an object. -class LKDashboardAttributeStringArrayView: LKDashboardAttributeView { +class DashboardAttributeStringArrayView: DashboardAttributeView { private let labelsVerInterSpace: CGFloat = 10 - private var labels: [LKLabel] = [] + private var labels: [TextLabel] = [] private var sepLayers: [CALayer] = [] private var danceButton: NSButton? @@ -65,7 +65,7 @@ class LKDashboardAttributeStringArrayView: LKDashboardAttributeView { labels.removeLast().removeFromSuperview() } while labels.count < list.count { - let label = LKLabel() + let label = TextLabel() label.lineBreakStrategy = [] label.isSelectable = true label.allowsEditingTextAttributes = true @@ -73,7 +73,7 @@ class LKDashboardAttributeStringArrayView: LKDashboardAttributeView { labels.append(label) } for (label, string) in zip(labels, list) { - label.attributedStringValue = LKDashboardText.attributed(string, font: LKDashboardStyle.font(12), color: .labelColor, lineHeight: 18) + label.attributedStringValue = DashboardText.attributed(string, font: DashboardStyle.font(12), color: .labelColor, lineHeight: 18) } let separatorCount = list.count > 1 ? list.count - 1 : 0 @@ -102,7 +102,7 @@ class LKDashboardAttributeStringArrayView: LKDashboardAttributeView { override func updateColors() { super.updateColors() - let color = LKDashboardStyle.separatorColor(isDarkMode: isDarkMode()).cgColor + let color = DashboardStyle.separatorColor(isDarkMode: isDarkMode()).cgColor for sepLayer in sepLayers { sepLayer.backgroundColor = color } @@ -118,7 +118,7 @@ class LKDashboardAttributeStringArrayView: LKDashboardAttributeView { return danceButton } let button = NSButton.lk_normalButton(withTitle: "", target: self, action: #selector(handleDanceButton)) - button.font = LKDashboardStyle.font(12) + button.font = DashboardStyle.font(12) addSubview(button) danceButton = button return button @@ -131,11 +131,11 @@ class LKDashboardAttributeStringArrayView: LKDashboardAttributeView { /// The class chain of the object, one class list per entry, demangled. @objc(LKDashboardAttributeClassView) -final class LKDashboardAttributeClassView: LKDashboardAttributeStringArrayView { +final class DashboardAttributeClassView: DashboardAttributeStringArrayView { override func stringList(with attribute: InspectedAttribute) -> [String] { let lists = attribute.value as? [[String]] ?? [] return lists.map { rawClassList in - rawClassList.map { LKSwiftDemangler.completedParse(input: $0) }.joined(separator: "\n") + rawClassList.map { SwiftDemangler.completedParse(input: $0) }.joined(separator: "\n") } } } @@ -143,7 +143,7 @@ final class LKDashboardAttributeClassView: LKDashboardAttributeStringArrayView { /// The relations of the object ("(AAA : BBB *)" and "(AAA *)" texts), with /// the Swift class names demangled. Cached on the attribute. @objc(LKDashboardAttributeRelationView) -final class LKDashboardAttributeRelationView: LKDashboardAttributeStringArrayView { +final class DashboardAttributeRelationView: DashboardAttributeStringArrayView { private static let cacheKey = "cachedDemangled" private static let memberRegex = try! NSRegularExpression(pattern: #"\(\s*(\w+)\s*:\s*(\w+)\s*\*\s*\)"#) @@ -169,8 +169,8 @@ final class LKDashboardAttributeRelationView: LKDashboardAttributeStringArrayVie let range2 = match.range(at: 2) let substring1 = text.substring(with: range1) let substring2 = text.substring(with: range2) - let demangled1 = LKSwiftDemangler.simpleParse(input: substring1) - let demangled2 = LKSwiftDemangler.simpleParse(input: substring2) + let demangled1 = SwiftDemangler.simpleParse(input: substring1) + let demangled2 = SwiftDemangler.simpleParse(input: substring2) let replaced = text.replacingCharacters(in: range1, with: demangled1) as NSString return replaced.replacingOccurrences(of: substring2, with: demangled2) } @@ -178,7 +178,7 @@ final class LKDashboardAttributeRelationView: LKDashboardAttributeStringArrayVie // "(AAA *)" if let match = objectRegex.firstMatch(in: rawText, range: fullRange) { let range = match.range(at: 1) - let demangled = LKSwiftDemangler.simpleParse(input: text.substring(with: range)) + let demangled = SwiftDemangler.simpleParse(input: text.substring(with: range)) return text.replacingCharacters(in: range, with: demangled) } diff --git a/LookInside/Dashboard/AttributeView/LKDashboardAttributeSwitchView.swift b/LookInside/Dashboard/AttributeView/DashboardAttributeSwitchView.swift similarity index 83% rename from LookInside/Dashboard/AttributeView/LKDashboardAttributeSwitchView.swift rename to LookInside/Dashboard/AttributeView/DashboardAttributeSwitchView.swift index 20664bcc..02b70839 100644 --- a/LookInside/Dashboard/AttributeView/LKDashboardAttributeSwitchView.swift +++ b/LookInside/Dashboard/AttributeView/DashboardAttributeSwitchView.swift @@ -1,5 +1,5 @@ // -// LKDashboardAttributeSwitchView.swift +// DashboardAttributeSwitchView.swift // LookInside // // Created by Li Kai on 2019/2/21. @@ -10,7 +10,7 @@ import AppKit /// A BOOL attribute as a checkbox. @objc(LKDashboardAttributeSwitchView) -final class LKDashboardAttributeSwitchView: LKDashboardAttributeView { +final class DashboardAttributeSwitchView: DashboardAttributeView { private let button = NSButton() required init(frame frameRect: NSRect) { @@ -19,7 +19,7 @@ final class LKDashboardAttributeSwitchView: LKDashboardAttributeView { button.setButtonType(.switch) button.target = self button.action = #selector(handleButton) - button.font = LKDashboardStyle.font(13) + button.font = DashboardStyle.font(13) addSubview(button) } @@ -40,7 +40,7 @@ final class LKDashboardAttributeSwitchView: LKDashboardAttributeView { } else { title = DashboardBlueprint.briefTitle(withAttrID: attribute.identifier) } - button.attributedTitle = LKDashboardText.attributed(title ?? "", color: NSColor(named: "DashboardCardValueColor")) + button.attributedTitle = DashboardText.attributed(title ?? "", color: NSColor(named: "DashboardCardValueColor")) let isOn = (attribute.value as? NSNumber)?.boolValue ?? false button.state = isOn ? .on : .off @@ -70,9 +70,9 @@ final class LKDashboardAttributeSwitchView: LKDashboardAttributeView { let expectedValue: NSNumber switch button.state { case .off: - expectedValue = LKDashboardModification.boolValue(isOn: false) + expectedValue = DashboardModification.boolValue(isOn: false) case .on: - expectedValue = LKDashboardModification.boolValue(isOn: true) + expectedValue = DashboardModification.boolValue(isOn: true) default: assertionFailure() return diff --git a/LookInside/Dashboard/AttributeView/LKDashboardAttributeTextView.swift b/LookInside/Dashboard/AttributeView/DashboardAttributeTextView.swift similarity index 85% rename from LookInside/Dashboard/AttributeView/LKDashboardAttributeTextView.swift rename to LookInside/Dashboard/AttributeView/DashboardAttributeTextView.swift index 27af321c..0ef6f34a 100644 --- a/LookInside/Dashboard/AttributeView/LKDashboardAttributeTextView.swift +++ b/LookInside/Dashboard/AttributeView/DashboardAttributeTextView.swift @@ -1,5 +1,5 @@ // -// LKDashboardAttributeTextView.swift +// DashboardAttributeTextView.swift // LookInside // // Created by Li Kai on 2019/9/16. @@ -11,8 +11,8 @@ import AppKit /// A string attribute in an editable text view. SwiftUI attributes that /// name another node get a button that jumps to it. @objc(LKDashboardAttributeTextView) -final class LKDashboardAttributeTextView: LKDashboardAttributeView, NSTextViewDelegate { - private let titleLabel = LKLabel() +final class DashboardAttributeTextView: DashboardAttributeView, NSTextViewDelegate { + private let titleLabel = TextLabel() private let scrollView: NSScrollView private let textView: NSTextView private var jumpButton: NSButton! @@ -20,14 +20,14 @@ final class LKDashboardAttributeTextView: LKDashboardAttributeView, NSTextViewDe private var initialText = "" required init(frame frameRect: NSRect) { - scrollView = LKHelper.scrollableTextView() + scrollView = AppHelper.scrollableTextView() textView = scrollView.documentView as! NSTextView super.init(frame: frameRect) - layer?.cornerRadius = LKDashboardMetrics.cardControlCornerRadius + layer?.cornerRadius = DashboardMetrics.cardControlCornerRadius titleLabel.textColor = NSColor(named: "DashboardInputAccessoryColor") - titleLabel.font = LKDashboardStyle.font(10) + titleLabel.font = DashboardStyle.font(10) titleLabel.maximumNumberOfLines = 1 titleLabel.isHidden = true addSubview(titleLabel) @@ -35,13 +35,13 @@ final class LKDashboardAttributeTextView: LKDashboardAttributeView, NSTextViewDe scrollView.drawsBackground = false scrollView.hasVerticalScroller = false scrollView.hasHorizontalScroller = false - textView.font = LKDashboardStyle.font(12) + textView.font = DashboardStyle.font(12) textView.drawsBackground = false textView.textContainerInset = NSSize(width: 2, height: 4) textView.delegate = self addSubview(scrollView) - jumpButton = NSButton(image: LKDashboardStyle.image("Icon_JumpDisclosure") ?? NSImage(), target: self, action: #selector(handleJumpButton(_:))) + jumpButton = NSButton(image: DashboardStyle.image("Icon_JumpDisclosure") ?? NSImage(), target: self, action: #selector(handleJumpButton(_:))) jumpButton.bezelStyle = .roundRect jumpButton.isBordered = false jumpButton.toolTip = NSLocalizedString("Jump in hierarchy", comment: "") @@ -59,7 +59,7 @@ final class LKDashboardAttributeTextView: LKDashboardAttributeView, NSTextViewDe if titleLabel.isHidden { scrollView.dashboardLayout.fullFrame().toRight(jumpButtonWidth) } else { - let titleHeight = titleLabel.sizeThatFits(LKDashboardMetrics.maxSize).height + let titleHeight = titleLabel.sizeThatFits(DashboardMetrics.maxSize).height titleLabel.dashboardLayout.x(7).toRight(7).heightToFit().y(4) scrollView.dashboardLayout.x(0).toRight(jumpButtonWidth).y(4 + titleHeight + 1).toBottom(0) } @@ -96,7 +96,7 @@ final class LKDashboardAttributeTextView: LKDashboardAttributeView, NSTextViewDe var textHeight = min(max(contentHeight, 24), 80) if !titleLabel.isHidden { - let titleHeight = titleLabel.sizeThatFits(LKDashboardMetrics.maxSize).height + let titleHeight = titleLabel.sizeThatFits(DashboardMetrics.maxSize).height textHeight += 3 + titleHeight + 1 } diff --git a/LookInside/Dashboard/AttributeView/LKDashboardAttributeView.swift b/LookInside/Dashboard/AttributeView/DashboardAttributeView.swift similarity index 92% rename from LookInside/Dashboard/AttributeView/LKDashboardAttributeView.swift rename to LookInside/Dashboard/AttributeView/DashboardAttributeView.swift index 74e39937..f860904c 100644 --- a/LookInside/Dashboard/AttributeView/LKDashboardAttributeView.swift +++ b/LookInside/Dashboard/AttributeView/DashboardAttributeView.swift @@ -1,5 +1,5 @@ // -// LKDashboardAttributeView.swift +// DashboardAttributeView.swift // LookInside // // Created by Li Kai on 2018/11/18. @@ -12,13 +12,13 @@ import AppKit /// size themselves through `sizeThatFits(_:)` and say how many of them fit /// in a row. @objc(LKDashboardAttributeView) -class LKDashboardAttributeView: LKBaseView { +class DashboardAttributeView: BaseView { /// Setting the attribute renders it. @objc var attribute: InspectedAttribute? { didSet { renderWithAttribute() } } - @objc weak var dashboardViewController: LKDashboardViewController? { + @objc weak var dashboardViewController: DashboardViewController? { didSet { dashboardViewControllerDidChange() } } @@ -91,9 +91,9 @@ class LKDashboardAttributeView: LKBaseView { /// fields ignore that second end-of-editing so the value is not submitted /// twice. @objc(LKDashboardTextControlEditingFlag) -final class LKDashboardTextControlEditingFlag: NSObject { +final class DashboardTextControlEditingFlag: NSObject { @objc(sharedInstance) - static let shared = LKDashboardTextControlEditingFlag() + static let shared = DashboardTextControlEditingFlag() @objc var shouldIgnoreTextEditingChangeEvent = false diff --git a/LookInside/Dashboard/AttributeView/JSON/LKJSONAttributeItem.swift b/LookInside/Dashboard/AttributeView/JSON/JSONAttributeItem.swift similarity index 79% rename from LookInside/Dashboard/AttributeView/JSON/LKJSONAttributeItem.swift rename to LookInside/Dashboard/AttributeView/JSON/JSONAttributeItem.swift index 014b4b39..a4d79dd1 100644 --- a/LookInside/Dashboard/AttributeView/JSON/LKJSONAttributeItem.swift +++ b/LookInside/Dashboard/AttributeView/JSON/JSONAttributeItem.swift @@ -1,5 +1,5 @@ // -// LKJSONAttributeItem.swift +// JSONAttributeItem.swift // LookInside // // Created by likai.123 on 2023/12/4. @@ -11,16 +11,16 @@ import Foundation -final class LKJSONAttributeItem { +final class JSONAttributeItem { var titleText: String? var desc: String? var expanded = true var indentation = 0 - var subItems: [LKJSONAttributeItem] = [] + var subItems: [JSONAttributeItem] = [] /// The item, then (when expanded) its sub-items' flat items, each one /// indented one level deeper than its parent. - func flatItems() -> [LKJSONAttributeItem] { + func flatItems() -> [JSONAttributeItem] { var array = [self] if expanded { for item in subItems { @@ -33,7 +33,7 @@ final class LKJSONAttributeItem { /// The root items of `json`; nil when it is nil, not valid JSON, or not /// an array. Entries that are not objects are skipped. - static func rootItems(fromJSON json: String?) -> [LKJSONAttributeItem]? { + static func rootItems(fromJSON json: String?) -> [JSONAttributeItem]? { guard let json else { return nil } let object: Any do { @@ -46,11 +46,11 @@ final class LKJSONAttributeItem { return items(from: object) } - private static func items(from rawArray: Any?) -> [LKJSONAttributeItem]? { + private static func items(from rawArray: Any?) -> [JSONAttributeItem]? { guard let rawArray = rawArray as? [Any] else { return nil } return rawArray.compactMap { element in guard let dict = element as? [String: Any] else { return nil } - let item = LKJSONAttributeItem() + let item = JSONAttributeItem() item.titleText = dict["title"] as? String item.desc = dict["desc"] as? String item.expanded = true @@ -60,7 +60,7 @@ final class LKJSONAttributeItem { } /// The rows to show for `rootItems`. - static func flatItems(of rootItems: [LKJSONAttributeItem]?) -> [LKJSONAttributeItem] { + static func flatItems(of rootItems: [JSONAttributeItem]?) -> [JSONAttributeItem] { (rootItems ?? []).flatMap { $0.flatItems() } } } diff --git a/LookInside/Dashboard/AttributeView/JSON/LKJSONAttributeViews.swift b/LookInside/Dashboard/AttributeView/JSON/LKJSONAttributeViews.swift index 5596dfab..9c90cd36 100644 --- a/LookInside/Dashboard/AttributeView/JSON/LKJSONAttributeViews.swift +++ b/LookInside/Dashboard/AttributeView/JSON/LKJSONAttributeViews.swift @@ -11,33 +11,33 @@ import AppKit /// The JSON tree rows of the card, flush with the card's left edge. -private final class LKJSONAttributeContentRowView: LKOutlineRowView { +private final class JSONAttributeContentRowView: OutlineRowView { override class func insetLeft() -> CGFloat { 0 } } /// The tree of rows shared by the card and the window. -private final class LKJSONAttributeTree { - var rootItems: [LKJSONAttributeItem]? - private(set) var flatItems: [LKJSONAttributeItem] = [] +private final class JSONAttributeTree { + var rootItems: [JSONAttributeItem]? + private(set) var flatItems: [JSONAttributeItem] = [] func render(json: String?) { - rootItems = LKJSONAttributeItem.rootItems(fromJSON: json) + rootItems = JSONAttributeItem.rootItems(fromJSON: json) rebuild() } func rebuild() { - flatItems = LKJSONAttributeItem.flatItems(of: rootItems) + flatItems = JSONAttributeItem.flatItems(of: rootItems) } - func item(at row: Int) -> LKJSONAttributeItem? { + func item(at row: Int) -> JSONAttributeItem? { flatItems.indices.contains(row) ? flatItems[row] : nil } /// Fills a row with `item`: title, description, indentation and /// disclosure state. - static func configure(_ view: LKOutlineRowView, row: Int, with item: LKJSONAttributeItem) { + static func configure(_ view: OutlineRowView, row: Int, with item: JSONAttributeItem) { view.titleLabel.stringValue = item.titleText ?? "" view.subtitleLabel.stringValue = item.desc ?? "" view.disclosureButton.tag = row @@ -61,11 +61,11 @@ private final class LKJSONAttributeTree { /// The tree on a Dashboard card. @objc(LKJSONAttributeContentView) -final class LKJSONAttributeContentView: LKBaseView, LKTableViewDelegate, LKTableViewDataSource { +final class JSONAttributeContentView: BaseView, TableViewDelegate, TableViewDataSource { private static let rowIdentifier = NSUserInterfaceItemIdentifier("myView") - private let tableView = LKTableView() - private let tree = LKJSONAttributeTree() + private let tableView = TableView() + private let tree = JSONAttributeTree() private let rowHeight: CGFloat /// Never set: the rows use the small font even in the big-font layout, /// as they always have. @@ -110,7 +110,7 @@ final class LKJSONAttributeContentView: LKBaseView, LKTableViewDelegate, LKTable CGFloat(tree.flatItems.count) * rowHeight } - // MARK: - LKTableView + // MARK: - TableView func numberOfRows(in _: NSTableView) -> Int { tree.flatItems.count @@ -122,13 +122,13 @@ final class LKJSONAttributeContentView: LKBaseView, LKTableViewDelegate, LKTable func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? { guard let item = tree.item(at: row) else { - return LKTableBlankRowView() + return TableBlankRowView() } - let view: LKOutlineRowView - if let reused = tableView.makeView(withIdentifier: Self.rowIdentifier, owner: self) as? LKOutlineRowView { + let view: OutlineRowView + if let reused = tableView.makeView(withIdentifier: Self.rowIdentifier, owner: self) as? OutlineRowView { view = reused } else { - view = LKJSONAttributeContentRowView(compactUI: true) + view = JSONAttributeContentRowView(compactUI: true) view.titleLabel.textColor = .secondaryLabelColor let fontSize: CGFloat = useBigFont ? 14 : 12 view.titleLabel.font = .monospacedDigitSystemFont(ofSize: fontSize, weight: .regular) @@ -140,7 +140,7 @@ final class LKJSONAttributeContentView: LKBaseView, LKTableViewDelegate, LKTable view.disclosureButton.action = #selector(handleExpand(_:)) view.identifier = Self.rowIdentifier } - LKJSONAttributeTree.configure(view, row: row, with: item) + JSONAttributeTree.configure(view, row: row, with: item) return view } @@ -154,12 +154,12 @@ final class LKJSONAttributeContentView: LKBaseView, LKTableViewDelegate, LKTable /// A JSON attribute on a card; the section's pop-out button shows it in a /// window. @objc(LKDashboardAttributeJsonView) -final class LKDashboardAttributeJsonView: LKDashboardAttributeView { - private let contentView = LKJSONAttributeContentView(bigFont: false) +final class DashboardAttributeJSONView: DashboardAttributeView { + private let contentView = JSONAttributeContentView(bigFont: false) required init(frame frameRect: NSRect) { super.init(frame: frameRect) - layer?.cornerRadius = LKDashboardMetrics.cardControlCornerRadius + layer?.cornerRadius = DashboardMetrics.cardControlCornerRadius contentView.didReloadData = { [weak self] in self?.dashboardViewController?.view.needsLayout = true } @@ -195,22 +195,22 @@ final class LKDashboardAttributeJsonView: LKDashboardAttributeView { assertionFailure() return } - LKNavigationManager.shared.showJSONWindow(json) + NavigationManager.shared.showJSONWindow(json) } } /// The JSON tree in a window of its own, with the bigger font. @objc(LKJSONAttributeViewController) -final class LKJSONAttributeViewController: LKBaseViewController, LKTableViewDelegate, LKTableViewDataSource { +final class JSONAttributeViewController: BaseViewController, TableViewDelegate, TableViewDataSource { private static let rowIdentifier = NSUserInterfaceItemIdentifier("myView") - private var tableView: LKTableView! - private let tree = LKJSONAttributeTree() + private var tableView: TableView! + private let tree = JSONAttributeTree() override func makeContainerView() -> NSView { - let containerView = LKBaseView() + let containerView = BaseView() - let tableView = LKTableView() + let tableView = TableView() tableView.drawsBackground = false tableView.delegate = self tableView.dataSource = self @@ -236,7 +236,7 @@ final class LKJSONAttributeViewController: LKBaseViewController, LKTableViewDele tableView.reloadData() } - // MARK: - LKTableView + // MARK: - TableView func numberOfRows(in _: NSTableView) -> Int { tree.flatItems.count @@ -248,13 +248,13 @@ final class LKJSONAttributeViewController: LKBaseViewController, LKTableViewDele func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? { guard let item = tree.item(at: row) else { - return LKTableBlankRowView() + return TableBlankRowView() } - let view: LKOutlineRowView - if let reused = tableView.makeView(withIdentifier: Self.rowIdentifier, owner: self) as? LKOutlineRowView { + let view: OutlineRowView + if let reused = tableView.makeView(withIdentifier: Self.rowIdentifier, owner: self) as? OutlineRowView { view = reused } else { - view = LKOutlineRowView() + view = OutlineRowView() view.titleLabel.textColor = .secondaryLabelColor view.titleLabel.font = .monospacedDigitSystemFont(ofSize: 14, weight: .regular) view.titleLabel.isSelectable = true @@ -265,7 +265,7 @@ final class LKJSONAttributeViewController: LKBaseViewController, LKTableViewDele view.disclosureButton.action = #selector(handleExpand(_:)) view.identifier = Self.rowIdentifier } - LKJSONAttributeTree.configure(view, row: row, with: item) + JSONAttributeTree.configure(view, row: row, with: item) return view } @@ -275,11 +275,11 @@ final class LKJSONAttributeViewController: LKBaseViewController, LKTableViewDele } } -/// The window of `LKJSONAttributeViewController`. +/// The window of `JSONAttributeViewController`. @objc(LKJSONAttributeWindowController) -final class LKJSONAttributeWindowController: LKWindowController { +final class JSONAttributeWindowController: WindowController { @objc convenience init() { - let window = LKWindow( + let window = AppWindow( contentRect: NSRect(x: 0, y: 0, width: 600, height: 320), styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView], backing: .buffered, @@ -292,7 +292,7 @@ final class LKJSONAttributeWindowController: LKWindowController { self.init(window: window) - let viewController = LKJSONAttributeViewController() + let viewController = JSONAttributeViewController() window.contentView = viewController.view contentViewController = viewController } diff --git a/LookInside/Dashboard/AttributeView/LKDashboardAttributeGeometryViews.swift b/LookInside/Dashboard/AttributeView/LKDashboardAttributeGeometryViews.swift index 77cf88cd..48897db1 100644 --- a/LookInside/Dashboard/AttributeView/LKDashboardAttributeGeometryViews.swift +++ b/LookInside/Dashboard/AttributeView/LKDashboardAttributeGeometryViews.swift @@ -13,18 +13,18 @@ import AppKit /// Number fields, two per row. Subclasses fill them from the attribute's /// `NSValue` and turn an edited field into the value to submit. -class LKDashboardAttributeFieldsView: LKDashboardAttributeView, NSTextFieldDelegate { +class DashboardAttributeFieldsView: DashboardAttributeView, NSTextFieldDelegate { /// The field titles, in field order. class var fieldTitles: [String] { [] } - private(set) var inputViews: [LKNumberInputView] = [] + private(set) var inputViews: [NumberInputView] = [] required init(frame frameRect: NSRect) { super.init(frame: frameRect) inputViews = Self.fieldTitles.map { title in - let view = LKNumberInputView() + let view = NumberInputView() view.title = title view.viewStyle = .horizontal view.textFieldView.textField.delegate = self @@ -44,12 +44,12 @@ class LKDashboardAttributeFieldsView: LKDashboardAttributeView, NSTextFieldDeleg override func layout() { super.layout() - let horSpace = LKDashboardMetrics.attrItemHorInterspace - let rowHeight = LKDashboardMetrics.numberInputHorizontalHeight + let horSpace = DashboardMetrics.attrItemHorInterspace + let rowHeight = DashboardMetrics.numberInputHorizontalHeight let itemWidth = (frame.width - horSpace) / 2.0 for (idx, view) in inputViews.enumerated() { let x = idx % 2 == 0 ? 0 : itemWidth + horSpace - let y = CGFloat(idx / 2) * (rowHeight + LKDashboardMetrics.attrItemVerInterspace) + let y = CGFloat(idx / 2) * (rowHeight + DashboardMetrics.attrItemVerInterspace) view.dashboardLayout.width(itemWidth).height(rowHeight).x(x).y(y) } } @@ -57,7 +57,7 @@ class LKDashboardAttributeFieldsView: LKDashboardAttributeView, NSTextFieldDeleg override func sizeThatFits(_ limitedSize: NSSize) -> NSSize { var size = limitedSize let rows = CGFloat(rowCount) - size.height = LKDashboardMetrics.numberInputHorizontalHeight * rows + LKDashboardMetrics.attrItemVerInterspace * (rows - 1) + size.height = DashboardMetrics.numberInputHorizontalHeight * rows + DashboardMetrics.attrItemVerInterspace * (rows - 1) return size } @@ -102,12 +102,12 @@ class LKDashboardAttributeFieldsView: LKDashboardAttributeView, NSTextFieldDeleg // notification when the field leaves the window or its editable // flag changes, although textShouldBeginEditing refused input. guard canEdit() else { return } - if LKDashboardTextControlEditingFlag.shared.shouldIgnoreTextEditingChangeEvent { + if DashboardTextControlEditingFlag.shared.shouldIgnoreTextEditingChangeEvent { NSLog("忽略 controlTextDidEndEditing 事件,驳回") return } guard let editingTextField = notification.object as? NSTextField, - let parsed = LKNumberInputView.parsedValue(with: editingTextField.stringValue, attrType: .double) as? NSNumber + let parsed = NumberInputView.parsedValue(with: editingTextField.stringValue, attrType: .double) as? NSNumber else { NSLog("输入格式校验不通过,驳回") renderWithAttribute() @@ -131,7 +131,7 @@ class LKDashboardAttributeFieldsView: LKDashboardAttributeView, NSTextFieldDeleg } @objc(LKDashboardAttributeRectView) -final class LKDashboardAttributeRectView: LKDashboardAttributeFieldsView { +final class DashboardAttributeRectView: DashboardAttributeFieldsView { override class var fieldTitles: [String] { ["X", "Y", "W", "H"] } @@ -152,7 +152,7 @@ final class LKDashboardAttributeRectView: LKDashboardAttributeFieldsView { } override func editedValue(from value: NSValue, field index: Int, number: Double) -> NSValue? { - guard let rect = LKDashboardModification.rect(value.rectValue, replacingField: index, with: number) else { + guard let rect = DashboardModification.rect(value.rectValue, replacingField: index, with: number) else { return nil } let newValue = NSValue(rect: rect) @@ -166,11 +166,11 @@ final class LKDashboardAttributeRectView: LKDashboardAttributeFieldsView { do { guard let self, try await self.submit(newValue) else { return } let currentRect = (self.attribute?.value as? NSValue)?.rectValue ?? .zero - if LKDashboardModification.rectEditWasReverted(old: oldRect, expected: expectedRect, current: currentRect) { + if DashboardModification.rectEditWasReverted(old: oldRect, expected: expectedRect, current: currentRect) { // The Server applied the new frame, then the app's own // code (layoutSubviews, for example) set it back. Say so, // or it looks as if the edit failed. - LKDashboardStyle.alert( + DashboardStyle.alert( title: NSLocalizedString("The modification seems to have no effect.", comment: ""), detail: NSLocalizedString("After modifying successfully by LookInside, the value seems to be recovered by the code in your iOS app. For example, modifying \"frame\" of a view may trigger \"layoutSubviews\", and \"layoutSubviews\" may modify the value again.", comment: ""), window: self.window @@ -185,7 +185,7 @@ final class LKDashboardAttributeRectView: LKDashboardAttributeFieldsView { } @objc(LKDashboardAttributeInsetsView) -final class LKDashboardAttributeInsetsView: LKDashboardAttributeFieldsView { +final class DashboardAttributeInsetsView: DashboardAttributeFieldsView { override class var fieldTitles: [String] { ["T", "L", "B", "R"] } @@ -207,8 +207,8 @@ final class LKDashboardAttributeInsetsView: LKDashboardAttributeFieldsView { override func editedValue(from value: NSValue, field index: Int, number: Double) -> NSValue? { let oldInsets = value.edgeInsetsValue - guard let insets = LKDashboardModification.insets(oldInsets, replacingField: index, with: number), - LKDashboardModification.insetsDiffer(oldInsets, insets) + guard let insets = DashboardModification.insets(oldInsets, replacingField: index, with: number), + DashboardModification.insetsDiffer(oldInsets, insets) else { return nil } @@ -217,7 +217,7 @@ final class LKDashboardAttributeInsetsView: LKDashboardAttributeFieldsView { } @objc(LKDashboardAttributePointView) -final class LKDashboardAttributePointView: LKDashboardAttributeFieldsView { +final class DashboardAttributePointView: DashboardAttributeFieldsView { override class var fieldTitles: [String] { ["X", "Y"] } @@ -228,7 +228,7 @@ final class LKDashboardAttributePointView: LKDashboardAttributeFieldsView { } override func editedValue(from value: NSValue, field index: Int, number: Double) -> NSValue? { - guard let point = LKDashboardModification.point(value.pointValue, replacingField: index, with: number) else { + guard let point = DashboardModification.point(value.pointValue, replacingField: index, with: number) else { return nil } let newValue = NSValue(point: point) @@ -237,7 +237,7 @@ final class LKDashboardAttributePointView: LKDashboardAttributeFieldsView { } @objc(LKDashboardAttributeSizeView) -final class LKDashboardAttributeSizeView: LKDashboardAttributeFieldsView { +final class DashboardAttributeSizeView: DashboardAttributeFieldsView { override class var fieldTitles: [String] { ["W", "H"] } @@ -259,7 +259,7 @@ final class LKDashboardAttributeSizeView: LKDashboardAttributeFieldsView { } override func editedValue(from value: NSValue, field index: Int, number: Double) -> NSValue? { - guard let size = LKDashboardModification.size(value.sizeValue, replacingField: index, with: number) else { + guard let size = DashboardModification.size(value.sizeValue, replacingField: index, with: number) else { return nil } let newValue = NSValue(size: size) diff --git a/LookInside/Dashboard/AttributeView/LKDashboardAttributeReadOnlyViews.swift b/LookInside/Dashboard/AttributeView/LKDashboardAttributeReadOnlyViews.swift index 90a81981..92653c1e 100644 --- a/LookInside/Dashboard/AttributeView/LKDashboardAttributeReadOnlyViews.swift +++ b/LookInside/Dashboard/AttributeView/LKDashboardAttributeReadOnlyViews.swift @@ -13,20 +13,20 @@ import AppKit /// The number of rows in each section of a table view. @objc(LKDashboardAttributeRowsCountView) -final class LKDashboardAttributeRowsCountView: LKDashboardAttributeView { - private var inputViews: [LKNumberInputView] = [] +final class DashboardAttributeRowsCountView: DashboardAttributeView { + private var inputViews: [NumberInputView] = [] override func layout() { super.layout() for (idx, view) in inputViews.enumerated() { - let y = CGFloat(idx) * (LKDashboardMetrics.numberInputHorizontalHeight + LKDashboardMetrics.attrItemVerInterspace) - view.dashboardLayout.fullWidth().height(LKDashboardMetrics.numberInputHorizontalHeight).y(y) + let y = CGFloat(idx) * (DashboardMetrics.numberInputHorizontalHeight + DashboardMetrics.attrItemVerInterspace) + view.dashboardLayout.fullWidth().height(DashboardMetrics.numberInputHorizontalHeight).y(y) } } override func sizeThatFits(_ limitedSize: NSSize) -> NSSize { let count = CGFloat(inputViews.count) - let height = (LKDashboardMetrics.numberInputHorizontalHeight + LKDashboardMetrics.attrItemVerInterspace) * count - LKDashboardMetrics.attrItemVerInterspace + let height = (DashboardMetrics.numberInputHorizontalHeight + DashboardMetrics.attrItemVerInterspace) * count - DashboardMetrics.attrItemVerInterspace var size = limitedSize size.height = max(height, 0) return size @@ -41,7 +41,7 @@ final class LKDashboardAttributeRowsCountView: LKDashboardAttributeView { inputViews.removeLast().removeFromSuperview() } while inputViews.count < numbers.count { - let view = LKNumberInputView() + let view = NumberInputView() view.textFieldView.textField.isEditable = false view.viewStyle = .horizontal view.textFieldView.backgroundColorName = "DashboardCardValueBGColor" @@ -64,27 +64,27 @@ final class LKDashboardAttributeRowsCountView: LKDashboardAttributeView { /// A layer shadow: colour, then opacity, radius and offset. @objc(LKDashboardAttributeShadowView) -final class LKDashboardAttributeShadowView: LKDashboardAttributeView { - private let colorContainerView = LKBaseView() - private let colorIndicatorLayer = LKColorIndicatorLayer() - private let colorDescLabel = LKLabel() - private var inputViews: [LKNumberInputView] = [] +final class DashboardAttributeShadowView: DashboardAttributeView { + private let colorContainerView = BaseView() + private let colorIndicatorLayer = ColorIndicatorLayer() + private let colorDescLabel = TextLabel() + private var inputViews: [NumberInputView] = [] private var rgbaFormatObservation: NSKeyValueObservation? required init(frame frameRect: NSRect) { super.init(frame: frameRect) - colorContainerView.layer?.cornerRadius = LKDashboardMetrics.cardControlCornerRadius + colorContainerView.layer?.cornerRadius = DashboardMetrics.cardControlCornerRadius colorContainerView.backgroundColorName = "DashboardCardValueBGColor" addSubview(colorContainerView) colorContainerView.layer?.addSublayer(colorIndicatorLayer) colorDescLabel.textColor = NSColor(named: "DashboardCardValueColor") - colorDescLabel.font = LKDashboardStyle.font(13) + colorDescLabel.font = DashboardStyle.font(13) colorContainerView.addSubview(colorDescLabel) inputViews = ["Opacity", "Radius", "OffsetW", "OffsetH"].map { title in - let view = LKNumberInputView() + let view = NumberInputView() view.textFieldView.textField.isEditable = false view.title = title view.viewStyle = .vertical @@ -93,7 +93,7 @@ final class LKDashboardAttributeShadowView: LKDashboardAttributeView { } // Re-render when the user switches between hex and RGBA. - rgbaFormatObservation = LKPreferenceManager.shared.observe(\.rgbaFormat, options: [.new]) { [weak self] _, _ in + rgbaFormatObservation = PreferenceManager.shared.observe(\.rgbaFormat, options: [.new]) { [weak self] _, _ in lkRunOnMain { self?.renderWithAttribute() } } } @@ -108,19 +108,19 @@ final class LKDashboardAttributeShadowView: LKDashboardAttributeView { colorIndicatorLayer.dashboardLayout.width(16).height(16).x(8).verAlign() colorDescLabel.dashboardLayout.x(28).toRight(20).heightToFit().verAlign().offsetY(-1) - let horSpace = LKDashboardMetrics.attrItemHorInterspace + let horSpace = DashboardMetrics.attrItemHorInterspace let itemWidth = (frame.width - horSpace * 3) / 4.0 - let y = colorContainerView.frame.maxY + LKDashboardMetrics.attrItemVerInterspace + let y = colorContainerView.frame.maxY + DashboardMetrics.attrItemVerInterspace var x: CGFloat = 0 for view in inputViews { - view.dashboardLayout.width(itemWidth).height(LKDashboardMetrics.numberInputVerticalHeight).x(x).y(y) + view.dashboardLayout.width(itemWidth).height(DashboardMetrics.numberInputVerticalHeight).x(x).y(y) x += itemWidth + horSpace } } override func sizeThatFits(_ limitedSize: NSSize) -> NSSize { var size = limitedSize - size.height = 30 + LKDashboardMetrics.attrItemVerInterspace + LKDashboardMetrics.numberInputVerticalHeight + size.height = 30 + DashboardMetrics.attrItemVerInterspace + DashboardMetrics.numberInputVerticalHeight return size } @@ -139,7 +139,7 @@ final class LKDashboardAttributeShadowView: LKDashboardAttributeView { colorIndicatorLayer.color = color if let color { - colorDescLabel.stringValue = LKPreferenceManager.shared.rgbaFormat ? color.rgbaString() : color.hexString() + colorDescLabel.stringValue = PreferenceManager.shared.rgbaFormat ? color.rgbaString() : color.hexString() } else { colorDescLabel.stringValue = "nil" } @@ -156,18 +156,18 @@ final class LKDashboardAttributeShadowView: LKDashboardAttributeView { /// Opens the image of an image view in Preview, fetched from the app (or /// taken from an imported Xcode capture). @objc(LKDashboardAttributeOpenImageView) -final class LKDashboardAttributeOpenImageView: LKDashboardAttributeView { - private let control = LKTextControl() +final class DashboardAttributeOpenImageView: DashboardAttributeView { + private let control = TextControl() required init(frame frameRect: NSRect) { super.init(frame: frameRect) layer?.borderWidth = 1 - layer?.cornerRadius = LKDashboardMetrics.cardControlCornerRadius - borderColors = LKTwoColors(colorInLightMode: LKDashboardStyle.rgb(181, 181, 181), colorInDarkMode: LKDashboardStyle.rgb(83, 83, 83)) + layer?.cornerRadius = DashboardMetrics.cardControlCornerRadius + borderColors = TwoColors(colorInLightMode: DashboardStyle.rgb(181, 181, 181), colorInDarkMode: DashboardStyle.rgb(83, 83, 83)) control.adjustAlphaWhenClick = true control.label.stringValue = NSLocalizedString("Open Image with Preview…", comment: "") - control.label.font = LKDashboardStyle.font(11) + control.label.font = DashboardStyle.font(11) control.addTarget(self, clickAction: #selector(handleClick)) addSubview(control) } @@ -183,7 +183,7 @@ final class LKDashboardAttributeOpenImageView: LKDashboardAttributeView { override func sizeThatFits(_ limitedSize: NSSize) -> NSSize { var size = limitedSize - size.height = LKDashboardMetrics.numberInputHorizontalHeight + size.height = DashboardMetrics.numberInputHorizontalHeight return size } @@ -196,13 +196,13 @@ final class LKDashboardAttributeOpenImageView: LKDashboardAttributeView { } guard let imageViewOid = (attribute?.value as? NSNumber)?.uintValue else { - LKDashboardStyle.alert(LKConnectionError.inner, window: window) + DashboardStyle.alert(ConnectionError.inner, window: window) assertionFailure() return } guard dashboardViewController?.isStaticMode == true else { - LKDashboardStyle.alert( + DashboardStyle.alert( title: NSLocalizedString("The feature is not available in current mode.", comment: ""), detail: NSLocalizedString("You must connect LookInside with target iOS app before using this feature.", comment: ""), window: window @@ -211,8 +211,8 @@ final class LKDashboardAttributeOpenImageView: LKDashboardAttributeView { } // The inspectable app of the document that owns this view's window. - guard let inspectableApp = LookinLiveDocument.document(in: window)?.inspectableApp else { - LKDashboardStyle.alert(LKConnectionError.noConnect, window: window) + guard let inspectableApp = LiveDocument.document(in: window)?.inspectableApp else { + DashboardStyle.alert(ConnectionError.noConnect, window: window) return } @@ -221,7 +221,7 @@ final class LKDashboardAttributeOpenImageView: LKDashboardAttributeView { let imageData = try await inspectableApp.image(imageViewOid: imageViewOid) guard let self else { return } guard let imageData else { - LKDashboardStyle.alert( + DashboardStyle.alert( title: NSLocalizedString("Operation failed. The image property value of selected UIImageView is nil.", comment: ""), detail: "", window: self.window @@ -230,7 +230,7 @@ final class LKDashboardAttributeOpenImageView: LKDashboardAttributeView { } self.openImageData(imageData) } catch { - LKDashboardStyle.alert(error, window: self?.window) + DashboardStyle.alert(error, window: self?.window) } } } @@ -244,11 +244,11 @@ final class LKDashboardAttributeOpenImageView: LKDashboardAttributeView { try imageData.write(to: URL(fileURLWithPath: filePath)) } catch { assertionFailure() - LKDashboardStyle.alert(error, window: window) + DashboardStyle.alert(error, window: window) return } NSWorkspace.shared.open(URL(fileURLWithPath: filePath)) - LKHelper.sharedInstance().tempImageFiles.append(filePath) + AppHelper.sharedInstance().tempImageFiles.append(filePath) } } diff --git a/LookInside/Dashboard/LKDashboardAccessoryWindowController.swift b/LookInside/Dashboard/DashboardAccessoryWindowController.swift similarity index 65% rename from LookInside/Dashboard/LKDashboardAccessoryWindowController.swift rename to LookInside/Dashboard/DashboardAccessoryWindowController.swift index ec8f0ad4..a8b05987 100644 --- a/LookInside/Dashboard/LKDashboardAccessoryWindowController.swift +++ b/LookInside/Dashboard/DashboardAccessoryWindowController.swift @@ -1,5 +1,5 @@ // -// LKDashboardAccessoryWindowController.swift +// DashboardAccessoryWindowController.swift // LookInside // // Created by Li Kai on 2019/8/30. @@ -8,24 +8,24 @@ import AppKit -protocol LKDashboardAccessoryWindowControllerDelegate: AnyObject { - func dashboardAccessoryWindowControllerWillClose(_ controller: LKDashboardAccessoryWindowController) +protocol DashboardAccessoryWindowControllerDelegate: AnyObject { + func dashboardAccessoryWindowControllerWillClose(_ controller: DashboardAccessoryWindowController) } /// The panel beside the window that lists a card's hidden sections, each /// with a button that adds it to the card. -final class LKDashboardAccessoryWindowController: LKWindowController, NSWindowDelegate { +final class DashboardAccessoryWindowController: WindowController, NSWindowDelegate { private let groupID: String? - private weak var dashboardController: LKDashboardViewController? + private weak var dashboardController: DashboardViewController? /// Keyed by section identifier. - private var sectionViews: [String: LKDashboardSectionView] = [:] + private var sectionViews: [String: DashboardSectionView] = [:] - weak var delegate: LKDashboardAccessoryWindowControllerDelegate? + weak var delegate: DashboardAccessoryWindowControllerDelegate? - init(dashboardController: LKDashboardViewController?, attrGroupID groupID: String?) { + init(dashboardController: DashboardViewController?, attrGroupID groupID: String?) { self.groupID = groupID self.dashboardController = dashboardController - let panel = LKPopPanel(size: NSSize(width: 400, height: 100)) + let panel = PopPanel(size: NSSize(width: 400, height: 100)) super.init(window: panel) panel.delegate = self } @@ -40,13 +40,13 @@ final class LKDashboardAccessoryWindowController: LKWindowController, NSWindowDe for (idx, section) in sections.enumerated() { let identifier = section.identifier ?? "" - let view: LKDashboardSectionView + let view: DashboardSectionView if let existing = sectionViews[identifier] { view = existing needlessViews.removeAll { $0 === existing } view.isHidden = false } else { - view = LKDashboardSectionView() + view = DashboardSectionView() sectionViews[identifier] = view } view.dashboardViewController = dashboardController @@ -58,12 +58,12 @@ final class LKDashboardAccessoryWindowController: LKWindowController, NSWindowDe needlessViews.forEach { $0.isHidden = true } - let normalSectionWidth = LKDashboardMetrics.viewWidth - LKDashboardMetrics.horInset * 2 + let normalSectionWidth = DashboardMetrics.viewWidth - DashboardMetrics.horInset * 2 var y: CGFloat = 8 for sectionID in DashboardBlueprint.sectionIDs(forGroupID: groupID) ?? [] { guard let view = sectionViews[sectionID], !view.isHidden else { continue } - view.dashboardLayout.x(LKDashboardMetrics.horInset).width(normalSectionWidth - LKDashboardMetrics.horInset * 2).heightToFit().y(y) - y = view.frame.maxY + LKDashboardMetrics.sectionMarginTop + view.dashboardLayout.x(DashboardMetrics.horInset).width(normalSectionWidth - DashboardMetrics.horInset * 2).heightToFit().y(y) + y = view.frame.maxY + DashboardMetrics.sectionMarginTop } return NSSize(width: normalSectionWidth + 23, height: y) diff --git a/LookInside/Dashboard/LKDashboardCardView.swift b/LookInside/Dashboard/DashboardCardView.swift similarity index 83% rename from LookInside/Dashboard/LKDashboardCardView.swift rename to LookInside/Dashboard/DashboardCardView.swift index fc30d54d..c11c8a95 100644 --- a/LookInside/Dashboard/LKDashboardCardView.swift +++ b/LookInside/Dashboard/DashboardCardView.swift @@ -1,5 +1,5 @@ // -// LKDashboardCardView.swift +// DashboardCardView.swift // LookInside // // Created by Li Kai on 2018/11/18. @@ -11,9 +11,9 @@ import QuartzCore /// The clickable title row of a card: icon, title, SwiftUI accent and /// disclosure arrow. -final class LKDashboardCardTitleControl: LKBaseControl { +final class DashboardCardTitleControl: BaseControl { let iconImageView = NSImageView() - let label = LKLabel() + let label = TextLabel() let disclosureImageView = NSImageView() let accentImageView = NSImageView() @@ -22,12 +22,12 @@ final class LKDashboardCardTitleControl: LKBaseControl { addSubview(iconImageView) label.textColor = .labelColor - label.font = LKDashboardStyle.font(13) + label.font = DashboardStyle.font(13) addSubview(label) addSubview(disclosureImageView) - accentImageView.contentTintColor = LKHelper.accentColor() + accentImageView.contentTintColor = AppHelper.accentColor() accentImageView.isHidden = true addSubview(accentImageView) } @@ -38,7 +38,7 @@ final class LKDashboardCardTitleControl: LKBaseControl { override func layout() { super.layout() - iconImageView.dashboardLayout.sizeToFit().verAlign().x(LKDashboardMetrics.horInset).offsetY(-1) + iconImageView.dashboardLayout.sizeToFit().verAlign().x(DashboardMetrics.horInset).offsetY(-1) label.dashboardLayout.sizeToFit().verAlign().offsetY(-1).x(iconImageView.frame.maxX + 3) var tailX = label.frame.maxX @@ -50,43 +50,43 @@ final class LKDashboardCardTitleControl: LKBaseControl { } } -protocol LKDashboardCardViewDelegate: AnyObject { - func dashboardCardViewNeedToggleCollapse(_ view: LKDashboardCardView) +protocol DashboardCardViewDelegate: AnyObject { + func dashboardCardViewNeedToggleCollapse(_ view: DashboardCardView) } /// One attribute group as a card: a title that collapses it, the shown /// sections, and a "more" button that offers the hidden sections in a /// panel beside the window. -final class LKDashboardCardView: LKBaseView, LKUserActionManagerDelegate, LKDashboardAccessoryWindowControllerDelegate { +final class DashboardCardView: BaseView, UserActionManagerDelegate, DashboardAccessoryWindowControllerDelegate { private let titleHeight: CGFloat = 30 private let insetBottom: CGFloat = 12 private var contentsY: CGFloat = 35 - private let backgroundEffectView = LKVisualEffectView() - private let titleControl = LKDashboardCardTitleControl() + private let backgroundEffectView = VisualEffectView() + private let titleControl = DashboardCardTitleControl() private var detailButton: NSButton! private var relationHelpButton: NSButton? - private var fadeView: LKBaseView? + private var fadeView: BaseView? - private let sectionViewPool = LKDashboardSectionViewPool() - private var sectionViews: [LKDashboardSectionView] = [] - private var accessoryWindowController: LKDashboardAccessoryWindowController? + private let sectionViewPool = DashboardSectionViewPool() + private var sectionViews: [DashboardSectionView] = [] + private var accessoryWindowController: DashboardAccessoryWindowController? - weak var dashboardViewController: LKDashboardViewController? - weak var delegate: LKDashboardCardViewDelegate? + weak var dashboardViewController: DashboardViewController? + weak var delegate: DashboardCardViewDelegate? /// The group to render; setting it does not render. var attrGroup: AttributesGroup? var isCollapsed = false { didSet { - titleControl.disclosureImageView.image = LKDashboardStyle.image(isCollapsed ? "icon_arrow_right" : "icon_arrow_down") + titleControl.disclosureImageView.image = DashboardStyle.image(isCollapsed ? "icon_arrow_right" : "icon_arrow_down") } } override init(frame frameRect: NSRect) { super.init(frame: frameRect) - layer?.cornerRadius = LKDashboardMetrics.cardCornerRadius + layer?.cornerRadius = DashboardMetrics.cardCornerRadius backgroundEffectView.blendingMode = .withinWindow backgroundEffectView.state = .active @@ -95,14 +95,14 @@ final class LKDashboardCardView: LKBaseView, LKUserActionManagerDelegate, LKDash titleControl.addTarget(self, clickAction: #selector(handleClickTitle)) addSubview(titleControl) - detailButton = NSButton(image: LKDashboardStyle.image("icon_more") ?? NSImage(), target: self, action: #selector(handleClickDetailButton)) + detailButton = NSButton(image: DashboardStyle.image("icon_more") ?? NSImage(), target: self, action: #selector(handleClickDetailButton)) detailButton.bezelStyle = .roundRect detailButton.isBordered = false addSubview(detailButton) updateColors() - LKUserActionManager.sharedInstance().add(self) + UserActionManager.sharedInstance().add(self) } required init?(coder _: NSCoder) { @@ -124,8 +124,8 @@ final class LKDashboardCardView: LKBaseView, LKUserActionManagerDelegate, LKDash var y = contentsY for view in sectionViews { - view.dashboardLayout.x(LKDashboardMetrics.horInset).toRight(LKDashboardMetrics.horInset).heightToFit().y(y) - y = view.frame.maxY + LKDashboardMetrics.sectionMarginTop + view.dashboardLayout.x(DashboardMetrics.horInset).toRight(DashboardMetrics.horInset).heightToFit().y(y) + y = view.frame.maxY + DashboardMetrics.sectionMarginTop } } @@ -135,12 +135,12 @@ final class LKDashboardCardView: LKBaseView, LKUserActionManagerDelegate, LKDash size.height = titleHeight return size } - size.width -= LKDashboardMetrics.horInset * 2 + size.width -= DashboardMetrics.horInset * 2 var height = contentsY for view in sectionViews { - height += view.sizeThatFits(size).height + LKDashboardMetrics.sectionMarginTop + height += view.sizeThatFits(size).height + DashboardMetrics.sectionMarginTop } - height -= LKDashboardMetrics.sectionMarginTop + height -= DashboardMetrics.sectionMarginTop height += insetBottom size.height = height return size @@ -162,7 +162,7 @@ final class LKDashboardCardView: LKBaseView, LKUserActionManagerDelegate, LKDash } let inspectedAppInfo = dashboardViewController?.currentDataSource()?.rawHierarchyInfo?.appInfo - let isMacTarget = LKHelper.appInfoLooksLikeMacTarget(inspectedAppInfo) + let isMacTarget = AppHelper.appInfoLooksLikeMacTarget(inspectedAppInfo) titleControl.label.stringValue = attrGroup.queryDisplayTitle(forMacTarget: isMacTarget) titleControl.iconImageView.image = Self.image(for: attrGroup) @@ -181,7 +181,7 @@ final class LKDashboardCardView: LKBaseView, LKUserActionManagerDelegate, LKDash sectionViewPool.recycleAll() for (idx, section) in (attrGroup.attrSections ?? []).enumerated() { - if !section.isUserCustom() && !(section.identifier.map { LKPreferenceManager.shared.isSectionShowing($0) } ?? false) { + if !section.isUserCustom() && !(section.identifier.map { PreferenceManager.shared.isSectionShowing($0) } ?? false) { continue } let sectionView = sectionViewPool.dequeueView(for: section) @@ -206,7 +206,7 @@ final class LKDashboardCardView: LKBaseView, LKUserActionManagerDelegate, LKDash needsLayout = true } - func querySectionView(with section: AttributesSection) -> LKDashboardSectionView? { + func querySectionView(with section: AttributesSection) -> DashboardSectionView? { sectionViews.first { $0.attrSection === section } } @@ -216,8 +216,8 @@ final class LKDashboardCardView: LKBaseView, LKUserActionManagerDelegate, LKDash if fadeView != nil { return } - let fadeView = LKBaseView() - fadeView.backgroundColor = isDarkMode() ? LKDashboardStyle.rgb(0, 0, 0, 0.7) : LKDashboardStyle.rgb(0, 0, 0, 0.6) + let fadeView = BaseView() + fadeView.backgroundColor = isDarkMode() ? DashboardStyle.rgb(0, 0, 0, 0.7) : DashboardStyle.rgb(0, 0, 0, 0.6) fadeView.alphaValue = 0 fadeView.frame = bounds addSubview(fadeView) @@ -354,7 +354,7 @@ final class LKDashboardCardView: LKBaseView, LKUserActionManagerDelegate, LKDash static func image(for group: AttributesGroup) -> NSImage? { let name = groupIconNames[group.identifier ?? ""] assert(name != nil, "missing dashboard icon for group \(group.identifier ?? "nil")") - return LKDashboardStyle.image(name ?? "dashboard_layer") + return DashboardStyle.image(name ?? "dashboard_layer") } private static let swiftUIAccentImage: NSImage? = { @@ -367,7 +367,7 @@ final class LKDashboardCardView: LKBaseView, LKUserActionManagerDelegate, LKDash private func showRelationHelpButton() { if relationHelpButton == nil { - let button = NSButton(image: LKDashboardStyle.image("ic_question") ?? NSImage(), target: self, action: #selector(handleRelationHelpButton)) + let button = NSButton(image: DashboardStyle.image("ic_question") ?? NSImage(), target: self, action: #selector(handleRelationHelpButton)) button.bezelStyle = .roundRect button.isBordered = false relationHelpButton = button @@ -381,7 +381,7 @@ final class LKDashboardCardView: LKBaseView, LKUserActionManagerDelegate, LKDash @objc private func handleRelationHelpButton() { let menu = NSMenu() let menuItem = NSMenuItem() - menuItem.image = LKDashboardStyle.image("Icon_Inspiration_small") + menuItem.image = DashboardStyle.image("Icon_Inspiration_small") menuItem.title = NSLocalizedString("How to display more member variables…", comment: "") menuItem.target = self menuItem.action = #selector(handleRelationDocument) @@ -392,19 +392,19 @@ final class LKDashboardCardView: LKBaseView, LKUserActionManagerDelegate, LKDash } @objc private func handleRelationDocument() { - LKHelper.showDisabledExternalLinkAlert(withMessage: NSLocalizedString("Legacy member-variable documentation links are disabled in this community build. See the repository README instead.", comment: "")) + AppHelper.showDisabledExternalLinkAlert(withMessage: NSLocalizedString("Legacy member-variable documentation links are disabled in this community build. See the repository README instead.", comment: "")) } // MARK: - Others override func mouseDown(with event: NSEvent) { super.mouseDown(with: event) - LKUserActionManager.sharedInstance().send(.dashboardClick) + UserActionManager.sharedInstance().send(.dashboardClick) } - // MARK: - LKUserActionManagerDelegate + // MARK: - UserActionManagerDelegate - func lkUserActionManager(_: LKUserActionManager, didAct type: LKUserActionType) { + func lkUserActionManager(_: UserActionManager, didAct type: UserActionType) { guard let accessoryWindowController else { return } guard [.previewOperation, .dashboardClick, .selectedItemChange].contains(type) else { return } accessoryWindowController.close() @@ -418,7 +418,7 @@ final class LKDashboardCardView: LKBaseView, LKUserActionManagerDelegate, LKDash return } - LKUserActionManager.sharedInstance().send(.dashboardClick) + UserActionManager.sharedInstance().send(.dashboardClick) if isCollapsed { // Expand a collapsed card first. @@ -426,7 +426,7 @@ final class LKDashboardCardView: LKBaseView, LKUserActionManagerDelegate, LKDash } guard let attrGroup else { return } - let controller = LKDashboardAccessoryWindowController(dashboardController: dashboardViewController, attrGroupID: attrGroup.identifier) + let controller = DashboardAccessoryWindowController(dashboardController: dashboardViewController, attrGroupID: attrGroup.identifier) controller.delegate = self accessoryWindowController = controller @@ -446,7 +446,7 @@ final class LKDashboardCardView: LKBaseView, LKUserActionManagerDelegate, LKDash sectionViews.forEach { $0.manageState = .canRemove } let allSectionIDs = DashboardBlueprint.sectionIDs(forGroupID: attrGroup.identifier) ?? [] - let hiddenSectionIDs = allSectionIDs.filter { !LKPreferenceManager.shared.isSectionShowing($0) } + let hiddenSectionIDs = allSectionIDs.filter { !PreferenceManager.shared.isSectionShowing($0) } if hiddenSectionIDs.isEmpty { controller.window?.contentView?.isHidden = true return @@ -475,7 +475,7 @@ final class LKDashboardCardView: LKBaseView, LKUserActionManagerDelegate, LKDash controller.window?.setFrame(NSRect(x: panelX, y: panelY, width: contentSize.width, height: contentSize.height), display: true) } - func dashboardAccessoryWindowControllerWillClose(_: LKDashboardAccessoryWindowController) { + func dashboardAccessoryWindowControllerWillClose(_: DashboardAccessoryWindowController) { sectionViews.forEach { $0.manageState = .none } accessoryWindowController = nil } diff --git a/LookInside/Dashboard/LKDashboardLayout.swift b/LookInside/Dashboard/DashboardLayout.swift similarity index 95% rename from LookInside/Dashboard/LKDashboardLayout.swift rename to LookInside/Dashboard/DashboardLayout.swift index 1cbe5a26..d0d824d6 100644 --- a/LookInside/Dashboard/LKDashboardLayout.swift +++ b/LookInside/Dashboard/DashboardLayout.swift @@ -1,5 +1,5 @@ // -// LKDashboardLayout.swift +// DashboardLayout.swift // LookInside // // Frame arithmetic for the Dashboard's hand-laid-out views. @@ -9,7 +9,7 @@ // geometry: // // - position and size setters round up to the main screen's pixel grid; -// - `sizeToFit()` / `heightToFit()` only measure `LKBaseView` and +// - `sizeToFit()` / `heightToFit()` only measure `BaseView` and // `NSControl` (through `sizeThatFits(_:)`), do not round, and leave any // other view alone; // - `right`, `bottom`, the alignments and the `to…` edges are relative to @@ -21,7 +21,7 @@ import AppKit /// A view or layer whose frame is being set. Every setter returns the /// layout again so calls chain in the order they are written. @MainActor -struct LKDashboardLayout { +struct DashboardLayout { private enum Target { case view(NSView) case layer(CALayer) @@ -248,17 +248,17 @@ struct LKDashboardLayout { // MARK: - Fitting - /// The view that can measure itself: an `LKBaseView` or an `NSControl`. + /// The view that can measure itself: an `BaseView` or an `NSControl`. private var measurableView: NSView? { guard case let .view(view) = target else { return nil } - if view is LKBaseView || view is NSControl { + if view is BaseView || view is NSControl { return view } return nil } private static func fittingSize(of view: NSView, in limit: NSSize) -> NSSize { - if let baseView = view as? LKBaseView { + if let baseView = view as? BaseView { return baseView.sizeThatFits(limit) } if let control = view as? NSControl { @@ -288,7 +288,7 @@ struct LKDashboardLayout { guard let view = measurableView else { return self } var rect = view.frame let limit = NSSize(width: view.bounds.width, height: .greatestFiniteMagnitude) - if let baseView = view as? LKBaseView { + if let baseView = view as? BaseView { rect.size.height = baseView.sizeThatFits(limit).height } else if let control = view as? NSControl { rect.size.height = control.sizeThatFits(limit).height @@ -301,21 +301,21 @@ struct LKDashboardLayout { extension NSView { /// Lays the view out with the Dashboard's frame rules. @MainActor - var dashboardLayout: LKDashboardLayout { - LKDashboardLayout(self) + var dashboardLayout: DashboardLayout { + DashboardLayout(self) } } extension CALayer { /// Lays the layer out with the Dashboard's frame rules. @MainActor - var dashboardLayout: LKDashboardLayout { - LKDashboardLayout(self) + var dashboardLayout: DashboardLayout { + DashboardLayout(self) } } -/// The Dashboard's shared metrics, mirrored from `LKHelper.swift`. -enum LKDashboardMetrics { +/// The Dashboard's shared metrics, mirrored from `AppHelper.swift`. +enum DashboardMetrics { static let viewWidth = DashboardViewWidth static let horInset = DashboardHorInset static let attrItemHorInterspace = DashboardAttrItemHorInterspace @@ -332,7 +332,7 @@ enum LKDashboardMetrics { } /// Colour, image and alert helpers that replace the old `LKHelper.h` macros. -enum LKDashboardStyle { +enum DashboardStyle { static func rgb(_ red: CGFloat, _ green: CGFloat, _ blue: CGFloat, _ alpha: CGFloat = 1) -> NSColor { NSColor(red: red / 255.0, green: green / 255.0, blue: blue / 255.0, alpha: alpha) } @@ -384,7 +384,7 @@ enum LKDashboardStyle { /// Builders for the attributed strings the Objective-C code made with /// ShortCocoa's string helpers. -enum LKDashboardText { +enum DashboardText { /// `$(string)` with optional `.font`, `.textColor` and `.lineHeight`, /// each applied to the whole string; an empty string stays plain. static func attributed(_ string: String, font: NSFont? = nil, color: NSColor? = nil, lineHeight: CGFloat? = nil) -> NSMutableAttributedString { diff --git a/LookInside/Dashboard/LKDashboardModification.swift b/LookInside/Dashboard/DashboardModification.swift similarity index 98% rename from LookInside/Dashboard/LKDashboardModification.swift rename to LookInside/Dashboard/DashboardModification.swift index daeeb46c..6e1727b7 100644 --- a/LookInside/Dashboard/LKDashboardModification.swift +++ b/LookInside/Dashboard/DashboardModification.swift @@ -1,5 +1,5 @@ // -// LKDashboardModification.swift +// DashboardModification.swift // LookInside // // The payloads the Dashboard sends when the user edits an attribute, and @@ -10,7 +10,7 @@ import Foundation -enum LKDashboardModification { +enum DashboardModification { /// The request for an attribute the Server knows: the setter of the /// attribute's identifier, called on the object the attribute belongs /// to (view, layer, window or cell of the item). Nil when the @@ -151,7 +151,7 @@ enum LKDashboardModification { // MARK: - Constraints -enum LKDashboardConstraintOrder { +enum DashboardConstraintOrder { /// The order the constraints card lists constraints in: effective ones /// first, then by first item type and first attribute. The sort is /// stable, as `-sortedArrayUsingComparator:` is. diff --git a/LookInside/Dashboard/LKDashboardSectionView.swift b/LookInside/Dashboard/DashboardSectionView.swift similarity index 79% rename from LookInside/Dashboard/LKDashboardSectionView.swift rename to LookInside/Dashboard/DashboardSectionView.swift index 9204f930..d8435724 100644 --- a/LookInside/Dashboard/LKDashboardSectionView.swift +++ b/LookInside/Dashboard/DashboardSectionView.swift @@ -1,5 +1,5 @@ // -// LKDashboardSectionView.swift +// DashboardSectionView.swift // LookInside // // Created by Li Kai on 2019/6/7. @@ -10,7 +10,7 @@ import AppKit /// Whether a section shows a button that adds it to, or removes it from, /// its card. -enum LKDashboardSectionManageState { +enum DashboardSectionManageState { case none case canAdd case canRemove @@ -18,16 +18,16 @@ enum LKDashboardSectionManageState { /// One section of a card: an optional title and separator, then the /// attribute views flowed into rows. -final class LKDashboardSectionView: LKBaseView { +final class DashboardSectionView: BaseView { private let titleMarginTop: CGFloat = 6 - private var attrViews: [LKDashboardAttributeView] = [] - private var titleLabel: LKLabel? + private var attrViews: [DashboardAttributeView] = [] + private var titleLabel: TextLabel? private let topSepLayer = CALayer() private var manageButton: NSButton? private var jsonPopupButton: NSButton? - weak var dashboardViewController: LKDashboardViewController? + weak var dashboardViewController: DashboardViewController? override init(frame frameRect: NSRect) { super.init(frame: frameRect) @@ -52,7 +52,7 @@ final class LKDashboardSectionView: LKBaseView { didSet { topSepLayer.isHidden = !showTopSeparator } } - var manageState: LKDashboardSectionManageState = .none { + var manageState: DashboardSectionManageState = .none { didSet { renderManageState() } } @@ -84,7 +84,7 @@ final class LKDashboardSectionView: LKBaseView { if !topSepLayer.isHidden { topSepLayer.dashboardLayout.x(contentsX).width(selfWidth).height(1).y(0) - contentsY = LKDashboardMetrics.attrItemVerInterspace + contentsY = DashboardMetrics.attrItemVerInterspace } if let titleLabel, titleLabel.isVisible { @@ -93,7 +93,7 @@ final class LKDashboardSectionView: LKBaseView { titleWidth -= 20 } titleLabel.dashboardLayout.x(contentsX).width(titleWidth).heightToFit().y(topSepLayer.isHidden ? 0 : titleMarginTop) - contentsY = titleLabel.frame.maxY + LKDashboardMetrics.attrItemVerInterspace + contentsY = titleLabel.frame.maxY + DashboardMetrics.attrItemVerInterspace } var rowTop = contentsY @@ -106,29 +106,29 @@ final class LKDashboardSectionView: LKBaseView { // A row is as tall as its tallest item, so a 21 pt switch // does not clip the 38 pt number input next to it. rowHeight = max(rowHeight, view.frame.height) - itemX = view.frame.maxX + LKDashboardMetrics.attrItemHorInterspace + itemX = view.frame.maxX + DashboardMetrics.attrItemHorInterspace } - rowTop += rowHeight + LKDashboardMetrics.attrItemVerInterspace + rowTop += rowHeight + DashboardMetrics.attrItemVerInterspace } } /// The width an attribute view gets in a container of `availableWidth`. /// Layout and measuring share it so they never disagree. - private func width(of view: LKDashboardAttributeView, inAvailableWidth availableWidth: CGFloat) -> CGFloat { + private func width(of view: DashboardAttributeView, inAvailableWidth availableWidth: CGFloat) -> CGFloat { let numberOfColumns = view.numberOfColumnsOccupied() if numberOfColumns == 0 { - return view.sizeThatFits(LKDashboardMetrics.maxSize).width + return view.sizeThatFits(DashboardMetrics.maxSize).width } - let horSpace = LKDashboardMetrics.attrItemHorInterspace + let horSpace = DashboardMetrics.attrItemHorInterspace return floor((availableWidth + horSpace) / CGFloat(numberOfColumns)) - horSpace } /// The visible attribute views grouped into rows the way layout places /// them, so a row is never measured at one height and drawn at another. - private func rowsOfVisibleAttrViews(inAvailableWidth availableWidth: CGFloat) -> [[LKDashboardAttributeView]] { - var rows: [[LKDashboardAttributeView]] = [] + private func rowsOfVisibleAttrViews(inAvailableWidth availableWidth: CGFloat) -> [[DashboardAttributeView]] { + var rows: [[DashboardAttributeView]] = [] var currentRowWidth: CGFloat = 0 - let horSpace = LKDashboardMetrics.attrItemHorInterspace + let horSpace = DashboardMetrics.attrItemHorInterspace for view in attrViews where view.isVisible { let width = width(of: view, inAvailableWidth: availableWidth) if !rows.isEmpty, currentRowWidth + horSpace + width <= availableWidth { @@ -145,7 +145,7 @@ final class LKDashboardSectionView: LKBaseView { override func sizeThatFits(_ limitedSize: NSSize) -> NSSize { var height: CGFloat = 0 if !topSepLayer.isHidden { - height += LKDashboardMetrics.attrItemVerInterspace + height += DashboardMetrics.attrItemVerInterspace } if let titleLabel, titleLabel.isVisible { var titleWidth = limitedSize.width @@ -164,7 +164,7 @@ final class LKDashboardSectionView: LKBaseView { rowHeight = max(rowHeight, view.sizeThatFits(NSSize(width: width, height: .greatestFiniteMagnitude)).height) } if rowIdx > 0 { - height += LKDashboardMetrics.attrItemVerInterspace + height += DashboardMetrics.attrItemVerInterspace } height += rowHeight } @@ -176,7 +176,7 @@ final class LKDashboardSectionView: LKBaseView { override func updateColors() { super.updateColors() - topSepLayer.backgroundColor = LKDashboardStyle.separatorColor(isDarkMode: isDarkMode()).cgColor + topSepLayer.backgroundColor = DashboardStyle.separatorColor(isDarkMode: isDarkMode()).cgColor } // MARK: - Rendering @@ -188,12 +188,12 @@ final class LKDashboardSectionView: LKBaseView { } if let title = resolveSectionTitle(), !title.isEmpty { - let label: LKLabel + let label: TextLabel if let titleLabel { label = titleLabel label.isHidden = false } else { - label = LKLabel() + label = TextLabel() label.font = .boldSystemFont(ofSize: 12) addSubview(label) titleLabel = label @@ -212,7 +212,7 @@ final class LKDashboardSectionView: LKBaseView { assertionFailure("LookInside dashboard: no attrView class for attrType=\(attr.attrType.rawValue) identifier=\(attr.identifier ?? "nil")") continue } - let view: LKDashboardAttributeView + let view: DashboardAttributeView if let index = notUsedViews.firstIndex(where: { type(of: $0) == viewClass }) { view = notUsedViews.remove(at: index) view.isHidden = false @@ -238,46 +238,46 @@ final class LKDashboardSectionView: LKBaseView { /// The view class for an attribute type (and, for custom objects, its /// identifier); nil when there is none. - static func attrViewClass(for type: LookinAttrType, identifier: String?) -> LKDashboardAttributeView.Type? { + static func attrViewClass(for type: LookinAttrType, identifier: String?) -> DashboardAttributeView.Type? { switch type { case .cgRect: - return LKDashboardAttributeRectView.self + return DashboardAttributeRectView.self case .uiEdgeInsets: - return LKDashboardAttributeInsetsView.self + return DashboardAttributeInsetsView.self case .BOOL: - return LKDashboardAttributeSwitchView.self + return DashboardAttributeSwitchView.self case .float, .double, .long, .unsignedLong, .int, .unsignedInt: - return LKDashboardAttributeNumberInputView.self + return DashboardAttributeNumberInputView.self case .uiColor: - return LKDashboardAttributeColorView.self + return DashboardAttributeColorView.self case .enumInt, .enumLong, .enumString: - return LKDashboardAttributeEnumsView.self + return DashboardAttributeEnumsView.self case .cgPoint: - return LKDashboardAttributePointView.self + return DashboardAttributePointView.self case .cgSize: - return LKDashboardAttributeSizeView.self + return DashboardAttributeSizeView.self case .nsString: - return LKDashboardAttributeTextView.self + return DashboardAttributeTextView.self case .shadow: - return LKDashboardAttributeShadowView.self + return DashboardAttributeShadowView.self case .json: - return LKDashboardAttributeJsonView.self + return DashboardAttributeJSONView.self case .customObj: switch identifier ?? "" { case "lookinside.private_discriminator.field": - return LKDashboardAttributePrivateDiscriminatorView.self + return DashboardAttributePrivateDiscriminatorView.self case LookinAttr_UITableView_RowsNumber_Number: - return LKDashboardAttributeRowsCountView.self + return DashboardAttributeRowsCountView.self case LookinAttr_Class_Class_Class: - return LKDashboardAttributeClassView.self + return DashboardAttributeClassView.self case LookinAttr_Relation_Relation_Relation: - return LKDashboardAttributeRelationView.self + return DashboardAttributeRelationView.self case LookinAttr_AutoLayout_Constraints_Constraints: - return LKDashboardAttributeConstraintsView.self + return DashboardAttributeConstraintsView.self case LookinAttr_UIImageView_Open_Open, LookinAttr_NSImageView_Open_Open: - return LKDashboardAttributeOpenImageView.self + return DashboardAttributeOpenImageView.self case LookinAttr_UIVisualEffectView_Style_Style: - return LKDashboardAttributeEnumsView.self + return DashboardAttributeEnumsView.self default: return nil } @@ -290,7 +290,7 @@ final class LKDashboardSectionView: LKBaseView { if jsonPopupButton != nil { return } - let button = NSButton(image: LKDashboardStyle.image("open_newwindow") ?? NSImage(), target: self, action: #selector(handleJSONPopupButton)) + let button = NSButton(image: DashboardStyle.image("open_newwindow") ?? NSImage(), target: self, action: #selector(handleJSONPopupButton)) button.bezelStyle = .roundRect button.isBordered = false addSubview(button) @@ -298,7 +298,7 @@ final class LKDashboardSectionView: LKBaseView { } @objc private func handleJSONPopupButton() { - guard let view = attrViews.first(where: { $0.attribute?.attrType == .json }) as? LKDashboardAttributeJsonView else { + guard let view = attrViews.first(where: { $0.attribute?.attrType == .json }) as? DashboardAttributeJSONView else { assertionFailure() return } @@ -332,7 +332,7 @@ final class LKDashboardSectionView: LKBaseView { case .canRemove: imageName = "icon_manage_remove" } - let image = LKDashboardStyle.image(imageName) + let image = DashboardStyle.image(imageName) if let manageButton { manageButton.image = image manageButton.isHidden = false @@ -348,7 +348,7 @@ final class LKDashboardSectionView: LKBaseView { @objc private func handleManageButton() { guard let identifier = attrSection?.identifier else { return } - let manager = LKPreferenceManager.shared + let manager = PreferenceManager.shared switch manageState { case .canAdd: manager.showSection(identifier) @@ -362,23 +362,23 @@ final class LKDashboardSectionView: LKBaseView { /// Reuses section views across renders of a card, keyed by section /// identifier (by attribute titles for user-custom sections). -final class LKDashboardSectionViewPool { +final class DashboardSectionViewPool { /// Views handed out since the last `recycleAll()`. private var dequeuedViews = Set() /// Every view made, dequeued or not. - private var cache: [String: [LKDashboardSectionView]] = [:] + private var cache: [String: [DashboardSectionView]] = [:] func recycleAll() { dequeuedViews.removeAll() } - func dequeueView(for section: AttributesSection) -> LKDashboardSectionView { + func dequeueView(for section: AttributesSection) -> DashboardSectionView { let key = Self.cacheKey(for: section) if let view = cache[key, default: []].first(where: { !dequeuedViews.contains(ObjectIdentifier($0)) }) { dequeuedViews.insert(ObjectIdentifier(view)) return view } - let view = LKDashboardSectionView() + let view = DashboardSectionView() dequeuedViews.insert(ObjectIdentifier(view)) cache[key, default: []].append(view) return view diff --git a/LookInside/Dashboard/LKDashboardViewController.swift b/LookInside/Dashboard/DashboardViewController.swift similarity index 80% rename from LookInside/Dashboard/LKDashboardViewController.swift rename to LookInside/Dashboard/DashboardViewController.swift index 7fbe054a..26ca0603 100644 --- a/LookInside/Dashboard/LKDashboardViewController.swift +++ b/LookInside/Dashboard/DashboardViewController.swift @@ -1,5 +1,5 @@ // -// LKDashboardViewController.swift +// DashboardViewController.swift // LookInside // // Created by Li Kai on 2018/8/6. @@ -13,28 +13,28 @@ import AppKit /// methods. Edits are sent to the inspected app on a live document; a /// document read from a file is read-only. @objc(LKDashboardViewController) -final class LKDashboardViewController: LKBaseViewController, LKDashboardCardViewDelegate, LKDashboardHeaderViewDelegate, LKDashboardSearchPropViewDelegate, LKDashboardSearchMethodsViewDelegate { +final class DashboardViewController: BaseViewController, DashboardCardViewDelegate, DashboardHeaderViewDelegate, DashboardSearchPropertyViewDelegate, DashboardSearchMethodsViewDelegate { /// Read by key by the DEBUG UI snapshots. @objc private(set) var scrollView: NSScrollView! - private var documentView: LKBaseView! - private var cardContainerView: LKBaseView! - private var searchContainerView: LKBaseView! - private var headerView: LKDashboardHeaderView! + private var documentView: BaseView! + private var cardContainerView: BaseView! + private var searchContainerView: BaseView! + private var headerView: DashboardHeaderView! private var groupList: [AttributesGroup] = [] /// Keyed by `AttributesGroup.uniqueKey`. - private var cardViews: [String: LKDashboardCardView] = [:] + private var cardViews: [String: DashboardCardView] = [:] - private var searchPropViews: [LKDashboardSearchPropView] = [] - private var searchMethodsView: LKDashboardSearchMethodsView? - private var methodsDataSource: LKDashboardSearchMethodsDataSource? + private var searchPropViews: [DashboardSearchPropertyView] = [] + private var searchMethodsView: DashboardSearchMethodsView? + private var methodsDataSource: DashboardSearchMethodsDataSource? - private let staticDataSource: LKStaticHierarchyDataSource? - private let readDataSource: LKReadHierarchyDataSource? + private let staticDataSource: StaticHierarchyDataSource? + private let readDataSource: ReadHierarchyDataSource? private var selectedItemObservation: NSKeyValueObservation? private var sectionShowingObserver: NSObjectProtocol? - private var dataSourceSubscriptions: [LKSyncSubscription] = [] + private var dataSourceSubscriptions: [SyncSubscription] = [] /// Whether this dashboard shows a live document (rather than one read /// from a file). @@ -42,17 +42,17 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView /// The update manager of the owning inspector, which patches the /// preview after modifications that need it. - @objc weak var asyncUpdateManager: LKStaticAsyncUpdateManager? + @objc weak var asyncUpdateManager: StaticAsyncUpdateManager? /// The live document that owns this dashboard; its inspectable app /// receives attribute modifications and method invocations. Nil on a /// document read from a file. - @objc weak var liveDocument: LookinLiveDocument? { + @objc weak var liveDocument: LiveDocument? { didSet { methodsDataSource?.liveDocument = liveDocument } } @objc(initWithStaticDataSource:) - init(staticDataSource dataSource: LKStaticHierarchyDataSource) { + init(staticDataSource dataSource: StaticHierarchyDataSource) { staticDataSource = dataSource readDataSource = nil isStaticMode = true @@ -61,7 +61,7 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView } @objc(initWithReadDataSource:) - init(readDataSource dataSource: LKReadHierarchyDataSource) { + init(readDataSource dataSource: ReadHierarchyDataSource) { staticDataSource = nil readDataSource = dataSource isStaticMode = false @@ -81,9 +81,9 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView } override func makeContainerView() -> NSView { - let containerView = LKBaseView() + let containerView = BaseView() - documentView = LKBaseView() + documentView = BaseView() scrollView = NSScrollView() scrollView.drawsBackground = false @@ -93,14 +93,14 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView scrollView.contentView.documentView = documentView containerView.addSubview(scrollView) - headerView = LKDashboardHeaderView() + headerView = DashboardHeaderView() headerView.delegate = self documentView.addSubview(headerView) - cardContainerView = LKBaseView() + cardContainerView = BaseView() documentView.addSubview(cardContainerView) - searchContainerView = LKBaseView() + searchContainerView = BaseView() searchContainerView.isHidden = true documentView.addSubview(searchContainerView) @@ -121,7 +121,7 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView } }) - let methodsDataSource = LKDashboardSearchMethodsDataSource() + let methodsDataSource = DashboardSearchMethodsDataSource() methodsDataSource.liveDocument = liveDocument self.methodsDataSource = methodsDataSource dataSourceSubscriptions.append(staticDataSource.didReloadHierarchyInfo.observe { [weak self] in @@ -140,7 +140,7 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView /// Renders the selected item now and whenever the selection changes, /// each time on a later turn of the main queue. - private func observeSelectedItem(of dataSource: LKHierarchyDataSource) { + private func observeSelectedItem(of dataSource: HierarchyDataSource) { selectedItemObservation = dataSource.observe(\.selectedItem, options: [.initial, .new]) { [weak self] _, _ in DispatchQueue.main.async { guard let self else { return } @@ -157,8 +157,8 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView scrollView.dashboardLayout.fullFrame() let verMargin: CGFloat = 10 - let horInset = LKDashboardMetrics.horInset - let contentWidth = LKDashboardMetrics.viewWidth - horInset * 2 + let horInset = DashboardMetrics.horInset + let contentWidth = DashboardMetrics.viewWidth - horInset * 2 headerView.dashboardLayout.width(contentWidth).x(horInset).height(23).y(10) @@ -194,7 +194,7 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView private func groupList(for item: DisplayItem?) -> [AttributesGroup] { guard let item else { return [] } - let groups = LKPrivateDiscriminatorStore.shared.appendingPrivateDiscriminatorGroup(to: item.queryAllAttrGroupList(), for: item) + let groups = PrivateDiscriminatorStore.shared.appendingPrivateDiscriminatorGroup(to: item.queryAllAttrGroupList(), for: item) // Cards are keyed by uniqueKey, so a duplicated key would lay the // shared card out twice and leave a blank gap. Servers 0.2.8 and // 0.2.9 sent a duplicate Layout group for UIWindowScene nodes. @@ -213,12 +213,12 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView var needlessViews = Array(cardViews.values) for group in list { let key = group.uniqueKey() ?? "" - let cardView: LKDashboardCardView + let cardView: DashboardCardView if let existing = cardViews[key] { cardView = existing needlessViews.removeAll { $0 === existing } } else { - cardView = LKDashboardCardView() + cardView = DashboardCardView() cardView.dashboardViewController = self cardView.delegate = self cardViews[key] = cardView @@ -226,7 +226,7 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView } cardView.isHidden = false cardView.attrGroup = group - cardView.isCollapsed = LKPreferenceManager.shared.collapsedAttrGroups.contains(group.identifier ?? "") + cardView.isCollapsed = PreferenceManager.shared.collapsedAttrGroups.contains(group.identifier ?? "") cardView.render() } needlessViews.forEach { $0.isHidden = true } @@ -238,7 +238,7 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView reload(groupList: groupList(for: currentDataSource()?.selectedItem)) } - @objc func currentDataSource() -> LKHierarchyDataSource? { + @objc func currentDataSource() -> HierarchyDataSource? { if let staticDataSource { return staticDataSource } @@ -270,18 +270,18 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView } private func failModification(_ error: Error) -> Error { - LKDashboardStyle.alert(error, window: view.window) + DashboardStyle.alert(error, window: view.window) return error } private func modifyCustomAttribute(_ attribute: InspectedAttribute, newValue: Any?) async throws { - guard let modification = LKDashboardModification.custom(attribute: attribute, newValue: newValue) else { + guard let modification = DashboardModification.custom(attribute: attribute, newValue: newValue) else { assertionFailure() - throw failModification(LKConnectionError.inner) + throw failModification(ConnectionError.inner) } // The live document's inspectable app applies the modification. guard let inspectableApp = liveDocument?.inspectableApp else { - throw failModification(LKConnectionError.noConnect) + throw failModification(ConnectionError.noConnect) } do { _ = try await inspectableApp.submit(modification) @@ -294,13 +294,13 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView private func modifyInbuiltAttribute(_ attribute: InspectedAttribute, newValue: Any?) async throws { let modifyingItem = attribute.targetDisplayItem - guard let modification = LKDashboardModification.inbuilt(attribute: attribute, newValue: newValue, clientReadableVersion: LKHelper.lookinReadableVersion()) else { + guard let modification = DashboardModification.inbuilt(attribute: attribute, newValue: newValue, clientReadableVersion: AppHelper.lookinReadableVersion()) else { assertionFailure() - throw failModification(LKConnectionError.inner) + throw failModification(ConnectionError.inner) } // The live document's inspectable app applies the modification. guard let inspectableApp = liveDocument?.inspectableApp else { - throw failModification(LKConnectionError.noConnect) + throw failModification(ConnectionError.noConnect) } let detail: DisplayItemDetail do { @@ -317,18 +317,18 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView // reloads the cards, which removes the field and ends editing again. // The flag keeps that second end-of-editing from submitting (and // syncing the image) a second time. - LKDashboardTextControlEditingFlag.shared.shouldIgnoreTextEditingChangeEvent = true + DashboardTextControlEditingFlag.shared.shouldIgnoreTextEditingChangeEvent = true staticDataSource.modify(with: detail) - LKDashboardTextControlEditingFlag.shared.shouldIgnoreTextEditingChangeEvent = false + DashboardTextControlEditingFlag.shared.shouldIgnoreTextEditingChangeEvent = false if DashboardBlueprint.needPatchAfterModification(withAttrID: attribute.identifier), let modifyingItem { _ = asyncUpdateManager?.perform(Selector(("updateAfterModifyingDisplayItem:")), with: modifyingItem) } } - // MARK: - LKDashboardCardViewDelegate + // MARK: - DashboardCardViewDelegate - func dashboardCardViewNeedToggleCollapse(_ view: LKDashboardCardView) { + func dashboardCardViewNeedToggleCollapse(_ view: DashboardCardView) { guard let manager = currentDataSource()?.preferenceManager(), let identifier = view.attrGroup?.identifier else { return } let collapsed = manager.collapsedAttrGroups if collapsed.contains(identifier) { @@ -341,9 +341,9 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView self.view.needsLayout = true } - // MARK: - LKDashboardHeaderViewDelegate + // MARK: - DashboardHeaderViewDelegate - func dashboardHeaderView(_: LKDashboardHeaderView, didInputString string: String) { + func dashboardHeaderView(_: DashboardHeaderView, didInputString string: String) { guard string.count >= 3 else { searchContainerView.isHidden = true return @@ -364,7 +364,7 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView } while searchPropViews.count < resultAttrs.count { - let propView = LKDashboardSearchPropView() + let propView = DashboardSearchPropertyView() propView.delegate = self searchContainerView.addSubview(propView) searchPropViews.append(propView) @@ -386,11 +386,11 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView return } - let methodsView: LKDashboardSearchMethodsView + let methodsView: DashboardSearchMethodsView if let searchMethodsView { methodsView = searchMethodsView } else { - methodsView = LKDashboardSearchMethodsView() + methodsView = DashboardSearchMethodsView() methodsView.delegate = self searchContainerView.addSubview(methodsView) searchMethodsView = methodsView @@ -402,7 +402,7 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView do { let methodsList = try await methodsDataSource.nonArgMethods(ofClass: selectedClassName) guard let self, searchString == self.headerView.currentInputString else { return } - let searchedMethods = LKHelper.bestMatches(inCandidates: methodsList, input: searchString, maxResultsCount: 5) + let searchedMethods = AppHelper.bestMatches(inCandidates: methodsList, input: searchString, maxResultsCount: 5) methodsView.render(methods: searchedMethods, oid: selectedObject?.oid ?? 0) self.searchContainerView.isHidden = false self.view.needsLayout = true @@ -415,7 +415,7 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView } } - func dashboardHeaderView(_ view: LKDashboardHeaderView, didToggleActive isActive: Bool) { + func dashboardHeaderView(_ view: DashboardHeaderView, didToggleActive isActive: Bool) { if isActive { cardContainerView.animator().isHidden = true currentDataSource()?.shouldAvoidChangingPreviewSelectionDueToDashboardSearch = true @@ -435,15 +435,15 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView } } - // MARK: - LKDashboardSearchMethodsViewDelegate + // MARK: - DashboardSearchMethodsViewDelegate - func dashboardSearchMethodsView(_: LKDashboardSearchMethodsView, requestToInvokeMethod method: String, oid: UInt) { + func dashboardSearchMethodsView(_: DashboardSearchMethodsView, requestToInvokeMethod method: String, oid: UInt) { // The live document's inspectable app invokes the method. let inspectableApp = liveDocument?.inspectableApp Task { @MainActor [weak self] in do { - guard oid != 0, !method.isEmpty else { throw LKConnectionError.inner } - guard let inspectableApp else { throw LKConnectionError.noConnect } + guard oid != 0, !method.isEmpty else { throw ConnectionError.inner } + guard let inspectableApp else { throw ConnectionError.noConnect } let value = try await inspectableApp.invokeMethod(oid: oid, text: method) let alert = NSAlert() alert.messageText = method @@ -455,22 +455,22 @@ final class LKDashboardViewController: LKBaseViewController, LKDashboardCardView alert.runModal() } } catch { - LKDashboardStyle.alert(error, window: self?.view.window) + DashboardStyle.alert(error, window: self?.view.window) } } } - // MARK: - LKDashboardSearchPropViewDelegate + // MARK: - DashboardSearchPropertyViewDelegate - func dashboardSearchPropView(_: LKDashboardSearchPropView, didClickRevealAttribute clickedAttribute: InspectedAttribute) { + func dashboardSearchPropView(_: DashboardSearchPropertyView, didClickRevealAttribute clickedAttribute: InspectedAttribute) { headerView.isActive = false var target: (group: AttributesGroup, section: AttributesSection)? search: for group in groupList(for: currentDataSource()?.selectedItem) { for section in group.attrSections ?? [] where (section.attributes ?? []).contains(where: { $0 === clickedAttribute }) { - if let identifier = section.identifier, !LKPreferenceManager.shared.isSectionShowing(identifier) { + if let identifier = section.identifier, !PreferenceManager.shared.isSectionShowing(identifier) { // Adds the section to its card. - LKPreferenceManager.shared.showSection(identifier) + PreferenceManager.shared.showSection(identifier) } target = (group, section) break search diff --git a/LookInside/Dashboard/LKEnumListRegistry.swift b/LookInside/Dashboard/EnumListRegistry.swift similarity index 97% rename from LookInside/Dashboard/LKEnumListRegistry.swift rename to LookInside/Dashboard/EnumListRegistry.swift index 5960f1a1..65e55616 100644 --- a/LookInside/Dashboard/LKEnumListRegistry.swift +++ b/LookInside/Dashboard/EnumListRegistry.swift @@ -1,5 +1,5 @@ // -// LKEnumListRegistry.swift +// EnumListRegistry.swift // LookInside // // Created by Li Kai on 2018/11/21. @@ -15,7 +15,7 @@ import Foundation /// One case of an enum: its name, raw value, and the first OS major /// version that has it (0 for every version). @objc(LKEnumListRegistryKeyValueItem) -final class LKEnumListRegistryKeyValueItem: NSObject { +final class EnumListRegistryKeyValueItem: NSObject { @objc let desc: String @objc let value: Int @objc let availableOSVersion: Int @@ -28,11 +28,11 @@ final class LKEnumListRegistryKeyValueItem: NSObject { } @objc(LKEnumListRegistry) -final class LKEnumListRegistry: NSObject { +final class EnumListRegistry: NSObject { @objc(sharedInstance) - static let shared = LKEnumListRegistry() + static let shared = EnumListRegistry() - private let data: [String: [LKEnumListRegistryKeyValueItem]] + private let data: [String: [EnumListRegistryKeyValueItem]] override private init() { data = Self.makeData() @@ -41,7 +41,7 @@ final class LKEnumListRegistry: NSObject { /// The cases of `enumName` in menu order, or nil for an unknown list. @objc(itemsForEnumName:) - func items(forEnumName enumName: String?) -> [LKEnumListRegistryKeyValueItem]? { + func items(forEnumName enumName: String?) -> [EnumListRegistryKeyValueItem]? { guard let enumName else { return nil } return data[enumName] } @@ -61,14 +61,14 @@ final class LKEnumListRegistry: NSObject { Array(data.keys) } - private static func item(_ desc: String, _ value: Int, _ availableOSVersion: Int = 0) -> LKEnumListRegistryKeyValueItem { - LKEnumListRegistryKeyValueItem(desc: desc, value: value, availableOSVersion: availableOSVersion) + private static func item(_ desc: String, _ value: Int, _ availableOSVersion: Int = 0) -> EnumListRegistryKeyValueItem { + EnumListRegistryKeyValueItem(desc: desc, value: value, availableOSVersion: availableOSVersion) } /// Lists are assigned in order; a later assignment of the same name /// replaces the earlier one, as `NSTextFieldBezelStyle` does. - private static func makeData() -> [String: [LKEnumListRegistryKeyValueItem]] { - var data: [String: [LKEnumListRegistryKeyValueItem]] = [:] + private static func makeData() -> [String: [EnumListRegistryKeyValueItem]] { + var data: [String: [EnumListRegistryKeyValueItem]] = [:] data["UIControlContentVerticalAlignment"] = [item("UIControlContentVerticalAlignmentCenter", 0), item("UIControlContentVerticalAlignmentTop", 1), diff --git a/LookInside/Dashboard/Search/LKDashboardHeaderView.swift b/LookInside/Dashboard/Search/DashboardHeaderView.swift similarity index 83% rename from LookInside/Dashboard/Search/LKDashboardHeaderView.swift rename to LookInside/Dashboard/Search/DashboardHeaderView.swift index 59ab7fc6..eb860e1d 100644 --- a/LookInside/Dashboard/Search/LKDashboardHeaderView.swift +++ b/LookInside/Dashboard/Search/DashboardHeaderView.swift @@ -1,5 +1,5 @@ // -// LKDashboardHeaderView.swift +// DashboardHeaderView.swift // LookInside // // Created by Li Kai on 2019/9/5. @@ -8,15 +8,15 @@ import AppKit -protocol LKDashboardHeaderViewDelegate: AnyObject { - func dashboardHeaderView(_ view: LKDashboardHeaderView, didToggleActive isActive: Bool) - func dashboardHeaderView(_ view: LKDashboardHeaderView, didInputString string: String) +protocol DashboardHeaderViewDelegate: AnyObject { + func dashboardHeaderView(_ view: DashboardHeaderView, didToggleActive isActive: Bool) + func dashboardHeaderView(_ view: DashboardHeaderView, didInputString string: String) } /// The search field above the cards, with the "add custom property" button. /// Clicking it activates the search; typing reports the text 0.3 s after /// the last keystroke. -final class LKDashboardHeaderView: LKBaseView, NSTextFieldDelegate { +final class DashboardHeaderView: BaseView, NSTextFieldDelegate { private static let inputDebounceInterval: TimeInterval = 0.3 private let iconXWhenActive: CGFloat = 11 @@ -28,17 +28,17 @@ final class LKDashboardHeaderView: LKBaseView, NSTextFieldDelegate { private let addButton = NSButton() private var pendingInput: DispatchWorkItem? - weak var delegate: LKDashboardHeaderViewDelegate? + weak var delegate: DashboardHeaderViewDelegate? override init(frame frameRect: NSRect) { super.init(frame: frameRect) inputBorderView.wantsLayer = true - inputBorderView.layer?.cornerRadius = LKDashboardMetrics.cardCornerRadius + inputBorderView.layer?.cornerRadius = DashboardMetrics.cardCornerRadius inputBorderView.layer?.borderWidth = 1 addSubview(inputBorderView) - iconImageView.image = LKDashboardStyle.image("icon_search") + iconImageView.image = DashboardStyle.image("icon_search") addSubview(iconImageView) textField.placeholderString = NSLocalizedString("properties or methods", comment: "") @@ -50,7 +50,7 @@ final class LKDashboardHeaderView: LKBaseView, NSTextFieldDelegate { textField.usesSingleLineMode = true textField.backgroundColor = .clear textField.lineBreakMode = .byTruncatingTail - textField.font = LKDashboardStyle.font(13) + textField.font = DashboardStyle.font(13) textField.isHidden = true addSubview(textField) @@ -113,9 +113,9 @@ final class LKDashboardHeaderView: LKBaseView, NSTextFieldDelegate { let isDarkMode = isDarkMode() let color: NSColor if isActive { - color = isDarkMode ? LKDashboardStyle.rgb(70, 71, 72) : LKDashboardStyle.rgb(198, 199, 200) + color = isDarkMode ? DashboardStyle.rgb(70, 71, 72) : DashboardStyle.rgb(198, 199, 200) } else { - color = isDarkMode ? LKDashboardStyle.rgb(47, 48, 49) : LKDashboardStyle.rgb(220, 221, 222) + color = isDarkMode ? DashboardStyle.rgb(47, 48, 49) : DashboardStyle.rgb(220, 221, 222) } inputBorderView.layer?.borderColor = color.cgColor } @@ -128,7 +128,7 @@ final class LKDashboardHeaderView: LKBaseView, NSTextFieldDelegate { @objc private func handleAddButton() { let menu = NSMenu() let menuItem = NSMenuItem() - menuItem.image = LKDashboardStyle.image("Icon_Inspiration_small") + menuItem.image = DashboardStyle.image("Icon_Inspiration_small") menuItem.title = NSLocalizedString("How to add custom properties…", comment: "") menuItem.target = self menuItem.action = #selector(handleAddCustomAttr) @@ -139,7 +139,7 @@ final class LKDashboardHeaderView: LKBaseView, NSTextFieldDelegate { } @objc private func handleAddCustomAttr() { - LKHelper.showDisabledExternalLinkAlert(withMessage: NSLocalizedString("Legacy custom property guides are disabled in this community build. See the repository README instead.", comment: "")) + AppHelper.showDisabledExternalLinkAlert(withMessage: NSLocalizedString("Legacy custom property guides are disabled in this community build. See the repository README instead.", comment: "")) } // MARK: - NSTextFieldDelegate diff --git a/LookInside/Dashboard/Search/LKDashboardSearchViews.swift b/LookInside/Dashboard/Search/LKDashboardSearchViews.swift index 90e57623..6f2443b3 100644 --- a/LookInside/Dashboard/Search/LKDashboardSearchViews.swift +++ b/LookInside/Dashboard/Search/LKDashboardSearchViews.swift @@ -12,12 +12,12 @@ import AppKit /// A search result card on a blurred background. -class LKDashboardSearchCardView: LKBaseView { - private let backgroundEffectView = LKVisualEffectView() +class DashboardSearchCardView: BaseView { + private let backgroundEffectView = VisualEffectView() override init(frame frameRect: NSRect) { super.init(frame: frameRect) - layer?.cornerRadius = LKDashboardMetrics.cardCornerRadius + layer?.cornerRadius = DashboardMetrics.cardCornerRadius backgroundEffectView.blendingMode = .withinWindow backgroundEffectView.state = .active addSubview(backgroundEffectView) @@ -33,29 +33,29 @@ class LKDashboardSearchCardView: LKBaseView { } } -protocol LKDashboardSearchPropViewDelegate: AnyObject { - func dashboardSearchPropView(_ view: LKDashboardSearchPropView, didClickRevealAttribute attribute: InspectedAttribute) +protocol DashboardSearchPropertyViewDelegate: AnyObject { + func dashboardSearchPropView(_ view: DashboardSearchPropertyView, didClickRevealAttribute attribute: InspectedAttribute) } /// One matching attribute: its title, its value as text, and a button that /// reveals it on its card. -final class LKDashboardSearchPropView: LKDashboardSearchCardView { +final class DashboardSearchPropertyView: DashboardSearchCardView { private let contentLabelY: CGFloat = 21 - private let titleLabel = LKLabel() - private let contentLabel = LKLabel() - private let revealControl = LKTextControl() + private let titleLabel = TextLabel() + private let contentLabel = TextLabel() + private let revealControl = TextControl() private var attribute: InspectedAttribute? - weak var delegate: LKDashboardSearchPropViewDelegate? + weak var delegate: DashboardSearchPropertyViewDelegate? override init(frame frameRect: NSRect) { super.init(frame: frameRect) - titleLabel.font = LKDashboardStyle.font(12) + titleLabel.font = DashboardStyle.font(12) titleLabel.textColor = .secondaryLabelColor addSubview(titleLabel) - contentLabel.font = LKDashboardStyle.font(15) + contentLabel.font = DashboardStyle.font(15) addSubview(contentLabel) revealControl.addTarget(self, clickAction: #selector(handleRevealButton)) @@ -71,7 +71,7 @@ final class LKDashboardSearchPropView: LKDashboardSearchCardView { override func layout() { super.layout() - let inset = LKDashboardMetrics.searchCardInset + let inset = DashboardMetrics.searchCardInset let width = frame.width - inset * 2 titleLabel.dashboardLayout.x(inset).width(width).heightToFit().y(5) contentLabel.dashboardLayout.x(inset).width(width).heightToFit().y(contentLabelY) @@ -79,7 +79,7 @@ final class LKDashboardSearchPropView: LKDashboardSearchCardView { } override func sizeThatFits(_ limitedSize: NSSize) -> NSSize { - let inset = LKDashboardMetrics.searchCardInset + let inset = DashboardMetrics.searchCardInset let width = limitedSize.width - inset * 2 var size = limitedSize size.height = contentLabelY + contentLabel.height(forWidth: width) + inset + 25 @@ -89,14 +89,14 @@ final class LKDashboardSearchPropView: LKDashboardSearchCardView { override func updateColors() { super.updateColors() let isDarkMode = isDarkMode() - contentLabel.textColor = isDarkMode ? LKDashboardStyle.rgb(250, 251, 252) : LKDashboardStyle.rgb(56, 57, 58) + contentLabel.textColor = isDarkMode ? DashboardStyle.rgb(250, 251, 252) : DashboardStyle.rgb(56, 57, 58) - let text = LKDashboardText.attributed( + let text = DashboardText.attributed( NSLocalizedString("Reveal in panel…", comment: ""), - font: LKDashboardStyle.font(11), - color: isDarkMode ? LKDashboardStyle.rgb(245, 166, 30) : LKDashboardStyle.rgb(229, 135, 67) + font: DashboardStyle.font(11), + color: isDarkMode ? DashboardStyle.rgb(245, 166, 30) : DashboardStyle.rgb(229, 135, 67) ) - LKDashboardText.appendImage(named: "icon_arrowRight_orange", baselineOffset: 0, marginLeft: 2, marginRight: 0, to: text) + DashboardText.appendImage(named: "icon_arrowRight_orange", baselineOffset: 0, marginLeft: 2, marginRight: 0, to: text) revealControl.label.attributedStringValue = text } @@ -144,13 +144,13 @@ final class LKDashboardSearchPropView: LKDashboardSearchCardView { case .enumInt, .enumLong: let enumValue = (attribute.value as? NSNumber)?.intValue ?? 0 let enumListName = DashboardBlueprint.enumListName(withAttrID: attribute.identifier) - return LKEnumListRegistry.shared.desc(forEnumName: enumListName, value: enumValue) ?? "" + return EnumListRegistry.shared.desc(forEnumName: enumListName, value: enumValue) ?? "" case .uiColor: guard let color = NSColor.lk_color(fromRGBAComponents: attribute.value as? [NSNumber]) else { return "nil" } - return LKPreferenceManager.shared.rgbaFormat ? color.rgbaString() : color.hexString() + return PreferenceManager.shared.rgbaFormat ? color.rgbaString() : color.hexString() case .shadow, .json: return "……" @@ -162,28 +162,28 @@ final class LKDashboardSearchPropView: LKDashboardSearchCardView { } } -protocol LKDashboardSearchMethodsViewDelegate: AnyObject { - func dashboardSearchMethodsView(_ view: LKDashboardSearchMethodsView, requestToInvokeMethod method: String, oid: UInt) +protocol DashboardSearchMethodsViewDelegate: AnyObject { + func dashboardSearchMethodsView(_ view: DashboardSearchMethodsView, requestToInvokeMethod method: String, oid: UInt) } /// The methods without arguments that match the search; a click invokes /// one. -final class LKDashboardSearchMethodsView: LKDashboardSearchCardView { +final class DashboardSearchMethodsView: DashboardSearchCardView { private let insetTop: CGFloat = 5 private let contentMarginTop: CGFloat = 10 private let itemInterspace: CGFloat = 8 - private let titleLabel = LKLabel() - private var errorLabel: LKLabel? - private var itemViews: [LKTextControl] = [] + private let titleLabel = TextLabel() + private var errorLabel: TextLabel? + private var itemViews: [TextControl] = [] private var methodNames: [ObjectIdentifier: String] = [:] private var oid: UInt = 0 - weak var delegate: LKDashboardSearchMethodsViewDelegate? + weak var delegate: DashboardSearchMethodsViewDelegate? override init(frame frameRect: NSRect) { super.init(frame: frameRect) - titleLabel.font = LKDashboardStyle.font(12) + titleLabel.font = DashboardStyle.font(12) titleLabel.textColor = .secondaryLabelColor titleLabel.stringValue = NSLocalizedString("Click to invoke methods below and get the return value.", comment: "") addSubview(titleLabel) @@ -195,7 +195,7 @@ final class LKDashboardSearchMethodsView: LKDashboardSearchCardView { override func layout() { super.layout() - let inset = LKDashboardMetrics.searchCardInset + let inset = DashboardMetrics.searchCardInset let width = frame.width - inset * 2 if titleLabel.isVisible { titleLabel.dashboardLayout.x(inset).width(width).heightToFit().y(insetTop) @@ -211,7 +211,7 @@ final class LKDashboardSearchMethodsView: LKDashboardSearchCardView { } override func sizeThatFits(_ limitedSize: NSSize) -> NSSize { - let contentWidth = limitedSize.width - LKDashboardMetrics.searchCardInset * 2 + let contentWidth = limitedSize.width - DashboardMetrics.searchCardInset * 2 var size = limitedSize if titleLabel.isVisible { var height = titleLabel.height(forWidth: contentWidth) + insetTop + contentMarginTop @@ -232,7 +232,7 @@ final class LKDashboardSearchMethodsView: LKDashboardSearchCardView { errorLabel?.isHidden = true while itemViews.count < methods.count { - let control = LKTextControl() + let control = TextControl() control.label.alignment = .left control.label.maximumNumberOfLines = 0 control.adjustAlphaWhenClick = true @@ -247,8 +247,8 @@ final class LKDashboardSearchMethodsView: LKDashboardSearchCardView { } view.isHidden = false methodNames[ObjectIdentifier(view)] = methods[idx] - let text = LKDashboardText.attributed(methods[idx], font: LKDashboardStyle.font(13), color: LKDashboardStyle.rgb(74, 144, 226)) - LKDashboardText.appendImage(named: "icon_arrowRight_blue", baselineOffset: -1, marginLeft: 2, marginRight: 0, to: text) + let text = DashboardText.attributed(methods[idx], font: DashboardStyle.font(13), color: DashboardStyle.rgb(74, 144, 226)) + DashboardText.appendImage(named: "icon_arrowRight_blue", baselineOffset: -1, marginLeft: 2, marginRight: 0, to: text) view.label.attributedStringValue = text view.needsLayout = true } @@ -259,13 +259,13 @@ final class LKDashboardSearchMethodsView: LKDashboardSearchCardView { NSLog("%@", String(describing: error)) itemViews.forEach { $0.isHidden = true } titleLabel.isHidden = true - let label: LKLabel + let label: TextLabel if let errorLabel { label = errorLabel } else { - label = LKLabel() + label = TextLabel() label.textColor = .labelColor - label.font = LKDashboardStyle.font(12) + label.font = DashboardStyle.font(12) addSubview(label) errorLabel = label } @@ -285,10 +285,10 @@ final class LKDashboardSearchMethodsView: LKDashboardSearchCardView { /// The selectors without arguments of each class, fetched once per class /// until the hierarchy reloads. -final class LKDashboardSearchMethodsDataSource { +final class DashboardSearchMethodsDataSource { /// The live document whose app answers; nil for a document read from a /// file. - weak var liveDocument: LookinLiveDocument? + weak var liveDocument: LiveDocument? /// Class name to selector names. private var classesToSelectors: [String: [String]] = [:] @@ -296,10 +296,10 @@ final class LKDashboardSearchMethodsDataSource { @MainActor func nonArgMethods(ofClass className: String?) async throws -> [String] { guard let className, !className.isEmpty else { - throw LKConnectionError.inner + throw ConnectionError.inner } guard let inspectableApp = liveDocument?.inspectableApp else { - throw LKConnectionError.noConnect + throw ConnectionError.noConnect } if let cached = classesToSelectors[className] { return cached diff --git a/LookInside/DebugE2E/LKDebugE2EDump.swift b/LookInside/DebugE2E/DebugE2EDump.swift similarity index 88% rename from LookInside/DebugE2E/LKDebugE2EDump.swift rename to LookInside/DebugE2E/DebugE2EDump.swift index eaf8d6e6..8659bb4c 100644 --- a/LookInside/DebugE2E/LKDebugE2EDump.swift +++ b/LookInside/DebugE2E/DebugE2EDump.swift @@ -9,7 +9,7 @@ /// detail the async update manager requests, then writes into the directory: /// /// snapshot.json hierarchy + merged details, normalized like - /// lookin-probe's snapshot (LookinSnapshotNormalizer) + /// lookin-probe's snapshot (SnapshotNormalizer) /// host-window.png the Host's own document window, drawn in process /// /// and exits 0. A step that runs past LOOKINSIDE_DEBUG_E2E_TIMEOUT seconds @@ -39,11 +39,11 @@ /// before the inspected app, so the launch window is captured with no /// app; the driver then launches the app and creates the file. /// LOOKINSIDE_DEBUG_UI_SNAPSHOT_DIR= - /// After writing the dump, run the UI scenes of LKDebugUISnapshots + /// After writing the dump, run the UI scenes of DebugUISnapshots /// against the loaded document instead of exiting; the Host exits /// when they are done. @MainActor - final class LKDebugE2EDump: NSObject { + final class DebugE2EDump: NSObject { private static let directoryKey = "LOOKINSIDE_DEBUG_E2E_DUMP_DIR" private static let bundleIDKey = "LOOKINSIDE_DEBUG_E2E_BUNDLE_ID" private static let timeoutKey = "LOOKINSIDE_DEBUG_E2E_TIMEOUT" @@ -79,7 +79,7 @@ private static let settleInterval: TimeInterval = 1.5 /// The running dump; it lives until the process exits. - private static var current: LKDebugE2EDump? + private static var current: DebugE2EDump? private let directory: String private let bundleID: String? @@ -97,8 +97,8 @@ private var nextAppPoll: Date? private var lastAppListSummary: String? - private var app: LKInspectableApp? - private var document: LookinLiveDocument? + private var app: InspectableApp? + private var document: LiveDocument? private var sawUpdating = false private var idleSince: Date? private var settleUntil = Date() @@ -133,7 +133,7 @@ guard let directory = environment[directoryKey], !directory.isEmpty else { return } - let dump = LKDebugE2EDump(directory: (directory as NSString).standardizingPath, environment: environment) + let dump = DebugE2EDump(directory: (directory as NSString).standardizingPath, environment: environment) current = dump NotificationCenter.default.addObserver( dump, @@ -146,7 +146,7 @@ /// LOOKINSIDE_DEBUG_E2E_PREPARE_LICENSE_CSR: see the type comment. private static func prepareLicenseKeyWritingRequest(to path: String) { do { - let pem = try LKSwiftUISupportGatekeeper.sharedInstance() + let pem = try SwiftUISupportGatekeeper.sharedInstance() .debugMakeTestKeyCertificateSigningRequestPEM(commonName: "LookInside Host E2E Test Device") try pem.write(toFile: path, atomically: true, encoding: .utf8) } catch { @@ -161,8 +161,8 @@ let target = (bundleID?.isEmpty == false) ? bundleID! : "the first inspectable app" log("waiting for \(target)\(expectsLicensed ? " on a licensed channel" : "") (timeout \(String(format: "%.0f", timeout))s per step)") enterPhase(.waitingForApp) - if LKDebugUISnapshots.isEnabled { - LKDebugUISnapshots.captureLaunchScene() + if DebugUISnapshots.isEnabled { + DebugUISnapshots.captureLaunchScene() } let timer = Timer.scheduledTimer( timeInterval: Self.tickInterval, @@ -221,7 +221,7 @@ switch phase { case .waitingForApp: if loggedLicenseWait { - let state = LKSwiftUISupportGatekeeper.sharedInstance().activationState.rawValue + let state = SwiftUISupportGatekeeper.sharedInstance().activationState.rawValue return "timed out waiting for the license handshake on \(bundleID ?? "the app") (activation state \(state))" } return "timed out waiting for an inspectable app; last app list: \(lastAppListSummary ?? "none received")" @@ -241,12 +241,12 @@ } if NSApp.windows.contains(where: \.isVisible) { notedFirstWindow = true - LKSwiftUISupportGatekeeper.sharedInstance().debugNoteFirstWindowShown() + SwiftUISupportGatekeeper.sharedInstance().debugNoteFirstWindowShown() log("a Host window is visible; first-window signing gate satisfied") } } - /// Same list the launch window shows: LKDebugE2EDumpWriter.fetchApps(completion:). + /// Same list the launch window shows: DebugE2EDumpWriter.fetchApps(completion:). private func pollApps() { if fetchingApps { return @@ -256,13 +256,13 @@ } fetchingApps = true nextAppPoll = Date(timeIntervalSinceNow: Self.appPollInterval) - LKDebugE2EDumpWriter.fetchApps { [self] apps in + DebugE2EDumpWriter.fetchApps { [self] apps in fetchingApps = false guard phase == .waitingForApp else { return } var summary: [String] = [] - var target: LKInspectableApp? + var target: InspectableApp? for app in apps ?? [] { let bundleID = app.appInfo?.appBundleIdentifier ?? "?" if let error = app.serverVersionError { @@ -284,7 +284,7 @@ // Each app-list request runs the license handshake on the channel // first (once the activation runtime allows signing), so polling // again is what retries it. - if expectsLicensed, !LKDebugE2EDumpWriter.isChannelLicensed(for: target) { + if expectsLicensed, !DebugE2EDumpWriter.isChannelLicensed(for: target) { if !loggedLicenseWait { loggedLicenseWait = true log("found \(target.appInfo?.appBundleIdentifier ?? "(null)"); waiting for the license handshake") @@ -295,16 +295,16 @@ } } - /// Mirrors LKLaunchViewController's app entry: fetch the hierarchy, open - /// a live document through LookinLiveDocumentController, prime its data + /// Mirrors LaunchViewController's app entry: fetch the hierarchy, open + /// a live document through LiveDocumentController, prime its data /// source with that hierarchy, close the launch window. The SwiftUI /// activation prompt that follows there is licensing UI and is left out. - private func open(_ app: LKInspectableApp) { - let licensed = LKDebugE2EDumpWriter.isChannelLicensed(for: app) ? "YES" : "NO" + private func open(_ app: InspectableApp) { + let licensed = DebugE2EDumpWriter.isChannelLicensed(for: app) ? "YES" : "NO" log("opening \(app.appInfo?.appBundleIdentifier ?? "(null)") (channel licensed: \(licensed))") self.app = app enterPhase(.opening) - LKDebugE2EDumpWriter.fetchHierarchy(for: app) { [self] info, error in + DebugE2EDumpWriter.fetchHierarchy(for: app) { [self] info, error in if let error { fail(.openFailed, "the hierarchy request failed: \(error as NSError)") return @@ -313,13 +313,13 @@ fail(.openFailed, "the hierarchy request returned nothing") return } - let (document, alreadyOpen) = LookinLiveDocumentController.shared.openLiveDocument(for: app) + let (document, alreadyOpen) = LiveDocumentController.shared.openLiveDocument(for: app) self.document = document enterPhase(.loadingDetails) if !alreadyOpen { document.hierarchyDataSource?.reload(with: info, keepState: false) } - LKNavigationManager.shared.closeLaunch() + NavigationManager.shared.closeLaunch() log("hierarchy loaded, \(document.hierarchyDataSource?.flatItems?.count ?? 0) items; waiting for details") } } @@ -365,23 +365,23 @@ return } let directoryURL = URL(fileURLWithPath: directory, isDirectory: true) - let platform = LKHelper.appInfoLooksLikeMacTarget(app?.appInfo) ? "macos" : "ios" + let platform = AppHelper.appInfoLooksLikeMacTarget(app?.appInfo) ? "macos" : "ios" do { - try LKDebugE2EDumpWriter.writeSnapshot(for: dataSource, app: document.inspectableApp, platform: platform, to: directoryURL) + try DebugE2EDumpWriter.writeSnapshot(for: dataSource, app: document.inspectableApp, platform: platform, to: directoryURL) } catch { fail(.writeFailed, "writing snapshot.json failed: \(error as NSError)") return } let window = document.windowControllers.first?.window let pngURL = directoryURL.appendingPathComponent("host-window.png") - guard let png = LKDebugWindowImage.pngData(of: window), !png.isEmpty, (try? png.write(to: pngURL, options: .atomic)) != nil else { + guard let png = DebugWindowImage.pngData(of: window), !png.isEmpty, (try? png.write(to: pngURL, options: .atomic)) != nil else { fail(.writeFailed, "capturing the Host window failed") return } log("wrote \(directory)") - if LKDebugUISnapshots.isEnabled { + if DebugUISnapshots.isEnabled { timer?.invalidate() - LKDebugUISnapshots.runScenes(for: document) { status in + DebugUISnapshots.runScenes(for: document) { status in exit(status) } return diff --git a/LookInside/DebugE2E/LKDebugE2EDumpWriter.swift b/LookInside/DebugE2E/DebugE2EDumpWriter.swift similarity index 78% rename from LookInside/DebugE2E/LKDebugE2EDumpWriter.swift rename to LookInside/DebugE2E/DebugE2EDumpWriter.swift index f4148ebd..7f4a274a 100644 --- a/LookInside/DebugE2E/LKDebugE2EDumpWriter.swift +++ b/LookInside/DebugE2E/DebugE2EDumpWriter.swift @@ -5,7 +5,7 @@ /// Writes what the Host loaded for one live document as a normalized /// `snapshot.json`, in the same format lookin-probe writes (shared - /// `LookinSnapshotNormalizer`), so the diff tool of + /// `SnapshotNormalizer`), so the diff tool of /// Scripts/reborn-e2e/LookinProbe compares both. /// /// The Host merges each detail into its display item, so a node has one @@ -14,22 +14,22 @@ /// node's `host` record names their pixel sizes; the pixels themselves are /// covered by lookin-probe. @objc(LKDebugE2EDumpWriter) - final class LKDebugE2EDumpWriter: NSObject { + final class DebugE2EDumpWriter: NSObject { @objc(writeSnapshotForDataSource:app:platform:toDirectory:error:) static func writeSnapshot( - for dataSource: LKStaticHierarchyDataSource, - app: LKInspectableApp, + for dataSource: StaticHierarchyDataSource, + app: InspectableApp, platform: String, to directory: URL ) throws { guard let hierarchy = dataSource.rawHierarchyInfo else { - throw LookinSnapshotError("the data source has no hierarchy") + throw SnapshotError("the data source has no hierarchy") } guard let appInfo = app.appInfo ?? hierarchy.appInfo else { - throw LookinSnapshotError("the inspected app has no app info") + throw SnapshotError("the inspected app has no app info") } - let nodes = LookinSnapshotNormalizer.collectNodes(roots: hierarchy.displayItems ?? []) - let childrenByParent = LookinSnapshotNormalizer.childrenByParent(nodes) + let nodes = SnapshotNormalizer.collectNodes(roots: hierarchy.displayItems ?? []) + let childrenByParent = SnapshotNormalizer.childrenByParent(nodes) let idsByItem = Dictionary( nodes.map { (ObjectIdentifier($0.item), $0.id) }, uniquingKeysWith: { first, _ in first } @@ -65,12 +65,12 @@ "parent": node.parentID.isEmpty ? NSNull() : node.parentID, "depth": node.depth, "children": childrenByParent[node.id] ?? [], - "item": LookinSnapshotNormalizer.nodeObjectJSON(item, imageSink: sizeOnlyImage), + "item": SnapshotNormalizer.nodeObjectJSON(item, imageSink: sizeOnlyImage), "host": host, ]) } - let session = LookinSnapshotNormalizer.sessionStateJSON( + let session = SnapshotNormalizer.sessionStateJSON( hostAppearance: NSApp.effectiveAppearance.name.rawValue ) let raw: [String: Any] = [ @@ -86,19 +86,19 @@ // Informational here; the diff checks session-state.json. "session": session, ], - "appInfo": LookinSnapshotNormalizer.appInfoJSON(appInfo, imageSink: sizeOnlyImage), - "hierarchy": LookinSnapshotNormalizer.hierarchyJSON(hierarchy), + "appInfo": SnapshotNormalizer.appInfoJSON(appInfo, imageSink: sizeOnlyImage), + "hierarchy": SnapshotNormalizer.hierarchyJSON(hierarchy), "roots": childrenByParent[""] ?? [], "displayed": displayingIDs, "nodes": flatNodes, ] - guard let snapshot = LookinSnapshotNormalizer.normalize(raw) as? [String: Any] else { - throw LookinSnapshotError("normalization did not return an object") + guard let snapshot = SnapshotNormalizer.normalize(raw) as? [String: Any] else { + throw SnapshotError("normalization did not return an object") } - let data = try LookinSnapshotNormalizer.serialize(snapshot) + let data = try SnapshotNormalizer.serialize(snapshot) try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true) try data.write(to: directory.appendingPathComponent("snapshot.json"), options: .atomic) - try LookinSnapshotNormalizer.writeSessionState(session, to: directory) + try SnapshotNormalizer.writeSessionState(session, to: directory) } /// The outline subtitle can list the ivars that reference the object @@ -108,7 +108,7 @@ guard let subtitle, !subtitle.isEmpty else { return NSNull() } let separator = " " return subtitle.components(separatedBy: separator) - .filter { !LookinSnapshotNormalizer.volatileIvarNames.contains($0) } + .filter { !SnapshotNormalizer.volatileIvarNames.contains($0) } .sorted() .joined(separator: separator) } @@ -128,14 +128,14 @@ } /// The list the launch window shows, from - /// `LKAppsManager.scanApps(needImages: true, localInfos: nil)`: + /// `AppsManager.scanApps(needImages: true, localInfos: nil)`: /// nil when no channel is connected. `completion` runs on the main /// thread, after this method returns. @objc(fetchAppsWithCompletion:) @MainActor - static func fetchApps(completion: @escaping ([LKInspectableApp]?) -> Void) { + static func fetchApps(completion: @escaping ([InspectableApp]?) -> Void) { Task { @MainActor in - let result = await LKAppsManager.shared.scanApps(needImages: true, localInfos: nil) + let result = await AppsManager.shared.scanApps(needImages: true, localInfos: nil) completion(result.channelCount == 0 ? nil : result.apps) } } @@ -144,7 +144,7 @@ /// `completion` runs on the main thread, after this method returns. @objc(fetchHierarchyForApp:completion:) @MainActor - static func fetchHierarchy(for app: LKInspectableApp, completion: @escaping (HierarchyInfo?, Error?) -> Void) { + static func fetchHierarchy(for app: InspectableApp, completion: @escaping (HierarchyInfo?, Error?) -> Void) { Task { @MainActor in do { try completion(await app.hierarchy(), nil) @@ -157,14 +157,14 @@ /// Whether the 220/221 license handshake succeeded on `app`'s channel, /// as the Host's connection layer records it. @objc(isChannelLicensedForApp:) - static func isChannelLicensed(for app: LKInspectableApp) -> Bool { + static func isChannelLicensed(for app: InspectableApp) -> Bool { MainActor.assumeIsolated { app.channel?.connectionState.licenseHandshake.isVerified ?? false } } private static func activationStateName() -> String { - switch LKSwiftUISupportGatekeeper.sharedInstance().activationState { + switch SwiftUISupportGatekeeper.sharedInstance().activationState { case .unknown: return "unknown" case .notActivated: return "notActivated" case .activated: return "activated" diff --git a/LookInside/DebugE2E/LKDebugUISnapshots.swift b/LookInside/DebugE2E/DebugUISnapshots.swift similarity index 85% rename from LookInside/DebugE2E/LKDebugUISnapshots.swift rename to LookInside/DebugE2E/DebugUISnapshots.swift index 555eef72..6291158e 100644 --- a/LookInside/DebugE2E/LKDebugUISnapshots.swift +++ b/LookInside/DebugE2E/DebugUISnapshots.swift @@ -5,7 +5,7 @@ /// DEBUG-only UI self-screenshots. When LOOKINSIDE_DEBUG_UI_SNAPSHOT_DIR /// is set (together with the end-to-end dump's LOOKINSIDE_DEBUG_E2E_*), /// the Host drives its own UI through a fixed list of scenes and writes - /// one PNG per scene, drawn in process (LKDebugWindowImage: no + /// one PNG per scene, drawn in process (DebugWindowImage: no /// Accessibility or Screen Recording permission), plus: /// /// scenes.json every scene: file, status (captured / skipped), @@ -21,7 +21,7 @@ /// captured ("launch-no-app"); then the marker is written. The dump /// waits for LOOKINSIDE_DEBUG_E2E_START_FILE before it looks for the /// app, so the driver launches the Example in between. - /// 2. LKDebugE2EDump opens the app, waits for every detail and writes its + /// 2. DebugE2EDump opens the app, waits for every detail and writes its /// snapshot, then hands the live document to `runScenes`. /// 3. The scenes run one after another in this launch, and the Host /// exits with 0 (all scenes captured or skipped), or non-zero. @@ -43,13 +43,13 @@ /// from the baseline's, and never loosens a threshold for it. @objc(LKDebugUISnapshots) @MainActor - final class LKDebugUISnapshots: NSObject { + final class DebugUISnapshots: NSObject { static let directoryVariable = "LOOKINSIDE_DEBUG_UI_SNAPSHOT_DIR" static let launchMarkerName = ".launch-captured" /// Content size of the inspector and reader windows, in points. static let documentContentSize = NSSize(width: 1280, height: 800) - /// Canonical snapshot ids (LookinSnapshotNormalizer, as in + /// Canonical snapshot ids (SnapshotNormalizer, as in /// host-dump-golden/macos) of the nodes the scenes select in /// LookInsideExampleAppKit's main window. static let contentStackID = "/NSWindow[0]/NSThemeFrame[0]/NSView[0]/NSSplitView[0]" @@ -63,7 +63,7 @@ static let stackViewID = contentStackID static let filterText = "TextField" - private static var shared: LKDebugUISnapshots? + private static var shared: DebugUISnapshots? private let directory: URL private var entries: [[String: Any]] = [] @@ -77,14 +77,14 @@ !(ProcessInfo.processInfo.environment[directoryVariable] ?? "").isEmpty } - private static func instance() -> LKDebugUISnapshots? { + private static func instance() -> DebugUISnapshots? { if let shared { return shared } guard let path = ProcessInfo.processInfo.environment[directoryVariable], !path.isEmpty else { return nil } - let snapshots = LKDebugUISnapshots(directory: URL(fileURLWithPath: (path as NSString).standardizingPath, isDirectory: true)) + let snapshots = DebugUISnapshots(directory: URL(fileURLWithPath: (path as NSString).standardizingPath, isDirectory: true)) shared = snapshots return snapshots } @@ -111,7 +111,7 @@ /// Steps 2 and 3: runs every scene against the loaded live document, /// then calls `completion` with the exit status. @objc(runScenesForDocument:completion:) - static func runScenes(for document: LookinLiveDocument, completion: @escaping (Int32) -> Void) { + static func runScenes(for document: LiveDocument, completion: @escaping (Int32) -> Void) { guard let snapshots = instance() else { completion(0) return @@ -134,13 +134,13 @@ private func launchScene() async throws { let window = try await waitFor("the launch window") { - LKNavigationManager.shared.launchWindowController?.window.flatMap { $0.isVisible ? $0 : nil } + NavigationManager.shared.launchWindowController?.window.flatMap { $0.isVisible ? $0 : nil } } quietWindows() // Two app-list rounds of the launch window (every 1.5 s), so its // "searching" state and progress bar have settled. await pause(3.5) - let apps = await LKAppsManager.shared.fetchAppInfos(needImages: false, localInfos: nil) + let apps = await AppsManager.shared.fetchAppInfos(needImages: false, localInfos: nil) if !apps.isEmpty { let names = apps.map { $0.appInfo?.appBundleIdentifier ?? "?" }.joined(separator: ", ") skip("launch-no-app", reason: "\(apps.count) inspectable app(s) already running: \(names)") @@ -149,18 +149,18 @@ try await capture("launch-no-app", window: window, includesInspectedApp: false) } - private func documentScenes(_ document: LookinLiveDocument) async throws { - guard let windowController = document.windowControllers.first as? LKStaticWindowController, + private func documentScenes(_ document: LiveDocument) async throws { + guard let windowController = document.windowControllers.first as? StaticWindowController, let window = windowController.window, let viewController = windowController.viewController, let dataSource = document.hierarchyDataSource - else { throw LookinSnapshotError("the live document has no inspector window") } - let preferences = LKPreferenceManager.shared + else { throw SnapshotError("the live document has no inspector window") } + let preferences = PreferenceManager.shared quietWindows() pinSize(of: window, to: Self.documentContentSize) logLayout(of: window) - let nodes = LookinSnapshotNormalizer.collectNodes(roots: dataSource.rawHierarchyInfo?.displayItems ?? []) + let nodes = SnapshotNormalizer.collectNodes(roots: dataSource.rawHierarchyInfo?.displayItems ?? []) let label = try node(Self.labelID, in: nodes) let imageView = try node(Self.imageViewID, in: nodes) let stackView = try node(Self.stackViewID, in: nodes) @@ -183,11 +183,11 @@ // Measure: label selected, image view hovered, measuring locked. select(label, in: dataSource) - preferences.measureState.setIntegerValue(LookinMeasureState.locked.rawValue, ignoreSubscriber: nil) + preferences.measureState.setIntegerValue(MeasureState.locked.rawValue, ignoreSubscriber: nil) dataSource.hoveredItem = imageView try await capture("measure", window: window, document: document) dataSource.hoveredItem = nil - preferences.measureState.setIntegerValue(LookinMeasureState.no.rawValue, ignoreSubscriber: nil) + preferences.measureState.setIntegerValue(MeasureState.no.rawValue, ignoreSubscriber: nil) // Console panel under the preview, label selected. viewController.showConsole = true @@ -203,24 +203,24 @@ // view is captured on its own; the exported data is then opened // as a .lookin file (Export -> Read round trip). guard let hierarchyInfo = dataSource.rawHierarchyInfo else { - throw LookinSnapshotError("the data source has no hierarchy") + throw SnapshotError("the data source has no hierarchy") } // Full image quality: below 1 the export scales every screenshot // down by drawing it, and that resampling is not pixel-stable // from run to run (measured: two variants of the reader's // preview at 50%). At 1 the images keep their size. var fileName: NSString? - guard let exported = LKExportManager.sharedInstance().data( + guard let exported = ExportManager.sharedInstance().data( from: hierarchyInfo, imageCompression: 1, fileName: &fileName ) - else { throw LookinSnapshotError("exporting the hierarchy returned no data") } + else { throw SnapshotError("exporting the hierarchy returned no data") } try await captureExportAccessory() try await readRoundTrip(exported) // Windows of their own. - LKNavigationManager.shared.showPreference() + NavigationManager.shared.showPreference() try await captureStandaloneWindow("preferences", controllerKey: "preferenceWindowController") - LKNavigationManager.shared.showAbout() + NavigationManager.shared.showAbout() try await captureStandaloneWindow("about", controllerKey: "aboutWindowController") try await captureActivationWindow() } @@ -235,19 +235,19 @@ if let document { continuation.resume(returning: document) } else { - continuation.resume(throwing: error ?? LookinSnapshotError("opening \(url.path) failed")) + continuation.resume(throwing: error ?? SnapshotError("opening \(url.path) failed")) } } } let readViewController = try await waitFor("the reader to load the file") { - (document.windowControllers.first?.contentViewController as? LKReadViewController) + (document.windowControllers.first?.contentViewController as? ReadViewController) } guard let window = document.windowControllers.first?.window, let dataSource = readViewController.hierarchyDataSource - else { throw LookinSnapshotError("the reader has no window") } + else { throw SnapshotError("the reader has no window") } quietWindows() pinSize(of: window, to: Self.documentContentSize) - let nodes = LookinSnapshotNormalizer.collectNodes(roots: dataSource.rawHierarchyInfo?.displayItems ?? []) + let nodes = SnapshotNormalizer.collectNodes(roots: dataSource.rawHierarchyInfo?.displayItems ?? []) try select(node(Self.labelID, in: nodes), in: dataSource) try await capture("read-roundtrip", window: window) document.close() @@ -261,7 +261,7 @@ static let exportAccessoryDataSize: UInt = 46_200_000 private func captureExportAccessory() async throws { - let accessory = LKExportAccessoryView() + let accessory = ExportAccessoryView() accessory.dataSize = Self.exportAccessoryDataSize accessory.setFrameSize(accessory.sizeThatFits(NSSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude))) @@ -277,7 +277,7 @@ } private func captureStandaloneWindow(_ name: String, controllerKey: String) async throws { - let navigation = LKNavigationManager.shared + let navigation = NavigationManager.shared let window = try await waitFor("the \(name) window") { (navigation.value(forKey: controllerKey) as? NSWindowController)?.window.flatMap { $0.isVisible ? $0 : nil } } @@ -288,7 +288,7 @@ } private func captureActivationWindow() async throws { - let window = await LKSwiftUISupportGatekeeper.sharedInstance().debugPreparedActivationWindow() + let window = await SwiftUISupportGatekeeper.sharedInstance().debugPreparedActivationWindow() window.center() window.orderFront(nil) quietWindows() @@ -298,14 +298,14 @@ // MARK: - Driving the UI - private func node(_ id: String, in nodes: [LookinSnapshotNormalizer.Node]) throws -> DisplayItem { + private func node(_ id: String, in nodes: [SnapshotNormalizer.Node]) throws -> DisplayItem { guard let node = nodes.first(where: { $0.id == id }) else { - throw LookinSnapshotError("no node \(id)") + throw SnapshotError("no node \(id)") } return node.item } - private func select(_ item: DisplayItem, in dataSource: LKHierarchyDataSource) { + private func select(_ item: DisplayItem, in dataSource: HierarchyDataSource) { // A fresh selection, so the dashboard renders its cards again // with the current collapsed-group preference. dataSource.selectedItem = nil @@ -314,19 +314,19 @@ /// Types into the hierarchy's filter field as the user would; nil /// ends the filter through its close button path. - private func filterHierarchy(_ viewController: LKStaticViewController, text: String?) async throws { + private func filterHierarchy(_ viewController: StaticViewController, text: String?) async throws { guard let hierarchyView = viewController.currentHierarchyView(), - let field = hierarchyView.value(forKey: "searchTextFieldView") as? LKTextFieldView - else { throw LookinSnapshotError("the hierarchy view has no filter field") } + let field = hierarchyView.value(forKey: "searchTextFieldView") as? TextFieldView + else { throw SnapshotError("the hierarchy view has no filter field") } field.textField.stringValue = text ?? "" hierarchyView.delegate?.hierarchyView(hierarchyView, didInputSearch: text) } - private func dashboardContentView(of viewController: LKStaticViewController) throws -> NSView { + private func dashboardContentView(of viewController: StaticViewController) throws -> NSView { guard let dashboard = viewController.value(forKey: "dashboardController") as? NSViewController, let scrollView = dashboard.value(forKey: "scrollView") as? NSScrollView, let content = scrollView.documentView - else { throw LookinSnapshotError("the dashboard has no scroll view") } + else { throw SnapshotError("the dashboard has no scroll view") } return content } @@ -336,9 +336,9 @@ private func pinSize(of window: NSWindow, to size: NSSize) { window.setContentSize(size) window.contentView?.layoutSubtreeIfNeeded() - var splitViews: [LKSplitView] = [] + var splitViews: [SplitView] = [] func collect(_ view: NSView) { - if let split = view as? LKSplitView { + if let split = view as? SplitView { splitViews.append(split) } view.subviews.forEach(collect) @@ -377,14 +377,14 @@ // MARK: - Capture - private func capture(_ name: String, window: NSWindow, document: LookinLiveDocument? = nil, + private func capture(_ name: String, window: NSWindow, document: LiveDocument? = nil, includesInspectedApp: Bool = true) async throws { try await settle(window, document: document) let restore = maskAddresses(in: window.contentView?.superview) defer { restore() } - guard let png = LKDebugWindowImage.pngData(of: window) else { - throw LookinSnapshotError("capturing \(name) failed") + guard let png = DebugWindowImage.pngData(of: window) else { + throw SnapshotError("capturing \(name) failed") } try write(png, scene: name, window: window, includesInspectedApp: includesInspectedApp) } @@ -393,13 +393,13 @@ try await settle(window, document: nil) let restore = maskAddresses(in: view) defer { restore() } - guard let png = LKDebugWindowImage.pngData(of: view) else { - throw LookinSnapshotError("capturing \(name) failed") + guard let png = DebugWindowImage.pngData(of: view) else { + throw SnapshotError("capturing \(name) failed") } try write(png, scene: name, window: window, includesInspectedApp: true) } - private func settle(_ window: NSWindow, document: LookinLiveDocument?) async throws { + private func settle(_ window: NSWindow, document: LiveDocument?) async throws { if let manager = document?.asyncUpdateManager { _ = try await waitFor("detail updates to finish") { manager.isUpdating() ? nil : true } } @@ -484,7 +484,7 @@ let state = sessionState(window: window, includesInspectedApp: includesInspectedApp) if includesInspectedApp, runState == nil { runState = state - try LookinSnapshotNormalizer.writeSessionState(state, to: directory) + try SnapshotNormalizer.writeSessionState(state, to: directory) } entries.append(["name": name, "file": file, "status": "captured", "state": state]) Self.log("captured \(name)") @@ -495,13 +495,13 @@ Self.log("SKIP \(name): \(reason)") } - /// The session state now (LookinSnapshotNormalizer.sessionStateJSON) + /// The session state now (SnapshotNormalizer.sessionStateJSON) /// plus what only the Host knows: whether it is active, whether the /// captured window is key, and the window's backing scale. private func sessionState(window: NSWindow, includesInspectedApp: Bool) -> [String: Any] { var state = includesInspectedApp - ? LookinSnapshotNormalizer.sessionStateJSON(hostAppearance: NSApp.effectiveAppearance.name.rawValue) - : LookinSnapshotNormalizer.systemSessionStateJSON() + ? SnapshotNormalizer.sessionStateJSON(hostAppearance: NSApp.effectiveAppearance.name.rawValue) + : SnapshotNormalizer.systemSessionStateJSON() state["hostAppearance"] = NSApp.effectiveAppearance.name.rawValue state["hostAppActive"] = NSApp.isActive state["hostWindowKey"] = window.isKeyWindow @@ -528,7 +528,7 @@ return value } if Date() > deadline { - throw LookinSnapshotError("timed out waiting for \(what)") + throw SnapshotError("timed out waiting for \(what)") } await pause(0.25) } diff --git a/LookInside/DebugE2E/LKDebugWindowImage.swift b/LookInside/DebugE2E/DebugWindowImage.swift similarity index 96% rename from LookInside/DebugE2E/LKDebugWindowImage.swift rename to LookInside/DebugE2E/DebugWindowImage.swift index fcb6fb9d..4a89c214 100644 --- a/LookInside/DebugE2E/LKDebugWindowImage.swift +++ b/LookInside/DebugE2E/DebugWindowImage.swift @@ -4,15 +4,15 @@ /// Draws a Host window or view into a bitmap in process, so no /// screen-recording permission is involved. Shared by the end-to-end - /// dump (LKDebugE2EDump.swift, host-window.png) and the UI snapshots - /// (LKDebugUISnapshots.swift). + /// dump (DebugE2EDump.swift, host-window.png) and the UI snapshots + /// (DebugUISnapshots.swift). /// /// SceneKit views render through Metal, which `cacheDisplay(in:to:)` does /// not capture, so each one's `SCNView.snapshot()` is drawn over its area, /// clipped away from the views that sit on top of it (outline, dashboard, /// toolbar). @objc(LKDebugWindowImage) - final class LKDebugWindowImage: NSObject { + final class DebugWindowImage: NSObject { /// PNG of `window`'s frame view: title bar and toolbar included. @objc(pngDataOfWindow:) static func pngData(of window: NSWindow?) -> Data? { diff --git a/LookInside/DebugE2E/LookinSnapshotNormalizer.swift b/LookInside/DebugE2E/SnapshotNormalizer.swift similarity index 95% rename from LookInside/DebugE2E/LookinSnapshotNormalizer.swift rename to LookInside/DebugE2E/SnapshotNormalizer.swift index 28a2006a..81d3ed7d 100644 --- a/LookInside/DebugE2E/LookinSnapshotNormalizer.swift +++ b/LookInside/DebugE2E/SnapshotNormalizer.swift @@ -1,7 +1,7 @@ // Shared by two regression tools so their outputs stay comparable: // - lookin-probe (Scripts/reborn-e2e/LookinProbe), which links this file // through a symlink and defines LOOKIN_PROBE; -// - the Host's DEBUG end-to-end dump (LKDebugE2EDump.swift). +// - the Host's DEBUG end-to-end dump (DebugE2EDump.swift). // It needs only Foundation, AppKit and the LookinCore model classes, which // the probe imports as a module and the Host sees through its bridging // header. Release Host builds compile it out. @@ -14,7 +14,7 @@ import LookinCoreImpl #endif - struct LookinSnapshotError: Error, CustomStringConvertible { + struct SnapshotError: Error, CustomStringConvertible { let description: String init(_ description: String) { @@ -25,7 +25,7 @@ /// Normalization rules for inspection snapshots: stable node ids, /// volatile-value masking, ordering of hash-table arrays, and the /// one-line-per-node JSON layout. - enum LookinSnapshotNormalizer { + enum SnapshotNormalizer { // MARK: - Nodes struct Node { @@ -229,8 +229,8 @@ static let appImageNames = ["1": "appIcon", "2": "screenshot"] /// `appInfo` as JSON with the machine-identifying fields masked. - static func appInfoJSON(_ appInfo: InspectedAppInfo, imageSink: @escaping LookinSnapshotWireJSON.ImageSink) -> [String: Any] { - var json = LookinSnapshotWireJSON(imageSink: imageSink).record(appInfo, keyPath: []) + static func appInfoJSON(_ appInfo: InspectedAppInfo, imageSink: @escaping SnapshotWireJSON.ImageSink) -> [String: Any] { + var json = SnapshotWireJSON(imageSink: imageSink).record(appInfo, keyPath: []) // "3" = deviceDescription: on a Mac that is the computer name, and // the model identifier names the hardware. Neither belongs in a // checked-in fixture; keep only whether they were sent. @@ -243,15 +243,15 @@ /// `hierarchy` as JSON without its display items ("1") and app info /// ("2"), which are recorded separately (LookinHierarchyInfo.m). static func hierarchyJSON(_ hierarchy: HierarchyInfo) -> [String: Any] { - LookinSnapshotWireJSON(skippedKeys: ["LookinHierarchyInfo": ["1", "2"]]) { _, _ in + SnapshotWireJSON(skippedKeys: ["LookinHierarchyInfo": ["1", "2"]]) { _, _ in ["$image": ""] }.record(hierarchy, keyPath: []) } /// A display item or detail as JSON without its `subitems`; the tree /// is recorded through the node ids instead. - static func nodeObjectJSON(_ object: NSObject, imageSink: @escaping LookinSnapshotWireJSON.ImageSink) -> [String: Any] { - LookinSnapshotWireJSON( + static func nodeObjectJSON(_ object: NSObject, imageSink: @escaping SnapshotWireJSON.ImageSink) -> [String: Any] { + SnapshotWireJSON( skippedKeys: [ "LookinDisplayItem": ["subitems"], "LookinDisplayItemDetail": ["subitems"], @@ -325,7 +325,7 @@ ) } if unorderedArrayKeys.contains(key), let array = normalized as? [Any] { - out[key] = array.sorted { LookinSnapshotWireJSON.sortKey($0) < LookinSnapshotWireJSON.sortKey($1) } + out[key] = array.sorted { SnapshotWireJSON.sortKey($0) < SnapshotWireJSON.sortKey($1) } } else { out[key] = normalized } @@ -356,7 +356,7 @@ if classes.count == 1, normalized.count > 1, unorderedElementClasses.isSuperset(of: classes), normalized.allSatisfy({ $0 is [String: Any] }) { - return normalized.sorted { LookinSnapshotWireJSON.sortKey($0) < LookinSnapshotWireJSON.sortKey($1) } + return normalized.sorted { SnapshotWireJSON.sortKey($0) < SnapshotWireJSON.sortKey($1) } } return normalized case let double as Double: @@ -405,7 +405,7 @@ // JSONSerialization raises an Objective-C exception on a value it // cannot write; name the value instead. if let path = firstUnwritablePath(snapshot, path: "$") { - throw LookinSnapshotError("cannot write \(path) as JSON") + throw SnapshotError("cannot write \(path) as JSON") } var header = snapshot let nodes = header.removeValue(forKey: "nodes") as? [Any] ?? [] @@ -415,7 +415,7 @@ try String(decoding: JSONSerialization.data(withJSONObject: $0, options: [.sortedKeys, .withoutEscapingSlashes]), as: UTF8.self) } guard let range = text.range(of: "\"nodes\" : [\n\n ]") ?? text.range(of: "\"nodes\" : [\n ]") ?? text.range(of: "\"nodes\" : []") else { - throw LookinSnapshotError("unexpected header layout") + throw SnapshotError("unexpected header layout") } text.replaceSubrange(range, with: "\"nodes\" : [\n" + lines.joined(separator: ",\n") + "\n ]") return Data((text + "\n").utf8) @@ -430,7 +430,7 @@ /// /// Images (NSImage, or NSData holding PNG / TIFF / JPEG bytes) are handed to /// `imageSink`, which returns the JSON that stands in for them. - final class LookinSnapshotWireJSON { + final class SnapshotWireJSON { typealias ImageSink = (_ image: CGImage, _ keyPath: [String]) -> Any private let imageSink: ImageSink @@ -500,7 +500,7 @@ func record(_ object: NSObject, keyPath: [String]) -> [String: Any] { let className = NSStringFromClass(object.classForKeyedArchiver ?? type(of: object)) - let coder = LookinSnapshotRecordingCoder(owner: self, keyPath: keyPath, skipped: skippedKeys[className] ?? []) + let coder = SnapshotRecordingCoder(owner: self, keyPath: keyPath, skipped: skippedKeys[className] ?? []) (object as? NSCoding)?.encode(with: coder) var out = coder.fields out["$class"] = className @@ -590,14 +590,14 @@ } /// A keyed NSCoder that only records. Scalars keep their JSON type; objects - /// recurse through `LookinSnapshotWireJSON.convert`. - private final class LookinSnapshotRecordingCoder: NSCoder { + /// recurse through `SnapshotWireJSON.convert`. + private final class SnapshotRecordingCoder: NSCoder { private(set) var fields: [String: Any] = [:] - private let owner: LookinSnapshotWireJSON + private let owner: SnapshotWireJSON private let keyPath: [String] private let skipped: Set - init(owner: LookinSnapshotWireJSON, keyPath: [String], skipped: Set) { + init(owner: SnapshotWireJSON, keyPath: [String], skipped: Set) { self.owner = owner self.keyPath = keyPath self.skipped = skipped diff --git a/LookInside/Export/LKExportAccessoryView.swift b/LookInside/Export/ExportAccessoryView.swift similarity index 89% rename from LookInside/Export/LKExportAccessoryView.swift rename to LookInside/Export/ExportAccessoryView.swift index a283e44d..3416806c 100644 --- a/LookInside/Export/LKExportAccessoryView.swift +++ b/LookInside/Export/ExportAccessoryView.swift @@ -1,5 +1,5 @@ // -// LKExportAccessoryView.swift +// ExportAccessoryView.swift // LookInside // // The save panel accessory of the `.lookin` export: an image-quality menu @@ -10,7 +10,7 @@ import AppKit import LookInsideHostCore @objc(LKExportAccessoryView) -final class LKExportAccessoryView: LKBaseView { +final class ExportAccessoryView: BaseView { private static let insetTop: CGFloat = 20 private static let insetBottom: CGFloat = 10 private static let buttonWidth: CGFloat = 150 @@ -24,9 +24,9 @@ final class LKExportAccessoryView: LKBaseView { } } - private let compressionLabel = LKLabel() + private let compressionLabel = TextLabel() private let compressionButton = NSPopUpButton() - private let sizeLabel = LKLabel() + private let sizeLabel = TextLabel() private var compressionObservation: NSKeyValueObservation? private var lastObservedCompression: CGFloat? @@ -49,7 +49,7 @@ final class LKExportAccessoryView: LKBaseView { sizeLabel.alignment = .right addSubview(sizeLabel) - compressionObservation = LKPreferenceManager.shared.observe(\.preferredExportCompression, options: [.initial, .new]) { + compressionObservation = PreferenceManager.shared.observe(\.preferredExportCompression, options: [.initial, .new]) { [weak self] manager, _ in let compression = manager.preferredExportCompression MainActor.assumeIsolated { @@ -91,7 +91,7 @@ final class LKExportAccessoryView: LKBaseView { @objc private func handleCompressionButton() { let index = compressionButton.indexOfSelectedItem guard ExportNaming.compressionOptions.indices.contains(index) else { return } - LKPreferenceManager.shared.preferredExportCompression = CGFloat(ExportNaming.compressionOptions[index]) + PreferenceManager.shared.preferredExportCompression = CGFloat(ExportNaming.compressionOptions[index]) } override func sizeThatFits(_: NSSize) -> NSSize { diff --git a/LookInside/Export/LKExportManager.swift b/LookInside/Export/ExportManager.swift similarity index 89% rename from LookInside/Export/LKExportManager.swift rename to LookInside/Export/ExportManager.swift index 9be476f2..95f825f1 100644 --- a/LookInside/Export/LKExportManager.swift +++ b/LookInside/Export/ExportManager.swift @@ -1,5 +1,5 @@ // -// LKExportManager.swift +// ExportManager.swift // LookInside // // Writes a hierarchy as a `.lookin` archive (screenshots scaled by the chosen @@ -12,10 +12,10 @@ import LookInsideHostCore import UniformTypeIdentifiers @objc(LKExportManager) -final class LKExportManager: NSObject { - private static let shared = LKExportManager() +final class ExportManager: NSObject { + private static let shared = ExportManager() - @objc class func sharedInstance() -> LKExportManager { + @objc class func sharedInstance() -> ExportManager { shared } @@ -33,7 +33,7 @@ final class LKExportManager: NSObject { var soloScreenshots: [NSNumber: Data] = [:] var groupScreenshots: [NSNumber: Data] = [:] - let prefersViewOID = LKHelper.appInfoLooksLikeMacTarget(info.appInfo) + let prefersViewOID = AppHelper.appInfoLooksLikeMacTarget(info.appInfo) let allItems = DisplayItem.flatItems(fromHierarchicalItems: info.displayItems ?? []) for displayItem in allItems { let oid = displayItem.bestObjectOidPreferView(prefersViewOID) @@ -48,7 +48,7 @@ final class LKExportManager: NSObject { file.soloScreenshots = soloScreenshots file.groupScreenshots = groupScreenshots - let document = LookinArchiveDocument() + let document = ArchiveDocument() document.hierarchyFile = file var exportedData: Data? do { @@ -92,7 +92,7 @@ final class LKExportManager: NSObject { guard let image = displayItem.groupScreenshot, let imageData = image.tiffRepresentation(using: .lzw, factor: 1) else { - LKPeripheralAlerts.show(LKConnectionError.inner, in: LKPeripheralAlerts.keyWindow) + PeripheralAlerts.show(ConnectionError.inner, in: PeripheralAlerts.keyWindow) return } @@ -108,11 +108,11 @@ final class LKExportManager: NSObject { do { try imageData.write(to: URL(fileURLWithPath: url.path)) } catch { - LKPeripheralAlerts.show(error, in: LKPeripheralAlerts.keyWindow) + PeripheralAlerts.show(error, in: PeripheralAlerts.keyWindow) assertionFailure("Writing the screenshot failed: \(error)") } } - if let window = LKPeripheralAlerts.keyWindow { + if let window = PeripheralAlerts.keyWindow { panel.beginSheetModal(for: window, completionHandler: completion) } else { panel.begin(completionHandler: completion) diff --git a/LookInside/GestureDebug/LKGestureDebugSession.swift b/LookInside/GestureDebug/GestureDebugSession.swift similarity index 89% rename from LookInside/GestureDebug/LKGestureDebugSession.swift rename to LookInside/GestureDebug/GestureDebugSession.swift index 9fb811a7..5d249832 100644 --- a/LookInside/GestureDebug/LKGestureDebugSession.swift +++ b/LookInside/GestureDebug/GestureDebugSession.swift @@ -3,9 +3,9 @@ import Combine /// One capture belongs to one inspection window and one channel. @MainActor -final class LKGestureDebugSession: ObservableObject { - @Published private(set) var snapshots: [LKGestureCaptureSnapshot] = [] - @Published private(set) var records: [LKGestureCaptureRecord] = [] +final class GestureDebugSession: ObservableObject { + @Published private(set) var snapshots: [GestureCaptureSnapshot] = [] + @Published private(set) var records: [GestureCaptureRecord] = [] @Published private(set) var isRunning = false @Published private(set) var isStarting = false @Published private(set) var state = "stopped" @@ -18,24 +18,24 @@ final class LKGestureDebugSession: ObservableObject { @Published var selectedNodeID: String? @Published var followsLatest = true @Published var overlayEnabled = true - @Published private(set) var overlayStatus: LKGestureOverlayStatus? - @Published private(set) var nativeRegions: [LKNativeInteractionRegion] = [] - @Published private var lastNativeRegions: [LKNativeInteractionRegion] = [] - @Published private(set) var suggestions = LKSuggestionReport() - @Published private(set) var suggestionPlatform = LKSuggestionPlatform.unsupported - private var lastInteractions: LKInteractionSnapshot? + @Published private(set) var overlayStatus: GestureOverlayStatus? + @Published private(set) var nativeRegions: [NativeInteractionRegion] = [] + @Published private var lastNativeRegions: [NativeInteractionRegion] = [] + @Published private(set) var suggestions = HitTargetSuggestionReport() + @Published private(set) var suggestionPlatform = HitTargetSuggestionPlatform.unsupported + private var lastInteractions: InteractionSnapshot? @Published private(set) var appName = NSLocalizedString("No target", comment: "") @Published private(set) var supported = false - private var app: LKInspectableApp? - private var channel: LKChannel? + private var app: InspectableApp? + private var channel: ServerChannel? private var sessionID: String? private var lastSessionID: String? private var lastBatchSequence = 0 private var startTask: Task? private var subscriptions: [Task] = [] - var selectedSnapshot: LKGestureCaptureSnapshot? { + var selectedSnapshot: GestureCaptureSnapshot? { snapshots.first { $0.id == selectedSnapshotID } } @@ -44,7 +44,7 @@ final class LKGestureDebugSession: ObservableObject { } init() { - let manager = LKConnectionManager.shared + let manager = ConnectionManager.shared let pushes = manager.pushEvents() subscriptions.append(Task { [weak self] in for await push in pushes { @@ -64,7 +64,7 @@ final class LKGestureDebugSession: ObservableObject { }) } - func bind(to app: LKInspectableApp?) { + func bind(to app: InspectableApp?) { guard self.app !== app || channel !== app?.channel else { return } stop() self.app = app @@ -90,7 +90,7 @@ final class LKGestureDebugSession: ObservableObject { func start(window: NSWindow?) { guard supported, !isRunning, !isStarting, let app else { return } - guard LKSwiftUISupportGatekeeper.sharedInstance().allowProtectedFeatureAccess(for: window) else { return } + guard SwiftUISupportGatekeeper.sharedInstance().allowProtectedFeatureAccess(for: window) else { return } let token = UUID().uuidString sessionID = token lastSessionID = token @@ -189,7 +189,7 @@ final class LKGestureDebugSession: ObservableObject { } func archiveData() throws -> Data { - let archive = LKGestureCaptureArchive( + let archive = GestureCaptureArchive( appName: appName, bundleIdentifier: app?.appInfo?.appBundleIdentifier ?? "", sessionID: lastSessionID, snapshots: snapshots, records: records, nativeRegions: lastNativeRegions, interactions: lastInteractions, suggestionPlatform: suggestionPlatform @@ -207,10 +207,10 @@ final class LKGestureDebugSession: ObservableObject { subscriptions.removeAll() } - private func receive(_ data: Data, from channel: LKChannel) { + private func receive(_ data: Data, from channel: ServerChannel) { guard channel === self.channel, let sessionID, data.count <= 4 * 1024 * 1024 else { return } do { - let batch = try JSONDecoder().decode(LKGestureCaptureBatch.self, from: data) + let batch = try JSONDecoder().decode(GestureCaptureBatch.self, from: data) guard batch.schemaVersion == 1, batch.sessionID == sessionID, batch.sequence > lastBatchSequence else { return } let gap = lastBatchSequence > 0 && batch.sequence != lastBatchSequence + 1 diff --git a/LookInside/GestureDebug/LKGestureDebugView.swift b/LookInside/GestureDebug/GestureDebugView.swift similarity index 95% rename from LookInside/GestureDebug/LKGestureDebugView.swift rename to LookInside/GestureDebug/GestureDebugView.swift index e5ca4ea3..9d4ec268 100644 --- a/LookInside/GestureDebug/LKGestureDebugView.swift +++ b/LookInside/GestureDebug/GestureDebugView.swift @@ -1,7 +1,7 @@ import SwiftUI -struct LKGestureDebugView: View { - @ObservedObject var session: LKGestureDebugSession +struct GestureDebugView: View { + @ObservedObject var session: GestureDebugSession let start: () -> Void let export: () -> Void @State private var section = Section.responders @@ -31,9 +31,9 @@ struct LKGestureDebugView: View { .pickerStyle(.segmented) .padding(12) if section == .suggestions { - LKSuggestionsView(report: session.suggestions, platform: session.suggestionPlatform) + HitTargetSuggestionsView(report: session.suggestions, platform: session.suggestionPlatform) } else if section == .native { - LKNativeInteractionDetailView(regions: session.nativeRegions, isRunning: session.isRunning, overlayEnabled: session.overlayEnabled) + NativeInteractionDetailView(regions: session.nativeRegions, isRunning: session.isRunning, overlayEnabled: session.overlayEnabled) } else if let snapshot = session.selectedSnapshot { snapshotContent(snapshot) } else { @@ -178,7 +178,7 @@ struct LKGestureDebugView: View { } } - private func snapshotContent(_ snapshot: LKGestureCaptureSnapshot) -> some View { + private func snapshotContent(_ snapshot: GestureCaptureSnapshot) -> some View { VStack(alignment: .leading, spacing: 0) { HStack { Text("Host: \(snapshot.hostAddress ?? NSLocalizedString("Not reported", comment: ""))") @@ -225,10 +225,10 @@ struct LKGestureDebugView: View { }.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading) } - private func tree(_ nodes: [LKGestureCaptureNode], snapshot: LKGestureCaptureSnapshot) -> some View { + private func tree(_ nodes: [GestureCaptureNode], snapshot: GestureCaptureSnapshot) -> some View { HSplitView { List(selection: $session.selectedNodeID) { - OutlineGroup(LKGestureTreeItem.roots(from: nodes), children: \.children) { item in + OutlineGroup(GestureTreeItem.roots(from: nodes), children: \.children) { item in HStack(alignment: .top, spacing: 7) { Image(systemName: item.node.kind == "responder" ? "arrow.triangle.branch" : "hand.draw") .foregroundStyle(.secondary) @@ -245,7 +245,7 @@ struct LKGestureDebugView: View { } .listStyle(.inset).frame(minWidth: 290, idealWidth: 380) if let node = nodes.first(where: { $0.id == session.selectedNodeID }) { - LKGestureNodeDetailView(node: node, snapshot: snapshot) + GestureNodeDetailView(node: node, snapshot: snapshot) .frame(minWidth: 250, idealWidth: 300) } else { Text(nodes.isEmpty ? LocalizedStringKey("No nodes reported.") : LocalizedStringKey("Select a node to inspect its details.")) diff --git a/LookInside/GestureDebug/LKGestureDebugWindowController.swift b/LookInside/GestureDebug/GestureDebugWindowController.swift similarity index 88% rename from LookInside/GestureDebug/LKGestureDebugWindowController.swift rename to LookInside/GestureDebug/GestureDebugWindowController.swift index 996c09d5..a1b9355a 100644 --- a/LookInside/GestureDebug/LKGestureDebugWindowController.swift +++ b/LookInside/GestureDebug/GestureDebugWindowController.swift @@ -4,13 +4,13 @@ import UniformTypeIdentifiers @MainActor @objc(LKGestureDebugWindowController) -final class LKGestureDebugWindowController: NSWindowController, NSWindowDelegate { - private let session = LKGestureDebugSession() +final class GestureDebugWindowController: NSWindowController, NSWindowDelegate { + private let session = GestureDebugSession() private var appObservation: NSKeyValueObservation? - private weak var inspectionOwner: LKStaticWindowController? + private weak var inspectionOwner: StaticWindowController? @objc(initWithOwner:) - init(owner: LKStaticWindowController) { + init(owner: StaticWindowController) { let window = NSWindow( contentRect: NSRect(x: 0, y: 0, width: 1180, height: 740), styleMask: [.titled, .closable, .miniaturizable, .resizable], @@ -24,7 +24,7 @@ final class LKGestureDebugWindowController: NSWindowController, NSWindowDelegate window.delegate = self window.setFrameAutosaveName("LookInside.GestureDebug") window.center() - window.contentView = NSHostingView(rootView: LKGestureDebugView( + window.contentView = NSHostingView(rootView: GestureDebugView( session: session, start: { [weak self] in self?.session.start(window: self?.window) }, export: { [weak self] in self?.exportCapture() } diff --git a/LookInside/GestureDebug/LKGestureNodeDetailView.swift b/LookInside/GestureDebug/GestureNodeDetailView.swift similarity index 96% rename from LookInside/GestureDebug/LKGestureNodeDetailView.swift rename to LookInside/GestureDebug/GestureNodeDetailView.swift index 7c8cd54e..8c4e36cd 100644 --- a/LookInside/GestureDebug/LKGestureNodeDetailView.swift +++ b/LookInside/GestureDebug/GestureNodeDetailView.swift @@ -1,8 +1,8 @@ import SwiftUI -struct LKGestureNodeDetailView: View { - let node: LKGestureCaptureNode - let snapshot: LKGestureCaptureSnapshot +struct GestureNodeDetailView: View { + let node: GestureCaptureNode + let snapshot: GestureCaptureSnapshot var body: some View { ScrollView { diff --git a/LookInside/GestureDebug/LKSuggestionsView.swift b/LookInside/GestureDebug/HitTargetSuggestionsView.swift similarity index 94% rename from LookInside/GestureDebug/LKSuggestionsView.swift rename to LookInside/GestureDebug/HitTargetSuggestionsView.swift index 3f6f8671..05f6effc 100644 --- a/LookInside/GestureDebug/LKSuggestionsView.swift +++ b/LookInside/GestureDebug/HitTargetSuggestionsView.swift @@ -1,8 +1,8 @@ import SwiftUI -struct LKSuggestionsView: View { - let report: LKSuggestionReport - let platform: LKSuggestionPlatform +struct HitTargetSuggestionsView: View { + let report: HitTargetSuggestionReport + let platform: HitTargetSuggestionPlatform @State private var selectedID: String? var body: some View { @@ -54,11 +54,11 @@ struct LKSuggestionsView: View { } } - private func size(_ target: LKInteractionTarget) -> some View { + private func size(_ target: InteractionTarget) -> some View { Text("\(target.geometry.width ?? 0, specifier: "%.1f") × \(target.geometry.height ?? 0, specifier: "%.1f") pt") } - private func detail(_ warning: LKSuggestion) -> some View { + private func detail(_ warning: HitTargetSuggestion) -> some View { ScrollView { VStack(alignment: .leading, spacing: 14) { Text(warning.title).font(.headline) diff --git a/LookInside/GestureDebug/LKGestureCaptureModels.swift b/LookInside/GestureDebug/LKGestureCaptureModels.swift index 4d04ca4b..be5234e2 100644 --- a/LookInside/GestureDebug/LKGestureCaptureModels.swift +++ b/LookInside/GestureDebug/LKGestureCaptureModels.swift @@ -1,51 +1,51 @@ import Foundation /// Version 1 of the gesture capture JSON carried by Peertalk push 306. -struct LKGestureCaptureBatch: Codable { +struct GestureCaptureBatch: Codable { var schemaVersion: Int var sessionID: String var sequence: Int - var snapshots: [LKGestureCaptureSnapshot] - var records: [LKGestureCaptureRecord] + var snapshots: [GestureCaptureSnapshot] + var records: [GestureCaptureRecord] var recordCount: Int var redactedCount: Int var droppedCount: Int var state: String var message: String var pollDurationMS: Double - var overlayStatus: LKGestureOverlayStatus? - var nativeRegions: [LKNativeInteractionRegion]? - var interactions: LKInteractionSnapshot? + var overlayStatus: GestureOverlayStatus? + var nativeRegions: [NativeInteractionRegion]? + var interactions: InteractionSnapshot? } -struct LKNativeInteractionRegion: Codable, Identifiable { +struct NativeInteractionRegion: Codable, Identifiable { var id: String var source: String var viewClass: String var viewAddress: String var windowAddress: String var label: String - var handlers: [LKNativeInteractionHandler] - var geometry: LKGestureCaptureGeometry + var handlers: [NativeInteractionHandler] + var geometry: GestureCaptureGeometry var isActive: Bool var geometryKind: String } -struct LKNativeInteractionHandler: Codable { +struct NativeInteractionHandler: Codable { var kind: String var name: String var target: String? var events: UInt? } -struct LKGestureOverlayStatus: Codable { +struct GestureOverlayStatus: Codable { var mode: String var isEnabled: Bool var regionCount: Int var hostingViewCount: Int } -struct LKGestureCaptureRecord: Codable, Identifiable { +struct GestureCaptureRecord: Codable, Identifiable { var sequence: Int var timestamp: TimeInterval var receivedAt: TimeInterval @@ -58,7 +58,7 @@ struct LKGestureCaptureRecord: Codable, Identifiable { } } -struct LKGestureCaptureSnapshot: Codable, Identifiable { +struct GestureCaptureSnapshot: Codable, Identifiable { var id: String var timestamp: TimeInterval var receivedAt: TimeInterval @@ -68,10 +68,10 @@ struct LKGestureCaptureSnapshot: Codable, Identifiable { var inputPhase: String? var eventText: String var hitTest: String - var responders: [LKGestureCaptureNode] - var gestures: [LKGestureCaptureNode] - var bindings: [LKGestureCaptureBinding] - var rawRecords: [LKGestureCaptureRecord] + var responders: [GestureCaptureNode] + var gestures: [GestureCaptureNode] + var bindings: [GestureCaptureBinding] + var rawRecords: [GestureCaptureRecord] var complete: Bool var responderTreeComplete: Bool? var warnings: [String] @@ -81,7 +81,7 @@ struct LKGestureCaptureSnapshot: Codable, Identifiable { } } -struct LKGestureCaptureNode: Codable, Identifiable { +struct GestureCaptureNode: Codable, Identifiable { var id: String var parentID: String? var depth: Int @@ -90,19 +90,19 @@ struct LKGestureCaptureNode: Codable, Identifiable { var address: String? var attributeID: String? var phase: String? - var geometry: LKGestureCaptureGeometry? - var contentShape: LKGestureContentShape? + var geometry: GestureCaptureGeometry? + var contentShape: GestureContentShape? var detail: String var recordSequence: Int } -struct LKGestureContentShape: Codable { +struct GestureContentShape: Codable { var typeName: String var kind: String? var source: String } -struct LKGestureCaptureGeometry: Codable { +struct GestureCaptureGeometry: Codable { var x: Double? var y: Double? var width: Double? @@ -111,37 +111,37 @@ struct LKGestureCaptureGeometry: Codable { var coordinateSpace: String } -struct LKGestureCaptureBinding: Codable { +struct GestureCaptureBinding: Codable { var eventID: String var responderAddresses: [String] } -struct LKGestureCaptureArchive: Codable { +struct GestureCaptureArchive: Codable { var schemaVersion = 1 var appName: String var bundleIdentifier: String var sessionID: String? - var snapshots: [LKGestureCaptureSnapshot] - var records: [LKGestureCaptureRecord] - var nativeRegions: [LKNativeInteractionRegion]? - var interactions: LKInteractionSnapshot? - var suggestionPlatform: LKSuggestionPlatform? + var snapshots: [GestureCaptureSnapshot] + var records: [GestureCaptureRecord] + var nativeRegions: [NativeInteractionRegion]? + var interactions: InteractionSnapshot? + var suggestionPlatform: HitTargetSuggestionPlatform? } -struct LKGestureTreeItem: Identifiable { - var node: LKGestureCaptureNode - var children: [LKGestureTreeItem]? +struct GestureTreeItem: Identifiable { + var node: GestureCaptureNode + var children: [GestureTreeItem]? var id: String { node.id } - static func roots(from nodes: [LKGestureCaptureNode]) -> [LKGestureTreeItem] { + static func roots(from nodes: [GestureCaptureNode]) -> [GestureTreeItem] { let grouped = Dictionary(grouping: nodes, by: \.parentID) - func children(of parentID: String?, depth: Int) -> [LKGestureTreeItem] { + func children(of parentID: String?, depth: Int) -> [GestureTreeItem] { guard depth < 64 else { return [] } return (grouped[parentID] ?? []).map { node in let nested = children(of: node.id, depth: depth + 1) - return LKGestureTreeItem(node: node, children: nested.isEmpty ? nil : nested) + return GestureTreeItem(node: node, children: nested.isEmpty ? nil : nested) } } return children(of: nil, depth: 0) diff --git a/LookInside/GestureDebug/LKSuggestions.swift b/LookInside/GestureDebug/LKSuggestions.swift index 77c49173..ba879301 100644 --- a/LookInside/GestureDebug/LKSuggestions.swift +++ b/LookInside/GestureDebug/LKSuggestions.swift @@ -1,20 +1,20 @@ import Foundation -struct LKInteractionSnapshot: Codable { - var targets: [LKInteractionTarget] +struct InteractionSnapshot: Codable { + var targets: [InteractionTarget] var swiftUIStatus: String var nativeStatus: String var truncated: Bool } -struct LKInteractionTarget: Codable, Identifiable { +struct InteractionTarget: Codable, Identifiable { var id: String var source: String var name: String var targetAddress: String var hostAddress: String? var windowAddress: String? - var geometry: LKGestureCaptureGeometry + var geometry: GestureCaptureGeometry var geometryKind: String var shapeKind: String? @@ -24,7 +24,7 @@ struct LKInteractionTarget: Codable, Identifiable { } /// Product rules in logical points, selected from the inspected device, not the Mac host. -enum LKSuggestionPlatform: String, Codable { +enum HitTargetSuggestionPlatform: String, Codable { case iPhone, mac, unsupported var minimumTargetSize: Double? { @@ -57,9 +57,9 @@ enum LKSuggestionPlatform: String, Codable { } } -struct LKSuggestion: Identifiable { +struct HitTargetSuggestion: Identifiable { let ruleID = "interaction.minimum-target-size" - let target: LKInteractionTarget + let target: InteractionTarget let minimumSize: Double var id: String { "\(ruleID):\(target.id)" @@ -70,26 +70,26 @@ struct LKSuggestion: Identifiable { } } -enum LKHitTargetSuggestionRule { - static func evaluate(_ targets: [LKInteractionTarget], platform: LKSuggestionPlatform) -> [LKSuggestion] { +enum HitTargetSuggestionRule { + static func evaluate(_ targets: [InteractionTarget], platform: HitTargetSuggestionPlatform) -> [HitTargetSuggestion] { guard let minimum = platform.minimumTargetSize else { return [] } var seen: Set = [] return targets.compactMap { target in guard let width = target.geometry.width, let height = target.geometry.height, LookinHitTargetSizeDeficit(width, height, minimum) > 0, seen.insert(target.id).inserted else { return nil } - return LKSuggestion(target: target, minimumSize: minimum) + return HitTargetSuggestion(target: target, minimumSize: minimum) }.sorted { $0.id < $1.id } } } /// Replaced by each current-page sample. Historical events never revive warnings. -struct LKSuggestionReport { - private(set) var warnings: [LKSuggestion] = [] +struct HitTargetSuggestionReport { + private(set) var warnings: [HitTargetSuggestion] = [] private(set) var inspectedCount = 0 private(set) var coverageMessage = NSLocalizedString("Start capture to inspect the current page.", comment: "") - mutating func replace(with snapshot: LKInteractionSnapshot?, platform: LKSuggestionPlatform, isCapturing: Bool) { + mutating func replace(with snapshot: InteractionSnapshot?, platform: HitTargetSuggestionPlatform, isCapturing: Bool) { warnings = [] inspectedCount = 0 guard isCapturing else { @@ -104,7 +104,7 @@ struct LKSuggestionReport { coverageMessage = NSLocalizedString("Waiting for current interaction regions. Older Servers need an update to provide Suggestions.", comment: "") return } - warnings = LKHitTargetSuggestionRule.evaluate(snapshot.targets, platform: platform) + warnings = HitTargetSuggestionRule.evaluate(snapshot.targets, platform: platform) inspectedCount = snapshot.targets.count var notes = [NSLocalizedString("Checks reported interaction regions; custom hit testing and occlusion may change the effective target.", comment: "")] if snapshot.swiftUIStatus != "available" { diff --git a/LookInside/GestureDebug/LKNativeInteractionDetailView.swift b/LookInside/GestureDebug/NativeInteractionDetailView.swift similarity index 96% rename from LookInside/GestureDebug/LKNativeInteractionDetailView.swift rename to LookInside/GestureDebug/NativeInteractionDetailView.swift index becfc488..78f74a93 100644 --- a/LookInside/GestureDebug/LKNativeInteractionDetailView.swift +++ b/LookInside/GestureDebug/NativeInteractionDetailView.swift @@ -1,8 +1,8 @@ import SwiftUI /// Current native regions are independent of historical SwiftUI log events. -struct LKNativeInteractionDetailView: View { - let regions: [LKNativeInteractionRegion] +struct NativeInteractionDetailView: View { + let regions: [NativeInteractionRegion] let isRunning: Bool let overlayEnabled: Bool @State private var selection: String? @@ -55,7 +55,7 @@ struct LKNativeInteractionDetailView: View { } } - private func detail(_ region: LKNativeInteractionRegion) -> some View { + private func detail(_ region: NativeInteractionRegion) -> some View { ScrollView { VStack(alignment: .leading, spacing: 16) { field("View", region.viewClass) diff --git a/LookInside/Hierarchy/LKDanceUIAttrMaker.swift b/LookInside/Hierarchy/DanceUIAttributeMaker.swift similarity index 96% rename from LookInside/Hierarchy/LKDanceUIAttrMaker.swift rename to LookInside/Hierarchy/DanceUIAttributeMaker.swift index 1aceb8f8..6d8e43a8 100644 --- a/LookInside/Hierarchy/LKDanceUIAttrMaker.swift +++ b/LookInside/Hierarchy/DanceUIAttributeMaker.swift @@ -1,5 +1,5 @@ // -// LKDanceUIAttrMaker.swift +// DanceUIAttributeMaker.swift // LookInside // // Created by likai.123 on 2023/12/21. @@ -9,7 +9,7 @@ import Foundation /// Adds the "jump to the DanceUI file" class attribute to DanceUI nodes. -enum LKDanceUIAttrMaker { +enum DanceUIAttributeMaker { /// Gives `item` a Class group naming the type in `source` (DanceUI's /// JSON), unless it already has one. static func makeDanceUIJumpAttribute(_ item: DisplayItem, danceSource source: String) { diff --git a/LookInside/Hierarchy/LKHierarchyController.swift b/LookInside/Hierarchy/HierarchyController.swift similarity index 70% rename from LookInside/Hierarchy/LKHierarchyController.swift rename to LookInside/Hierarchy/HierarchyController.swift index b5787164..0da4c21b 100644 --- a/LookInside/Hierarchy/LKHierarchyController.swift +++ b/LookInside/Hierarchy/HierarchyController.swift @@ -1,5 +1,5 @@ // -// LKHierarchyController.swift +// HierarchyController.swift // LookInside // // Created by Li Kai on 2019/5/12. @@ -10,12 +10,12 @@ import AppKit @objc(LKHierarchyController) @objcMembers -class LKHierarchyController: LKBaseViewController, LKHierarchyViewDelegate { - private(set) var dataSource: LKHierarchyDataSource! - private(set) var hierarchyView: LKHierarchyView! +class HierarchyController: BaseViewController, HierarchyViewDelegate { + private(set) var dataSource: HierarchyDataSource! + private(set) var hierarchyView: HierarchyView! - init!(dataSource: LKHierarchyDataSource!) { - let hierarchyView = LKHierarchyView(dataSource: dataSource) + init!(dataSource: HierarchyDataSource!) { + let hierarchyView = HierarchyView(dataSource: dataSource) self.dataSource = dataSource self.hierarchyView = hierarchyView super.init(containerView: hierarchyView) @@ -23,7 +23,7 @@ class LKHierarchyController: LKBaseViewController, LKHierarchyViewDelegate { } required init?(coder _: NSCoder) { - fatalError("LKHierarchyController is not loaded from archives") + fatalError("HierarchyController is not loaded from archives") } func currentSelectedRowView() -> NSView! { @@ -46,16 +46,16 @@ class LKHierarchyController: LKBaseViewController, LKHierarchyViewDelegate { super.keyDown(with: event) } - // MARK: - LKHierarchyViewDelegate + // MARK: - HierarchyViewDelegate @objc(hierarchyView:didSelectItem:) - func hierarchyView(_: LKHierarchyView!, didSelect item: DisplayItem!) { + func hierarchyView(_: HierarchyView!, didSelect item: DisplayItem!) { dataSource.selectedItem = item } @objc(hierarchyView:didDoubleClickItem:) - func hierarchyView(_: LKHierarchyView!, didDoubleClick item: DisplayItem!) { - switch LKPreferenceManager.shared.doubleClickBehavior { + func hierarchyView(_: HierarchyView!, didDoubleClick item: DisplayItem!) { + switch PreferenceManager.shared.doubleClickBehavior { case .collapse: guard item.isExpandable else { return @@ -74,22 +74,22 @@ class LKHierarchyController: LKBaseViewController, LKHierarchyViewDelegate { /// `item` is nil when the mouse leaves the rows. @objc(hierarchyView:didHoverAtItem:) - func hierarchyView(_: LKHierarchyView!, didHoverAt item: DisplayItem!) { + func hierarchyView(_: HierarchyView!, didHoverAt item: DisplayItem!) { dataSource.hoveredItem = item } @objc(hierarchyView:needToCollapseItem:) - func hierarchyView(_: LKHierarchyView!, needToCollapse item: DisplayItem!) { + func hierarchyView(_: HierarchyView!, needToCollapse item: DisplayItem!) { dataSource.collapse(item) } @objc(hierarchyView:needToCollapseChildrenOfItem:) - func hierarchyView(_: LKHierarchyView!, needToCollapseChildrenOf item: DisplayItem!) { + func hierarchyView(_: HierarchyView!, needToCollapseChildrenOf item: DisplayItem!) { dataSource.collapseAllChildren(of: item) } @objc(hierarchyView:needToExpandItem:recursively:) - func hierarchyView(_: LKHierarchyView!, needToExpand item: DisplayItem!, recursively: Bool) { + func hierarchyView(_: HierarchyView!, needToExpand item: DisplayItem!, recursively: Bool) { if recursively { dataSource.expandItemsRooted(by: item) } else { @@ -98,7 +98,7 @@ class LKHierarchyController: LKBaseViewController, LKHierarchyViewDelegate { } @objc(hierarchyView:didInputSearchString:) - func hierarchyView(_: LKHierarchyView!, didInputSearch string: String!) { + func hierarchyView(_: HierarchyView!, didInputSearch string: String!) { NSLog("search string:%@", string ?? "(null)") if let string, !string.isEmpty { dataSource.search(with: string) diff --git a/LookInside/Hierarchy/LKHierarchyDataSource+KeyDown.swift b/LookInside/Hierarchy/HierarchyDataSource+KeyDown.swift similarity index 94% rename from LookInside/Hierarchy/LKHierarchyDataSource+KeyDown.swift rename to LookInside/Hierarchy/HierarchyDataSource+KeyDown.swift index a91ec515..1c7f94de 100644 --- a/LookInside/Hierarchy/LKHierarchyDataSource+KeyDown.swift +++ b/LookInside/Hierarchy/HierarchyDataSource+KeyDown.swift @@ -1,5 +1,5 @@ // -// LKHierarchyDataSource+KeyDown.swift +// HierarchyDataSource+KeyDown.swift // LookInside // // Created by Hares on 7/17/23. @@ -9,7 +9,7 @@ import AppKit import LookInsideHostCore -extension LKHierarchyDataSource { +extension HierarchyDataSource { /// Arrow keys move the selection and expand or collapse rows. Returns /// whether the key was handled. @objc(keyDown:) diff --git a/LookInside/Hierarchy/LKHierarchyDataSource.swift b/LookInside/Hierarchy/HierarchyDataSource.swift similarity index 94% rename from LookInside/Hierarchy/LKHierarchyDataSource.swift rename to LookInside/Hierarchy/HierarchyDataSource.swift index bf18d39f..68f5d13c 100644 --- a/LookInside/Hierarchy/LKHierarchyDataSource.swift +++ b/LookInside/Hierarchy/HierarchyDataSource.swift @@ -1,5 +1,5 @@ // -// LKHierarchyDataSource.swift +// HierarchyDataSource.swift // LookInside // // Created by Li Kai on 2019/5/6. @@ -10,7 +10,7 @@ import AppKit import LookInsideHostCore /// What the data source is showing. KVO-observable through `state`. -@objc enum LKHierarchyDataSourceState: UInt { +@objc enum HierarchyDataSourceState: UInt { case normal case search case focus @@ -19,7 +19,7 @@ import LookInsideHostCore /// What a hierarchy data source reports besides its KVO-observable /// properties (`state`, `selectedItem`, `hoveredItem`, `displayingFlatItems`, /// `rawHierarchyInfo`). -enum LKHierarchyDataSourceEvent { +enum HierarchyDataSourceEvent { case willReloadHierarchyInfo case didReloadHierarchyInfo case didReloadFlatItemsWithSearchOrFocus @@ -97,24 +97,24 @@ private func selfAndDescendants(of item: DisplayItem) -> [DisplayItem] { /// The hierarchy tree of a document: the flat rows, selection, hover, /// expansion, search and focus. Subclasses supply the preference manager. @objc(LKHierarchyDataSource) -class LKHierarchyDataSource: NSObject { +class HierarchyDataSource: NSObject { /// KVO-observable. - @objc dynamic var state: LKHierarchyDataSourceState { + @objc dynamic var state: HierarchyDataSourceState { storedState } - // Synchronous events; see LKSyncSignal. Everything sent on them also + // Synchronous events; see SyncSignal. Everything sent on them also // reaches `events()`. - final let willReloadHierarchyInfo = LKSyncSignal() - final let didReloadHierarchyInfo = LKSyncSignal() + final let willReloadHierarchyInfo = SyncSignal() + final let didReloadHierarchyInfo = SyncSignal() /// An item's `isHidden` or `alpha` changed. - final let itemDidChangeHiddenAlphaValue = LKSyncSignal() + final let itemDidChangeHiddenAlphaValue = SyncSignal() /// An item's attribute groups changed. - final let itemDidChangeAttrGroup = LKSyncSignal() + final let itemDidChangeAttrGroup = SyncSignal() /// The preview rebuilds from the whole tree. - final let itemDidChangeNoPreview = LKSyncSignal() + final let itemDidChangeNoPreview = SyncSignal() /// A search or focus changed `flatItems`. - final let didReloadFlatItemsWithSearchOrFocus = LKSyncSignal() + final let didReloadFlatItemsWithSearchOrFocus = SyncSignal() /// Every display item of the tree, visible or not. @objc var rawFlatItems: [DisplayItem]! { @@ -176,7 +176,7 @@ class LKHierarchyDataSource: NSObject { // Storage of the read-only properties. Writes go // through the setters below, which post the KVO notifications. - private var storedState: LKHierarchyDataSourceState = .normal + private var storedState: HierarchyDataSourceState = .normal private var storedDisplayingFlatItems: [DisplayItem]? private var storedRawHierarchyInfo: HierarchyInfo? private var storedSelectColorMenu: NSMenu? @@ -187,14 +187,14 @@ class LKHierarchyDataSource: NSObject { private var colorToAliasMap: [String: [String]] = [:] private var lastRGBAFormat: Bool? private var rgbaFormatObservation: NSKeyValueObservation? - private var signalSubscriptions: [LKSyncSubscription] = [] - final let eventBroadcaster = AsyncBroadcaster() + private var signalSubscriptions: [SyncSubscription] = [] + final let eventBroadcaster = AsyncBroadcaster() override init() { super.init() forwardSignalsToEvents() - rgbaFormatObservation = LKPreferenceManager.shared.observe(\.rgbaFormat, options: [.new]) { [weak self] preferences, _ in + rgbaFormatObservation = PreferenceManager.shared.observe(\.rgbaFormat, options: [.new]) { [weak self] preferences, _ in guard let self else { return } // Every change after the first value, skipping repeats. let format = preferences.rgbaFormat @@ -207,7 +207,7 @@ class LKHierarchyDataSource: NSObject { // Toggling the system-layout-guide visibility re-filters the visible // rows; the tree data itself keeps every node. - LKPreferenceManager.shared.showSystemLayoutGuides.subscribe( + PreferenceManager.shared.showSystemLayoutGuides.subscribe( self, action: #selector(handleShowSystemLayoutGuidesDidChange(_:)), relatedObject: nil @@ -232,15 +232,15 @@ class LKHierarchyDataSource: NSObject { willReloadHierarchyInfo.send() if !(info.colorAlias ?? [:]).isEmpty { - LKPreferenceManager.shared.receivingConfigTime_Color = Date().timeIntervalSince1970 + PreferenceManager.shared.receivingConfigTime_Color = Date().timeIntervalSince1970 } if !(info.collapsedClassList ?? []).isEmpty { - LKPreferenceManager.shared.receivingConfigTime_Class = Date().timeIntervalSince1970 + PreferenceManager.shared.receivingConfigTime_Class = Date().timeIntervalSince1970 } var previousSelectedOid: UInt = 0 var previousExpansion: [String: NSNumber] = [:] - let prefersViewOID = LKHelper.appInfoLooksLikeMacTarget(info.appInfo) + let prefersViewOID = AppHelper.appInfoLooksLikeMacTarget(info.appInfo) if keepState { previousSelectedOid = selectedItem?.bestObjectOidPreferView(prefersViewOID) ?? 0 for item in flatItems ?? [] { @@ -284,7 +284,7 @@ class LKHierarchyDataSource: NSObject { storedServerSideIsSwiftProject = true } if let source = item.customInfo?.danceuiSource, !source.isEmpty { - LKDanceUIAttrMaker.makeDanceUIJumpAttribute(item, danceSource: source) + DanceUIAttributeMaker.makeDanceUIJumpAttribute(item, danceSource: source) } } @@ -360,7 +360,7 @@ class LKHierarchyDataSource: NSObject { } @objc func buildDisplayingFlatItems() { - let showSystemLayoutGuides = LKPreferenceManager.shared.showSystemLayoutGuides.currentBOOLValue + let showSystemLayoutGuides = PreferenceManager.shared.showSystemLayoutGuides.currentBOOLValue let rows = (flatItems ?? []).filter { item in guard item.displayingInHierarchy else { return false @@ -382,7 +382,7 @@ class LKHierarchyDataSource: NSObject { didChangeValue(forKey: key) } - private func setState(_ state: LKHierarchyDataSourceState) { + private func setState(_ state: HierarchyDataSourceState) { setKVO("state") { storedState = state } } @@ -397,7 +397,7 @@ class LKHierarchyDataSource: NSObject { previousItem?.notifySelectionChangeToDelegates() item?.notifySelectionChangeToDelegates() - LKUserActionManager.sharedInstance().send(.selectedItemChange) + UserActionManager.sharedInstance().send(.selectedItemChange) if NSColorPanel.sharedColorPanelExists { NSColorPanel.shared.close() @@ -405,9 +405,9 @@ class LKHierarchyDataSource: NSObject { // Clearing the selection ends measuring. if item == nil, let measureState = preferenceManager()?.measureState, - measureState.currentIntegerValue != LookinMeasureState.no.rawValue + measureState.currentIntegerValue != MeasureState.no.rawValue { - measureState.setIntegerValue(LookinMeasureState.no.rawValue, ignoreSubscriber: nil) + measureState.setIntegerValue(MeasureState.no.rawValue, ignoreSubscriber: nil) } } @@ -1021,7 +1021,7 @@ class LKHierarchyDataSource: NSObject { private func setUpColors() { let catalog = ColorAliasCatalog(aliases: colorAliasEntries(), colorKey: { $0.rgbaString() }) colorToAliasMap = catalog.aliasesByColorKey - storedSelectColorMenu = makeColorMenu(aliasEntries: catalog.entries, usingRGBAFormat: LKPreferenceManager.shared.rgbaFormat) + storedSelectColorMenu = makeColorMenu(aliasEntries: catalog.entries, usingRGBAFormat: PreferenceManager.shared.rgbaFormat) } /// `colorAlias` maps an alias to a color, or a group title to a @@ -1115,7 +1115,7 @@ class LKHierarchyDataSource: NSObject { private func colorMenuItem(title: String, color: NSColor?) -> NSMenuItem { let item = NSMenuItem() - item.image = LKColorIndicatorLayer.image(with: color, shapeSize: NSSize(width: 20, height: 20), insets: NSEdgeInsets(top: 4, left: 5, bottom: 4, right: 6)) + item.image = ColorIndicatorLayer.image(with: color, shapeSize: NSSize(width: 20, height: 20), insets: NSEdgeInsets(top: 4, left: 5, bottom: 4, right: 6)) item.title = title item.representedObject = color return item @@ -1124,7 +1124,7 @@ class LKHierarchyDataSource: NSObject { // MARK: - Others /// Subclasses return their preference manager. - @objc func preferenceManager() -> LKPreferenceManager! { + @objc func preferenceManager() -> PreferenceManager! { assertionFailure("should implement by subclass") return nil } @@ -1147,13 +1147,13 @@ class LKHierarchyDataSource: NSObject { oidToDisplayItem = map } - @objc private func handleShowSystemLayoutGuidesDidChange(_: LookinMsgActionParams?) { + @objc private func handleShowSystemLayoutGuidesDidChange(_: MessageActionParameters?) { buildDisplayingFlatItems() } private func forwardSignalsToEvents() { let broadcaster = eventBroadcaster - func forward(_ signal: LKSyncSignal, _ event: @escaping (Value) -> LKHierarchyDataSourceEvent) { + func forward(_ signal: SyncSignal, _ event: @escaping (Value) -> HierarchyDataSourceEvent) { signalSubscriptions.append(signal.observe { [weak broadcaster] value in broadcaster?.yield(event(value)) }) @@ -1167,10 +1167,10 @@ class LKHierarchyDataSource: NSObject { } } -extension LKHierarchyDataSource { - /// The data source's events from now on; see `LKHierarchyDataSourceEvent`. +extension HierarchyDataSource { + /// The data source's events from now on; see `HierarchyDataSourceEvent`. /// Ends when the data source is released. - func events() -> AsyncStream { + func events() -> AsyncStream { eventBroadcaster.subscribe() } } diff --git a/LookInside/Hierarchy/LKHierarchyFrameLayout.swift b/LookInside/Hierarchy/HierarchyFrameLayout.swift similarity index 96% rename from LookInside/Hierarchy/LKHierarchyFrameLayout.swift rename to LookInside/Hierarchy/HierarchyFrameLayout.swift index cde272d2..487f0261 100644 --- a/LookInside/Hierarchy/LKHierarchyFrameLayout.swift +++ b/LookInside/Hierarchy/HierarchyFrameLayout.swift @@ -1,5 +1,5 @@ // -// LKHierarchyFrameLayout.swift +// HierarchyFrameLayout.swift // LookInside // // Frame layout for the hierarchy outline and its table views, with the @@ -15,7 +15,7 @@ import QuartzCore /// Every value written is rounded up to the main screen's pixel grid, as /// ShortCocoa did. Methods return `self` so calls chain in the same order as /// the ShortCocoa expressions they replace. -struct LKHierarchyFrameLayout { +struct HierarchyFrameLayout { private let getFrame: () -> CGRect private let setFrame: (CGRect) -> Void private let ownBounds: () -> CGRect @@ -34,7 +34,7 @@ struct LKHierarchyFrameLayout { ownBounds = { view.bounds } superBounds = { view.superview?.bounds } superIsFlipped = { view.superview?.isFlipped ?? false } - if let baseView = view as? LKBaseView { + if let baseView = view as? BaseView { measure = { baseView.sizeThatFits($0) } zeroesNaN = false } else if let control = view as? NSControl { @@ -217,7 +217,7 @@ struct LKHierarchyFrameLayout { verAlign().horAlign() } - /// Sizes an LKBaseView or a control to `sizeThatFits` with no limit, as + /// Sizes an BaseView or a control to `sizeThatFits` with no limit, as /// LookInside's replacement for ShortCocoa's `sizeToFit` did; other /// views are left alone. AppKit's own `-sizeToFit` sizes an image view /// to nothing, which hid the row icons. @@ -239,7 +239,7 @@ struct LKHierarchyFrameLayout { return self } - /// Fits an LKBaseView's or a control's height to its width; other views + /// Fits an BaseView's or a control's height to its width; other views /// are left alone. @discardableResult func heightToFit() -> Self { diff --git a/LookInside/Hierarchy/LKHierarchyHandlersPopoverController.swift b/LookInside/Hierarchy/HierarchyHandlersPopoverController.swift similarity index 84% rename from LookInside/Hierarchy/LKHierarchyHandlersPopoverController.swift rename to LookInside/Hierarchy/HierarchyHandlersPopoverController.swift index 5bdb8b95..00feb1ee 100644 --- a/LookInside/Hierarchy/LKHierarchyHandlersPopoverController.swift +++ b/LookInside/Hierarchy/HierarchyHandlersPopoverController.swift @@ -1,5 +1,5 @@ // -// LKHierarchyHandlersPopoverController.swift +// HierarchyHandlersPopoverController.swift // LookInside // // Created by Li Kai on 2019/8/11. @@ -10,25 +10,25 @@ import AppKit /// The popover a hierarchy row's event-handler button opens: one item per /// gesture recognizer or target-action of the node. -final class LKHierarchyHandlersPopoverController: LKBaseViewController { +final class HierarchyHandlersPopoverController: BaseViewController { private let scrollView: NSScrollView = { let scrollView = NSScrollView() scrollView.drawsBackground = false return scrollView }() - private var itemViews: [LKHierarchyHandlersPopoverItemView] = [] + private var itemViews: [HierarchyHandlersPopoverItemView] = [] private let verInset: CGFloat = 0 /// - Parameter editable: false in read mode, where a gesture recognizer /// cannot be switched on or off. init(displayItem: DisplayItem, editable: Bool) { super.init(containerView: nil) - let documentView = LKBaseView() + let documentView = BaseView() scrollView.documentView = documentView itemViews = (displayItem.eventHandlers ?? []).enumerated().map { index, handler in - let view = LKHierarchyHandlersPopoverItemView(eventHandler: handler, editable: editable) + let view = HierarchyHandlersPopoverItemView(eventHandler: handler, editable: editable) documentView.addSubview(view) view.needTopBorder = index > 0 view.isHidden = false @@ -37,7 +37,7 @@ final class LKHierarchyHandlersPopoverController: LKBaseViewController { } required init?(coder _: NSCoder) { - fatalError("LKHierarchyHandlersPopoverController is not loaded from archives") + fatalError("HierarchyHandlersPopoverController is not loaded from archives") } override func makeContainerView() -> NSView { @@ -49,7 +49,7 @@ final class LKHierarchyHandlersPopoverController: LKBaseViewController { guard let documentView = scrollView.documentView else { return } - LKHierarchyFrameLayout(documentView).fullWidth().y(0) + HierarchyFrameLayout(documentView).fullWidth().y(0) // Item views are LKBaseViews: the height fit sizes them with // sizeThatFits, as LookInside's ShortCocoa fitting did. @@ -57,12 +57,12 @@ final class LKHierarchyHandlersPopoverController: LKBaseViewController { let visibleViews = itemViews.filter { !$0.isHidden } for (index, view) in visibleViews.enumerated() { let y = index > 0 ? itemViews[index - 1].frame.maxY : verInset - LKHierarchyFrameLayout(view).fullWidth().heightToFit().y(y) + HierarchyFrameLayout(view).fullWidth().heightToFit().y(y) if index == visibleViews.count - 1 { maxY = view.frame.maxY } } - LKHierarchyFrameLayout(documentView).height(maxY) + HierarchyFrameLayout(documentView).height(maxY) } func neededSize() -> NSSize { @@ -78,7 +78,7 @@ final class LKHierarchyHandlersPopoverController: LKBaseViewController { /// One event handler in the popover: its name, targets and actions, and /// for a gesture recognizer its delegate, ivar traces and an enabled switch. -final class LKHierarchyHandlersPopoverItemView: LKBaseView { +final class HierarchyHandlersPopoverItemView: BaseView { var needTopBorder = false { didSet { topSepLayer.isHidden = !needTopBorder @@ -87,10 +87,10 @@ final class LKHierarchyHandlersPopoverItemView: LKBaseView { private let eventHandler: EventHandlerDescription private let iconImageView = NSImageView() - private let titleLabel = LKLabel() - private var subtitleLabel: LKLabel? + private let titleLabel = TextLabel() + private var subtitleLabel: TextLabel? private var recognizerEnableButton: NSButton? - private let contentView = LKTextsMenuView() + private let contentView = TextsMenuView() private let topSepLayer = CALayer() private let contentX: CGFloat = 28 @@ -174,8 +174,8 @@ final class LKHierarchyHandlersPopoverItemView: LKBaseView { } lines.append(contentsOf: eventHandler.recognizerIvarTraces ?? []) if !lines.isEmpty { - let label = LKLabel() - // LKHelper's NSColorGray9 / NSColorGray1. + let label = TextLabel() + // AppHelper's NSColorGray9 / NSColorGray1. label.textColor = isDarkMode() ? NSColor(red: 216 / 255, green: 220 / 255, blue: 228 / 255, alpha: 1).withAlphaComponent(0.5) : NSColor(red: 53 / 255, green: 60 / 255, blue: 70 / 255, alpha: 1).withAlphaComponent(0.6) @@ -191,23 +191,23 @@ final class LKHierarchyHandlersPopoverItemView: LKBaseView { } required init?(coder _: NSCoder) { - fatalError("LKHierarchyHandlersPopoverItemView is not loaded from archives") + fatalError("HierarchyHandlersPopoverItemView is not loaded from archives") } override func layout() { super.layout() - LKHierarchyFrameLayout(topSepLayer).x(contentX).toRight(insetRight).y(0).height(1) + HierarchyFrameLayout(topSepLayer).x(contentX).toRight(insetRight).y(0).height(1) - LKHierarchyFrameLayout(titleLabel).x(contentX).toRight(insetRight).heightToFit().y(verInset) + HierarchyFrameLayout(titleLabel).x(contentX).toRight(insetRight).heightToFit().y(verInset) var y = titleLabel.frame.maxY if let subtitleLabel { - LKHierarchyFrameLayout(subtitleLabel).x(contentX).toRight(insetRight).heightToFit().y(y + subtitleMarginTop) + HierarchyFrameLayout(subtitleLabel).x(contentX).toRight(insetRight).heightToFit().y(y + subtitleMarginTop) y = subtitleLabel.frame.maxY } - LKHierarchyFrameLayout(contentView).x(contentX).toRight(insetRight).heightToFit().y(y + contentMarginTop) - LKHierarchyFrameLayout(iconImageView).sizeToFit().midX(contentX / 2 + 1).midY(titleLabel.frame.midY) + HierarchyFrameLayout(contentView).x(contentX).toRight(insetRight).heightToFit().y(y + contentMarginTop) + HierarchyFrameLayout(iconImageView).sizeToFit().midX(contentX / 2 + 1).midY(titleLabel.frame.midY) } override func sizeThatFits(_ limitedSize: NSSize) -> NSSize { @@ -229,8 +229,8 @@ final class LKHierarchyHandlersPopoverItemView: LKBaseView { // The popover sits on the Live Doc that hosts it, so the app and the // alert's window both come from `window`. let hostWindow = window - guard let inspectableApp = LookinLiveDocument.document(in: hostWindow)?.inspectableApp else { - Self.present(LKConnectionError.noConnect, in: hostWindow) + guard let inspectableApp = LiveDocument.document(in: hostWindow)?.inspectableApp else { + Self.present(ConnectionError.noConnect, in: hostWindow) renderRecognizerEnabledButton() return } @@ -253,7 +253,7 @@ final class LKHierarchyHandlersPopoverItemView: LKBaseView { recognizerEnableButton?.state = eventHandler.gestureRecognizerIsEnabled ? .on : .off } - /// LKHelper's AlertError: a sheet for every error except a discarded + /// AppHelper's AlertError: a sheet for every error except a discarded /// request. private static func present(_ error: NSError, in window: NSWindow?) { guard error.code != LookinErrCode_Discard, let window else { diff --git a/LookInside/Hierarchy/LKHierarchyRowView.swift b/LookInside/Hierarchy/HierarchyRowView.swift similarity index 93% rename from LookInside/Hierarchy/LKHierarchyRowView.swift rename to LookInside/Hierarchy/HierarchyRowView.swift index 94051bba..29bcaa1b 100644 --- a/LookInside/Hierarchy/LKHierarchyRowView.swift +++ b/LookInside/Hierarchy/HierarchyRowView.swift @@ -1,5 +1,5 @@ // -// LKHierarchyRowView.swift +// HierarchyRowView.swift // LookInside // // Created by Li Kai on 2018/8/4. @@ -72,7 +72,7 @@ private func rgba(_ red: CGFloat, _ green: CGFloat, _ blue: CGFloat, _ alpha: CG @objc(LKHierarchyRowView) @objcMembers -class LKHierarchyRowView: LKOutlineRowView { +class HierarchyRowView: OutlineRowView { /// Weak: the table keeps many row views around, and a strong reference /// would keep display items (and their screenshots) alive across /// hierarchy reloads. @@ -87,7 +87,7 @@ class LKHierarchyRowView: LKOutlineRowView { /// 左侧的小蓝条图标 private(set) var eventHandlerButton: NSButton? - private var dataSource: LKHierarchyDataSource? + private var dataSource: HierarchyDataSource? private var strikethroughLayer: CALayer? private var eventHandlerButtonColorLayer: CALayer? private var swiftUIBadge: NSImageView? @@ -101,20 +101,20 @@ class LKHierarchyRowView: LKOutlineRowView { } } - init!(dataSource: LKHierarchyDataSource!) { + init!(dataSource: HierarchyDataSource!) { self.dataSource = dataSource super.init(compactUI: false) } required init?(coder _: NSCoder) { - fatalError("LKHierarchyRowView is not loaded from archives") + fatalError("HierarchyRowView is not loaded from archives") } override func layout() { super.layout() if let eventHandlerButton { - LKHierarchyFrameLayout(eventHandlerButton).y(3).toBottom(3).width(10).x(3) + HierarchyFrameLayout(eventHandlerButton).y(3).toBottom(3).width(10).x(3) } updateEventHandlerButtonLayout() @@ -123,10 +123,10 @@ class LKHierarchyRowView: LKOutlineRowView { // where it would overlap the badge, so move it right and report the // row width again. if let swiftUIBadge, !swiftUIBadge.isHidden { - LKHierarchyFrameLayout(swiftUIBadge).sizeToFit().x(titleLabel.frame.maxX + 4).verAlign() + HierarchyFrameLayout(swiftUIBadge).sizeToFit().x(titleLabel.frame.maxX + 4).verAlign() var finalMaxX = swiftUIBadge.frame.maxX if !subtitleLabel.isHidden, subtitleLabel.alphaValue > 0 { - LKHierarchyFrameLayout(subtitleLabel).x(swiftUIBadge.frame.maxX + subtitleLeft) + HierarchyFrameLayout(subtitleLabel).x(swiftUIBadge.frame.maxX + subtitleLeft) finalMaxX = subtitleLabel.frame.maxX } horizontalScrollWidthManager?.rowDidLayout(withWidth: finalMaxX) @@ -134,7 +134,7 @@ class LKHierarchyRowView: LKOutlineRowView { if let strikethroughLayer, !strikethroughLayer.isHidden { let maxX = subtitleLabel.isHidden ? titleLabel.frame.maxX + 2 : subtitleLabel.frame.maxX + 2 - LKHierarchyFrameLayout(strikethroughLayer) + HierarchyFrameLayout(strikethroughLayer) .height(1) .x(titleLabel.frame.minX - 1) .toMaxX(maxX) @@ -229,7 +229,7 @@ class LKHierarchyRowView: LKOutlineRowView { image?.isTemplate = true let badge = NSImageView() badge.image = image - badge.contentTintColor = LKHelper.accentColor() + badge.contentTintColor = AppHelper.accentColor() addSubview(badge) swiftUIBadge = badge } @@ -338,16 +338,16 @@ class LKHierarchyRowView: LKOutlineRowView { return } let width: CGFloat = isFocusingHandlerButton ? 8 : 5 - LKHierarchyFrameLayout(eventHandlerButtonColorLayer).fullHeight().width(width).horAlign() + HierarchyFrameLayout(eventHandlerButtonColorLayer).fullHeight().width(width).horAlign() eventHandlerButtonColorLayer.cornerRadius = width / 2 } private func updateLabelsFonts(for item: DisplayItem) { let noImage = item.inNoPreviewHierarchy || item.inHiddenHierarchy - let isPrivate = LKPrivateDiscriminatorStore.shared.isPrivateDisplayItem(item) + let isPrivate = PrivateDiscriminatorStore.shared.isPrivateDisplayItem(item) if !item.isUserCustom(), noImage || isPrivate { - titleLabel.font = LKHelper.italicFont(ofSize: 13) - subtitleLabel.font = LKHelper.italicFont(ofSize: 12) + titleLabel.font = AppHelper.italicFont(ofSize: 13) + subtitleLabel.font = AppHelper.italicFont(ofSize: 12) } else { titleLabel.font = .systemFont(ofSize: 13) subtitleLabel.font = .systemFont(ofSize: 12) @@ -428,9 +428,9 @@ class LKHierarchyRowView: LKOutlineRowView { } // A row inside a Live Doc's window is editable; rows in a read-only // archive or launch window are not. - let editable = LookinLiveDocument.document(in: window) != nil + let editable = LiveDocument.document(in: window) != nil - let controller = LKHierarchyHandlersPopoverController(displayItem: item, editable: editable) + let controller = HierarchyHandlersPopoverController(displayItem: item, editable: editable) let popover = NSPopover() popover.animates = false popover.behavior = .transient @@ -440,7 +440,7 @@ class LKHierarchyRowView: LKOutlineRowView { } } -extension LKHierarchyRowView: DisplayItemDelegate { +extension HierarchyRowView: DisplayItemDelegate { func displayItem(_: DisplayItem, propertyDidChange property: LookinDisplayItemProperty) { if property == .isHovered { updateHoverState() diff --git a/LookInside/Hierarchy/LKHierarchyView.swift b/LookInside/Hierarchy/HierarchyView.swift similarity index 85% rename from LookInside/Hierarchy/LKHierarchyView.swift rename to LookInside/Hierarchy/HierarchyView.swift index 15dd72fc..399dacb1 100644 --- a/LookInside/Hierarchy/LKHierarchyView.swift +++ b/LookInside/Hierarchy/HierarchyView.swift @@ -1,5 +1,5 @@ // -// LKHierarchyView.swift +// HierarchyView.swift // LookInside // // Created by Li Kai on 2018/8/4. @@ -11,16 +11,16 @@ import AppKit private let rowHeight: CGFloat = 28 /// Posted with the display item as object to print it in the console; -/// LKStaticViewController shows the console. +/// StaticViewController shows the console. private let showConsoleNotification = Notification.Name("LKAppShowConsoleNotificationName") /// A row's context menu, which knows the row it belongs to. -private final class LKHierarchyRowMenu: NSMenu { - weak var rowView: LKHierarchyRowView? +private final class HierarchyRowMenu: NSMenu { + weak var rowView: HierarchyRowView? } /// Runs the latest scheduled action once no new one arrived for `delay`. -private final class LKHierarchyDebouncer { +private final class HierarchyDebouncer { private let delay: TimeInterval private var pending: DispatchWorkItem? @@ -40,63 +40,63 @@ private final class LKHierarchyDebouncer { } } -@objc protocol LKHierarchyViewDelegate: NSObjectProtocol { +@objc protocol HierarchyViewDelegate: NSObjectProtocol { @objc(hierarchyView:didSelectItem:) - func hierarchyView(_ view: LKHierarchyView!, didSelect item: DisplayItem!) + func hierarchyView(_ view: HierarchyView!, didSelect item: DisplayItem!) @objc(hierarchyView:didDoubleClickItem:) - func hierarchyView(_ view: LKHierarchyView!, didDoubleClick item: DisplayItem!) + func hierarchyView(_ view: HierarchyView!, didDoubleClick item: DisplayItem!) @objc(hierarchyView:didHoverAtItem:) - func hierarchyView(_ view: LKHierarchyView!, didHoverAt item: DisplayItem!) + func hierarchyView(_ view: HierarchyView!, didHoverAt item: DisplayItem!) @objc(hierarchyView:needToExpandItem:recursively:) - func hierarchyView(_ view: LKHierarchyView!, needToExpand item: DisplayItem!, recursively: Bool) + func hierarchyView(_ view: HierarchyView!, needToExpand item: DisplayItem!, recursively: Bool) @objc(hierarchyView:needToCollapseItem:) - func hierarchyView(_ view: LKHierarchyView!, needToCollapse item: DisplayItem!) + func hierarchyView(_ view: HierarchyView!, needToCollapse item: DisplayItem!) @objc(hierarchyView:needToCollapseChildrenOfItem:) - func hierarchyView(_ view: LKHierarchyView!, needToCollapseChildrenOf item: DisplayItem!) + func hierarchyView(_ view: HierarchyView!, needToCollapseChildrenOf item: DisplayItem!) /// 在底部的搜索框里输入了文字,string 可能为空字符串或 nil /// 当用户通过搜索框的关闭按钮、ESC 等方式手动结束搜索时,该方法同样会被调用,参数是 nil @objc(hierarchyView:didInputSearchString:) - func hierarchyView(_ view: LKHierarchyView!, didInputSearch string: String!) + func hierarchyView(_ view: HierarchyView!, didInputSearch string: String!) @objc(hierarchyView:needToCancelPreviewOfItem:) - optional func hierarchyView(_ view: LKHierarchyView!, needToCancelPreviewOf item: DisplayItem!) + optional func hierarchyView(_ view: HierarchyView!, needToCancelPreviewOf item: DisplayItem!) @objc(hierarchyView:needToShowPreviewOfItem:) - optional func hierarchyView(_ view: LKHierarchyView!, needToShowPreviewOf item: DisplayItem!) + optional func hierarchyView(_ view: HierarchyView!, needToShowPreviewOf item: DisplayItem!) } @objc(LKHierarchyView) @objcMembers -class LKHierarchyView: LKBaseView { - let tableView: LKTableView! +class HierarchyView: BaseView { + let tableView: TableView! /// The filter field under the rows. The DEBUG UI snapshots type into it. - let searchTextFieldView: LKTextFieldView! - var dataSource: LKHierarchyDataSource! - /// Phase A 引入:由 owner(LKStaticHierarchyController / LKStaticViewController 链路)注入的 per-instance update manager(weak)。 + let searchTextFieldView: TextFieldView! + var dataSource: HierarchyDataSource! + /// Phase A 引入:由 owner(StaticHierarchyController / StaticViewController 链路)注入的 per-instance update manager(weak)。 /// 若 nil 则 fallback 到 +sharedInstance,以保留 read-only / archive workspace 的 legacy 行为。 - weak var asyncUpdateManager: LKStaticAsyncUpdateManager? - weak var delegate: LKHierarchyViewDelegate? + weak var asyncUpdateManager: StaticAsyncUpdateManager? + weak var delegate: HierarchyViewDelegate? - private let backgroundEffectView = LKVisualEffectView() + private let backgroundEffectView = VisualEffectView() private let guidesShapeLayer = CAShapeLayer() - private var emptyDataLabel: LKLabel? + private var emptyDataLabel: TextLabel? private var displayItems: [DisplayItem] = [] private var minIndentLevel = 0 private var observations: [NSKeyValueObservation] = [] private var textChangeObserver: NSObjectProtocol? - private let searchDebouncer = LKHierarchyDebouncer(delay: 0.5) - private let guidesDebouncer = LKHierarchyDebouncer(delay: 0.75) + private let searchDebouncer = HierarchyDebouncer(delay: 0.5) + private let guidesDebouncer = HierarchyDebouncer(delay: 0.75) - init!(dataSource: LKHierarchyDataSource!) { + init!(dataSource: HierarchyDataSource!) { self.dataSource = dataSource - tableView = LKTableView() - searchTextFieldView = LKTextFieldView() + tableView = TableView() + searchTextFieldView = TextFieldView() super.init(frame: .zero) backgroundEffectView.material = .sidebar @@ -122,7 +122,7 @@ class LKHierarchyView: LKBaseView { } required init?(coder _: NSCoder) { - fatalError("LKHierarchyView is not loaded from archives") + fatalError("HierarchyView is not loaded from archives") } deinit { @@ -133,16 +133,16 @@ class LKHierarchyView: LKBaseView { override func layout() { super.layout() - LKHierarchyFrameLayout(backgroundEffectView).fullFrame() - LKHierarchyFrameLayout(searchTextFieldView).fullWidth().height(25).bottom(0) + HierarchyFrameLayout(backgroundEffectView).fullFrame() + HierarchyFrameLayout(searchTextFieldView).fullWidth().height(25).bottom(0) - LKHierarchyFrameLayout(tableView).fullFrame().y(searchTextFieldView.frame.minY) - LKHierarchyFrameLayout(tableView).fullFrame().toMaxY(searchTextFieldView.frame.minY) + HierarchyFrameLayout(tableView).fullFrame().y(searchTextFieldView.frame.minY) + HierarchyFrameLayout(tableView).fullFrame().toMaxY(searchTextFieldView.frame.minY) - LKHierarchyFrameLayout(guidesShapeLayer).frame(.zero) + HierarchyFrameLayout(guidesShapeLayer).frame(.zero) if let emptyDataLabel, !emptyDataLabel.isHidden, emptyDataLabel.alphaValue > 0 { - LKHierarchyFrameLayout(emptyDataLabel).sizeToFit().centerAlign() + HierarchyFrameLayout(emptyDataLabel).sizeToFit().centerAlign() } } @@ -180,7 +180,7 @@ class LKHierarchyView: LKBaseView { textField.isBordered = false textField.focusRingType = .none searchTextFieldView.borderPosition = .top - searchTextFieldView.borderColors = LKTwoColors( + searchTextFieldView.borderColors = TwoColors( colorInLightMode: NSColor(red: 200 / 255, green: 201 / 255, blue: 202 / 255, alpha: 1), colorInDarkMode: NSColor(red: 67 / 255, green: 68 / 255, blue: 69 / 255, alpha: 1) ) @@ -204,7 +204,7 @@ class LKHierarchyView: LKBaseView { searchTextFieldView.closeButton?.action = #selector(handleSearchCloseButton) } - private func observe(_ dataSource: LKHierarchyDataSource?) { + private func observe(_ dataSource: HierarchyDataSource?) { var observations = [ // Reads the insets from the scroll view: NSEdgeInsets does not // bridge from the NSValue KVO delivers, so change.newValue is @@ -212,7 +212,7 @@ class LKHierarchyView: LKBaseView { tableView.observe(\.contentInsets, options: [.initial, .new]) { tableView, _ in MainActor.assumeIsolated { let top = tableView.contentInsets.top - let navigation = LKNavigationManager.shared + let navigation = NavigationManager.shared if navigation.windowTitleBarHeight != top { navigation.windowTitleBarHeight = top } @@ -277,11 +277,11 @@ class LKHierarchyView: LKBaseView { tableView.reloadDataWithOffset() if items.isEmpty { - let label: LKLabel + let label: TextLabel if let emptyDataLabel { label = emptyDataLabel } else { - label = LKLabel() + label = TextLabel() label.font = .systemFont(ofSize: 15) label.stringValue = NSLocalizedString("No Filter Results", comment: "") addSubview(label) @@ -325,7 +325,7 @@ class LKHierarchyView: LKBaseView { return } - let rootX = LKHierarchyRowView.dislosureMidX(withIndentLevel: UInt(bitPattern: rootItem.indentLevel() - minIndentLevel)) + let rootX = HierarchyRowView.dislosureMidX(withIndentLevel: UInt(bitPattern: rootItem.indentLevel() - minIndentLevel)) let rootY = rowHeight * CGFloat(rootRow) + rowHeight / 2 let rootMaxY = CGFloat(lastChildRow) * rowHeight + rowHeight / 2 @@ -354,7 +354,7 @@ class LKHierarchyView: LKBaseView { } fileprivate func displayItem(of menuItem: NSMenuItem) -> DisplayItem? { - (menuItem.menu as? LKHierarchyRowMenu)?.rowView?.displayItem + (menuItem.menu as? HierarchyRowMenu)?.rowView?.displayItem } // MARK: - Menu and control actions @@ -411,7 +411,7 @@ class LKHierarchyView: LKBaseView { @objc fileprivate func handleExportScreenshot(_ menuItem: NSMenuItem) { guard let item = displayItem(of: menuItem) else { return } - LKExportManager.exportScreenshot(with: item) + ExportManager.exportScreenshot(with: item) } @objc fileprivate func handleCopyDisplayItemName(_ menuItem: NSMenuItem) { @@ -434,7 +434,7 @@ class LKHierarchyView: LKBaseView { } @objc fileprivate func handleHideScreenshotForever() { - LKHelper.openCustomConfigWebsite() + AppHelper.openCustomConfigWebsite() } fileprivate func menuItem(_ title: String, action: Selector?, representedObject: Any? = nil) -> NSMenuItem { @@ -453,10 +453,10 @@ class LKHierarchyView: LKBaseView { } } -// MARK: - LKTableViewDataSource / LKTableViewDelegate +// MARK: - TableViewDataSource / TableViewDelegate -extension LKHierarchyView: LKTableViewDataSource, LKTableViewDelegate { - func tableView(_: LKTableView!, didHoverAtRow row: Int) { +extension HierarchyView: TableViewDataSource, TableViewDelegate { + func tableView(_: TableView!, didHoverAtRow row: Int) { // nil when the mouse is not over a row. delegate?.hierarchyView(self, didHoverAt: item(atRow: row)) } @@ -472,18 +472,18 @@ extension LKHierarchyView: LKTableViewDataSource, LKTableViewDelegate { func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView? { guard let item = item(atRow: row) else { assertionFailure("no item at row \(row)") - return LKTableBlankRowView() + return TableBlankRowView() } - let rowView: LKHierarchyRowView - if let reused = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier("cell"), owner: self) as? LKHierarchyRowView { + let rowView: HierarchyRowView + if let reused = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier("cell"), owner: self) as? HierarchyRowView { rowView = reused } else { - rowView = LKHierarchyRowView(dataSource: dataSource) + rowView = HierarchyRowView(dataSource: dataSource) rowView.disclosureButton.target = self rowView.disclosureButton.action = #selector(handleDisclosureButton(_:)) rowView.identifier = NSUserInterfaceItemIdentifier("cell") - let menu = LKHierarchyRowMenu() + let menu = HierarchyRowMenu() menu.autoenablesItems = true menu.rowView = rowView menu.delegate = self @@ -495,7 +495,7 @@ extension LKHierarchyView: LKTableViewDataSource, LKTableViewDelegate { return rowView } - func tableView(_: LKTableView!, didSelectRow row: Int) { + func tableView(_: TableView!, didSelectRow row: Int) { guard let item = item(atRow: row) else { return } @@ -505,7 +505,7 @@ extension LKHierarchyView: LKTableViewDataSource, LKTableViewDelegate { } } - func tableView(_: LKTableView!, didDoubleClickAtRow row: Int) { + func tableView(_: TableView!, didDoubleClickAtRow row: Int) { guard let item = item(atRow: row) else { return } @@ -515,10 +515,10 @@ extension LKHierarchyView: LKTableViewDataSource, LKTableViewDelegate { // MARK: - NSMenuDelegate -extension LKHierarchyView: NSMenuDelegate { +extension HierarchyView: NSMenuDelegate { func menuNeedsUpdate(_ menu: NSMenu) { menu.removeAllItems() - guard let displayItem = (menu as? LKHierarchyRowMenu)?.rowView?.displayItem else { + guard let displayItem = (menu as? HierarchyRowMenu)?.rowView?.displayItem else { return } let isReadOnly = dataSource.isReadOnly() @@ -569,7 +569,7 @@ extension LKHierarchyView: NSMenuDelegate { menu.addItem(.separator()) } guard !string.isEmpty else { - assertionFailure("LKHierarchyView, menuNeedsUpdate, stringsToCopy length is zero.") + assertionFailure("HierarchyView, menuNeedsUpdate, stringsToCopy length is zero.") continue } menu.addItem(menuItem( @@ -637,7 +637,7 @@ extension LKHierarchyView: NSMenuDelegate { // MARK: - NSTextFieldDelegate -extension LKHierarchyView: NSTextFieldDelegate { +extension HierarchyView: NSTextFieldDelegate { func control(_: NSControl, textView _: NSTextView, doCommandBy commandSelector: Selector) -> Bool { guard commandSelector == #selector(NSResponder.cancelOperation(_:)) else { return false diff --git a/LookInside/Hierarchy/LKSyncSignal.swift b/LookInside/Hierarchy/SyncSignal.swift similarity index 77% rename from LookInside/Hierarchy/LKSyncSignal.swift rename to LookInside/Hierarchy/SyncSignal.swift index 190d52f4..34aac4f6 100644 --- a/LookInside/Hierarchy/LKSyncSignal.swift +++ b/LookInside/Hierarchy/SyncSignal.swift @@ -1,5 +1,5 @@ // -// LKSyncSignal.swift +// SyncSignal.swift // LookInside // // The hierarchy data sources' synchronous events. `send` runs every @@ -10,17 +10,17 @@ // /// A synchronous multicast event. -final class LKSyncSignal { +final class SyncSignal { private var observers: [(id: Int, handler: (Value) -> Void)] = [] private var nextObserverID = 0 /// Runs `handler` on every value sent until the subscription is /// cancelled or released. - func observe(_ handler: @escaping (Value) -> Void) -> LKSyncSubscription { + func observe(_ handler: @escaping (Value) -> Void) -> SyncSubscription { let id = nextObserverID nextObserverID += 1 observers.append((id, handler)) - return LKSyncSubscription { [weak self] in + return SyncSubscription { [weak self] in self?.observers.removeAll { $0.id == id } } } @@ -35,14 +35,14 @@ final class LKSyncSignal { } } -extension LKSyncSignal where Value == Void { +extension SyncSignal where Value == Void { func send() { send(()) } } -/// Ends an `LKSyncSignal` observation when cancelled or released. -final class LKSyncSubscription { +/// Ends an `SyncSignal` observation when cancelled or released. +final class SyncSubscription { private var onCancel: (() -> Void)? init(_ onCancel: @escaping () -> Void) { @@ -61,12 +61,12 @@ final class LKSyncSubscription { } /// Subscriptions that end together when the owner releases the bag. -final class LKSyncSubscriptionBag { - private var subscriptions: [LKSyncSubscription] = [] +final class SyncSubscriptionBag { + private var subscriptions: [SyncSubscription] = [] /// Runs `handler` on every value `signal` sends, ignoring the value. A /// nil signal is ignored. - func observe(_ signal: LKSyncSignal?, _ handler: @escaping () -> Void) { + func observe(_ signal: SyncSignal?, _ handler: @escaping () -> Void) { guard let signal else { return } subscriptions.append(signal.observe { _ in handler() }) } diff --git a/LookInside/Injection/Device/LKAttachedDeviceMonitor.swift b/LookInside/Injection/Device/AttachedDeviceMonitor.swift similarity index 93% rename from LookInside/Injection/Device/LKAttachedDeviceMonitor.swift rename to LookInside/Injection/Device/AttachedDeviceMonitor.swift index b1a1d592..4a76f4b6 100644 --- a/LookInside/Injection/Device/LKAttachedDeviceMonitor.swift +++ b/LookInside/Injection/Device/AttachedDeviceMonitor.swift @@ -2,7 +2,7 @@ import AppKit /// Which iOS devices are attached over USB right now. /// -/// A monitor of its own rather than a reading off `LKConnectionManager`, which +/// A monitor of its own rather than a reading off `ConnectionManager`, which /// tracks the same attaches for a different purpose (it turns each one into /// five server ports to probe) and keeps the result private. /// @@ -12,7 +12,7 @@ import AppKit /// launch, says nothing to an observer that arrives later. A private client /// listens when this starts, and therefore reports the devices already there. @MainActor -final class LKAttachedDeviceMonitor { +final class AttachedDeviceMonitor { struct Device: Hashable { /// usbmuxd's handle for the device. Not stable across replugs. let identifier: Int @@ -21,7 +21,7 @@ final class LKAttachedDeviceMonitor { let serialNumber: String } - static let shared = LKAttachedDeviceMonitor() + static let shared = AttachedDeviceMonitor() /// Attached devices, in the order they were reported. private(set) var devices: [Device] = [] @@ -65,7 +65,7 @@ final class LKAttachedDeviceMonitor { // machine, and usbmuxd's Connect reaches one exactly the same way — // so filtering to `USB` would hide a jailbroken iPhone that // happened to be off the cable. The host's own - // `LKConnectionManager` does not filter either, and this list has + // `ConnectionManager` does not filter either, and this list has // to agree with it: a device this skipped could still have its // injected server found afterwards, which would read as the // injector list being wrong. diff --git a/LookInside/Injection/Device/LKDeviceControlClient.swift b/LookInside/Injection/Device/DeviceControlClient.swift similarity index 89% rename from LookInside/Injection/Device/LKDeviceControlClient.swift rename to LookInside/Injection/Device/DeviceControlClient.swift index 39f08346..b1e1d93a 100644 --- a/LookInside/Injection/Device/LKDeviceControlClient.swift +++ b/LookInside/Injection/Device/DeviceControlClient.swift @@ -14,7 +14,7 @@ import Foundation /// is cheaper than defending the pending table with a lock that would only /// ever be taken from one thread. @MainActor -final class LKDeviceControlClient { +final class DeviceControlClient { /// Why a request did not produce an answer. enum Failure: LocalizedError { /// usbmuxd would not connect. By far the most common cause is the @@ -26,7 +26,7 @@ final class LKDeviceControlClient { case channelEnded /// The device accepted the request and never answered. - case timedOut(command: LKDeviceControlCommand) + case timedOut(command: DeviceControlCommand) /// The injector answered, and its answer was that it would not do it. case deviceReported(message: String) @@ -34,7 +34,7 @@ final class LKDeviceControlClient { /// The injector's answer did not decode. Reported as its own case /// because the remedy is a version mismatch between the two builds, not /// anything the user did. - case malformedAnswer(command: LKDeviceControlCommand, underlying: any Error) + case malformedAnswer(command: DeviceControlCommand, underlying: any Error) var errorDescription: String? { switch self { @@ -78,7 +78,7 @@ final class LKDeviceControlClient { let serialNumber: String /// The usbmuxd client the tunnel is opened through: the monitor's own, - /// the one that enumerated the device (see `LKAttachedDeviceMonitor` for + /// the one that enumerated the device (see `AttachedDeviceMonitor` for /// why it does not share the connection manager's). private let usbMuxClient: USBMuxClient @@ -100,7 +100,7 @@ final class LKDeviceControlClient { func connect() async throws { let tunnel: (fileDescriptor: Int32, initialBytes: Data) = try await withCheckedThrowingContinuation { continuation in - usbMuxClient.connect(deviceID: deviceIdentifier, port: UInt16(LKDeviceControlWire.portNumber)) { result in + usbMuxClient.connect(deviceID: deviceIdentifier, port: UInt16(DeviceControlWire.portNumber)) { result in switch result { case let .success(tunnel): continuation.resume(returning: tunnel) @@ -121,7 +121,7 @@ final class LKDeviceControlClient { // rather than read: this channel's requests all travel the other way, // so one arriving would mean the two ends had swapped roles. newChannel.shouldAcceptFrame = { header in - header.type == LKDeviceControlWire.responseFrameType + header.type == DeviceControlWire.responseFrameType } newChannel.onFrame = { [weak self] frame in // The channel calls back on the main queue, so this is already the @@ -152,13 +152,13 @@ final class LKDeviceControlClient { // MARK: - Commands /// Whether this device can inject, and when it cannot, why. - func injectionCapability() async throws -> LKDeviceControlCapability { - try await send(.injectionCapability, expecting: LKDeviceControlCapability.self, timeout: Self.quickTimeout) + func injectionCapability() async throws -> DeviceControlCapability { + try await send(.injectionCapability, expecting: DeviceControlCapability.self, timeout: Self.quickTimeout) } /// What the device can be asked to inject into. - func processList() async throws -> [LKDeviceControlProcess] { - try await send(.processList, expecting: [LKDeviceControlProcess].self, timeout: Self.listTimeout) + func processList() async throws -> [DeviceControlProcess] { + try await send(.processList, expecting: [DeviceControlProcess].self, timeout: Self.listTimeout) } /// Loads the device's own payload into one of its processes. @@ -167,11 +167,11 @@ final class LKDeviceControlClient { /// request not arriving or not being answered, the result is the injection /// itself ending one way or another. Only the second has a remedy worth /// naming to the user. - func injectIntoProcess(withIdentifier processIdentifier: pid_t) async throws -> LKDeviceControlInjectionResult { + func injectIntoProcess(withIdentifier processIdentifier: pid_t) async throws -> DeviceControlInjectionResult { try await send( .injectIntoProcess, processIdentifier: processIdentifier, - expecting: LKDeviceControlInjectionResult.self, + expecting: DeviceControlInjectionResult.self, timeout: Self.injectionTimeout ) } @@ -191,7 +191,7 @@ final class LKDeviceControlClient { // MARK: - Sending private func send( - _ command: LKDeviceControlCommand, + _ command: DeviceControlCommand, processIdentifier: pid_t? = nil, expecting _: Result.Type, timeout: TimeInterval @@ -200,7 +200,7 @@ final class LKDeviceControlClient { throw Failure.channelEnded } - let request = LKDeviceControlRequest(command, processIdentifier: processIdentifier) + let request = DeviceControlRequest(command, processIdentifier: processIdentifier) let requestData = try JSONEncoder().encode(request) let frameTag = nextFrameTag @@ -223,7 +223,7 @@ final class LKDeviceControlClient { } channel.send( - type: LKDeviceControlWire.requestFrameType, + type: DeviceControlWire.requestFrameType, tag: frameTag, payload: requestData ) { [weak self] error in @@ -235,9 +235,9 @@ final class LKDeviceControlClient { } } - let outcome: LKDeviceControlOutcome + let outcome: DeviceControlOutcome do { - outcome = try JSONDecoder().decode(LKDeviceControlOutcome.self, from: answer) + outcome = try JSONDecoder().decode(DeviceControlOutcome.self, from: answer) } catch { throw Failure.malformedAnswer(command: command, underlying: error) } diff --git a/LookInside/Injection/Device/LKDeviceControlWire.swift b/LookInside/Injection/Device/DeviceControlWire.swift similarity index 94% rename from LookInside/Injection/Device/LKDeviceControlWire.swift rename to LookInside/Injection/Device/DeviceControlWire.swift index 412207c8..61f95ee7 100644 --- a/LookInside/Injection/Device/LKDeviceControlWire.swift +++ b/LookInside/Injection/Device/DeviceControlWire.swift @@ -14,7 +14,7 @@ import Foundation /// What keeps them honest is `LKDeviceControlWireFormatTests`, which pins the /// encoded JSON rather than only a round trip — a round trip inside one process /// passes however both ends are wrong. -enum LKDeviceControlWire { +enum DeviceControlWire { /// The port the injector listens on inside the device, reached through /// usbmuxd. /// @@ -31,16 +31,16 @@ enum LKDeviceControlWire { } /// One command, as it travels. -struct LKDeviceControlRequest: Codable, Hashable { +struct DeviceControlRequest: Codable, Hashable { /// Which command. A plain `String` because that is what the injector reads /// it as — it answers an unknown name with a failure that quotes it, rather /// than failing to parse. var command: String - /// Set only for ``LKDeviceControlCommand/injectIntoProcess``. + /// Set only for ``DeviceControlCommand/injectIntoProcess``. var processIdentifier: pid_t? - init(_ command: LKDeviceControlCommand, processIdentifier: pid_t? = nil) { + init(_ command: DeviceControlCommand, processIdentifier: pid_t? = nil) { self.command = command.wireName self.processIdentifier = processIdentifier } @@ -51,7 +51,7 @@ struct LKDeviceControlRequest: Codable, Hashable { /// The names carry no `device` prefix deliberately: the same three could serve /// another kind of peer later, and `deviceProcessList` would be wrong the /// moment they did. -enum LKDeviceControlCommand: String, CaseIterable { +enum DeviceControlCommand: String, CaseIterable { case injectionCapability case processList case injectIntoProcess @@ -66,7 +66,7 @@ enum LKDeviceControlCommand: String, CaseIterable { /// Generic over the result because both ends know which command a frame tag /// belongs to. The failure case names no result type, which is what lets the /// injector answer a command it could not even identify. -enum LKDeviceControlOutcome: Codable, Hashable { +enum DeviceControlOutcome: Codable, Hashable { case succeeded(Result) case failed(message: String) @@ -108,7 +108,7 @@ enum LKDeviceControlOutcome: Codable, Hashable { /// ``unsupportedReason`` still means "can inject", an injector built before /// this sends no ``deviceName`` and a Mac built before it ignores the one it /// does not know. -struct LKDeviceControlCapability: Codable, Hashable { +struct DeviceControlCapability: Codable, Hashable { /// What to call this device. `nil` when the device could not read its own /// name, or when the injector predates this field — the picker then falls /// back to the serial number. @@ -134,7 +134,7 @@ struct LKDeviceControlCapability: Codable, Hashable { /// An application rather than a bare process, even though the command is /// `processList`: the injector's lister answers "installed ∩ running", which /// gives a row the user recognizes by name instead of by executable path. -struct LKDeviceControlProcess: Codable, Hashable { +struct DeviceControlProcess: Codable, Hashable { var processIdentifier: pid_t var name: String var bundleIdentifier: String? @@ -145,11 +145,11 @@ struct LKDeviceControlProcess: Codable, Hashable { /// The device's verdict. Carried with the row because this Mac cannot work /// it out — only the device knows its own uid and the target's. - var injectability: LKDeviceControlInjectability + var injectability: DeviceControlInjectability } /// What the device said about injecting into one target. -enum LKDeviceControlInjectability: Codable, Hashable { +enum DeviceControlInjectability: Codable, Hashable { /// Nothing ruled it out. **Not a promise** — it is also the answer for a /// target whose uid could not be read. case injectable @@ -224,7 +224,7 @@ enum LKDeviceControlInjectability: Codable, Hashable { /// Arrives inside a `succeeded` outcome even when it did not work: the request /// ran, and these four cases have four different remedies that one failure /// string would flatten. -enum LKDeviceControlInjectionResult: Codable, Hashable { +enum DeviceControlInjectionResult: Codable, Hashable { case injected case taskPortUnavailable(reason: String) case targetRefusedPayload(reason: String) diff --git a/LookInside/Injection/Device/LKDeviceInjectionFlow.swift b/LookInside/Injection/Device/DeviceInjectionFlow.swift similarity index 91% rename from LookInside/Injection/Device/LKDeviceInjectionFlow.swift rename to LookInside/Injection/Device/DeviceInjectionFlow.swift index d02e5c48..cd11e3a4 100644 --- a/LookInside/Injection/Device/LKDeviceInjectionFlow.swift +++ b/LookInside/Injection/Device/DeviceInjectionFlow.swift @@ -3,7 +3,7 @@ import RunningApplicationKit /// Attach to an app running on an attached iOS device, driven from this Mac. /// -/// The counterpart to `LKInjectionFlow`, which does the same thing for a +/// The counterpart to `InjectionFlow`, which does the same thing for a /// process on this Mac. The two are kept apart because almost nothing is /// shared: the Mac path has to register and get approval for a privileged /// daemon, download an injectable framework, and then ask the daemon to load @@ -20,16 +20,16 @@ import RunningApplicationKit /// are still bugs and still need fixing; this just stops them being hit every /// single time. @objc(LKDeviceInjectionFlow) -final class LKDeviceInjectionFlow: NSObject { - @objc(sharedInstance) static let shared = LKDeviceInjectionFlow() +final class DeviceInjectionFlow: NSObject { + @objc(sharedInstance) static let shared = DeviceInjectionFlow() - private var picker: LKInjectionTargetPicker? - private var startGate = LKInjectionStartGate() + private var picker: InjectionTargetPicker? + private var startGate = InjectionStartGate() /// One reachable injector, with what it said about itself. private struct ReachableDevice { - let client: LKDeviceControlClient - let capability: LKDeviceControlCapability + let client: DeviceControlClient + let capability: DeviceControlCapability /// What to call it. The device's own name when it reported one, /// otherwise the serial number — which is all this Mac can see of a @@ -41,7 +41,7 @@ final class LKDeviceInjectionFlow: NSObject { @objc func startFromWindow(_ window: NSWindow?) { let decision = startGate.begin { - LKSwiftUISupportGatekeeper.sharedInstance().canUseProtectedFeatureWithoutPrompt() + SwiftUISupportGatekeeper.sharedInstance().canUseProtectedFeatureWithoutPrompt() } guard decision == .started else { return } @@ -53,8 +53,8 @@ final class LKDeviceInjectionFlow: NSObject { @MainActor private func runFlow(presentingWindow window: NSWindow?) async { - await LKAttachedDeviceMonitor.shared.startAndWaitForInitialDevices() - let attachedDevices = LKAttachedDeviceMonitor.shared.devices + await AttachedDeviceMonitor.shared.startAndWaitForInitialDevices() + let attachedDevices = AttachedDeviceMonitor.shared.devices guard !attachedDevices.isEmpty else { presentMessage( title: NSLocalizedString("No Device Connected", comment: ""), @@ -88,7 +88,7 @@ final class LKDeviceInjectionFlow: NSObject { guard let target = await pickTarget(on: chosen, window: window) else { return } - let result: LKDeviceControlInjectionResult + let result: DeviceControlInjectionResult do { result = try await chosen.client.injectIntoProcess(withIdentifier: target.processIdentifier) } catch { @@ -133,15 +133,15 @@ final class LKDeviceInjectionFlow: NSObject { /// `@MainActor` clients through a task group for. @MainActor private func probe( - _ attachedDevices: [LKAttachedDeviceMonitor.Device] - ) async -> (reachable: [ReachableDevice], unreachable: [LKAttachedDeviceMonitor.Device]) { + _ attachedDevices: [AttachedDeviceMonitor.Device] + ) async -> (reachable: [ReachableDevice], unreachable: [AttachedDeviceMonitor.Device]) { var reachable: [ReachableDevice] = [] - var unreachable: [LKAttachedDeviceMonitor.Device] = [] + var unreachable: [AttachedDeviceMonitor.Device] = [] for attachedDevice in attachedDevices { - let client = LKDeviceControlClient( + let client = DeviceControlClient( deviceIdentifier: attachedDevice.identifier, serialNumber: attachedDevice.serialNumber, - usbMuxClient: LKAttachedDeviceMonitor.shared.connectionClient + usbMuxClient: AttachedDeviceMonitor.shared.connectionClient ) do { try await client.connect() @@ -168,7 +168,7 @@ final class LKDeviceInjectionFlow: NSObject { /// installed and a device with the injector not yet opened both produce. private static func explanation( forNoUsableDeviceAmong reachable: [ReachableDevice], - unreachable: [LKAttachedDeviceMonitor.Device] + unreachable: [AttachedDeviceMonitor.Device] ) -> String { let refusals = reachable.compactMap { device in device.capability.unsupportedReason.map { "\(device.displayName):\n\($0)" } @@ -230,7 +230,7 @@ final class LKDeviceInjectionFlow: NSObject { // What the device last said, kept for two things the picker needs: an // answer for `shouldSelect` ready before the first click, and // something to show when a *refresh* fails. - let snapshot = LKDeviceProcessSnapshot() + let snapshot = DeviceProcessSnapshot() let itemSource = AnyRunningItemSource { do { @@ -250,7 +250,7 @@ final class LKDeviceInjectionFlow: NSObject { } return await withCheckedContinuation { continuation in - let picker = LKInjectionTargetPicker( + let picker = InjectionTargetPicker( deviceName: device.displayName, processItemSource: itemSource, refusalReasonForProcess: { processIdentifier in @@ -339,13 +339,13 @@ final class LKDeviceInjectionFlow: NSObject { /// picker's item source is a `@Sendable` closure, so it cannot reach into /// main-actor state to record what it fetched, and both readers — the /// `shouldSelect` callback and the refresh timer — arrive on the main thread. -private final class LKDeviceProcessSnapshot: @unchecked Sendable { +private final class DeviceProcessSnapshot: @unchecked Sendable { private let lock = NSLock() - private var processes: [LKDeviceControlProcess]? + private var processes: [DeviceControlProcess]? private var refusalByProcessIdentifier: [pid_t: String] = [:] private var hasFailedARefresh = false - func record(_ processes: [LKDeviceControlProcess]) { + func record(_ processes: [DeviceControlProcess]) { lock.lock() defer { lock.unlock() } self.processes = processes @@ -359,7 +359,7 @@ private final class LKDeviceProcessSnapshot: @unchecked Sendable { /// The last list the device sent, or `nil` if it has never answered — which /// is what separates a refresh worth absorbing from a first load worth /// reporting. - func lastKnownProcesses() -> [LKDeviceControlProcess]? { + func lastKnownProcesses() -> [DeviceControlProcess]? { lock.lock() defer { lock.unlock() } return processes @@ -405,7 +405,7 @@ private extension RunningProcess { /// has no bundle-identifier column, and on an iOS device the bundle /// identifier is what tells two similarly-named apps apart — far more /// useful than a path that always ends in the display name again. - init(deviceProcess: LKDeviceControlProcess) { + init(deviceProcess: DeviceControlProcess) { self.init( processIdentifier: deviceProcess.processIdentifier, name: deviceProcess.name, diff --git a/LookInside/Injection/LKInjectableFrameworkInstaller.swift b/LookInside/Injection/InjectableFrameworkInstaller.swift similarity index 75% rename from LookInside/Injection/LKInjectableFrameworkInstaller.swift rename to LookInside/Injection/InjectableFrameworkInstaller.swift index 5ab0ccb1..660f7c60 100644 --- a/LookInside/Injection/LKInjectableFrameworkInstaller.swift +++ b/LookInside/Injection/InjectableFrameworkInstaller.swift @@ -1,7 +1,7 @@ import AppKit import Foundation -enum LKInjectableFrameworkInstallerError: LocalizedError { +enum InjectableFrameworkInstallerError: LocalizedError { case downloadFailed(String) case unzipFailed(String) case xcframeworkSliceNotFound @@ -30,7 +30,7 @@ enum LKInjectableFrameworkInstallerError: LocalizedError { } } -enum LKInjectableFrameworkInstallerStage { +enum InjectableFrameworkInstallerStage { case preparing case checkingForUpdates case downloading @@ -59,7 +59,7 @@ enum LKInjectableFrameworkInstallerStage { } } -enum LKInjectableFrameworkInstallerLayout { +enum InjectableFrameworkInstallerLayout { /// Hard floor — bundled-baseline server version this build of the client is /// known to be compatible with. If the GitHub latest-release lookup fails /// (rate limit, offline) the installer falls back to this version. @@ -99,13 +99,13 @@ enum LKInjectableFrameworkInstallerLayout { } } -struct LKInjectableFrameworkInstallation { +struct InjectableFrameworkInstallation { let version: String let frameworkURL: URL } -final class LKInjectableFrameworkInstaller { - static let shared = LKInjectableFrameworkInstaller() +final class InjectableFrameworkInstaller { + static let shared = InjectableFrameworkInstaller() private init() {} @@ -123,9 +123,9 @@ final class LKInjectableFrameworkInstaller { /// matches the host team identifier, returns immediately. /// - Otherwise presents a modal progress window while downloading, /// extracting, signature-verifying and moving the framework into place. - func ensureInstalled(presentingWindow: NSWindow?) throws -> LKInjectableFrameworkInstallation { + func ensureInstalled(presentingWindow: NSWindow?) throws -> InjectableFrameworkInstallation { if !Thread.isMainThread { - var captured: Result! + var captured: Result! DispatchQueue.main.sync { do { let installation = try self.ensureInstalled(presentingWindow: presentingWindow) @@ -140,43 +140,43 @@ final class LKInjectableFrameworkInstaller { installLock.lock() defer { installLock.unlock() } - LKInstallerLogger.installer.info("ensureInstalled: entered") + InstallerLogger.installer.info("ensureInstalled: entered") let targetVersion = resolveTargetVersion() - LKInstallerLogger.installer.info( + InstallerLogger.installer.info( "ensureInstalled: resolved target version=\(targetVersion, privacy: .public)" ) - let installedURL = LKInjectableFrameworkInstallerLayout.installedFrameworkURL(for: targetVersion) - LKInstallerLogger.installer.info( + let installedURL = InjectableFrameworkInstallerLayout.installedFrameworkURL(for: targetVersion) + InstallerLogger.installer.info( "ensureInstalled: checking existing path=\(installedURL.path, privacy: .public)" ) if FileManager.default.fileExists(atPath: installedURL.path) { do { try verifyTeamIdentifier(of: installedURL) - LKInstallerLogger.installer.info( + InstallerLogger.installer.info( "ensureInstalled: existing framework valid; reusing version=\(targetVersion, privacy: .public)" ) - return LKInjectableFrameworkInstallation(version: targetVersion, frameworkURL: installedURL) + return InjectableFrameworkInstallation(version: targetVersion, frameworkURL: installedURL) } catch { - LKInstallerLogger.installer.notice( + InstallerLogger.installer.notice( "ensureInstalled: existing framework signature invalid (\(error.localizedDescription, privacy: .public)); will re-download" ) try? FileManager.default.removeItem(at: installedURL) } } else { - LKInstallerLogger.installer.info("ensureInstalled: no existing framework; running modal install") + InstallerLogger.installer.info("ensureInstalled: no existing framework; running modal install") } return try runInstallWithModal(version: targetVersion, presentingWindow: presentingWindow) } func verifyTeamIdentifier(of frameworkURL: URL) throws { - try LKInstallerCodeSignature.verifyTeamIdentifierMatchesHost( + try InstallerCodeSignature.verifyTeamIdentifierMatchesHost( of: frameworkURL, - unavailableErrorBuilder: { LKInjectableFrameworkInstallerError.teamIdentifierUnavailable($0) }, + unavailableErrorBuilder: { InjectableFrameworkInstallerError.teamIdentifierUnavailable($0) }, mismatchErrorBuilder: { expected, found in - LKInjectableFrameworkInstallerError.teamIdentifierMismatch(expected: expected, found: found) + InjectableFrameworkInstallerError.teamIdentifierMismatch(expected: expected, found: found) } ) } @@ -184,9 +184,9 @@ final class LKInjectableFrameworkInstaller { // MARK: - Version resolution private func resolveTargetVersion() -> String { - let minimum = LKInjectableFrameworkInstallerLayout.minimumServerVersion + let minimum = InjectableFrameworkInstallerLayout.minimumServerVersion guard let latest = fetchLatestVersionFromGitHub() else { - LKInstallerLogger.installer.info( + InstallerLogger.installer.info( "GH latest-release lookup unavailable, falling back to minimum version=\(minimum, privacy: .public)" ) return minimum @@ -194,7 +194,7 @@ final class LKInjectableFrameworkInstaller { if compareSemver(latest, minimum) >= 0 { return latest } - LKInstallerLogger.installer.notice( + InstallerLogger.installer.notice( "GH latest=\(latest, privacy: .public) is older than minimum=\(minimum, privacy: .public); using minimum" ) return minimum @@ -204,7 +204,7 @@ final class LKInjectableFrameworkInstaller { var capturedTag: String? let semaphore = DispatchSemaphore(value: 0) - var request = URLRequest(url: LKInjectableFrameworkInstallerLayout.latestReleaseAPIURL) + var request = URLRequest(url: InjectableFrameworkInstallerLayout.latestReleaseAPIURL) request.timeoutInterval = 5 request.cachePolicy = .reloadIgnoringLocalAndRemoteCacheData request.addValue("application/vnd.github+json", forHTTPHeaderField: "Accept") @@ -213,7 +213,7 @@ final class LKInjectableFrameworkInstaller { let task = URLSession.shared.dataTask(with: request) { data, response, error in defer { semaphore.signal() } if let error { - LKInstallerLogger.installer.warning( + InstallerLogger.installer.warning( "GH latest fetch failed: \(error.localizedDescription, privacy: .public)" ) return @@ -223,7 +223,7 @@ final class LKInjectableFrameworkInstaller { let data else { let status = (response as? HTTPURLResponse)?.statusCode ?? -1 - LKInstallerLogger.installer.warning("GH latest fetch returned status=\(status)") + InstallerLogger.installer.warning("GH latest fetch returned status=\(status)") return } do { @@ -232,7 +232,7 @@ final class LKInjectableFrameworkInstaller { capturedTag = tag } } catch { - LKInstallerLogger.installer.warning( + InstallerLogger.installer.warning( "GH latest JSON parse failed: \(error.localizedDescription, privacy: .public)" ) } @@ -263,15 +263,15 @@ final class LKInjectableFrameworkInstaller { // MARK: - Install flow - private func runInstallWithModal(version: String, presentingWindow _: NSWindow?) throws -> LKInjectableFrameworkInstallation { + private func runInstallWithModal(version: String, presentingWindow _: NSWindow?) throws -> InjectableFrameworkInstallation { precondition(Thread.isMainThread, "runInstallWithModal must run on the main thread") - LKInstallerLogger.installer.info("runInstallWithModal: start version=\(version, privacy: .public)") + InstallerLogger.installer.info("runInstallWithModal: start version=\(version, privacy: .public)") - let cancellation = LKInstallerCancellation() - let controller = LKInstallerProgressWindowController( + let cancellation = InstallerCancellation() + let controller = InstallerProgressWindowController( title: NSLocalizedString("Downloading LookInside Server Framework", comment: ""), - initialStatus: LKInjectableFrameworkInstallerStage.preparing.localizedDescription + initialStatus: InjectableFrameworkInstallerStage.preparing.localizedDescription ) var cancelledByUser = false controller.onCancel = { @@ -280,24 +280,24 @@ final class LKInjectableFrameworkInstaller { NSApp.stopModal() } controller.showWindow(self) - LKInstallerLogger.installer.info("runInstallWithModal: progress window shown") + InstallerLogger.installer.info("runInstallWithModal: progress window shown") - var captured: Result! + var captured: Result! let semaphore = DispatchSemaphore(value: 0) Thread.detachNewThread { - LKInstallerLogger.installer.info("install worker: thread started") + InstallerLogger.installer.info("install worker: thread started") do { let installation = try self.performInstall(version: version, cancellation: cancellation) { stage in - LKInstallerLogger.installer.info("install worker: stage=\(String(describing: stage), privacy: .public)") + InstallerLogger.installer.info("install worker: stage=\(String(describing: stage), privacy: .public)") RunLoop.main.perform(inModes: [.default, .modalPanel, .common]) { controller.updateStatus(stage.localizedDescription) } } - LKInstallerLogger.installer.info("install worker: success") + InstallerLogger.installer.info("install worker: success") captured = .success(installation) } catch { - LKInstallerLogger.installer.error( + InstallerLogger.installer.error( "install worker: failed error=\(error.localizedDescription, privacy: .public)" ) captured = .failure(error) @@ -308,29 +308,29 @@ final class LKInjectableFrameworkInstaller { } } - LKInstallerLogger.installer.info("runInstallWithModal: entering runModal") + InstallerLogger.installer.info("runInstallWithModal: entering runModal") NSApp.runModal(for: controller.window!) - LKInstallerLogger.installer.info("runInstallWithModal: runModal returned") + InstallerLogger.installer.info("runInstallWithModal: runModal returned") let waitResult = semaphore.wait(timeout: .now() + 5) controller.close() if cancelledByUser { - LKInstallerLogger.installer.info("runInstallWithModal: cancelled by user") - throw LKInjectableFrameworkInstallerError.cancelled + InstallerLogger.installer.info("runInstallWithModal: cancelled by user") + throw InjectableFrameworkInstallerError.cancelled } if waitResult == .timedOut { - LKInstallerLogger.installer.error("runInstallWithModal: worker did not signal within 5s after modal stop") + InstallerLogger.installer.error("runInstallWithModal: worker did not signal within 5s after modal stop") cancellation.cancel() - throw LKInjectableFrameworkInstallerError.cancelled + throw InjectableFrameworkInstallerError.cancelled } return try captured.get() } private func performInstall( version: String, - cancellation: LKInstallerCancellation, - onStage: @escaping (LKInjectableFrameworkInstallerStage) -> Void - ) throws -> LKInjectableFrameworkInstallation { + cancellation: InstallerCancellation, + onStage: @escaping (InjectableFrameworkInstallerStage) -> Void + ) throws -> InjectableFrameworkInstallation { do { try cancellation.checkCancellation() onStage(.preparing) @@ -338,7 +338,7 @@ final class LKInjectableFrameworkInstaller { let stagingRoot = fileManager.temporaryDirectory .appendingPathComponent("LookInsideServerFramework-\(UUID().uuidString)", isDirectory: true) try fileManager.createDirectory(at: stagingRoot, withIntermediateDirectories: true) - LKInstallerLogger.installer.info( + InstallerLogger.installer.info( "performInstall: staging root=\(stagingRoot.path, privacy: .public)" ) defer { @@ -348,47 +348,47 @@ final class LKInjectableFrameworkInstaller { try cancellation.checkCancellation() onStage(.downloading) let zipURL = stagingRoot.appendingPathComponent("server.xcframework.zip", isDirectory: false) - let downloadURL = LKInjectableFrameworkInstallerLayout.assetDownloadURL(for: version) - LKInstallerLogger.installer.info( + let downloadURL = InjectableFrameworkInstallerLayout.assetDownloadURL(for: version) + InstallerLogger.installer.info( "performInstall: starting download url=\(downloadURL.absoluteString, privacy: .public)" ) - try LKInstallerDownloader.download( + try InstallerDownloader.download( from: downloadURL, to: zipURL, cancellation: cancellation, timeout: 120, - errorBuilder: { LKInjectableFrameworkInstallerError.downloadFailed($0) } + errorBuilder: { InjectableFrameworkInstallerError.downloadFailed($0) } ) let zipSize = (try? fileManager.attributesOfItem(atPath: zipURL.path)[.size] as? Int) ?? -1 - LKInstallerLogger.installer.info("performInstall: download complete bytes=\(zipSize)") + InstallerLogger.installer.info("performInstall: download complete bytes=\(zipSize)") try cancellation.checkCancellation() onStage(.extracting) let extractDir = stagingRoot.appendingPathComponent("extracted", isDirectory: true) try fileManager.createDirectory(at: extractDir, withIntermediateDirectories: true) - LKInstallerLogger.installer.info("performInstall: starting unzip into=\(extractDir.path, privacy: .public)") - try LKInstallerArchiveExtractor.unzip( + InstallerLogger.installer.info("performInstall: starting unzip into=\(extractDir.path, privacy: .public)") + try InstallerArchiveExtractor.unzip( zipURL, into: extractDir, cancellation: cancellation, - errorBuilder: { LKInjectableFrameworkInstallerError.unzipFailed($0) } + errorBuilder: { InjectableFrameworkInstallerError.unzipFailed($0) } ) - LKInstallerLogger.installer.info("performInstall: unzip complete") + InstallerLogger.installer.info("performInstall: unzip complete") try cancellation.checkCancellation() let stagedFramework = try locateMacFramework(in: extractDir) - LKInstallerLogger.installer.info( + InstallerLogger.installer.info( "performInstall: located macOS framework path=\(stagedFramework.path, privacy: .public)" ) onStage(.verifying) try verifyTeamIdentifier(of: stagedFramework) - LKInstallerLogger.installer.info("performInstall: signature verified") + InstallerLogger.installer.info("performInstall: signature verified") try cancellation.checkCancellation() onStage(.installing) - let destinationDir = LKInjectableFrameworkInstallerLayout.versionDirectoryURL(for: version) - let destinationFramework = LKInjectableFrameworkInstallerLayout.installedFrameworkURL(for: version) + let destinationDir = InjectableFrameworkInstallerLayout.versionDirectoryURL(for: version) + let destinationFramework = InjectableFrameworkInstallerLayout.installedFrameworkURL(for: version) try fileManager.createDirectory( at: destinationDir, withIntermediateDirectories: true @@ -399,9 +399,9 @@ final class LKInjectableFrameworkInstaller { do { try fileManager.moveItem(at: stagedFramework, to: destinationFramework) } catch { - throw LKInjectableFrameworkInstallerError.installFailed(error.localizedDescription) + throw InjectableFrameworkInstallerError.installFailed(error.localizedDescription) } - LKInstallerLogger.installer.info( + InstallerLogger.installer.info( "performInstall: moved into place path=\(destinationFramework.path, privacy: .public)" ) @@ -409,13 +409,13 @@ final class LKInjectableFrameworkInstaller { onStage(.finishing) try verifyTeamIdentifier(of: destinationFramework) - LKInstallerLogger.installer.info( + InstallerLogger.installer.info( "performInstall: done version=\(version, privacy: .public)" ) - return LKInjectableFrameworkInstallation(version: version, frameworkURL: destinationFramework) - } catch is LKInstallerCancelled { - LKInstallerLogger.installer.info("performInstall: cancelled") - throw LKInjectableFrameworkInstallerError.cancelled + return InjectableFrameworkInstallation(version: version, frameworkURL: destinationFramework) + } catch is InstallerCancelled { + InstallerLogger.installer.info("performInstall: cancelled") + throw InjectableFrameworkInstallerError.cancelled } } @@ -426,7 +426,7 @@ final class LKInjectableFrameworkInstaller { private func locateMacFramework(in directory: URL) throws -> URL { let fileManager = FileManager.default let xcframework = directory - .appendingPathComponent(LKInjectableFrameworkInstallerLayout.xcframeworkBundleName, isDirectory: true) + .appendingPathComponent(InjectableFrameworkInstallerLayout.xcframeworkBundleName, isDirectory: true) var searchRoots: [URL] = [] if fileManager.fileExists(atPath: xcframework.path) { @@ -444,13 +444,13 @@ final class LKInjectableFrameworkInstaller { } for slice in children where slice.lastPathComponent.hasPrefix("macos-") { let framework = slice - .appendingPathComponent(LKInjectableFrameworkInstallerLayout.frameworkBundleName, isDirectory: true) + .appendingPathComponent(InjectableFrameworkInstallerLayout.frameworkBundleName, isDirectory: true) if fileManager.fileExists(atPath: framework.path) { return framework } } } - throw LKInjectableFrameworkInstallerError.xcframeworkSliceNotFound + throw InjectableFrameworkInstallerError.xcframeworkSliceNotFound } } diff --git a/LookInside/Injection/LKInjectionFlow.swift b/LookInside/Injection/InjectionFlow.swift similarity index 75% rename from LookInside/Injection/LKInjectionFlow.swift rename to LookInside/Injection/InjectionFlow.swift index 21797c57..065068ea 100644 --- a/LookInside/Injection/LKInjectionFlow.swift +++ b/LookInside/Injection/InjectionFlow.swift @@ -3,27 +3,27 @@ import Foundation /// Orchestrates the attach-to-running-app flow: /// -/// 1. `LKInjectionService.registerDaemonIfNeeded()` — only after the user +/// 1. `InjectionService.registerDaemonIfNeeded()` — only after the user /// clicks Attach, asks before registering the privileged daemon with /// SMAppService and waits for administrator approval if macOS requires it. -/// 2. `LKInjectionTargetPicker` — wraps `RunningPickerTabViewController`. -/// 3. `LKInjectableFrameworkInstaller` — ensures LookInsideServer.framework is +/// 2. `InjectionTargetPicker` — wraps `RunningPickerTabViewController`. +/// 3. `InjectableFrameworkInstaller` — ensures LookInsideServer.framework is /// downloaded under `~/Library/Application Support/LookInside/InjectableFrameworks/`. -/// 4. `LKInjectionService.attach(pid:dylibURL:)` — fires +/// 4. `InjectionService.attach(pid:dylibURL:)` — fires /// `InjectApplicationRequest` at the root daemon over XPC. /// 5. Brief sleep so the target app's Server listener can bind; the existing -/// `LKLaunchViewController` 1.5s refresh tick then discovers the newly +/// `LaunchViewController` 1.5s refresh tick then discovers the newly /// inspectable app automatically. @objc(LKInjectionFlow) -final class LKInjectionFlow: NSObject { - @objc(sharedInstance) static let shared = LKInjectionFlow() +final class InjectionFlow: NSObject { + @objc(sharedInstance) static let shared = InjectionFlow() - private var picker: LKInjectionTargetPicker? - private var startGate = LKInjectionStartGate() + private var picker: InjectionTargetPicker? + private var startGate = InjectionStartGate() @objc func startFromWindow(_ window: NSWindow?) { let decision = startGate.begin { - LKSwiftUISupportGatekeeper.sharedInstance().canUseProtectedFeatureWithoutPrompt() + SwiftUISupportGatekeeper.sharedInstance().canUseProtectedFeatureWithoutPrompt() } guard decision == .started else { return } @@ -43,10 +43,10 @@ final class LKInjectionFlow: NSObject { return } - let installation: LKInjectableFrameworkInstallation + let installation: InjectableFrameworkInstallation do { - installation = try LKInjectableFrameworkInstaller.shared.ensureInstalled(presentingWindow: window) - } catch let error as LKInjectableFrameworkInstallerError where error.isCancellation { + installation = try InjectableFrameworkInstaller.shared.ensureInstalled(presentingWindow: window) + } catch let error as InjectableFrameworkInstallerError where error.isCancellation { return } catch { presentAlert(error: error, window: window) @@ -56,7 +56,7 @@ final class LKInjectionFlow: NSObject { let dylibURL = installation.frameworkURL.appendingPathComponent("LookInsideServer", isDirectory: false) do { - try await LKInjectionService.shared.attach(pid: pid, dylibURL: dylibURL) + try await InjectionService.shared.attach(pid: pid, dylibURL: dylibURL) } catch { presentAlert(error: error, window: window) return @@ -69,8 +69,8 @@ final class LKInjectionFlow: NSObject { @MainActor private func ensureDaemonReady(window: NSWindow?) async -> Bool { while true { - let status = await LKInjectionService.shared.currentDaemonStatusSnapshot() - switch LKInjectionDaemonReadiness.nextStep(for: status) { + let status = await InjectionService.shared.currentDaemonStatusSnapshot() + switch InjectionDaemonReadiness.nextStep(for: status) { case .proceed: return true @@ -79,9 +79,9 @@ final class LKInjectionFlow: NSObject { return false } do { - try await LKInjectionService.shared.registerDaemonIfNeeded() + try await InjectionService.shared.registerDaemonIfNeeded() return true - } catch LKInjectionServiceError.daemonRequiresApproval { + } catch InjectionServiceError.daemonRequiresApproval { return await presentDaemonApprovalGuide(window: window) } catch { presentAlert(error: error, window: window) @@ -94,15 +94,15 @@ final class LKInjectionFlow: NSObject { } case .reportMissingBundle: - presentAlert(error: LKInjectionServiceError.daemonBundleMissing, window: window) + presentAlert(error: InjectionServiceError.daemonBundleMissing, window: window) return false case .reportCurrentLocationUnsupported: - presentAlert(error: LKInjectionServiceError.daemonUnavailableFromCurrentLocation, window: window) + presentAlert(error: InjectionServiceError.daemonUnavailableFromCurrentLocation, window: window) return false case let .reportUnsupportedStatus(rawValue): - presentAlert(error: LKInjectionServiceError.unsupportedDaemonStatus(rawValue), window: window) + presentAlert(error: InjectionServiceError.unsupportedDaemonStatus(rawValue), window: window) return false } } @@ -133,7 +133,7 @@ final class LKInjectionFlow: NSObject { @MainActor private func pickTargetPID(window: NSWindow?) async -> pid_t? { await withCheckedContinuation { continuation in - let picker = LKInjectionTargetPicker() + let picker = InjectionTargetPicker() self.picker = picker var resumed = false picker.onConfirm = { [weak self] pid, _ in @@ -155,22 +155,22 @@ final class LKInjectionFlow: NSObject { @MainActor private func presentDaemonApprovalGuide(window: NSWindow?) async -> Bool { while true { - let status = await LKInjectionService.shared.currentDaemonStatusSnapshot() - switch LKInjectionDaemonReadiness.nextStep(for: status) { + let status = await InjectionService.shared.currentDaemonStatusSnapshot() + switch InjectionDaemonReadiness.nextStep(for: status) { case .proceed: return true case .reportMissingBundle: - presentAlert(error: LKInjectionServiceError.daemonBundleMissing, window: window) + presentAlert(error: InjectionServiceError.daemonBundleMissing, window: window) return false case .reportCurrentLocationUnsupported: - presentAlert(error: LKInjectionServiceError.daemonUnavailableFromCurrentLocation, window: window) + presentAlert(error: InjectionServiceError.daemonUnavailableFromCurrentLocation, window: window) return false case .requestRegistrationConsent: return false case .waitForApproval: break case let .reportUnsupportedStatus(rawValue): - presentAlert(error: LKInjectionServiceError.unsupportedDaemonStatus(rawValue), window: window) + presentAlert(error: InjectionServiceError.unsupportedDaemonStatus(rawValue), window: window) return false } @@ -197,7 +197,7 @@ final class LKInjectionFlow: NSObject { case .alertFirstButtonReturn: continue case .alertSecondButtonReturn: - LKInjectionService.shared.openLoginItemsSettings() + InjectionService.shared.openLoginItemsSettings() return false default: return false @@ -232,7 +232,7 @@ final class LKInjectionFlow: NSObject { } } -private extension LKInjectableFrameworkInstallerError { +private extension InjectableFrameworkInstallerError { var isCancellation: Bool { if case .cancelled = self { return true diff --git a/LookInside/Injection/LKInjectionService.swift b/LookInside/Injection/InjectionService.swift similarity index 87% rename from LookInside/Injection/LKInjectionService.swift rename to LookInside/Injection/InjectionService.swift index b74caae7..683f61a8 100644 --- a/LookInside/Injection/LKInjectionService.swift +++ b/LookInside/Injection/InjectionService.swift @@ -5,7 +5,7 @@ import HelperCommunication import InjectionServiceInterface import ServiceManagement -enum LKInjectionServiceError: LocalizedError { +enum InjectionServiceError: LocalizedError { case daemonRegistrationFailed(String) case daemonRequiresApproval case daemonBundleMissing @@ -71,8 +71,8 @@ enum LKInjectionServiceError: LocalizedError { } } -final class LKInjectionService { - static let shared = LKInjectionService() +final class InjectionService { + static let shared = InjectionService() static let machServiceName = "app.lookinside.LookInsideInjector" static let daemonPlistName = "app.lookinside.LookInsideInjector.plist" @@ -88,7 +88,7 @@ final class LKInjectionService { await daemonInstaller.currentStatus } - func currentDaemonStatusSnapshot() async -> LKInjectionDaemonStatusSnapshot { + func currentDaemonStatusSnapshot() async -> InjectionDaemonStatusSnapshot { Self.statusSnapshot(await daemonInstaller.currentStatus) } @@ -107,32 +107,32 @@ final class LKInjectionService { case .enabled: return case .requiresApproval: - throw LKInjectionServiceError.daemonRequiresApproval + throw InjectionServiceError.daemonRequiresApproval case .notFound: - throw LKInjectionServiceError.daemonBundleMissing + throw InjectionServiceError.daemonBundleMissing case .unavailableFromCurrentLocation: - throw LKInjectionServiceError.daemonUnavailableFromCurrentLocation + throw InjectionServiceError.daemonUnavailableFromCurrentLocation case .notRegistered: do { try await daemonInstaller.register() } catch { - throw LKInjectionServiceError.daemonRegistrationFailed(Self.registrationFailureMessage(from: error)) + throw InjectionServiceError.daemonRegistrationFailed(Self.registrationFailureMessage(from: error)) } let newStatus = await currentDaemonStatusSnapshot() switch newStatus { case .enabled: return case .requiresApproval, .notRegistered: - throw LKInjectionServiceError.daemonRequiresApproval + throw InjectionServiceError.daemonRequiresApproval case .notFound: - throw LKInjectionServiceError.daemonBundleMissing + throw InjectionServiceError.daemonBundleMissing case .unavailableFromCurrentLocation: - throw LKInjectionServiceError.daemonUnavailableFromCurrentLocation + throw InjectionServiceError.daemonUnavailableFromCurrentLocation case let .unknown(rawValue): - throw LKInjectionServiceError.unsupportedDaemonStatus(rawValue) + throw InjectionServiceError.unsupportedDaemonStatus(rawValue) } case let .unknown(rawValue): - throw LKInjectionServiceError.unsupportedDaemonStatus(rawValue) + throw InjectionServiceError.unsupportedDaemonStatus(rawValue) } } @@ -146,7 +146,7 @@ final class LKInjectionService { /// The daemon performs the actual `task_for_pid` + Mach-injection. Callers /// must have: /// 1. Resolved a valid macOS-slice dylib URL inside an installed - /// `LookInsideServer.framework` (see `LKInjectableFrameworkInstaller`). + /// `LookInsideServer.framework` (see `InjectableFrameworkInstaller`). /// 2. Confirmed daemon enablement via `registerDaemonIfNeeded()`. /// /// LookInside Pro gating is enforced in the host before this service is @@ -160,14 +160,14 @@ final class LKInjectionService { request: InjectApplicationRequest(pid: pid, dylibURL: dylibURL) ) } catch { - throw LKInjectionServiceError.attachFailed(error.localizedDescription) + throw InjectionServiceError.attachFailed(error.localizedDescription) } } private func ensureConnectedToTool() async throws { let status = await daemonInstaller.currentStatus guard status == .enabled else { - throw LKInjectionServiceError.daemonNotEnabled(status: status) + throw InjectionServiceError.daemonNotEnabled(status: status) } if await helperClient.isConnectedToTool { return @@ -178,7 +178,7 @@ final class LKInjectionService { isPrivilegedHelperTool: true ) } catch { - throw LKInjectionServiceError.daemonUnreachable(error.localizedDescription) + throw InjectionServiceError.daemonUnreachable(error.localizedDescription) } } @@ -194,7 +194,7 @@ final class LKInjectionService { ) } - private static func statusSnapshot(_ status: SMAppService.Status) -> LKInjectionDaemonStatusSnapshot { + private static func statusSnapshot(_ status: SMAppService.Status) -> InjectionDaemonStatusSnapshot { switch status { case .notRegistered: return .notRegistered diff --git a/LookInside/Injection/LKInjectionStartGate.swift b/LookInside/Injection/InjectionStartGate.swift similarity index 79% rename from LookInside/Injection/LKInjectionStartGate.swift rename to LookInside/Injection/InjectionStartGate.swift index 562d683b..ffa630f7 100644 --- a/LookInside/Injection/LKInjectionStartGate.swift +++ b/LookInside/Injection/InjectionStartGate.swift @@ -1,15 +1,15 @@ import Foundation -enum LKInjectionStartDecision: Equatable { +enum InjectionStartDecision: Equatable { case started case alreadyInProgress case blocked } -struct LKInjectionStartGate { +struct InjectionStartGate { private(set) var isInProgress = false - mutating func begin(isProtectedFeatureAllowedSilently: () -> Bool) -> LKInjectionStartDecision { + mutating func begin(isProtectedFeatureAllowedSilently: () -> Bool) -> InjectionStartDecision { guard !isInProgress else { return .alreadyInProgress } @@ -25,7 +25,7 @@ struct LKInjectionStartGate { } } -enum LKInjectionDaemonStatusSnapshot: Equatable { +enum InjectionDaemonStatusSnapshot: Equatable { case notRegistered case enabled case requiresApproval @@ -34,7 +34,7 @@ enum LKInjectionDaemonStatusSnapshot: Equatable { case unknown(Int) } -enum LKInjectionDaemonNextStep: Equatable { +enum InjectionDaemonNextStep: Equatable { case proceed case requestRegistrationConsent case waitForApproval @@ -43,8 +43,8 @@ enum LKInjectionDaemonNextStep: Equatable { case reportUnsupportedStatus(Int) } -enum LKInjectionDaemonReadiness { - static func nextStep(for status: LKInjectionDaemonStatusSnapshot) -> LKInjectionDaemonNextStep { +enum InjectionDaemonReadiness { + static func nextStep(for status: InjectionDaemonStatusSnapshot) -> InjectionDaemonNextStep { switch status { case .enabled: return .proceed diff --git a/LookInside/Injection/LKInjectionTargetPicker.swift b/LookInside/Injection/InjectionTargetPicker.swift similarity index 98% rename from LookInside/Injection/LKInjectionTargetPicker.swift rename to LookInside/Injection/InjectionTargetPicker.swift index 9af12def..b9fc9cf7 100644 --- a/LookInside/Injection/LKInjectionTargetPicker.swift +++ b/LookInside/Injection/InjectionTargetPicker.swift @@ -1,7 +1,7 @@ import AppKit import RunningApplicationKit -final class LKInjectionTargetPicker: NSObject, RunningPickerTabViewController.Delegate { +final class InjectionTargetPicker: NSObject, RunningPickerTabViewController.Delegate { typealias ConfirmHandler = (_ pid: pid_t, _ label: String) -> Void typealias CancelHandler = () -> Void diff --git a/LookInside/Launch/LKLaunchAppView.swift b/LookInside/Launch/LaunchAppView.swift similarity index 81% rename from LookInside/Launch/LKLaunchAppView.swift rename to LookInside/Launch/LaunchAppView.swift index 6ee1e52a..11767385 100644 --- a/LookInside/Launch/LKLaunchAppView.swift +++ b/LookInside/Launch/LaunchAppView.swift @@ -1,5 +1,5 @@ // -// LKLaunchAppView.swift +// LaunchAppView.swift // Lookin // // Created by Li Kai on 2018/11/3. @@ -13,16 +13,16 @@ import AppKit /// version is unsupported shows the error and a link to the explanation /// instead. @objc(LKLaunchAppView) -final class LKLaunchAppView: LKBaseControl { +final class LaunchAppView: BaseControl { private let hoverBgLayer = CALayer() private let previewImageView = NSImageView() private let iconImageView = NSImageView() - private let titleLabel = LKLabel() - private let subtitleLabel = LKLabel() + private let titleLabel = TextLabel() + private let subtitleLabel = TextLabel() private var errorImageView: NSImageView? - private var errorTitleLabel: LKLabel? - private var errorSubtitleLabel: LKLabel? + private var errorTitleLabel: TextLabel? + private var errorSubtitleLabel: TextLabel? private var previewSize = NSSize.zero private var insets = NSEdgeInsetsZero @@ -59,7 +59,7 @@ final class LKLaunchAppView: LKBaseControl { didSet { applyLayoutMetrics() } } - @objc var app: LKInspectableApp? { + @objc var app: InspectableApp? { didSet { appDidChange() } } @@ -91,25 +91,25 @@ final class LKLaunchAppView: LKBaseControl { hoverBgLayer.frame = layer?.bounds ?? .zero if hasServerVersionError, let errorImageView, let errorTitleLabel, let errorSubtitleLabel { - LKViewFrameLayout(errorImageView).sizeToFit().horAlign() - LKViewFrameLayout(errorTitleLabel).x(10).toRight(10).heightToFit().y(errorImageView.frame.maxY + 15) - LKViewFrameLayout(errorSubtitleLabel).sizeToFit().horAlign().y(errorTitleLabel.frame.maxY + 10) + ViewFrameLayout(errorImageView).sizeToFit().horAlign() + ViewFrameLayout(errorTitleLabel).x(10).toRight(10).heightToFit().y(errorImageView.frame.maxY + 15) + ViewFrameLayout(errorSubtitleLabel).sizeToFit().horAlign().y(errorTitleLabel.frame.maxY + 10) let errorViews: [NSView] = [errorImageView, errorTitleLabel, errorSubtitleLabel] - LKViewFrameLayout.groupVerAlign(errorViews) - errorViews.forEach { LKViewFrameLayout($0).offsetY(-10) } + ViewFrameLayout.groupVerAlign(errorViews) + errorViews.forEach { ViewFrameLayout($0).offsetY(-10) } } else if !hasServerVersionError { - LKViewFrameLayout(previewImageView).size(previewSize).horAlign().y(insets.top) - LKViewFrameLayout(iconImageView).sizeToFit().y(insets.top + previewSize.height + iconTop) + ViewFrameLayout(previewImageView).size(previewSize).horAlign().y(insets.top) + ViewFrameLayout(iconImageView).sizeToFit().y(insets.top + previewSize.height + iconTop) - LKViewFrameLayout(titleLabel).sizeToFit() - LKViewFrameLayout(subtitleLabel).sizeToFit().y(titleLabel.frame.maxY + 2) + ViewFrameLayout(titleLabel).sizeToFit() + ViewFrameLayout(subtitleLabel).sizeToFit().y(titleLabel.frame.maxY + 2) let labels: [NSView] = [titleLabel, subtitleLabel] - labels.forEach { LKViewFrameLayout($0).x(iconImageView.frame.maxX + iconMarginRight) } - LKViewFrameLayout.groupMidY(labels, iconImageView.frame.midY) + labels.forEach { ViewFrameLayout($0).x(iconImageView.frame.maxX + iconMarginRight) } + ViewFrameLayout.groupMidY(labels, iconImageView.frame.midY) let row: [NSView] = [iconImageView, titleLabel, subtitleLabel] - LKViewFrameLayout.groupHorAlign(row) - row.forEach { LKViewFrameLayout($0).offsetX(-2) } + ViewFrameLayout.groupHorAlign(row) + row.forEach { ViewFrameLayout($0).offsetX(-2) } } } @@ -142,7 +142,7 @@ final class LKLaunchAppView: LKBaseControl { makeErrorViewsIfNeeded() [errorImageView, errorTitleLabel, errorSubtitleLabel].forEach { $0?.isHidden = false } normalViews.forEach { $0.isHidden = true } - errorTitleLabel?.stringValue = LKLaunchRules.serverVersionErrorTitle( + errorTitleLabel?.stringValue = LaunchRules.serverVersionErrorTitle( errorCode: error.code, localizedDescription: error.localizedDescription ) @@ -163,10 +163,10 @@ final class LKLaunchAppView: LKBaseControl { /// Prefer the icon of the actual hardware model the app runs on. Falls back to the /// per-family asset when the peer's LookinServer does not report a model identifier. private static func deviceIcon(for appInfo: InspectedAppInfo?) -> NSImage? { - if let icon = LKDeviceIconProvider.deviceIcon(forAppInfo: appInfo, pointSize: LKDeviceIconProvider.launchPointSize) { + if let icon = DeviceIconProvider.deviceIcon(forAppInfo: appInfo, pointSize: DeviceIconProvider.launchPointSize) { return icon } - if LKHelper.appInfoLooksLikeMacTarget(appInfo) || appInfo?.deviceType == .macCatalyst { + if AppHelper.appInfoLooksLikeMacTarget(appInfo) || appInfo?.deviceType == .macCatalyst { // A Catalyst app runs on Mac hardware, so it gets the Mac icon even though // +appInfoLooksLikeMacTarget: deliberately answers NO for it (its views are UIKit). return NSImage(named: "icon_mac_big") @@ -216,7 +216,7 @@ final class LKLaunchAppView: LKBaseControl { errorImageView = imageView } if errorTitleLabel == nil { - let label = LKLabel() + let label = TextLabel() label.textColor = .labelColor label.alignment = .center label.maximumNumberOfLines = 0 @@ -224,7 +224,7 @@ final class LKLaunchAppView: LKBaseControl { errorTitleLabel = label } if errorSubtitleLabel == nil { - let label = LKLabel() + let label = TextLabel() label.stringValue = NSLocalizedString("Find solution…", comment: "") label.textColor = .linkColor addSubview(label) diff --git a/LookInside/Launch/LKLaunchRules.swift b/LookInside/Launch/LaunchRules.swift similarity index 97% rename from LookInside/Launch/LKLaunchRules.swift rename to LookInside/Launch/LaunchRules.swift index 70f5a9ba..84c75a0c 100644 --- a/LookInside/Launch/LKLaunchRules.swift +++ b/LookInside/Launch/LaunchRules.swift @@ -1,5 +1,5 @@ // -// LKLaunchRules.swift +// LaunchRules.swift // LookInside // // The decisions of the launch window, kept free of AppKit views so they can @@ -8,7 +8,7 @@ import Foundation -enum LKLaunchRules { +enum LaunchRules { /// Whether the launch window opens the only app it found by itself. /// /// Only the first scan after the window opens may do this, only with diff --git a/LookInside/Launch/LKLaunchViewController.swift b/LookInside/Launch/LaunchViewController.swift similarity index 79% rename from LookInside/Launch/LKLaunchViewController.swift rename to LookInside/Launch/LaunchViewController.swift index ad00d5f9..473ee9b1 100644 --- a/LookInside/Launch/LKLaunchViewController.swift +++ b/LookInside/Launch/LaunchViewController.swift @@ -1,5 +1,5 @@ // -// LKLaunchViewController.swift +// LaunchViewController.swift // Lookin // // Created by Li Kai on 2018/11/3. @@ -12,7 +12,7 @@ import AppKit /// every 1.5 seconds, and the attach-to-running-app button. Picking an app /// fetches its hierarchy and opens a live document for it. @objc(LKLaunchViewController) -final class LKLaunchViewController: LKBaseViewController { +final class LaunchViewController: BaseViewController { private static let appViewInterSpace: CGFloat = 10 private static let contentHorInset: CGFloat = 30 private static let contentHeight: CGFloat = 400 @@ -24,10 +24,10 @@ final class LKLaunchViewController: LKBaseViewController { private weak var window: NSWindow? private var autoEnterOnInitialReload: Bool - private var appViews: [LKLaunchAppView] = [] - private let bottomIndicatorView = LKProgressIndicatorView() + private var appViews: [LaunchAppView] = [] + private let bottomIndicatorView = ProgressIndicatorView() private var reloadingIndicator: NSProgressIndicator? - private var noAppsTitleLabel: LKLabel? + private var noAppsTitleLabel: TextLabel? private let attachToRunningAppButton = NSButton( title: NSLocalizedString("Attach to Running App…", comment: ""), target: nil, @@ -57,7 +57,7 @@ final class LKLaunchViewController: LKBaseViewController { } override func makeContainerView() -> NSView { - let containerView = LKVisualEffectView() + let containerView = VisualEffectView() containerView.blendingMode = .behindWindow containerView.state = .active @@ -85,31 +85,31 @@ final class LKLaunchViewController: LKBaseViewController { if let reloadingIndicator, let noAppsTitleLabel { reloadingIndicator.sizeToFit() - LKViewFrameLayout(noAppsTitleLabel).sizeToFit().x(reloadingIndicator.frame.maxX + 5).midY(reloadingIndicator.frame.midY) + ViewFrameLayout(noAppsTitleLabel).sizeToFit().x(reloadingIndicator.frame.maxX + 5).midY(reloadingIndicator.frame.midY) let views: [NSView] = [reloadingIndicator, noAppsTitleLabel] - LKViewFrameLayout.groupHorAlign(views) - LKViewFrameLayout.groupMidY(views, view.bounds.height * 0.35) + ViewFrameLayout.groupHorAlign(views) + ViewFrameLayout.groupMidY(views, view.bounds.height * 0.35) } var posX = Self.contentHorInset for appView in appViews { - LKViewFrameLayout(appView).sizeToFit().x(posX).y(30) + ViewFrameLayout(appView).sizeToFit().x(posX).y(30) posX = appView.frame.maxX + Self.appViewInterSpace } - LKViewFrameLayout(bottomIndicatorView).fullWidth().height(3).bottom(0) + ViewFrameLayout(bottomIndicatorView).fullWidth().height(3).bottom(0) attachToRunningAppButton.sizeToFit() - LKViewFrameLayout(attachToRunningAppButton) + ViewFrameLayout(attachToRunningAppButton) .midX(view.bounds.width / 2) .y(view.bounds.height - attachToRunningAppButton.frame.height - 14) } @objc private func handleAttachToRunningAppClick(_: Any?) { - guard LKSwiftUISupportGatekeeper.sharedInstance().allowProtectedFeatureAccess(for: window) else { + guard SwiftUISupportGatekeeper.sharedInstance().allowProtectedFeatureAccess(for: window) else { return } - LKInjectionFlow.shared.startFromWindow(window) + InjectionFlow.shared.startFromWindow(window) } // MARK: - Scanning @@ -119,19 +119,19 @@ final class LKLaunchViewController: LKBaseViewController { return } Task { [weak self, appInfos] in - let apps = await LKAppsManager.shared.fetchAppInfos(needImages: true, localInfos: appInfos) + let apps = await AppsManager.shared.fetchAppInfos(needImages: true, localInfos: appInfos) self?.didScan(apps, autoEnter: autoEnter) } } - private func didScan(_ apps: [LKInspectableApp], autoEnter: Bool) { + private func didScan(_ apps: [InspectableApp], autoEnter: Bool) { appInfos = apps.compactMap(\.appInfo) - let canAutoEnter = LKLaunchRules.canAutoEnter( + let canAutoEnter = LaunchRules.canAutoEnter( requested: autoEnter, appCount: apps.count, onlyAppHasServerVersionError: apps.first?.serverVersionError != nil, - isActivated: LKSwiftUISupportGatekeeper.sharedInstance().activationState == .activated + isActivated: SwiftUISupportGatekeeper.sharedInstance().activationState == .activated ) if canAutoEnter, let app = apps.first { // The scan that runs as the window opens found exactly one app: @@ -151,14 +151,14 @@ final class LKLaunchViewController: LKBaseViewController { } } - private func render(_ apps: [LKInspectableApp]) { + private func render(_ apps: [InspectableApp]) { if apps.isEmpty { window?.setContentSize(NSSize(width: 256, height: Self.contentHeight)) showNoAppsViews() appViews.forEach { $0.isHidden = true } } else { while appViews.count < apps.count { - let appView = LKLaunchAppView() + let appView = LaunchAppView() view.addSubview(appView) appViews.append(appView) } @@ -182,25 +182,25 @@ final class LKLaunchViewController: LKBaseViewController { // MARK: - Entering an app - @objc private func handleClickAppView(_ appView: LKLaunchAppView) { + @objc private func handleClickAppView(_ appView: LaunchAppView) { if isEnteringApp { return } guard let app = appView.app else { return } if let error = app.serverVersionError { - LKHelper.openLookinWebsite(withPath: LKLaunchRules.serverVersionHelpPath(errorCode: error.code)) + AppHelper.openLookinWebsite(withPath: LaunchRules.serverVersionHelpPath(errorCode: error.code)) } else { bottomIndicatorView.animate(toProgress: 0.8, duration: 1) enter(app) } } - private func enter(_ app: LKInspectableApp) { + private func enter(_ app: InspectableApp) { if isEnteringApp { return } isEnteringApp = true - LKPerformanceReporter.sharedInstance().willStartReload() + PerformanceReporter.sharedInstance().willStartReload() Task { [weak self] in let info: HierarchyInfo @@ -211,27 +211,27 @@ final class LKLaunchViewController: LKBaseViewController { return } self?.didFetchHierarchy(info, of: app) - LKPerformanceReporter.sharedInstance().didFetchHierarchy() + PerformanceReporter.sharedInstance().didFetchHierarchy() } } /// A successful pick opens a live document, which owns its own data /// source and update manager. The hierarchy just fetched primes the new /// document so its window opens populated. - private func didFetchHierarchy(_ info: HierarchyInfo, of app: LKInspectableApp) { + private func didFetchHierarchy(_ info: HierarchyInfo, of app: InspectableApp) { bottomIndicatorView.finish { [weak self] in self?.openLiveDocument(for: app, priming: info) } } - private func openLiveDocument(for app: LKInspectableApp, priming info: HierarchyInfo) { - let (document, alreadyOpen) = LookinLiveDocumentController.shared.openLiveDocument(for: app) + private func openLiveDocument(for app: InspectableApp, priming info: HierarchyInfo) { + let (document, alreadyOpen) = LiveDocumentController.shared.openLiveDocument(for: app) if !alreadyOpen { document.hierarchyDataSource?.reload(with: info, keepState: false) } - LKNavigationManager.shared.closeLaunch() + NavigationManager.shared.closeLaunch() let liveWindow = document.windowControllers.first?.window - LKSwiftUISupportGatekeeper.sharedInstance().promptForPendingDetectedSwiftUISupportIfNeeded(window: liveWindow) + SwiftUISupportGatekeeper.sharedInstance().promptForPendingDetectedSwiftUISupportIfNeeded(window: liveWindow) isEnteringApp = false } @@ -254,7 +254,7 @@ final class LKLaunchViewController: LKBaseViewController { private func showNoAppsViews() { if noAppsTitleLabel == nil { - let label = LKLabel() + let label = TextLabel() label.textColor = .labelColor label.font = NSFont.systemFont(ofSize: 14) label.stringValue = NSLocalizedString("Searching for inspectable apps", comment: "") diff --git a/LookInside/Launch/LKLaunchWindowController.swift b/LookInside/Launch/LaunchWindowController.swift similarity index 78% rename from LookInside/Launch/LKLaunchWindowController.swift rename to LookInside/Launch/LaunchWindowController.swift index baeea327..19eb4d4b 100644 --- a/LookInside/Launch/LKLaunchWindowController.swift +++ b/LookInside/Launch/LaunchWindowController.swift @@ -1,5 +1,5 @@ // -// LKLaunchWindowController.swift +// LaunchWindowController.swift // Lookin // // Created by Li Kai on 2018/11/3. @@ -10,14 +10,14 @@ import AppKit /// The small launch window that lists the inspectable apps. @objc(LKLaunchWindowController) -final class LKLaunchWindowController: LKWindowController { - @objc let launchViewController: LKLaunchViewController +final class LaunchWindowController: WindowController { + @objc let launchViewController: LaunchViewController /// - Parameter autoEnterOnInitialReload: whether the first scan opens /// the only app it finds by itself. @objc(initWithAutoEnterOnInitialReload:) init(autoEnterOnInitialReload: Bool) { - let window = LKWindow( + let window = AppWindow( contentRect: NSRect(x: 0, y: 0, width: 252, height: 400), styleMask: [.titled, .closable, .miniaturizable, .fullSizeContentView], backing: .buffered, @@ -28,7 +28,7 @@ final class LKLaunchWindowController: LKWindowController { window.isMovableByWindowBackground = true window.center() - launchViewController = LKLaunchViewController(window: window, autoEnterOnInitialReload: autoEnterOnInitialReload) + launchViewController = LaunchViewController(window: window, autoEnterOnInitialReload: autoEnterOnInitialReload) super.init(window: window) window.contentView = launchViewController.view contentViewController = launchViewController diff --git a/LookInside/MCPBridge/LKMCPBridgeFrame.swift b/LookInside/MCPBridge/LKMCPBridgeFrame.swift index e20fe7c5..4e8a2ade 100644 --- a/LookInside/MCPBridge/LKMCPBridgeFrame.swift +++ b/LookInside/MCPBridge/LKMCPBridgeFrame.swift @@ -14,7 +14,7 @@ import Foundation // MARK: - Envelope /// Discriminates the three frame kinds carried on the wire. -enum LKMCPBridgeFrameKind: String, Sendable, Codable { +enum MCPBridgeFrameKind: String, Sendable, Codable { case request case response case event @@ -27,11 +27,11 @@ enum LKMCPBridgeFrameKind: String, Sendable, Codable { /// `identifier` correlates request and response frames; it is opaque to the /// server and echoed back verbatim. `method` selects an inspection verb on the /// server side (for example, `targets.list`, `hierarchy.read`). -struct LKMCPBridgeRequest: Sendable, Codable { - let kind: LKMCPBridgeFrameKind +struct MCPBridgeRequest: Sendable, Codable { + let kind: MCPBridgeFrameKind let identifier: String let method: String - let parameters: [String: LKMCPBridgeJSONValue]? + let parameters: [String: MCPBridgeJSONValue]? enum CodingKeys: String, CodingKey { case kind @@ -47,11 +47,11 @@ struct LKMCPBridgeRequest: Sendable, Codable { /// /// Exactly one of `result` or `error` is set. The server MUST echo the /// request's `identifier` verbatim. -struct LKMCPBridgeResponse: Sendable, Codable { - let kind: LKMCPBridgeFrameKind +struct MCPBridgeResponse: Sendable, Codable { + let kind: MCPBridgeFrameKind let identifier: String - let result: LKMCPBridgeJSONValue? - let error: LKMCPBridgeErrorPayload? + let result: MCPBridgeJSONValue? + let error: MCPBridgeErrorPayload? enum CodingKeys: String, CodingKey { case kind @@ -60,12 +60,12 @@ struct LKMCPBridgeResponse: Sendable, Codable { case error } - static func success(identifier: String, result: LKMCPBridgeJSONValue?) -> LKMCPBridgeResponse { - return LKMCPBridgeResponse(kind: .response, identifier: identifier, result: result, error: nil) + static func success(identifier: String, result: MCPBridgeJSONValue?) -> MCPBridgeResponse { + return MCPBridgeResponse(kind: .response, identifier: identifier, result: result, error: nil) } - static func failure(identifier: String, error: LKMCPBridgeErrorPayload) -> LKMCPBridgeResponse { - return LKMCPBridgeResponse(kind: .response, identifier: identifier, result: nil, error: error) + static func failure(identifier: String, error: MCPBridgeErrorPayload) -> MCPBridgeResponse { + return MCPBridgeResponse(kind: .response, identifier: identifier, result: nil, error: error) } } @@ -74,12 +74,12 @@ struct LKMCPBridgeResponse: Sendable, Codable { /// An unsolicited event frame pushed by the server. The `topic` is a dotted /// path identifying the event category (for example, `hierarchy.invalidated`, /// `targets.attached`); the `payload` carries topic-specific structure. -struct LKMCPBridgeEvent: Sendable, Codable { - let kind: LKMCPBridgeFrameKind +struct MCPBridgeEvent: Sendable, Codable { + let kind: MCPBridgeFrameKind let topic: String - let payload: [String: LKMCPBridgeJSONValue]? + let payload: [String: MCPBridgeJSONValue]? - init(topic: String, payload: [String: LKMCPBridgeJSONValue]?) { + init(topic: String, payload: [String: MCPBridgeJSONValue]?) { kind = .event self.topic = topic self.payload = payload @@ -92,26 +92,26 @@ struct LKMCPBridgeEvent: Sendable, Codable { /// dotted-namespace convention (for example, `dispatch.unknownMethod`, /// `license.entitlementRequired`); free-form messages may be present for /// debuggability but must not be relied on for programmatic dispatch. -struct LKMCPBridgeErrorPayload: Sendable, Codable, Error { +struct MCPBridgeErrorPayload: Sendable, Codable, Error { let code: String let message: String - static let unknownMethod = LKMCPBridgeErrorPayload( + static let unknownMethod = MCPBridgeErrorPayload( code: "dispatch.unknownMethod", message: "The requested method is not implemented by this server." ) - static let invalidParameters = LKMCPBridgeErrorPayload( + static let invalidParameters = MCPBridgeErrorPayload( code: "dispatch.invalidParameters", message: "The request parameters could not be decoded into the expected shape." ) - static let licenseRequired = LKMCPBridgeErrorPayload( + static let licenseRequired = MCPBridgeErrorPayload( code: "license.entitlementRequired", message: "The connected LookInside license does not include the required entitlement." ) - static let internalError = LKMCPBridgeErrorPayload( + static let internalError = MCPBridgeErrorPayload( code: "dispatch.internalError", message: "An unexpected internal error occurred while servicing the request." ) @@ -123,14 +123,14 @@ struct LKMCPBridgeErrorPayload: Sendable, Codable, Error { /// the inspection schema to be statically typed at the wire layer. Used inside /// request `parameters`, response `result`, and event `payload` containers so /// the server can route opaque JSON to method-specific handlers. -enum LKMCPBridgeJSONValue: Sendable, Codable { +enum MCPBridgeJSONValue: Sendable, Codable { case null case bool(Bool) case integer(Int64) case double(Double) case string(String) - case array([LKMCPBridgeJSONValue]) - case object([String: LKMCPBridgeJSONValue]) + case array([MCPBridgeJSONValue]) + case object([String: MCPBridgeJSONValue]) init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() @@ -144,9 +144,9 @@ enum LKMCPBridgeJSONValue: Sendable, Codable { self = .double(floating) } else if let text = try? container.decode(String.self) { self = .string(text) - } else if let elements = try? container.decode([LKMCPBridgeJSONValue].self) { + } else if let elements = try? container.decode([MCPBridgeJSONValue].self) { self = .array(elements) - } else if let object = try? container.decode([String: LKMCPBridgeJSONValue].self) { + } else if let object = try? container.decode([String: MCPBridgeJSONValue].self) { self = .object(object) } else { throw DecodingError.dataCorruptedError( diff --git a/LookInside/MCPBridge/LKMCPBridgeInspectionModels.swift b/LookInside/MCPBridge/LKMCPBridgeInspectionModels.swift index d6351eac..844d8c19 100644 --- a/LookInside/MCPBridge/LKMCPBridgeInspectionModels.swift +++ b/LookInside/MCPBridge/LKMCPBridgeInspectionModels.swift @@ -6,7 +6,7 @@ // remote inspectors). They do not depend on AppKit / UIKit types. // // The naming follows the wire vocabulary: a "target" is one inspection -// session bound to a running app (one `LookinLiveDocument`); a "view node" +// session bound to a running app (one `LiveDocument`); a "view node" // is one row in a target's UI hierarchy (one `DisplayItem`). import CoreGraphics @@ -16,7 +16,7 @@ import Foundation /// CGRect represented as JSON-friendly doubles. Origin is the root coordinate /// space of the inspected hierarchy. -struct LKMCPBridgeRect: Sendable, Codable, Equatable { +struct MCPBridgeRect: Sendable, Codable, Equatable { let x: Double let y: Double let width: Double @@ -43,7 +43,7 @@ struct LKMCPBridgeRect: Sendable, Codable, Equatable { /// One row in a `targets.list` response: a single live inspection session /// (typically corresponding to one inspector window in the host UI). -struct LKMCPBridgeTargetInfo: Sendable, Codable { +struct MCPBridgeTargetInfo: Sendable, Codable { /// Stable identifier for the duration of the inspection session. /// Derived from `InspectedAppInfo.appInfoIdentifier` (randomly generated per /// app launch and reused across reconnects to the same app instance). @@ -81,7 +81,7 @@ struct LKMCPBridgeTargetInfo: Sendable, Codable { /// and the immediate parent / child relationship. Per-attribute reads and /// screenshot URIs live in separate methods to be added in subsequent /// commits. -struct LKMCPBridgeViewNode: Sendable, Codable { +struct MCPBridgeViewNode: Sendable, Codable { /// Hex-encoded `InspectedObject.oid`, prefixed with `0x` (for example, /// `0x600000abc123`). Stable within a single connected app instance. let objectIdentifier: String @@ -98,7 +98,7 @@ struct LKMCPBridgeViewNode: Sendable, Codable { let nodeKind: String /// Frame in the root coordinate space (host calls this `frameToRoot`). - let frame: LKMCPBridgeRect + let frame: MCPBridgeRect /// `true` when the view is hidden via UIKit / AppKit visibility flags. let isHidden: Bool @@ -115,14 +115,14 @@ struct LKMCPBridgeViewNode: Sendable, Codable { /// Inlined child nodes when the request asked for a depth greater than /// one. `nil` means children were not expanded; an empty array means /// children were expanded and there are none. - let children: [LKMCPBridgeViewNode]? + let children: [MCPBridgeViewNode]? } // MARK: - AttributeGroup / Section / Attribute /// One attribute "card" in the host's inspector — a coherent bundle of /// related attributes (Frame, View, Layer, AutoLayout, UIControl, …). -struct LKMCPBridgeAttributeGroup: Sendable, Codable { +struct MCPBridgeAttributeGroup: Sendable, Codable { /// Group identifier (`LookinAttrGroupIdentifier`, e.g. `Layout`, /// `UIScrollView`, `NSWindow`), or the user-supplied title when the /// group originates from `lookin_customDebugInfos`. @@ -136,17 +136,17 @@ struct LKMCPBridgeAttributeGroup: Sendable, Codable { /// extension; agents can use this to flag paid-feature data origin. let isSwiftUIGroup: Bool - let sections: [LKMCPBridgeAttributeSection] + let sections: [MCPBridgeAttributeSection] } /// One sub-row inside an attribute group. -struct LKMCPBridgeAttributeSection: Sendable, Codable { +struct MCPBridgeAttributeSection: Sendable, Codable { let identifier: String - let attributes: [LKMCPBridgeAttribute] + let attributes: [MCPBridgeAttribute] } /// One inspected attribute value with a type-discriminating `kind`. -struct LKMCPBridgeAttribute: Sendable, Codable { +struct MCPBridgeAttribute: Sendable, Codable { /// `LookinAttrIdentifier` string (e.g. `BasicViewClass_Frame`, /// `BasicViewClass_Hidden`). Stable across LookinServer versions. let identifier: String @@ -158,7 +158,7 @@ struct LKMCPBridgeAttribute: Sendable, Codable { /// `true` when this attribute originates from `lookin_customDebugInfos`. let isUserCustom: Bool - /// Type discriminator for `value`. See `LKMCPBridgeAttributeEncoder` + /// Type discriminator for `value`. See `MCPBridgeAttributeEncoder` /// for the full kind → JSON-shape mapping. Common values: /// `integer`, `double`, `bool`, `string`, `selector`, `class`, /// `point`, `size`, `rect`, `edgeInsets`, `offset`, `transform`, @@ -170,12 +170,12 @@ struct LKMCPBridgeAttribute: Sendable, Codable { /// The encoded attribute value, shape-correlated with `kind`. `nil` /// when the source attribute carries no value (`LookinAttrTypeVoid` /// or genuinely empty optional fields). - let value: LKMCPBridgeJSONValue? + let value: MCPBridgeJSONValue? /// Auxiliary payload for select kinds. For `enum` types, this is the /// list of all enum case names the inspected object can hold (the /// host calls these `extraValue` on `InspectedAttribute`). - let extraValue: LKMCPBridgeJSONValue? + let extraValue: MCPBridgeJSONValue? /// Server-side identifier of a custom-attribute setter, present only /// when the host can write to this attribute through a registered @@ -192,7 +192,7 @@ struct LKMCPBridgeAttribute: Sendable, Codable { /// `InspectedObject.oid` and is NOT guaranteed to appear in a subsequent /// `hierarchy.read` (the hierarchy walks the view tree, not the server's /// general object registry). -struct LKMCPBridgeReturnedObject: Sendable, Codable { +struct MCPBridgeReturnedObject: Sendable, Codable { /// Hex-encoded `InspectedObject.oid` for the returned object, prefixed /// with `0x` (matches the form used everywhere else on the bridge). let objectIdentifier: String @@ -215,7 +215,7 @@ struct LKMCPBridgeReturnedObject: Sendable, Codable { /// callers can disambiguate "method returned `nil` / `0` / empty string" /// from "method returned void"; the two cases produce the same JSON /// `description: null` shape on most type-erased clients otherwise. -struct LKMCPBridgeInvocationResult: Sendable, Codable { +struct MCPBridgeInvocationResult: Sendable, Codable { /// Stringified return value. `nil` when the method returned `void` /// or when `secureContent` is `true`. For scalar (non-object, /// non-void) returns the server fills in a generic `"Method invoked."` @@ -232,10 +232,10 @@ struct LKMCPBridgeInvocationResult: Sendable, Codable { /// `oid` — matching the redaction philosophy of `attributes.read` /// (string-bearing attribute values get redacted; structural /// metadata does not). - let returnObject: LKMCPBridgeReturnedObject? + let returnObject: MCPBridgeReturnedObject? /// `true` when the receiver display item is treated as carrying - /// secure user content (see `LKMCPBridgeSecureContentDetector`). In + /// secure user content (see `MCPBridgeSecureContentDetector`). In /// that case `description` is redacted to `nil` to avoid leaking /// passwords / OTPs into agent transcripts. `returnObject` is kept; /// see its doc comment for the redaction rationale. @@ -246,14 +246,14 @@ struct LKMCPBridgeInvocationResult: Sendable, Codable { /// Wire envelope for an attribute value passed across the bridge in a /// modification context: `kind` is the same string the read-side -/// `LKMCPBridgeAttributeEncoder` produces, `data` is its corresponding +/// `MCPBridgeAttributeEncoder` produces, `data` is its corresponding /// JSON-friendly payload. The bridge consumes this in both directions: /// requests carry it as the value to apply; responses echo it as /// `requestedValue` so agents can compare against `effectiveAttribute` /// without having to reconstruct the wire form. -struct LKMCPBridgeAttributeValueWire: Sendable, Codable { +struct MCPBridgeAttributeValueWire: Sendable, Codable { let kind: String - let data: LKMCPBridgeJSONValue? + let data: MCPBridgeJSONValue? } /// Result envelope for `attribute.modify`. Echoes the requested value, @@ -261,21 +261,21 @@ struct LKMCPBridgeAttributeValueWire: Sendable, Codable { /// host-visible side-effect snapshot (frame / bounds / hidden / alpha) /// that the server captures in `DisplayItemDetail` after the /// setter has run and a layout pass has completed. -struct LKMCPBridgeModificationResult: Sendable, Codable { +struct MCPBridgeModificationResult: Sendable, Codable { /// Echo of the attribute identifier the agent asked to modify. let attributeIdentifier: String /// Echo of the wire `value` payload the agent supplied. Lets the /// agent diff against `effectiveAttribute.value` without re-deriving /// the wire shape from the encoded result. - let requestedValue: LKMCPBridgeAttributeValueWire + let requestedValue: MCPBridgeAttributeValueWire /// Fully-encoded attribute as the host saw it AFTER the setter ran /// and a layout pass settled. May differ from the request (autolayout /// adjusts frames; some setters round to pixel boundaries; some /// setters are no-ops). When `secureContent` is `true` the value /// here is redacted in the same way `read_attributes` redacts. - let effectiveAttribute: LKMCPBridgeAttribute + let effectiveAttribute: MCPBridgeAttribute /// `true` when the effective wire value is structurally equal to /// the requested wire value. Strict equality — no float epsilon. @@ -286,10 +286,10 @@ struct LKMCPBridgeModificationResult: Sendable, Codable { /// Post-modification frame snapshot. Often differs from the previous /// `get_hierarchy` result when the modification touched layout. - let frame: LKMCPBridgeRect + let frame: MCPBridgeRect /// Post-modification bounds snapshot. - let bounds: LKMCPBridgeRect + let bounds: MCPBridgeRect /// Post-modification `isHidden` snapshot. let isHidden: Bool @@ -309,9 +309,9 @@ struct LKMCPBridgeModificationResult: Sendable, Codable { /// already consume `attributes.read` can reuse their `groups` parsing /// code unchanged. The `secureContent` flag is per-item because a /// single batch may contain both regular and secure-input views. -struct LKMCPBridgeViewDetail: Sendable, Codable { +struct MCPBridgeViewDetail: Sendable, Codable { let objectIdentifier: String - let groups: [LKMCPBridgeAttributeGroup] + let groups: [MCPBridgeAttributeGroup] let secureContent: Bool } @@ -320,8 +320,8 @@ struct LKMCPBridgeViewDetail: Sendable, Codable { /// hierarchy or returned `failureCode = -1` from the server fall /// into `failedIdentifiers` — the call as a whole still succeeds so /// agents can act on whatever did come back. -struct LKMCPBridgeDetailsReadResult: Sendable, Codable { - let details: [LKMCPBridgeViewDetail] +struct MCPBridgeDetailsReadResult: Sendable, Codable { + let details: [MCPBridgeViewDetail] let failedIdentifiers: [String] } @@ -331,7 +331,7 @@ struct LKMCPBridgeDetailsReadResult: Sendable, Codable { /// base64 rather than as a URI: the bridge has no static file server, /// and the consuming MCP shim needs the bytes anyway to build an image /// content block. -struct LKMCPBridgeScreenshotResult: Sendable, Codable { +struct MCPBridgeScreenshotResult: Sendable, Codable { /// The object actually captured. Differs from the request when the /// caller omitted `objectIdentifier` and the service resolved the /// key window on their behalf. @@ -365,7 +365,7 @@ struct LKMCPBridgeScreenshotResult: Sendable, Codable { /// Frame of the captured view in the hierarchy's root coordinate /// space, in points. Lets an agent map pixel coordinates in the /// image back onto the coordinates `hierarchy.read` reports. - let frame: LKMCPBridgeRect + let frame: MCPBridgeRect /// `true` when the image came from the host's existing cache rather /// than a fresh render in the target app. Cached images can lag @@ -390,7 +390,7 @@ struct LKMCPBridgeScreenshotResult: Sendable, Codable { /// `hierarchy.read`: the identifier for subsequent calls, the ancestor /// chain for orientation, and the fields that matched so the caller can /// tell a class-name hit apart from an incidental substring in a subtitle. -struct LKMCPBridgeSearchMatch: Sendable, Codable { +struct MCPBridgeSearchMatch: Sendable, Codable { let objectIdentifier: String /// Leaf Objective-C class name, matching `hierarchy.read`'s field of @@ -406,7 +406,7 @@ struct LKMCPBridgeSearchMatch: Sendable, Codable { let subtitle: String? /// Frame in the hierarchy's root coordinate space, in points. - let frame: LKMCPBridgeRect + let frame: MCPBridgeRect let isHidden: Bool let alpha: Double @@ -439,8 +439,8 @@ struct LKMCPBridgeSearchMatch: Sendable, Codable { /// `totalMatchCount` counts every hit in the searched scope, so a caller /// that receives `truncated: true` knows how much it is not seeing and /// can narrow the query rather than paginate blindly. -struct LKMCPBridgeSearchResult: Sendable, Codable { - let matches: [LKMCPBridgeSearchMatch] +struct MCPBridgeSearchResult: Sendable, Codable { + let matches: [MCPBridgeSearchMatch] /// Hits found before `limit` was applied. let totalMatchCount: Int @@ -463,7 +463,7 @@ struct LKMCPBridgeSearchResult: Sendable, Codable { /// The server walks the entire class chain up to `NSObject`, so /// `totalCount` on a UIKit / AppKit view runs into four digits. Callers /// are expected to narrow with `nameFilter` rather than raise `limit`. -struct LKMCPBridgeSelectorListResult: Sendable, Codable { +struct MCPBridgeSelectorListResult: Sendable, Codable { /// The class actually queried. Differs from the request when the /// caller passed `objectIdentifier` and the service resolved the leaf /// class on their behalf. @@ -500,7 +500,7 @@ struct LKMCPBridgeSelectorListResult: Sendable, Codable { /// to tell a refresh that found a whole new screen from one that found the /// same screen it already had. Reporting both counts answers that without a /// follow-up `hierarchy.read`. -struct LKMCPBridgeRefreshResult: Sendable, Codable { +struct MCPBridgeRefreshResult: Sendable, Codable { /// Echo of the requested target. let targetIdentifier: String diff --git a/LookInside/MCPBridge/LKMCPBridgeAttributeEncoder.swift b/LookInside/MCPBridge/MCPBridgeAttributeEncoder.swift similarity index 88% rename from LookInside/MCPBridge/LKMCPBridgeAttributeEncoder.swift rename to LookInside/MCPBridge/MCPBridgeAttributeEncoder.swift index 17518192..4496ab53 100644 --- a/LookInside/MCPBridge/LKMCPBridgeAttributeEncoder.swift +++ b/LookInside/MCPBridge/MCPBridgeAttributeEncoder.swift @@ -1,7 +1,7 @@ -// LKMCPBridgeAttributeEncoder.swift +// MCPBridgeAttributeEncoder.swift // // Encodes a host-side `InspectedAttribute` into the wire DTO -// `LKMCPBridgeAttribute` for the `attributes.read` MCPBridge method. +// `MCPBridgeAttribute` for the `attributes.read` MCPBridge method. // // The host represents an attribute's payload as a polymorphic `id value` // disambiguated by `LookinAttrType`. The wire format flattens that into a @@ -21,7 +21,7 @@ import Foundation import AppKit #endif -enum LKMCPBridgeAttributeEncoder { +enum MCPBridgeAttributeEncoder { /// Encodes one host-side `InspectedAttribute` into the wire DTO. /// /// - Parameter redactingSecureContent: when `true`, string-valued kinds @@ -30,19 +30,19 @@ enum LKMCPBridgeAttributeEncoder { /// leaves this encoder. Geometry / numeric / color projections are /// not affected — they cannot reveal secret user content. The flag is /// evaluated once per display item by the caller (see - /// `LKMCPBridgeSecureContentDetector`) and applies uniformly to every + /// `MCPBridgeSecureContentDetector`) and applies uniformly to every /// attribute carried by that item, so a secure text field never leaks /// either its `text`, its `placeholder`, or any custom-attribute /// string the host might collect via `lookin_customDebugInfos`. static func encode( _ attribute: InspectedAttribute, redactingSecureContent: Bool - ) -> LKMCPBridgeAttribute { + ) -> MCPBridgeAttribute { let projection = projectValue(of: attribute) let finalProjection = redactingSecureContent ? redactedIfString(projection) : projection - return LKMCPBridgeAttribute( + return MCPBridgeAttribute( identifier: attribute.identifier ?? "", displayTitle: attribute.displayTitle, isUserCustom: attribute.isUserCustom(), @@ -78,7 +78,7 @@ enum LKMCPBridgeAttributeEncoder { private struct Projection { let kind: String - let value: LKMCPBridgeJSONValue? + let value: MCPBridgeJSONValue? } private static func projectValue(of attribute: InspectedAttribute) -> Projection { @@ -165,7 +165,7 @@ enum LKMCPBridgeAttributeEncoder { // MARK: - extraValue - private static func encodeExtraValue(_ attribute: InspectedAttribute) -> LKMCPBridgeJSONValue? { + private static func encodeExtraValue(_ attribute: InspectedAttribute) -> MCPBridgeJSONValue? { guard let extra = attribute.extraValue else { return nil } // For LookinAttrTypeEnumString, `extraValue` is the array of all // possible enum case names — surface it directly. Other attribute @@ -173,24 +173,24 @@ enum LKMCPBridgeAttributeEncoder { // object through `encodeArbitraryJSON` which falls back to a // description-string if the type cannot be projected losslessly. if let strings = extra as? [String] { - return .array(strings.map(LKMCPBridgeJSONValue.string)) + return .array(strings.map(MCPBridgeJSONValue.string)) } return encodeArbitraryJSON(extra) } // MARK: - Number helpers - private static func encodeNumberAsInteger(_ raw: Any?) -> LKMCPBridgeJSONValue? { + private static func encodeNumberAsInteger(_ raw: Any?) -> MCPBridgeJSONValue? { guard let number = raw as? NSNumber else { return nil } return .integer(Int64(truncatingIfNeeded: number.int64Value)) } - private static func encodeNumberAsDouble(_ raw: Any?) -> LKMCPBridgeJSONValue? { + private static func encodeNumberAsDouble(_ raw: Any?) -> MCPBridgeJSONValue? { guard let number = raw as? NSNumber else { return nil } return .double(number.doubleValue) } - private static func encodeAsString(_ raw: Any?) -> LKMCPBridgeJSONValue? { + private static func encodeAsString(_ raw: Any?) -> MCPBridgeJSONValue? { guard let text = raw as? String else { return nil } return .string(text) } @@ -202,7 +202,7 @@ enum LKMCPBridgeAttributeEncoder { return number.doubleValue } - private static func encodePoint(_ raw: Any?) -> LKMCPBridgeJSONValue? { + private static func encodePoint(_ raw: Any?) -> MCPBridgeJSONValue? { guard let nsValue = raw as? NSValue else { return nil } var point = CGPoint.zero nsValue.getValue(&point, size: MemoryLayout.size) @@ -212,7 +212,7 @@ enum LKMCPBridgeAttributeEncoder { ]) } - private static func encodeVector(_ raw: Any?) -> LKMCPBridgeJSONValue? { + private static func encodeVector(_ raw: Any?) -> MCPBridgeJSONValue? { guard let nsValue = raw as? NSValue else { return nil } var vector = CGVector.zero nsValue.getValue(&vector, size: MemoryLayout.size) @@ -222,7 +222,7 @@ enum LKMCPBridgeAttributeEncoder { ]) } - private static func encodeSize(_ raw: Any?) -> LKMCPBridgeJSONValue? { + private static func encodeSize(_ raw: Any?) -> MCPBridgeJSONValue? { guard let nsValue = raw as? NSValue else { return nil } var size = CGSize.zero nsValue.getValue(&size, size: MemoryLayout.size) @@ -232,7 +232,7 @@ enum LKMCPBridgeAttributeEncoder { ]) } - private static func encodeRect(_ raw: Any?) -> LKMCPBridgeJSONValue? { + private static func encodeRect(_ raw: Any?) -> MCPBridgeJSONValue? { guard let nsValue = raw as? NSValue else { return nil } var rect = CGRect.zero nsValue.getValue(&rect, size: MemoryLayout.size) @@ -244,7 +244,7 @@ enum LKMCPBridgeAttributeEncoder { ]) } - private static func encodeAffineTransform(_ raw: Any?) -> LKMCPBridgeJSONValue? { + private static func encodeAffineTransform(_ raw: Any?) -> MCPBridgeJSONValue? { guard let nsValue = raw as? NSValue else { return nil } var transform = CGAffineTransform.identity nsValue.getValue(&transform, size: MemoryLayout.size) @@ -258,7 +258,7 @@ enum LKMCPBridgeAttributeEncoder { ]) } - private static func encodeEdgeInsets(_ raw: Any?) -> LKMCPBridgeJSONValue? { + private static func encodeEdgeInsets(_ raw: Any?) -> MCPBridgeJSONValue? { guard let nsValue = raw as? NSValue else { return nil } // UIKit's UIEdgeInsets and AppKit's NSEdgeInsets share the same // memory layout: top / left / bottom / right CGFloats. @@ -272,7 +272,7 @@ enum LKMCPBridgeAttributeEncoder { ]) } - private static func encodeOffset(_ raw: Any?) -> LKMCPBridgeJSONValue? { + private static func encodeOffset(_ raw: Any?) -> MCPBridgeJSONValue? { guard let nsValue = raw as? NSValue else { return nil } var offset: (CGFloat, CGFloat) = (0, 0) nsValue.getValue(&offset, size: MemoryLayout.size(ofValue: offset)) @@ -284,7 +284,7 @@ enum LKMCPBridgeAttributeEncoder { // MARK: - Color / Shadow - private static func encodeColor(_ raw: Any?) -> LKMCPBridgeJSONValue? { + private static func encodeColor(_ raw: Any?) -> MCPBridgeJSONValue? { // LookinServer encodes UIColor as @[NSNumber, NSNumber, NSNumber, NSNumber] // in RGBA, components in 0...1. Surface as a named-key object for // agent readability while still preserving the underlying numbers. @@ -299,12 +299,12 @@ enum LKMCPBridgeAttributeEncoder { ]) } - private static func encodeShadow(_ raw: Any?) -> LKMCPBridgeJSONValue? { + private static func encodeShadow(_ raw: Any?) -> MCPBridgeJSONValue? { // Server-side shape (LKS_CustomAttrGroupsMaker.m): NSDictionary with // keys offset (NSValue), opacity (NSNumber), radius // (NSNumber), color ([NSNumber] RGBA). guard let dictionary = raw as? [String: Any] else { return nil } - var encoded: [String: LKMCPBridgeJSONValue] = [:] + var encoded: [String: MCPBridgeJSONValue] = [:] if let offset = encodeSize(dictionary["offset"]) { encoded["offset"] = offset } @@ -322,7 +322,7 @@ enum LKMCPBridgeAttributeEncoder { // MARK: - Custom / JSON / fallback - private static func encodeArbitraryJSON(_ raw: Any?) -> LKMCPBridgeJSONValue? { + private static func encodeArbitraryJSON(_ raw: Any?) -> MCPBridgeJSONValue? { guard let raw else { return nil } // Try to round-trip through Foundation's JSONSerialization. This // handles dictionaries, arrays, NSNumber, NSString, NSNull cleanly @@ -330,7 +330,7 @@ enum LKMCPBridgeAttributeEncoder { if JSONSerialization.isValidJSONObject(raw) { do { let data = try JSONSerialization.data(withJSONObject: raw, options: [.fragmentsAllowed]) - return try JSONDecoder().decode(LKMCPBridgeJSONValue.self, from: data) + return try JSONDecoder().decode(MCPBridgeJSONValue.self, from: data) } catch { // Fall through to description fallback. } @@ -361,8 +361,8 @@ enum LKMCPBridgeAttributeEncoder { } } - private static func encodeConstraintEndpoint(_ endpointObject: InspectedObject?, itemType: LookinConstraintItemType) -> LKMCPBridgeJSONValue { - var fields: [String: LKMCPBridgeJSONValue] = [ + private static func encodeConstraintEndpoint(_ endpointObject: InspectedObject?, itemType: LookinConstraintItemType) -> MCPBridgeJSONValue { + var fields: [String: MCPBridgeJSONValue] = [ "itemType": .string(constraintItemTypeString(itemType)), ] if let endpointObject, endpointObject.oid != 0 { @@ -379,9 +379,9 @@ enum LKMCPBridgeAttributeEncoder { /// The attribute numbers stay raw NSInteger values: UIKit and AppKit /// assign different numbers to NSLayoutAttribute cases, and the bridge /// does not know which platform produced the data. - private static func encodeConstraints(_ constraints: [AutoLayoutConstraint]) -> LKMCPBridgeJSONValue { - let encodedConstraints: [LKMCPBridgeJSONValue] = constraints.map { constraint in - var fields: [String: LKMCPBridgeJSONValue] = [ + private static func encodeConstraints(_ constraints: [AutoLayoutConstraint]) -> MCPBridgeJSONValue { + let encodedConstraints: [MCPBridgeJSONValue] = constraints.map { constraint in + var fields: [String: MCPBridgeJSONValue] = [ "firstItem": encodeConstraintEndpoint(constraint.firstItem, itemType: constraint.firstItemType), "firstAttributeRawValue": .integer(Int64(constraint.firstAttribute)), "relation": .string(constraintRelationString(constraint.relation)), @@ -406,14 +406,16 @@ enum LKMCPBridgeAttributeEncoder { return .array(encodedConstraints) } - private static func encodeCustomObject(_ raw: Any?) -> LKMCPBridgeJSONValue? { + private static func encodeCustomObject(_ raw: Any?) -> MCPBridgeJSONValue? { // Custom objects don't have a fixed shape; surface their class name - // and a description so agents have something to render. Bridge + // and a description so agents have something to render. The class + // name is the Objective-C runtime name, which the LookinCore model + // classes kept when their Swift names lost the prefix. Bridge // consumers that need a typed projection should use the attribute // identifier to know what they're looking at. guard let raw else { return nil } let object = raw as AnyObject - let className = String(describing: type(of: object)) + let className = NSStringFromClass(type(of: object)) let descriptionText = String(describing: object) return .object([ "className": .string(className), @@ -421,7 +423,7 @@ enum LKMCPBridgeAttributeEncoder { ]) } - private static func encodeFallbackDescription(_ raw: Any?) -> LKMCPBridgeJSONValue? { + private static func encodeFallbackDescription(_ raw: Any?) -> MCPBridgeJSONValue? { guard let raw else { return nil } return .object([ "rawDescription": .string(String(describing: raw)), diff --git a/LookInside/MCPBridge/LKMCPBridgeAttributeValueDecoder.swift b/LookInside/MCPBridge/MCPBridgeAttributeValueDecoder.swift similarity index 95% rename from LookInside/MCPBridge/LKMCPBridgeAttributeValueDecoder.swift rename to LookInside/MCPBridge/MCPBridgeAttributeValueDecoder.swift index 147b9318..a0f8262c 100644 --- a/LookInside/MCPBridge/LKMCPBridgeAttributeValueDecoder.swift +++ b/LookInside/MCPBridge/MCPBridgeAttributeValueDecoder.swift @@ -1,6 +1,6 @@ -// LKMCPBridgeAttributeValueDecoder.swift +// MCPBridgeAttributeValueDecoder.swift // -// Symmetric inverse of LKMCPBridgeAttributeEncoder: turns the wire +// Symmetric inverse of MCPBridgeAttributeEncoder: turns the wire // `{ kind, data }` shape that a bridge client uses to express an // attribute write back into the polymorphic Objective-C value that // AttributeModification carries to the inspected server @@ -23,7 +23,7 @@ import CoreGraphics import Foundation @MainActor -enum LKMCPBridgeAttributeValueDecoder { +enum MCPBridgeAttributeValueDecoder { // MARK: - Errors enum DecodeError: Error { @@ -52,7 +52,7 @@ enum LKMCPBridgeAttributeValueDecoder { /// bridge error. static func decode( wireKind: String, - wireData: LKMCPBridgeJSONValue?, + wireData: MCPBridgeJSONValue?, expectedAttrType: LookinAttrType ) throws -> Any { switch wireKind { @@ -102,7 +102,7 @@ enum LKMCPBridgeAttributeValueDecoder { ] private static func decodeInteger( - _ data: LKMCPBridgeJSONValue?, + _ data: MCPBridgeJSONValue?, expectedAttrType: LookinAttrType ) throws -> Any { guard integerCompatibleTypes.contains(expectedAttrType) else { @@ -125,7 +125,7 @@ enum LKMCPBridgeAttributeValueDecoder { private static let doubleCompatibleTypes: Set = [.float, .double] private static func decodeDouble( - _ data: LKMCPBridgeJSONValue?, + _ data: MCPBridgeJSONValue?, expectedAttrType: LookinAttrType ) throws -> Any { guard doubleCompatibleTypes.contains(expectedAttrType) else { @@ -145,7 +145,7 @@ enum LKMCPBridgeAttributeValueDecoder { } private static func decodeBool( - _ data: LKMCPBridgeJSONValue?, + _ data: MCPBridgeJSONValue?, expectedAttrType: LookinAttrType ) throws -> Any { guard expectedAttrType == .BOOL else { @@ -160,7 +160,7 @@ enum LKMCPBridgeAttributeValueDecoder { // MARK: - String-ish kinds private static func decodeString( - _ data: LKMCPBridgeJSONValue?, + _ data: MCPBridgeJSONValue?, expectedAttrType: LookinAttrType, allowedTypes: Set ) throws -> Any { @@ -185,7 +185,7 @@ enum LKMCPBridgeAttributeValueDecoder { private static let enumNumericTypes: Set = [.enumInt, .enumLong] private static func decodeEnum( - _ data: LKMCPBridgeJSONValue?, + _ data: MCPBridgeJSONValue?, expectedAttrType: LookinAttrType ) throws -> Any { switch expectedAttrType { @@ -215,7 +215,7 @@ enum LKMCPBridgeAttributeValueDecoder { // MARK: - Geometry private static func decodePoint( - _ data: LKMCPBridgeJSONValue?, + _ data: MCPBridgeJSONValue?, expectedAttrType: LookinAttrType ) throws -> Any { guard expectedAttrType == .cgPoint else { @@ -228,7 +228,7 @@ enum LKMCPBridgeAttributeValueDecoder { } private static func decodeVector( - _ data: LKMCPBridgeJSONValue?, + _ data: MCPBridgeJSONValue?, expectedAttrType: LookinAttrType ) throws -> Any { guard expectedAttrType == .cgVector else { @@ -241,7 +241,7 @@ enum LKMCPBridgeAttributeValueDecoder { } private static func decodeSize( - _ data: LKMCPBridgeJSONValue?, + _ data: MCPBridgeJSONValue?, expectedAttrType: LookinAttrType ) throws -> Any { guard expectedAttrType == .cgSize else { @@ -254,7 +254,7 @@ enum LKMCPBridgeAttributeValueDecoder { } private static func decodeRect( - _ data: LKMCPBridgeJSONValue?, + _ data: MCPBridgeJSONValue?, expectedAttrType: LookinAttrType ) throws -> Any { guard expectedAttrType == .cgRect else { @@ -269,7 +269,7 @@ enum LKMCPBridgeAttributeValueDecoder { } private static func decodeAffineTransform( - _ data: LKMCPBridgeJSONValue?, + _ data: MCPBridgeJSONValue?, expectedAttrType: LookinAttrType ) throws -> Any { guard expectedAttrType == .cgAffineTransform else { @@ -287,7 +287,7 @@ enum LKMCPBridgeAttributeValueDecoder { } private static func decodeEdgeInsets( - _ data: LKMCPBridgeJSONValue?, + _ data: MCPBridgeJSONValue?, expectedAttrType: LookinAttrType ) throws -> Any { guard expectedAttrType == .uiEdgeInsets else { @@ -309,7 +309,7 @@ enum LKMCPBridgeAttributeValueDecoder { } private static func decodeOffset( - _ data: LKMCPBridgeJSONValue?, + _ data: MCPBridgeJSONValue?, expectedAttrType: LookinAttrType ) throws -> Any { guard expectedAttrType == .uiOffset else { @@ -328,7 +328,7 @@ enum LKMCPBridgeAttributeValueDecoder { // MARK: - Color private static func decodeColor( - _ data: LKMCPBridgeJSONValue?, + _ data: MCPBridgeJSONValue?, expectedAttrType: LookinAttrType ) throws -> Any { guard expectedAttrType == .uiColor else { @@ -353,9 +353,9 @@ enum LKMCPBridgeAttributeValueDecoder { // MARK: - Helpers private static func requireObject( - _ data: LKMCPBridgeJSONValue?, + _ data: MCPBridgeJSONValue?, fieldName: String - ) throws -> [String: LKMCPBridgeJSONValue] { + ) throws -> [String: MCPBridgeJSONValue] { guard case let .object(object)? = data else { throw DecodeError.shapeInvalid(reason: "\(fieldName) expects a JSON object") } @@ -363,7 +363,7 @@ enum LKMCPBridgeAttributeValueDecoder { } private static func requireDouble( - _ data: LKMCPBridgeJSONValue?, + _ data: MCPBridgeJSONValue?, fieldName: String ) throws -> Double { guard let data else { diff --git a/LookInside/MCPBridge/LKMCPBridgeConnection.swift b/LookInside/MCPBridge/MCPBridgeConnection.swift similarity index 90% rename from LookInside/MCPBridge/LKMCPBridgeConnection.swift rename to LookInside/MCPBridge/MCPBridgeConnection.swift index e8a772b4..ff1e740c 100644 --- a/LookInside/MCPBridge/LKMCPBridgeConnection.swift +++ b/LookInside/MCPBridge/MCPBridgeConnection.swift @@ -1,11 +1,11 @@ -// LKMCPBridgeConnection.swift +// MCPBridgeConnection.swift // // Per-client connection handler for the MCPBridge Unix domain socket. // -// Each accepted connection becomes one `LKMCPBridgeConnection` instance that +// Each accepted connection becomes one `MCPBridgeConnection` instance that // reads newline-delimited JSON frames from its socket, decodes them as -// `LKMCPBridgeRequest`, dispatches via a request handler closure, and writes -// the resulting `LKMCPBridgeResponse` (or pushed `LKMCPBridgeEvent`) back. +// `MCPBridgeRequest`, dispatches via a request handler closure, and writes +// the resulting `MCPBridgeResponse` (or pushed `MCPBridgeEvent`) back. // // Buffering is line-oriented: bytes accumulate in a buffer until a `\n` // separator is found; partial frames are tolerated across read events but @@ -27,8 +27,8 @@ import Dispatch import Foundation import os -final class LKMCPBridgeConnection { - typealias RequestHandler = @Sendable (LKMCPBridgeRequest) async -> LKMCPBridgeResponse +final class MCPBridgeConnection { + typealias RequestHandler = @Sendable (MCPBridgeRequest) async -> MCPBridgeResponse /// Maximum accumulated bytes for a single frame before the connection is /// torn down. Inspection responses can carry large screenshot data so the @@ -40,7 +40,7 @@ final class LKMCPBridgeConnection { private let fileDescriptor: Int32 private let connectionQueue: DispatchQueue private let requestHandler: RequestHandler - private let onClose: @Sendable (LKMCPBridgeConnection) -> Void + private let onClose: @Sendable (MCPBridgeConnection) -> Void /// All three are `connectionQueue`-confined; never touch them from /// another thread. @@ -52,7 +52,7 @@ final class LKMCPBridgeConnection { fileDescriptor: Int32, queue: DispatchQueue, requestHandler: @escaping RequestHandler, - onClose: @escaping @Sendable (LKMCPBridgeConnection) -> Void + onClose: @escaping @Sendable (MCPBridgeConnection) -> Void ) { self.fileDescriptor = fileDescriptor connectionQueue = DispatchQueue( @@ -88,7 +88,7 @@ final class LKMCPBridgeConnection { // Strong capture on purpose. This block is what cancels the read // source and closes the socket, so it must still run when the caller // drops its reference first -- which is exactly what - // `LKMCPBridgeServer.stop()` does when it clears `openConnections`. + // `MCPBridgeServer.stop()` does when it clears `openConnections`. // Captured weakly, shutdown would leak the descriptor and leave a // live read source firing on a connection nobody owns. connectionQueue.async { @@ -150,7 +150,7 @@ final class LKMCPBridgeConnection { private func dispatchFrame(_ frameData: Data) { do { - let request = try JSONDecoder().decode(LKMCPBridgeRequest.self, from: frameData) + let request = try JSONDecoder().decode(MCPBridgeRequest.self, from: frameData) Task { [weak self] in guard let self else { return } let response = await self.requestHandler(request) @@ -160,7 +160,7 @@ final class LKMCPBridgeConnection { Self.logger.error("Failed to decode inbound frame as request: \(error.localizedDescription, privacy: .public)") // No identifier available — push a generic error event so the peer // can observe the malformed frame without correlating to a request. - let event = LKMCPBridgeEvent( + let event = MCPBridgeEvent( topic: "frame.decodeError", payload: ["message": .string(error.localizedDescription)] ) @@ -170,11 +170,11 @@ final class LKMCPBridgeConnection { // MARK: - Write path - func send(response: LKMCPBridgeResponse) { + func send(response: MCPBridgeResponse) { sendCodable(response) } - func send(event: LKMCPBridgeEvent) { + func send(event: MCPBridgeEvent) { sendCodable(event) } @@ -212,7 +212,7 @@ final class LKMCPBridgeConnection { } if errorNumber == EAGAIN || errorNumber == EWOULDBLOCK { // Unreachable while the descriptor is blocking, which - // `LKMCPBridgeListenSocket.acceptConnection` guarantees -- + // `MCPBridgeListenSocket.acceptConnection` guarantees -- // and that guarantee is load-bearing: on macOS accept(2) // inherits O_NONBLOCK from the (necessarily non-blocking) // listener, and a non-blocking descriptor lands here diff --git a/LookInside/MCPBridge/LKMCPBridgeDetailsService.swift b/LookInside/MCPBridge/MCPBridgeDetailsService.swift similarity index 87% rename from LookInside/MCPBridge/LKMCPBridgeDetailsService.swift rename to LookInside/MCPBridge/MCPBridgeDetailsService.swift index 1dc07e53..1b0c0db4 100644 --- a/LookInside/MCPBridge/LKMCPBridgeDetailsService.swift +++ b/LookInside/MCPBridge/MCPBridgeDetailsService.swift @@ -1,4 +1,4 @@ -// LKMCPBridgeDetailsService.swift +// MCPBridgeDetailsService.swift // // Handles the `details.read` bridge route: actively triggers RPC 203 // `HierarchyDetails` for a batch of object identifiers and returns @@ -14,7 +14,7 @@ // full streamed response (one frame per server-side task package), // and surfaces every successful view's detail. The same routing // also writes the response through -// `LKStaticHierarchyDataSource.modifyWithDisplayItemDetail:` so +// `StaticHierarchyDataSource.modifyWithDisplayItemDetail:` so // subsequent `attributes.read` calls see populated cache and the // inspector UI reflects the new state. // @@ -30,9 +30,9 @@ import Foundation import os @MainActor -final class LKMCPBridgeDetailsService { +final class MCPBridgeDetailsService { /// Hard cap on per-call batch size. Matches the host inspector's - /// own `packageMaxTasksCount` (see `LKStaticAsyncUpdateManager`). + /// own `packageMaxTasksCount` (see `StaticAsyncUpdateManager`). /// Larger batches are rejected at the wire boundary; agents that /// need more issue multiple calls. private static let maximumObjectIdentifiersPerCall = 100 @@ -43,7 +43,7 @@ final class LKMCPBridgeDetailsService { // MARK: - Entry point - func handle(request: LKMCPBridgeRequest) async -> LKMCPBridgeResponse { + func handle(request: MCPBridgeRequest) async -> MCPBridgeResponse { guard request.method == "details.read" else { return .failure(identifier: request.identifier, error: .unknownMethod) } @@ -57,8 +57,8 @@ final class LKMCPBridgeDetailsService { private func handleDetailsRead( identifier: String, - parameters: [String: LKMCPBridgeJSONValue]? - ) async -> LKMCPBridgeResponse { + parameters: [String: MCPBridgeJSONValue]? + ) async -> MCPBridgeResponse { // Parameter extraction guard let parameters, case let .string(targetIdentifier)? = parameters["targetIdentifier"], @@ -73,7 +73,7 @@ final class LKMCPBridgeDetailsService { // the oid-keyed index built below traps on a duplicate key, which // would take down the whole host app rather than fail this request. let requestedIdentifiers: [String] - switch LKMCPBridgeObjectIdentifierList.parse( + switch MCPBridgeObjectIdentifierList.parse( wireValues: identifierWireValues, limit: Self.maximumObjectIdentifiersPerCall ) { @@ -89,7 +89,7 @@ final class LKMCPBridgeDetailsService { case let .failure(.tooMany(distinctCount, limit)): return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "dispatch.tooMany", message: "details.read accepts at most \(limit) object identifiers per call; received \(distinctCount) distinct. Split into multiple calls." ) @@ -104,10 +104,10 @@ final class LKMCPBridgeDetailsService { } // Live-document lookup - guard let document = LKMCPBridgeLiveDocumentLookup.findLiveDocument(targetIdentifier: targetIdentifier) else { + guard let document = MCPBridgeLiveDocumentLookup.findLiveDocument(targetIdentifier: targetIdentifier) else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "hierarchy.targetNotFound", message: "No live inspection document found for target identifier \(targetIdentifier)." ) @@ -117,7 +117,7 @@ final class LKMCPBridgeDetailsService { guard document.hierarchyDataSource != nil else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "hierarchy.notReady", message: "Live document has not loaded a hierarchy yet." ) @@ -128,13 +128,13 @@ final class LKMCPBridgeDetailsService { // identifiers go into failedIdentifiers and skip the server // round-trip; the agent learns which oids vanished without the // request blowing up entirely. - let roots = LKMCPBridgeLiveDocumentLookup.topLevelDisplayItems(in: document) + let roots = MCPBridgeLiveDocumentLookup.topLevelDisplayItems(in: document) var resolvedItems: [(identifier: String, displayItem: DisplayItem, nativeOid: UInt)] = [] resolvedItems.reserveCapacity(requestedIdentifiers.count) var failedIdentifiers: [String] = [] for requested in requestedIdentifiers { - guard let displayItem = LKMCPBridgeLiveDocumentLookup.findDisplayItem( + guard let displayItem = MCPBridgeLiveDocumentLookup.findDisplayItem( amongRoots: roots, matchingObjectIdentifier: requested ), @@ -152,7 +152,7 @@ final class LKMCPBridgeDetailsService { if resolvedItems.isEmpty { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "details.objectNotFound", message: "None of the requested object identifiers are present in this target's hierarchy. Refresh the hierarchy via get_hierarchy and retry." ) @@ -162,7 +162,7 @@ final class LKMCPBridgeDetailsService { // Build the RPC 203 task package. Single package — we already // cap the batch at 100 entries, so the host inspector's own // pixel/count packing thresholds never need to come into play. - let clientReadableVersion = LKHelper.lookinReadableVersion() + let clientReadableVersion = AppHelper.lookinReadableVersion() let tasks = resolvedItems.map { resolved -> StaticAsyncUpdateTask in let task = StaticAsyncUpdateTask() task.oid = resolved.nativeOid @@ -213,7 +213,7 @@ final class LKMCPBridgeDetailsService { // to its owning document. let staticDataSource = document.hierarchyDataSource - var emittedDetails: [LKMCPBridgeViewDetail] = [] + var emittedDetails: [MCPBridgeViewDetail] = [] emittedDetails.reserveCapacity(allDetails.count) var seenOids: Set = [] @@ -244,7 +244,7 @@ final class LKMCPBridgeDetailsService { // Encode the attribute groups carried in this detail // through the read-side encoder so the wire shape matches // attributes.read. - let redactSecureContent = LKMCPBridgeSecureContentDetector.isSecure(displayItem: resolved.displayItem) + let redactSecureContent = MCPBridgeSecureContentDetector.isSecure(displayItem: resolved.displayItem) var rawGroups: [AttributesGroup] = [] if let inbuiltGroups = detail.attributesGroupList { rawGroups.append(contentsOf: inbuiltGroups) @@ -252,21 +252,21 @@ final class LKMCPBridgeDetailsService { if includeUserCustom, let customGroups = detail.customAttrGroupList { rawGroups.append(contentsOf: customGroups) } - let encodedGroups = rawGroups.map { group -> LKMCPBridgeAttributeGroup in - let sections = (group.attrSections ?? []).map { section -> LKMCPBridgeAttributeSection in + let encodedGroups = rawGroups.map { group -> MCPBridgeAttributeGroup in + let sections = (group.attrSections ?? []).map { section -> MCPBridgeAttributeSection in let attributes = (section.attributes ?? []).map { attribute in - LKMCPBridgeAttributeEncoder.encode( + MCPBridgeAttributeEncoder.encode( attribute, redactingSecureContent: redactSecureContent ) } - return LKMCPBridgeAttributeSection( + return MCPBridgeAttributeSection( identifier: section.identifier ?? "", attributes: attributes ) } let groupIdentifier = group.userCustomTitle ?? group.identifier ?? "" - return LKMCPBridgeAttributeGroup( + return MCPBridgeAttributeGroup( identifier: groupIdentifier, isUserCustom: group.userCustomTitle != nil, isSwiftUIGroup: group.isSwiftUIGroup, @@ -274,7 +274,7 @@ final class LKMCPBridgeDetailsService { ) } - emittedDetails.append(LKMCPBridgeViewDetail( + emittedDetails.append(MCPBridgeViewDetail( objectIdentifier: resolved.identifier, groups: encodedGroups, secureContent: redactSecureContent @@ -299,10 +299,10 @@ final class LKMCPBridgeDetailsService { private func successResponse( identifier: String, - details: [LKMCPBridgeViewDetail], + details: [MCPBridgeViewDetail], failedIdentifiers: [String] - ) -> LKMCPBridgeResponse { - let result = LKMCPBridgeDetailsReadResult( + ) -> MCPBridgeResponse { + let result = MCPBridgeDetailsReadResult( details: details, failedIdentifiers: failedIdentifiers ) @@ -315,41 +315,41 @@ final class LKMCPBridgeDetailsService { } } - private func mapDetailsError(_ error: NSError) -> LKMCPBridgeErrorPayload { + private func mapDetailsError(_ error: NSError) -> MCPBridgeErrorPayload { switch error.code { case LookinErrCode_ObjectNotFound: - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "details.objectNotFound", message: "The target app could not find one or more of the requested objects. They may have been deallocated; refresh via get_hierarchy and retry." ) case LookinErrCode_Inner: - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "details.internalError", message: "The target app rejected the details request with a generic inner error." ) case LookinErrCode_LicenseRequired: return .licenseRequired case LookinErrCode_NoConnect: - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "details.disconnected", message: "The target app is no longer connected. Re-attach from the LookInside inspector and try again." ) case LookinErrCode_Timeout: - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "details.timeout", message: "The target app did not respond within the request timeout. Reduce the batch size or check whether the target is paused in Xcode." ) default: Self.logger.error("details.read received unmapped error code \(error.code, privacy: .public): \(error.localizedDescription, privacy: .public)") - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "details.internalError", message: "The target app reported an unexpected error (code \(error.code))." ) } } - private func encodeAsJSONValue(_ value: some Encodable) throws -> LKMCPBridgeJSONValue { + private func encodeAsJSONValue(_ value: some Encodable) throws -> MCPBridgeJSONValue { let data = try JSONEncoder().encode(value) - return try JSONDecoder().decode(LKMCPBridgeJSONValue.self, from: data) + return try JSONDecoder().decode(MCPBridgeJSONValue.self, from: data) } } diff --git a/LookInside/MCPBridge/LKMCPBridgeEventPublisher.swift b/LookInside/MCPBridge/MCPBridgeEventPublisher.swift similarity index 81% rename from LookInside/MCPBridge/LKMCPBridgeEventPublisher.swift rename to LookInside/MCPBridge/MCPBridgeEventPublisher.swift index c844f067..c489ca9c 100644 --- a/LookInside/MCPBridge/LKMCPBridgeEventPublisher.swift +++ b/LookInside/MCPBridge/MCPBridgeEventPublisher.swift @@ -1,7 +1,7 @@ -// LKMCPBridgeEventPublisher.swift +// MCPBridgeEventPublisher.swift // -// Turns host-side state changes into `LKMCPBridgeEvent` frames and hands -// them to `LKMCPBridgeServer.broadcast(event:)`. +// Turns host-side state changes into `MCPBridgeEvent` frames and hands +// them to `MCPBridgeServer.broadcast(event:)`. // // What belongs here, and what deliberately does not: // @@ -13,7 +13,7 @@ // That rules out the data source's three item-change signals // (`itemDidChangeAttrGroup`, `itemDidChangeHiddenAlphaValue`, // `itemsDidChangeFrame`). All three fire only from inside -// `LKStaticHierarchyDataSource.modify(with:)`, which is +// `StaticHierarchyDataSource.modify(with:)`, which is // the moment fetched detail lands in the cache -- and the fetch was // almost always the caller's own `details.read` / `screenshot.read` / // `attribute.modify`. Publishing them would tell a client "something @@ -42,12 +42,12 @@ import Foundation import os @MainActor -final class LKMCPBridgeEventPublisher { +final class MCPBridgeEventPublisher { private static let logger = Logger(subsystem: "com.lookinside.app", category: "MCPBridge.Events") /// Where finished events go. Injected rather than reaching for the /// server singleton so this type can be exercised without a socket. - private let broadcast: @MainActor (LKMCPBridgeEvent) -> Void + private let broadcast: @MainActor (MCPBridgeEvent) -> Void /// The channel-end and push listeners; they live as long as the /// publisher runs. @@ -56,11 +56,11 @@ final class LKMCPBridgeEventPublisher { /// One reload subscription per open live document. Documents come and /// go, so these are attached on open and cancelled on close; a stale one /// would keep publishing reloads for a window nobody can see. - private var documentSubscriptions: [ObjectIdentifier: LKSyncSubscription] = [:] + private var documentSubscriptions: [ObjectIdentifier: SyncSubscription] = [:] private var hasStarted = false - init(broadcast: @escaping @MainActor (LKMCPBridgeEvent) -> Void) { + init(broadcast: @escaping @MainActor (MCPBridgeEvent) -> Void) { self.broadcast = broadcast } @@ -79,7 +79,7 @@ final class LKMCPBridgeEventPublisher { // Documents can already exist: a document opened by an auto-connect // environment variable races the bridge's start. Adopt whatever is // already open rather than only ever seeing the next one. - for document in LKMCPBridgeLiveDocumentLookup.enumerateLiveDocuments() { + for document in MCPBridgeLiveDocumentLookup.enumerateLiveDocuments() { attachReloadSubscription(to: document) } } @@ -104,26 +104,26 @@ final class LKMCPBridgeEventPublisher { NotificationCenter.default.addObserver( self, selector: #selector(handleDocumentDidOpen(_:)), - name: LookinLiveDocument.didOpenNotification, + name: LiveDocument.didOpenNotification, object: nil ) NotificationCenter.default.addObserver( self, selector: #selector(handleDocumentWillClose(_:)), - name: LookinLiveDocument.willCloseNotification, + name: LiveDocument.willCloseNotification, object: nil ) } @objc private func handleDocumentDidOpen(_ notification: Notification) { - guard let document = notification.object as? LookinLiveDocument else { return } + guard let document = notification.object as? LiveDocument else { return } attachReloadSubscription(to: document) // Carries the whole target record rather than just an identifier: // a client that learns a target appeared will immediately want to // know what it is, and the round-trip back to `targets.list` buys // nothing the host does not already have in hand. broadcast( - LKMCPBridgeEvent( + MCPBridgeEvent( topic: "targets.attached", payload: targetPayload(for: document) ) @@ -131,10 +131,10 @@ final class LKMCPBridgeEventPublisher { } @objc private func handleDocumentWillClose(_ notification: Notification) { - guard let document = notification.object as? LookinLiveDocument else { return } + guard let document = notification.object as? LiveDocument else { return } detachReloadSubscription(from: document) broadcast( - LKMCPBridgeEvent( + MCPBridgeEvent( topic: "targets.detached", payload: targetPayload(for: document) ) @@ -143,7 +143,7 @@ final class LKMCPBridgeEventPublisher { // MARK: - Per-document reload subscription - private func attachReloadSubscription(to document: LookinLiveDocument) { + private func attachReloadSubscription(to document: LiveDocument) { let key = ObjectIdentifier(document) guard documentSubscriptions[key] == nil else { return } guard let dataSource = document.hierarchyDataSource else { return } @@ -161,11 +161,11 @@ final class LKMCPBridgeEventPublisher { } } - private func detachReloadSubscription(from document: LookinLiveDocument) { + private func detachReloadSubscription(from document: LiveDocument) { documentSubscriptions.removeValue(forKey: ObjectIdentifier(document))?.cancel() } - private func publishHierarchyReloaded(for document: LookinLiveDocument) { + private func publishHierarchyReloaded(for document: LiveDocument) { var payload = targetPayload(for: document) payload["nodeCount"] = .integer(Int64(document.hierarchyDataSource?.rawFlatItems?.count ?? 0)) // `agent` means "a bridge client asked for this", so a client that @@ -173,13 +173,13 @@ final class LKMCPBridgeEventPublisher { // `host` is news. let initiator = document.staticWindowController?.lastReloadInitiator ?? .host payload["initiator"] = .string(initiator == .agent ? "agent" : "host") - broadcast(LKMCPBridgeEvent(topic: "hierarchy.reloaded", payload: payload)) + broadcast(MCPBridgeEvent(topic: "hierarchy.reloaded", payload: payload)) } // MARK: - Connection manager private func subscribeToConnectionManager() { - let connectionManager = LKConnectionManager.shared + let connectionManager = ConnectionManager.shared // A channel ending is the one thing here that is genuinely about // the target app rather than the host: the app was killed, the USB @@ -203,28 +203,28 @@ final class LKMCPBridgeEventPublisher { /// Resolves a channel back to the document that owns it, so an event can /// name a target identifier the client already knows rather than an /// opaque channel the bridge protocol never exposes. - private func document(forChannel channel: LKChannel) -> LookinLiveDocument? { - LookinLiveDocumentController.shared.liveDocument(for: channel) + private func document(forChannel channel: ServerChannel) -> LiveDocument? { + LiveDocumentController.shared.liveDocument(for: channel) } - private func publishDisconnected(channel: LKChannel) { + private func publishDisconnected(channel: ServerChannel) { guard let document = document(forChannel: channel) else { return } broadcast( - LKMCPBridgeEvent( + MCPBridgeEvent( topic: "targets.disconnected", payload: targetPayload(for: document) ) ) } - private func handleServerPush(_ push: LKConnectionPush) { + private func handleServerPush(_ push: ConnectionPush) { guard push.type == UInt32(LookinPush_SwiftUISupportDetected) else { return } - var payload: [String: LKMCPBridgeJSONValue] = [:] + var payload: [String: MCPBridgeJSONValue] = [:] if let document = document(forChannel: push.channel) { payload = targetPayload(for: document) } payload["capability"] = .string("swiftUI") - broadcast(LKMCPBridgeEvent(topic: "capabilities.swiftUIDetected", payload: payload)) + broadcast(MCPBridgeEvent(topic: "capabilities.swiftUIDetected", payload: payload)) } // MARK: - Activation state @@ -233,7 +233,7 @@ final class LKMCPBridgeEventPublisher { NotificationCenter.default.addObserver( self, selector: #selector(handleActivationStateDidChange(_:)), - name: LKSwiftUISupportGatekeeper.activationStateDidChangeNotification, + name: SwiftUISupportGatekeeper.activationStateDidChangeNotification, object: nil ) } @@ -241,16 +241,16 @@ final class LKMCPBridgeEventPublisher { @objc private func handleActivationStateDidChange(_: Notification) { // Read silently: asking for protected-feature access would put an // activation window on screen, which an event handler must never do. - let state = LKSwiftUISupportGatekeeper.sharedInstance().activationState + let state = SwiftUISupportGatekeeper.sharedInstance().activationState broadcast( - LKMCPBridgeEvent( + MCPBridgeEvent( topic: "license.stateChanged", payload: ["state": .string(Self.wireName(for: state))] ) ) } - private static func wireName(for state: LKSwiftUISupportActivationState) -> String { + private static func wireName(for state: SwiftUISupportActivationState) -> String { switch state { case .activated: "activated" @@ -266,8 +266,8 @@ final class LKMCPBridgeEventPublisher { /// The same target description `targets.list` returns, minus the /// fields that require a round-trip. Kept in one place so every topic /// names a target the same way. - private func targetPayload(for document: LookinLiveDocument) -> [String: LKMCPBridgeJSONValue] { - var payload: [String: LKMCPBridgeJSONValue] = [:] + private func targetPayload(for document: LiveDocument) -> [String: MCPBridgeJSONValue] { + var payload: [String: MCPBridgeJSONValue] = [:] guard let appInfo = document.inspectableApp.appInfo else { return payload } diff --git a/LookInside/MCPBridge/LKMCPBridgeInspectionService.swift b/LookInside/MCPBridge/MCPBridgeInspectionService.swift similarity index 82% rename from LookInside/MCPBridge/LKMCPBridgeInspectionService.swift rename to LookInside/MCPBridge/MCPBridgeInspectionService.swift index 3fb6e662..4b41493b 100644 --- a/LookInside/MCPBridge/LKMCPBridgeInspectionService.swift +++ b/LookInside/MCPBridge/MCPBridgeInspectionService.swift @@ -1,9 +1,9 @@ -// LKMCPBridgeInspectionService.swift +// MCPBridgeInspectionService.swift // // Routes MCPBridge inspection requests to the host's per-window -// `LookinLiveDocument` instances and converts the results to wire DTOs. +// `LiveDocument` instances and converts the results to wire DTOs. // -// All access to `NSDocumentController` and `LookinLiveDocument` happens on +// All access to `NSDocumentController` and `LiveDocument` happens on // the main thread; the entry point is `@MainActor` so the bridge // connection handlers can `await` it from a background queue and get the // hop for free. @@ -14,7 +14,7 @@ import Foundation import os @MainActor -final class LKMCPBridgeInspectionService { +final class MCPBridgeInspectionService { private static let logger = Logger(subsystem: "com.lookinside.app", category: "MCPBridge.Inspection") init() {} @@ -22,7 +22,7 @@ final class LKMCPBridgeInspectionService { /// Routes a decoded request frame to the appropriate inspection method. /// Falls through to `dispatch.unknownMethod` for any verb the host does /// not implement so the wire layer behaves predictably for new clients. - func handle(request: LKMCPBridgeRequest) async -> LKMCPBridgeResponse { + func handle(request: MCPBridgeRequest) async -> MCPBridgeResponse { switch request.method { case "targets.list": return handleTargetsList(identifier: request.identifier) @@ -37,8 +37,8 @@ final class LKMCPBridgeInspectionService { // MARK: - targets.list - private func handleTargetsList(identifier: String) -> LKMCPBridgeResponse { - let documents = LKMCPBridgeLiveDocumentLookup.enumerateLiveDocuments() + private func handleTargetsList(identifier: String) -> MCPBridgeResponse { + let documents = MCPBridgeLiveDocumentLookup.enumerateLiveDocuments() let infos = documents.compactMap(makeTargetInfo(for:)) do { let payload = try encodeAsJSONValue(infos) @@ -49,9 +49,9 @@ final class LKMCPBridgeInspectionService { } } - private func makeTargetInfo(for document: LookinLiveDocument) -> LKMCPBridgeTargetInfo? { + private func makeTargetInfo(for document: LiveDocument) -> MCPBridgeTargetInfo? { guard let appInfo = document.inspectableApp.appInfo else { return nil } - return LKMCPBridgeTargetInfo( + return MCPBridgeTargetInfo( targetIdentifier: String(appInfo.appInfoIdentifier), applicationName: appInfo.appName, bundleIdentifier: appInfo.appBundleIdentifier, @@ -78,8 +78,8 @@ final class LKMCPBridgeInspectionService { private func handleHierarchyRead( identifier: String, - parameters: [String: LKMCPBridgeJSONValue]? - ) -> LKMCPBridgeResponse { + parameters: [String: MCPBridgeJSONValue]? + ) -> MCPBridgeResponse { guard let parameters = parameters, case let .string(targetIdentifier)? = parameters["targetIdentifier"] else { @@ -116,10 +116,10 @@ final class LKMCPBridgeInspectionService { includeCells = false } - guard let document = LKMCPBridgeLiveDocumentLookup.findLiveDocument(targetIdentifier: targetIdentifier) else { + guard let document = MCPBridgeLiveDocumentLookup.findLiveDocument(targetIdentifier: targetIdentifier) else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "hierarchy.targetNotFound", message: "No live inspection document found for target identifier \(targetIdentifier)." ) @@ -129,7 +129,7 @@ final class LKMCPBridgeInspectionService { guard let dataSource = document.hierarchyDataSource else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "hierarchy.notReady", message: "Live document has not loaded a hierarchy yet." ) @@ -138,13 +138,13 @@ final class LKMCPBridgeInspectionService { let rootItems: [DisplayItem] if let rootObjectIdentifier { - guard let scopedRoot = LKMCPBridgeLiveDocumentLookup.findDisplayItem( + guard let scopedRoot = MCPBridgeLiveDocumentLookup.findDisplayItem( amongRoots: dataSource.rawFlatItems ?? [], matchingObjectIdentifier: rootObjectIdentifier ) else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "hierarchy.objectNotFound", message: "Object identifier \(rootObjectIdentifier) is not present in this target's hierarchy." ) @@ -152,7 +152,7 @@ final class LKMCPBridgeInspectionService { } rootItems = [scopedRoot] } else { - rootItems = LKMCPBridgeLiveDocumentLookup.topLevelDisplayItems(in: document) + rootItems = MCPBridgeLiveDocumentLookup.topLevelDisplayItems(in: document) } let nodes = rootItems.map { makeViewNode(from: $0, remainingDepth: depth, includeLayoutGuides: includeLayoutGuides, includeCells: includeCells) } @@ -181,10 +181,10 @@ final class LKMCPBridgeInspectionService { } } - private func makeViewNode(from item: DisplayItem, remainingDepth: Int?, includeLayoutGuides: Bool, includeCells: Bool) -> LKMCPBridgeViewNode { - let identity = LKMCPBridgeLiveDocumentLookup.objectIdentifierString(for: item) + private func makeViewNode(from item: DisplayItem, remainingDepth: Int?, includeLayoutGuides: Bool, includeCells: Bool) -> MCPBridgeViewNode { + let identity = MCPBridgeLiveDocumentLookup.objectIdentifierString(for: item) let className = item.displayingObject()?.classChainList?.first ?? "" - let frame = LKMCPBridgeRect(cgRect: LKMCPBridgeLiveDocumentLookup.rootSpaceFrame(for: item)) + let frame = MCPBridgeRect(cgRect: MCPBridgeLiveDocumentLookup.rootSpaceFrame(for: item)) var subitems = item.subitems ?? [] if includeLayoutGuides == false { // Default-off so existing agents' structural paths and snapshot @@ -195,9 +195,9 @@ final class LKMCPBridgeInspectionService { // Same reasoning as includeLayoutGuides, for cell nodes. subitems = subitems.filter { $0.resolvedNodeKind() != .cell } } - let childIdentifiers = subitems.map(LKMCPBridgeLiveDocumentLookup.objectIdentifierString(for:)) + let childIdentifiers = subitems.map(MCPBridgeLiveDocumentLookup.objectIdentifierString(for:)) - let inlinedChildren: [LKMCPBridgeViewNode]? + let inlinedChildren: [MCPBridgeViewNode]? if let remainingDepth, remainingDepth <= 1 { inlinedChildren = nil } else { @@ -205,7 +205,7 @@ final class LKMCPBridgeInspectionService { inlinedChildren = subitems.map { makeViewNode(from: $0, remainingDepth: nextDepth, includeLayoutGuides: includeLayoutGuides, includeCells: includeCells) } } - return LKMCPBridgeViewNode( + return MCPBridgeViewNode( objectIdentifier: identity, className: className, nodeKind: Self.nodeKindString(for: item), @@ -222,8 +222,8 @@ final class LKMCPBridgeInspectionService { private func handleAttributesRead( identifier: String, - parameters: [String: LKMCPBridgeJSONValue]? - ) -> LKMCPBridgeResponse { + parameters: [String: MCPBridgeJSONValue]? + ) -> MCPBridgeResponse { guard let parameters = parameters, case let .string(targetIdentifier)? = parameters["targetIdentifier"], case let .string(objectIdentifier)? = parameters["objectIdentifier"] @@ -238,10 +238,10 @@ final class LKMCPBridgeInspectionService { includeUserCustom = true } - guard let document = LKMCPBridgeLiveDocumentLookup.findLiveDocument(targetIdentifier: targetIdentifier) else { + guard let document = MCPBridgeLiveDocumentLookup.findLiveDocument(targetIdentifier: targetIdentifier) else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "hierarchy.targetNotFound", message: "No live inspection document found for target identifier \(targetIdentifier)." ) @@ -251,20 +251,20 @@ final class LKMCPBridgeInspectionService { guard document.hierarchyDataSource != nil else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "hierarchy.notReady", message: "Live document has not loaded a hierarchy yet." ) ) } - guard let displayItem = LKMCPBridgeLiveDocumentLookup.findDisplayItem( - amongRoots: LKMCPBridgeLiveDocumentLookup.topLevelDisplayItems(in: document), + guard let displayItem = MCPBridgeLiveDocumentLookup.findDisplayItem( + amongRoots: MCPBridgeLiveDocumentLookup.topLevelDisplayItems(in: document), matchingObjectIdentifier: objectIdentifier ) else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "hierarchy.objectNotFound", message: "Object identifier \(objectIdentifier) is not present in this target's hierarchy." ) @@ -283,7 +283,7 @@ final class LKMCPBridgeInspectionService { // attribute we emit for this view shares the same redaction // decision (a UITextField/NSSecureTextField can't have its // `placeholder` leak when its `text` is redacted, for example). - let redactSecureContent = LKMCPBridgeSecureContentDetector.isSecure(displayItem: displayItem) + let redactSecureContent = MCPBridgeSecureContentDetector.isSecure(displayItem: displayItem) let encodedGroups = rawGroups.map { group in encodeGroup(group, redactingSecureContent: redactSecureContent) @@ -314,12 +314,12 @@ final class LKMCPBridgeInspectionService { private func encodeGroup( _ group: AttributesGroup, redactingSecureContent: Bool - ) -> LKMCPBridgeAttributeGroup { + ) -> MCPBridgeAttributeGroup { let identifier = group.userCustomTitle ?? group.identifier let sections = (group.attrSections ?? []).map { section in encodeSection(section, redactingSecureContent: redactingSecureContent) } - return LKMCPBridgeAttributeGroup( + return MCPBridgeAttributeGroup( identifier: identifier ?? "", isUserCustom: group.userCustomTitle != nil, isSwiftUIGroup: group.isSwiftUIGroup, @@ -330,14 +330,14 @@ final class LKMCPBridgeInspectionService { private func encodeSection( _ section: AttributesSection, redactingSecureContent: Bool - ) -> LKMCPBridgeAttributeSection { + ) -> MCPBridgeAttributeSection { let attributes = (section.attributes ?? []).map { attribute in - LKMCPBridgeAttributeEncoder.encode( + MCPBridgeAttributeEncoder.encode( attribute, redactingSecureContent: redactingSecureContent ) } - return LKMCPBridgeAttributeSection( + return MCPBridgeAttributeSection( identifier: section.identifier ?? "", attributes: attributes ) @@ -345,12 +345,12 @@ final class LKMCPBridgeInspectionService { // MARK: - Encoding helpers - /// Encodes any `Encodable` value into the loose `LKMCPBridgeJSONValue` + /// Encodes any `Encodable` value into the loose `MCPBridgeJSONValue` /// tree used inside response frame `result` containers. Round-trips /// through `JSONEncoder` / `JSONDecoder` so non-trivial nested types /// (arrays, optionals, etc.) preserve their wire shape. - private func encodeAsJSONValue(_ value: some Encodable) throws -> LKMCPBridgeJSONValue { + private func encodeAsJSONValue(_ value: some Encodable) throws -> MCPBridgeJSONValue { let data = try JSONEncoder().encode(value) - return try JSONDecoder().decode(LKMCPBridgeJSONValue.self, from: data) + return try JSONDecoder().decode(MCPBridgeJSONValue.self, from: data) } } diff --git a/LookInside/MCPBridge/LKMCPBridgeInvocationService.swift b/LookInside/MCPBridge/MCPBridgeInvocationService.swift similarity index 81% rename from LookInside/MCPBridge/LKMCPBridgeInvocationService.swift rename to LookInside/MCPBridge/MCPBridgeInvocationService.swift index dff54cd5..02b58b5a 100644 --- a/LookInside/MCPBridge/LKMCPBridgeInvocationService.swift +++ b/LookInside/MCPBridge/MCPBridgeInvocationService.swift @@ -1,14 +1,14 @@ -// LKMCPBridgeInvocationService.swift +// MCPBridgeInvocationService.swift // // Handles the `invoke.method` bridge route: arbitrary zero-argument // Objective-C selector invocation on a view in an attached target app. // This is the bridge's first mutating route — it goes over the connection channel // (RPC 206 `LookinRequestType_InvokeMethod`) and can change the // inspected app's state. Read-only inspection routes live in -// `LKMCPBridgeInspectionService`; they share the live-document / -// display-item lookup through `LKMCPBridgeLiveDocumentLookup`. +// `MCPBridgeInspectionService`; they share the live-document / +// display-item lookup through `MCPBridgeLiveDocumentLookup`. // -// Selector blacklist mirrors `LKConsoleDataSource` (rejects selectors +// Selector blacklist mirrors `ConsoleDataSource` (rejects selectors // containing `:` and `.`). The server enforces a hard zero-argument // limit on top of that. Anything else — method visibility, naming // conventions, side-effect ack — is left to the agent and tool-level @@ -19,14 +19,14 @@ import Foundation import os @MainActor -final class LKMCPBridgeInvocationService { +final class MCPBridgeInvocationService { private static let logger = Logger(subsystem: "com.lookinside.app", category: "MCPBridge.Invocation") init() {} // MARK: - Entry point - func handle(request: LKMCPBridgeRequest) async -> LKMCPBridgeResponse { + func handle(request: MCPBridgeRequest) async -> MCPBridgeResponse { guard request.method == "invoke.method" else { return .failure(identifier: request.identifier, error: .unknownMethod) } @@ -40,8 +40,8 @@ final class LKMCPBridgeInvocationService { private func handleInvokeMethod( identifier: String, - parameters: [String: LKMCPBridgeJSONValue]? - ) async -> LKMCPBridgeResponse { + parameters: [String: MCPBridgeJSONValue]? + ) async -> MCPBridgeResponse { guard let parameters = parameters, case let .string(targetIdentifier)? = parameters["targetIdentifier"], case let .string(objectIdentifier)? = parameters["objectIdentifier"], @@ -54,7 +54,7 @@ final class LKMCPBridgeInvocationService { return .failure(identifier: identifier, error: .invalidParameters) } - // Mirror LKConsoleDataSource's selector blacklist (rejects + // Mirror ConsoleDataSource's selector blacklist (rejects // anything that wouldn't go through RPC 206's zero-argument // gate on the server side). Centralizing this here gives a // single explicit error code with a hint instead of relying on @@ -62,7 +62,7 @@ final class LKMCPBridgeInvocationService { if selector.contains(":") { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "invoke.unsupportedSelector", message: "Multi-argument selectors (containing ':') are not supported in this release. Use a zero-argument selector or wait for a future bridge method." ) @@ -71,17 +71,17 @@ final class LKMCPBridgeInvocationService { if selector.contains(".") { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "invoke.unsupportedSelector", message: "Dotted access (containing '.') is not supported; pass a single method or property name." ) ) } - guard let document = LKMCPBridgeLiveDocumentLookup.findLiveDocument(targetIdentifier: targetIdentifier) else { + guard let document = MCPBridgeLiveDocumentLookup.findLiveDocument(targetIdentifier: targetIdentifier) else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "hierarchy.targetNotFound", message: "No live inspection document found for target identifier \(targetIdentifier)." ) @@ -91,41 +91,41 @@ final class LKMCPBridgeInvocationService { guard document.hierarchyDataSource != nil else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "hierarchy.notReady", message: "Live document has not loaded a hierarchy yet." ) ) } - guard let displayItem = LKMCPBridgeLiveDocumentLookup.findDisplayItem( - amongRoots: LKMCPBridgeLiveDocumentLookup.topLevelDisplayItems(in: document), + guard let displayItem = MCPBridgeLiveDocumentLookup.findDisplayItem( + amongRoots: MCPBridgeLiveDocumentLookup.topLevelDisplayItems(in: document), matchingObjectIdentifier: objectIdentifier ) else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "hierarchy.objectNotFound", message: "Object identifier \(objectIdentifier) is not present in this target's hierarchy." ) ) } - // The wire oid is hex-encoded; LKInspectableApp accepts the raw + // The wire oid is hex-encoded; InspectableApp accepts the raw // unsigned-long value. Re-derive it from the display item we // just resolved so we don't have to parse the wire string — // the display item already holds the canonical numeric oid. guard let nativeOid = displayItem.displayingObject()?.oid, nativeOid != 0 else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "hierarchy.objectNotFound", message: "Display item \(objectIdentifier) does not carry a live object identifier." ) ) } - let redactSecureContent = LKMCPBridgeSecureContentDetector.isSecure(displayItem: displayItem) + let redactSecureContent = MCPBridgeSecureContentDetector.isSecure(displayItem: displayItem) // Sent through `response(type:data:as:)` rather than // `invokeMethod(oid:text:)`: that one replaces the Server's @@ -136,7 +136,7 @@ final class LKMCPBridgeInvocationService { do { rawDictionary = try await document.inspectableApp.response( type: UInt32(LookinRequestTypeInvokeMethod), - data: LKInspectableApp.invokeMethodParameters(oid: nativeOid, text: selector), + data: InspectableApp.invokeMethodParameters(oid: nativeOid, text: selector), as: NSDictionary.self ) } catch { @@ -162,7 +162,7 @@ final class LKMCPBridgeInvocationService { private func makeInvocationResult( from dictionary: NSDictionary, redactSecureContent: Bool - ) -> LKMCPBridgeInvocationResult { + ) -> MCPBridgeInvocationResult { let rawDescription = dictionary["description"] as? String let returnedVoid = rawDescription == LookinStringFlag_VoidReturn @@ -177,7 +177,7 @@ final class LKMCPBridgeInvocationService { let returnObject = makeReturnedObject(from: dictionary["object"]) - return LKMCPBridgeInvocationResult( + return MCPBridgeInvocationResult( description: surfacedDescription, returnedVoid: returnedVoid, returnObject: returnObject, @@ -185,10 +185,10 @@ final class LKMCPBridgeInvocationService { ) } - private func makeReturnedObject(from rawObject: Any?) -> LKMCPBridgeReturnedObject? { + private func makeReturnedObject(from rawObject: Any?) -> MCPBridgeReturnedObject? { guard let lookinObject = rawObject as? InspectedObject else { return nil } let oidString = String(format: "0x%lx", lookinObject.oid) - return LKMCPBridgeReturnedObject( + return MCPBridgeReturnedObject( objectIdentifier: oidString, memoryAddress: lookinObject.memoryAddress ?? "", classChainList: lookinObject.classChainList ?? [], @@ -198,33 +198,33 @@ final class LKMCPBridgeInvocationService { // MARK: - Error mapping - private func mapInvocationError(_ error: NSError) -> LKMCPBridgeErrorPayload { + private func mapInvocationError(_ error: NSError) -> MCPBridgeErrorPayload { switch error.code { case LookinErrCode_ObjectNotFound: - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "invoke.objectNotFound", message: "The target app could not find an object for this identifier or it does not respond to the selector. The object may have been deallocated; try reloading the inspector." ) case LookinErrCode_Inner: - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "invoke.invalidSelector", message: "The target app rejected the selector — most likely it requires arguments or has no method signature. Only zero-argument selectors are supported." ) case LookinErrCode_LicenseRequired: return .licenseRequired case LookinErrCode_NoConnect: - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "invoke.disconnected", message: "The target app is no longer connected. Re-attach from the LookInside inspector and try again." ) case LookinErrCode_Timeout: - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "invoke.timeout", message: "The target app did not respond within the request timeout. Check whether it is paused in Xcode or blocked on the main thread." ) default: Self.logger.error("invoke.method received unmapped error code \(error.code, privacy: .public): \(error.localizedDescription, privacy: .public)") - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "invoke.internalError", message: "The target app reported an unexpected error (code \(error.code))." ) @@ -239,8 +239,8 @@ final class LKMCPBridgeInvocationService { // service rather than introducing a shared protocol just for two // identical four-line helpers. - private func encodeAsJSONValue(_ value: some Encodable) throws -> LKMCPBridgeJSONValue { + private func encodeAsJSONValue(_ value: some Encodable) throws -> MCPBridgeJSONValue { let data = try JSONEncoder().encode(value) - return try JSONDecoder().decode(LKMCPBridgeJSONValue.self, from: data) + return try JSONDecoder().decode(MCPBridgeJSONValue.self, from: data) } } diff --git a/LookInside/MCPBridge/LKMCPBridgeListenSocket.swift b/LookInside/MCPBridge/MCPBridgeListenSocket.swift similarity index 89% rename from LookInside/MCPBridge/LKMCPBridgeListenSocket.swift rename to LookInside/MCPBridge/MCPBridgeListenSocket.swift index 1b313f5f..84c16650 100644 --- a/LookInside/MCPBridge/LKMCPBridgeListenSocket.swift +++ b/LookInside/MCPBridge/MCPBridgeListenSocket.swift @@ -1,14 +1,14 @@ -// LKMCPBridgeListenSocket.swift +// MCPBridgeListenSocket.swift // // Creation of the MCPBridge listening Unix domain socket, split out of -// `LKMCPBridgeServer` so it can be exercised on its own. +// `MCPBridgeServer` so it can be exercised on its own. // // The split exists for a reason beyond tidiness: the socket's blocking // mode is a correctness property that is invisible at the call site and // impossible to test through the server, which drags in the whole // inspection stack (AppKit, NSDocumentController, the ObjC bridge). // Everything here depends on Darwin and Foundation only, so -// `Tests/MCPBridge/LKMCPBridgeListenSocketTests.swift` can compile it +// `Tests/MCPBridge/MCPBridgeListenSocketTests.swift` can compile it // with a bare `swiftc` invocation the way the other host-side tests do. // // Why non-blocking matters: the server drives accepts from a @@ -24,7 +24,7 @@ import Darwin import Foundation -enum LKMCPBridgeListenSocket { +enum MCPBridgeListenSocket { /// File permissions for the socket itself: owner-only, matching the /// per-user trust model (any process running as this user may /// connect; nothing else may). @@ -37,7 +37,7 @@ enum LKMCPBridgeListenSocket { /// file from a crashed host would otherwise make `bind` fail with /// `EADDRINUSE` forever. /// - /// - Throws: `LKMCPBridgeListenSocketError` when any step fails. The + /// - Throws: `MCPBridgeListenSocketError` when any step fails. The /// descriptor is closed before throwing, so a failed call leaks /// nothing. static func makeListening( @@ -46,7 +46,7 @@ enum LKMCPBridgeListenSocket { ) throws -> Int32 { let descriptor = socket(AF_UNIX, SOCK_STREAM, 0) guard descriptor >= 0 else { - throw LKMCPBridgeListenSocketError(message: "socket(AF_UNIX) failed (errno \(errno))") + throw MCPBridgeListenSocketError(message: "socket(AF_UNIX) failed (errno \(errno))") } var address = sockaddr_un() @@ -55,7 +55,7 @@ enum LKMCPBridgeListenSocket { let pathCapacity = MemoryLayout.size(ofValue: address.sun_path) if pathBytes.count >= pathCapacity { Darwin.close(descriptor) - throw LKMCPBridgeListenSocketError( + throw MCPBridgeListenSocketError( message: "Socket path is longer than the kernel's sun_path limit (\(pathCapacity) bytes)." ) } @@ -76,7 +76,7 @@ enum LKMCPBridgeListenSocket { if bindResult != 0 { let savedErrorNumber = errno Darwin.close(descriptor) - throw LKMCPBridgeListenSocketError(message: "bind() failed (errno \(savedErrorNumber))") + throw MCPBridgeListenSocketError(message: "bind() failed (errno \(savedErrorNumber))") } // Best-effort: a permissive umask would otherwise leave the @@ -88,7 +88,7 @@ enum LKMCPBridgeListenSocket { let savedErrorNumber = errno Darwin.close(descriptor) unlink(socketPath) - throw LKMCPBridgeListenSocketError(message: "listen() failed (errno \(savedErrorNumber))") + throw MCPBridgeListenSocketError(message: "listen() failed (errno \(savedErrorNumber))") } // The accept drain loop's termination condition. See the file @@ -97,7 +97,7 @@ enum LKMCPBridgeListenSocket { let savedErrorNumber = errno Darwin.close(descriptor) unlink(socketPath) - throw LKMCPBridgeListenSocketError( + throw MCPBridgeListenSocketError( message: "fcntl(F_SETFL, O_NONBLOCK) failed (errno \(savedErrorNumber))" ) } @@ -116,7 +116,7 @@ enum LKMCPBridgeListenSocket { /// listener has to be non-blocking (see `makeListening`), every /// connection would silently come out non-blocking too. /// - /// That matters because `LKMCPBridgeConnection` writes responses + /// That matters because `MCPBridgeConnection` writes responses /// with a blocking `write(2)` loop and treats `EAGAIN` as fatal. /// On a non-blocking descriptor, any response larger than the /// socket send buffer hits `EAGAIN` partway through and the @@ -150,7 +150,7 @@ enum LKMCPBridgeListenSocket { } } -struct LKMCPBridgeListenSocketError: LocalizedError { +struct MCPBridgeListenSocketError: LocalizedError { let message: String var errorDescription: String? { return message diff --git a/LookInside/MCPBridge/LKMCPBridgeLiveDocumentLookup.swift b/LookInside/MCPBridge/MCPBridgeLiveDocumentLookup.swift similarity index 85% rename from LookInside/MCPBridge/LKMCPBridgeLiveDocumentLookup.swift rename to LookInside/MCPBridge/MCPBridgeLiveDocumentLookup.swift index 0064568b..b6d3fa95 100644 --- a/LookInside/MCPBridge/LKMCPBridgeLiveDocumentLookup.swift +++ b/LookInside/MCPBridge/MCPBridgeLiveDocumentLookup.swift @@ -1,36 +1,36 @@ -// LKMCPBridgeLiveDocumentLookup.swift +// MCPBridgeLiveDocumentLookup.swift // // Shared lookup helpers that translate the bridge wire identifiers // (`targetIdentifier`, `objectIdentifier`) into the host's live runtime -// objects (`LookinLiveDocument`, `DisplayItem`). Both the inspection +// objects (`LiveDocument`, `DisplayItem`). Both the inspection // service (read-only queries) and the invocation service (round-trips to // the server over the connection channel) share this surface so the wire shape — hex // `oid` strings, decimal `appInfoIdentifier` strings — stays one // canonical implementation. // // All entry points are `@MainActor`: `NSDocumentController` and -// `LookinLiveDocument` require main-thread isolation, and the bridge +// `LiveDocument` require main-thread isolation, and the bridge // connection handlers already hop here before invoking lookup. import AppKit import Foundation @MainActor -enum LKMCPBridgeLiveDocumentLookup { - /// Enumerates every currently-open `LookinLiveDocument` known to the +enum MCPBridgeLiveDocumentLookup { + /// Enumerates every currently-open `LiveDocument` known to the /// host. Static (archived `.lookin`) documents are excluded because /// they have no attached app to inspect / invoke against. - static func enumerateLiveDocuments() -> [LookinLiveDocument] { + static func enumerateLiveDocuments() -> [LiveDocument] { let allDocuments = NSDocumentController.shared.documents - return allDocuments.compactMap { $0 as? LookinLiveDocument } + return allDocuments.compactMap { $0 as? LiveDocument } } /// Resolves a wire `targetIdentifier` (decimal string form of /// `InspectedAppInfo.appInfoIdentifier`) to the matching - /// `LookinLiveDocument`. Returns `nil` when the string is not a valid + /// `LiveDocument`. Returns `nil` when the string is not a valid /// unsigned integer or no open live document carries that /// `appInfoIdentifier`. - static func findLiveDocument(targetIdentifier: String) -> LookinLiveDocument? { + static func findLiveDocument(targetIdentifier: String) -> LiveDocument? { guard let identifierValue = UInt(targetIdentifier) else { return nil } return enumerateLiveDocuments().first { document in document.inspectableApp.appInfo?.appInfoIdentifier == identifierValue @@ -61,7 +61,7 @@ enum LKMCPBridgeLiveDocumentLookup { /// Top-level display items (windows / scenes) inside a live document. /// These are the seed points for `findDisplayItem(amongRoots:matchingObjectIdentifier:)` /// when the caller didn't pre-narrow the search space. - static func topLevelDisplayItems(in document: LookinLiveDocument) -> [DisplayItem] { + static func topLevelDisplayItems(in document: LiveDocument) -> [DisplayItem] { guard let dataSource = document.hierarchyDataSource, let flatItems = dataSource.rawFlatItems else { return [] } diff --git a/LookInside/MCPBridge/LKMCPBridgeModificationService.swift b/LookInside/MCPBridge/MCPBridgeModificationService.swift similarity index 82% rename from LookInside/MCPBridge/LKMCPBridgeModificationService.swift rename to LookInside/MCPBridge/MCPBridgeModificationService.swift index 84c453f8..a944cb4f 100644 --- a/LookInside/MCPBridge/LKMCPBridgeModificationService.swift +++ b/LookInside/MCPBridge/MCPBridgeModificationService.swift @@ -1,4 +1,4 @@ -// LKMCPBridgeModificationService.swift +// MCPBridgeModificationService.swift // // Handles the `attribute.modify` bridge route: mutates one inspected // attribute on a view in the attached target app (RPC 204 @@ -9,9 +9,9 @@ // It shares the same round-trip plumbing — selector lookup // happens against `DashboardBlueprint`; the polymorphic wire // value is decoded into the right ObjC type by -// `LKMCPBridgeAttributeValueDecoder`; the round-trip awaits -// `LKInspectableApp.submit(_:)`; -// `LKMCPBridgeAttributeEncoder` re-encodes the effective post-layout +// `MCPBridgeAttributeValueDecoder`; the round-trip awaits +// `InspectableApp.submit(_:)`; +// `MCPBridgeAttributeEncoder` re-encodes the effective post-layout // attribute so the caller can compare against what they sent. // // The bridge does NOT pre-compute settability — it asks @@ -25,14 +25,14 @@ import Foundation import os @MainActor -final class LKMCPBridgeModificationService { +final class MCPBridgeModificationService { private static let logger = Logger(subsystem: "com.lookinside.app", category: "MCPBridge.Modification") init() {} // MARK: - Entry point - func handle(request: LKMCPBridgeRequest) async -> LKMCPBridgeResponse { + func handle(request: MCPBridgeRequest) async -> MCPBridgeResponse { guard request.method == "attribute.modify" else { return .failure(identifier: request.identifier, error: .unknownMethod) } @@ -46,8 +46,8 @@ final class LKMCPBridgeModificationService { private func handleAttributeModify( identifier: String, - parameters: [String: LKMCPBridgeJSONValue]? - ) async -> LKMCPBridgeResponse { + parameters: [String: MCPBridgeJSONValue]? + ) async -> MCPBridgeResponse { // Parameter extraction guard let parameters, case let .string(targetIdentifier)? = parameters["targetIdentifier"], @@ -61,10 +61,10 @@ final class LKMCPBridgeModificationService { let wireData = valueObject["data"] // Live-document / display-item lookup - guard let document = LKMCPBridgeLiveDocumentLookup.findLiveDocument(targetIdentifier: targetIdentifier) else { + guard let document = MCPBridgeLiveDocumentLookup.findLiveDocument(targetIdentifier: targetIdentifier) else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "hierarchy.targetNotFound", message: "No live inspection document found for target identifier \(targetIdentifier)." ) @@ -74,20 +74,20 @@ final class LKMCPBridgeModificationService { guard document.hierarchyDataSource != nil else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "hierarchy.notReady", message: "Live document has not loaded a hierarchy yet." ) ) } - guard let displayItem = LKMCPBridgeLiveDocumentLookup.findDisplayItem( - amongRoots: LKMCPBridgeLiveDocumentLookup.topLevelDisplayItems(in: document), + guard let displayItem = MCPBridgeLiveDocumentLookup.findDisplayItem( + amongRoots: MCPBridgeLiveDocumentLookup.topLevelDisplayItems(in: document), matchingObjectIdentifier: objectIdentifier ) else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "hierarchy.objectNotFound", message: "Object identifier \(objectIdentifier) is not present in this target's hierarchy." ) @@ -101,7 +101,7 @@ final class LKMCPBridgeModificationService { ) else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "modify.attributeNotFound", message: "Attribute \(attributeIdentifier) is not present in this view's cached detail. Open the view in the LookInside inspector (or call read_attributes first) to populate its detail, then retry." ) @@ -114,7 +114,7 @@ final class LKMCPBridgeModificationService { guard let setterSelector = DashboardBlueprint.setter(withAttrID: attributeIdentifier) else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "modify.readOnly", message: "Attribute \(attributeIdentifier) is read-only; there is no registered setter for it." ) @@ -125,7 +125,7 @@ final class LKMCPBridgeModificationService { guard let nativeOid = displayItem.displayingObject()?.oid, nativeOid != 0 else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "hierarchy.objectNotFound", message: "Display item \(objectIdentifier) does not carry a live object identifier." ) @@ -135,31 +135,31 @@ final class LKMCPBridgeModificationService { // Decode wire value into the polymorphic id AttributeModification expects. let nativeValue: Any do { - nativeValue = try LKMCPBridgeAttributeValueDecoder.decode( + nativeValue = try MCPBridgeAttributeValueDecoder.decode( wireKind: wireKind, wireData: wireData, expectedAttrType: attribute.attrType ) - } catch let LKMCPBridgeAttributeValueDecoder.DecodeError.unsupportedKind(kind) { + } catch let MCPBridgeAttributeValueDecoder.DecodeError.unsupportedKind(kind) { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "modify.unsupportedKind", message: "Wire kind '\(kind)' is not supported for modification in this release. Supported kinds: integer, double, bool, string, selector, class, point, vector, size, rect, transform, edgeInsets, offset, color, enum." ) ) - } catch let LKMCPBridgeAttributeValueDecoder.DecodeError.kindMismatch(wireKind, expectedAttrType) { + } catch let MCPBridgeAttributeValueDecoder.DecodeError.kindMismatch(wireKind, expectedAttrType) { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "modify.valueKindMismatch", message: "Wire kind '\(wireKind)' does not match attribute's declared LookinAttrType (\(expectedAttrType.rawValue))." ) ) - } catch let LKMCPBridgeAttributeValueDecoder.DecodeError.shapeInvalid(reason) { + } catch let MCPBridgeAttributeValueDecoder.DecodeError.shapeInvalid(reason) { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "modify.valueShapeInvalid", message: reason ) @@ -175,7 +175,7 @@ final class LKMCPBridgeModificationService { modification.setterSelector = setterSelector modification.attrType = attribute.attrType modification.value = nativeValue - modification.clientReadableVersion = LKHelper.lookinReadableVersion() + modification.clientReadableVersion = AppHelper.lookinReadableVersion() let detail: DisplayItemDetail do { @@ -205,7 +205,7 @@ final class LKMCPBridgeModificationService { ) else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "modify.internalError", message: "Effective attribute disappeared from the server's post-modification detail. This indicates a server-side bug." ) @@ -214,14 +214,14 @@ final class LKMCPBridgeModificationService { // Encode the effective attribute through the same encoder // the read route uses, so its shape matches read_attributes. - let redactSecureContent = LKMCPBridgeSecureContentDetector.isSecure(displayItem: displayItem) - let encodedEffective = LKMCPBridgeAttributeEncoder.encode( + let redactSecureContent = MCPBridgeSecureContentDetector.isSecure(displayItem: displayItem) + let encodedEffective = MCPBridgeAttributeEncoder.encode( effectiveAttribute, redactingSecureContent: redactSecureContent ) - let requestedWire = LKMCPBridgeAttributeValueWire(kind: wireKind, data: wireData) - let effectiveWire = LKMCPBridgeAttributeValueWire( + let requestedWire = MCPBridgeAttributeValueWire(kind: wireKind, data: wireData) + let effectiveWire = MCPBridgeAttributeValueWire( kind: encodedEffective.kind, data: encodedEffective.value ) @@ -234,13 +234,13 @@ final class LKMCPBridgeModificationService { let isHidden = detail.hiddenValue?.boolValue ?? false let alpha = detail.alphaValue?.doubleValue ?? 1.0 - let result = LKMCPBridgeModificationResult( + let result = MCPBridgeModificationResult( attributeIdentifier: attributeIdentifier, requestedValue: requestedWire, effectiveAttribute: encodedEffective, effectiveMatchesRequested: matches, - frame: LKMCPBridgeRect(cgRect: frame), - bounds: LKMCPBridgeRect(cgRect: bounds), + frame: MCPBridgeRect(cgRect: frame), + bounds: MCPBridgeRect(cgRect: bounds), isHidden: isHidden, alpha: alpha, secureContent: redactSecureContent @@ -273,14 +273,14 @@ final class LKMCPBridgeModificationService { return nil } - /// Equality on `LKMCPBridgeJSONValue` by canonical JSON encoding. + /// Equality on `MCPBridgeJSONValue` by canonical JSON encoding. /// Uses `.sortedKeys` so object key order does not affect the result. /// This is intentionally strict — no float epsilon — because layout /// pass adjustments are a real signal we want to surface to the /// agent rather than absorb. private func jsonValuesEqual( - _ lhs: LKMCPBridgeJSONValue?, - _ rhs: LKMCPBridgeJSONValue? + _ lhs: MCPBridgeJSONValue?, + _ rhs: MCPBridgeJSONValue? ) -> Bool { switch (lhs, rhs) { case (nil, nil): @@ -296,15 +296,15 @@ final class LKMCPBridgeModificationService { } } - private func mapModificationError(_ error: NSError) -> LKMCPBridgeErrorPayload { + private func mapModificationError(_ error: NSError) -> MCPBridgeErrorPayload { switch error.code { case LookinErrCode_ObjectNotFound: - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "modify.objectNotFound", message: "The target app could not find an object for this identifier. The object may have been deallocated; try reloading the inspector." ) case LookinErrCode_Inner: - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "modify.invalidSetter", message: "The target app rejected the modification — the setter signature was missing or the value type did not unbox cleanly." ) @@ -312,33 +312,33 @@ final class LKMCPBridgeModificationService { // NSException thrown by the setter; the server stuffs the // exception's reason into the NSLocalizedDescriptionKey. let reason = (error.userInfo[NSLocalizedDescriptionKey] as? String) ?? "no further detail" - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "modify.exception", message: "The setter raised an NSException in the target app: \(reason)" ) case LookinErrCode_LicenseRequired: return .licenseRequired case LookinErrCode_NoConnect: - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "modify.disconnected", message: "The target app is no longer connected. Re-attach from the LookInside inspector and try again." ) case LookinErrCode_Timeout: - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "modify.timeout", message: "The target app did not respond within the request timeout. Check whether it is paused in Xcode or blocked on the main thread." ) default: Self.logger.error("attribute.modify received unmapped error code \(error.code, privacy: .public): \(error.localizedDescription, privacy: .public)") - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "modify.internalError", message: "The target app reported an unexpected error (code \(error.code))." ) } } - private func encodeAsJSONValue(_ value: some Encodable) throws -> LKMCPBridgeJSONValue { + private func encodeAsJSONValue(_ value: some Encodable) throws -> MCPBridgeJSONValue { let data = try JSONEncoder().encode(value) - return try JSONDecoder().decode(LKMCPBridgeJSONValue.self, from: data) + return try JSONDecoder().decode(MCPBridgeJSONValue.self, from: data) } } diff --git a/LookInside/MCPBridge/LKMCPBridgeObjectIdentifierList.swift b/LookInside/MCPBridge/MCPBridgeObjectIdentifierList.swift similarity index 92% rename from LookInside/MCPBridge/LKMCPBridgeObjectIdentifierList.swift rename to LookInside/MCPBridge/MCPBridgeObjectIdentifierList.swift index 5351649b..e41b0560 100644 --- a/LookInside/MCPBridge/LKMCPBridgeObjectIdentifierList.swift +++ b/LookInside/MCPBridge/MCPBridgeObjectIdentifierList.swift @@ -1,10 +1,10 @@ -// LKMCPBridgeObjectIdentifierList.swift +// MCPBridgeObjectIdentifierList.swift // // Parses and normalizes the `objectIdentifiers` array that `details.read` // accepts off the wire. // -// This lives apart from LKMCPBridgeDetailsService for the same reason -// LKMCPBridgeSearchQuery lives apart from LKMCPBridgeSearchService: the +// This lives apart from MCPBridgeDetailsService for the same reason +// MCPBridgeSearchQuery lives apart from MCPBridgeSearchService: the // service imports AppKit and the ObjC bridge, so it cannot be compiled into // the standalone binaries that Scripts/test-mcp-bridge.sh builds, while the // list handling itself needs nothing but Foundation. @@ -18,7 +18,7 @@ import Foundation -enum LKMCPBridgeObjectIdentifierList { +enum MCPBridgeObjectIdentifierList { /// Why a wire payload was rejected. enum ParseFailure: Error, Equatable { /// At least one entry was not a JSON string. Loose typing is fine @@ -50,7 +50,7 @@ enum LKMCPBridgeObjectIdentifierList { /// - wireValues: The raw `objectIdentifiers` array. /// - limit: Maximum number of distinct identifiers the route accepts. static func parse( - wireValues: [LKMCPBridgeJSONValue], + wireValues: [MCPBridgeJSONValue], limit: Int ) -> Result { var identifiers: [String] = [] diff --git a/LookInside/MCPBridge/LKMCPBridgeRefreshService.swift b/LookInside/MCPBridge/MCPBridgeRefreshService.swift similarity index 84% rename from LookInside/MCPBridge/LKMCPBridgeRefreshService.swift rename to LookInside/MCPBridge/MCPBridgeRefreshService.swift index 7eba66a6..e2d2e8e0 100644 --- a/LookInside/MCPBridge/LKMCPBridgeRefreshService.swift +++ b/LookInside/MCPBridge/MCPBridgeRefreshService.swift @@ -1,4 +1,4 @@ -// LKMCPBridgeRefreshService.swift +// MCPBridgeRefreshService.swift // // Handles the `hierarchy.refresh` bridge route: re-fetching the target // app's whole view tree (RPC 202) and handing it to the host's data @@ -12,13 +12,13 @@ // had no equivalent and could only read a snapshot that silently went // stale the moment the app navigated. // -// This service is deliberately NOT folded into `LKMCPBridgeInspectionService`. +// This service is deliberately NOT folded into `MCPBridgeInspectionService`. // That service is pure cached reads with no RPC; refresh round-trips to // the target and mutates host state, and merging them would quietly // retire the "the read surface never emits RPC" property. // // The actual reload is not reimplemented here. It runs through -// `LKStaticWindowController.reloadHierarchy(initiator:)`, the same method +// `StaticWindowController.reloadHierarchy(initiator:)`, the same method // the toolbar button calls, so both paths share one re-entrancy gate // and one fetch chain. Duplicating the chain in Swift would have left two // copies to drift apart, and writing the window controller's private @@ -30,14 +30,14 @@ import Foundation import os @MainActor -final class LKMCPBridgeRefreshService { +final class MCPBridgeRefreshService { private static let logger = Logger(subsystem: "com.lookinside.app", category: "MCPBridge.Refresh") init() {} // MARK: - Entry point - func handle(request: LKMCPBridgeRequest) async -> LKMCPBridgeResponse { + func handle(request: MCPBridgeRequest) async -> MCPBridgeResponse { guard request.method == "hierarchy.refresh" else { return .failure(identifier: request.identifier, error: .unknownMethod) } @@ -51,18 +51,18 @@ final class LKMCPBridgeRefreshService { private func handleHierarchyRefresh( identifier: String, - parameters: [String: LKMCPBridgeJSONValue]? - ) async -> LKMCPBridgeResponse { + parameters: [String: MCPBridgeJSONValue]? + ) async -> MCPBridgeResponse { guard let parameters = parameters, case let .string(targetIdentifier)? = parameters["targetIdentifier"] else { return .failure(identifier: identifier, error: .invalidParameters) } - guard let document = LKMCPBridgeLiveDocumentLookup.findLiveDocument(targetIdentifier: targetIdentifier) else { + guard let document = MCPBridgeLiveDocumentLookup.findLiveDocument(targetIdentifier: targetIdentifier) else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "hierarchy.targetNotFound", message: "No live inspection document found for target identifier \(targetIdentifier)." ) @@ -72,7 +72,7 @@ final class LKMCPBridgeRefreshService { guard let windowController = document.staticWindowController else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "hierarchy.notReady", message: "Live document has no inspector window yet." ) @@ -104,11 +104,11 @@ final class LKMCPBridgeRefreshService { let durationMilliseconds = Int(elapsedComponents.seconds) * 1000 + Int(elapsedComponents.attoseconds / 1_000_000_000_000_000) - let rootIdentifiers = LKMCPBridgeLiveDocumentLookup + let rootIdentifiers = MCPBridgeLiveDocumentLookup .topLevelDisplayItems(in: document) - .map { LKMCPBridgeLiveDocumentLookup.objectIdentifierString(for: $0) } + .map { MCPBridgeLiveDocumentLookup.objectIdentifierString(for: $0) } - let result = LKMCPBridgeRefreshResult( + let result = MCPBridgeRefreshResult( targetIdentifier: targetIdentifier, rootObjectIdentifiers: rootIdentifiers, nodeCount: document.hierarchyDataSource?.rawFlatItems?.count ?? 0, @@ -127,43 +127,43 @@ final class LKMCPBridgeRefreshService { // MARK: - Error mapping - private func mapRefreshError(_ error: NSError) -> LKMCPBridgeErrorPayload { + private func mapRefreshError(_ error: NSError) -> MCPBridgeErrorPayload { // Two domains reach here. The window controller's own domain means // the host declined to start; `LookinErrorDomain` means the target // app failed the fetch. Keeping them apart matters to the caller: // the first is worth retrying in a moment, the second usually is // not. - typealias ReloadError = LKStaticWindowController.ReloadError + typealias ReloadError = StaticWindowController.ReloadError if error.domain == ReloadError.domain { switch error.code { case ReloadError.alreadyInProgress: - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "refresh.alreadyInProgress", message: "A hierarchy reload is already running for this target — either a user clicked reload or another refresh call is still in flight. Retry once it settles." ) case ReloadError.detailSyncInProgress: - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "refresh.detailSyncInProgress", message: "The inspector is still syncing view details. Reloading now would discard that work; wait for it to finish." ) case ReloadError.noInspectableApp: - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "refresh.notAttached", message: "The inspector window is not attached to an app. Attach a target in LookInside and try again." ) case ReloadError.windowClosed: - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "refresh.windowClosed", message: "The inspector window closed while the hierarchy was being fetched, so the result was discarded." ) case ReloadError.noResponse: - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "refresh.disconnected", message: "The target app finished the hierarchy request without returning a hierarchy. The channel may have been closed mid-request." ) default: Self.logger.error("hierarchy.refresh received unmapped host refusal \(error.code, privacy: .public)") - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "refresh.internalError", message: "The inspector declined the reload for an unexpected reason (code \(error.code))." ) @@ -174,18 +174,18 @@ final class LKMCPBridgeRefreshService { case LookinErrCode_LicenseRequired: return .licenseRequired case LookinErrCode_NoConnect: - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "refresh.disconnected", message: "The target app is no longer connected. Re-attach from the LookInside inspector and try again." ) case LookinErrCode_Timeout: - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "refresh.timeout", message: "The target app did not return its hierarchy within the request timeout. Check whether it is paused in Xcode or blocked on the main thread." ) default: Self.logger.error("hierarchy.refresh received unmapped error code \(error.code, privacy: .public): \(error.localizedDescription, privacy: .public)") - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "refresh.internalError", message: "The target app reported an unexpected error (code \(error.code))." ) @@ -194,8 +194,8 @@ final class LKMCPBridgeRefreshService { // MARK: - Encoding helper (duplicated from InspectionService) - private func encodeAsJSONValue(_ value: some Encodable) throws -> LKMCPBridgeJSONValue { + private func encodeAsJSONValue(_ value: some Encodable) throws -> MCPBridgeJSONValue { let data = try JSONEncoder().encode(value) - return try JSONDecoder().decode(LKMCPBridgeJSONValue.self, from: data) + return try JSONDecoder().decode(MCPBridgeJSONValue.self, from: data) } } diff --git a/LookInside/MCPBridge/LKMCPBridgeScreenshotService.swift b/LookInside/MCPBridge/MCPBridgeScreenshotService.swift similarity index 89% rename from LookInside/MCPBridge/LKMCPBridgeScreenshotService.swift rename to LookInside/MCPBridge/MCPBridgeScreenshotService.swift index e4bebbfc..1ed13ae5 100644 --- a/LookInside/MCPBridge/LKMCPBridgeScreenshotService.swift +++ b/LookInside/MCPBridge/MCPBridgeScreenshotService.swift @@ -1,4 +1,4 @@ -// LKMCPBridgeScreenshotService.swift +// MCPBridgeScreenshotService.swift // // Handles the `screenshot.read` bridge route: renders one display item — // either on its own (`solo`) or together with its whole subtree @@ -7,8 +7,8 @@ // Why every mode goes through RPC 203 rather than RPC 201 `App`: // RPC 201 with `needImages=YES` also carries a whole-app screenshot // (`InspectedAppInfo.screenshot`), but reaching it means driving -// `LKAppsManager.fetchAppInfos(needImages:localInfos:)`, which re-scans -// *every* Server port and rebuilds a fresh `LKInspectableApp` list +// `AppsManager.fetchAppInfos(needImages:localInfos:)`, which re-scans +// *every* Server port and rebuilds a fresh `InspectableApp` list // for all connected apps. That is a heavyweight, side-effecting // operation to perform for one picture, and the resulting screenshot // is whatever the app looked like when the scan ran. Taking a `group` @@ -22,7 +22,7 @@ // view. Those are served directly (`fromCache: true`) so repeat calls // stay cheap. On a miss the service issues RPC 203 with the matching // task type, merges the response back through -// `LKStaticHierarchyDataSource.modifyWithDisplayItemDetail:` (same +// `StaticHierarchyDataSource.modifyWithDisplayItemDetail:` (same // side-effect `details.read` relies on) and encodes the fresh image. // // Redaction: screenshots are pixels, and the host's secure-content @@ -39,7 +39,7 @@ import Foundation import os @MainActor -final class LKMCPBridgeScreenshotService { +final class MCPBridgeScreenshotService { // MARK: - Configuration /// Default cap on the longest side of the returned image, in pixels. @@ -96,7 +96,7 @@ final class LKMCPBridgeScreenshotService { // MARK: - Entry point - func handle(request: LKMCPBridgeRequest) async -> LKMCPBridgeResponse { + func handle(request: MCPBridgeRequest) async -> MCPBridgeResponse { guard request.method == "screenshot.read" else { return .failure(identifier: request.identifier, error: .unknownMethod) } @@ -110,8 +110,8 @@ final class LKMCPBridgeScreenshotService { private func handleScreenshotRead( identifier: String, - parameters: [String: LKMCPBridgeJSONValue]? - ) async -> LKMCPBridgeResponse { + parameters: [String: MCPBridgeJSONValue]? + ) async -> MCPBridgeResponse { guard let parameters, case let .string(targetIdentifier)? = parameters["targetIdentifier"] else { @@ -130,7 +130,7 @@ final class LKMCPBridgeScreenshotService { guard let parsed = ScreenshotMode(rawValue: raw) else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "screenshot.invalidMode", message: "Unsupported screenshot mode \"\(raw)\". Valid modes are \"solo\" and \"group\"." ) @@ -157,7 +157,7 @@ final class LKMCPBridgeScreenshotService { else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "screenshot.invalidPixelDimension", message: "maximumPixelDimension must be between \(Self.minimumPixelDimension) and \(Self.hardMaximumPixelDimension); received \(maximumPixelDimension)." ) @@ -165,10 +165,10 @@ final class LKMCPBridgeScreenshotService { } // Live-document lookup - guard let document = LKMCPBridgeLiveDocumentLookup.findLiveDocument(targetIdentifier: targetIdentifier) else { + guard let document = MCPBridgeLiveDocumentLookup.findLiveDocument(targetIdentifier: targetIdentifier) else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "hierarchy.targetNotFound", message: "No live inspection document found for target identifier \(targetIdentifier)." ) @@ -177,7 +177,7 @@ final class LKMCPBridgeScreenshotService { guard document.hierarchyDataSource != nil else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "hierarchy.notReady", message: "Live document has not loaded a hierarchy yet." ) @@ -185,16 +185,16 @@ final class LKMCPBridgeScreenshotService { } // Resolve which display item to capture. - let roots = LKMCPBridgeLiveDocumentLookup.topLevelDisplayItems(in: document) + let roots = MCPBridgeLiveDocumentLookup.topLevelDisplayItems(in: document) let displayItem: DisplayItem if let requestedObjectIdentifier { - guard let found = LKMCPBridgeLiveDocumentLookup.findDisplayItem( + guard let found = MCPBridgeLiveDocumentLookup.findDisplayItem( amongRoots: roots, matchingObjectIdentifier: requestedObjectIdentifier ) else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "screenshot.objectNotFound", message: "Object identifier \(requestedObjectIdentifier) is not present in this target's hierarchy. Refresh via get_hierarchy and retry." ) @@ -209,7 +209,7 @@ final class LKMCPBridgeScreenshotService { guard let keyWindowItem = roots.first(where: { $0.representedAsKeyWindow }) ?? roots.first else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "screenshot.objectNotFound", message: "This target's hierarchy has no top-level window to capture." ) @@ -218,7 +218,7 @@ final class LKMCPBridgeScreenshotService { displayItem = keyWindowItem } - let resolvedObjectIdentifier = LKMCPBridgeLiveDocumentLookup.objectIdentifierString(for: displayItem) + let resolvedObjectIdentifier = MCPBridgeLiveDocumentLookup.objectIdentifierString(for: displayItem) let containsSecureContent = Self.subtreeContainsSecureContent(rootDisplayItem: displayItem) // Fast path: the inspector UI already rendered this view, so the @@ -242,7 +242,7 @@ final class LKMCPBridgeScreenshotService { else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "screenshot.objectNotFound", message: "The resolved display item has no live object behind it; it was probably deallocated. Refresh via get_hierarchy and retry." ) @@ -258,7 +258,7 @@ final class LKMCPBridgeScreenshotService { task.attrRequest = .notNeed task.needBasisVisualInfo = false task.needSubitems = false - task.clientReadableVersion = LKHelper.lookinReadableVersion() + task.clientReadableVersion = AppHelper.lookinReadableVersion() let package = StaticAsyncUpdateTasksPackage() package.tasks = [task] @@ -276,7 +276,7 @@ final class LKMCPBridgeScreenshotService { guard let detail = matchingDetail else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "screenshot.notAvailable", message: "The target app did not return a detail for the requested object." ) @@ -285,7 +285,7 @@ final class LKMCPBridgeScreenshotService { if detail.failureCode == -1 { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "screenshot.objectNotFound", message: "The target app could not find the requested object; it may have been deallocated. Refresh via get_hierarchy and retry." ) @@ -304,7 +304,7 @@ final class LKMCPBridgeScreenshotService { // than leaving it to guess. return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "screenshot.notAvailable", message: "The target app returned no \(mode.rawValue) screenshot for this object. Some views cannot be captured in \"solo\" mode; retry with mode \"group\"." ) @@ -334,18 +334,18 @@ final class LKMCPBridgeScreenshotService { maximumPixelDimension: Int, containsSecureContent: Bool, servedFromCache: Bool - ) -> LKMCPBridgeResponse { + ) -> MCPBridgeResponse { guard let encoded = Self.encodePNG(from: image, maximumPixelDimension: maximumPixelDimension) else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "screenshot.encodingFailed", message: "The captured image could not be encoded as PNG." ) ) } - let result = LKMCPBridgeScreenshotResult( + let result = MCPBridgeScreenshotResult( objectIdentifier: objectIdentifier, mode: mode.rawValue, imageData: encoded.pngData.base64EncodedString(), @@ -355,7 +355,7 @@ final class LKMCPBridgeScreenshotService { sourcePixelWidth: encoded.sourcePixelWidth, sourcePixelHeight: encoded.sourcePixelHeight, byteCount: encoded.pngData.count, - frame: LKMCPBridgeRect(cgRect: LKMCPBridgeLiveDocumentLookup.rootSpaceFrame(for: displayItem)), + frame: MCPBridgeRect(cgRect: MCPBridgeLiveDocumentLookup.rootSpaceFrame(for: displayItem)), servedFromCache: servedFromCache, containsSecureContent: containsSecureContent ) @@ -440,7 +440,7 @@ final class LKMCPBridgeScreenshotService { var pendingItems: [DisplayItem] = [rootDisplayItem] while pendingItems.isEmpty == false { let currentItem = pendingItems.removeFirst() - if LKMCPBridgeSecureContentDetector.isSecure(displayItem: currentItem) { + if MCPBridgeSecureContentDetector.isSecure(displayItem: currentItem) { return true } if let subitems = currentItem.subitems { @@ -450,41 +450,41 @@ final class LKMCPBridgeScreenshotService { return false } - private func mapScreenshotError(_ error: NSError) -> LKMCPBridgeErrorPayload { + private func mapScreenshotError(_ error: NSError) -> MCPBridgeErrorPayload { switch error.code { case LookinErrCode_ObjectNotFound: - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "screenshot.objectNotFound", message: "The target app could not find the requested object. It may have been deallocated; refresh via get_hierarchy and retry." ) case LookinErrCode_Inner: - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "screenshot.internalError", message: "The target app rejected the render request with a generic inner error." ) case LookinErrCode_LicenseRequired: return .licenseRequired case LookinErrCode_NoConnect: - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "screenshot.disconnected", message: "The target app is no longer connected. Re-attach from the LookInside inspector and try again." ) case LookinErrCode_Timeout: - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "screenshot.timeout", message: "The target app did not render within the request timeout. Check whether the target is paused in Xcode." ) default: Self.logger.error("screenshot.read received unmapped error code \(error.code, privacy: .public): \(error.localizedDescription, privacy: .public)") - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "screenshot.internalError", message: "The target app reported an unexpected error (code \(error.code))." ) } } - private func encodeAsJSONValue(_ value: some Encodable) throws -> LKMCPBridgeJSONValue { + private func encodeAsJSONValue(_ value: some Encodable) throws -> MCPBridgeJSONValue { let data = try JSONEncoder().encode(value) - return try JSONDecoder().decode(LKMCPBridgeJSONValue.self, from: data) + return try JSONDecoder().decode(MCPBridgeJSONValue.self, from: data) } } diff --git a/LookInside/MCPBridge/LKMCPBridgeSearchQuery.swift b/LookInside/MCPBridge/MCPBridgeSearchQuery.swift similarity index 96% rename from LookInside/MCPBridge/LKMCPBridgeSearchQuery.swift rename to LookInside/MCPBridge/MCPBridgeSearchQuery.swift index e1df458e..21bdf719 100644 --- a/LookInside/MCPBridge/LKMCPBridgeSearchQuery.swift +++ b/LookInside/MCPBridge/MCPBridgeSearchQuery.swift @@ -1,4 +1,4 @@ -// LKMCPBridgeSearchQuery.swift +// MCPBridgeSearchQuery.swift // // Pure matching core behind the `hierarchy.find` bridge route. // @@ -6,9 +6,9 @@ // which fields a query looks at, and how a hit is reported back, is the // part of search whose correctness is invisible at the call site (a field // silently never matching looks exactly like "nothing in the tree matched"). -// Splitting it out lets `Tests/MCPBridge/LKMCPBridgeSearchQueryTests.swift` +// Splitting it out lets `Tests/MCPBridge/MCPBridgeSearchQueryTests.swift` // compile it standalone under the host repo's `swiftc`-single-binary test -// pattern, the same reason `LKMCPBridgeListenSocket` was split out. +// pattern, the same reason `MCPBridgeListenSocket` was split out. // // Matching is case-insensitive substring containment. That is intentionally // dumber than the host inspector's own search: an agent issues a query it @@ -18,7 +18,7 @@ import Foundation -struct LKMCPBridgeSearchQuery: Sendable { +struct MCPBridgeSearchQuery: Sendable { // MARK: - Fields /// The searchable projections of a hierarchy node. Wire names are the diff --git a/LookInside/MCPBridge/LKMCPBridgeSearchService.swift b/LookInside/MCPBridge/MCPBridgeSearchService.swift similarity index 82% rename from LookInside/MCPBridge/LKMCPBridgeSearchService.swift rename to LookInside/MCPBridge/MCPBridgeSearchService.swift index 4bef81dc..cee93aa0 100644 --- a/LookInside/MCPBridge/LKMCPBridgeSearchService.swift +++ b/LookInside/MCPBridge/MCPBridgeSearchService.swift @@ -1,4 +1,4 @@ -// LKMCPBridgeSearchService.swift +// MCPBridgeSearchService.swift // // Handles the `hierarchy.find` bridge route: locating views in an // attached target by class name, label, or memory address. @@ -17,14 +17,14 @@ // republishes the visible row list. Running it for a bridge request would // reach through the socket and rearrange the window the user is looking // at. Only the pure per-item predicate is reused in spirit, reimplemented -// over a wider field set in `LKMCPBridgeSearchQuery`. +// over a wider field set in `MCPBridgeSearchQuery`. import AppKit import Foundation import os @MainActor -final class LKMCPBridgeSearchService { +final class MCPBridgeSearchService { /// Default number of matches returned when the caller doesn't ask. /// Sized so a typical response stays well inside an agent's context /// budget while still showing enough of a broad query (say, every @@ -41,7 +41,7 @@ final class LKMCPBridgeSearchService { // MARK: - Entry point - func handle(request: LKMCPBridgeRequest) async -> LKMCPBridgeResponse { + func handle(request: MCPBridgeRequest) async -> MCPBridgeResponse { guard request.method == "hierarchy.find" else { return .failure(identifier: request.identifier, error: .unknownMethod) } @@ -55,8 +55,8 @@ final class LKMCPBridgeSearchService { private func handleHierarchyFind( identifier: String, - parameters: [String: LKMCPBridgeJSONValue]? - ) -> LKMCPBridgeResponse { + parameters: [String: MCPBridgeJSONValue]? + ) -> MCPBridgeResponse { guard let parameters = parameters, case let .string(targetIdentifier)? = parameters["targetIdentifier"], case let .string(rawQuery)? = parameters["query"] @@ -71,14 +71,14 @@ final class LKMCPBridgeSearchService { if trimmedQuery.isEmpty { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "search.emptyQuery", message: "`query` must be a non-empty search string. To list the tree instead of searching it, use hierarchy.read." ) ) } - let fields: [LKMCPBridgeSearchQuery.Field] + let fields: [MCPBridgeSearchQuery.Field] if case let .array(rawFields)? = parameters["matchFields"] { let names: [String] = rawFields.compactMap { value in if case let .string(name) = value { @@ -89,25 +89,25 @@ final class LKMCPBridgeSearchService { guard names.count == rawFields.count else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "search.invalidMatchField", message: "`matchFields` must be an array of strings. Valid values: \(Self.validFieldList)." ) ) } - guard let resolved = LKMCPBridgeSearchQuery.fields(fromWireNames: names) else { - let unrecognized = LKMCPBridgeSearchQuery.firstUnrecognizedFieldName(in: names) ?? "?" + guard let resolved = MCPBridgeSearchQuery.fields(fromWireNames: names) else { + let unrecognized = MCPBridgeSearchQuery.firstUnrecognizedFieldName(in: names) ?? "?" return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "search.invalidMatchField", message: "`\(unrecognized)` is not a searchable field. Valid values: \(Self.validFieldList)." ) ) } - fields = resolved.isEmpty ? LKMCPBridgeSearchQuery.Field.allCases : resolved + fields = resolved.isEmpty ? MCPBridgeSearchQuery.Field.allCases : resolved } else { - fields = LKMCPBridgeSearchQuery.Field.allCases + fields = MCPBridgeSearchQuery.Field.allCases } let matchLimit: Int @@ -124,7 +124,7 @@ final class LKMCPBridgeSearchService { guard matchLimit >= 1, matchLimit <= Self.maximumMatchLimit else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "search.invalidLimit", message: "`limit` must be between 1 and \(Self.maximumMatchLimit); received \(matchLimit)." ) @@ -145,10 +145,10 @@ final class LKMCPBridgeSearchService { scopeObjectIdentifier = nil } - guard let document = LKMCPBridgeLiveDocumentLookup.findLiveDocument(targetIdentifier: targetIdentifier) else { + guard let document = MCPBridgeLiveDocumentLookup.findLiveDocument(targetIdentifier: targetIdentifier) else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "hierarchy.targetNotFound", message: "No live inspection document found for target identifier \(targetIdentifier)." ) @@ -160,7 +160,7 @@ final class LKMCPBridgeSearchService { else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "hierarchy.notReady", message: "Live document has not loaded a hierarchy yet." ) @@ -169,13 +169,13 @@ final class LKMCPBridgeSearchService { let searchScope: [DisplayItem] if let scopeObjectIdentifier { - guard let scopeRoot = LKMCPBridgeLiveDocumentLookup.findDisplayItem( + guard let scopeRoot = MCPBridgeLiveDocumentLookup.findDisplayItem( amongRoots: allItems, matchingObjectIdentifier: scopeObjectIdentifier ) else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "hierarchy.objectNotFound", message: "Object identifier \(scopeObjectIdentifier) is not present in this target's hierarchy." ) @@ -188,13 +188,13 @@ final class LKMCPBridgeSearchService { searchScope = allItems } - let query = LKMCPBridgeSearchQuery(rawQuery: trimmedQuery, fields: fields) + let query = MCPBridgeSearchQuery(rawQuery: trimmedQuery, fields: fields) // The whole scope is scanned even after `limit` is reached: an // agent that only learns "here are 50" cannot tell a complete // answer from the tip of an iceberg, and the scan is a cheap // in-memory string compare over a list the host already holds. - var matches: [LKMCPBridgeSearchMatch] = [] + var matches: [MCPBridgeSearchMatch] = [] var totalMatchCount = 0 var searchedNodeCount = 0 @@ -213,7 +213,7 @@ final class LKMCPBridgeSearchService { } } - let result = LKMCPBridgeSearchResult( + let result = MCPBridgeSearchResult( matches: matches, totalMatchCount: totalMatchCount, truncated: matches.count < totalMatchCount, @@ -232,7 +232,7 @@ final class LKMCPBridgeSearchService { // MARK: - Candidate / match construction - private func makeCandidate(from item: DisplayItem) -> LKMCPBridgeSearchQuery.Candidate { + private func makeCandidate(from item: DisplayItem) -> MCPBridgeSearchQuery.Candidate { let displayingObject = item.displayingObject() let classChain = displayingObject?.classChainList ?? [] @@ -247,7 +247,7 @@ final class LKMCPBridgeSearchService { } } - return LKMCPBridgeSearchQuery.Candidate( + return MCPBridgeSearchQuery.Candidate( className: classChain.first ?? "", classChain: classChain, title: item.title(), @@ -258,19 +258,19 @@ final class LKMCPBridgeSearchService { private func makeMatch( from item: DisplayItem, - matchedFields: [LKMCPBridgeSearchQuery.Field] - ) -> LKMCPBridgeSearchMatch { + matchedFields: [MCPBridgeSearchQuery.Field] + ) -> MCPBridgeSearchMatch { // Titles and subtitles can carry app-supplied strings through the // in-app `lookin_customDebugInfos` hook, so they go through the // same redaction gate as `attributes.read`'s textual values. - let redactSecureContent = LKMCPBridgeSecureContentDetector.isSecure(displayItem: item) + let redactSecureContent = MCPBridgeSecureContentDetector.isSecure(displayItem: item) let title = redactSecureContent ? nil : item.title() let subtitle = redactSecureContent ? nil : item.subtitle() var ancestorIdentifiers: [String] = [] var ancestorTitles: [String] = [] item.enumerateAncestors { ancestor, _ in - ancestorIdentifiers.append(LKMCPBridgeLiveDocumentLookup.objectIdentifierString(for: ancestor)) + ancestorIdentifiers.append(MCPBridgeLiveDocumentLookup.objectIdentifierString(for: ancestor)) ancestorTitles.append(Self.pathComponentTitle(for: ancestor)) } // `enumerateAncestors` walks upward; the wire order is root first @@ -280,12 +280,12 @@ final class LKMCPBridgeSearchService { let pathComponents = ancestorTitles + [Self.pathComponentTitle(for: item)] - return LKMCPBridgeSearchMatch( - objectIdentifier: LKMCPBridgeLiveDocumentLookup.objectIdentifierString(for: item), + return MCPBridgeSearchMatch( + objectIdentifier: MCPBridgeLiveDocumentLookup.objectIdentifierString(for: item), className: item.displayingObject()?.classChainList?.first ?? "", title: title, subtitle: subtitle, - frame: LKMCPBridgeRect(cgRect: LKMCPBridgeLiveDocumentLookup.rootSpaceFrame(for: item)), + frame: MCPBridgeRect(cgRect: MCPBridgeLiveDocumentLookup.rootSpaceFrame(for: item)), isHidden: item.isHidden, alpha: Double(item.alpha), depth: ancestorIdentifiers.count, @@ -304,14 +304,14 @@ final class LKMCPBridgeSearchService { return className.isEmpty ? "?" : className } - private static let validFieldList: String = LKMCPBridgeSearchQuery.Field.allCases + private static let validFieldList: String = MCPBridgeSearchQuery.Field.allCases .map(\.rawValue) .joined(separator: ", ") // MARK: - Encoding helper (duplicated from InspectionService) - private func encodeAsJSONValue(_ value: some Encodable) throws -> LKMCPBridgeJSONValue { + private func encodeAsJSONValue(_ value: some Encodable) throws -> MCPBridgeJSONValue { let data = try JSONEncoder().encode(value) - return try JSONDecoder().decode(LKMCPBridgeJSONValue.self, from: data) + return try JSONDecoder().decode(MCPBridgeJSONValue.self, from: data) } } diff --git a/LookInside/MCPBridge/LKMCPBridgeSecureContentDetector.swift b/LookInside/MCPBridge/MCPBridgeSecureContentDetector.swift similarity index 96% rename from LookInside/MCPBridge/LKMCPBridgeSecureContentDetector.swift rename to LookInside/MCPBridge/MCPBridgeSecureContentDetector.swift index dd3d86dd..419820a0 100644 --- a/LookInside/MCPBridge/LKMCPBridgeSecureContentDetector.swift +++ b/LookInside/MCPBridge/MCPBridgeSecureContentDetector.swift @@ -1,4 +1,4 @@ -// LKMCPBridgeSecureContentDetector.swift +// MCPBridgeSecureContentDetector.swift // // Decides whether an inspected display item carries secure user content // (passwords, OTPs, payment fields) so callers can redact the textual @@ -24,7 +24,7 @@ import Foundation -enum LKMCPBridgeSecureContentDetector { +enum MCPBridgeSecureContentDetector { /// Returns `true` when the given display item represents a view that /// the host should treat as carrying secure user input. When `true`, /// callers must replace any user-visible text strings on the item's diff --git a/LookInside/MCPBridge/LKMCPBridgeSelectorService.swift b/LookInside/MCPBridge/MCPBridgeSelectorService.swift similarity index 89% rename from LookInside/MCPBridge/LKMCPBridgeSelectorService.swift rename to LookInside/MCPBridge/MCPBridgeSelectorService.swift index 2c5b15fb..f522b446 100644 --- a/LookInside/MCPBridge/LKMCPBridgeSelectorService.swift +++ b/LookInside/MCPBridge/MCPBridgeSelectorService.swift @@ -1,4 +1,4 @@ -// LKMCPBridgeSelectorService.swift +// MCPBridgeSelectorService.swift // // Handles the `selectors.list` bridge route: enumerating the Objective-C // methods a class in the target app responds to (RPC 213 @@ -21,7 +21,7 @@ import Foundation import os @MainActor -final class LKMCPBridgeSelectorService { +final class MCPBridgeSelectorService { /// Default cap on returned selectors. Deliberately far below the /// thousands a framework class yields: the useful answer to "what can /// I call on this" is nearly always reachable with a `nameFilter`, @@ -37,7 +37,7 @@ final class LKMCPBridgeSelectorService { // MARK: - Entry point - func handle(request: LKMCPBridgeRequest) async -> LKMCPBridgeResponse { + func handle(request: MCPBridgeRequest) async -> MCPBridgeResponse { guard request.method == "selectors.list" else { return .failure(identifier: request.identifier, error: .unknownMethod) } @@ -51,8 +51,8 @@ final class LKMCPBridgeSelectorService { private func handleSelectorsList( identifier: String, - parameters: [String: LKMCPBridgeJSONValue]? - ) async -> LKMCPBridgeResponse { + parameters: [String: MCPBridgeJSONValue]? + ) async -> MCPBridgeResponse { guard let parameters = parameters, case let .string(targetIdentifier)? = parameters["targetIdentifier"] else { @@ -76,7 +76,7 @@ final class LKMCPBridgeSelectorService { if requestedClassName == nil, requestedObjectIdentifier == nil { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "selectors.missingSubject", message: "Supply either `className` or `objectIdentifier` to name the class whose selectors you want." ) @@ -112,17 +112,17 @@ final class LKMCPBridgeSelectorService { guard selectorLimit >= 1, selectorLimit <= Self.maximumSelectorLimit else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "selectors.invalidLimit", message: "`limit` must be between 1 and \(Self.maximumSelectorLimit); received \(selectorLimit)." ) ) } - guard let document = LKMCPBridgeLiveDocumentLookup.findLiveDocument(targetIdentifier: targetIdentifier) else { + guard let document = MCPBridgeLiveDocumentLookup.findLiveDocument(targetIdentifier: targetIdentifier) else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "hierarchy.targetNotFound", message: "No live inspection document found for target identifier \(targetIdentifier)." ) @@ -138,19 +138,19 @@ final class LKMCPBridgeSelectorService { guard document.hierarchyDataSource != nil else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "hierarchy.notReady", message: "Live document has not loaded a hierarchy yet." ) ) } - guard let displayItem = LKMCPBridgeLiveDocumentLookup.findDisplayItem( - amongRoots: LKMCPBridgeLiveDocumentLookup.topLevelDisplayItems(in: document), + guard let displayItem = MCPBridgeLiveDocumentLookup.findDisplayItem( + amongRoots: MCPBridgeLiveDocumentLookup.topLevelDisplayItems(in: document), matchingObjectIdentifier: requestedObjectIdentifier ) else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "hierarchy.objectNotFound", message: "Object identifier \(requestedObjectIdentifier) is not present in this target's hierarchy." ) @@ -160,7 +160,7 @@ final class LKMCPBridgeSelectorService { guard let leafClassName = classChain.first, leafClassName.isEmpty == false else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "selectors.classNotFound", message: "Display item \(requestedObjectIdentifier) does not report a class name." ) @@ -173,7 +173,7 @@ final class LKMCPBridgeSelectorService { guard className.isEmpty == false else { return .failure( identifier: identifier, - error: LKMCPBridgeErrorPayload( + error: MCPBridgeErrorPayload( code: "selectors.missingSubject", message: "`className` must be a non-empty class name." ) @@ -215,7 +215,7 @@ final class LKMCPBridgeSelectorService { let totalCount = selectorNames.count let truncatedSelectors = Array(selectorNames.prefix(selectorLimit)) - let result = LKMCPBridgeSelectorListResult( + let result = MCPBridgeSelectorListResult( className: resolvedClassName, selectors: truncatedSelectors, totalCount: totalCount, @@ -235,30 +235,30 @@ final class LKMCPBridgeSelectorService { // MARK: - Error mapping - private func mapSelectorError(_ error: NSError, className: String) -> LKMCPBridgeErrorPayload { + private func mapSelectorError(_ error: NSError, className: String) -> MCPBridgeErrorPayload { switch error.code { case LookinErrCode_Inner: // RPC 213's only `Inner` path is a failed NSClassFromString, // so this is specific enough to name the cause outright. - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "selectors.classNotFound", message: "The target app has no class named `\(className)`. Swift types need their module prefix (for example `MyApp.ContentView`); check the `classChain` reported by hierarchy.read." ) case LookinErrCode_LicenseRequired: return .licenseRequired case LookinErrCode_NoConnect: - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "selectors.disconnected", message: "The target app is no longer connected. Re-attach from the LookInside inspector and try again." ) case LookinErrCode_Timeout: - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "selectors.timeout", message: "The target app did not respond within the request timeout. Check whether it is paused in Xcode or blocked on the main thread." ) default: Self.logger.error("selectors.list received unmapped error code \(error.code, privacy: .public): \(error.localizedDescription, privacy: .public)") - return LKMCPBridgeErrorPayload( + return MCPBridgeErrorPayload( code: "selectors.internalError", message: "The target app reported an unexpected error (code \(error.code))." ) @@ -267,8 +267,8 @@ final class LKMCPBridgeSelectorService { // MARK: - Encoding helper (duplicated from InspectionService) - private func encodeAsJSONValue(_ value: some Encodable) throws -> LKMCPBridgeJSONValue { + private func encodeAsJSONValue(_ value: some Encodable) throws -> MCPBridgeJSONValue { let data = try JSONEncoder().encode(value) - return try JSONDecoder().decode(LKMCPBridgeJSONValue.self, from: data) + return try JSONDecoder().decode(MCPBridgeJSONValue.self, from: data) } } diff --git a/LookInside/MCPBridge/LKMCPBridgeServer.swift b/LookInside/MCPBridge/MCPBridgeServer.swift similarity index 81% rename from LookInside/MCPBridge/LKMCPBridgeServer.swift rename to LookInside/MCPBridge/MCPBridgeServer.swift index 8439c182..b683a969 100644 --- a/LookInside/MCPBridge/LKMCPBridgeServer.swift +++ b/LookInside/MCPBridge/MCPBridgeServer.swift @@ -1,4 +1,4 @@ -// LKMCPBridgeServer.swift +// MCPBridgeServer.swift // // The MCPBridge server is the GPL-side surface that exposes LookInside's // inspection state over a local Unix domain socket. Proprietary consumers @@ -21,10 +21,10 @@ import Foundation import os @objc(LKMCPBridgeServer) -final class LKMCPBridgeServer: NSObject { +final class MCPBridgeServer: NSObject { // MARK: - Singleton - @objc static let sharedInstance = LKMCPBridgeServer() + @objc static let sharedInstance = MCPBridgeServer() // MARK: - Configuration @@ -39,7 +39,7 @@ final class LKMCPBridgeServer: NSObject { /// Shared parent for every connection's private serial queue. Kept /// concurrent so separate connections make progress independently; - /// each `LKMCPBridgeConnection` targets its own serial queue at this + /// each `MCPBridgeConnection` targets its own serial queue at this /// one, which is what keeps a single connection's frames from /// interleaving. Do not hand this queue to a connection as its /// working queue directly. @@ -52,59 +52,59 @@ final class LKMCPBridgeServer: NSObject { private var listenFileDescriptor: Int32 = -1 private var acceptSource: DispatchSourceRead? private var activeConnections: Set = [] - private var openConnections: [ObjectIdentifier: LKMCPBridgeConnection] = [:] + private var openConnections: [ObjectIdentifier: MCPBridgeConnection] = [:] private var isRunning = false /// Routes inspection-method requests (`targets.list`, `hierarchy.read`, /// …) to the host's per-window inspection state. Lazily constructed on /// the main actor on first use because `NSDocumentController` access /// requires main-thread isolation. - private var inspectionService: LKMCPBridgeInspectionService? + private var inspectionService: MCPBridgeInspectionService? /// Routes mutating / RPC-emitting methods (`invoke.method`). Kept /// separate from `inspectionService` so the inspection surface stays /// read-only even as new mutating verbs land; lazily constructed on /// the main actor on first use. - private var invocationService: LKMCPBridgeInvocationService? + private var invocationService: MCPBridgeInvocationService? /// Routes `attribute.modify` (RPC 204 InbuiltAttrModification). /// Kept distinct from `invocationService` so each route's setter /// lookup / value decoding code stays self-contained. - private var modificationService: LKMCPBridgeModificationService? + private var modificationService: MCPBridgeModificationService? /// Routes `details.read` (batch RPC 203 HierarchyDetails prefetch). /// Kept distinct from the read-only inspection service because /// details.read actively pumps the connection channel rather than /// reading cached state. - private var detailsService: LKMCPBridgeDetailsService? + private var detailsService: MCPBridgeDetailsService? /// Routes `screenshot.read` (RPC 203 with a Solo/Group task type). /// Separate from `detailsService` because the two ask the same RPC /// for entirely different payloads — attribute groups versus image /// bytes — and their error vocabularies differ accordingly. - private var screenshotService: LKMCPBridgeScreenshotService? + private var screenshotService: MCPBridgeScreenshotService? /// Routes `hierarchy.find`. Kept apart from `inspectionService` /// even though both only read cached state, because search owns a /// parameter vocabulary of its own (match fields, limits) and its /// own error namespace. - private var searchService: LKMCPBridgeSearchService? + private var searchService: MCPBridgeSearchService? /// Routes `selectors.list` (RPC 213 AllSelectorNames). Read-only, /// so kept out of `invocationService` even though the two serve the /// same workflow — discovering a method, then calling it. - private var selectorService: LKMCPBridgeSelectorService? + private var selectorService: MCPBridgeSelectorService? /// Routes `hierarchy.refresh` (RPC 202 Hierarchy). Kept out of the /// inspection service because refreshing round-trips to the target /// and replaces host state, which would break that service's /// "cached reads only, never emits RPC" property. - private var refreshService: LKMCPBridgeRefreshService? + private var refreshService: MCPBridgeRefreshService? /// Translates host state changes into pushed event frames. Main-actor /// isolated (every signal it watches is published there) and owned /// here so its lifetime matches the socket's. - @MainActor private static var eventPublisher: LKMCPBridgeEventPublisher? + @MainActor private static var eventPublisher: MCPBridgeEventPublisher? // MARK: - Lifecycle @@ -115,7 +115,7 @@ final class LKMCPBridgeServer: NSObject { do { try self.bindAndListen() self.isRunning = true - Self.logger.notice("MCPBridge started at \(LKMCPBridgeServer.socketURL.path, privacy: .public)") + Self.logger.notice("MCPBridge started at \(MCPBridgeServer.socketURL.path, privacy: .public)") self.startEventPublisher() } catch { Self.logger.error("MCPBridge failed to start: \(error.localizedDescription, privacy: .public)") @@ -161,7 +161,7 @@ final class LKMCPBridgeServer: NSObject { /// idea how many bridge clients are attached or what any of them care /// about, and teaching it would drag Model Context Protocol concepts /// into this GPL layer. Clients filter; the host broadcasts. - func broadcast(event: LKMCPBridgeEvent) { + func broadcast(event: MCPBridgeEvent) { stateQueue.async { [weak self] in guard let self, self.isRunning else { return } for connection in self.openConnections.values { @@ -173,8 +173,8 @@ final class LKMCPBridgeServer: NSObject { private func startEventPublisher() { Task { @MainActor in if Self.eventPublisher == nil { - Self.eventPublisher = LKMCPBridgeEventPublisher(broadcast: { event in - LKMCPBridgeServer.sharedInstance.broadcast(event: event) + Self.eventPublisher = MCPBridgeEventPublisher(broadcast: { event in + MCPBridgeServer.sharedInstance.broadcast(event: event) }) } Self.eventPublisher?.start() @@ -187,11 +187,11 @@ final class LKMCPBridgeServer: NSObject { let socketURL = Self.socketURL try ensureRuntimeDirectory(at: socketURL.deletingLastPathComponent()) - // Socket creation lives in LKMCPBridgeListenSocket so its + // Socket creation lives in MCPBridgeListenSocket so its // blocking mode — which `acceptPendingConnections()` depends on // for loop termination — can be asserted by a test that does not // need the whole inspection stack. See that file's header. - let descriptor = try LKMCPBridgeListenSocket.makeListening( + let descriptor = try MCPBridgeListenSocket.makeListening( atPath: socketURL.path, backlog: Self.listenBacklog ) @@ -210,10 +210,10 @@ final class LKMCPBridgeServer: NSObject { private func acceptPendingConnections() { while true { - // Goes through LKMCPBridgeListenSocket because the accepted + // Goes through MCPBridgeListenSocket because the accepted // descriptor has to be put back into blocking mode; see that // method's documentation. - let clientDescriptor = LKMCPBridgeListenSocket.acceptConnection( + let clientDescriptor = MCPBridgeListenSocket.acceptConnection( listenDescriptor: listenFileDescriptor ) if clientDescriptor < 0 { @@ -224,7 +224,7 @@ final class LKMCPBridgeServer: NSObject { Self.logger.error("accept() failed (errno \(errorNumber))") return } - let connection = LKMCPBridgeConnection( + let connection = MCPBridgeConnection( fileDescriptor: clientDescriptor, queue: ioQueue, requestHandler: { [weak self] request in @@ -245,7 +245,7 @@ final class LKMCPBridgeServer: NSObject { } } - private func removeConnection(_ connection: LKMCPBridgeConnection) { + private func removeConnection(_ connection: MCPBridgeConnection) { stateQueue.async { [weak self] in guard let self else { return } let key = ObjectIdentifier(connection) @@ -256,7 +256,7 @@ final class LKMCPBridgeServer: NSObject { // MARK: - Request dispatch - private func handle(request: LKMCPBridgeRequest) async -> LKMCPBridgeResponse { + private func handle(request: MCPBridgeRequest) async -> MCPBridgeResponse { // `ping` stays as a transport-level smoke test that doesn't require // the inspection state to be initialized; mutating verbs route to // the invocation service; everything else routes to the (read-only) @@ -290,96 +290,96 @@ final class LKMCPBridgeServer: NSObject { } } - private func inspectionDispatch(request: LKMCPBridgeRequest) async -> LKMCPBridgeResponse { - let service = await MainActor.run { () -> LKMCPBridgeInspectionService in + private func inspectionDispatch(request: MCPBridgeRequest) async -> MCPBridgeResponse { + let service = await MainActor.run { () -> MCPBridgeInspectionService in if let existing = self.inspectionService { return existing } - let created = LKMCPBridgeInspectionService() + let created = MCPBridgeInspectionService() self.inspectionService = created return created } return await service.handle(request: request) } - private func invocationDispatch(request: LKMCPBridgeRequest) async -> LKMCPBridgeResponse { - let service = await MainActor.run { () -> LKMCPBridgeInvocationService in + private func invocationDispatch(request: MCPBridgeRequest) async -> MCPBridgeResponse { + let service = await MainActor.run { () -> MCPBridgeInvocationService in if let existing = self.invocationService { return existing } - let created = LKMCPBridgeInvocationService() + let created = MCPBridgeInvocationService() self.invocationService = created return created } return await service.handle(request: request) } - private func modificationDispatch(request: LKMCPBridgeRequest) async -> LKMCPBridgeResponse { - let service = await MainActor.run { () -> LKMCPBridgeModificationService in + private func modificationDispatch(request: MCPBridgeRequest) async -> MCPBridgeResponse { + let service = await MainActor.run { () -> MCPBridgeModificationService in if let existing = self.modificationService { return existing } - let created = LKMCPBridgeModificationService() + let created = MCPBridgeModificationService() self.modificationService = created return created } return await service.handle(request: request) } - private func detailsDispatch(request: LKMCPBridgeRequest) async -> LKMCPBridgeResponse { - let service = await MainActor.run { () -> LKMCPBridgeDetailsService in + private func detailsDispatch(request: MCPBridgeRequest) async -> MCPBridgeResponse { + let service = await MainActor.run { () -> MCPBridgeDetailsService in if let existing = self.detailsService { return existing } - let created = LKMCPBridgeDetailsService() + let created = MCPBridgeDetailsService() self.detailsService = created return created } return await service.handle(request: request) } - private func screenshotDispatch(request: LKMCPBridgeRequest) async -> LKMCPBridgeResponse { - let service = await MainActor.run { () -> LKMCPBridgeScreenshotService in + private func screenshotDispatch(request: MCPBridgeRequest) async -> MCPBridgeResponse { + let service = await MainActor.run { () -> MCPBridgeScreenshotService in if let existing = self.screenshotService { return existing } - let created = LKMCPBridgeScreenshotService() + let created = MCPBridgeScreenshotService() self.screenshotService = created return created } return await service.handle(request: request) } - private func searchDispatch(request: LKMCPBridgeRequest) async -> LKMCPBridgeResponse { - let service = await MainActor.run { () -> LKMCPBridgeSearchService in + private func searchDispatch(request: MCPBridgeRequest) async -> MCPBridgeResponse { + let service = await MainActor.run { () -> MCPBridgeSearchService in if let existing = self.searchService { return existing } - let created = LKMCPBridgeSearchService() + let created = MCPBridgeSearchService() self.searchService = created return created } return await service.handle(request: request) } - private func selectorDispatch(request: LKMCPBridgeRequest) async -> LKMCPBridgeResponse { - let service = await MainActor.run { () -> LKMCPBridgeSelectorService in + private func selectorDispatch(request: MCPBridgeRequest) async -> MCPBridgeResponse { + let service = await MainActor.run { () -> MCPBridgeSelectorService in if let existing = self.selectorService { return existing } - let created = LKMCPBridgeSelectorService() + let created = MCPBridgeSelectorService() self.selectorService = created return created } return await service.handle(request: request) } - private func refreshDispatch(request: LKMCPBridgeRequest) async -> LKMCPBridgeResponse { - let service = await MainActor.run { () -> LKMCPBridgeRefreshService in + private func refreshDispatch(request: MCPBridgeRequest) async -> MCPBridgeResponse { + let service = await MainActor.run { () -> MCPBridgeRefreshService in if let existing = self.refreshService { return existing } - let created = LKMCPBridgeRefreshService() + let created = MCPBridgeRefreshService() self.refreshService = created return created } diff --git a/LookInside/Manager/LKHelper.swift b/LookInside/Manager/AppHelper.swift similarity index 98% rename from LookInside/Manager/LKHelper.swift rename to LookInside/Manager/AppHelper.swift index 6a25f307..2ce5a830 100644 --- a/LookInside/Manager/LKHelper.swift +++ b/LookInside/Manager/AppHelper.swift @@ -1,5 +1,5 @@ // -// LKHelper.swift +// AppHelper.swift // Lookin // // Created by Li Kai on 2018/8/4. @@ -28,10 +28,10 @@ struct HorizontalMargins { var right: CGFloat } -final class LKHelper { - private static let shared = LKHelper() +final class AppHelper { + private static let shared = AppHelper() - static func sharedInstance() -> LKHelper { + static func sharedInstance() -> AppHelper { shared } diff --git a/LookInside/Manager/LKAppMenuManager.swift b/LookInside/Manager/AppMenuManager.swift similarity index 88% rename from LookInside/Manager/LKAppMenuManager.swift rename to LookInside/Manager/AppMenuManager.swift index af60afaa..5a793ab7 100644 --- a/LookInside/Manager/LKAppMenuManager.swift +++ b/LookInside/Manager/AppMenuManager.swift @@ -1,5 +1,5 @@ // -// LKAppMenuManager.swift +// AppMenuManager.swift // LookInside // // Created by Li Kai on 2019/3/20. @@ -7,7 +7,7 @@ // // Builds the main menu and handles its commands. Window commands (reload, // zoom, export…) go to the key window's controller through -// LKAppMenuManagerDelegate and are enabled only when that controller +// AppMenuManagerDelegate and are enabled only when that controller // implements them. // @@ -18,7 +18,7 @@ import Sparkle /// the item only when the controller implements the method. @objc(LKAppMenuManagerDelegate) @MainActor -protocol LKAppMenuManagerDelegate: NSObjectProtocol { +protocol AppMenuManagerDelegate: NSObjectProtocol { @objc optional func appMenuManagerDidSelectReload() @objc optional func appMenuManagerDidSelectDimension() @objc optional func appMenuManagerDidSelectZoomIn() @@ -35,8 +35,8 @@ protocol LKAppMenuManagerDelegate: NSObjectProtocol { @objc(LKAppMenuManager) @MainActor -final class LKAppMenuManager: NSObject, NSMenuDelegate { - static let shared = LKAppMenuManager() +final class AppMenuManager: NSObject, NSMenuDelegate { + static let shared = AppMenuManager() override private init() { super.init() @@ -77,18 +77,18 @@ final class LKAppMenuManager: NSObject, NSMenuDelegate { /// The title `menuNeedsUpdate(_:)` recognizes the LookInside Pro submenu by. private static let swiftUISupportMenuTitle = "LookInside Pro" - /// The window commands: menu item tag → LKAppMenuManagerDelegate method. + /// The window commands: menu item tag → AppMenuManagerDelegate method. private static let delegatingSelectors: [Int: Selector] = [ - Tag.reload: #selector(LKAppMenuManagerDelegate.appMenuManagerDidSelectReload), - Tag.dimension: #selector(LKAppMenuManagerDelegate.appMenuManagerDidSelectDimension), - Tag.zoomIn: #selector(LKAppMenuManagerDelegate.appMenuManagerDidSelectZoomIn), - Tag.zoomOut: #selector(LKAppMenuManagerDelegate.appMenuManagerDidSelectZoomOut), - Tag.decreaseInterspace: #selector(LKAppMenuManagerDelegate.appMenuManagerDidSelectDecreaseInterspace), - Tag.increaseInterspace: #selector(LKAppMenuManagerDelegate.appMenuManagerDidSelectIncreaseInterspace), - Tag.expansion: #selector(LKAppMenuManagerDelegate.appMenuManagerDidSelectExpansionIndex(_:)), - Tag.export: #selector(LKAppMenuManagerDelegate.appMenuManagerDidSelectExport), - Tag.openInNewWindow: #selector(LKAppMenuManagerDelegate.appMenuManagerDidSelectOpenInNewWindow), - Tag.filter: #selector(LKAppMenuManagerDelegate.appMenuManagerDidSelectFilter), + Tag.reload: #selector(AppMenuManagerDelegate.appMenuManagerDidSelectReload), + Tag.dimension: #selector(AppMenuManagerDelegate.appMenuManagerDidSelectDimension), + Tag.zoomIn: #selector(AppMenuManagerDelegate.appMenuManagerDidSelectZoomIn), + Tag.zoomOut: #selector(AppMenuManagerDelegate.appMenuManagerDidSelectZoomOut), + Tag.decreaseInterspace: #selector(AppMenuManagerDelegate.appMenuManagerDidSelectDecreaseInterspace), + Tag.increaseInterspace: #selector(AppMenuManagerDelegate.appMenuManagerDidSelectIncreaseInterspace), + Tag.expansion: #selector(AppMenuManagerDelegate.appMenuManagerDidSelectExpansionIndex(_:)), + Tag.export: #selector(AppMenuManagerDelegate.appMenuManagerDidSelectExport), + Tag.openInNewWindow: #selector(AppMenuManagerDelegate.appMenuManagerDidSelectOpenInNewWindow), + Tag.filter: #selector(AppMenuManagerDelegate.appMenuManagerDidSelectFilter), ] private var recentDocumentsMenu: NSMenu? @@ -261,7 +261,7 @@ final class LKAppMenuManager: NSObject, NSMenuDelegate { private func populateSwiftUIPluginSubmenu(_ menu: NSMenu) { menu.removeAllItems() - if LKSwiftUISupportGatekeeper.sharedInstance().activationState == .activated { + if SwiftUISupportGatekeeper.sharedInstance().activationState == .activated { menu.addItem(item(NSLocalizedString("LookInside Pro License…", comment: ""), action: #selector(handleSwiftUISupportLicense), tag: Tag.swiftUISupportLicense)) menu.addItem(item(NSLocalizedString("Refresh License Status", comment: ""), action: #selector(handleRefreshSwiftUISupportLicense), tag: Tag.refreshSwiftUISupportLicense)) menu.addItem(.separator()) @@ -366,12 +366,12 @@ final class LKAppMenuManager: NSObject, NSMenuDelegate { } if menu.title == Self.swiftUISupportMenuTitle { - LKSwiftUISupportGatekeeper.sharedInstance().refreshActivationStateInBackground() + SwiftUISupportGatekeeper.sharedInstance().refreshActivationStateInBackground() populateSwiftUIPluginSubmenu(menu) return } - let windowController = LKNavigationManager.shared.currentKeyWindowController() + let windowController = NavigationManager.shared.currentKeyWindowController() for menuItem in menu.items { if let selector = Self.delegatingSelectors[menuItem.tag] { menuItem.isEnabled = windowController?.responds(to: selector) ?? false @@ -397,7 +397,7 @@ final class LKAppMenuManager: NSObject, NSMenuDelegate { assertionFailure("no window command for tag \(item.tag)") return } - guard let windowController = LKNavigationManager.shared.currentKeyWindowController(), + guard let windowController = NavigationManager.shared.currentKeyWindowController(), windowController.responds(to: selector) else { assertionFailure("the key window does not handle \(selector)") @@ -411,8 +411,8 @@ final class LKAppMenuManager: NSObject, NSMenuDelegate { assertionFailure("expansion item without an index") return } - guard let windowController = LKNavigationManager.shared.currentKeyWindowController(), - let handler = (windowController as LKAppMenuManagerDelegate).appMenuManagerDidSelectExpansionIndex + guard let windowController = NavigationManager.shared.currentKeyWindowController(), + let handler = (windowController as AppMenuManagerDelegate).appMenuManagerDidSelectExpansionIndex else { assertionFailure("the key window does not handle expansion") return @@ -430,15 +430,15 @@ final class LKAppMenuManager: NSObject, NSMenuDelegate { } @objc private func handleAbout() { - LKNavigationManager.shared.showAbout() + NavigationManager.shared.showAbout() } @objc private func handlePreferences() { - LKNavigationManager.shared.showPreference() + NavigationManager.shared.showPreference() } @objc private func handlePrivateDiscriminatorSettings() { - LKPrivateDiscriminatorSettingsWindowController.showSettingsWindow() + PrivateDiscriminatorSettingsWindowController.showSettingsWindow() } @objc private func handleCheckUpdates() { @@ -446,15 +446,15 @@ final class LKAppMenuManager: NSObject, NSMenuDelegate { } @objc private func handleActivateSwiftUISupport() { - LKSwiftUISupportGatekeeper.sharedInstance().showActivationWindow() + SwiftUISupportGatekeeper.sharedInstance().showActivationWindow() } @objc private func handleSwiftUISupportLicense() { - LKSwiftUISupportGatekeeper.sharedInstance().showLicenseWindow() + SwiftUISupportGatekeeper.sharedInstance().showLicenseWindow() } @objc private func handleRefreshSwiftUISupportLicense() { - LKSwiftUISupportGatekeeper.sharedInstance().refreshLicenseStatus() + SwiftUISupportGatekeeper.sharedInstance().refreshLicenseStatus() } @objc private func handlePurchaseSwiftUISupport() { @@ -470,39 +470,39 @@ final class LKAppMenuManager: NSObject, NSMenuDelegate { } @objc private func handleShowGitHub() { - LKHelper.openProjectGitHubRepository() + AppHelper.openProjectGitHubRepository() } @objc private func handleAcknowledgements() { - LKHelper.openProjectREADME() + AppHelper.openProjectREADME() } /// File > New Inspection… reuses the Launch window's app picker, so a /// fresh live document can be created from any state. @objc private func handleNewInspection() { - LKNavigationManager.shared.showLaunch() + NavigationManager.shared.showLaunch() } /// File > Attach to Running App… opens the running-process picker and /// injects LookInsideServer.framework into the chosen pid through the - /// privileged injector daemon (LKInjectionFlow); sheets attach to the + /// privileged injector daemon (InjectionFlow); sheets attach to the /// key window. @objc private func handleAttachToRunningApp() { - guard LKSwiftUISupportGatekeeper.sharedInstance().allowProtectedFeatureAccess(for: NSApp.keyWindow) else { + guard SwiftUISupportGatekeeper.sharedInstance().allowProtectedFeatureAccess(for: NSApp.keyWindow) else { return } - LKInjectionFlow.shared.startFromWindow(NSApp.keyWindow) + InjectionFlow.shared.startFromWindow(NSApp.keyWindow) } /// File > Attach to App on Device… asks the LookInside Injector running /// on a connected iPhone or iPad for its list of running apps and has /// *it* do the injecting — there is no daemon and no framework download /// on this side, because the device carries its own payload - /// (LKDeviceInjectionFlow). + /// (DeviceInjectionFlow). @objc private func handleAttachToAppOnDevice() { - guard LKSwiftUISupportGatekeeper.sharedInstance().allowProtectedFeatureAccess(for: NSApp.keyWindow) else { + guard SwiftUISupportGatekeeper.sharedInstance().allowProtectedFeatureAccess(for: NSApp.keyWindow) else { return } - LKDeviceInjectionFlow.shared.startFromWindow(NSApp.keyWindow) + DeviceInjectionFlow.shared.startFromWindow(NSApp.keyWindow) } } diff --git a/LookInside/Manager/LKNavigationManager.swift b/LookInside/Manager/NavigationManager.swift similarity index 77% rename from LookInside/Manager/LKNavigationManager.swift rename to LookInside/Manager/NavigationManager.swift index e121ad80..b09ff6c9 100644 --- a/LookInside/Manager/LKNavigationManager.swift +++ b/LookInside/Manager/NavigationManager.swift @@ -1,5 +1,5 @@ // -// LKNavigationManager.swift +// NavigationManager.swift // LookInside // // Created by Li Kai on 2018/11/3. @@ -13,19 +13,19 @@ import AppKit @objc(LKNavigationManager) @MainActor -final class LKNavigationManager: NSObject, NSWindowDelegate { - static let shared = LKNavigationManager() +final class NavigationManager: NSObject, NSWindowDelegate { + static let shared = NavigationManager() override private init() { super.init() } - @objc private(set) var launchWindowController: LKLaunchWindowController? + @objc private(set) var launchWindowController: LaunchWindowController? // Read by name (KVC) by the DEBUG UI snapshots. - @objc private(set) var preferenceWindowController: LKPreferenceWindowController? - @objc private(set) var aboutWindowController: LKAboutWindowController? - private var jsonWindowController: LKJSONAttributeWindowController? + @objc private(set) var preferenceWindowController: PreferenceWindowController? + @objc private(set) var aboutWindowController: AboutWindowController? + private var jsonWindowController: JSONAttributeWindowController? /// Set by the hierarchy view from its top inset. @objc var windowTitleBarHeight: CGFloat = 0 @@ -36,7 +36,7 @@ final class LKNavigationManager: NSObject, NSWindowDelegate { @objc(showLaunchAllowingAutoEnter:) func showLaunch(allowingAutoEnter allowAutoEnter: Bool) { - let controller = LKLaunchWindowController(autoEnterOnInitialReload: allowAutoEnter) + let controller = LaunchWindowController(autoEnterOnInitialReload: allowAutoEnter) launchWindowController = controller controller.showWindow(self) } @@ -48,7 +48,7 @@ final class LKNavigationManager: NSObject, NSWindowDelegate { @objc func showPreference() { let controller = preferenceWindowController ?? { - let controller = LKPreferenceWindowController() + let controller = PreferenceWindowController() controller.window?.delegate = self return controller }() @@ -58,7 +58,7 @@ final class LKNavigationManager: NSObject, NSWindowDelegate { @objc func showAbout() { let controller = aboutWindowController ?? { - let controller = LKAboutWindowController() + let controller = AboutWindowController() controller.window?.delegate = self return controller }() @@ -69,18 +69,18 @@ final class LKNavigationManager: NSObject, NSWindowDelegate { @objc(showJsonWindow:) func showJSONWindow(_ json: String?) { let controller = jsonWindowController ?? { - let controller = LKJSONAttributeWindowController() + let controller = JSONAttributeWindowController() controller.window?.delegate = self return controller }() jsonWindowController = controller - (controller.contentViewController as? LKJSONAttributeViewController)?.render(json: json) + (controller.contentViewController as? JSONAttributeViewController)?.render(json: json) controller.showWindow(self) } /// The window controller of the key window, when it is one of ours. - @objc func currentKeyWindowController() -> LKWindowController? { - NSApplication.shared.keyWindow?.windowController as? LKWindowController + @objc func currentKeyWindowController() -> WindowController? { + NSApplication.shared.keyWindow?.windowController as? WindowController } /// Opens the file through `NSDocumentController`, so `.lookin` archives @@ -97,12 +97,12 @@ final class LKNavigationManager: NSObject, NSWindowDelegate { } } - /// Wraps an in-memory hierarchy in an untitled `LookinArchiveDocument`, + /// Wraps an in-memory hierarchy in an untitled `ArchiveDocument`, /// so it gets the same document life cycle (Save As, Versions, Recent on /// save) as a file-backed archive, and shows its window. @objc(showReaderWithHierarchyFile:title:) func showReader(with file: HierarchyFile?, title: String?) { - let document = LookinArchiveDocument() + let document = ArchiveDocument() document.hierarchyFile = file NSDocumentController.shared.addDocument(document) document.makeWindowControllers() diff --git a/LookInside/Manager/LKPreferenceManager.swift b/LookInside/Manager/PreferenceManager.swift similarity index 89% rename from LookInside/Manager/LKPreferenceManager.swift rename to LookInside/Manager/PreferenceManager.swift index 636dd43b..28587f82 100644 --- a/LookInside/Manager/LKPreferenceManager.swift +++ b/LookInside/Manager/PreferenceManager.swift @@ -1,5 +1,5 @@ // -// LKPreferenceManager.swift +// PreferenceManager.swift // LookInside // // Created by Li Kai on 2019/1/8. @@ -9,7 +9,7 @@ // defaults under the original keys; other instances (the reader windows) // start from the stored values and keep their changes in memory. // -// Properties are KVO-observable; the LookinMsgAttribute ones notify their +// Properties are KVO-observable; the MessageAttribute ones notify their // subscribers instead. // @@ -32,18 +32,18 @@ let NotificationName_DidChangeSectionShowing = "NotificationName_DidChangeSectio // The raw values of these enums are stored in the user defaults; never // reorder the cases. -@objc enum LookinPreferredAppeanranceType: Int { +@objc enum PreferredAppearanceType: Int { case dark case light case system } -@objc enum LookinDoubleClickBehavior: Int { +@objc enum DoubleClickBehavior: Int { case collapse case focus } -@objc enum LookinPreferredCallStackType: Int { +@objc enum PreferredCallStackType: Int { /// Formatted and shortened. case `default` /// Formatted, complete. @@ -52,7 +52,7 @@ let NotificationName_DidChangeSectionShowing = "NotificationName_DidChangeSectio case raw } -@objc enum LookinMeasureState: Int { +@objc enum MeasureState: Int { /// Not measuring. case no /// Measuring until the key is released. @@ -62,7 +62,7 @@ let NotificationName_DidChangeSectionShowing = "NotificationName_DidChangeSectio } @objc(LKPreferenceManager) -final class LKPreferenceManager: NSObject { +final class PreferenceManager: NSObject { /// User-defaults keys. Never rename: they hold existing users' settings. private enum Key { static let previousClientVersion = "preVer" @@ -89,8 +89,8 @@ final class LKPreferenceManager: NSObject { static let rememberExpansionState = "rememberExpansionState" } - static let shared: LKPreferenceManager = { - let manager = LKPreferenceManager() + static let shared: PreferenceManager = { + let manager = PreferenceManager() manager.shouldStoreToLocal = true return manager }() @@ -102,14 +102,14 @@ final class LKPreferenceManager: NSObject { /// 默认为 NO @objc var shouldStoreToLocal = false - @objc dynamic var appearanceType: LookinPreferredAppeanranceType { + @objc dynamic var appearanceType: PreferredAppearanceType { didSet { guard oldValue != appearanceType else { return } store(appearanceType.rawValue, forKey: Key.appearanceType) } } - @objc dynamic var doubleClickBehavior: LookinDoubleClickBehavior { + @objc dynamic var doubleClickBehavior: DoubleClickBehavior { didSet { store(doubleClickBehavior.rawValue, forKey: Key.doubleClickBehavior) } @@ -125,21 +125,21 @@ final class LKPreferenceManager: NSObject { /// Not stored: the subscription in the Objective-C version targeted /// `showHiddenItems` before it existed, so changes were never written. - @objc let showOutline: LookinBOOLMsgAttribute + @objc let showOutline: BoolMessageAttribute - @objc let showHiddenItems: LookinBOOLMsgAttribute + @objc let showHiddenItems: BoolMessageAttribute /// 是否在层级树里显示系统自动创建的 LayoutGuide(safe area、layout margins 等)。 /// 默认显示;关闭只是宿主端过滤,数据仍在。用户自建 guide 不受此开关影响。 - @objc let showSystemLayoutGuides: LookinBOOLMsgAttribute + @objc let showSystemLayoutGuides: BoolMessageAttribute /// 是否显示 view 的 backing layer 子树(backing-layer-toggle 提案)。 /// 默认关闭。开启后像 Xcode 的 Show Layers:每个 view 节点下展开完整 layer 子树, /// 内容显示在真正渲染它的 layer 上,view 节点变为线框。切换时重新拉取层级。 - @objc let showBackingLayers: LookinBOOLMsgAttribute + @objc let showBackingLayers: BoolMessageAttribute /// 范围是 0 ~ 1 - @objc let zInterspace: LookinDoubleMsgAttribute + @objc let zInterspace: DoubleMessageAttribute @objc dynamic var rgbaFormat: Bool { didSet { @@ -213,9 +213,9 @@ final class LKPreferenceManager: NSObject { } } - @objc let freeRotation: LookinBOOLMsgAttribute + @objc let freeRotation: BoolMessageAttribute - @objc let fastMode: LookinBOOLMsgAttribute + @objc let fastMode: BoolMessageAttribute /// 上次接收到 iOS app 里传过来的 color config 和 collapsedClasses 信息的时间,用来统计 /// Always stored, even when `shouldStoreToLocal` is off. @@ -235,9 +235,9 @@ final class LKPreferenceManager: NSObject { // MARK: - Not stored - private var storedCallStackType: LookinPreferredCallStackType = .default + private var storedCallStackType: PreferredCallStackType = .default - @objc dynamic var callStackType: LookinPreferredCallStackType { + @objc dynamic var callStackType: PreferredCallStackType { get { storedCallStackType } set { if newValue.rawValue < 0 || newValue.rawValue > 2 { @@ -249,16 +249,16 @@ final class LKPreferenceManager: NSObject { } } - /// 参数是 LookinPreviewDimension - @objc let previewDimension: LookinIntegerMsgAttribute + /// 参数是 PreviewDimension + @objc let previewDimension: IntegerMessageAttribute - @objc let previewScale: LookinDoubleMsgAttribute + @objc let previewScale: DoubleMessageAttribute - /// 参数是 LookinMeasureState - @objc let measureState: LookinIntegerMsgAttribute + /// 参数是 MeasureState + @objc let measureState: IntegerMessageAttribute /// 是否用户正在按住 cmd 键而处于快速选择模式 - @objc let isQuickSelecting: LookinBOOLMsgAttribute + @objc let isQuickSelecting: BoolMessageAttribute // MARK: - Init @@ -267,10 +267,10 @@ final class LKPreferenceManager: NSObject { override init() { let defaults = UserDefaults.standard - previewScale = LookinDoubleMsgAttribute(double: Double(LKInitialPreviewScale)) - previewDimension = LookinIntegerMsgAttribute(integer: Int(LookinPreviewDimension.dimension3D.rawValue)) - measureState = LookinIntegerMsgAttribute(integer: LookinMeasureState.no.rawValue) - isQuickSelecting = LookinBOOLMsgAttribute(bool: false) + previewScale = DoubleMessageAttribute(double: Double(LKInitialPreviewScale)) + previewDimension = IntegerMessageAttribute(integer: Int(PreviewDimension.dimension3D.rawValue)) + measureState = IntegerMessageAttribute(integer: MeasureState.no.rawValue) + isQuickSelecting = BoolMessageAttribute(bool: false) if defaults.integer(forKey: Key.previousClientVersion) != Int(LOOKIN_CLIENT_VERSION) { defaults.set(Int(LOOKIN_CLIENT_VERSION), forKey: Key.previousClientVersion) @@ -285,23 +285,23 @@ final class LKPreferenceManager: NSObject { return fallback } - showOutline = LookinBOOLMsgAttribute(bool: number(Key.showOutline, default: true).boolValue) - showHiddenItems = LookinBOOLMsgAttribute(bool: number(Key.showHiddenItems, default: false).boolValue) - showSystemLayoutGuides = LookinBOOLMsgAttribute(bool: number(Key.showSystemLayoutGuides, default: true).boolValue) - showBackingLayers = LookinBOOLMsgAttribute(bool: number(Key.showBackingLayers, default: false).boolValue) - doubleClickBehavior = LookinDoubleClickBehavior(rawValue: number(Key.doubleClickBehavior, default: NSNumber(value: LookinDoubleClickBehavior.collapse.rawValue)).intValue) ?? .collapse + showOutline = BoolMessageAttribute(bool: number(Key.showOutline, default: true).boolValue) + showHiddenItems = BoolMessageAttribute(bool: number(Key.showHiddenItems, default: false).boolValue) + showSystemLayoutGuides = BoolMessageAttribute(bool: number(Key.showSystemLayoutGuides, default: true).boolValue) + showBackingLayers = BoolMessageAttribute(bool: number(Key.showBackingLayers, default: false).boolValue) + doubleClickBehavior = DoubleClickBehavior(rawValue: number(Key.doubleClickBehavior, default: NSNumber(value: DoubleClickBehavior.collapse.rawValue)).intValue) ?? .collapse rgbaFormat = number(Key.rgbaFormat, default: true).boolValue // 默认值为 0.22 let zInterspaceValue = number(Key.zInterspace, default: 0.22).doubleValue - zInterspace = LookinDoubleMsgAttribute(double: max(min(zInterspaceValue, Double(LookinPreviewMaxZInterspace)), Double(LookinPreviewMinZInterspace))) + zInterspace = DoubleMessageAttribute(double: max(min(zInterspaceValue, Double(LookinPreviewMaxZInterspace)), Double(LookinPreviewMinZInterspace))) - appearanceType = LookinPreferredAppeanranceType(rawValue: number(Key.appearanceType, default: NSNumber(value: LookinPreferredAppeanranceType.system.rawValue)).intValue) ?? .system + appearanceType = PreferredAppearanceType(rawValue: number(Key.appearanceType, default: NSNumber(value: PreferredAppearanceType.system.rawValue)).intValue) ?? .system expansionIndex = number(Key.expansionIndex, default: 3).intValue imageContrastLevel = number(Key.contrastLevel, default: 0).intValue syncConsoleTarget = number(Key.syncConsoleTarget, default: true).boolValue - freeRotation = LookinBOOLMsgAttribute(bool: number(Key.freeRotation, default: true).boolValue) - fastMode = LookinBOOLMsgAttribute(bool: number(Key.fastMode, default: false).boolValue) + freeRotation = BoolMessageAttribute(bool: number(Key.freeRotation, default: true).boolValue) + fastMode = BoolMessageAttribute(bool: number(Key.fastMode, default: false).boolValue) var sectionShowConfig: [String: Bool] = [:] if let stored = defaults.object(forKey: Key.sectionsShow) as? NSDictionary { @@ -420,27 +420,27 @@ final class LKPreferenceManager: NSObject { // MARK: - Attribute subscribers - @objc private func handleShowHiddenItemsChange(_ param: LookinMsgActionParams) { + @objc private func handleShowHiddenItemsChange(_ param: MessageActionParameters) { store(param.boolValue, forKey: Key.showHiddenItems) } - @objc private func handleShowSystemLayoutGuidesChange(_ param: LookinMsgActionParams) { + @objc private func handleShowSystemLayoutGuidesChange(_ param: MessageActionParameters) { store(param.boolValue, forKey: Key.showSystemLayoutGuides) } - @objc private func handleShowBackingLayersChange(_ param: LookinMsgActionParams) { + @objc private func handleShowBackingLayersChange(_ param: MessageActionParameters) { store(param.boolValue, forKey: Key.showBackingLayers) } - @objc private func handleFreeRotationDidChange(_ param: LookinMsgActionParams) { + @objc private func handleFreeRotationDidChange(_ param: MessageActionParameters) { store(param.boolValue, forKey: Key.freeRotation) } - @objc private func handleFastModeDidChange(_ param: LookinMsgActionParams) { + @objc private func handleFastModeDidChange(_ param: MessageActionParameters) { store(param.boolValue, forKey: Key.fastMode) } - @objc private func handleZInterspaceDidChange(_ param: LookinMsgActionParams) { + @objc private func handleZInterspaceDidChange(_ param: MessageActionParameters) { store(param.doubleValue, forKey: Key.zInterspace) } diff --git a/LookInside/Measure/LKMeasureController.swift b/LookInside/Measure/MeasureController.swift similarity index 89% rename from LookInside/Measure/LKMeasureController.swift rename to LookInside/Measure/MeasureController.swift index 2561967f..a9c3976d 100644 --- a/LookInside/Measure/LKMeasureController.swift +++ b/LookInside/Measure/MeasureController.swift @@ -1,5 +1,5 @@ // -// LKMeasureController.swift +// MeasureController.swift // LookInside // // The Measure panel: while measuring, it shows the distances between the @@ -11,21 +11,21 @@ import AppKit import LookInsideHostCore @objc(LKMeasureController) -final class LKMeasureController: LKBaseViewController { +final class MeasureController: BaseViewController { private static let placeholderInsets = NSEdgeInsets(top: 15, left: 5, bottom: 12, right: 5) - private let dataSource: LKHierarchyDataSource - private let placeholderView = LKBaseView() + private let dataSource: HierarchyDataSource + private let placeholderView = BaseView() private let placeholderImageView = NSImageView() - private let placeholderTitleLabel = LKLabel() - private let placeholderSubtitleLabel = LKLabel() - private let resultView = LKMeasureResultView() - private var shortcutLabel: LKLabel? + private let placeholderTitleLabel = TextLabel() + private let placeholderSubtitleLabel = TextLabel() + private let resultView = MeasureResultView() + private var shortcutLabel: TextLabel? private var lockSwitchButton: NSButton? private var itemObservations: [NSKeyValueObservation] = [] @objc(initWithDataSource:) - init(dataSource: LKHierarchyDataSource) { + init(dataSource: HierarchyDataSource) { self.dataSource = dataSource super.init(containerView: nil) @@ -67,7 +67,7 @@ final class LKMeasureController: LKBaseViewController { override func viewDidLayout() { super.viewDidLayout() - let titleHeight = LKNavigationManager.shared.windowTitleBarHeight + let titleHeight = NavigationManager.shared.windowTitleBarHeight var contentView: NSView? if placeholderView.isVisible { @@ -98,10 +98,10 @@ final class LKMeasureController: LKBaseViewController { } } - @objc private func measureStateDidChange(_ params: LookinMsgActionParams) { + @objc private func measureStateDidChange(_ params: MessageActionParameters) { shortcutLabel?.isHidden = true - switch LookinMeasureState(rawValue: params.integerValue) { + switch MeasureState(rawValue: params.integerValue) { case .no: lockSwitchButton?.isHidden = true lockSwitchButton?.state = .off @@ -131,8 +131,8 @@ final class LKMeasureController: LKBaseViewController { return button } - private func makeShortcutLabel() -> LKLabel { - let label = LKLabel() + private func makeShortcutLabel() -> TextLabel { + let label = TextLabel() label.stringValue = NSLocalizedString("shortcut: holding \"option\" key", comment: "") label.textColor = .secondaryLabelColor view.addSubview(label) @@ -141,8 +141,8 @@ final class LKMeasureController: LKBaseViewController { } private func reRender() { - let measureState: LookinIntegerMsgAttribute = dataSource.preferenceManager().measureState - guard measureState.currentIntegerValue != LookinMeasureState.no.rawValue, + let measureState: IntegerMessageAttribute = dataSource.preferenceManager().measureState + guard measureState.currentIntegerValue != MeasureState.no.rawValue, let selectedItem = dataSource.selectedItem else { return } @@ -222,7 +222,7 @@ final class LKMeasureController: LKBaseViewController { @objc private func handleLockSwitchButton() { guard let lockSwitchButton else { return } - let state: LookinMeasureState = lockSwitchButton.state == .on ? .unlocked : .locked + let state: MeasureState = lockSwitchButton.state == .on ? .unlocked : .locked dataSource.preferenceManager().measureState.setIntegerValue(state.rawValue, ignoreSubscriber: self) } } diff --git a/LookInside/Measure/LKMeasureResultView.swift b/LookInside/Measure/MeasureResultView.swift similarity index 95% rename from LookInside/Measure/LKMeasureResultView.swift rename to LookInside/Measure/MeasureResultView.swift index c64ea17d..420ef29c 100644 --- a/LookInside/Measure/LKMeasureResultView.swift +++ b/LookInside/Measure/MeasureResultView.swift @@ -1,5 +1,5 @@ // -// LKMeasureResultView.swift +// MeasureResultView.swift // LookInside // // Draws the two measured items scaled into the Measure panel, with blue @@ -9,7 +9,7 @@ import AppKit import LookInsideHostCore -final class LKMeasureResultView: LKBaseView { +final class MeasureResultView: BaseView { private static let horizontalInset: CGFloat = 20 private static let verticalInset: CGFloat = 20 private static let labelHeight: CGFloat = 18 @@ -18,15 +18,15 @@ final class LKMeasureResultView: LKBaseView { private static let horizontalColor = NSColor(red: 10 / 255.0, green: 127 / 255.0, blue: 251 / 255.0, alpha: 1) private static let verticalColor = NSColor(red: 209 / 255.0, green: 120 / 255.0, blue: 0, alpha: 1) - private let contentView = LKBaseView() + private let contentView = BaseView() private let mainImageView = NSImageView() private let referImageView = NSImageView() - private let linesContainerView = LKBaseView() + private let linesContainerView = BaseView() private let horizontalLinesLayer = CAShapeLayer() private let verticalLinesLayer = CAShapeLayer() private let mainImageViewBorderLayer = CALayer() private let referImageViewBorderLayer = CALayer() - private var labelViews: [LKTextFieldView] = [] + private var labelViews: [TextFieldView] = [] private var originalMainFrame: CGRect = .zero private var originalReferFrame: CGRect = .zero @@ -110,7 +110,7 @@ final class LKMeasureResultView: LKBaseView { let maxContentWidth = MeasureViewWidth - Self.horizontalInset * 2 let windowHeight = window?.frame.height ?? 0 - let titleBarHeight = LKNavigationManager.shared.windowTitleBarHeight + let titleBarHeight = NavigationManager.shared.windowTitleBarHeight let maxContentHeight = max((windowHeight - titleBarHeight) * 0.8, 200) let factor = MeasureGuides.scaleFactor(main: mainRect, refer: referRect, maxWidth: maxContentWidth, maxHeight: maxContentHeight) @@ -200,12 +200,12 @@ final class LKMeasureResultView: LKBaseView { return NSSize(width: MeasureViewWidth, height: height + Self.verticalInset * 2) } - private func dequeueLabelView() -> LKTextFieldView { + private func dequeueLabelView() -> TextFieldView { if let hidden = labelViews.first(where: { $0.isHidden }) { hidden.isHidden = false return hidden } - let labelView = LKTextFieldView.label() + let labelView = TextFieldView.label() labelView.insets = NSEdgeInsets(top: 0, left: 3, bottom: 0, right: 3) labelView.textField.textColor = .white labelView.textField.font = .systemFont(ofSize: 13) diff --git a/LookInside/Other/LKVersionComparer.swift b/LookInside/Other/VersionComparer.swift similarity index 94% rename from LookInside/Other/LKVersionComparer.swift rename to LookInside/Other/VersionComparer.swift index 878262c4..0c65d9af 100644 --- a/LookInside/Other/LKVersionComparer.swift +++ b/LookInside/Other/VersionComparer.swift @@ -1,5 +1,5 @@ // -// LKVersionComparer.swift +// VersionComparer.swift // LookInside // // Created by likai.123 on 2023/10/30. @@ -10,7 +10,7 @@ import Foundation import LookInsideHostCore @objc(LKVersionComparer) -final class LKVersionComparer: NSObject { +final class VersionComparer: NSObject { /// latest 指网上最高的 LookinServer 版本号,user 指用户真实的版本号。如果用户版本号低于最高版本号,则该方法返回 NO,此时应该提示用户升级。 @objc(compareWithNewest:user:) static func compare(newest latest: String?, user: String?) -> Bool { diff --git a/LookInside/Preference/LKPreferenceView.swift b/LookInside/Preference/LKPreferenceView.swift index 09cf086e..9969a1f7 100644 --- a/LookInside/Preference/LKPreferenceView.swift +++ b/LookInside/Preference/LKPreferenceView.swift @@ -2,14 +2,14 @@ import AppKit import SwiftUI @objc(LKPreferenceHostingController) -public final class LKPreferenceHostingController: NSViewController { +public final class PreferenceHostingController: NSViewController { override public func loadView() { - view = NSHostingView(rootView: LKPreferenceRootView()) + view = NSHostingView(rootView: PreferenceRootView()) } } -private struct LKPreferenceRootView: View { - @StateObject private var model = LKPreferenceViewModel() +private struct PreferenceRootView: View { + @StateObject private var model = PreferenceViewModel() var body: some View { VStack(spacing: 0) { @@ -214,7 +214,7 @@ private struct TimeoutEditor: View { /// Stays an ObservableObject: as an @Observable model the segmented pickers /// laid out narrower than before (the ui-snapshots preferences scene). @MainActor -private final class LKPreferenceViewModel: ObservableObject { +private final class PreferenceViewModel: ObservableObject { @Published private var appearanceType: Int @Published private var colorFormat: Int @Published private var imageContrast: Int @@ -226,9 +226,9 @@ private final class LKPreferenceViewModel: ObservableObject { @Published private var licenseTimeout: Double #endif - private let manager: LKPreferenceManager + private let manager: PreferenceManager - init(manager: LKPreferenceManager = LKPreferenceManager.shared) { + init(manager: PreferenceManager = PreferenceManager.shared) { self.manager = manager appearanceType = manager.appearanceType.rawValue colorFormat = manager.rgbaFormat ? 0 : 1 @@ -312,23 +312,23 @@ private final class LKPreferenceViewModel: ObservableObject { } func reset() { - setAppearanceType(LookinPreferredAppeanranceType.system.rawValue) + setAppearanceType(PreferredAppearanceType.system.rawValue) setColorFormat(0) setImageContrast(0) - setDoubleClickBehavior(LookinDoubleClickBehavior.collapse.rawValue) + setDoubleClickBehavior(DoubleClickBehavior.collapse.rawValue) setRememberExpansionState(true) setHierarchyTimeout(LKDefaultHierarchyRequestTimeoutInterval) setLicenseTimeoutIfAvailable(LKDefaultLicenseHandshakeTimeoutInterval) #if DEBUG - LKMessageManager.sharedInstance().reset() + MessageManager.sharedInstance().reset() manager.reset() UserDefaults.standard.removeObject(forKey: "IgnoreFastModeTips") #endif } private func setAppearanceType(_ rawValue: Int) { - guard let type = LookinPreferredAppeanranceType(rawValue: rawValue) else { + guard let type = PreferredAppearanceType(rawValue: rawValue) else { return } appearanceType = rawValue @@ -347,7 +347,7 @@ private final class LKPreferenceViewModel: ObservableObject { } private func setDoubleClickBehavior(_ rawValue: Int) { - guard let behavior = LookinDoubleClickBehavior(rawValue: rawValue) else { + guard let behavior = DoubleClickBehavior(rawValue: rawValue) else { return } doubleClickBehavior = rawValue diff --git a/LookInside/Preference/LKPreferenceWindowController.swift b/LookInside/Preference/PreferenceWindowController.swift similarity index 79% rename from LookInside/Preference/LKPreferenceWindowController.swift rename to LookInside/Preference/PreferenceWindowController.swift index 259d05de..9161f8d3 100644 --- a/LookInside/Preference/LKPreferenceWindowController.swift +++ b/LookInside/Preference/PreferenceWindowController.swift @@ -1,22 +1,22 @@ // -// LKPreferenceWindowController.swift +// PreferenceWindowController.swift // LookInside // // The Preferences window. Its content is the SwiftUI preference form -// (LKPreferenceView.swift) hosted inside an LKBaseViewController. +// (LKPreferenceView.swift) hosted inside an BaseViewController. // import AppKit @objc(LKPreferenceWindowController) -final class LKPreferenceWindowController: LKWindowController { +final class PreferenceWindowController: WindowController { @objc init() { #if DEBUG let windowHeight: CGFloat = 520 #else let windowHeight: CGFloat = 455 #endif - let window = LKWindow(contentRect: NSRect(x: 0, y: 0, width: 660, height: windowHeight), + let window = AppWindow(contentRect: NSRect(x: 0, y: 0, width: 660, height: windowHeight), styleMask: [.titled, .closable, .miniaturizable], backing: .buffered, defer: true) window.isMovableByWindowBackground = true @@ -25,7 +25,7 @@ final class LKPreferenceWindowController: LKWindowController { window.center() super.init(window: window) - let viewController = LKPreferenceViewController() + let viewController = PreferenceViewController() window.contentView = viewController.view contentViewController = viewController } @@ -37,7 +37,7 @@ final class LKPreferenceWindowController: LKWindowController { } @objc(LKPreferenceViewController) -final class LKPreferenceViewController: LKBaseViewController { +final class PreferenceViewController: BaseViewController { init() { super.init(containerView: nil) installPreferenceForm() @@ -49,7 +49,7 @@ final class LKPreferenceViewController: LKBaseViewController { } private func installPreferenceForm() { - let hostingController = LKPreferenceHostingController() + let hostingController = PreferenceHostingController() addChild(hostingController) let hostedView = hostingController.view hostedView.translatesAutoresizingMaskIntoConstraints = false diff --git a/LookInside/PrivateDiscriminator/LKPrivateDiscriminatorSettingsWindowController.swift b/LookInside/PrivateDiscriminator/PrivateDiscriminatorSettingsWindowController.swift similarity index 96% rename from LookInside/PrivateDiscriminator/LKPrivateDiscriminatorSettingsWindowController.swift rename to LookInside/PrivateDiscriminator/PrivateDiscriminatorSettingsWindowController.swift index a8ea889e..871d9fdc 100644 --- a/LookInside/PrivateDiscriminator/LKPrivateDiscriminatorSettingsWindowController.swift +++ b/LookInside/PrivateDiscriminator/PrivateDiscriminatorSettingsWindowController.swift @@ -2,8 +2,8 @@ import AppKit import SwiftUI @objc(LKPrivateDiscriminatorSettingsWindowController) -final class LKPrivateDiscriminatorSettingsWindowController: NSWindowController { - private static let sharedController = LKPrivateDiscriminatorSettingsWindowController() +final class PrivateDiscriminatorSettingsWindowController: NSWindowController { + private static let sharedController = PrivateDiscriminatorSettingsWindowController() @objc(showSettingsWindow) static func showSettingsWindow() { @@ -23,7 +23,7 @@ final class LKPrivateDiscriminatorSettingsWindowController: NSWindowController { window.titlebarAppearsTransparent = true window.isReleasedWhenClosed = false window.minSize = NSSize(width: 640, height: 520) - window.contentViewController = NSHostingController(rootView: LKPrivateDiscriminatorSettingsRootView()) + window.contentViewController = NSHostingController(rootView: PrivateDiscriminatorSettingsRootView()) window.center() super.init(window: window) } @@ -34,8 +34,8 @@ final class LKPrivateDiscriminatorSettingsWindowController: NSWindowController { } } -private struct LKPrivateDiscriminatorSettingsRootView: View { - private var store = LKPrivateDiscriminatorStore.shared +private struct PrivateDiscriminatorSettingsRootView: View { + private var store = PrivateDiscriminatorStore.shared @State private var importError: String? var body: some View { @@ -299,8 +299,8 @@ private struct SettingsDivider: View { } private struct ModuleStatusRow: View { - let status: LKPrivateDiscriminatorModuleStatus - let store: LKPrivateDiscriminatorStore + let status: PrivateDiscriminatorModuleStatus + let store: PrivateDiscriminatorStore let onError: (String) -> Void var body: some View { diff --git a/LookInside/PrivateDiscriminator/LKPrivateDiscriminatorStore.swift b/LookInside/PrivateDiscriminator/PrivateDiscriminatorStore.swift similarity index 96% rename from LookInside/PrivateDiscriminator/LKPrivateDiscriminatorStore.swift rename to LookInside/PrivateDiscriminator/PrivateDiscriminatorStore.swift index 0442622f..56f6cf41 100644 --- a/LookInside/PrivateDiscriminator/LKPrivateDiscriminatorStore.swift +++ b/LookInside/PrivateDiscriminator/PrivateDiscriminatorStore.swift @@ -3,7 +3,7 @@ import Foundation import LookInsidePrivateDiscriminator import Observation -struct LKPrivateDiscriminatorModuleStatus: Identifiable, Hashable { +struct PrivateDiscriminatorModuleStatus: Identifiable, Hashable { let module: String let isEnabled: Bool let importedCSVPath: String? @@ -50,7 +50,7 @@ struct LKPrivateDiscriminatorModuleStatus: Identifiable, Hashable { } } -struct LKPrivateDiscriminatorInvalidDiagnostic: Identifiable, Hashable { +struct PrivateDiscriminatorInvalidDiagnostic: Identifiable, Hashable { let module: String let source: String let message: String @@ -64,13 +64,13 @@ struct LKPrivateDiscriminatorInvalidDiagnostic: Identifiable, Hashable { /// observes the state below through Observation. @objc(LKPrivateDiscriminatorStore) @Observable -final class LKPrivateDiscriminatorStore: NSObject { - @objc(shared) static let shared = LKPrivateDiscriminatorStore() +final class PrivateDiscriminatorStore: NSObject { + @objc(shared) static let shared = PrivateDiscriminatorStore() private(set) var featureEnabled = false private(set) var autosaveEnabled = false - private(set) var moduleStatuses: [LKPrivateDiscriminatorModuleStatus] = [] - private(set) var invalidDiagnostics: [LKPrivateDiscriminatorInvalidDiagnostic] = [] + private(set) var moduleStatuses: [PrivateDiscriminatorModuleStatus] = [] + private(set) var invalidDiagnostics: [PrivateDiscriminatorInvalidDiagnostic] = [] private(set) var lastSettingsError: String? private(set) var isUpdatingDefaultLibrary = false private(set) var lastDefaultLibraryUpdateMessage: String? @@ -186,7 +186,7 @@ final class LKPrivateDiscriminatorStore: NSObject { func importModule(named module: String, from folderURL: URL) throws { let trimmedModule = module.trimmingCharacters(in: .whitespacesAndNewlines) guard PrivateDiscriminatorModuleIndex.isValidModuleName(trimmedModule) else { - throw LKPrivateDiscriminatorStoreError.invalidModuleName(trimmedModule) + throw PrivateDiscriminatorStoreError.invalidModuleName(trimmedModule) } try ensureStorageDirectories() @@ -217,7 +217,7 @@ final class LKPrivateDiscriminatorStore: NSObject { func reimportModule(_ module: String) throws { guard let path = configuration.importSources[module], !path.isEmpty else { - throw LKPrivateDiscriminatorStoreError.missingImportSource(module) + throw PrivateDiscriminatorStoreError.missingImportSource(module) } try importModule(named: module, from: URL(fileURLWithPath: path, isDirectory: true)) } @@ -285,13 +285,13 @@ final class LKPrivateDiscriminatorStore: NSObject { func submitPrivateDiscriminator(for item: DisplayItem, module: String, filename: String, error: NSErrorPointer) -> Bool { do { guard let parsed = parsedPrivateDiscriminator(for: item) else { - throw LKPrivateDiscriminatorStoreError.missingPrivateDiscriminator + throw PrivateDiscriminatorStoreError.missingPrivateDiscriminator } let trimmedModule = module.trimmingCharacters(in: .whitespacesAndNewlines) let trimmedFilename = filename.trimmingCharacters(in: .whitespacesAndNewlines) let verification = verificationCache.verify(id: parsed.id, module: trimmedModule, filename: trimmedFilename) guard verification.isMatch else { - throw LKPrivateDiscriminatorStoreError.verificationFailed(Self.message(for: verification)) + throw PrivateDiscriminatorStoreError.verificationFailed(Self.message(for: verification)) } try saveRecord( @@ -311,7 +311,7 @@ final class LKPrivateDiscriminatorStore: NSObject { func importPrivateDiscriminatorFromCodebase(for item: DisplayItem, window: NSWindow?, error: NSErrorPointer) -> Bool { do { guard let parsed = parsedPrivateDiscriminator(for: item) else { - throw LKPrivateDiscriminatorStoreError.missingPrivateDiscriminator + throw PrivateDiscriminatorStoreError.missingPrivateDiscriminator } guard let module = promptForModuleName(defaultModule: parsed.moduleHint, window: window) else { return false @@ -453,7 +453,7 @@ final class LKPrivateDiscriminatorStore: NSObject { private func rebuildIndexes() { loadedIndexesByModule = [:] var builders: [String: ModuleStatusBuilder] = [:] - var diagnostics: [LKPrivateDiscriminatorInvalidDiagnostic] = [] + var diagnostics: [PrivateDiscriminatorInvalidDiagnostic] = [] for (module, sourcePath) in configuration.importSources { builders[module, default: ModuleStatusBuilder(module: module)].sourceFolderPath = sourcePath @@ -514,7 +514,7 @@ final class LKPrivateDiscriminatorStore: NSObject { source: LoadedModuleIndex.Source, path: String, builders: inout [String: ModuleStatusBuilder], - diagnostics: inout [LKPrivateDiscriminatorInvalidDiagnostic] + diagnostics: inout [PrivateDiscriminatorInvalidDiagnostic] ) { do { let text = try String(contentsOf: URL(fileURLWithPath: path), encoding: .utf8) @@ -529,7 +529,7 @@ final class LKPrivateDiscriminatorStore: NSObject { break } } catch { - let diagnostic = LKPrivateDiscriminatorInvalidDiagnostic( + let diagnostic = PrivateDiscriminatorInvalidDiagnostic( module: module, source: source.rawValue, message: String(describing: error) @@ -582,7 +582,7 @@ final class LKPrivateDiscriminatorStore: NSObject { defer { semaphore.signal() } if let error { - capturedError = LKPrivateDiscriminatorStoreError.defaultLibraryDownloadFailed( + capturedError = PrivateDiscriminatorStoreError.defaultLibraryDownloadFailed( module.name, error.localizedDescription ) @@ -590,7 +590,7 @@ final class LKPrivateDiscriminatorStore: NSObject { } guard let httpResponse = response as? HTTPURLResponse else { - capturedError = LKPrivateDiscriminatorStoreError.defaultLibraryDownloadFailed( + capturedError = PrivateDiscriminatorStoreError.defaultLibraryDownloadFailed( module.name, NSLocalizedString("No response received.", comment: "") ) @@ -598,7 +598,7 @@ final class LKPrivateDiscriminatorStore: NSObject { } guard (200 ... 299).contains(httpResponse.statusCode) else { - capturedError = LKPrivateDiscriminatorStoreError.defaultLibraryDownloadFailed( + capturedError = PrivateDiscriminatorStoreError.defaultLibraryDownloadFailed( module.name, "HTTP \(httpResponse.statusCode)" ) @@ -606,7 +606,7 @@ final class LKPrivateDiscriminatorStore: NSObject { } guard let data, !data.isEmpty else { - capturedError = LKPrivateDiscriminatorStoreError.defaultLibraryDownloadFailed( + capturedError = PrivateDiscriminatorStoreError.defaultLibraryDownloadFailed( module.name, NSLocalizedString("Empty download payload.", comment: "") ) @@ -623,7 +623,7 @@ final class LKPrivateDiscriminatorStore: NSObject { } guard let capturedData, let text = String(data: capturedData, encoding: .utf8) else { - throw LKPrivateDiscriminatorStoreError.defaultLibraryDownloadFailed( + throw PrivateDiscriminatorStoreError.defaultLibraryDownloadFailed( module.name, NSLocalizedString("Unable to decode CSV as UTF-8.", comment: "") ) @@ -646,7 +646,7 @@ final class LKPrivateDiscriminatorStore: NSObject { includingPropertiesForKeys: [.isRegularFileKey], options: [.skipsHiddenFiles, .skipsPackageDescendants] ) else { - throw LKPrivateDiscriminatorStoreError.unreadableFolder(folderURL.path) + throw PrivateDiscriminatorStoreError.unreadableFolder(folderURL.path) } var filenames: Set = [] @@ -839,15 +839,15 @@ final class LKPrivateDiscriminatorStore: NSObject { if let rawName = object.rawClassName(), !rawName.isEmpty { append(rawName) - append(LKSwiftDemangler.completedParse(input: rawName)) - append(LKSwiftDemangler.simpleParse(input: rawName)) + append(SwiftDemangler.completedParse(input: rawName)) + append(SwiftDemangler.simpleParse(input: rawName)) } append(object.specialTrace) for className in object.classChainList ?? [] { append(className) - append(LKSwiftDemangler.completedParse(input: className)) - append(LKSwiftDemangler.simpleParse(input: className)) + append(SwiftDemangler.completedParse(input: className)) + append(SwiftDemangler.simpleParse(input: className)) } } @@ -868,7 +868,7 @@ final class LKPrivateDiscriminatorStore: NSObject { attribute.identifier = Self.dashboardAttributeIdentifier attribute.displayTitle = NSLocalizedString("Discriminator Details", comment: "") attribute.attrType = .customObj - attribute.value = LKPrivateDiscriminatorDashboardPayload(descriptor: descriptor) + attribute.value = PrivateDiscriminatorDashboardPayload(descriptor: descriptor) attribute.targetDisplayItem = item let section = AttributesSection() @@ -1385,7 +1385,7 @@ private enum GuessState { } @objc(LKPrivateDiscriminatorDashboardPayload) -final class LKPrivateDiscriminatorDashboardPayload: NSObject { +final class PrivateDiscriminatorDashboardPayload: NSObject { @objc let discriminatorID: String @objc let module: String @objc let filename: String @@ -1423,8 +1423,8 @@ private struct ModuleStatusBuilder { var autosavedRecordCount: Int? var diagnostics: [String] = [] - func status(disabledModules: Set) -> LKPrivateDiscriminatorModuleStatus { - LKPrivateDiscriminatorModuleStatus( + func status(disabledModules: Set) -> PrivateDiscriminatorModuleStatus { + PrivateDiscriminatorModuleStatus( module: module, isEnabled: !disabledModules.contains(module), importedCSVPath: importedCSVPath, @@ -1437,7 +1437,7 @@ private struct ModuleStatusBuilder { } } -private enum LKPrivateDiscriminatorStoreError: LocalizedError { +private enum PrivateDiscriminatorStoreError: LocalizedError { case invalidModuleName(String) case unreadableFolder(String) case missingImportSource(String) diff --git a/LookInside/Read/LookinArchiveCoding.swift b/LookInside/Read/ArchiveCoding.swift similarity index 94% rename from LookInside/Read/LookinArchiveCoding.swift rename to LookInside/Read/ArchiveCoding.swift index b06cd0e6..5deb2dba 100644 --- a/LookInside/Read/LookinArchiveCoding.swift +++ b/LookInside/Read/ArchiveCoding.swift @@ -1,5 +1,5 @@ // -// LookinArchiveCoding.swift +// ArchiveCoding.swift // LookInside // // Turns a `HierarchyFile` into the bytes of a `.lookin` file and back. @@ -11,8 +11,8 @@ import Foundation -enum LookinArchiveCoding { - /// The document type `LookinArchiveDocument` reads and writes. +enum ArchiveCoding { + /// The document type `ArchiveDocument` reads and writes. static let typeIdentifier = "com.lookin.lookin" /// Archives `file` with secure coding, as the Objective-C reader did. diff --git a/LookInside/Read/LookinArchiveDocument.swift b/LookInside/Read/ArchiveDocument.swift similarity index 81% rename from LookInside/Read/LookinArchiveDocument.swift rename to LookInside/Read/ArchiveDocument.swift index 73dc5a1a..51540405 100644 --- a/LookInside/Read/LookinArchiveDocument.swift +++ b/LookInside/Read/ArchiveDocument.swift @@ -1,5 +1,5 @@ // -// LookinArchiveDocument.swift +// ArchiveDocument.swift // LookInside // // The NSDocument for a `.lookin` hierarchy archive. Archives are read-only @@ -12,7 +12,7 @@ import AppKit @objc(LookinArchiveDocument) -class LookinArchiveDocument: NSDocument { +class ArchiveDocument: NSDocument { /// The archive's hierarchy. The window controller observes it (KVO) and /// builds a reader for every file assigned. @objc dynamic var hierarchyFile: HierarchyFile? @@ -35,7 +35,7 @@ class LookinArchiveDocument: NSDocument { } override func makeWindowControllers() { - addWindowController(LKReadWindowController(document: self)) + addWindowController(ReadWindowController(document: self)) } /// Whether the document can rebuild `hierarchyFile` for a different @@ -57,15 +57,15 @@ class LookinArchiveDocument: NSDocument { override func data(ofType typeName: String) throws -> Data { guard let hierarchyFile else { assertionFailure("No hierarchy to save") - throw LookinArchiveCoding.innerError + throw ArchiveCoding.innerError } - guard typeName == LookinArchiveCoding.typeIdentifier else { - throw LookinArchiveCoding.innerError + guard typeName == ArchiveCoding.typeIdentifier else { + throw ArchiveCoding.innerError } - return try LookinArchiveCoding.data(of: hierarchyFile) + return try ArchiveCoding.data(of: hierarchyFile) } override func read(from data: Data, ofType _: String) throws { - hierarchyFile = try LookinArchiveCoding.hierarchyFile(from: data) + hierarchyFile = try ArchiveCoding.hierarchyFile(from: data) } } diff --git a/LookInside/Read/LKReadHierarchyController.swift b/LookInside/Read/ReadHierarchyController.swift similarity index 76% rename from LookInside/Read/LKReadHierarchyController.swift rename to LookInside/Read/ReadHierarchyController.swift index 6640c846..d6f7bcde 100644 --- a/LookInside/Read/LKReadHierarchyController.swift +++ b/LookInside/Read/ReadHierarchyController.swift @@ -1,5 +1,5 @@ // -// LKReadHierarchyController.swift +// ReadHierarchyController.swift // Lookin // // Created by Li Kai on 2019/5/13. @@ -11,15 +11,15 @@ import AppKit /// The reader's hierarchy list. Hiding or showing an item's preview only /// changes the in-memory tree; there is no app to tell. @objc(LKReadHierarchyController) -final class LKReadHierarchyController: LKHierarchyController { +final class ReadHierarchyController: HierarchyController { @objc(hierarchyView:needToCancelPreviewOfItem:) - func hierarchyView(_: LKHierarchyView?, needToCancelPreviewOf item: DisplayItem?) { + func hierarchyView(_: HierarchyView?, needToCancelPreviewOf item: DisplayItem?) { item?.noPreview = true notifyNoPreviewDidChange() } @objc(hierarchyView:needToShowPreviewOfItem:) - func hierarchyView(_: LKHierarchyView?, needToShowPreviewOf item: DisplayItem?) { + func hierarchyView(_: HierarchyView?, needToShowPreviewOf item: DisplayItem?) { // A preview shows only when none of its ancestors hides theirs. item?.enumerateSelfAndAncestors { item, _ in if item.noPreview { diff --git a/LookInside/Read/LKReadHierarchyDataSource.swift b/LookInside/Read/ReadHierarchyDataSource.swift similarity index 72% rename from LookInside/Read/LKReadHierarchyDataSource.swift rename to LookInside/Read/ReadHierarchyDataSource.swift index f8aebc80..c588958e 100644 --- a/LookInside/Read/LKReadHierarchyDataSource.swift +++ b/LookInside/Read/ReadHierarchyDataSource.swift @@ -1,5 +1,5 @@ // -// LKReadHierarchyDataSource.swift +// ReadHierarchyDataSource.swift // Lookin // // Created by Li Kai on 2019/5/12. @@ -12,11 +12,11 @@ import AppKit /// stored screenshots put back on the items. It uses the reader window's own /// preference set. @objc(LKReadHierarchyDataSource) -final class LKReadHierarchyDataSource: LKHierarchyDataSource { - private let readPreferenceManager: LKPreferenceManager +final class ReadHierarchyDataSource: HierarchyDataSource { + private let readPreferenceManager: PreferenceManager @objc(initWithFile:preferenceManager:) - init(file: HierarchyFile, preferenceManager manager: LKPreferenceManager) { + init(file: HierarchyFile, preferenceManager manager: PreferenceManager) { readPreferenceManager = manager super.init() @@ -27,9 +27,9 @@ final class LKReadHierarchyDataSource: LKHierarchyDataSource { guard !solo.isEmpty || !group.isEmpty else { return } // A Mac capture keys its screenshots by the view's oid, an iOS one by // the layer's. - let prefersViewOID = LKHelper.appInfoLooksLikeMacTarget(file.hierarchyInfo?.appInfo) + let prefersViewOID = AppHelper.appInfoLooksLikeMacTarget(file.hierarchyInfo?.appInfo) for item in flatItems ?? [] { - let screenshots = LKReadScreenshotLookup.screenshots( + let screenshots = ReadScreenshotLookup.screenshots( forOids: item.availableObjectOidsPreferView(prefersViewOID), solo: solo, group: group @@ -43,7 +43,7 @@ final class LKReadHierarchyDataSource: LKHierarchyDataSource { } } - override func preferenceManager() -> LKPreferenceManager! { + override func preferenceManager() -> PreferenceManager! { readPreferenceManager } } diff --git a/LookInside/Read/LKReadScreenshotLookup.swift b/LookInside/Read/ReadScreenshotLookup.swift similarity index 93% rename from LookInside/Read/LKReadScreenshotLookup.swift rename to LookInside/Read/ReadScreenshotLookup.swift index 035a17d2..a0ae73d9 100644 --- a/LookInside/Read/LKReadScreenshotLookup.swift +++ b/LookInside/Read/ReadScreenshotLookup.swift @@ -1,5 +1,5 @@ // -// LKReadScreenshotLookup.swift +// ReadScreenshotLookup.swift // LookInside // // Which of a `.lookin` file's stored screenshots belong to a display item. @@ -7,7 +7,7 @@ import Foundation -enum LKReadScreenshotLookup { +enum ReadScreenshotLookup { /// The solo and group screenshot data stored for one item. /// /// `oids` are the item's object ids in preference order. The first oid diff --git a/LookInside/Read/LKReadViewController.swift b/LookInside/Read/ReadViewController.swift similarity index 68% rename from LookInside/Read/LKReadViewController.swift rename to LookInside/Read/ReadViewController.swift index fc74b0a7..a6d37aba 100644 --- a/LookInside/Read/LKReadViewController.swift +++ b/LookInside/Read/ReadViewController.swift @@ -1,5 +1,5 @@ // -// LKReadViewController.swift +// ReadViewController.swift // Lookin // // Created by Li Kai on 2019/5/12. @@ -12,28 +12,28 @@ import AppKit /// preview, the dashboard or the measure panel on the right; and a tip /// while the tree is in focus mode. @objc(LKReadViewController) -final class LKReadViewController: LKBaseViewController, NSSplitViewDelegate { +final class ReadViewController: BaseViewController, NSSplitViewDelegate { /// Implicitly unwrapped as the Objective-C property was; Swift callers /// bind it with `guard let`. - @objc var hierarchyDataSource: LKReadHierarchyDataSource! - - private let splitView = LKSplitView() - private let hierarchyController: LKReadHierarchyController - private let splitRightView = LKBaseView() - private let previewController: LKPreviewController - private let dashboardController: LKDashboardViewController - private let measureController: LKMeasureController - private let focusTipView = LKYellowTipsView() + @objc var hierarchyDataSource: ReadHierarchyDataSource! + + private let splitView = SplitView() + private let hierarchyController: ReadHierarchyController + private let splitRightView = BaseView() + private let previewController: PreviewController + private let dashboardController: DashboardViewController + private let measureController: MeasureController + private let focusTipView = YellowTipsView() private var stateObservation: NSKeyValueObservation? @objc(initWithFile:preferenceManager:) - init(file: HierarchyFile, preferenceManager manager: LKPreferenceManager) { - let dataSource = LKReadHierarchyDataSource(file: file, preferenceManager: manager) + init(file: HierarchyFile, preferenceManager manager: PreferenceManager) { + let dataSource = ReadHierarchyDataSource(file: file, preferenceManager: manager) hierarchyDataSource = dataSource - hierarchyController = LKReadHierarchyController(dataSource: dataSource) - previewController = LKPreviewController(dataSource: dataSource) - dashboardController = LKDashboardViewController(readDataSource: dataSource) - measureController = LKMeasureController(dataSource: dataSource) + hierarchyController = ReadHierarchyController(dataSource: dataSource) + previewController = PreviewController(dataSource: dataSource) + dashboardController = DashboardViewController(readDataSource: dataSource) + measureController = MeasureController(dataSource: dataSource) super.init(containerView: nil) addChild(hierarchyController) @@ -85,21 +85,21 @@ final class LKReadViewController: LKBaseViewController, NSSplitViewDelegate { override func viewDidLayout() { super.viewDidLayout() - LKViewFrameLayout(previewController.view).fullFrame() - LKViewFrameLayout(dashboardController.view).width(DashboardViewWidth).right(0).fullHeight() - LKViewFrameLayout(measureController.view).width(MeasureViewWidth).right(DashboardHorInset).fullHeight() + ViewFrameLayout(previewController.view).fullFrame() + ViewFrameLayout(dashboardController.view).width(DashboardViewWidth).right(0).fullHeight() + ViewFrameLayout(measureController.view).width(MeasureViewWidth).right(DashboardHorInset).fullHeight() - var tipsY = LKNavigationManager.shared.windowTitleBarHeight + 10 + var tipsY = NavigationManager.shared.windowTitleBarHeight + 10 let visibleTips = [focusTipView].filter { !$0.isHidden && $0.superview != nil && $0.alphaValue >= 0.01 } for tipsView in visibleTips { let midX = hierarchyController.view.bounds.width + (previewController.view.bounds.width - DashboardViewWidth) / 2 - LKViewFrameLayout(tipsView).sizeToFit().y(tipsY).midX(midX) + ViewFrameLayout(tipsView).sizeToFit().y(tipsY).midX(midX) tipsY = tipsView.frame.maxY + 5 } } /// The reader's hierarchy list. - @objc func currentHierarchyView() -> LKHierarchyView? { + @objc func currentHierarchyView() -> HierarchyView? { hierarchyController.hierarchyView } @@ -113,8 +113,8 @@ final class LKReadViewController: LKBaseViewController, NSSplitViewDelegate { view.needsLayout = true } - @objc private func handleMeasureStateChange(_ param: LookinMsgActionParams) { - let isMeasure = param.integerValue != LookinMeasureState.no.rawValue + @objc private func handleMeasureStateChange(_ param: MessageActionParameters) { + let isMeasure = param.integerValue != MeasureState.no.rawValue dashboardController.view.isHidden = isMeasure measureController.view.isHidden = !isMeasure } diff --git a/LookInside/Read/LKReadWindowController.swift b/LookInside/Read/ReadWindowController.swift similarity index 81% rename from LookInside/Read/LKReadWindowController.swift rename to LookInside/Read/ReadWindowController.swift index 68f8a8ae..8ab17cad 100644 --- a/LookInside/Read/LKReadWindowController.swift +++ b/LookInside/Read/ReadWindowController.swift @@ -1,5 +1,5 @@ // -// LKReadWindowController.swift +// ReadWindowController.swift // Lookin // // Created by Li Kai on 2019/5/12. @@ -8,29 +8,29 @@ import AppKit -/// The window of a `LookinArchiveDocument`. +/// The window of a `ArchiveDocument`. /// /// Reader windows are owned by the document exclusively: -/// `LKNavigationManager.showReaderWithHierarchyFile:title:` wraps in-memory +/// `NavigationManager.showReaderWithHierarchyFile:title:` wraps in-memory /// hierarchies in an untitled document, and archives on disk open through /// `NSDocumentController.openDocumentWithContentsOfURL:`. @objc(LKReadWindowController) -final class LKReadWindowController: LKWindowController, NSToolbarDelegate { +final class ReadWindowController: WindowController, NSToolbarDelegate { /// This window's own preference set: the reader's view settings, including /// the show-backing-layers toggle, are per document window. A document that /// can rebuild its tree reads the toggle from here. - @objc let preferenceManager = LKPreferenceManager() + @objc let preferenceManager = PreferenceManager() - private var viewController: LKReadViewController? + private var viewController: ReadViewController? private var toolbarItemsMap: [String: NSToolbarItem] = [:] private var hierarchyFileObservation: NSKeyValueObservation? private var selectedItemObservation: NSKeyValueObservation? private weak var shownFile: HierarchyFile? @objc(initWithDocument:) - init(document: LookinArchiveDocument) { + init(document: ArchiveDocument) { let screenSize = NSScreen.main?.frame.size ?? .zero - let window = LKWindow( + let window = AppWindow( contentRect: NSRect(x: 0, y: 0, width: screenSize.width * 0.7, height: screenSize.height * 0.7), styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView], backing: .buffered, @@ -46,7 +46,7 @@ final class LKReadWindowController: LKWindowController, NSToolbarDelegate { if document.hierarchyFile == nil { // The document is still importing in the background (an Xcode // capture): hold the window on a placeholder until the file lands. - window.contentView = LKReadLoadingView() + window.contentView = ReadLoadingView() } // Every file the document produces gets a reader built in place: the // one that lands after the import, and each rebuild the backing-layer @@ -77,8 +77,8 @@ final class LKReadWindowController: LKWindowController, NSToolbarDelegate { showHierarchyFile(file) } - @objc private func handleShowBackingLayersDidChange(_ param: LookinMsgActionParams) { - guard let document = document as? LookinArchiveDocument, document.canRebuildHierarchyFile() else { + @objc private func handleShowBackingLayersDidChange(_ param: MessageActionParameters) { + guard let document = document as? ArchiveDocument, document.canRebuildHierarchyFile() else { return } // Back to the placeholder; the new file's reader replaces it. Toolbar @@ -88,7 +88,7 @@ final class LKReadWindowController: LKWindowController, NSToolbarDelegate { selectedItemObservation = nil toolbarItemsMap = [:] window?.toolbar = nil - window?.contentView = LKReadLoadingView() + window?.contentView = ReadLoadingView() document.rebuildHierarchyFile(showingBackingLayers: param.boolValue) } @@ -97,7 +97,7 @@ final class LKReadWindowController: LKWindowController, NSToolbarDelegate { /// data source to exist. private func showHierarchyFile(_ file: HierarchyFile) { guard let window else { return } - let viewController = LKReadViewController(file: file, preferenceManager: preferenceManager) + let viewController = ReadViewController(file: file, preferenceManager: preferenceManager) self.viewController = viewController // Setting contentViewController sizes the window to the view; keep the // size the window already has. @@ -148,7 +148,7 @@ final class LKReadWindowController: LKWindowController, NSToolbarDelegate { if let item = toolbarItemsMap[identifier] { return item } - let helper = LKWindowToolbarHelper.shared + let helper = WindowToolbarHelper.shared let item: NSToolbarItem? if identifier == LKToolBarIdentifier_AppInReadMode { item = helper.makeAppInReadModeItem(with: viewController?.hierarchyDataSource.rawHierarchyInfo?.appInfo) @@ -177,42 +177,42 @@ final class LKReadWindowController: LKWindowController, NSToolbarDelegate { let popover = NSPopover() popover.behavior = .transient popover.animates = false - popover.contentSize = NSSize(width: LKHelper.isEnglish() ? 270 : 350, height: 260) + popover.contentSize = NSSize(width: AppHelper.isEnglish() ? 270 : 350, height: 260) let inspectedAppInfo = viewController?.hierarchyDataSource.rawHierarchyInfo?.appInfo - popover.contentViewController = LKMenuPopoverSettingController( + popover.contentViewController = MenuPopoverSettingController( preferenceManager: preferenceManager, - isMacTarget: LKHelper.appInfoLooksLikeMacTarget(inspectedAppInfo) + isMacTarget: AppHelper.appInfoLooksLikeMacTarget(inspectedAppInfo) ) popover.show(relativeTo: NSRect(origin: .zero, size: button.bounds.size), of: button, preferredEdge: .maxY) } @objc private func handleFreeRotation() { - let freeRotation: LookinBOOLMsgAttribute = preferenceManager.freeRotation + let freeRotation: BoolMessageAttribute = preferenceManager.freeRotation freeRotation.setBOOLValue(!freeRotation.currentBOOLValue, ignoreSubscriber: nil) } - // MARK: - LKAppMenuManagerDelegate + // MARK: - AppMenuManagerDelegate @objc func appMenuManagerDidSelectDimension() { - let dimension: LookinIntegerMsgAttribute = preferenceManager.previewDimension - let target: LookinPreviewDimension = dimension.currentIntegerValue == LookinPreviewDimension.dimension2D.rawValue ? .dimension3D : .dimension2D + let dimension: IntegerMessageAttribute = preferenceManager.previewDimension + let target: PreviewDimension = dimension.currentIntegerValue == PreviewDimension.dimension2D.rawValue ? .dimension3D : .dimension2D dimension.setIntegerValue(Int(target.rawValue), ignoreSubscriber: nil) } @objc func appMenuManagerDidSelectZoomIn() { - stepScale(by: LKToolbarRules.step) + stepScale(by: ToolbarRules.step) } @objc func appMenuManagerDidSelectZoomOut() { - stepScale(by: -LKToolbarRules.step) + stepScale(by: -ToolbarRules.step) } @objc func appMenuManagerDidSelectDecreaseInterspace() { - stepInterspace(by: -LKToolbarRules.step) + stepInterspace(by: -ToolbarRules.step) } @objc func appMenuManagerDidSelectIncreaseInterspace() { - stepInterspace(by: LKToolbarRules.step) + stepInterspace(by: ToolbarRules.step) } @objc func appMenuManagerDidSelectExpansionIndex(_ index: UInt) { @@ -224,8 +224,8 @@ final class LKReadWindowController: LKWindowController, NSToolbarDelegate { } private func stepScale(by delta: Double) { - let scale: LookinDoubleMsgAttribute = preferenceManager.previewScale - let value = LKToolbarRules.stepped( + let scale: DoubleMessageAttribute = preferenceManager.previewScale + let value = ToolbarRules.stepped( scale.currentDoubleValue, by: delta, lower: Double(LookinPreviewMinScale), @@ -235,8 +235,8 @@ final class LKReadWindowController: LKWindowController, NSToolbarDelegate { } private func stepInterspace(by delta: Double) { - let interspace: LookinDoubleMsgAttribute = preferenceManager.zInterspace - let value = LKToolbarRules.stepped( + let interspace: DoubleMessageAttribute = preferenceManager.zInterspace + let value = ToolbarRules.stepped( interspace.currentDoubleValue, by: delta, lower: Double(LookinPreviewMinZInterspace), @@ -248,9 +248,9 @@ final class LKReadWindowController: LKWindowController, NSToolbarDelegate { /// What the window shows while a document is still importing in the /// background: an indeterminate spinner and one line of text. -final class LKReadLoadingView: LKBaseView { +final class ReadLoadingView: BaseView { private let indicator = NSProgressIndicator() - private let titleLabel = LKLabel() + private let titleLabel = TextLabel() override init(frame frameRect: NSRect) { super.init(frame: frameRect) @@ -274,9 +274,9 @@ final class LKReadLoadingView: LKBaseView { override func layout() { super.layout() indicator.sizeToFit() - LKViewFrameLayout(titleLabel).sizeToFit().x(indicator.frame.maxX + 8).midY(indicator.frame.midY) + ViewFrameLayout(titleLabel).sizeToFit().x(indicator.frame.maxX + 8).midY(indicator.frame.midY) let views: [NSView] = [indicator, titleLabel] - LKViewFrameLayout.groupHorAlign(views) - LKViewFrameLayout.groupMidY(views, bounds.height * 0.5) + ViewFrameLayout.groupHorAlign(views) + ViewFrameLayout.groupMidY(views, bounds.height * 0.5) } } diff --git a/LookInside/Static/LKStaticConstants.swift b/LookInside/Static/LKStaticConstants.swift index 9f30862e..73930f4d 100644 --- a/LookInside/Static/LKStaticConstants.swift +++ b/LookInside/Static/LKStaticConstants.swift @@ -12,18 +12,18 @@ import CoreGraphics /// print that item's view in it. let LKAppShowConsoleNotificationName = "LKAppShowConsoleNotificationName" -/// Message identifiers of LKMessageManager. +/// Message identifiers of MessageManager. let LKMessage_Jobs = "LKMessage_Jobs" let LKMessage_SwiftSubspec = "LKMessage_SwiftSubspec" -/// Bounds of LKPreviewView's scale and zInterspace (and of the preference +/// Bounds of PreviewView's scale and zInterspace (and of the preference /// values that drive them). let LookinPreviewMinScale: CGFloat = 0 let LookinPreviewMaxScale: CGFloat = 1 let LookinPreviewMinZInterspace: CGFloat = 0 let LookinPreviewMaxZInterspace: CGFloat = 1 -@objc enum LookinPreviewDimension: UInt { +@objc enum PreviewDimension: UInt { case dimension2D case dimension3D } diff --git a/LookInside/Static/LKMessageManager.swift b/LookInside/Static/MessageManager.swift similarity index 88% rename from LookInside/Static/LKMessageManager.swift rename to LookInside/Static/MessageManager.swift index fc789b57..3881e01d 100644 --- a/LookInside/Static/LKMessageManager.swift +++ b/LookInside/Static/MessageManager.swift @@ -1,5 +1,5 @@ // -// LKMessageManager.swift +// MessageManager.swift // LookInside // // Created by likai.123 on 2023/10/30. @@ -12,13 +12,13 @@ import Foundation /// button. Identifiers are `LKMessage_Jobs` and `LKMessage_SwiftSubspec` /// (LKStaticConstants.swift). @objc(LKMessageManager) -final class LKMessageManager: NSObject { +final class MessageManager: NSObject { /// Set once the jobs notice was dismissed. private static let hasReadJobsDefaultsKey = "LKMessageManager_HasReadJobs" - private static let shared = LKMessageManager() + private static let shared = MessageManager() - @objc class func sharedInstance() -> LKMessageManager { + @objc class func sharedInstance() -> MessageManager { shared } diff --git a/LookInside/Static/Preview/LKDisplayItemNode.swift b/LookInside/Static/Preview/DisplayItemNode.swift similarity index 97% rename from LookInside/Static/Preview/LKDisplayItemNode.swift rename to LookInside/Static/Preview/DisplayItemNode.swift index d11aae54..d7b63f47 100644 --- a/LookInside/Static/Preview/LKDisplayItemNode.swift +++ b/LookInside/Static/Preview/DisplayItemNode.swift @@ -1,5 +1,5 @@ // -// LKDisplayItemNode.swift +// DisplayItemNode.swift // LookInside // // Created by Li Kai on 2019/8/17. @@ -12,7 +12,7 @@ import SceneKit /// One item's plane in the 3D preview: the screenshot (or background /// colour), a tint mask for hover and selection, and an outline. @objc(LKDisplayItemNode) -final class LKDisplayItemNode: SCNNode, DisplayItemDelegate { +final class DisplayItemNode: SCNNode, DisplayItemDelegate { /// Rendering order added to a coplanar overlay node's border so it draws /// after every ordinary node. Paired with a depth-test-free material, /// this puts the highlight box on top of whatever the owning view has @@ -24,7 +24,7 @@ final class LKDisplayItemNode: SCNNode, DisplayItemDelegate { /// Scene units per point. private static let factor: CGFloat = 0.01 - private let dataSource: LKHierarchyDataSource? + private let dataSource: HierarchyDataSource? private let isMacTarget: Bool private let contentPlane = SCNPlane() @@ -50,7 +50,7 @@ final class LKDisplayItemNode: SCNNode, DisplayItemDelegate { } /// The point of frameToRoot space at the origin of the 3D scene. Set by - /// LKPreviewView on every render from the largest top-level window item, + /// PreviewView on every render from the largest top-level window item, /// so that window's centre stays at (0, 0) and smaller windows sit /// around it. var referenceCenter: CGPoint = .zero { @@ -60,7 +60,7 @@ final class LKDisplayItemNode: SCNNode, DisplayItemDelegate { } } - weak var preferenceManager: LKPreferenceManager? { + weak var preferenceManager: PreferenceManager? { didSet { preferenceManager?.showHiddenItems.subscribe(self, action: #selector(renderVisibility), relatedObject: nil) preferenceManager?.showOutline.subscribe(self, action: #selector(renderImageAndColor), relatedObject: nil) @@ -86,9 +86,9 @@ final class LKDisplayItemNode: SCNNode, DisplayItemDelegate { didSet { renderImageAndColor() } } - init(dataSource: LKHierarchyDataSource?) { + init(dataSource: HierarchyDataSource?) { self.dataSource = dataSource - isMacTarget = LKHelper.appInfoLooksLikeMacTarget(dataSource?.rawHierarchyInfo?.appInfo) + isMacTarget = AppHelper.appInfoLooksLikeMacTarget(dataSource?.rawHierarchyInfo?.appInfo) contentPlane.firstMaterial?.isDoubleSided = true contentPlane.firstMaterial?.lightingModel = .constant @@ -326,7 +326,7 @@ final class LKDisplayItemNode: SCNNode, DisplayItemDelegate { } } else { maskColor = Self.color(110, 183, 255) - var level = LKPreferenceManager.shared.imageContrastLevel + var level = PreferenceManager.shared.imageContrastLevel if level < 0 || level > 2 { assertionFailure() level = 0 diff --git a/LookInside/Static/Preview/LKPreviewController.swift b/LookInside/Static/Preview/PreviewController.swift similarity index 91% rename from LookInside/Static/Preview/LKPreviewController.swift rename to LookInside/Static/Preview/PreviewController.swift index a4917176..3d906b29 100644 --- a/LookInside/Static/Preview/LKPreviewController.swift +++ b/LookInside/Static/Preview/PreviewController.swift @@ -1,5 +1,5 @@ // -// LKPreviewController.swift +// PreviewController.swift // LookInside // // Created by Li Kai on 2018/8/6. @@ -11,18 +11,18 @@ import AppKit /// Hosts the 3D preview and turns mouse, trackpad and keyboard input into /// rotation, translation, zoom, selection and the context menu. @objc(LKPreviewController) -final class LKPreviewController: LKBaseViewController, NSGestureRecognizerDelegate, NSMenuDelegate, LKPreviewStageViewDelegate { - @objc weak var staticViewController: LKStaticViewController? +final class PreviewController: BaseViewController, NSGestureRecognizerDelegate, NSMenuDelegate, PreviewStageViewDelegate { + @objc weak var staticViewController: StaticViewController? /// Set by the owner in a live window; nil when reading a `.lookin` file. - @objc weak var asyncUpdateManager: LKStaticAsyncUpdateManager? + @objc weak var asyncUpdateManager: StaticAsyncUpdateManager? - private let dataSource: LKHierarchyDataSource? - private let previewView: LKPreviewView + private let dataSource: HierarchyDataSource? + private let previewView: PreviewView /// Made by makeContainerView() during the superclass initializer. - private var stageView: LKPreviewStageView! + private var stageView: PreviewStageView! - private var panRecognizer: LKPreviewPanGestureRecognizer! + private var panRecognizer: PreviewPanGestureRecognizer! private var clickRecognizer: NSClickGestureRecognizer! private var doubleClickRecognizer: NSClickGestureRecognizer! private var rightClickRecognizer: NSClickGestureRecognizer! @@ -33,7 +33,7 @@ final class LKPreviewController: LKBaseViewController, NSGestureRecognizerDelega private var eventMonitors: [Any] = [] private var notificationObservers: [NSObjectProtocol] = [] private var keyValueObservations: [NSKeyValueObservation] = [] - private let dataSourceSignals = LKSyncSubscriptionBag() + private let dataSourceSignals = SyncSubscriptionBag() private var hasLaidOut = false /// The rotation to go back to when switching from 2D to 3D. @@ -63,19 +63,19 @@ final class LKPreviewController: LKBaseViewController, NSGestureRecognizerDelega private var isKeyingDownOption = false { didSet { guard isKeyingDownOption != oldValue, let preferenceManager = dataSource?.preferenceManager() else { return } - if preferenceManager.measureState.currentIntegerValue == LookinMeasureState.locked.rawValue { + if preferenceManager.measureState.currentIntegerValue == MeasureState.locked.rawValue { return } let measures = isKeyingDownOption && dataSource?.selectedItem != nil && view.window?.isKeyWindow == true - let state: LookinMeasureState = measures ? .unlocked : .no + let state: MeasureState = measures ? .unlocked : .no preferenceManager.measureState.setIntegerValue(state.rawValue, ignoreSubscriber: nil) } } @objc(initWithDataSource:) - init(dataSource: LKHierarchyDataSource?) { + init(dataSource: HierarchyDataSource?) { self.dataSource = dataSource - previewView = LKPreviewView(dataSource: dataSource) + previewView = PreviewView(dataSource: dataSource) super.init(containerView: nil) setUp() } @@ -95,7 +95,7 @@ final class LKPreviewController: LKBaseViewController, NSGestureRecognizerDelega } override func makeContainerView() -> NSView { - let stageView = LKPreviewStageView() + let stageView = PreviewStageView() stageView.didChangeAppearanceBlock = { view, isDarkMode in view?.backgroundColor = isDarkMode ? NSColor(red: 0, green: 0, blue: 0, alpha: 1) @@ -148,7 +148,7 @@ final class LKPreviewController: LKBaseViewController, NSGestureRecognizerDelega self?.previewView.didSelect(dataSource.selectedItem) }) } - if let staticDataSource = dataSource as? LKStaticHierarchyDataSource { + if let staticDataSource = dataSource as? StaticHierarchyDataSource { dataSourceSignals.observe(staticDataSource.itemDidChangeHiddenAlphaValue) { [weak self] in self?.previewView.updateZPosition() } @@ -157,7 +157,7 @@ final class LKPreviewController: LKBaseViewController, NSGestureRecognizerDelega } } - panRecognizer = LKPreviewPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:))) + panRecognizer = PreviewPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:))) panRecognizer.delegate = self previewView.addGestureRecognizer(panRecognizer) @@ -235,8 +235,8 @@ final class LKPreviewController: LKBaseViewController, NSGestureRecognizerDelega // Reach a dashboard's width further left (20 less, since the preview // usually turns right) and a title bar's height further down, so the // preview looks centred. - let titleBarHeight = LKNavigationManager.shared.windowTitleBarHeight - let layout = LKStaticLayout(previewView) + let titleBarHeight = NavigationManager.shared.windowTitleBarHeight + let layout = StaticLayout(previewView) layout.width(view.frame.width + DashboardViewWidth - DashboardHorInset - 20) layout.right(0) layout.height(view.frame.height + titleBarHeight) @@ -282,9 +282,9 @@ final class LKPreviewController: LKBaseViewController, NSGestureRecognizerDelega return true } - // MARK: - LKPreviewStageViewDelegate + // MARK: - PreviewStageViewDelegate - func previewStageView(_: LKPreviewStageView, mouseMoved event: NSEvent) { + func previewStageView(_: PreviewStageView, mouseMoved event: NSEvent) { guard let dataSource else { return } if isKeyingDownSpace { if dataSource.hoveredItem != nil { @@ -305,7 +305,7 @@ final class LKPreviewController: LKBaseViewController, NSGestureRecognizerDelega } } - func didResetCursorRects(in view: LKPreviewStageView) { + func didResetCursorRects(in view: PreviewStageView) { if isKeyingDownSpace { view.addCursorRect(self.view.bounds, cursor: .openHand) } @@ -313,12 +313,12 @@ final class LKPreviewController: LKBaseViewController, NSGestureRecognizerDelega // MARK: - Preferences - @objc private func handleShowHiddenItemsChange(_ param: LookinMsgActionParams) { + @objc private func handleShowHiddenItemsChange(_ param: MessageActionParameters) { previewView.showHiddenItems = param.boolValue previewView.updateZPosition() } - @objc private func handleFreeRotationChange(_ param: LookinMsgActionParams) { + @objc private func handleFreeRotationChange(_ param: MessageActionParameters) { var rotation = previewView.rotation if param.boolValue { if previewView.dimension == .dimension3D { @@ -332,12 +332,12 @@ final class LKPreviewController: LKBaseViewController, NSGestureRecognizerDelega } } - @objc private func handlePreviewScaleChange(_ param: LookinMsgActionParams) { + @objc private func handlePreviewScaleChange(_ param: MessageActionParameters) { previewView.scale = param.doubleValue } - @objc private func handlePreviewDimensionChange(_ param: LookinMsgActionParams) { - guard let newDimension = LookinPreviewDimension(rawValue: UInt(bitPattern: param.integerValue)), + @objc private func handlePreviewDimensionChange(_ param: MessageActionParameters) { + guard let newDimension = PreviewDimension(rawValue: UInt(bitPattern: param.integerValue)), previewView.dimension != newDimension else { return @@ -362,7 +362,7 @@ final class LKPreviewController: LKBaseViewController, NSGestureRecognizerDelega } } - @objc private func handleZInterspaceChange(_ param: LookinMsgActionParams) { + @objc private func handleZInterspaceChange(_ param: MessageActionParameters) { previewView.zInterspace = param.doubleValue } @@ -387,10 +387,10 @@ final class LKPreviewController: LKBaseViewController, NSGestureRecognizerDelega // MARK: - Gestures - @objc private func handlePanGesture(_ recognizer: LKPreviewPanGestureRecognizer) { + @objc private func handlePanGesture(_ recognizer: PreviewPanGestureRecognizer) { switch recognizer.state { case .began: - LKUserActionManager.sharedInstance().send(.previewOperation) + UserActionManager.sharedInstance().send(.previewOperation) // End any editing in a dashboard card. view.window?.makeFirstResponder(self) recognizer.purpose = isKeyingDownSpace ? .translate : .rotate @@ -429,7 +429,7 @@ final class LKPreviewController: LKBaseViewController, NSGestureRecognizerDelega @objc private func handleClickGesture(_ recognizer: NSClickGestureRecognizer) { guard let dataSource, !dataSource.shouldAvoidChangingPreviewSelectionDueToDashboardSearch else { return } - LKUserActionManager.sharedInstance().send(.previewOperation) + UserActionManager.sharedInstance().send(.previewOperation) // End any editing in a dashboard card. view.window?.makeFirstResponder(self) @@ -445,7 +445,7 @@ final class LKPreviewController: LKBaseViewController, NSGestureRecognizerDelega } @objc private func handleRightClick(_ recognizer: NSClickGestureRecognizer) { - LKUserActionManager.sharedInstance().send(.previewOperation) + UserActionManager.sharedInstance().send(.previewOperation) // End any editing in a dashboard card. view.window?.makeFirstResponder(self) @@ -462,7 +462,7 @@ final class LKPreviewController: LKBaseViewController, NSGestureRecognizerDelega } @objc private func handleDoubleClick(_ recognizer: NSClickGestureRecognizer) { - LKUserActionManager.sharedInstance().send(.previewOperation) + UserActionManager.sharedInstance().send(.previewOperation) // End any editing in a dashboard card. view.window?.makeFirstResponder(self) @@ -471,7 +471,7 @@ final class LKPreviewController: LKBaseViewController, NSGestureRecognizerDelega else { return } - switch LKPreferenceManager.shared.doubleClickBehavior { + switch PreferenceManager.shared.doubleClickBehavior { case .collapse: if item.isExpandable { if item.isExpanded { @@ -633,10 +633,10 @@ final class LKPreviewController: LKBaseViewController, NSGestureRecognizerDelega @objc private func handleExportScreenshot(_: NSMenuItem) { guard let item = rightClickingDisplayItem else { return } - LKExportManager.exportScreenshot(with: item) + ExportManager.exportScreenshot(with: item) } @objc private func handleHideScreenshotForever() { - LKHelper.openCustomConfigWebsite() + AppHelper.openCustomConfigWebsite() } } diff --git a/LookInside/Static/Preview/LKPreviewStageView.swift b/LookInside/Static/Preview/PreviewStageView.swift similarity index 76% rename from LookInside/Static/Preview/LKPreviewStageView.swift rename to LookInside/Static/Preview/PreviewStageView.swift index d021a115..d08e67a4 100644 --- a/LookInside/Static/Preview/LKPreviewStageView.swift +++ b/LookInside/Static/Preview/PreviewStageView.swift @@ -1,5 +1,5 @@ // -// LKPreviewStageView.swift +// PreviewStageView.swift // LookInside // // Created by Li Kai on 2018/8/6. @@ -9,16 +9,16 @@ import AppKit @MainActor -protocol LKPreviewStageViewDelegate: AnyObject { - func previewStageView(_ view: LKPreviewStageView, mouseMoved event: NSEvent) - func didResetCursorRects(in view: LKPreviewStageView) +protocol PreviewStageViewDelegate: AnyObject { + func previewStageView(_ view: PreviewStageView, mouseMoved event: NSEvent) + func didResetCursorRects(in view: PreviewStageView) } /// The preview controller's root view: reports mouse moves anywhere over it /// and lets the delegate add cursor rects. @objc(LKPreviewStageView) -final class LKPreviewStageView: LKBaseView { - weak var delegate: LKPreviewStageViewDelegate? +final class PreviewStageView: BaseView { + weak var delegate: PreviewStageViewDelegate? override func mouseMoved(with event: NSEvent) { super.mouseMoved(with: event) @@ -47,7 +47,7 @@ final class LKPreviewStageView: LKBaseView { /// The preview's pan gesture: rotates the preview, or moves it while space /// is held. @objc(LKPreviewPanGestureRecognizer) -final class LKPreviewPanGestureRecognizer: NSPanGestureRecognizer { +final class PreviewPanGestureRecognizer: NSPanGestureRecognizer { enum Purpose { case rotate case translate diff --git a/LookInside/Static/Preview/LKPreviewView.swift b/LookInside/Static/Preview/PreviewView.swift similarity index 94% rename from LookInside/Static/Preview/LKPreviewView.swift rename to LookInside/Static/Preview/PreviewView.swift index 0916fcb6..72557f96 100644 --- a/LookInside/Static/Preview/LKPreviewView.swift +++ b/LookInside/Static/Preview/PreviewView.swift @@ -1,5 +1,5 @@ // -// LKPreviewView.swift +// PreviewView.swift // LookInside // // Created by Li Kai on 2019/8/17. @@ -14,11 +14,11 @@ import AppKit import LookInsideHostCore import SceneKit -/// The 3D (or flat) preview of the hierarchy: one LKDisplayItemNode per +/// The 3D (or flat) preview of the hierarchy: one DisplayItemNode per /// item, stacked along the z axis. @objc(LKPreviewView) -final class LKPreviewView: SCNView { - private let dataSource: LKHierarchyDataSource? +final class PreviewView: SCNView { + private let dataSource: HierarchyDataSource? private let stageNode = SCNNode() private let cameraNode = SCNNode() @@ -26,7 +26,7 @@ final class LKPreviewView: SCNView { private let leftLightNode = SCNNode() private var flatDisplayItems: [DisplayItem] = [] - private var displayItemNodes: [LKDisplayItemNode] = [] + private var displayItemNodes: [DisplayItemNode] = [] /// The frameToRoot point at the 3D origin: the centre of the largest /// top-level window item. Recomputed on every render and handed to every @@ -74,7 +74,7 @@ final class LKPreviewView: SCNView { private var storedZInterspace: CGFloat = 0 /// 2D or 3D. Going 2D resets the rotation; going 3D keeps it. - private(set) var dimension: LookinPreviewDimension = .dimension2D + private(set) var dimension: PreviewDimension = .dimension2D /// The inspected app's screen size. var appScreenSize: CGSize = .zero { @@ -99,7 +99,7 @@ final class LKPreviewView: SCNView { } } - var preferenceManager: LKPreferenceManager? + var preferenceManager: PreferenceManager? var isDarkMode = false { didSet { @@ -114,7 +114,7 @@ final class LKPreviewView: SCNView { var showHiddenItems = false - init(dataSource: LKHierarchyDataSource?) { + init(dataSource: HierarchyDataSource?) { self.dataSource = dataSource super.init(frame: .zero, options: nil) @@ -194,11 +194,11 @@ final class LKPreviewView: SCNView { referenceCenter = referenceCenter(for: items) for (index, item) in items.enumerated() { - let node: LKDisplayItemNode + let node: DisplayItemNode if index < displayItemNodes.count { node = displayItemNodes[index] } else { - node = LKDisplayItemNode(dataSource: dataSource) + node = DisplayItemNode(dataSource: dataSource) node.referenceCenter = referenceCenter node.preferenceManager = preferenceManager node.isDarkMode = isDarkMode @@ -313,7 +313,7 @@ final class LKPreviewView: SCNView { /// Moves the lights level with the selected item's plane. func didSelect(_ item: DisplayItem?) { guard let item else { return } - let nodeZ = (item.previewNode as LKDisplayItemNode?)?.position.z ?? 0 + let nodeZ = (item.previewNode as DisplayItemNode?)?.position.z ?? 0 var rightPosition = rightLightNode.position rightPosition.z = nodeZ + 2 @@ -331,7 +331,7 @@ final class LKPreviewView: SCNView { .ignoreHiddenNodes: false, ]) guard let result = results.first else { return nil } - let targetNode = result.node.parent as? LKDisplayItemNode + let targetNode = result.node.parent as? DisplayItemNode assert(targetNode != nil) return targetNode?.displayItem } @@ -370,7 +370,7 @@ final class LKPreviewView: SCNView { } } - func setDimension(_ dimension: LookinPreviewDimension, animated: Bool) { + func setDimension(_ dimension: PreviewDimension, animated: Bool) { self.dimension = dimension if dimension != .dimension3D { setRotation(.zero, animated: animated) diff --git a/LookInside/Static/LKStaticAsyncUpdateManager.swift b/LookInside/Static/StaticAsyncUpdateManager.swift similarity index 89% rename from LookInside/Static/LKStaticAsyncUpdateManager.swift rename to LookInside/Static/StaticAsyncUpdateManager.swift index 1900aca5..97f6642c 100644 --- a/LookInside/Static/LKStaticAsyncUpdateManager.swift +++ b/LookInside/Static/StaticAsyncUpdateManager.swift @@ -1,5 +1,5 @@ // -// LKStaticAsyncUpdateManager.swift +// StaticAsyncUpdateManager.swift // LookInside // // Created by Li Kai on 2019/2/19. @@ -10,7 +10,7 @@ import AppKit import LookInsideHostCore @objc(LKStaticAsyncUpdateManagerDelegate) -protocol LKStaticAsyncUpdateManagerDelegate: NSObjectProtocol { +protocol StaticAsyncUpdateManagerDelegate: NSObjectProtocol { /// Called whenever the number of unfinished tasks changes: `totalCount` /// tasks in all, `finishedCount` of them done. @objc(detailUpdateTasksTotalCount:finishedCount:) @@ -21,7 +21,7 @@ protocol LKStaticAsyncUpdateManagerDelegate: NSObjectProtocol { } /// Progress of `updateAfterModifyingDisplayItem(_:)`. -enum LKModifyingUpdateEvent { +enum ModifyingUpdateEvent { /// `received` of `total` screenshots arrived. case progress(received: Int, total: Int) case failure(Error) @@ -31,29 +31,29 @@ enum LKModifyingUpdateEvent { /// one inspector window's hierarchy from the inspected app. @objc(LKStaticAsyncUpdateManager) @MainActor -final class LKStaticAsyncUpdateManager: NSObject { +final class StaticAsyncUpdateManager: NSObject { /// Set by the owner (window controller / live document), which holds it /// strongly. - @objc weak var hierarchyDataSource: LKStaticHierarchyDataSource? + @objc weak var hierarchyDataSource: StaticHierarchyDataSource? /// The app every request goes to. The owner refreshes it when a new /// hierarchy arrives or the document reconnects. - @objc weak var inspectableApp: LKInspectableApp? + @objc weak var inspectableApp: InspectableApp? - @objc weak var delegate: LKStaticAsyncUpdateManagerDelegate? + @objc weak var delegate: StaticAsyncUpdateManagerDelegate? /// Events of `updateAfterModifyingDisplayItem(_:)`. - let modifyingUpdates = AsyncBroadcaster() + let modifyingUpdates = AsyncBroadcaster() /// Requests that received every reply. - private var succeededRequests: [LKDetailUpdateRequest] = [] + private var succeededRequests: [DetailUpdateRequest] = [] /// The request sent and not yet ended. - private var ongoingRequest: LKDetailUpdateRequest? + private var ongoingRequest: DetailUpdateRequest? - private let dataSourceSignals = LKSyncSubscriptionBag() + private let dataSourceSignals = SyncSubscriptionBag() @objc(initWithHierarchyDataSource:inspectableApp:) - init(hierarchyDataSource: LKStaticHierarchyDataSource?, inspectableApp: LKInspectableApp?) { + init(hierarchyDataSource: StaticHierarchyDataSource?, inspectableApp: InspectableApp?) { self.hierarchyDataSource = hierarchyDataSource self.inspectableApp = inspectableApp super.init() @@ -66,7 +66,7 @@ final class LKStaticAsyncUpdateManager: NSObject { self.init(hierarchyDataSource: nil, inspectableApp: nil) } - private var dataSource: LKStaticHierarchyDataSource? { + private var dataSource: StaticHierarchyDataSource? { hierarchyDataSource } @@ -74,7 +74,7 @@ final class LKStaticAsyncUpdateManager: NSObject { /// With fast mode off: after a reload, fetches the details of every item. @objc func updateAll() { - assert(!LKPreferenceManager.shared.fastMode.currentBOOLValue) + assert(!PreferenceManager.shared.fastMode.currentBOOLValue) guard inspectableApp != nil, let dataSource, !dataSource.flatItems.isEmpty else { return } @@ -87,7 +87,7 @@ final class LKStaticAsyncUpdateManager: NSObject { /// With fast mode on: fetches the details of the visible items that do /// not have them yet. Call it whenever the displayed items change. @objc func updateForDisplayingItems() { - assert(LKPreferenceManager.shared.fastMode.currentBOOLValue) + assert(PreferenceManager.shared.fastMode.currentBOOLValue) guard inspectableApp != nil else { return } let items = dataSource?.displayingFlatItems ?? [] guard !items.isEmpty else { return } @@ -267,7 +267,7 @@ final class LKStaticAsyncUpdateManager: NSObject { private func updateAfterReloadingItemAndChildren(_ rootItem: DisplayItem) { // The root item's and its children's screenshots and attributes. - if LKPreferenceManager.shared.fastMode.currentBOOLValue { + if PreferenceManager.shared.fastMode.currentBOOLValue { updateForDisplayingItems() return } @@ -314,7 +314,7 @@ final class LKStaticAsyncUpdateManager: NSObject { // layers on): then the view node has to use the view oid. let viewOid = item.viewObject?.oid ?? 0 let layerOid = item.layerObject?.oid ?? 0 - let prefersViewOid = LKHelper.appInfoLooksLikeMacTarget(appInfo) || item.lk_ownsSeparateBackingLayerNode() + let prefersViewOid = AppHelper.appInfoLooksLikeMacTarget(appInfo) || item.lk_ownsSeparateBackingLayerNode() if prefersViewOid, viewOid != 0 { oid = viewOid } else if layerOid != 0 { @@ -330,15 +330,15 @@ final class LKStaticAsyncUpdateManager: NSObject { task.frameSize = item.frame.size task.taskType = type task.needBasisVisualInfo = true - task.clientReadableVersion = LKHelper.lookinReadableVersion() + task.clientReadableVersion = AppHelper.lookinReadableVersion() return task } private static func allowsSwiftUISupportAccess(for item: DisplayItem, appInfo: InspectedAppInfo?) -> Bool { - guard LKHelper.appInfoLooksLikeMacTarget(appInfo), item.lk_isSwiftUISupportRelated() else { + guard AppHelper.appInfoLooksLikeMacTarget(appInfo), item.lk_isSwiftUISupportRelated() else { return true } - return LKSwiftUISupportGatekeeper.sharedInstance().allowProtectedFeatureAccess(for: NSApplication.shared.keyWindow) + return SwiftUISupportGatekeeper.sharedInstance().allowProtectedFeatureAccess(for: NSApplication.shared.keyWindow) } private static func packages(from tasks: [StaticAsyncUpdateTask]) -> [StaticAsyncUpdateTasksPackage] { @@ -356,23 +356,23 @@ final class LKStaticAsyncUpdateManager: NSObject { /// thread. `endUpdating()` relies on that: cancelling the details /// request completes it before the next request starts. private func startRequest( - app: LKInspectableApp, + app: InspectableApp, type: Int, tasks: NSArray, - onEvent: @escaping (LKAppResponseEvent) -> Void + onEvent: @escaping (AppResponseEvent) -> Void ) { guard let channel = app.channel else { - onEvent(.failure(LKConnectionError.noConnect)) + onEvent(.failure(ConnectionError.noConnect)) return } - _ = LKInspectableApp.startRequest(on: channel, type: UInt32(type), data: tasks, onEvent: onEvent) + _ = InspectableApp.startRequest(on: channel, type: UInt32(type), data: tasks, onEvent: onEvent) } private func startRequest( - app: LKInspectableApp, + app: InspectableApp, type: Int, tasks: [StaticAsyncUpdateTask], - onEvent: @escaping (LKAppResponseEvent) -> Void + onEvent: @escaping (AppResponseEvent) -> Void ) { startRequest(app: app, type: type, tasks: tasks as NSArray, onEvent: onEvent) } @@ -383,7 +383,7 @@ final class LKStaticAsyncUpdateManager: NSObject { endUpdating() let packages = Self.packages(from: newTasks) - let request = LKDetailUpdateRequest(packages: packages) + let request = DetailUpdateRequest(packages: packages) ongoingRequest = request notifyTasksCountToDelegate() @@ -453,7 +453,7 @@ final class LKStaticAsyncUpdateManager: NSObject { "Perhaps your iOS app is paused with breakpoint in Xcode, blocked by other tasks in main thread, or moved to background state.\nToo large screenshots may also lead to this error.", comment: "" ) - if LKSwiftUISupportGatekeeper.sharedInstance().activationState == .activated, + if SwiftUISupportGatekeeper.sharedInstance().activationState == .activated, (dataSource?.flatItems ?? []).contains(where: { $0.lk_isSwiftUISupportRelated() }) { detail += "\n" + NSLocalizedString( @@ -461,7 +461,7 @@ final class LKStaticAsyncUpdateManager: NSObject { comment: "" ) } - let error = LKStaticErrors.make(title: title, detail: detail) + let error = StaticErrors.make(title: title, detail: detail) DispatchQueue.main.asyncAfter(deadline: .now() + 1) { // The static view controller may not be set up yet to show the // tip, so wait a little. @@ -476,7 +476,7 @@ final class LKStaticAsyncUpdateManager: NSObject { succeededRequests.append(request) } if request.failedTasksCount > 0 { - let error = LKStaticErrors.make( + let error = StaticErrors.make( title: NSLocalizedString("Some layer data failed to transmit.", comment: ""), detail: NSLocalizedString( "It may be due to changes in the layer structure within the iOS app. You can try reloading the entire structure in LookInside.", @@ -490,7 +490,7 @@ final class LKStaticAsyncUpdateManager: NSObject { assertionFailure() } notifyTasksCountToDelegate() - LKPerformanceReporter.sharedInstance().didComplete() + PerformanceReporter.sharedInstance().didComplete() } private func notifyTasksCountToDelegate() { @@ -503,7 +503,7 @@ final class LKStaticAsyncUpdateManager: NSObject { // MARK: - Reload tasks -extension LKStaticAsyncUpdateManager { +extension StaticAsyncUpdateManager { /// The tasks that reload one item: its group screenshot (and solo one /// when it has children), or its attributes alone when it has no /// screenshot. Empty when the Server is too old or the item is a @@ -553,17 +553,17 @@ extension LKStaticAsyncUpdateManager { return false } let appInfo = inspectableApp?.appInfo - guard LKVersionComparer.compare(expectedVersion: "1.2.7", realVersion: (appInfo?.serverReadableVersion as String?) ?? "") else { - let error = LKStaticErrors.make( + guard VersionComparer.compare(expectedVersion: "1.2.7", realVersion: (appInfo?.serverReadableVersion as String?) ?? "") else { + let error = StaticErrors.make( title: NSLocalizedString("Operation failed.", comment: ""), detail: NSLocalizedString("Please upgrade the LookinServer SDK version in your iOS project to 1.2.7 or higher.", comment: "") ) - LKStaticErrors.alert(error, in: NSApplication.shared.keyWindow) + StaticErrors.alert(error, in: NSApplication.shared.keyWindow) return false } - if LKHelper.appInfoLooksLikeMacTarget(appInfo), + if AppHelper.appInfoLooksLikeMacTarget(appInfo), item.lk_isSwiftUISupportRelated(), - !LKSwiftUISupportGatekeeper.sharedInstance().allowProtectedFeatureAccess(for: NSApplication.shared.keyWindow) + !SwiftUISupportGatekeeper.sharedInstance().allowProtectedFeatureAccess(for: NSApplication.shared.keyWindow) { return false } @@ -571,20 +571,20 @@ extension LKStaticAsyncUpdateManager { } private static func reloadTask(from item: DisplayItem, appInfo: InspectedAppInfo?) -> StaticAsyncUpdateTask? { - let oid = item.bestObjectOidPreferView(LKHelper.appInfoLooksLikeMacTarget(appInfo)) + let oid = item.bestObjectOidPreferView(AppHelper.appInfoLooksLikeMacTarget(appInfo)) guard oid != 0 else { return nil } let task = StaticAsyncUpdateTask() task.oid = oid task.frameSize = item.frame.size - task.clientReadableVersion = LKHelper.lookinReadableVersion() + task.clientReadableVersion = AppHelper.lookinReadableVersion() return task } } -// MARK: - LKDetailUpdateRequest +// MARK: - DetailUpdateRequest /// One details request: its packages and how many of their tasks replied. -private final class LKDetailUpdateRequest { +private final class DetailUpdateRequest { private(set) var packages: [StaticAsyncUpdateTasksPackage] /// Tasks that received a reply, failed ones included. Which ones is not /// known, only how many. @@ -615,7 +615,7 @@ private final class LKDetailUpdateRequest { /// The NSError the Objective-C `LookinErrorMake` / `AlertError` macros made /// and showed. -enum LKStaticErrors { +enum StaticErrors { static func make(title: String, detail: String) -> NSError { NSError(domain: LookinErrorDomain, code: LookinErrCode_Default, userInfo: [ NSLocalizedDescriptionKey: title, diff --git a/LookInside/Static/LKStaticHierarchyController.swift b/LookInside/Static/StaticHierarchyController.swift similarity index 67% rename from LookInside/Static/LKStaticHierarchyController.swift rename to LookInside/Static/StaticHierarchyController.swift index d3a14416..f53d45d9 100644 --- a/LookInside/Static/LKStaticHierarchyController.swift +++ b/LookInside/Static/StaticHierarchyController.swift @@ -1,5 +1,5 @@ // -// LKStaticHierarchyController.swift +// StaticHierarchyController.swift // LookInside // // Created by Li Kai on 2018/8/4. @@ -10,17 +10,17 @@ import AppKit /// The hierarchy tree of a live inspector window. @objc(LKStaticHierarchyController) -final class LKStaticHierarchyController: LKHierarchyController { - // MARK: - LKHierarchyViewDelegate +final class StaticHierarchyController: HierarchyController { + // MARK: - HierarchyViewDelegate @objc(hierarchyView:needToCancelPreviewOfItem:) - func hierarchyView(_: LKHierarchyView?, needToCancelPreviewOf item: DisplayItem?) { + func hierarchyView(_: HierarchyView?, needToCancelPreviewOf item: DisplayItem?) { item?.noPreview = true dataSource?.itemDidChangeNoPreview.send() } @objc(hierarchyView:needToShowPreviewOfItem:) - func hierarchyView(_: LKHierarchyView?, needToShowPreviewOf item: DisplayItem?) { + func hierarchyView(_: HierarchyView?, needToShowPreviewOf item: DisplayItem?) { item?.enumerateSelfAndAncestors { item, _ in if item.noPreview { item.noPreview = false diff --git a/LookInside/Static/LKStaticHierarchyDataSource.swift b/LookInside/Static/StaticHierarchyDataSource.swift similarity index 89% rename from LookInside/Static/LKStaticHierarchyDataSource.swift rename to LookInside/Static/StaticHierarchyDataSource.swift index 68024012..504e24ec 100644 --- a/LookInside/Static/LKStaticHierarchyDataSource.swift +++ b/LookInside/Static/StaticHierarchyDataSource.swift @@ -1,5 +1,5 @@ // -// LKStaticHierarchyDataSource.swift +// StaticHierarchyDataSource.swift // LookInside // // Created by Li Kai on 2018/12/21. @@ -11,17 +11,17 @@ import AppKit /// The data source of a live document: applies the details the update /// tasks deliver and starts those tasks. @objc(LKStaticHierarchyDataSource) -class LKStaticHierarchyDataSource: LKHierarchyDataSource { +class StaticHierarchyDataSource: HierarchyDataSource { @objc var appInfo: InspectedAppInfo! { storedAppInfo } /// The update manager of the owning window controller. - @objc weak var asyncUpdateManager: LKStaticAsyncUpdateManager? + @objc weak var asyncUpdateManager: StaticAsyncUpdateManager? /// Sends each item whose frame changed. Also reaches `events()` as /// `.itemDidChangeFrame`. - final let itemsDidChangeFrame = LKSyncSignal() + final let itemsDidChangeFrame = SyncSignal() /// Keeps a detail's subitems rebuild from starting a fast-mode update /// while the update task that delivered it is still running: update @@ -29,7 +29,7 @@ class LKStaticHierarchyDataSource: LKHierarchyDataSource { private var storedAppInfo: InspectedAppInfo? private var shouldIgnoreFastModeAutoUpdate = false private var isUsingDanceUI = false - private var frameSubscription: LKSyncSubscription? + private var frameSubscription: SyncSubscription? override init() { super.init() @@ -69,7 +69,7 @@ class LKStaticHierarchyDataSource: LKHierarchyDataSource { updateMessageStatus() - if !LKPreferenceManager.shared.fastMode.currentBOOLValue { + if !PreferenceManager.shared.fastMode.currentBOOLValue { MainActor.assumeIsolated { asyncUpdateManager?.updateAll() } @@ -169,7 +169,7 @@ class LKStaticHierarchyDataSource: LKHierarchyDataSource { } } if let source = node.customInfo?.danceuiSource, !source.isEmpty { - LKDanceUIAttrMaker.makeDanceUIJumpAttribute(node, danceSource: source) + DanceUIAttributeMaker.makeDanceUIJumpAttribute(node, danceSource: source) } } buildDisplayingFlatItems() @@ -178,15 +178,15 @@ class LKStaticHierarchyDataSource: LKHierarchyDataSource { override func buildDisplayingFlatItems() { super.buildDisplayingFlatItems() - if LKPreferenceManager.shared.fastMode.currentBOOLValue, !shouldIgnoreFastModeAutoUpdate { + if PreferenceManager.shared.fastMode.currentBOOLValue, !shouldIgnoreFastModeAutoUpdate { MainActor.assumeIsolated { asyncUpdateManager?.updateForDisplayingItems() } } } - override func preferenceManager() -> LKPreferenceManager! { - LKPreferenceManager.shared + override func preferenceManager() -> PreferenceManager! { + PreferenceManager.shared } override func isReadOnly() -> Bool { @@ -206,9 +206,9 @@ class LKStaticHierarchyDataSource: LKHierarchyDataSource { private func updateMessageStatus() { if serverSideIsSwiftProject, appInfo?.swiftEnabledInLookinServer == -1 { - LKMessageManager.sharedInstance().addMessage(LKMessage_SwiftSubspec) + MessageManager.sharedInstance().addMessage(LKMessage_SwiftSubspec) } else { - LKMessageManager.sharedInstance().removeMessage(LKMessage_SwiftSubspec) + MessageManager.sharedInstance().removeMessage(LKMessage_SwiftSubspec) } } } diff --git a/LookInside/Static/LKStaticLayout.swift b/LookInside/Static/StaticLayout.swift similarity index 93% rename from LookInside/Static/LKStaticLayout.swift rename to LookInside/Static/StaticLayout.swift index f7db2584..edc5b630 100644 --- a/LookInside/Static/LKStaticLayout.swift +++ b/LookInside/Static/StaticLayout.swift @@ -1,5 +1,5 @@ // -// LKStaticLayout.swift +// StaticLayout.swift // LookInside // // The few frame operations the inspector window's controllers used from @@ -10,7 +10,7 @@ import AppKit @MainActor -struct LKStaticLayout { +struct StaticLayout { let view: NSView init(_ view: NSView) { @@ -84,9 +84,9 @@ struct LKStaticLayout { fullHeight() } - /// Sizes an LKBaseView to what it needs with no limit. + /// Sizes an BaseView to what it needs with no limit. func sizeToFit() { - guard let baseView = view as? LKBaseView else { return } + guard let baseView = view as? BaseView else { return } let size = baseView.sizeThatFits(NSSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude)) update { $0.size = size } } diff --git a/LookInside/Static/LKStaticViewController.swift b/LookInside/Static/StaticViewController.swift similarity index 82% rename from LookInside/Static/LKStaticViewController.swift rename to LookInside/Static/StaticViewController.swift index 2bf2c855..8a2616a0 100644 --- a/LookInside/Static/LKStaticViewController.swift +++ b/LookInside/Static/StaticViewController.swift @@ -1,5 +1,5 @@ // -// LKStaticViewController.swift +// StaticViewController.swift // LookInside // // Created by Li Kai on 2018/8/4. @@ -12,56 +12,56 @@ import AppKit /// on the right the preview with the dashboard (or measure panel) over it, /// and the console under them; tips float above the preview. @objc(LKStaticViewController) -final class LKStaticViewController: LKBaseViewController, NSSplitViewDelegate { +final class StaticViewController: BaseViewController, NSSplitViewDelegate { /// Set when the fast mode tip is dismissed for good. private static let ignoreFastModeTipsDefaultsKey = "IgnoreFastModeTips" - /// The per-document data source, owned by LKStaticWindowController. - @objc private(set) weak var hierarchyDataSource: LKStaticHierarchyDataSource? + /// The per-document data source, owned by StaticWindowController. + @objc private(set) weak var hierarchyDataSource: StaticHierarchyDataSource? - /// The per-document update manager, owned by LKStaticWindowController. - @objc private(set) weak var asyncUpdateManager: LKStaticAsyncUpdateManager? + /// The per-document update manager, owned by StaticWindowController. + @objc private(set) weak var asyncUpdateManager: StaticAsyncUpdateManager? - @objc private(set) var viewsPreviewController: LKPreviewController! + @objc private(set) var viewsPreviewController: PreviewController! - @objc var progressView: LKProgressIndicatorView! + @objc var progressView: ProgressIndicatorView! /// Shows or hides the console under the preview. Observable with KVO. @objc dynamic var showConsole = false { didSet { applyShowConsole() } } - private var mainSplitView: LKSplitView! - private var rightSplitView: LKSplitView! - private var splitTopView: LKBaseView! + private var mainSplitView: SplitView! + private var rightSplitView: SplitView! + private var splitTopView: BaseView! - private var imageSyncTipsView: LKTipsView! - private var tooLargeToSyncScreenshotTipsView: LKRedTipsView! - private var userConfigNoPreviewTipsView: LKTipsView! - private var noPreviewTipView: LKTipsView! - private var customViewTipView: LKTipsView! - private var focusTipView: LKYellowTipsView! - private var fastModeTipView: LKTipsView! - private var serverUpgradeTipView: LKTipsView! + private var imageSyncTipsView: TipsView! + private var tooLargeToSyncScreenshotTipsView: RedTipsView! + private var userConfigNoPreviewTipsView: TipsView! + private var noPreviewTipView: TipsView! + private var customViewTipView: TipsView! + private var focusTipView: YellowTipsView! + private var fastModeTipView: TipsView! + private var serverUpgradeTipView: TipsView! /// Read with KVC by the DEBUG UI snapshots. - @objc private(set) var dashboardController: LKDashboardViewController! - private var hierarchyController: LKStaticHierarchyController! - private var consoleController: LKConsoleViewController? - private var measureController: LKMeasureController! + @objc private(set) var dashboardController: DashboardViewController! + private var hierarchyController: StaticHierarchyController! + private var consoleController: ConsoleViewController? + private var measureController: MeasureController! private var notificationObservers: [NSObjectProtocol] = [] private var keyValueObservations: [NSKeyValueObservation] = [] - private let dataSourceSignals = LKSyncSubscriptionBag() + private let dataSourceSignals = SyncSubscriptionBag() private var modifyingUpdatesTask: Task? /// Both arguments must be non-nil. The superclass initializer sets the /// view, and setting it builds the children that read them, so they are /// stored first. @objc(initWithHierarchyDataSource:asyncUpdateManager:) - init(hierarchyDataSource: LKStaticHierarchyDataSource?, asyncUpdateManager: LKStaticAsyncUpdateManager?) { + init(hierarchyDataSource: StaticHierarchyDataSource?, asyncUpdateManager: StaticAsyncUpdateManager?) { assert(hierarchyDataSource != nil && asyncUpdateManager != nil, - "LKStaticViewController requires non-nil per-doc data source and update manager") + "StaticViewController requires non-nil per-doc data source and update manager") self.hierarchyDataSource = hierarchyDataSource self.asyncUpdateManager = asyncUpdateManager super.init(containerView: nil) @@ -80,7 +80,7 @@ final class LKStaticViewController: LKBaseViewController, NSSplitViewDelegate { } override func makeContainerView() -> NSView { - let splitView = LKSplitView() + let splitView = SplitView() splitView.didFinishFirstLayout = { view in let x = min(max(350, view.bounds.size.width * 0.3), 700) view.setPosition(x, ofDividerAt: 0) @@ -108,35 +108,35 @@ final class LKStaticViewController: LKBaseViewController, NSSplitViewDelegate { // MARK: - Building private func buildContent() { - let preferenceManager = LKPreferenceManager.shared + let preferenceManager = PreferenceManager.shared preferenceManager.measureState.subscribe(self, action: #selector(handleMeasureStateChange(_:)), relatedObject: nil) // The initializer requires a data source (see its assert). let dataSource = hierarchyDataSource! - hierarchyController = LKStaticHierarchyController(dataSource: dataSource) + hierarchyController = StaticHierarchyController(dataSource: dataSource) addChild(hierarchyController) mainSplitView.addArrangedSubview(hierarchyController.view) // Hand the per-document update manager down the owner chain. hierarchyController.hierarchyView.asyncUpdateManager = asyncUpdateManager - rightSplitView = LKSplitView() + rightSplitView = SplitView() rightSplitView.arrangesAllSubviews = true rightSplitView.isVertical = false rightSplitView.dividerStyle = .thin rightSplitView.delegate = self mainSplitView.addArrangedSubview(rightSplitView) - splitTopView = LKBaseView() + splitTopView = BaseView() rightSplitView.addArrangedSubview(splitTopView) - viewsPreviewController = LKPreviewController(dataSource: dataSource) + viewsPreviewController = PreviewController(dataSource: dataSource) viewsPreviewController.staticViewController = self viewsPreviewController.asyncUpdateManager = asyncUpdateManager splitTopView.addSubview(viewsPreviewController.view) addChild(viewsPreviewController) - dashboardController = LKDashboardViewController(staticDataSource: dataSource) + dashboardController = DashboardViewController(staticDataSource: dataSource) dashboardController.asyncUpdateManager = asyncUpdateManager splitTopView.addSubview(dashboardController.view) addChild(dashboardController) @@ -145,19 +145,19 @@ final class LKStaticViewController: LKBaseViewController, NSSplitViewDelegate { // send per-document requests (dashboard, console). observeWindowBecomingMain { [weak self] in guard let self else { return } - let document = LookinLiveDocument.document(in: view.window) + let document = LiveDocument.document(in: view.window) dashboardController.liveDocument = document consoleController?.liveDocument = document } - measureController = LKMeasureController(dataSource: dataSource) + measureController = MeasureController(dataSource: dataSource) measureController.view.isHidden = true splitTopView.addSubview(measureController.view) addChild(measureController) buildTips() - progressView = LKProgressIndicatorView() + progressView = ProgressIndicatorView() view.addSubview(progressView) observeDataSource(dataSource) @@ -166,7 +166,7 @@ final class LKStaticViewController: LKBaseViewController, NSSplitViewDelegate { // Re-evaluating whenever a window becomes main covers both the first // window-document binding and reconnecting to a new app. observeWindowBecomingMain { [weak self] in - guard let self, let app = LookinLiveDocument.document(in: view.window)?.inspectableApp else { return } + guard let self, let app = LiveDocument.document(in: view.window)?.inspectableApp else { return } imageSyncTipsView.setImage(byAppInfo: app.appInfo) } @@ -192,17 +192,17 @@ final class LKStaticViewController: LKBaseViewController, NSSplitViewDelegate { } private func buildTips() { - imageSyncTipsView = LKTipsView() + imageSyncTipsView = TipsView() imageSyncTipsView.isHidden = true view.addSubview(imageSyncTipsView) - tooLargeToSyncScreenshotTipsView = LKRedTipsView() + tooLargeToSyncScreenshotTipsView = RedTipsView() tooLargeToSyncScreenshotTipsView.image = NSImage(named: "icon_info") tooLargeToSyncScreenshotTipsView.title = NSLocalizedString("Image is too large to be displayed.", comment: "") tooLargeToSyncScreenshotTipsView.isHidden = true view.addSubview(tooLargeToSyncScreenshotTipsView) - focusTipView = LKYellowTipsView() + focusTipView = YellowTipsView() focusTipView.image = NSImage(named: "icon_info") focusTipView.title = NSLocalizedString("Currently in focus mode", comment: "") focusTipView.isHidden = true @@ -211,7 +211,7 @@ final class LKStaticViewController: LKBaseViewController, NSSplitViewDelegate { focusTipView.clickAction = #selector(handleExitFocusTipView) view.addSubview(focusTipView) - fastModeTipView = LKTipsView() + fastModeTipView = TipsView() fastModeTipView.image = NSImage(named: "Icon_Inspiration_small") fastModeTipView.title = NSLocalizedString("Fast refresh mode is enabled, which may result in layer consistency issues.", comment: "") fastModeTipView.isHidden = true @@ -220,7 +220,7 @@ final class LKStaticViewController: LKBaseViewController, NSSplitViewDelegate { fastModeTipView.clickAction = #selector(handleFastModeTipViewClick) view.addSubview(fastModeTipView) - noPreviewTipView = LKTipsView() + noPreviewTipView = TipsView() noPreviewTipView.image = NSImage(named: "icon_hide") noPreviewTipView.title = NSLocalizedString("The screenshot of selected item is not displayed.", comment: "") noPreviewTipView.buttonText = NSLocalizedString("Display", comment: "") @@ -229,7 +229,7 @@ final class LKStaticViewController: LKBaseViewController, NSSplitViewDelegate { noPreviewTipView.isHidden = true view.addSubview(noPreviewTipView) - customViewTipView = LKTipsView() + customViewTipView = TipsView() customViewTipView.image = NSImage(named: "Icon_Inspiration_small") // The view class name depends on the inspected app, which is unknown // until a hierarchy arrives; handleSelectItemDidChange() refreshes @@ -241,7 +241,7 @@ final class LKStaticViewController: LKBaseViewController, NSSplitViewDelegate { customViewTipView.isHidden = true view.addSubview(customViewTipView) - userConfigNoPreviewTipsView = LKTipsView() + userConfigNoPreviewTipsView = TipsView() userConfigNoPreviewTipsView.image = NSImage(named: "icon_hide") userConfigNoPreviewTipsView.title = NSLocalizedString("The screenshot is not displayed due to the config in iOS App.", comment: "") userConfigNoPreviewTipsView.buttonText = NSLocalizedString("Details", comment: "") @@ -250,7 +250,7 @@ final class LKStaticViewController: LKBaseViewController, NSSplitViewDelegate { userConfigNoPreviewTipsView.isHidden = true view.addSubview(userConfigNoPreviewTipsView) - serverUpgradeTipView = LKTipsView() + serverUpgradeTipView = TipsView() serverUpgradeTipView.image = NSImage(named: "Icon_Inspiration_small") serverUpgradeTipView.title = NSLocalizedString("The app's integrator should upgrade LookInside Server.", comment: "Tip shown once per inspected app whose LookInside Server is 0.2.9 or older") serverUpgradeTipView.buttonText = NSLocalizedString("OK", comment: "") @@ -265,7 +265,7 @@ final class LKStaticViewController: LKBaseViewController, NSSplitViewDelegate { self?.updateServerUpgradeTip() } notificationObservers.append(NotificationCenter.default.addObserver( - forName: LKServerUpgradeHint.releaseDidArriveNotification, + forName: ServerUpgradeHint.releaseDidArriveNotification, object: nil, queue: nil ) { [weak self] _ in @@ -279,7 +279,7 @@ final class LKStaticViewController: LKBaseViewController, NSSplitViewDelegate { /// and no window showed the hint for that app during this launch. private func updateServerUpgradeTip() { guard serverUpgradeTipView.isHidden, - LKServerUpgradeHint.shouldShowHint(for: LookinLiveDocument.document(in: view.window)?.inspectableApp) + ServerUpgradeHint.shouldShowHint(for: LiveDocument.document(in: view.window)?.inspectableApp) else { return } @@ -287,7 +287,7 @@ final class LKStaticViewController: LKBaseViewController, NSSplitViewDelegate { view.needsLayout = true } - private func observeDataSource(_ dataSource: LKStaticHierarchyDataSource?) { + private func observeDataSource(_ dataSource: StaticHierarchyDataSource?) { guard let dataSource else { return } var isInitialSelection = true keyValueObservations.append(dataSource.observe(\.selectedItem, options: [.initial]) { [weak self] _, _ in @@ -332,21 +332,21 @@ final class LKStaticViewController: LKBaseViewController, NSSplitViewDelegate { override func viewDidLayout() { super.viewDidLayout() - let dashboardLayout = LKStaticLayout(dashboardController.view) + let dashboardLayout = StaticLayout(dashboardController.view) dashboardLayout.width(DashboardViewWidth) dashboardLayout.right(0) dashboardLayout.fullHeight() - let measureLayout = LKStaticLayout(measureController.view) + let measureLayout = StaticLayout(measureController.view) measureLayout.width(MeasureViewWidth) measureLayout.right(DashboardHorInset) measureLayout.fullHeight() - LKStaticLayout(viewsPreviewController.view).fullFrame() + StaticLayout(viewsPreviewController.view).fullFrame() - let windowTitleHeight = LKNavigationManager.shared.windowTitleBarHeight + let windowTitleHeight = NavigationManager.shared.windowTitleBarHeight - let progressLayout = LKStaticLayout(progressView) + let progressLayout = StaticLayout(progressView) progressLayout.fullWidth() progressLayout.height(3) progressLayout.y(windowTitleHeight) @@ -365,7 +365,7 @@ final class LKStaticViewController: LKBaseViewController, NSSplitViewDelegate { var tipsY = windowTitleHeight + 10 for tipsView in tips.compactMap({ $0 }) where Self.isVisible(tipsView) { let midX = hierarchyController.view.frame.width + (viewsPreviewController.view.frame.width - DashboardViewWidth) / 2 - let layout = LKStaticLayout(tipsView) + let layout = StaticLayout(tipsView) layout.sizeToFit() layout.y(tipsY) layout.midX(midX) @@ -395,15 +395,15 @@ final class LKStaticViewController: LKBaseViewController, NSSplitViewDelegate { private func applyShowConsole() { if showConsole { - let consoleController: LKConsoleViewController + let consoleController: ConsoleViewController if let existing = self.consoleController { consoleController = existing } else { guard let hierarchyDataSource else { return } - consoleController = LKConsoleViewController(hierarchyDataSource: hierarchyDataSource) + consoleController = ConsoleViewController(hierarchyDataSource: hierarchyDataSource) // Made on first show, so it takes the window's live document // at that moment. - consoleController.liveDocument = LookinLiveDocument.document(in: view.window) + consoleController.liveDocument = LiveDocument.document(in: view.window) addChild(consoleController) self.consoleController = consoleController } @@ -423,11 +423,11 @@ final class LKStaticViewController: LKBaseViewController, NSSplitViewDelegate { } /// The hierarchy view of the tree on the left. - @objc func currentHierarchyView() -> LKHierarchyView? { + @objc func currentHierarchyView() -> HierarchyView? { hierarchyController.hierarchyView } - private var dataSource: LKHierarchyDataSource? { + private var dataSource: HierarchyDataSource? { hierarchyController.dataSource } @@ -457,7 +457,7 @@ final class LKStaticViewController: LKBaseViewController, NSSplitViewDelegate { // MARK: - Events - private func handleModifyingUpdate(_ event: LKModifyingUpdateEvent) { + private func handleModifyingUpdate(_ event: ModifyingUpdateEvent) { switch event { case let .progress(received, total): let progress = CGFloat(received) / CGFloat(max(1, total)) @@ -501,7 +501,7 @@ final class LKStaticViewController: LKBaseViewController, NSSplitViewDelegate { } @objc private func handleCustomViewTipsView() { - LKHelper.showDisabledExternalLinkAlert(withMessage: NSLocalizedString( + AppHelper.showDisabledExternalLinkAlert(withMessage: NSLocalizedString( "Legacy custom information guides are disabled in this community build. See the repository README instead.", comment: "" )) @@ -539,7 +539,7 @@ final class LKStaticViewController: LKBaseViewController, NSSplitViewDelegate { } @objc private func handleFastModeDocumentation() { - LKHelper.showDisabledExternalLinkAlert(withMessage: NSLocalizedString( + AppHelper.showDisabledExternalLinkAlert(withMessage: NSLocalizedString( "Legacy fast mode documentation links are disabled in this community build. See the repository README instead.", comment: "" )) @@ -551,16 +551,16 @@ final class LKStaticViewController: LKBaseViewController, NSSplitViewDelegate { } @objc private func handleUserConfigNoPreviewTipView() { - LKHelper.openCustomConfigWebsite() + AppHelper.openCustomConfigWebsite() } - @objc private func handleMeasureStateChange(_ param: LookinMsgActionParams) { - let isMeasure = param.integerValue != LookinMeasureState.no.rawValue + @objc private func handleMeasureStateChange(_ param: MessageActionParameters) { + let isMeasure = param.integerValue != MeasureState.no.rawValue dashboardController.view.isHidden = isMeasure measureController.view.isHidden = !isMeasure } - @objc private func handleFastModeChange(_ param: LookinMsgActionParams) { + @objc private func handleFastModeChange(_ param: MessageActionParameters) { guard param.boolValue else { fastModeTipView.isHidden = true return @@ -599,7 +599,7 @@ final class LKStaticViewController: LKBaseViewController, NSSplitViewDelegate { let inspectedAppInfo = hierarchyController?.dataSource?.rawHierarchyInfo?.appInfo return String( format: NSLocalizedString("This object may not be a %@ or CALayer.", comment: ""), - LKHelper.viewClassName(for: inspectedAppInfo) + AppHelper.viewClassName(for: inspectedAppInfo) ) } } diff --git a/LookInside/Static/LKStaticWindowController.swift b/LookInside/Static/StaticWindowController.swift similarity index 87% rename from LookInside/Static/LKStaticWindowController.swift rename to LookInside/Static/StaticWindowController.swift index b21384c9..62b5abbb 100644 --- a/LookInside/Static/LKStaticWindowController.swift +++ b/LookInside/Static/StaticWindowController.swift @@ -1,5 +1,5 @@ // -// LKStaticWindowController.swift +// StaticWindowController.swift // LookInside // // Created by Li Kai on 2018/11/4. @@ -8,7 +8,7 @@ // The window of a live document: hierarchy, preview and dashboard of one // inspected app, with the inspector toolbar. Owns the document's hierarchy // data source and async update manager; every request goes to the app the -// owning LookinLiveDocument injects (`inspectableApp`). +// owning LiveDocument injects (`inspectableApp`). // import AppKit @@ -17,7 +17,7 @@ import UniformTypeIdentifiers @objc(LKStaticWindowController) @MainActor -final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @preconcurrency LKStaticAsyncUpdateManagerDelegate { +final class StaticWindowController: WindowController, NSToolbarDelegate, @preconcurrency StaticAsyncUpdateManagerDelegate { /// Who asked for a hierarchy reload. Recorded when a reload actually /// starts, so an observer of the data source's `didReloadHierarchyInfo` /// can attribute the reload it just saw. Reloads cannot overlap, so the @@ -65,17 +65,17 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr /// Implicitly unwrapped for the Swift callers written against the /// Objective-C header; set before init returns. - @objc private(set) var viewController: LKStaticViewController! + @objc private(set) var viewController: StaticViewController! /// Per-window hierarchy data source. - @objc private(set) var hierarchyDataSource: LKStaticHierarchyDataSource! + @objc private(set) var hierarchyDataSource: StaticHierarchyDataSource! /// Per-window async update manager. - @objc private(set) var asyncUpdateManager: LKStaticAsyncUpdateManager! + @objc private(set) var asyncUpdateManager: StaticAsyncUpdateManager! - /// Injected by the owning LookinLiveDocument, which also swaps it when + /// Injected by the owning LiveDocument, which also swaps it when /// the app reconnects; every request uses it. - @objc dynamic weak var inspectableApp: LKInspectableApp? { + @objc dynamic weak var inspectableApp: InspectableApp? { didSet { updateAppButton() } @@ -85,7 +85,7 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr private(set) var lastReloadInitiator: ReloadInitiator = .host private var toolbarItemsMap: [NSToolbarItem.Identifier: NSToolbarItem] = [:] - private var gestureDebugWindowController: LKGestureDebugWindowController? + private var gestureDebugWindowController: GestureDebugWindowController? /// The reload item as it was when the window was set up; the fetching /// state enables and disables this one. private var fetchingStateReloadItem: NSToolbarItem? @@ -108,12 +108,12 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr // MARK: - Init - /// Used by LookinLiveDocument: the window, data source and update + /// Used by LiveDocument: the window, data source and update /// manager, all bound to `app`. @objc(initWithInspectableApp:) - init(inspectableApp app: LKInspectableApp?) { + init(inspectableApp app: InspectableApp?) { let screenSize = NSScreen.main?.frame.size ?? .zero - let window = LKWindow( + let window = AppWindow( contentRect: NSRect(x: 0, y: 0, width: screenSize.width * 0.7, height: screenSize.height * 0.7), styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView], backing: .buffered, @@ -131,8 +131,8 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr // Saves this window's frame across launches. windowFrameAutosaveName = LKWindowSizeName_Static - let dataSource = LKStaticHierarchyDataSource() - let updateManager = LKStaticAsyncUpdateManager(hierarchyDataSource: dataSource, inspectableApp: nil) + let dataSource = StaticHierarchyDataSource() + let updateManager = StaticAsyncUpdateManager(hierarchyDataSource: dataSource, inspectableApp: nil) dataSource.asyncUpdateManager = updateManager hierarchyDataSource = dataSource asyncUpdateManager = updateManager @@ -146,7 +146,7 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr // Flipping the backing-layer toggle changes the node set itself, so // it always goes through a full server-side reload. - LKPreferenceManager.shared.showBackingLayers.subscribe( + PreferenceManager.shared.showBackingLayers.subscribe( self, action: #selector(handleShowBackingLayersDidChange(_:)), relatedObject: nil @@ -154,7 +154,7 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr // The view controller builds its view inside its initializer, so the // data source and update manager go in up front. - let viewController = LKStaticViewController(hierarchyDataSource: dataSource, asyncUpdateManager: updateManager) + let viewController = StaticViewController(hierarchyDataSource: dataSource, asyncUpdateManager: updateManager) self.viewController = viewController window.contentView = viewController.view contentViewController = viewController @@ -200,17 +200,17 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr } private func updateAppButton() { - let appButton = toolbarItemsMap[NSToolbarItem.Identifier(LKToolBarIdentifier_App)]?.view as? LKWindowToolbarAppButton + let appButton = toolbarItemsMap[NSToolbarItem.Identifier(LKToolBarIdentifier_App)]?.view as? WindowToolbarAppButton appButton?.appInfo = inspectableApp?.appInfo } // MARK: - Fetching /// Sends a hierarchy request to `app` and returns what it sent first. - private static func fetchHierarchy(from app: LKInspectableApp) async throws -> HierarchyFetchResult { + private static func fetchHierarchy(from app: InspectableApp) async throws -> HierarchyFetchResult { let responses = app.responses( type: UInt32(LookinRequestTypeHierarchy), - data: LKInspectableApp.hierarchyRequestParameters() + data: InspectableApp.hierarchyRequestParameters() ) for try await value in responses { return .info(value as? HierarchyInfo) @@ -219,7 +219,7 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr } private func alertError(_ error: Error?, in window: NSWindow?) { - let error = (error as NSError?) ?? LKConnectionError.inner + let error = (error as NSError?) ?? ConnectionError.inner guard error.code != LookinErrCode_Discard, let window else { return } @@ -240,9 +240,9 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr viewController.progressView.animate(toProgress: InitialIndicatorProgressWhenFetchHierarchy) Task { [weak self] in - let apps = await LKAppsManager.shared.fetchAppInfos(needImages: true, localInfos: nil) + let apps = await AppsManager.shared.fetchAppInfos(needImages: true, localInfos: nil) guard let self else { return } - let targetApp: LKInspectableApp? + let targetApp: InspectableApp? if !targetBundleID.isEmpty { targetApp = apps.first { $0.appInfo?.appBundleIdentifier == targetBundleID } } else { @@ -271,9 +271,9 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr let appItemView = toolbarItemsMap[NSToolbarItem.Identifier(LKToolBarIdentifier_App)]?.view Task { [weak self] in - let apps = await LKAppsManager.shared.fetchAppInfos(needImages: true, localInfos: nil) + let apps = await AppsManager.shared.fetchAppInfos(needImages: true, localInfos: nil) guard let self else { return } - let listController = LKMenuPopoverAppsListController(apps: apps, source: source) + let listController = MenuPopoverAppsListController(apps: apps, source: source) let popover = NSPopover() listController.didSelectApp = { [weak self, weak popover] app in popover?.close() @@ -289,18 +289,18 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr } } - private func didSelectAppInPicker(_ app: LKInspectableApp) { + private func didSelectAppInPicker(_ app: InspectableApp) { if let versionError = app.serverVersionError { if versionError.code == LookinErrCode_ServerVersionTooLow { - LKHelper.openLookinWebsite(withPath: "faq/server-version-too-low/") + AppHelper.openLookinWebsite(withPath: "faq/server-version-too-low/") } else { - LKHelper.openLookinWebsite(withPath: "faq/server-version-too-high/") + AppHelper.openLookinWebsite(withPath: "faq/server-version-too-high/") } return } // A different app opens in a new window rather than swapping this - // window's target; LookinLiveDocumentController brings forward a + // window's target; LiveDocumentController brings forward a // window already open on the same channel. let currentInfo = inspectableApp?.appInfo let isTheSameApp = currentInfo.map { $0.isEqual(app.appInfo) } ?? false @@ -311,8 +311,8 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr // window, so this window's session is never disturbed. A picker // click always means "inspect now", so the hierarchy is fetched // even when the document was already open. - let (document, alreadyOpen) = LookinLiveDocumentController.shared.openLiveDocument(for: app) - guard let targetController = document.windowControllers.first as? LKStaticWindowController else { + let (document, alreadyOpen) = LiveDocumentController.shared.openLiveDocument(for: app) + guard let targetController = document.windowControllers.first as? StaticWindowController else { return } targetController.viewController.progressView.animate(toProgress: InitialIndicatorProgressWhenFetchHierarchy) @@ -323,7 +323,7 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr } guard let info else { targetController.viewController.progressView.resetToZero() - targetController.alertError(LKConnectionError.inner, in: targetController.window) + targetController.alertError(ConnectionError.inner, in: targetController.window) return } targetController.applyHierarchyInfo(info, for: app, keepState: alreadyOpen) @@ -390,7 +390,7 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr lastReloadInitiator = initiator isFetchingHierarchy = true viewController.progressView.animate(toProgress: InitialIndicatorProgressWhenFetchHierarchy) - LKPerformanceReporter.sharedInstance().willStartReload() + PerformanceReporter.sharedInstance().willStartReload() Task { [weak self] in let result: HierarchyFetchResult @@ -417,7 +417,7 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr viewController.progressView.finish(completion: nil) hierarchyDataSource.reload(with: info, keepState: true) isFetchingHierarchy = false - LKPerformanceReporter.sharedInstance().didFetchHierarchy() + PerformanceReporter.sharedInstance().didFetchHierarchy() completion(.success(info)) case .noResponse: // Left unhandled this would strand every party: the reload @@ -459,7 +459,7 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr .flexibleSpace, NSToolbarItem.Identifier(LKToolBarIdentifier_Measure), NSToolbarItem.Identifier(LKToolBarIdentifier_Console), ] - if !LKMessageManager.sharedInstance().queryMessages().isEmpty { + if !MessageManager.sharedInstance().queryMessages().isEmpty { identifiers.append(NSToolbarItem.Identifier(LKToolBarIdentifier_Message)) } return identifiers @@ -473,9 +473,9 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr if let item = toolbarItemsMap[itemIdentifier] { return item } - guard let item = LKWindowToolbarHelper.shared.makeToolBarItem( + guard let item = WindowToolbarHelper.shared.makeToolBarItem( identifier: itemIdentifier.rawValue, - preferenceManager: LKPreferenceManager.shared + preferenceManager: PreferenceManager.shared ) else { return nil } @@ -492,7 +492,7 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr item.target = self item.action = #selector(handleApp) // Shows the bound app's icon; `inspectableApp` updates it when - // LookinLiveDocument swaps in the reconnected app. + // LiveDocument swaps in the reconnected app. updateAppButton() case NSToolbarItem.Identifier(LKToolBarIdentifier_Rotation): item.target = self @@ -549,7 +549,7 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr } @objc(_handleShowBackingLayersDidChange:) - private func handleShowBackingLayersDidChange(_: LookinMsgActionParams) { + private func handleShowBackingLayersDidChange(_: MessageActionParameters) { // No app bound or a reload already running: the new value still // applies on the next manual reload, so refusals stay quiet. reloadHierarchy { _ in } @@ -565,17 +565,17 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr let popover = NSPopover() popover.behavior = .transient popover.animates = false - popover.contentSize = NSSize(width: LKHelper.isEnglish() ? 270 : 350, height: 260) - popover.contentViewController = LKMenuPopoverSettingController( - preferenceManager: LKPreferenceManager.shared, - isMacTarget: LKHelper.appInfoLooksLikeMacTarget(inspectableApp?.appInfo) + popover.contentSize = NSSize(width: AppHelper.isEnglish() ? 270 : 350, height: 260) + popover.contentViewController = MenuPopoverSettingController( + preferenceManager: PreferenceManager.shared, + isMacTarget: AppHelper.appInfoLooksLikeMacTarget(inspectableApp?.appInfo) ) popover.show(relativeTo: button.bounds, of: button, preferredEdge: .maxY) } @objc(_handleGestureDebug) private func handleGestureDebug() { - let controller = gestureDebugWindowController ?? LKGestureDebugWindowController(owner: self) + let controller = gestureDebugWindowController ?? GestureDebugWindowController(owner: self) gestureDebugWindowController = controller controller.showWindow(self) controller.window?.makeKeyAndOrderFront(self) @@ -587,14 +587,14 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr } @objc func handleFastMode() { - let fastMode = LKPreferenceManager.shared.fastMode + let fastMode = PreferenceManager.shared.fastMode fastMode.setBOOLValue(!fastMode.currentBOOLValue, ignoreSubscriber: nil) } @objc(_handleMessage:) private func handleMessage(_ button: NSButton) { let menu = NSMenu() - for message in LKMessageManager.sharedInstance().queryMessages() { + for message in MessageManager.sharedInstance().queryMessages() { if message == LKMessage_Jobs { let item = NSMenuItem() item.image = NSImage(named: "Icon_Inspiration_small") @@ -631,20 +631,20 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr @objc(_handleFreeRotation) private func handleFreeRotation() { - let freeRotation = LKPreferenceManager.shared.freeRotation + let freeRotation = PreferenceManager.shared.freeRotation freeRotation.setBOOLValue(!freeRotation.currentBOOLValue, ignoreSubscriber: nil) } @objc func handleJobsMenuItem() { - LKHelper.showDisabledExternalLinkAlert(withMessage: NSLocalizedString("This upstream community link is not available in this build.", comment: "")) - LKMessageManager.sharedInstance().removeMessage(LKMessage_Jobs) + AppHelper.showDisabledExternalLinkAlert(withMessage: NSLocalizedString("This upstream community link is not available in this build.", comment: "")) + MessageManager.sharedInstance().removeMessage(LKMessage_Jobs) } @objc func handleTurnOnSwift() { - LKHelper.showDisabledExternalLinkAlert(withMessage: NSLocalizedString("Legacy Swift integration guides are disabled in this community build. See the repository README instead.", comment: "")) + AppHelper.showDisabledExternalLinkAlert(withMessage: NSLocalizedString("Legacy Swift integration guides are disabled in this community build. See the repository README instead.", comment: "")) } - // MARK: - LKAppMenuManagerDelegate + // MARK: - AppMenuManagerDelegate @objc func appMenuManagerDidSelectReload() { if isFetchingHierarchy { @@ -664,9 +664,9 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr } @objc func appMenuManagerDidSelectDimension() { - let dimension = LKPreferenceManager.shared.previewDimension - let dimension2D = Int(LookinPreviewDimension.dimension2D.rawValue) - let dimension3D = Int(LookinPreviewDimension.dimension3D.rawValue) + let dimension = PreferenceManager.shared.previewDimension + let dimension2D = Int(PreviewDimension.dimension2D.rawValue) + let dimension3D = Int(PreviewDimension.dimension3D.rawValue) dimension.setIntegerValue(dimension.currentIntegerValue == dimension2D ? dimension3D : dimension2D, ignoreSubscriber: nil) } @@ -679,7 +679,7 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr } private func adjustPreviewScale(by delta: Double) { - let scale = LKPreferenceManager.shared.previewScale + let scale = PreferenceManager.shared.previewScale let target = min(max(scale.currentDoubleValue + delta, Double(LookinPreviewMinScale)), Double(LookinPreviewMaxScale)) scale.setDoubleValue(target, ignoreSubscriber: nil) } @@ -693,7 +693,7 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr } private func adjustZInterspace(by delta: Double) { - let interspace = LKPreferenceManager.shared.zInterspace + let interspace = PreferenceManager.shared.zInterspace let target = min(max(interspace.currentDoubleValue + delta, Double(LookinPreviewMinZInterspace)), Double(LookinPreviewMaxZInterspace)) interspace.setDoubleValue(target, ignoreSubscriber: nil) } @@ -710,12 +710,12 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr var fileName: NSString? var exportedData: Data? - let accessoryView = LKExportAccessoryView() + let accessoryView = ExportAccessoryView() // The data is rebuilt whenever the accessory view changes the // compression, for as long as the panel is up. - let compressionObservation = LKPreferenceManager.shared.observe(\.preferredExportCompression, options: [.initial, .new]) { manager, _ in + let compressionObservation = PreferenceManager.shared.observe(\.preferredExportCompression, options: [.initial, .new]) { manager, _ in MainActor.assumeIsolated { - exportedData = LKExportManager.sharedInstance().data( + exportedData = ExportManager.sharedInstance().data( from: hierarchyInfo, imageCompression: manager.preferredExportCompression, fileName: &fileName @@ -756,14 +756,14 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr let file = HierarchyFile() file.serverVersion = newHierarchyInfo?.serverVersion ?? 0 file.hierarchyInfo = newHierarchyInfo - LKNavigationManager.shared.showReader(with: file, title: nil) + NavigationManager.shared.showReader(with: file, title: nil) } @objc func appMenuManagerDidSelectFilter() { viewController.currentHierarchyView()?.activateSearchBar() } - // MARK: - LKStaticAsyncUpdateManagerDelegate + // MARK: - StaticAsyncUpdateManagerDelegate func detailUpdateTasksTotalCount(_ totalCount: UInt, finishedCount: UInt) { let reloadItem = toolbarItemsMap[NSToolbarItem.Identifier(LKToolBarIdentifier_Reload)] @@ -797,7 +797,7 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr /// Binds `app` to this window and loads `info`. Every same-window /// reload (auto-connect, toolbar same app, SwiftUI mode) goes through /// here. - private func applyHierarchyInfo(_ info: HierarchyInfo?, for app: LKInspectableApp, keepState: Bool) { + private func applyHierarchyInfo(_ info: HierarchyInfo?, for app: InspectableApp, keepState: Bool) { viewController.progressView.finish(completion: nil) inspectableApp = app asyncUpdateManager.inspectableApp = app @@ -805,7 +805,7 @@ final class LKStaticWindowController: LKWindowController, NSToolbarDelegate, @pr // Move this bundle id to the front of the expansion-state LRU, so // inspected apps aren't evicted just because nothing was toggled yet. - LKPreferenceManager.shared.bumpExpansionStateBundleIdentifierToMostRecent(info?.appInfo?.appBundleIdentifier) + PreferenceManager.shared.bumpExpansionStateBundleIdentifierToMostRecent(info?.appInfo?.appBundleIdentifier) } @objc(_handleSwiftUIModeDidChange:) diff --git a/LookInside/SwiftUISupport/LKSwiftUIHierarchyDisplayMode.swift b/LookInside/SwiftUISupport/SwiftUIHierarchyDisplayMode.swift similarity index 75% rename from LookInside/SwiftUISupport/LKSwiftUIHierarchyDisplayMode.swift rename to LookInside/SwiftUISupport/SwiftUIHierarchyDisplayMode.swift index 3c0bea3b..d357b8a8 100644 --- a/LookInside/SwiftUISupport/LKSwiftUIHierarchyDisplayMode.swift +++ b/LookInside/SwiftUISupport/SwiftUIHierarchyDisplayMode.swift @@ -1,38 +1,38 @@ // -// LKSwiftUIHierarchyDisplayMode.swift +// SwiftUIHierarchyDisplayMode.swift // LookInside // import AppKit -@objc enum LKSwiftUIHierarchyDisplayMode: Int { +@objc enum SwiftUIHierarchyDisplayMode: Int { case verbose = 0 case compact = 1 } extension Notification.Name { /// Posted on the main thread whenever - /// `LKSwiftUIHierarchyDisplayModeStore.currentMode()` changes. + /// `SwiftUIHierarchyDisplayModeStore.currentMode()` changes. /// Notification object: the store class. static let LKSwiftUIHierarchyDisplayModeDidChange = Notification.Name("LKSwiftUIHierarchyDisplayModeDidChangeNotification") } @objc(LKSwiftUIHierarchyDisplayModeStore) -final class LKSwiftUIHierarchyDisplayModeStore: NSObject { +final class SwiftUIHierarchyDisplayModeStore: NSObject { private static let defaultsKey = "LookInside.SwiftUIHierarchyDisplayMode" /// Default = compact when no value persisted yet. - static func currentMode() -> LKSwiftUIHierarchyDisplayMode { + static func currentMode() -> SwiftUIHierarchyDisplayMode { let defaults = UserDefaults.standard guard defaults.object(forKey: defaultsKey) != nil else { return .compact } - return LKSwiftUIHierarchyDisplayMode(rawValue: defaults.integer(forKey: defaultsKey)) ?? .compact + return SwiftUIHierarchyDisplayMode(rawValue: defaults.integer(forKey: defaultsKey)) ?? .compact } /// Persist the new mode to UserDefaults and post /// LKSwiftUIHierarchyDisplayModeDidChange if the value actually changed. - static func setCurrentMode(_ mode: LKSwiftUIHierarchyDisplayMode) { + static func setCurrentMode(_ mode: SwiftUIHierarchyDisplayMode) { guard currentMode() != mode else { return } diff --git a/LookInside/SwiftUISupport/LKSwiftUISupportGatekeeper.swift b/LookInside/SwiftUISupport/SwiftUISupportGatekeeper.swift similarity index 94% rename from LookInside/SwiftUISupport/LKSwiftUISupportGatekeeper.swift rename to LookInside/SwiftUISupport/SwiftUISupportGatekeeper.swift index d8c033e4..a704ecec 100644 --- a/LookInside/SwiftUISupport/LKSwiftUISupportGatekeeper.swift +++ b/LookInside/SwiftUISupport/SwiftUISupportGatekeeper.swift @@ -3,7 +3,7 @@ import Foundation import LookInsideActivation import LookInsideActivationUI -@objc public enum LKSwiftUISupportActivationState: Int { +@objc public enum SwiftUISupportActivationState: Int { case unknown case notActivated case activated @@ -25,7 +25,7 @@ import LookInsideActivationUI } } -private enum LKSwiftUISupportGatekeeperConstants { +private enum SwiftUISupportGatekeeperConstants { /// How often the stored license state is re-evaluated, so a lease that runs /// out while LookInside is open closes access without a user action. static let monitoringInterval: Duration = .seconds(60) @@ -39,8 +39,8 @@ private enum LKSwiftUISupportGatekeeperConstants { /// runtime reads and writes the helper's `state.json` and keychain key; this /// class never launches, updates or removes the helper. @objcMembers -public final class LKSwiftUISupportGatekeeper: NSObject { - private static let shared = LKSwiftUISupportGatekeeper(runtime: ActivationRuntime()) +public final class SwiftUISupportGatekeeper: NSObject { + private static let shared = SwiftUISupportGatekeeper(runtime: ActivationRuntime()) public static let activationStateDidChangeNotification = Notification.Name( "LKSwiftUISupportActivationStateDidChangeNotification" @@ -65,7 +65,7 @@ public final class LKSwiftUISupportGatekeeper: NSObject { private let runtime: ActivationRuntime private let stateLock = NSLock() - private var publishedState: LKSwiftUISupportActivationState + private var publishedState: SwiftUISupportActivationState private var publishedStatusSummary: String? private var stateRefreshInFlight = false private var licenseStatusRefreshInFlight = false @@ -92,11 +92,11 @@ public final class LKSwiftUISupportGatekeeper: NSObject { init(runtime: ActivationRuntime, monitorsState: Bool = true) { self.runtime = runtime let initialDecision = runtime.lastDecision - publishedState = LKSwiftUISupportActivationState(initialDecision) + publishedState = SwiftUISupportActivationState(initialDecision) publishedStatusSummary = initialDecision?.statusSummary presentsKeychainExplainer = monitorsState super.init() - LKSwiftUISupportLogger.activation.info( + SwiftUISupportLogger.activation.info( // Logger interpolations are escaping autoclosures. // swiftformat:disable:next redundantSelf "activation runtime ready, state=\(self.publishedState.lkDebugDescription, privacy: .public)" @@ -108,7 +108,7 @@ public final class LKSwiftUISupportGatekeeper: NSObject { self?.recordSigningStatus(status) } if monitorsState { - runtime.startMonitoring(interval: LKSwiftUISupportGatekeeperConstants.monitoringInterval) + runtime.startMonitoring(interval: SwiftUISupportGatekeeperConstants.monitoringInterval) allowSigningAfterFirstWindow() } else { // Without an app around it (tests, the end-to-end harness) there @@ -155,7 +155,7 @@ public final class LKSwiftUISupportGatekeeper: NSObject { return handshakeGeneration != status.handshakeGeneration } guard shouldNotify else { return } - LKSwiftUISupportLogger.activation.info( + SwiftUISupportLogger.activation.info( "license handshakes may start again (generation \(status.handshakeGeneration, privacy: .public))" ) DispatchQueue.main.async { @@ -173,18 +173,18 @@ public final class LKSwiftUISupportGatekeeper: NSObject { onMain { coordinator in guard runtime.signingStatus.needsKeychainAccessExplainer else { return } let window = NSApp.mainWindow ?? NSApp.keyWindow ?? NSApp.windows.first { $0.isVisible } - LKSwiftUISupportLogger.activation.info("showing the keychain access explainer") + SwiftUISupportLogger.activation.info("showing the keychain access explainer") coordinator.showKeychainAccessExplainer(over: window) } } - @objc public class func sharedInstance() -> LKSwiftUISupportGatekeeper { + @objc public class func sharedInstance() -> SwiftUISupportGatekeeper { shared } // MARK: - State - public var activationState: LKSwiftUISupportActivationState { + public var activationState: SwiftUISupportActivationState { stateLock.withLock { publishedState } } @@ -212,8 +212,8 @@ public final class LKSwiftUISupportGatekeeper: NSObject { } private func recordDecision(_ decision: ActivationAccessDecision) { - let newState = LKSwiftUISupportActivationState(decision) - var previousState = LKSwiftUISupportActivationState.unknown + let newState = SwiftUISupportActivationState(decision) + var previousState = SwiftUISupportActivationState.unknown let shouldNotify: Bool = stateLock.withLock { let stateChanged = publishedState != newState let licenseMaterialMayHaveChanged = newState == .activated @@ -225,7 +225,7 @@ public final class LKSwiftUISupportGatekeeper: NSObject { return true } guard shouldNotify else { return } - LKSwiftUISupportLogger.activation.info( + SwiftUISupportLogger.activation.info( "activation state changed: \(previousState.lkDebugDescription, privacy: .public) -> \(newState.lkDebugDescription, privacy: .public) (decision=\(decision.decision.rawValue, privacy: .public))" ) DispatchQueue.main.async { @@ -279,7 +279,7 @@ public final class LKSwiftUISupportGatekeeper: NSObject { private func evaluateDecisionBlocking() -> ActivationAccessDecision { let runtime = runtime - let box = LKSwiftUISupportDecisionBox() + let box = SwiftUISupportDecisionBox() let semaphore = DispatchSemaphore(value: 0) Task.detached(priority: .userInitiated) { box.decision = await runtime.currentDecision() @@ -384,7 +384,7 @@ public final class LKSwiftUISupportGatekeeper: NSObject { result = measured.signature keyUseDurationOut?.pointee = measured.keyUseDuration } catch let error as ActivationError { - LKSwiftUISupportLogger.activation.error( + SwiftUISupportLogger.activation.error( "sign_challenge failed code=\(error.errorCode, privacy: .public)" ) throw error @@ -440,7 +440,7 @@ public final class LKSwiftUISupportGatekeeper: NSObject { ActivationAlert(title: decision.title, message: decision.message, style: .warning) ) } catch { - LKSwiftUISupportLogger.activation.error( + SwiftUISupportLogger.activation.error( "license status refresh failed: \(error.localizedDescription, privacy: .public)" ) coordinator.showAlert( @@ -540,7 +540,7 @@ public final class LKSwiftUISupportGatekeeper: NSObject { let runtime = runtime Task { [weak self, weak window] in guard await runtime.hasLicenseMaterial() else { - LKSwiftUISupportLogger.activation.info( + SwiftUISupportLogger.activation.info( "activation prompt skipped: no local license material" ) return @@ -604,13 +604,13 @@ public final class LKSwiftUISupportGatekeeper: NSObject { } } -private final class LKSwiftUISupportDecisionBox: @unchecked Sendable { +private final class SwiftUISupportDecisionBox: @unchecked Sendable { var decision: ActivationAccessDecision? } #if DEBUG - public extension LKSwiftUISupportGatekeeper { - /// DEBUG end-to-end hook (LKDebugE2EDump.swift): creates the license key + public extension SwiftUISupportGatekeeper { + /// DEBUG end-to-end hook (DebugE2EDump.swift): creates the license key /// in the test file keychain and returns a certificate request for /// it. See `ActivationRuntime.debugMakeTestKeyCertificateSigningRequestPEM`. @objc(debugMakeTestKeyCertificateSigningRequestPEMWithCommonName:error:) @@ -618,7 +618,7 @@ private final class LKSwiftUISupportDecisionBox: @unchecked Sendable { try runtime.debugMakeTestKeyCertificateSigningRequestPEM(commonName: commonName) } - /// DEBUG end-to-end hook (LKDebugE2EDump.swift): the Host runs behind + /// DEBUG end-to-end hook (DebugE2EDump.swift): the Host runs behind /// other apps there, so its window never becomes key. The dump calls /// this once a Host window is visible, the condition this gatekeeper /// itself accepts when it is created after the first window. @@ -627,7 +627,7 @@ private final class LKSwiftUISupportDecisionBox: @unchecked Sendable { runtime.noteFirstWindowShown() } - /// DEBUG UI snapshot hook (LKDebugUISnapshots.swift): the activation + /// DEBUG UI snapshot hook (DebugUISnapshots.swift): the activation /// window with its model restored from the activation state, as /// `showActivationWindow()` prepares it, but not presented: the /// snapshot shows it without activating the app or floating it. diff --git a/LookInside/SwiftUISupport/LKSwiftUISupportLogger.swift b/LookInside/SwiftUISupport/SwiftUISupportLogger.swift similarity index 84% rename from LookInside/SwiftUISupport/LKSwiftUISupportLogger.swift rename to LookInside/SwiftUISupport/SwiftUISupportLogger.swift index 29de4451..9139960b 100644 --- a/LookInside/SwiftUISupport/LKSwiftUISupportLogger.swift +++ b/LookInside/SwiftUISupport/SwiftUISupportLogger.swift @@ -1,7 +1,7 @@ import Foundation import os -enum LKSwiftUISupportLogger { +enum SwiftUISupportLogger { static let activation = Logger(subsystem: subsystem, category: "Activation") private static let subsystem = "com.lookinside.app" diff --git a/LookInside/Toolbar/LKMenuPopoverAppsListController.swift b/LookInside/Toolbar/MenuPopoverAppsListController.swift similarity index 78% rename from LookInside/Toolbar/LKMenuPopoverAppsListController.swift rename to LookInside/Toolbar/MenuPopoverAppsListController.swift index 1dd2b494..74b3669e 100644 --- a/LookInside/Toolbar/LKMenuPopoverAppsListController.swift +++ b/LookInside/Toolbar/MenuPopoverAppsListController.swift @@ -1,5 +1,5 @@ // -// LKMenuPopoverAppsListController.swift +// MenuPopoverAppsListController.swift // Lookin // // Created by Li Kai on 2018/11/5. @@ -11,28 +11,28 @@ import AppKit /// The popover that lists the inspectable apps, opened from the app button, /// the reload button or the connection-lost tips. @objc(LKMenuPopoverAppsListController) -final class LKMenuPopoverAppsListController: LKBaseViewController { +final class MenuPopoverAppsListController: BaseViewController { private let insets = NSEdgeInsets(top: 9, left: 18, bottom: 35, right: 14) private let titleMarginBottom: CGFloat = 3 private let subtitleMarginBottom: CGFloat = 5 private let appViewInterSpace: CGFloat = 1 - private var appViews: [LKLaunchAppView] = [] - private var titleLabel: LKLabel? - private var subtitleLabel: LKLabel? + private var appViews: [LaunchAppView] = [] + private var titleLabel: TextLabel? + private var subtitleLabel: TextLabel? - @objc var didSelectApp: ((LKInspectableApp) -> Void)? + @objc var didSelectApp: ((InspectableApp) -> Void)? @objc(initWithApps:source:) - init(apps: [LKInspectableApp]?, source: MenuPopoverAppsListControllerEventSource) { + init(apps: [InspectableApp]?, source: MenuPopoverAppsListControllerEventSource) { // The apps scan sends nil when no port is connected. let apps = apps ?? [] super.init(containerView: nil) - let copy = LKToolbarRules.appsPopoverCopy(source: source, appCount: apps.count) + let copy = ToolbarRules.appsPopoverCopy(source: source, appCount: apps.count) appViews = apps.map { app in - let appView = LKLaunchAppView() + let appView = LaunchAppView() appView.compactLayout = true appView.app = app appView.addTarget(self, clickAction: #selector(handleClickAppView(_:))) @@ -53,8 +53,8 @@ final class LKMenuPopoverAppsListController: LKBaseViewController { fatalError("init(coder:) is not supported") } - private func makeLabel(_ text: String, fontSize: CGFloat) -> LKLabel { - let label = LKLabel() + private func makeLabel(_ text: String, fontSize: CGFloat) -> TextLabel { + let label = TextLabel() label.alignment = .center label.font = NSFont.systemFont(ofSize: fontSize) label.textColor = .labelColor @@ -68,28 +68,28 @@ final class LKMenuPopoverAppsListController: LKBaseViewController { var y = insets.top if let titleLabel { - LKViewFrameLayout(titleLabel).fullWidth().heightToFit().y(y) + ViewFrameLayout(titleLabel).fullWidth().heightToFit().y(y) y = titleLabel.frame.maxY + titleMarginBottom } if let subtitleLabel { - LKViewFrameLayout(subtitleLabel).fullWidth().heightToFit().y(y) + ViewFrameLayout(subtitleLabel).fullWidth().heightToFit().y(y) y = subtitleLabel.frame.maxY + subtitleMarginBottom } if appViews.isEmpty { let labels = [titleLabel, subtitleLabel].compactMap { $0 }.filter { !$0.isHidden } - LKViewFrameLayout.groupVerAlign(labels) + ViewFrameLayout.groupVerAlign(labels) } else { var posX: CGFloat = 0 for appView in appViews { - LKViewFrameLayout(appView).sizeToFit().x(posX).y(y) + ViewFrameLayout(appView).sizeToFit().x(posX).y(y) posX = appView.frame.maxX + appViewInterSpace } - LKViewFrameLayout.groupHorAlign(appViews) + ViewFrameLayout.groupHorAlign(appViews) } } - @objc private func handleClickAppView(_ appView: LKLaunchAppView) { + @objc private func handleClickAppView(_ appView: LaunchAppView) { guard let app = appView.app else { return } didSelectApp?(app) } diff --git a/LookInside/Toolbar/LKMenuPopoverSettingController.swift b/LookInside/Toolbar/MenuPopoverSettingController.swift similarity index 77% rename from LookInside/Toolbar/LKMenuPopoverSettingController.swift rename to LookInside/Toolbar/MenuPopoverSettingController.swift index 9a10d42a..48e74fbd 100644 --- a/LookInside/Toolbar/LKMenuPopoverSettingController.swift +++ b/LookInside/Toolbar/MenuPopoverSettingController.swift @@ -1,5 +1,5 @@ // -// LKMenuPopoverSettingController.swift +// MenuPopoverSettingController.swift // Lookin // // Created by Li Kai on 2019/1/9. @@ -12,21 +12,21 @@ import AppKit /// layout guides, backing layers, item separation, and a way to the /// preferences. @objc(LKMenuPopoverSettingController) -final class LKMenuPopoverSettingController: LKBaseViewController { - private let manager: LKPreferenceManager +final class MenuPopoverSettingController: BaseViewController { + private let manager: PreferenceManager private let enableOutlineButton = NSButton() private let showInvisiblesButton = NSButton() private let showSystemLayoutGuidesButton = NSButton() private let showBackingLayersButton = NSButton() private let spaceSlider = NSSlider() - private let spaceSliderLabel = LKLabel() - private let preferenceButton = LKMenuPopoverSettingController.makePreferenceButton() + private let spaceSliderLabel = TextLabel() + private let preferenceButton = MenuPopoverSettingController.makePreferenceButton() /// `isMacTarget` describes the app being inspected, not the host. It decides whether the /// copy talks about `NSView` or `UIView`. @objc(initWithPreferenceManager:isMacTarget:) - init(preferenceManager manager: LKPreferenceManager, isMacTarget: Bool) { + init(preferenceManager manager: PreferenceManager, isMacTarget: Bool) { self.manager = manager super.init(containerView: nil) @@ -40,7 +40,7 @@ final class LKMenuPopoverSettingController: LKBaseViewController { showInvisiblesButton, title: String( format: NSLocalizedString("Show hidden %@ and CALayer", comment: ""), - LKHelper.viewClassName(forMacTarget: isMacTarget) + AppHelper.viewClassName(forMacTarget: isMacTarget) ), action: #selector(handleShowInvisiblesControl), isOn: manager.showHiddenItems.currentBOOLValue @@ -102,15 +102,15 @@ final class LKMenuPopoverSettingController: LKBaseViewController { override func viewDidLayout() { super.viewDidLayout() - LKViewFrameLayout(enableOutlineButton).x(15).toRight(0).height(24).y(15) - LKViewFrameLayout(showInvisiblesButton).x(15).toRight(0).height(24).y(enableOutlineButton.frame.maxY + 6) - LKViewFrameLayout(showSystemLayoutGuidesButton).x(15).toRight(0).height(24).y(showInvisiblesButton.frame.maxY + 6) - LKViewFrameLayout(showBackingLayersButton).x(15).toRight(0).height(24).y(showSystemLayoutGuidesButton.frame.maxY + 6) + ViewFrameLayout(enableOutlineButton).x(15).toRight(0).height(24).y(15) + ViewFrameLayout(showInvisiblesButton).x(15).toRight(0).height(24).y(enableOutlineButton.frame.maxY + 6) + ViewFrameLayout(showSystemLayoutGuidesButton).x(15).toRight(0).height(24).y(showInvisiblesButton.frame.maxY + 6) + ViewFrameLayout(showBackingLayersButton).x(15).toRight(0).height(24).y(showSystemLayoutGuidesButton.frame.maxY + 6) - LKViewFrameLayout(spaceSlider).x(15).toRight(15).height(26).y(showBackingLayersButton.frame.maxY + 22) - LKViewFrameLayout(spaceSliderLabel).sizeToFit().x(spaceSlider.frame.minX + 3).y(spaceSlider.frame.maxY) + ViewFrameLayout(spaceSlider).x(15).toRight(15).height(26).y(showBackingLayersButton.frame.maxY + 22) + ViewFrameLayout(spaceSliderLabel).sizeToFit().x(spaceSlider.frame.minX + 3).y(spaceSlider.frame.maxY) - LKViewFrameLayout(preferenceButton).width(130).horAlign().bottom(4) + ViewFrameLayout(preferenceButton).width(130).horAlign().bottom(4) } @objc private func handleOutlineControl() { @@ -134,10 +134,10 @@ final class LKMenuPopoverSettingController: LKBaseViewController { } @objc private func handlePreferenceButton() { - LKNavigationManager.shared.showPreference() + NavigationManager.shared.showPreference() } - @objc private func handleZInterspaceDidChange(_ param: LookinMsgActionParams) { + @objc private func handleZInterspaceDidChange(_ param: MessageActionParameters) { spaceSlider.doubleValue = param.doubleValue } } diff --git a/LookInside/Toolbar/LKToolbarRules.swift b/LookInside/Toolbar/ToolbarRules.swift similarity index 98% rename from LookInside/Toolbar/LKToolbarRules.swift rename to LookInside/Toolbar/ToolbarRules.swift index 389d104b..e28b9052 100644 --- a/LookInside/Toolbar/LKToolbarRules.swift +++ b/LookInside/Toolbar/ToolbarRules.swift @@ -1,5 +1,5 @@ // -// LKToolbarRules.swift +// ToolbarRules.swift // LookInside // // The decisions behind the window toolbars and their popovers, kept free of @@ -33,7 +33,7 @@ let LKToolBarIdentifier_GestureDebug = "21" case appButton } -enum LKToolbarRules { +enum ToolbarRules { /// The step the zoom buttons, the zoom menu items and the separation /// menu items move by. static let step = 0.1 diff --git a/LookInside/Toolbar/LKViewFrameLayout.swift b/LookInside/Toolbar/ViewFrameLayout.swift similarity index 95% rename from LookInside/Toolbar/LKViewFrameLayout.swift rename to LookInside/Toolbar/ViewFrameLayout.swift index f3ebfdf8..83f322db 100644 --- a/LookInside/Toolbar/LKViewFrameLayout.swift +++ b/LookInside/Toolbar/ViewFrameLayout.swift @@ -1,5 +1,5 @@ // -// LKViewFrameLayout.swift +// ViewFrameLayout.swift // LookInside // // Manual frame layout for the Launch, Toolbar and Read views, with the @@ -12,7 +12,7 @@ import AppKit @MainActor -struct LKViewFrameLayout { +struct ViewFrameLayout { let view: NSView init(_ view: NSView) { @@ -154,12 +154,12 @@ struct LKViewFrameLayout { return edit { $0.size.height = height } } - /// `sizeThatFits` of a control or an `LKBaseView`; other views keep their size. + /// `sizeThatFits` of a control or an `BaseView`; other views keep their size. static func fittingSize(of view: NSView, limit: NSSize) -> NSSize { if let control = view as? NSControl { return control.sizeThatFits(limit) } - if let baseView = view as? LKBaseView { + if let baseView = view as? BaseView { return baseView.sizeThatFits(limit) } return view.frame.size @@ -183,12 +183,12 @@ struct LKViewFrameLayout { static func groupMidX(_ views: [NSView], _ value: CGFloat) { guard let union = union(of: views) else { return } - views.forEach { LKViewFrameLayout($0).offsetX(value - union.midX) } + views.forEach { ViewFrameLayout($0).offsetX(value - union.midX) } } static func groupMidY(_ views: [NSView], _ value: CGFloat) { guard let union = union(of: views) else { return } - views.forEach { LKViewFrameLayout($0).offsetY(value - union.midY) } + views.forEach { ViewFrameLayout($0).offsetY(value - union.midY) } } private static func union(of views: [NSView]) -> NSRect? { diff --git a/LookInside/Toolbar/LKWindowToolbarAppButton.swift b/LookInside/Toolbar/WindowToolbarAppButton.swift similarity index 78% rename from LookInside/Toolbar/LKWindowToolbarAppButton.swift rename to LookInside/Toolbar/WindowToolbarAppButton.swift index 13d1623e..3f6d98c3 100644 --- a/LookInside/Toolbar/LKWindowToolbarAppButton.swift +++ b/LookInside/Toolbar/WindowToolbarAppButton.swift @@ -1,5 +1,5 @@ // -// LKWindowToolbarAppButton.swift +// WindowToolbarAppButton.swift // LookinClient // // Created by 李凯 on 2020/6/14. @@ -12,12 +12,12 @@ import AppKit /// icon, app name, a chevron, device icon, device and OS. Without an app it /// shows a plain app icon. @objc(LKWindowToolbarAppButton) -final class LKWindowToolbarAppButton: NSButton { +final class WindowToolbarAppButton: NSButton { private let appImageView = NSImageView() - private let appNameLabel = LKLabel() + private let appNameLabel = TextLabel() private let sepImageView = NSImageView() private let deviceImageView = NSImageView() - private let deviceLabel = LKLabel() + private let deviceLabel = TextLabel() private let appImageWidth: CGFloat = 14 /// Gaps before the app icon, the name, the chevron, the device icon and @@ -52,8 +52,8 @@ final class LKWindowToolbarAppButton: NSButton { fatalError("init(coder:) is not supported") } - private static var labelColors: LKTwoColors { - LKTwoColors(colorInLightMode: NSColor(red: 65 / 255.0, green: 65 / 255.0, blue: 65 / 255.0, alpha: 1), colorInDarkMode: .labelColor) + private static var labelColors: TwoColors { + TwoColors(colorInLightMode: NSColor(red: 65 / 255.0, green: 65 / 255.0, blue: 65 / 255.0, alpha: 1), colorInDarkMode: .labelColor) } @objc var appInfo: InspectedAppInfo? { @@ -62,11 +62,11 @@ final class LKWindowToolbarAppButton: NSButton { override func layout() { super.layout() - LKViewFrameLayout(appImageView).width(appImageWidth).height(appImageWidth).x(spaces[0]).verAlign().offsetY(-0.5) - LKViewFrameLayout(appNameLabel).sizeToFit().verAlign().x(appImageView.frame.maxX + spaces[1]).offsetY(-1) - LKViewFrameLayout(sepImageView).sizeToFit().verAlign().x(appNameLabel.frame.maxX + spaces[2]).offsetY(-0.5) - LKViewFrameLayout(deviceImageView).sizeToFit().x(sepImageView.frame.maxX + spaces[3]).verAlign() - LKViewFrameLayout(deviceLabel).sizeToFit().verAlign().x(deviceImageView.frame.maxX + spaces[4]).toMaxX(bounds.width).offsetY(-1) + ViewFrameLayout(appImageView).width(appImageWidth).height(appImageWidth).x(spaces[0]).verAlign().offsetY(-0.5) + ViewFrameLayout(appNameLabel).sizeToFit().verAlign().x(appImageView.frame.maxX + spaces[1]).offsetY(-1) + ViewFrameLayout(sepImageView).sizeToFit().verAlign().x(appNameLabel.frame.maxX + spaces[2]).offsetY(-0.5) + ViewFrameLayout(deviceImageView).sizeToFit().x(sepImageView.frame.maxX + spaces[3]).verAlign() + ViewFrameLayout(deviceLabel).sizeToFit().verAlign().x(deviceImageView.frame.maxX + spaces[4]).toMaxX(bounds.width).offsetY(-1) } private func appInfoDidChange() { @@ -79,7 +79,7 @@ final class LKWindowToolbarAppButton: NSButton { deviceLabel.stringValue = "\(appInfo.deviceDescription ?? "(null)") (\(appInfo.osDescription ?? "(null)"))" // Prefer the icon of the actual hardware model the app runs on. Falls back to the // per-family asset when the peer's LookinServer does not report a model identifier. - deviceImageView.image = LKDeviceIconProvider.deviceIcon(forAppInfo: appInfo, pointSize: LKDeviceIconProvider.toolbarPointSize) + deviceImageView.image = DeviceIconProvider.deviceIcon(forAppInfo: appInfo, pointSize: DeviceIconProvider.toolbarPointSize) ?? Self.familyIcon(for: appInfo) } else { parts.forEach { $0.isHidden = true } @@ -90,7 +90,7 @@ final class LKWindowToolbarAppButton: NSButton { } private static func familyIcon(for appInfo: InspectedAppInfo) -> NSImage? { - if LKHelper.appInfoLooksLikeMacTarget(appInfo) { + if AppHelper.appInfoLooksLikeMacTarget(appInfo) { return NSImage(named: "icon_mac_small") } switch appInfo.deviceType { diff --git a/LookInside/Toolbar/LKWindowToolbarHelper.swift b/LookInside/Toolbar/WindowToolbarHelper.swift similarity index 80% rename from LookInside/Toolbar/LKWindowToolbarHelper.swift rename to LookInside/Toolbar/WindowToolbarHelper.swift index 4d2bb2f6..355d2a6f 100644 --- a/LookInside/Toolbar/LKWindowToolbarHelper.swift +++ b/LookInside/Toolbar/WindowToolbarHelper.swift @@ -1,5 +1,5 @@ // -// LKWindowToolbarHelper.swift +// WindowToolbarHelper.swift // Lookin // // Created by Li Kai on 2019/5/8. @@ -15,9 +15,9 @@ import AppKit /// others itself: Reload, App, Setting, Console, Add, Remove and Message. @objc(LKWindowToolbarHelper) @MainActor -final class LKWindowToolbarHelper: NSObject { +final class WindowToolbarHelper: NSObject { @objc(sharedInstance) - static let shared = LKWindowToolbarHelper() + static let shared = WindowToolbarHelper() override private init() { super.init() @@ -26,7 +26,7 @@ final class LKWindowToolbarHelper: NSObject { /// The item for `identifier`. Use `makeAppInReadModeItem(with:)` for the /// reader's app item. @objc(makeToolBarItemWithIdentifier:preferenceManager:) - func makeToolBarItem(identifier: String, preferenceManager manager: LKPreferenceManager) -> NSToolbarItem? { + func makeToolBarItem(identifier: String, preferenceManager manager: PreferenceManager) -> NSToolbarItem? { assert(identifier != LKToolBarIdentifier_AppInReadMode, "Use makeAppInReadModeItemWithAppInfo:") switch identifier { @@ -38,7 +38,7 @@ final class LKWindowToolbarHelper: NSObject { return item case LKToolBarIdentifier_Measure: - let button = LKToolbarPreferenceButton() + let button = ToolbarPreferenceButton() button.preferenceManager = manager button.image = Self.templateImage("icon_measure") button.bezelStyle = .texturedRounded @@ -55,7 +55,7 @@ final class LKWindowToolbarHelper: NSObject { case LKToolBarIdentifier_Dimension: let images = [Self.templateImage("icon_2d"), Self.templateImage("icon_3d")].compactMap { $0 } - let control = LKToolbarPreferenceSegmentedControl( + let control = ToolbarPreferenceSegmentedControl( images: images, trackingMode: .selectOne, target: self, @@ -69,7 +69,7 @@ final class LKWindowToolbarHelper: NSObject { return Self.item(LKToolBarIdentifier_Dimension, label: "2D / 3D", view: control) case LKToolBarIdentifier_Scale: - let scaleView = LKWindowToolbarScaleView() + let scaleView = WindowToolbarScaleView() let slider = scaleView.slider slider.preferenceManager = manager slider.minValue = Double(LookinPreviewMinScale) @@ -93,7 +93,7 @@ final class LKWindowToolbarHelper: NSObject { return Self.item(LKToolBarIdentifier_Reload, label: NSLocalizedString("Reload", comment: ""), view: Self.imageButton("icon_reload")) case LKToolBarIdentifier_App: - let button = LKWindowToolbarAppButton() + let button = WindowToolbarAppButton() button.bezelStyle = .texturedRounded // The owning live document's window controller binds the button // to its inspected app. @@ -103,10 +103,10 @@ final class LKWindowToolbarHelper: NSObject { let segmented = NSSegmentedControl( labels: [NSLocalizedString("Compact", comment: ""), NSLocalizedString("Verbose", comment: "")], trackingMode: .selectOne, - target: LKSwiftUIHierarchyDisplayModeStore.self as AnyObject, - action: #selector(LKSwiftUIHierarchyDisplayModeStore.swiftUIModeSegmentChanged(_:)) + target: SwiftUIHierarchyDisplayModeStore.self as AnyObject, + action: #selector(SwiftUIHierarchyDisplayModeStore.swiftUIModeSegmentChanged(_:)) ) - segmented.selectedSegment = LKSwiftUIHierarchyDisplayModeStore.currentMode() == .compact ? 0 : 1 + segmented.selectedSegment = SwiftUIHierarchyDisplayModeStore.currentMode() == .compact ? 0 : 1 return Self.item(LKToolBarIdentifier_SwiftUIMode, label: NSLocalizedString("SwiftUI", comment: ""), view: segmented) case LKToolBarIdentifier_Console: @@ -141,7 +141,7 @@ final class LKWindowToolbarHelper: NSObject { /// The reader's app item, showing `appInfo`. @objc(makeAppInReadModeItemWithAppInfo:) func makeAppInReadModeItem(with appInfo: InspectedAppInfo?) -> NSToolbarItem { - let button = LKWindowToolbarAppButton() + let button = WindowToolbarAppButton() button.bezelStyle = .texturedRounded button.appInfo = appInfo return Self.item(LKToolBarIdentifier_AppInReadMode, label: "iOS App", view: button) @@ -176,25 +176,25 @@ final class LKWindowToolbarHelper: NSObject { // MARK: - Control → preference - @objc private func handleDimension(_ control: LKToolbarPreferenceSegmentedControl) { + @objc private func handleDimension(_ control: ToolbarPreferenceSegmentedControl) { control.preferenceManager?.previewDimension.setIntegerValue(control.selectedSegment, ignoreSubscriber: self) } - @objc private func handleScaleSlider(_ slider: LKToolbarPreferenceSlider) { + @objc private func handleScaleSlider(_ slider: ToolbarPreferenceSlider) { slider.preferenceManager?.previewScale.setDoubleValue(slider.doubleValue, ignoreSubscriber: self) } - @objc private func handleScaleIncreaseButton(_ button: LKToolbarPreferenceButton) { - stepScale(of: button.preferenceManager, by: LKToolbarRules.step) + @objc private func handleScaleIncreaseButton(_ button: ToolbarPreferenceButton) { + stepScale(of: button.preferenceManager, by: ToolbarRules.step) } - @objc private func handleScaleDecreaseButton(_ button: LKToolbarPreferenceButton) { - stepScale(of: button.preferenceManager, by: -LKToolbarRules.step) + @objc private func handleScaleDecreaseButton(_ button: ToolbarPreferenceButton) { + stepScale(of: button.preferenceManager, by: -ToolbarRules.step) } - private func stepScale(of manager: LKPreferenceManager?, by delta: Double) { + private func stepScale(of manager: PreferenceManager?, by delta: Double) { guard let manager else { return } - let scale = LKToolbarRules.stepped( + let scale = ToolbarRules.stepped( manager.previewScale.currentDoubleValue, by: delta, lower: Double(LookinPreviewMinScale), @@ -203,41 +203,41 @@ final class LKWindowToolbarHelper: NSObject { manager.previewScale.setDoubleValue(scale, ignoreSubscriber: nil) } - @objc private func handleToggleMeasureButton(_ button: LKToolbarPreferenceButton) { - let state: LookinMeasureState = button.state == .on ? .locked : .no + @objc private func handleToggleMeasureButton(_ button: ToolbarPreferenceButton) { + let state: MeasureState = button.state == .on ? .locked : .no button.preferenceManager?.measureState.setIntegerValue(state.rawValue, ignoreSubscriber: self) } // MARK: - Preference → control - @objc private func handlePreviewScaleDidChange(_ param: LookinMsgActionParams) { + @objc private func handlePreviewScaleDidChange(_ param: MessageActionParameters) { (param.relatedObject as? NSSlider)?.doubleValue = param.doubleValue } /// Fast mode and free rotation: the button is on while the preference is. - @objc private func handleOnOffDidChange(_ param: LookinMsgActionParams) { + @objc private func handleOnOffDidChange(_ param: MessageActionParameters) { (param.relatedObject as? NSButton)?.state = param.boolValue ? .on : .off } - @objc private func handleDimensionDidChange(_ param: LookinMsgActionParams) { + @objc private func handleDimensionDidChange(_ param: MessageActionParameters) { (param.relatedObject as? NSSegmentedControl)?.selectedSegment = param.integerValue } - @objc private func handleMeasureStateDidChange(_ param: LookinMsgActionParams) { - (param.relatedObject as? NSButton)?.state = param.integerValue != LookinMeasureState.no.rawValue ? .on : .off + @objc private func handleMeasureStateDidChange(_ param: MessageActionParameters) { + (param.relatedObject as? NSButton)?.state = param.integerValue != MeasureState.no.rawValue ? .on : .off } } /// Toolbar controls that remember the preference manager they drive; the /// shared helper is their target. -final class LKToolbarPreferenceButton: NSButton { - weak var preferenceManager: LKPreferenceManager? +final class ToolbarPreferenceButton: NSButton { + weak var preferenceManager: PreferenceManager? } -final class LKToolbarPreferenceSlider: NSSlider { - weak var preferenceManager: LKPreferenceManager? +final class ToolbarPreferenceSlider: NSSlider { + weak var preferenceManager: PreferenceManager? } -final class LKToolbarPreferenceSegmentedControl: NSSegmentedControl { - weak var preferenceManager: LKPreferenceManager? +final class ToolbarPreferenceSegmentedControl: NSSegmentedControl { + weak var preferenceManager: PreferenceManager? } diff --git a/LookInside/Toolbar/LKWindowToolbarScaleView.swift b/LookInside/Toolbar/WindowToolbarScaleView.swift similarity index 55% rename from LookInside/Toolbar/LKWindowToolbarScaleView.swift rename to LookInside/Toolbar/WindowToolbarScaleView.swift index fdd1d50b..16cb2a28 100644 --- a/LookInside/Toolbar/LKWindowToolbarScaleView.swift +++ b/LookInside/Toolbar/WindowToolbarScaleView.swift @@ -1,5 +1,5 @@ // -// LKWindowToolbarScaleView.swift +// WindowToolbarScaleView.swift // Lookin // // Created by Li Kai on 2019/10/14. @@ -10,10 +10,10 @@ import AppKit /// The toolbar's zoom control: a slider between a decrease and an increase /// button. -final class LKWindowToolbarScaleView: LKBaseView { - let slider = LKToolbarPreferenceSlider() - let decreaseButton = LKWindowToolbarScaleView.makeButton(imageNamed: "icon_decrease") - let increaseButton = LKWindowToolbarScaleView.makeButton(imageNamed: "icon_increase") +final class WindowToolbarScaleView: BaseView { + let slider = ToolbarPreferenceSlider() + let decreaseButton = WindowToolbarScaleView.makeButton(imageNamed: "icon_decrease") + let increaseButton = WindowToolbarScaleView.makeButton(imageNamed: "icon_increase") override init(frame frameRect: NSRect) { super.init(frame: frameRect) @@ -29,9 +29,9 @@ final class LKWindowToolbarScaleView: LKBaseView { override func layout() { super.layout() - LKViewFrameLayout(decreaseButton).width(20).fullHeight().x(0) - LKViewFrameLayout(increaseButton).width(20).fullHeight().right(0) - LKViewFrameLayout(slider).fullHeight().x(decreaseButton.frame.maxX).toMaxX(increaseButton.frame.minX) + ViewFrameLayout(decreaseButton).width(20).fullHeight().x(0) + ViewFrameLayout(increaseButton).width(20).fullHeight().right(0) + ViewFrameLayout(slider).fullHeight().x(decreaseButton.frame.maxX).toMaxX(increaseButton.frame.minX) } override var intrinsicContentSize: NSSize { @@ -39,8 +39,8 @@ final class LKWindowToolbarScaleView: LKBaseView { } /// `+[NSButton lk_buttonWithImage:target:action:]`: borderless, image only. - private static func makeButton(imageNamed name: String) -> LKToolbarPreferenceButton { - let button = LKToolbarPreferenceButton() + private static func makeButton(imageNamed name: String) -> ToolbarPreferenceButton { + let button = ToolbarPreferenceButton() button.image = NSImage(named: name) button.bezelStyle = .roundRect button.isBordered = false diff --git a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyAttributeCatalog.swift b/LookInside/XcodeViewHierarchy/XcodeViewHierarchyAttributeCatalog.swift similarity index 99% rename from LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyAttributeCatalog.swift rename to LookInside/XcodeViewHierarchy/XcodeViewHierarchyAttributeCatalog.swift index 73d4a77a..4925f6a8 100644 --- a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyAttributeCatalog.swift +++ b/LookInside/XcodeViewHierarchy/XcodeViewHierarchyAttributeCatalog.swift @@ -1,4 +1,4 @@ -// LKXcodeViewHierarchyAttributeCatalog.swift +// XcodeViewHierarchyAttributeCatalog.swift // // Which dashboard rows an imported capture can fill, and where in the capture // each one's value lives. @@ -26,7 +26,7 @@ import AppKit import Foundation -struct LKXcodeViewHierarchyAttributeSpecification { +struct XcodeViewHierarchyAttributeSpecification { /// Which object the property is read from. enum Source { /// The node itself. @@ -82,7 +82,7 @@ struct LKXcodeViewHierarchyAttributeSpecification { } } -enum LKXcodeViewHierarchyAttributeCatalog { +enum XcodeViewHierarchyAttributeCatalog { struct Section { let identifier: String let attributes: [String] @@ -477,7 +477,7 @@ enum LKXcodeViewHierarchyAttributeCatalog { // MARK: - Specifications - private typealias Specification = LKXcodeViewHierarchyAttributeSpecification + private typealias Specification = XcodeViewHierarchyAttributeSpecification private static let anyView = ["UIView", "NSView"] private static let anyViewOrWindow = ["UIView", "NSView", "NSWindow"] @@ -489,8 +489,8 @@ enum LKXcodeViewHierarchyAttributeCatalog { /// Where each attribute's value comes from. Attributes built from more /// than a property — the class chain, relations, constraints, a scene's - /// window count — are not here; `LKXcodeViewHierarchyAttributes` handles them. - static let specifications: [String: LKXcodeViewHierarchyAttributeSpecification] = [ + /// window count — are not here; `XcodeViewHierarchyAttributes` handles them. + static let specifications: [String: XcodeViewHierarchyAttributeSpecification] = [ // Layout. AppKit records a view's frame on the view and its layer's // on the layer, and the two differ under flipping; the view's is the // one the inspector's other cards are built from. diff --git a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyAttributes.swift b/LookInside/XcodeViewHierarchy/XcodeViewHierarchyAttributes.swift similarity index 89% rename from LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyAttributes.swift rename to LookInside/XcodeViewHierarchy/XcodeViewHierarchyAttributes.swift index 38eecaf1..c32afe49 100644 --- a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyAttributes.swift +++ b/LookInside/XcodeViewHierarchy/XcodeViewHierarchyAttributes.swift @@ -1,4 +1,4 @@ -// LKXcodeViewHierarchyAttributes.swift +// XcodeViewHierarchyAttributes.swift // // Builds the attribute cards the dashboard shows for a node imported from an // Xcode capture. @@ -11,7 +11,7 @@ // key-value rows — with the editors inert, since the document is read-only. // // The card order and the capture property behind each row live in -// `LKXcodeViewHierarchyAttributeCatalog`. This file walks that catalog, gates +// `XcodeViewHierarchyAttributeCatalog`. This file walks that catalog, gates // each row on the node's class chain, and converts the decoded capture value // into the value type the card expects. A few rows are not one property but a // derivation — the class chains, the relations, the Auto Layout constraints, @@ -31,15 +31,15 @@ import Foundation // MARK: - Context /// Per-conversion facts the cards need beyond a node's own properties. -struct LKXcodeViewHierarchyAttributeEnvironment { +struct XcodeViewHierarchyAttributeEnvironment { let isAppKit: Bool - let constraintIndex: LKXcodeViewHierarchyConstraintIndex + let constraintIndex: XcodeViewHierarchyConstraintIndex /// The window the application object names as key, if the capture says. let keyWindowIdentifier: String? } /// What a node is to the inspector, and which neighbours its cards refer to. -struct LKXcodeViewHierarchyAttributeContext { +struct XcodeViewHierarchyAttributeContext { enum Role { /// A view, including a UIKit window, which is a view too. case view @@ -56,17 +56,17 @@ struct LKXcodeViewHierarchyAttributeContext { } let role: Role - let environment: LKXcodeViewHierarchyAttributeEnvironment + let environment: XcodeViewHierarchyAttributeEnvironment /// The controller whose view this is (or a window's root view controller). - var viewControllerNode: LKXcodeViewHierarchyNode? = nil + var viewControllerNode: XcodeViewHierarchyNode? = nil /// An AppKit window's controller. - var windowControllerNode: LKXcodeViewHierarchyNode? = nil + var windowControllerNode: XcodeViewHierarchyNode? = nil /// The control owning a cell, or the view owning a layout guide. - var ownerNode: LKXcodeViewHierarchyNode? = nil + var ownerNode: XcodeViewHierarchyNode? = nil /// The node's parent in the tree, for typing constraint endpoints. - var superviewNode: LKXcodeViewHierarchyNode? = nil + var superviewNode: XcodeViewHierarchyNode? = nil /// The windows listed under a scene, after Xcode's skip rule. - var sceneWindowNodes: [LKXcodeViewHierarchyNode] = [] + var sceneWindowNodes: [XcodeViewHierarchyNode] = [] } // MARK: - Constraint index @@ -77,13 +77,13 @@ struct LKXcodeViewHierarchyAttributeContext { /// a view's Auto Layout card wants the constraints that involve that view — /// the server's `lks_involvedRawConstraints`. Walking the whole group per /// view would be quadratic on captures with thousands of constraints. -final class LKXcodeViewHierarchyConstraintIndex { +final class XcodeViewHierarchyConstraintIndex { private static let constraintClassName = "NSLayoutConstraint" private static let endpointPropertyNames = ["firstItem", "secondItem"] private let constraintIdentifiersByItemIdentifier: [String: [String]] - init(graph: LKXcodeViewHierarchyObjectGraph) { + init(graph: XcodeViewHierarchyObjectGraph) { var index: [String: [String]] = [:] // Dictionary order is unstable; sort so two imports of one capture // list a view's constraints in the same order. @@ -108,7 +108,7 @@ final class LKXcodeViewHierarchyConstraintIndex { constraintIdentifiersByItemIdentifier[itemIdentifier] ?? [] } - private static func isConstraint(_ node: LKXcodeViewHierarchyNode, graph: LKXcodeViewHierarchyObjectGraph) -> Bool { + private static func isConstraint(_ node: XcodeViewHierarchyNode, graph: XcodeViewHierarchyObjectGraph) -> Bool { if node.groupingIdentifier?.hasSuffix("." + constraintClassName) == true { return true } @@ -119,9 +119,9 @@ final class LKXcodeViewHierarchyConstraintIndex { // MARK: - Builder -enum LKXcodeViewHierarchyAttributes { - private typealias Catalog = LKXcodeViewHierarchyAttributeCatalog - private typealias Specification = LKXcodeViewHierarchyAttributeSpecification +enum XcodeViewHierarchyAttributes { + private typealias Catalog = XcodeViewHierarchyAttributeCatalog + private typealias Specification = XcodeViewHierarchyAttributeSpecification private enum GroupIdentifier { static let cell = "com.apple.AppKit.NSCell" @@ -145,10 +145,10 @@ enum LKXcodeViewHierarchyAttributes { /// properties the Layout and View/Layer cards show (position, anchor point, /// corner radius, masks to bounds) live on the layer rather than the view. static func makingGroups( - for node: LKXcodeViewHierarchyNode, - layerNode: LKXcodeViewHierarchyNode?, - graph: LKXcodeViewHierarchyObjectGraph, - context: LKXcodeViewHierarchyAttributeContext + for node: XcodeViewHierarchyNode, + layerNode: XcodeViewHierarchyNode?, + graph: XcodeViewHierarchyObjectGraph, + context: XcodeViewHierarchyAttributeContext ) -> [AttributesGroup] { let classChain = graph.classChain(forClassName: node.className ?? "NSObject") var groups: [AttributesGroup] = [] @@ -182,11 +182,11 @@ enum LKXcodeViewHierarchyAttributes { private static func makingAttribute( _ identifier: String, - node: LKXcodeViewHierarchyNode, - layerNode: LKXcodeViewHierarchyNode?, + node: XcodeViewHierarchyNode, + layerNode: XcodeViewHierarchyNode?, classChain: [String], - graph: LKXcodeViewHierarchyObjectGraph, - context: LKXcodeViewHierarchyAttributeContext + graph: XcodeViewHierarchyObjectGraph, + context: XcodeViewHierarchyAttributeContext ) -> InspectedAttribute? { switch identifier { case LookinAttr_Class_Class_Class: @@ -232,11 +232,11 @@ enum LKXcodeViewHierarchyAttributes { /// A row the catalog maps to a capture property. private static func makingSpecifiedAttribute( _ identifier: String, - node: LKXcodeViewHierarchyNode, - layerNode: LKXcodeViewHierarchyNode?, + node: XcodeViewHierarchyNode, + layerNode: XcodeViewHierarchyNode?, classChain: [String], - graph: LKXcodeViewHierarchyObjectGraph, - context: LKXcodeViewHierarchyAttributeContext + graph: XcodeViewHierarchyObjectGraph, + context: XcodeViewHierarchyAttributeContext ) -> InspectedAttribute? { guard let specification = Catalog.specifications[identifier] else { return nil } if context.role == .layer { @@ -268,11 +268,11 @@ enum LKXcodeViewHierarchyAttributes { /// first of its candidate sources. private static func capturedProperty( for specification: Specification, - node: LKXcodeViewHierarchyNode, - layerNode: LKXcodeViewHierarchyNode?, - graph: LKXcodeViewHierarchyObjectGraph - ) -> LKXcodeViewHierarchyProperty? { - let sourceNodes: [LKXcodeViewHierarchyNode?] + node: XcodeViewHierarchyNode, + layerNode: XcodeViewHierarchyNode?, + graph: XcodeViewHierarchyObjectGraph + ) -> XcodeViewHierarchyProperty? { + let sourceNodes: [XcodeViewHierarchyNode?] switch specification.source { case .node: sourceNodes = [node] case .layer: sourceNodes = [layerNode] @@ -293,18 +293,18 @@ enum LKXcodeViewHierarchyAttributes { } private static func cellNode( - of node: LKXcodeViewHierarchyNode, - graph: LKXcodeViewHierarchyObjectGraph - ) -> LKXcodeViewHierarchyNode? { + of node: XcodeViewHierarchyNode, + graph: XcodeViewHierarchyObjectGraph + ) -> XcodeViewHierarchyNode? { guard let cellIdentifier = node.associatedIdentifiers(inGroup: GroupIdentifier.cell).first else { return nil } return graph.node(cellIdentifier) } private static func referencedNode( - from node: LKXcodeViewHierarchyNode, + from node: XcodeViewHierarchyNode, propertyName: String, - graph: LKXcodeViewHierarchyObjectGraph - ) -> LKXcodeViewHierarchyNode? { + graph: XcodeViewHierarchyObjectGraph + ) -> XcodeViewHierarchyNode? { guard case let .objectReference(reference)? = node.property(named: propertyName)?.value else { return nil } return graph.node(reference.objectIdentifier) } @@ -314,7 +314,7 @@ enum LKXcodeViewHierarchyAttributes { /// The attribute value a decoded capture value becomes, typed the way the /// card for that kind reads it (`LookinAttrType.h`). private static func makingValue( - _ value: LKXcodeViewHierarchyValue, + _ value: XcodeViewHierarchyValue, kind: Specification.Kind, isEnumeration: Bool ) -> (attrType: LookinAttrType, value: Any)? { @@ -398,7 +398,7 @@ enum LKXcodeViewHierarchyAttributes { } } - private static func integerValue(of value: LKXcodeViewHierarchyValue) -> Int64? { + private static func integerValue(of value: XcodeViewHierarchyValue) -> Int64? { switch value { case let .integer(integer): return integer case let .unsignedInteger(unsigned): return Int64(bitPattern: unsigned) @@ -416,7 +416,7 @@ enum LKXcodeViewHierarchyAttributes { /// the system's white/black colours, and CMYK on occasion. The card only /// knows RGBA, so the others are converted, and wide-gamut components are /// clamped — an approximation the card can show rather than a row lost. - private static func rgbaComponents(of color: LKXcodeViewHierarchyColor) -> [NSNumber]? { + private static func rgbaComponents(of color: XcodeViewHierarchyColor) -> [NSNumber]? { let components = color.components let rgba: [Double] switch components.count { @@ -439,8 +439,8 @@ enum LKXcodeViewHierarchyAttributes { /// controller's cut the same way — the server's `lks_relatedClassChainList`. private static func relatedClassChains( _ classChain: [String], - graph: LKXcodeViewHierarchyObjectGraph, - context: LKXcodeViewHierarchyAttributeContext + graph: XcodeViewHierarchyObjectGraph, + context: XcodeViewHierarchyAttributeContext ) -> [[String]] { var chains: [[String]] = [] switch context.role { @@ -467,8 +467,8 @@ enum LKXcodeViewHierarchyAttributes { } private static func classChainOfNode( - _ node: LKXcodeViewHierarchyNode?, - graph: LKXcodeViewHierarchyObjectGraph + _ node: XcodeViewHierarchyNode?, + graph: XcodeViewHierarchyObjectGraph ) -> [String]? { guard let className = node?.className else { return nil } return graph.classChain(forClassName: className) @@ -485,8 +485,8 @@ enum LKXcodeViewHierarchyAttributes { /// The server's `lks_selfRelation` strings: who owns this object. private static func relationDescriptions( - for node: LKXcodeViewHierarchyNode, - context: LKXcodeViewHierarchyAttributeContext + for node: XcodeViewHierarchyNode, + context: XcodeViewHierarchyAttributeContext ) -> [String] { var relations: [String] = [] switch context.role { @@ -515,7 +515,7 @@ enum LKXcodeViewHierarchyAttributes { return relations } - private static func delegateDescription(of node: LKXcodeViewHierarchyNode) -> String? { + private static func delegateDescription(of node: XcodeViewHierarchyNode) -> String? { guard case let .objectReference(reference)? = node.property(named: "delegate")?.value else { return nil } return "(\(reference.className) *) delegate" } @@ -542,9 +542,9 @@ enum LKXcodeViewHierarchyAttributes { /// constraint naming the view as an item, marked effective when the /// capture lists it among the ones affecting the view's layout. private static func makingConstraints( - for node: LKXcodeViewHierarchyNode, - graph: LKXcodeViewHierarchyObjectGraph, - context: LKXcodeViewHierarchyAttributeContext + for node: XcodeViewHierarchyNode, + graph: XcodeViewHierarchyObjectGraph, + context: XcodeViewHierarchyAttributeContext ) -> [AutoLayoutConstraint] { let effectiveIdentifiers = affectingConstraintIdentifiers(of: node) let constraintIdentifiers = context.environment.constraintIndex.constraintIdentifiers(involving: node.objectIdentifier) @@ -580,7 +580,7 @@ enum LKXcodeViewHierarchyAttributes { constraint.constant = CGFloat(constraintNode.property(named: ConstraintProperty.constant)?.value.doubleValue ?? 0) constraint.priority = CGFloat(constraintNode.property(named: ConstraintProperty.priority)?.value.doubleValue ?? 1000) constraint.identifier = constraintNode.property(named: ConstraintProperty.identifier)?.value.textValue - constraint.constraintOid = LKXcodeViewHierarchyConverter.objectIdentifierValue(constraintIdentifier) + constraint.constraintOid = XcodeViewHierarchyConverter.objectIdentifierValue(constraintIdentifier) return constraint } } @@ -592,7 +592,7 @@ enum LKXcodeViewHierarchyAttributes { !((21 ... 31).contains(attribute) || attribute > 37) } - private static func affectingConstraintIdentifiers(of node: LKXcodeViewHierarchyNode) -> Set { + private static func affectingConstraintIdentifiers(of node: XcodeViewHierarchyNode) -> Set { var identifiers: Set = [] for propertyName in ConstraintProperty.affecting { guard let text = node.property(named: propertyName)?.value.textValue else { continue } @@ -606,7 +606,7 @@ enum LKXcodeViewHierarchyAttributes { return identifiers } - private static func integerProperty(_ node: LKXcodeViewHierarchyNode, _ propertyName: String) -> Int? { + private static func integerProperty(_ node: XcodeViewHierarchyNode, _ propertyName: String) -> Int? { guard let value = node.property(named: propertyName)?.value, let integer = integerValue(of: value) else { return nil } return Int(integer) } @@ -614,17 +614,17 @@ enum LKXcodeViewHierarchyAttributes { /// One end of a constraint, typed the way the server's /// `_lks_constraintItemTypeForItem:` types it relative to the view. private static func endpoint( - of constraintNode: LKXcodeViewHierarchyNode, + of constraintNode: XcodeViewHierarchyNode, propertyName: String, - for node: LKXcodeViewHierarchyNode, - graph: LKXcodeViewHierarchyObjectGraph, - context: LKXcodeViewHierarchyAttributeContext + for node: XcodeViewHierarchyNode, + graph: XcodeViewHierarchyObjectGraph, + context: XcodeViewHierarchyAttributeContext ) -> (object: InspectedObject?, type: LookinConstraintItemType) { guard case let .objectReference(reference)? = constraintNode.property(named: propertyName)?.value else { return (nil, .`nil`) } let object = InspectedObject() - object.oid = LKXcodeViewHierarchyConverter.objectIdentifierValue(reference.objectIdentifier) + object.oid = XcodeViewHierarchyConverter.objectIdentifierValue(reference.objectIdentifier) object.memoryAddress = reference.objectIdentifier object.classChainList = graph.classChain(forClassName: reference.className) diff --git a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyBundleReader.swift b/LookInside/XcodeViewHierarchy/XcodeViewHierarchyBundleReader.swift similarity index 83% rename from LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyBundleReader.swift rename to LookInside/XcodeViewHierarchy/XcodeViewHierarchyBundleReader.swift index 23f40ac3..3c8b66ac 100644 --- a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyBundleReader.swift +++ b/LookInside/XcodeViewHierarchy/XcodeViewHierarchyBundleReader.swift @@ -1,4 +1,4 @@ -// LKXcodeViewHierarchyBundleReader.swift +// XcodeViewHierarchyBundleReader.swift // // Reads an Xcode-exported `.viewhierarchy` document off disk into an object graph. // @@ -23,21 +23,21 @@ import Foundation -struct LKXcodeViewHierarchyBundleMetadata { +struct XcodeViewHierarchyBundleMetadata { let documentVersion: String? let runnableDisplayName: String? let runnableProcessIdentifier: Int? } -struct LKXcodeViewHierarchyBundle { - let metadata: LKXcodeViewHierarchyBundleMetadata - let graph: LKXcodeViewHierarchyObjectGraph +struct XcodeViewHierarchyBundle { + let metadata: XcodeViewHierarchyBundleMetadata + let graph: XcodeViewHierarchyObjectGraph /// Number of response entries that were present but unusable. let failedResponseCount: Int let succeededResponseCount: Int } -enum LKXcodeViewHierarchyBundleReadingError: Error, CustomStringConvertible { +enum XcodeViewHierarchyBundleReadingError: Error, CustomStringConvertible { case notADirectory(URL) case missingResponses(URL) case noUsableResponses(URL) @@ -54,20 +54,20 @@ enum LKXcodeViewHierarchyBundleReadingError: Error, CustomStringConvertible { } } -enum LKXcodeViewHierarchyBundleReader { +enum XcodeViewHierarchyBundleReader { static let responseDirectoryName = "RequestResponses" static let metadataFileName = "metadata" private static let responseFilePrefix = "Response_" - static func reading(contentsOf bundleURL: URL) throws -> LKXcodeViewHierarchyBundle { + static func reading(contentsOf bundleURL: URL) throws -> XcodeViewHierarchyBundle { var isDirectory: ObjCBool = false guard FileManager.default.fileExists(atPath: bundleURL.path, isDirectory: &isDirectory), isDirectory.boolValue - else { throw LKXcodeViewHierarchyBundleReadingError.notADirectory(bundleURL) } + else { throw XcodeViewHierarchyBundleReadingError.notADirectory(bundleURL) } let responseURLs = try orderedResponseURLs(inBundleAt: bundleURL) - let builder = LKXcodeViewHierarchyObjectGraphBuilder() + let builder = XcodeViewHierarchyObjectGraphBuilder() var failedResponseCount = 0 var succeededResponseCount = 0 @@ -83,10 +83,10 @@ enum LKXcodeViewHierarchyBundleReader { } guard succeededResponseCount > 0 else { - throw LKXcodeViewHierarchyBundleReadingError.noUsableResponses(bundleURL) + throw XcodeViewHierarchyBundleReadingError.noUsableResponses(bundleURL) } - return LKXcodeViewHierarchyBundle( + return XcodeViewHierarchyBundle( metadata: readingMetadata(inBundleAt: bundleURL), graph: builder.build(), failedResponseCount: failedResponseCount, @@ -101,9 +101,9 @@ enum LKXcodeViewHierarchyBundleReader { var isDirectory: ObjCBool = false guard FileManager.default.fileExists(atPath: bundleURL.path, isDirectory: &isDirectory), isDirectory.boolValue - else { throw LKXcodeViewHierarchyBundleReadingError.notADirectory(bundleURL) } + else { throw XcodeViewHierarchyBundleReadingError.notADirectory(bundleURL) } guard try !orderedResponseURLs(inBundleAt: bundleURL).isEmpty else { - throw LKXcodeViewHierarchyBundleReadingError.noUsableResponses(bundleURL) + throw XcodeViewHierarchyBundleReadingError.noUsableResponses(bundleURL) } } @@ -114,7 +114,7 @@ enum LKXcodeViewHierarchyBundleReader { static func orderedResponseURLs(inBundleAt bundleURL: URL) throws -> [URL] { let responsesURL = bundleURL.appendingPathComponent(responseDirectoryName) guard let fileNames = try? FileManager.default.contentsOfDirectory(atPath: responsesURL.path) else { - throw LKXcodeViewHierarchyBundleReadingError.missingResponses(bundleURL) + throw XcodeViewHierarchyBundleReadingError.missingResponses(bundleURL) } return fileNames .filter { $0.hasPrefix(responseFilePrefix) } @@ -137,7 +137,7 @@ enum LKXcodeViewHierarchyBundleReader { private static func readingResponse(at responseURL: URL) throws -> [String: Any]? { let rawData = try Data(contentsOf: responseURL) - let inflatedData = try LKXcodeViewHierarchyGzip.inflatingIfNeeded(rawData) + let inflatedData = try XcodeViewHierarchyGzip.inflatingIfNeeded(rawData) let parsed = try JSONSerialization.jsonObject(with: inflatedData) return parsed as? [String: Any] } @@ -152,17 +152,17 @@ enum LKXcodeViewHierarchyBundleReader { // MARK: Metadata - static func readingMetadata(inBundleAt bundleURL: URL) -> LKXcodeViewHierarchyBundleMetadata { + static func readingMetadata(inBundleAt bundleURL: URL) -> XcodeViewHierarchyBundleMetadata { let metadataURL = bundleURL.appendingPathComponent(metadataFileName) guard let metadataData = try? Data(contentsOf: metadataURL), let parsed = try? PropertyListSerialization.propertyList(from: metadataData, format: nil), let metadata = parsed as? [String: Any] else { - return LKXcodeViewHierarchyBundleMetadata( + return XcodeViewHierarchyBundleMetadata( documentVersion: nil, runnableDisplayName: nil, runnableProcessIdentifier: nil ) } - return LKXcodeViewHierarchyBundleMetadata( + return XcodeViewHierarchyBundleMetadata( documentVersion: stringValue(metadata["DocumentVersion"]), runnableDisplayName: stringValue(metadata["RunnableDisplayName"]), runnableProcessIdentifier: (metadata["RunnablePID"] as? NSNumber)?.intValue @@ -184,7 +184,7 @@ enum LKXcodeViewHierarchyBundleReader { /// Shown by the document when an import fails, so the wording must be the /// user-facing one rather than "The operation couldn't be completed". -extension LKXcodeViewHierarchyBundleReadingError: LocalizedError { +extension XcodeViewHierarchyBundleReadingError: LocalizedError { var errorDescription: String? { description } diff --git a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyConverter.swift b/LookInside/XcodeViewHierarchy/XcodeViewHierarchyConverter.swift similarity index 91% rename from LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyConverter.swift rename to LookInside/XcodeViewHierarchy/XcodeViewHierarchyConverter.swift index 1e922f9e..e27cb6e9 100644 --- a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyConverter.swift +++ b/LookInside/XcodeViewHierarchy/XcodeViewHierarchyConverter.swift @@ -1,4 +1,4 @@ -// LKXcodeViewHierarchyConverter.swift +// XcodeViewHierarchyConverter.swift // // Turns a decoded `.viewhierarchy` capture into the model the inspector // already knows how to display: a `HierarchyFile`, which the existing @@ -36,7 +36,7 @@ import AppKit import Foundation -enum LKXcodeViewHierarchyConversionError: Error, CustomStringConvertible { +enum XcodeViewHierarchyConversionError: Error, CustomStringConvertible { case noWindowsOrRootViews var description: String { @@ -47,7 +47,7 @@ enum LKXcodeViewHierarchyConversionError: Error, CustomStringConvertible { } } -enum LKXcodeViewHierarchyConverter { +enum XcodeViewHierarchyConverter { // MARK: Group identifiers private enum GroupIdentifier { @@ -135,8 +135,8 @@ enum LKXcodeViewHierarchyConverter { /// proposal). The recovered images are the same either way; what changes /// is which node each image is filed under. static func makingHierarchyFile( - from bundle: LKXcodeViewHierarchyBundle, - screenshots: LKXcodeViewHierarchyScreenshots, + from bundle: XcodeViewHierarchyBundle, + screenshots: XcodeViewHierarchyScreenshots, showingBackingLayers: Bool = false ) throws -> HierarchyFile { let graph = bundle.graph @@ -148,7 +148,7 @@ enum LKXcodeViewHierarchyConverter { ) let displayItems = makingRootDisplayItems(session: session) - guard !displayItems.isEmpty else { throw LKXcodeViewHierarchyConversionError.noWindowsOrRootViews } + guard !displayItems.isEmpty else { throw XcodeViewHierarchyConversionError.noWindowsOrRootViews } let hierarchyInfo = HierarchyInfo() hierarchyInfo.displayItems = displayItems @@ -175,12 +175,12 @@ enum LKXcodeViewHierarchyConverter { /// the view itself (`bestObjectOidPreferView:`), and a layer node shows a /// group image that leaves out the views beneath it. private final class ConversionSession { - let graph: LKXcodeViewHierarchyObjectGraph + let graph: XcodeViewHierarchyObjectGraph let vocabulary: Vocabulary - let screenshots: LKXcodeViewHierarchyScreenshots + let screenshots: XcodeViewHierarchyScreenshots let showsBackingLayers: Bool - let topology: LKXcodeViewHierarchyLayerTopology - let environment: LKXcodeViewHierarchyAttributeEnvironment + let topology: XcodeViewHierarchyLayerTopology + let environment: XcodeViewHierarchyAttributeEnvironment /// Layers already emitted as nodes. The capture's layer tree is a /// tree, but a layer reachable twice must not appear twice. var convertedLayerIdentifiers: Set = [] @@ -188,20 +188,20 @@ enum LKXcodeViewHierarchyConverter { private(set) var groupScreenshotsByOid: [NSNumber: Data] = [:] init( - graph: LKXcodeViewHierarchyObjectGraph, + graph: XcodeViewHierarchyObjectGraph, vocabulary: Vocabulary, - screenshots: LKXcodeViewHierarchyScreenshots, + screenshots: XcodeViewHierarchyScreenshots, showsBackingLayers: Bool ) { self.graph = graph self.vocabulary = vocabulary self.screenshots = screenshots self.showsBackingLayers = showsBackingLayers - topology = LKXcodeViewHierarchyLayerTopology(graph: graph) - environment = LKXcodeViewHierarchyAttributeEnvironment( + topology = XcodeViewHierarchyLayerTopology(graph: graph) + environment = XcodeViewHierarchyAttributeEnvironment( isAppKit: vocabulary.isAppKit, - constraintIndex: LKXcodeViewHierarchyConstraintIndex(graph: graph), - keyWindowIdentifier: LKXcodeViewHierarchyConverter.keyWindowIdentifier(graph: graph, vocabulary: vocabulary) + constraintIndex: XcodeViewHierarchyConstraintIndex(graph: graph), + keyWindowIdentifier: XcodeViewHierarchyConverter.keyWindowIdentifier(graph: graph, vocabulary: vocabulary) ) } @@ -220,7 +220,7 @@ enum LKXcodeViewHierarchyConverter { under keyIdentifier: String, onto item: DisplayItem ) { - let oid = LKXcodeViewHierarchyConverter.objectIdentifierValue(keyIdentifier) + let oid = XcodeViewHierarchyConverter.objectIdentifierValue(keyIdentifier) guard oid != 0 else { return } let key = NSNumber(value: UInt64(oid)) if let soloIdentifier, let solo = screenshots.soloByObjectIdentifier[soloIdentifier] { @@ -375,7 +375,7 @@ enum LKXcodeViewHierarchyConverter { /// window root group first, then child windows of those, minus the ones /// its skip rule excludes. private static func listedWindowIdentifiers( - graph: LKXcodeViewHierarchyObjectGraph, + graph: XcodeViewHierarchyObjectGraph, vocabulary: Vocabulary ) -> [String] { let rootWindowIdentifiers = graph.rootIdentifiers(inGroup: vocabulary.windowGroup) @@ -399,7 +399,7 @@ enum LKXcodeViewHierarchyConverter { /// its subviews, which are not windows and are left alone here). private static func appendingChildWindowIdentifiers( of windowIdentifier: String, - graph: LKXcodeViewHierarchyObjectGraph, + graph: XcodeViewHierarchyObjectGraph, vocabulary: Vocabulary, into childWindowIdentifiers: inout [String] ) { @@ -418,8 +418,8 @@ enum LKXcodeViewHierarchyConverter { /// only recorded by the UIKit agent; AppKit captures carry neither, so no /// AppKit window is ever skipped on their account. private static func shouldSkipWindow( - _ windowNode: LKXcodeViewHierarchyNode, - graph: LKXcodeViewHierarchyObjectGraph, + _ windowNode: XcodeViewHierarchyNode, + graph: XcodeViewHierarchyObjectGraph, vocabulary: Vocabulary ) -> Bool { if isNode(windowNode, kindOfClassNamed: ClassName.systemOverlayWindow, graph: graph) { @@ -436,8 +436,8 @@ enum LKXcodeViewHierarchyConverter { /// keyboard and iMessage extension windows are the system's, but the view /// controllers inside them are the user's. private static func hostsExternallyRelevantContent( - _ windowNode: LKXcodeViewHierarchyNode, - graph: LKXcodeViewHierarchyObjectGraph, + _ windowNode: XcodeViewHierarchyNode, + graph: XcodeViewHierarchyObjectGraph, vocabulary: Vocabulary ) -> Bool { if isNode(windowNode, kindOfClassNamed: ClassName.remoteKeyboardWindow, graph: graph) { @@ -464,7 +464,7 @@ enum LKXcodeViewHierarchyConverter { /// recorded one. Xcode reads the pointer off the application, not the /// windows' own flags. private static func keyWindowIdentifier( - graph: LKXcodeViewHierarchyObjectGraph, + graph: XcodeViewHierarchyObjectGraph, vocabulary: Vocabulary ) -> String? { guard let applicationIdentifier = graph.rootIdentifiers(inGroup: vocabulary.applicationGroup).first, @@ -481,20 +481,20 @@ enum LKXcodeViewHierarchyConverter { /// A UIKit scene, the node a live session puts above its windows. private static func makingSceneItem( - sceneNode: LKXcodeViewHierarchyNode, - windowNodes: [LKXcodeViewHierarchyNode], + sceneNode: XcodeViewHierarchyNode, + windowNodes: [XcodeViewHierarchyNode], windowItems: [DisplayItem], - graph: LKXcodeViewHierarchyObjectGraph, - environment: LKXcodeViewHierarchyAttributeEnvironment + graph: XcodeViewHierarchyObjectGraph, + environment: XcodeViewHierarchyAttributeEnvironment ) -> DisplayItem { let item = makingDisplayItem(kind: .windowScene) item.windowObject = makingLookinObject(for: sceneNode, graph: graph) item.alpha = 1 item.customDisplayTitle = sceneDisplayTitle(for: sceneNode) item.representedAsKeyWindow = windowItems.contains { $0.representedAsKeyWindow } - var context = LKXcodeViewHierarchyAttributeContext(role: .windowScene, environment: environment) + var context = XcodeViewHierarchyAttributeContext(role: .windowScene, environment: environment) context.sceneWindowNodes = windowNodes - item.attributesGroupList = LKXcodeViewHierarchyAttributes.makingGroups( + item.attributesGroupList = XcodeViewHierarchyAttributes.makingGroups( for: sceneNode, layerNode: nil, graph: graph, context: context ) item.subitems = windowItems @@ -502,7 +502,7 @@ enum LKXcodeViewHierarchyConverter { } /// The server's title shape for a scene: class, title, activation state. - private static func sceneDisplayTitle(for sceneNode: LKXcodeViewHierarchyNode) -> String { + private static func sceneDisplayTitle(for sceneNode: XcodeViewHierarchyNode) -> String { var title = sceneNode.className ?? "UIWindowScene" if let sceneTitle = sceneNode.property(named: "title")?.value.textValue, !sceneTitle.isEmpty { title += " – \(sceneTitle)" @@ -524,9 +524,9 @@ enum LKXcodeViewHierarchyConverter { private static func makingWindowItem( windowIdentifier: String, isKeyWindow: Bool, - graph: LKXcodeViewHierarchyObjectGraph, + graph: XcodeViewHierarchyObjectGraph, vocabulary: Vocabulary, - environment: LKXcodeViewHierarchyAttributeEnvironment, + environment: XcodeViewHierarchyAttributeEnvironment, session: ConversionSession, convertedViewIdentifiers: inout Set ) -> DisplayItem? { @@ -536,7 +536,7 @@ enum LKXcodeViewHierarchyConverter { item.windowObject = makingLookinObject(for: windowNode, graph: graph) item.representedAsKeyWindow = isKeyWindow // A UIWindow is a view and gets a view's cards; an NSWindow is not. - var context = LKXcodeViewHierarchyAttributeContext( + var context = XcodeViewHierarchyAttributeContext( role: vocabulary.isAppKit ? .window : .view, environment: environment ) @@ -605,7 +605,7 @@ enum LKXcodeViewHierarchyConverter { owner: windowNode, graph: graph, vocabulary: vocabulary, environment: environment )) item.subitems = subitems - item.attributesGroupList = LKXcodeViewHierarchyAttributes.makingGroups( + item.attributesGroupList = XcodeViewHierarchyAttributes.makingGroups( for: windowNode, layerNode: associatedLayerNode(of: windowNode, graph: graph), graph: graph, context: context ) @@ -620,10 +620,10 @@ enum LKXcodeViewHierarchyConverter { private static func makingViewItem( viewIdentifier: String, - superviewNode: LKXcodeViewHierarchyNode?, - graph: LKXcodeViewHierarchyObjectGraph, + superviewNode: XcodeViewHierarchyNode?, + graph: XcodeViewHierarchyObjectGraph, vocabulary: Vocabulary, - environment: LKXcodeViewHierarchyAttributeEnvironment, + environment: XcodeViewHierarchyAttributeEnvironment, session: ConversionSession, convertedViewIdentifiers: inout Set ) -> DisplayItem? { @@ -652,7 +652,7 @@ enum LKXcodeViewHierarchyConverter { } applyingVisibility(from: viewNode, to: item) - var context = LKXcodeViewHierarchyAttributeContext(role: .view, environment: environment) + var context = XcodeViewHierarchyAttributeContext(role: .view, environment: environment) context.superviewNode = superviewNode if let controllerIdentifier = viewNode.associatedIdentifiers(inGroup: vocabulary.viewControllerGroup).first, let controllerNode = graph.node(controllerIdentifier) @@ -660,7 +660,7 @@ enum LKXcodeViewHierarchyConverter { item.hostViewControllerObject = makingLookinObject(for: controllerNode, graph: graph) context.viewControllerNode = controllerNode } - item.attributesGroupList = LKXcodeViewHierarchyAttributes.makingGroups( + item.attributesGroupList = XcodeViewHierarchyAttributes.makingGroups( for: viewNode, layerNode: associatedLayerNode(of: viewNode, graph: graph), graph: graph, context: context ) @@ -702,11 +702,11 @@ enum LKXcodeViewHierarchyConverter { private struct OwnedLayers { /// The layer the capture associates with the object: its backing /// layer, or on iOS 26 the `_UIMultiLayer` wrapper UIKit put above it. - let associatedNode: LKXcodeViewHierarchyNode + let associatedNode: XcodeViewHierarchyNode /// The layer whose contents are the object's own drawing. - let backingNode: LKXcodeViewHierarchyNode + let backingNode: XcodeViewHierarchyNode /// The wrapper, when UIKit installed one; nil elsewhere. - let outerNode: LKXcodeViewHierarchyNode? + let outerNode: XcodeViewHierarchyNode? } private static let multiLayerWrapperClassName = "_UIMultiLayer" @@ -719,8 +719,8 @@ enum LKXcodeViewHierarchyConverter { /// delegate is the view too, but any other layer parked on the wrapper /// belongs to someone else (the server's `lks_viewWrappedAsOuterLayer`). private static func resolvingOwnedLayers( - of node: LKXcodeViewHierarchyNode, - graph: LKXcodeViewHierarchyObjectGraph + of node: XcodeViewHierarchyNode, + graph: XcodeViewHierarchyObjectGraph ) -> OwnedLayers? { guard let associatedNode = associatedLayerNode(of: node, graph: graph) else { return nil } guard isNode(associatedNode, kindOfClassNamed: multiLayerWrapperClassName, graph: graph) else { @@ -819,7 +819,7 @@ enum LKXcodeViewHierarchyConverter { /// the end. private static func interleaving( _ subviewItems: [DisplayItem], - amongSublayersOf backingNode: LKXcodeViewHierarchyNode, + amongSublayersOf backingNode: XcodeViewHierarchyNode, session: ConversionSession ) -> [DisplayItem] { var anchoredItems: [String: [DisplayItem]] = [:] @@ -890,7 +890,7 @@ enum LKXcodeViewHierarchyConverter { /// edge to edge; its solo is the layer's own content and its group the /// subtree minus the subviews' planes, which render on their own nodes. private static func makingBackingLayerItem( - _ backingNode: LKXcodeViewHierarchyNode, + _ backingNode: XcodeViewHierarchyNode, session: ConversionSession ) -> DisplayItem { session.convertedLayerIdentifiers.insert(backingNode.objectIdentifier) @@ -919,7 +919,7 @@ enum LKXcodeViewHierarchyConverter { /// pixels (the contents stayed on the backing layer), so no image is /// filed for it; the host suppresses screenshots for this kind. private static func makingOuterLayerItem( - _ outerNode: LKXcodeViewHierarchyNode, + _ outerNode: XcodeViewHierarchyNode, session: ConversionSession ) -> DisplayItem { session.convertedLayerIdentifiers.insert(outerNode.objectIdentifier) @@ -933,11 +933,11 @@ enum LKXcodeViewHierarchyConverter { } private static func makingLayerAttributeGroups( - for layerNode: LKXcodeViewHierarchyNode, + for layerNode: XcodeViewHierarchyNode, session: ConversionSession ) -> [AttributesGroup] { - let context = LKXcodeViewHierarchyAttributeContext(role: .layer, environment: session.environment) - return LKXcodeViewHierarchyAttributes.makingGroups( + let context = XcodeViewHierarchyAttributeContext(role: .layer, environment: session.environment) + return XcodeViewHierarchyAttributes.makingGroups( for: layerNode, layerNode: layerNode, graph: session.graph, context: context ) } @@ -947,7 +947,7 @@ enum LKXcodeViewHierarchyConverter { /// own drawing (a CGDisplayList) rather than an image the app assigned. /// Its pixels are the host view's; with the toggle off it is no node. private static func representsDrawingContainer( - _ layerNode: LKXcodeViewHierarchyNode, + _ layerNode: XcodeViewHierarchyNode, session: ConversionSession ) -> Bool { guard session.vocabulary.isAppKit else { return false } @@ -965,12 +965,12 @@ enum LKXcodeViewHierarchyConverter { /// A layer node covering its parent node edge to edge: origin zero, the /// layer's own size (the server's shape for backing and wrapper nodes). - private static func applyingCoveringGeometry(from layerNode: LKXcodeViewHierarchyNode, to item: DisplayItem) { + private static func applyingCoveringGeometry(from layerNode: XcodeViewHierarchyNode, to item: DisplayItem) { applyingGeometry(from: layerNode, to: item) item.frame = CGRect(origin: .zero, size: item.bounds.size) } - private static func applyingLayerVisibility(from layerNode: LKXcodeViewHierarchyNode, to item: DisplayItem) { + private static func applyingLayerVisibility(from layerNode: XcodeViewHierarchyNode, to item: DisplayItem) { applyingVisibility(from: layerNode, to: item) // The server reads a layer node's flip off the layer itself. item.isFlipped = layerNode.property(named: "geometryFlipped")?.value.boolValue ?? false @@ -979,12 +979,12 @@ enum LKXcodeViewHierarchyConverter { /// Layout guides mark out a region of their owner and carry no pixels of /// their own — the node model's LayoutGuide kind, riding `kindObject`. private static func makingLayoutGuideItems( - owner: LKXcodeViewHierarchyNode, - graph: LKXcodeViewHierarchyObjectGraph, + owner: XcodeViewHierarchyNode, + graph: XcodeViewHierarchyObjectGraph, vocabulary: Vocabulary, - environment: LKXcodeViewHierarchyAttributeEnvironment + environment: XcodeViewHierarchyAttributeEnvironment ) -> [DisplayItem] { - var context = LKXcodeViewHierarchyAttributeContext(role: .layoutGuide, environment: environment) + var context = XcodeViewHierarchyAttributeContext(role: .layoutGuide, environment: environment) context.ownerNode = owner return owner.associatedIdentifiers(inGroup: vocabulary.layoutGuideGroup).compactMap { guideIdentifier in guard let guideNode = graph.node(guideIdentifier) else { return nil } @@ -998,7 +998,7 @@ enum LKXcodeViewHierarchyConverter { applyingGeometry(from: guideNode, to: item) } item.alpha = 1 - item.attributesGroupList = LKXcodeViewHierarchyAttributes.makingGroups( + item.attributesGroupList = XcodeViewHierarchyAttributes.makingGroups( for: guideNode, layerNode: nil, graph: graph, context: context ) return item @@ -1008,12 +1008,12 @@ enum LKXcodeViewHierarchyConverter { /// An AppKit control's cell, promoted to a first-class node by the /// cell-node proposal: pixelless, attributes read from the cell itself. private static func makingCellItems( - owner: LKXcodeViewHierarchyNode, + owner: XcodeViewHierarchyNode, cellGroup: String, - graph: LKXcodeViewHierarchyObjectGraph, - environment: LKXcodeViewHierarchyAttributeEnvironment + graph: XcodeViewHierarchyObjectGraph, + environment: XcodeViewHierarchyAttributeEnvironment ) -> [DisplayItem] { - var context = LKXcodeViewHierarchyAttributeContext(role: .cell, environment: environment) + var context = XcodeViewHierarchyAttributeContext(role: .cell, environment: environment) context.ownerNode = owner return owner.associatedIdentifiers(inGroup: cellGroup).compactMap { cellIdentifier in guard let cellNode = graph.node(cellIdentifier) else { return nil } @@ -1021,7 +1021,7 @@ enum LKXcodeViewHierarchyConverter { item.kindObject = makingLookinObject(for: cellNode, graph: graph) applyingGeometry(from: cellNode, to: item) item.alpha = 1 - item.attributesGroupList = LKXcodeViewHierarchyAttributes.makingGroups( + item.attributesGroupList = XcodeViewHierarchyAttributes.makingGroups( for: cellNode, layerNode: nil, graph: graph, context: context ) return item @@ -1030,7 +1030,7 @@ enum LKXcodeViewHierarchyConverter { /// Layout guides the system creates (safe area, layout margins, readable /// width) drive the inspector's toggle for hiding them. - private static func looksSystemManaged(_ guideNode: LKXcodeViewHierarchyNode) -> Bool { + private static func looksSystemManaged(_ guideNode: XcodeViewHierarchyNode) -> Bool { let identifier = guideNode.property(named: "identifier")?.value.textValue ?? "" if identifier.hasPrefix("UIView") || identifier.hasPrefix("NSView") { return true @@ -1060,18 +1060,18 @@ enum LKXcodeViewHierarchyConverter { /// Xcode's `isKindOfTypeWithName:` — the class or any of its ancestors. private static func isNode( - _ node: LKXcodeViewHierarchyNode, + _ node: XcodeViewHierarchyNode, kindOfClassNamed className: String, - graph: LKXcodeViewHierarchyObjectGraph + graph: XcodeViewHierarchyObjectGraph ) -> Bool { guard let nodeClassName = node.className else { return false } return graph.classChain(forClassName: nodeClassName).contains(className) } private static func associatedLayerNode( - of node: LKXcodeViewHierarchyNode, - graph: LKXcodeViewHierarchyObjectGraph - ) -> LKXcodeViewHierarchyNode? { + of node: XcodeViewHierarchyNode, + graph: XcodeViewHierarchyObjectGraph + ) -> XcodeViewHierarchyNode? { guard let layerIdentifier = node.associatedIdentifiers(inGroup: GroupIdentifier.layer).first else { return nil } @@ -1079,8 +1079,8 @@ enum LKXcodeViewHierarchyConverter { } private static func makingLookinObject( - for node: LKXcodeViewHierarchyNode, - graph: LKXcodeViewHierarchyObjectGraph + for node: XcodeViewHierarchyNode, + graph: XcodeViewHierarchyObjectGraph ) -> InspectedObject { let object = InspectedObject() object.oid = objectIdentifierValue(node.objectIdentifier) @@ -1091,8 +1091,8 @@ enum LKXcodeViewHierarchyConverter { } private static func applyingGeometry( - from node: LKXcodeViewHierarchyNode, - fallback fallbackNode: LKXcodeViewHierarchyNode? = nil, + from node: XcodeViewHierarchyNode, + fallback fallbackNode: XcodeViewHierarchyNode? = nil, to item: DisplayItem ) { if let frameComponents = node.property(named: "frame")?.value.numericComponents(expectedCount: 4) { @@ -1113,7 +1113,7 @@ enum LKXcodeViewHierarchyConverter { } } - private static func applyingVisibility(from node: LKXcodeViewHierarchyNode, to item: DisplayItem) { + private static func applyingVisibility(from node: XcodeViewHierarchyNode, to item: DisplayItem) { item.isHidden = node.property(named: "hidden")?.value.boolValue ?? false if let alpha = node.property(named: "alpha")?.value.doubleValue { item.alpha = Float(alpha) @@ -1126,7 +1126,7 @@ enum LKXcodeViewHierarchyConverter { /// The inspector paints this before a screenshot is available, so a node /// with no recovered pixels still reads as something rather than a hole. - private static func applyingBackgroundColor(from layerNode: LKXcodeViewHierarchyNode, to item: DisplayItem) { + private static func applyingBackgroundColor(from layerNode: XcodeViewHierarchyNode, to item: DisplayItem) { guard case let .color(color)? = layerNode.property(named: "backgroundColor")?.value, color.components.count >= 3 else { return } @@ -1157,7 +1157,7 @@ enum LKXcodeViewHierarchyConverter { // MARK: App info private static func makingAppInfo( - from bundle: LKXcodeViewHierarchyBundle, + from bundle: XcodeViewHierarchyBundle, vocabulary: Vocabulary ) -> InspectedAppInfo { let appInfo = InspectedAppInfo() @@ -1171,7 +1171,7 @@ enum LKXcodeViewHierarchyConverter { } } -extension LKXcodeViewHierarchyConversionError: LocalizedError { +extension XcodeViewHierarchyConversionError: LocalizedError { var errorDescription: String? { description } diff --git a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyDocument.swift b/LookInside/XcodeViewHierarchy/XcodeViewHierarchyDocument.swift similarity index 80% rename from LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyDocument.swift rename to LookInside/XcodeViewHierarchy/XcodeViewHierarchyDocument.swift index 4b77fd2d..28e74cdf 100644 --- a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyDocument.swift +++ b/LookInside/XcodeViewHierarchy/XcodeViewHierarchyDocument.swift @@ -1,9 +1,9 @@ -// LKXcodeViewHierarchyDocument.swift +// XcodeViewHierarchyDocument.swift // // The document type for Xcode-exported `.viewhierarchy` captures, and the // import pipeline behind it. // -// It subclasses `LookinArchiveDocument` rather than `NSDocument` directly so +// It subclasses `ArchiveDocument` rather than `NSDocument` directly so // that the entire reader — window controller, hierarchy tree, preview, // dashboard — is reused untouched. Once the import lands, the document holds // an ordinary `HierarchyFile`, indistinguishable from one that came out @@ -18,7 +18,7 @@ // and builds the reader in place when the import finishes. // // The import itself is split the same way: decoding and rendering produce an -// `LKXcodeViewHierarchyImportedCapture`, which the document keeps; shaping it +// `XcodeViewHierarchyImportedCapture`, which the document keeps; shaping it // into a tree is cheap and is redone whenever the window's show-backing-layers // toggle flips, the way a live session reloads its hierarchy for that toggle. @@ -28,12 +28,12 @@ import Foundation /// A capture decoded and rendered, but not yet shaped into a tree: what the /// document keeps so the tree can be rebuilt for the other setting of the /// show-backing-layers toggle without decoding or rendering again. -struct LKXcodeViewHierarchyImportedCapture { - let bundle: LKXcodeViewHierarchyBundle - let screenshots: LKXcodeViewHierarchyScreenshots +struct XcodeViewHierarchyImportedCapture { + let bundle: XcodeViewHierarchyBundle + let screenshots: XcodeViewHierarchyScreenshots } -enum LKXcodeViewHierarchyImporter { +enum XcodeViewHierarchyImporter { /// Reads a capture and recovers its pixels: the expensive half. /// /// Synchronous and not cheap; run it off the main thread. It must stay on @@ -43,25 +43,25 @@ enum LKXcodeViewHierarchyImporter { static func importingCapture( at url: URL, isCancelled: () -> Bool = { false } - ) throws -> LKXcodeViewHierarchyImportedCapture { - let bundle = try LKXcodeViewHierarchyBundleReader.reading(contentsOf: url) + ) throws -> XcodeViewHierarchyImportedCapture { + let bundle = try XcodeViewHierarchyBundleReader.reading(contentsOf: url) if isCancelled() { throw CancellationError() } - let screenshots = LKXcodeViewHierarchyPixelRecovery.recovering(from: bundle.graph, isCancelled: isCancelled) + let screenshots = XcodeViewHierarchyPixelRecovery.recovering(from: bundle.graph, isCancelled: isCancelled) if isCancelled() { throw CancellationError() } - return LKXcodeViewHierarchyImportedCapture(bundle: bundle, screenshots: screenshots) + return XcodeViewHierarchyImportedCapture(bundle: bundle, screenshots: screenshots) } /// Shapes an imported capture into the inspector's model: the cheap half, /// repeated whenever the backing-layer toggle flips. static func makingHierarchyFile( - from capture: LKXcodeViewHierarchyImportedCapture, + from capture: XcodeViewHierarchyImportedCapture, showingBackingLayers: Bool ) throws -> HierarchyFile { - try LKXcodeViewHierarchyConverter.makingHierarchyFile( + try XcodeViewHierarchyConverter.makingHierarchyFile( from: capture.bundle, screenshots: capture.screenshots, showingBackingLayers: showingBackingLayers ) } @@ -81,23 +81,23 @@ enum LKXcodeViewHierarchyImporter { } @objc(LKXcodeViewHierarchyDocument) -final class LKXcodeViewHierarchyDocument: LookinArchiveDocument { +final class XcodeViewHierarchyDocument: ArchiveDocument { private var importTask: Task? private var rebuildTask: Task? /// Kept for the document's lifetime so the tree can be rebuilt when the /// show-backing-layers toggle flips; the layer archives themselves are /// not kept — the rendered images are all a rebuild needs. - private var importedCapture: LKXcodeViewHierarchyImportedCapture? + private var importedCapture: XcodeViewHierarchyImportedCapture? /// Validates the package and starts the import, returning before the /// import finishes so the window can open on its placeholder. override func read(from url: URL, ofType _: String) throws { - try LKXcodeViewHierarchyBundleReader.validatingBundle(at: url) + try XcodeViewHierarchyBundleReader.validatingBundle(at: url) importTask?.cancel() importTask = Task.detached(priority: .userInitiated) { [weak self] in - let outcome: Result + let outcome: Result do { - outcome = try .success(LKXcodeViewHierarchyImporter.importingCapture(at: url) { Task.isCancelled }) + outcome = try .success(XcodeViewHierarchyImporter.importingCapture(at: url) { Task.isCancelled }) } catch { outcome = .failure(error) } @@ -128,7 +128,7 @@ final class LKXcodeViewHierarchyDocument: LookinArchiveDocument { rebuildTask = Task.detached(priority: .userInitiated) { [weak self] in let outcome: Result do { - outcome = try .success(LKXcodeViewHierarchyImporter.makingHierarchyFile( + outcome = try .success(XcodeViewHierarchyImporter.makingHierarchyFile( from: importedCapture, showingBackingLayers: showingBackingLayers )) } catch { @@ -143,10 +143,10 @@ final class LKXcodeViewHierarchyDocument: LookinArchiveDocument { /// for through it, and before it exists the persisted default applies. @MainActor private var showsBackingLayersPreference: Bool { - if let windowController = windowControllers.first as? LKReadWindowController { + if let windowController = windowControllers.first as? ReadWindowController { return windowController.preferenceManager.showBackingLayers.currentBOOLValue } - return LKPreferenceManager.shared.showBackingLayers.currentBOOLValue + return PreferenceManager.shared.showBackingLayers.currentBOOLValue } /// The task has to be created where `close()` can cancel it, on the @@ -156,7 +156,7 @@ final class LKXcodeViewHierarchyDocument: LookinArchiveDocument { } @MainActor - private func finishingImport(with outcome: Result) { + private func finishingImport(with outcome: Result) { importTask = nil switch outcome { case let .success(capture): diff --git a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyGzip.swift b/LookInside/XcodeViewHierarchy/XcodeViewHierarchyGzip.swift similarity index 83% rename from LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyGzip.swift rename to LookInside/XcodeViewHierarchy/XcodeViewHierarchyGzip.swift index 1895114f..5085a404 100644 --- a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyGzip.swift +++ b/LookInside/XcodeViewHierarchy/XcodeViewHierarchyGzip.swift @@ -1,4 +1,4 @@ -// LKXcodeViewHierarchyGzip.swift +// XcodeViewHierarchyGzip.swift // // Gzip inflation for the `Response_N` entries inside an Xcode-exported // `.viewhierarchy` bundle. @@ -19,7 +19,7 @@ import Compression import Foundation -enum LKXcodeViewHierarchyGzipError: Error, CustomStringConvertible { +enum XcodeViewHierarchyGzipError: Error, CustomStringConvertible { case truncatedHeader case unsupportedCompressionMethod(UInt8) case truncatedPayload @@ -39,7 +39,7 @@ enum LKXcodeViewHierarchyGzipError: Error, CustomStringConvertible { } } -enum LKXcodeViewHierarchyGzip { +enum XcodeViewHierarchyGzip { private static let streamBufferSize = 256 * 1024 private enum HeaderFlag { @@ -69,22 +69,22 @@ enum LKXcodeViewHierarchyGzip { static func inflating(_ payload: Data) throws -> Data { let bytes = [UInt8](payload) let deflateStart = try deflateStreamOffset(in: bytes) - guard bytes.count >= deflateStart + 8 else { throw LKXcodeViewHierarchyGzipError.truncatedPayload } + guard bytes.count >= deflateStart + 8 else { throw XcodeViewHierarchyGzipError.truncatedPayload } let deflateBytes = bytes[deflateStart ..< (bytes.count - 8)] return try inflatingRawDeflate(Array(deflateBytes)) } /// Walks the variable-length gzip header and returns where the DEFLATE stream starts. private static func deflateStreamOffset(in bytes: [UInt8]) throws -> Int { - guard bytes.count >= 10 else { throw LKXcodeViewHierarchyGzipError.truncatedHeader } - guard bytes[0] == 0x1F, bytes[1] == 0x8B else { throw LKXcodeViewHierarchyGzipError.truncatedHeader } - guard bytes[2] == 8 else { throw LKXcodeViewHierarchyGzipError.unsupportedCompressionMethod(bytes[2]) } + guard bytes.count >= 10 else { throw XcodeViewHierarchyGzipError.truncatedHeader } + guard bytes[0] == 0x1F, bytes[1] == 0x8B else { throw XcodeViewHierarchyGzipError.truncatedHeader } + guard bytes[2] == 8 else { throw XcodeViewHierarchyGzipError.unsupportedCompressionMethod(bytes[2]) } let flags = bytes[3] var cursor = 10 if flags & HeaderFlag.extraField != 0 { - guard cursor + 1 < bytes.count else { throw LKXcodeViewHierarchyGzipError.truncatedHeader } + guard cursor + 1 < bytes.count else { throw XcodeViewHierarchyGzipError.truncatedHeader } let extraFieldLength = Int(bytes[cursor]) | (Int(bytes[cursor + 1]) << 8) cursor += 2 + extraFieldLength } @@ -98,7 +98,7 @@ enum LKXcodeViewHierarchyGzip { cursor += 2 } - guard cursor < bytes.count else { throw LKXcodeViewHierarchyGzipError.truncatedHeader } + guard cursor < bytes.count else { throw XcodeViewHierarchyGzipError.truncatedHeader } return cursor } @@ -107,7 +107,7 @@ enum LKXcodeViewHierarchyGzip { while cursor < bytes.count, bytes[cursor] != 0 { cursor += 1 } - guard cursor < bytes.count else { throw LKXcodeViewHierarchyGzipError.truncatedHeader } + guard cursor < bytes.count else { throw XcodeViewHierarchyGzipError.truncatedHeader } return cursor + 1 } @@ -122,7 +122,7 @@ enum LKXcodeViewHierarchyGzip { state: nil ) guard compression_stream_init(&stream, COMPRESSION_STREAM_DECODE, COMPRESSION_ZLIB) == COMPRESSION_STATUS_OK - else { throw LKXcodeViewHierarchyGzipError.inflateFailed } + else { throw XcodeViewHierarchyGzipError.inflateFailed } defer { compression_stream_destroy(&stream) } var inflated = Data() @@ -148,9 +148,9 @@ enum LKXcodeViewHierarchyGzip { return inflated case COMPRESSION_STATUS_OK: // Ran out of destination room; loop for another buffer. - guard producedCount > 0 else { throw LKXcodeViewHierarchyGzipError.inflateFailed } + guard producedCount > 0 else { throw XcodeViewHierarchyGzipError.inflateFailed } default: - throw LKXcodeViewHierarchyGzipError.inflateFailed + throw XcodeViewHierarchyGzipError.inflateFailed } } } diff --git a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyLayerArchive.swift b/LookInside/XcodeViewHierarchy/XcodeViewHierarchyLayerArchive.swift similarity index 92% rename from LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyLayerArchive.swift rename to LookInside/XcodeViewHierarchy/XcodeViewHierarchyLayerArchive.swift index b9d6b613..5c93c57a 100644 --- a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyLayerArchive.swift +++ b/LookInside/XcodeViewHierarchy/XcodeViewHierarchyLayerArchive.swift @@ -1,4 +1,4 @@ -// LKXcodeViewHierarchyLayerArchive.swift +// XcodeViewHierarchyLayerArchive.swift // // Decodes the `encodedPresentationLayer` payloads in a `.viewhierarchy` // capture, and pairs the layers they contain with the objects the capture @@ -33,7 +33,7 @@ import AppKit import Foundation import QuartzCore -struct LKXcodeViewHierarchyLayerTree { +struct XcodeViewHierarchyLayerTree { /// Object identifier of the captured layer this archive is rooted at. let rootObjectIdentifier: String let rootLayer: CALayer @@ -41,16 +41,16 @@ struct LKXcodeViewHierarchyLayerTree { let isGeometryFlipped: Bool } -enum LKXcodeViewHierarchyLayerArchive { +enum XcodeViewHierarchyLayerArchive { static let propertyName = "encodedPresentationLayer" private static let rootLayerKey = "rootLayer" private static let geometryFlippedKey = "geometryFlipped" /// Decodes every layer archive the capture carries, in a stable order. static func decodingLayerTrees( - in graph: LKXcodeViewHierarchyObjectGraph - ) -> (trees: [LKXcodeViewHierarchyLayerTree], failedIdentifiers: [String]) { - var trees: [LKXcodeViewHierarchyLayerTree] = [] + in graph: XcodeViewHierarchyObjectGraph + ) -> (trees: [XcodeViewHierarchyLayerTree], failedIdentifiers: [String]) { + var trees: [XcodeViewHierarchyLayerTree] = [] var failedIdentifiers: [String] = [] for objectIdentifier in graph.nodesByIdentifier.keys.sorted() { @@ -68,7 +68,7 @@ enum LKXcodeViewHierarchyLayerArchive { return (trees, failedIdentifiers) } - static func decodingLayerTree(from archiveData: Data, rootObjectIdentifier: String) -> LKXcodeViewHierarchyLayerTree? { + static func decodingLayerTree(from archiveData: Data, rootObjectIdentifier: String) -> XcodeViewHierarchyLayerTree? { guard let unarchiver = try? NSKeyedUnarchiver(forReadingFrom: archiveData) else { return nil } // The archive names QuartzCore's private coding proxies, which cannot // be declared to a secure unarchiver ahead of time. @@ -79,7 +79,7 @@ enum LKXcodeViewHierarchyLayerArchive { let rootLayer = root[rootLayerKey] as? CALayer else { return nil } - return LKXcodeViewHierarchyLayerTree( + return XcodeViewHierarchyLayerTree( rootObjectIdentifier: rootObjectIdentifier, rootLayer: rootLayer, isGeometryFlipped: (root[geometryFlippedKey] as? NSNumber)?.boolValue ?? false @@ -90,7 +90,7 @@ enum LKXcodeViewHierarchyLayerArchive { // MARK: - Alignment /// Pairs captured layer objects with the archived layers that hold their pixels. -enum LKXcodeViewHierarchyLayerAlignment { +enum XcodeViewHierarchyLayerAlignment { /// Positional tolerance when matching a captured layer to an archived one. /// /// The archive holds the *presentation* layer while the capture's numbers @@ -101,8 +101,8 @@ enum LKXcodeViewHierarchyLayerAlignment { /// Maps captured layer object identifiers to archived layers. static func aligning( - trees: [LKXcodeViewHierarchyLayerTree], - graph: LKXcodeViewHierarchyObjectGraph + trees: [XcodeViewHierarchyLayerTree], + graph: XcodeViewHierarchyObjectGraph ) -> [String: CALayer] { var alignment: [String: CALayer] = [:] for tree in trees { @@ -119,7 +119,7 @@ enum LKXcodeViewHierarchyLayerAlignment { private static func aligning( capturedIdentifier: String, archivedLayer: CALayer, - graph: LKXcodeViewHierarchyObjectGraph, + graph: XcodeViewHierarchyObjectGraph, into alignment: inout [String: CALayer] ) { // A layer reached twice would mean a cycle in the capture; stop rather @@ -157,7 +157,7 @@ enum LKXcodeViewHierarchyLayerAlignment { private static func pairing( capturedChildren: [String], archivedChildren: [CALayer], - graph: LKXcodeViewHierarchyObjectGraph + graph: XcodeViewHierarchyObjectGraph ) -> [(String, CALayer)] { if capturedChildren.count == archivedChildren.count { return Array(zip(capturedChildren, archivedChildren)) @@ -188,7 +188,7 @@ enum LKXcodeViewHierarchyLayerAlignment { private static func geometry( ofCapturedLayer objectIdentifier: String, - graph: LKXcodeViewHierarchyObjectGraph + graph: XcodeViewHierarchyObjectGraph ) -> CapturedGeometry { guard let node = graph.node(objectIdentifier) else { return CapturedGeometry(bounds: nil, position: nil) diff --git a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyLayerTopology.swift b/LookInside/XcodeViewHierarchy/XcodeViewHierarchyLayerTopology.swift similarity index 95% rename from LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyLayerTopology.swift rename to LookInside/XcodeViewHierarchy/XcodeViewHierarchyLayerTopology.swift index 0e31ab80..e0030d53 100644 --- a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyLayerTopology.swift +++ b/LookInside/XcodeViewHierarchy/XcodeViewHierarchyLayerTopology.swift @@ -1,4 +1,4 @@ -// LKXcodeViewHierarchyLayerTopology.swift +// XcodeViewHierarchyLayerTopology.swift // // Which layers of a capture back a view, and how the layer tree hangs // together. Shared by pixel recovery (which sublayers to hide when a layer @@ -13,7 +13,7 @@ import Foundation -struct LKXcodeViewHierarchyLayerTopology { +struct XcodeViewHierarchyLayerTopology { static let layerGroupingIdentifier = "com.apple.QuartzCore.CALayer" /// Layers some captured object owns as its `layer`: views and, on UIKit, @@ -23,7 +23,7 @@ struct LKXcodeViewHierarchyLayerTopology { /// Superlayer of every layer that has one. let parentByLayerIdentifier: [String: String] - init(graph: LKXcodeViewHierarchyObjectGraph) { + init(graph: XcodeViewHierarchyObjectGraph) { var hosted: Set = [] var parents: [String: String] = [:] for (identifier, node) in graph.nodesByIdentifier { @@ -49,7 +49,7 @@ struct LKXcodeViewHierarchyLayerTopology { /// render, which a layer node's own image must leave out. func hostedDescendantIdentifiers( of layerIdentifier: String, - graph: LKXcodeViewHierarchyObjectGraph + graph: XcodeViewHierarchyObjectGraph ) -> [String] { var collected: [String] = [] var visited: Set = [layerIdentifier] diff --git a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyObjectGraph.swift b/LookInside/XcodeViewHierarchy/XcodeViewHierarchyObjectGraph.swift similarity index 93% rename from LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyObjectGraph.swift rename to LookInside/XcodeViewHierarchy/XcodeViewHierarchyObjectGraph.swift index 62f79426..3592dd09 100644 --- a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyObjectGraph.swift +++ b/LookInside/XcodeViewHierarchy/XcodeViewHierarchyObjectGraph.swift @@ -1,4 +1,4 @@ -// LKXcodeViewHierarchyObjectGraph.swift +// XcodeViewHierarchyObjectGraph.swift // // Assembles the object graph a `.viewhierarchy` capture describes, by merging // the several JSON responses a capture is split across. @@ -41,20 +41,20 @@ import Foundation // MARK: - Property -struct LKXcodeViewHierarchyProperty { +struct XcodeViewHierarchyProperty { let name: String let runtimeTypeName: String? let logicalTypeName: String? let format: String? - let value: LKXcodeViewHierarchyValue - let fetchStatus: LKXcodeViewHierarchyFetchStatus + let value: XcodeViewHierarchyValue + let fetchStatus: XcodeViewHierarchyFetchStatus } // MARK: - Node /// One object in the capture. Reference semantics because the same node is /// reached from several responses and refined in place. -final class LKXcodeViewHierarchyNode { +final class XcodeViewHierarchyNode { let objectIdentifier: String /// Nil until a response describes this object in full rather than referencing it. var className: String? @@ -65,7 +65,7 @@ final class LKXcodeViewHierarchyNode { var childIdentifiers: [String] = [] /// Associated objects by grouping identifier, in capture order. var additionalGroups: [(groupingIdentifier: String, objectIdentifiers: [String])] = [] - var properties: [String: LKXcodeViewHierarchyProperty] = [:] + var properties: [String: XcodeViewHierarchyProperty] = [:] init(objectIdentifier: String) { self.objectIdentifier = objectIdentifier @@ -76,15 +76,15 @@ final class LKXcodeViewHierarchyNode { additionalGroups.first { $0.groupingIdentifier == groupingIdentifier }?.objectIdentifiers ?? [] } - func property(named name: String) -> LKXcodeViewHierarchyProperty? { + func property(named name: String) -> XcodeViewHierarchyProperty? { properties[name] } } // MARK: - Graph -struct LKXcodeViewHierarchyObjectGraph { - let nodesByIdentifier: [String: LKXcodeViewHierarchyNode] +struct XcodeViewHierarchyObjectGraph { + let nodesByIdentifier: [String: XcodeViewHierarchyNode] /// Top-level groupings in capture order, each with its root objects. let rootGroups: [(groupingIdentifier: String, objectIdentifiers: [String])] /// Superclass of each class the capture described, from `classInformation`. @@ -97,7 +97,7 @@ struct LKXcodeViewHierarchyObjectGraph { /// represented here; see rule 5 in the file comment. let captureCount: Int - func node(_ objectIdentifier: String) -> LKXcodeViewHierarchyNode? { + func node(_ objectIdentifier: String) -> XcodeViewHierarchyNode? { nodesByIdentifier[objectIdentifier] } @@ -125,8 +125,8 @@ struct LKXcodeViewHierarchyObjectGraph { // MARK: - Builder -final class LKXcodeViewHierarchyObjectGraphBuilder { - private var nodesByIdentifier: [String: LKXcodeViewHierarchyNode] = [:] +final class XcodeViewHierarchyObjectGraphBuilder { + private var nodesByIdentifier: [String: XcodeViewHierarchyNode] = [:] private var rootGroupOrder: [String] = [] private var rootGroupMembers: [String: [String]] = [:] private var superclassByClassName: [String: String] = [:] @@ -192,7 +192,7 @@ final class LKXcodeViewHierarchyObjectGraphBuilder { } } - private func ingestingGroup(_ group: [String: Any], isOwnedChildGroup: Bool, parent: LKXcodeViewHierarchyNode?) { + private func ingestingGroup(_ group: [String: Any], isOwnedChildGroup: Bool, parent: XcodeViewHierarchyNode?) { let groupingIdentifier = group["groupingID"] as? String ?? "" let objects = group["debugHierarchyObjects"] as? [Any] ?? [] @@ -306,14 +306,14 @@ final class LKXcodeViewHierarchyObjectGraphBuilder { private func applyingPropertyDescription( _ rawDescription: [String: Any], - to node: LKXcodeViewHierarchyNode, + to node: XcodeViewHierarchyNode, responseVersion: Int ) { let description = modernizingPropertyDescription(rawDescription, responseVersion: responseVersion) guard let propertyName = description["propertyName"] as? String else { return } let fetchStatusValue = (description["fetchStatus"] as? NSNumber)?.intValue ?? 0 - let fetchStatus = LKXcodeViewHierarchyFetchStatus(rawValue: fetchStatusValue) ?? .failed + let fetchStatus = XcodeViewHierarchyFetchStatus(rawValue: fetchStatusValue) ?? .failed // Rule from Xcode's reader: a failed or unchanged fetch must not // overwrite what an earlier response already established. @@ -322,10 +322,10 @@ final class LKXcodeViewHierarchyObjectGraphBuilder { } let format = description["propertyFormat"] as? String - var decodedValue = LKXcodeViewHierarchyValue.absent + var decodedValue = XcodeViewHierarchyValue.absent if fetchStatus == .retrieved, let format, !format.isEmpty { do { - decodedValue = try LKXcodeViewHierarchyValueDecoder.decoding( + decodedValue = try XcodeViewHierarchyValueDecoder.decoding( jsonValue: description["propertyValue"], format: format ) } catch { @@ -334,7 +334,7 @@ final class LKXcodeViewHierarchyObjectGraphBuilder { } } - node.properties[propertyName] = LKXcodeViewHierarchyProperty( + node.properties[propertyName] = XcodeViewHierarchyProperty( name: propertyName, runtimeTypeName: description["propertyRuntimeType"] as? String, logicalTypeName: description["propertyLogicalType"] as? String, @@ -388,11 +388,11 @@ final class LKXcodeViewHierarchyObjectGraphBuilder { decodingIssues.removeAll() } - private func nodeForIdentifier(_ objectIdentifier: String) -> LKXcodeViewHierarchyNode { + private func nodeForIdentifier(_ objectIdentifier: String) -> XcodeViewHierarchyNode { if let existing = nodesByIdentifier[objectIdentifier] { return existing } - let created = LKXcodeViewHierarchyNode(objectIdentifier: objectIdentifier) + let created = XcodeViewHierarchyNode(objectIdentifier: objectIdentifier) nodesByIdentifier[objectIdentifier] = created return created } @@ -400,7 +400,7 @@ final class LKXcodeViewHierarchyObjectGraphBuilder { private func appendingAdditionalGroup( groupingIdentifier: String, objectIdentifiers: [String], - to node: LKXcodeViewHierarchyNode + to node: XcodeViewHierarchyNode ) { if let existingIndex = node.additionalGroups.firstIndex(where: { $0.groupingIdentifier == groupingIdentifier }) { let merged = mergingPreservingOrder( @@ -431,8 +431,8 @@ final class LKXcodeViewHierarchyObjectGraphBuilder { // MARK: Result - func build() -> LKXcodeViewHierarchyObjectGraph { - LKXcodeViewHierarchyObjectGraph( + func build() -> XcodeViewHierarchyObjectGraph { + XcodeViewHierarchyObjectGraph( nodesByIdentifier: nodesByIdentifier, rootGroups: rootGroupOrder.map { ($0, rootGroupMembers[$0] ?? []) }, superclassByClassName: superclassByClassName, diff --git a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyPixelRecovery.swift b/LookInside/XcodeViewHierarchy/XcodeViewHierarchyPixelRecovery.swift similarity index 96% rename from LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyPixelRecovery.swift rename to LookInside/XcodeViewHierarchy/XcodeViewHierarchyPixelRecovery.swift index 5cb0072a..32dc4aba 100644 --- a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyPixelRecovery.swift +++ b/LookInside/XcodeViewHierarchy/XcodeViewHierarchyPixelRecovery.swift @@ -1,4 +1,4 @@ -// LKXcodeViewHierarchyPixelRecovery.swift +// XcodeViewHierarchyPixelRecovery.swift // // Renders the layer trees recovered from a `.viewhierarchy` capture into the // per-node screenshots the inspector displays. @@ -35,7 +35,7 @@ import AppKit import Foundation import QuartzCore -struct LKXcodeViewHierarchyScreenshots { +struct XcodeViewHierarchyScreenshots { /// PNG data for each node rendered without its sublayers. let soloByObjectIdentifier: [String: Data] /// PNG data for each node rendered with its whole subtree. @@ -60,7 +60,7 @@ struct LKXcodeViewHierarchyScreenshots { let failedArchiveIdentifiers: [String] } -enum LKXcodeViewHierarchyPixelRecovery { +enum XcodeViewHierarchyPixelRecovery { /// Upper bound on the pixels of one rendered image. /// /// A capture holds thousands of layers; without a cap the import of a @@ -94,12 +94,12 @@ enum LKXcodeViewHierarchyPixelRecovery { /// stops and nothing is returned: a partial set of images would read as /// missing pixels rather than as an abandoned import. static func recovering( - from graph: LKXcodeViewHierarchyObjectGraph, + from graph: XcodeViewHierarchyObjectGraph, isCancelled: () -> Bool = { false } - ) -> LKXcodeViewHierarchyScreenshots { - let (trees, failedIdentifiers) = LKXcodeViewHierarchyLayerArchive.decodingLayerTrees(in: graph) - let alignment = LKXcodeViewHierarchyLayerAlignment.aligning(trees: trees, graph: graph) - let topology = LKXcodeViewHierarchyLayerTopology(graph: graph) + ) -> XcodeViewHierarchyScreenshots { + let (trees, failedIdentifiers) = XcodeViewHierarchyLayerArchive.decodingLayerTrees(in: graph) + let alignment = XcodeViewHierarchyLayerAlignment.aligning(trees: trees, graph: graph) + let topology = XcodeViewHierarchyLayerTopology(graph: graph) for tree in trees where tree.isGeometryFlipped { // A y-down capture: the root carries the axis and the subtree @@ -119,7 +119,7 @@ enum LKXcodeViewHierarchyPixelRecovery { for (objectIdentifier, layer) in alignment { if isCancelled() { - return LKXcodeViewHierarchyScreenshots( + return XcodeViewHierarchyScreenshots( soloByObjectIdentifier: [:], groupByObjectIdentifier: [:], failedArchiveIdentifiers: failedIdentifiers ) } @@ -165,7 +165,7 @@ enum LKXcodeViewHierarchyPixelRecovery { } } - return LKXcodeViewHierarchyScreenshots( + return XcodeViewHierarchyScreenshots( soloByObjectIdentifier: soloByObjectIdentifier, groupByObjectIdentifier: groupByObjectIdentifier, groupExcludingHostedViewsByObjectIdentifier: groupExcludingHostedViewsByObjectIdentifier, diff --git a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyValue.swift b/LookInside/XcodeViewHierarchy/XcodeViewHierarchyValue.swift similarity index 84% rename from LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyValue.swift rename to LookInside/XcodeViewHierarchy/XcodeViewHierarchyValue.swift index 66c60a89..520ec659 100644 --- a/LookInside/XcodeViewHierarchy/LKXcodeViewHierarchyValue.swift +++ b/LookInside/XcodeViewHierarchy/XcodeViewHierarchyValue.swift @@ -1,4 +1,4 @@ -// LKXcodeViewHierarchyValue.swift +// XcodeViewHierarchyValue.swift // // The value model of an Xcode `.viewhierarchy` capture, and the decoder that // turns a JSON property description into it. @@ -42,12 +42,12 @@ import Foundation /// A reference to another object in the capture, as carried by properties like /// a constraint's `firstItem` or a layer's `delegate`. -struct LKXcodeViewHierarchyObjectReference: Equatable { +struct XcodeViewHierarchyObjectReference: Equatable { let className: String let objectIdentifier: String } -struct LKXcodeViewHierarchyImageMetadata: Equatable { +struct XcodeViewHierarchyImageMetadata: Equatable { let width: Double let height: Double let imageName: String? @@ -59,21 +59,21 @@ struct LKXcodeViewHierarchyImageMetadata: Equatable { let baselineOffsetFromBottom: Double? } -struct LKXcodeViewHierarchyImage: Equatable { +struct XcodeViewHierarchyImage: Equatable { /// Encoded image bytes; PNG unless a more specific type identifier says otherwise. let encodedData: Data let typeIdentifier: String - let metadata: LKXcodeViewHierarchyImageMetadata? + let metadata: XcodeViewHierarchyImageMetadata? } -struct LKXcodeViewHierarchyColor: Equatable { +struct XcodeViewHierarchyColor: Equatable { let colorSpaceName: String let components: [Double] let colorName: String? let catalogName: String? } -struct LKXcodeViewHierarchyFont: Equatable { +struct XcodeViewHierarchyFont: Equatable { let fontName: String let familyName: String let pointSize: Double @@ -87,25 +87,25 @@ struct LKXcodeViewHierarchyFont: Equatable { // MARK: - Value -indirect enum LKXcodeViewHierarchyValue: Equatable { +indirect enum XcodeViewHierarchyValue: Equatable { case boolean(Bool) case number(Double) case integer(Int64) case unsignedInteger(UInt64) case text(String) case binaryData(Data) - case image(LKXcodeViewHierarchyImage) - case color(LKXcodeViewHierarchyColor) - case font(LKXcodeViewHierarchyFont) - case objectReference(LKXcodeViewHierarchyObjectReference) - case list([LKXcodeViewHierarchyValue]) + case image(XcodeViewHierarchyImage) + case color(XcodeViewHierarchyColor) + case font(XcodeViewHierarchyFont) + case objectReference(XcodeViewHierarchyObjectReference) + case list([XcodeViewHierarchyValue]) /// A value the capture declared as schema-less ("custom"), kept as its JSON text. case custom(String) /// The property exists but carries no value (unfetched, unchanged, or explicitly nil). case absent } -extension LKXcodeViewHierarchyValue { +extension XcodeViewHierarchyValue { /// Convenience for the geometry the conversion layer cares about most. var doubleValue: Double? { switch self { @@ -154,7 +154,7 @@ extension LKXcodeViewHierarchyValue { /// Taken from Xcode's reader: only `retrieved` and `unchanged` are meaningful /// outcomes, and `unchanged` means "reuse what you already have" rather than /// "no value". Values outside the known set are treated as failures. -enum LKXcodeViewHierarchyFetchStatus: Int { +enum XcodeViewHierarchyFetchStatus: Int { case failed = 0 case noValue = 1 case retrieved = 4 @@ -168,7 +168,7 @@ enum LKXcodeViewHierarchyFetchStatus: Int { // MARK: - Decoder -enum LKXcodeViewHierarchyValueDecodingError: Error, CustomStringConvertible { +enum XcodeViewHierarchyValueDecodingError: Error, CustomStringConvertible { case specifierCountMismatch(format: String, valueCount: Int, specifierCount: Int) case multipleSpecifiersOnNonArray(format: String) case unsupportedSpecifier(String) @@ -191,7 +191,7 @@ enum LKXcodeViewHierarchyValueDecodingError: Error, CustomStringConvertible { } } -enum LKXcodeViewHierarchyValueDecoder { +enum XcodeViewHierarchyValueDecoder { static let customFormat = "custom" /// Splits a `propertyFormat` into its comma-separated specifiers. @@ -203,7 +203,7 @@ enum LKXcodeViewHierarchyValueDecoder { /// /// `jsonValue` is the raw `propertyValue`; `nil` (or `NSNull`) yields `.absent`, /// which is the common case — most descriptions in a capture carry no value. - static func decoding(jsonValue: Any?, format: String) throws -> LKXcodeViewHierarchyValue { + static func decoding(jsonValue: Any?, format: String) throws -> XcodeViewHierarchyValue { guard let jsonValue, !(jsonValue is NSNull) else { return .absent } if format == customFormat { @@ -215,10 +215,10 @@ enum LKXcodeViewHierarchyValueDecoder { if formatSpecifiers.count > 1 { guard let elements = jsonValue as? [Any] else { - throw LKXcodeViewHierarchyValueDecodingError.multipleSpecifiersOnNonArray(format: format) + throw XcodeViewHierarchyValueDecodingError.multipleSpecifiersOnNonArray(format: format) } guard elements.count == formatSpecifiers.count else { - throw LKXcodeViewHierarchyValueDecodingError.specifierCountMismatch( + throw XcodeViewHierarchyValueDecodingError.specifierCountMismatch( format: format, valueCount: elements.count, specifierCount: formatSpecifiers.count ) } @@ -244,53 +244,53 @@ enum LKXcodeViewHierarchyValueDecoder { // string was expected still yields a usable value. return .number(number.doubleValue) } - throw LKXcodeViewHierarchyValueDecodingError.malformedStructure(specifier: specifier) + throw XcodeViewHierarchyValueDecodingError.malformedStructure(specifier: specifier) } // MARK: Scalars - private static func decodingScalar(text: String, specifier: String) throws -> LKXcodeViewHierarchyValue { + private static func decodingScalar(text: String, specifier: String) throws -> XcodeViewHierarchyValue { switch specifier { case "b": guard let value = parsingSignedInteger(text, radix: 10) else { - throw LKXcodeViewHierarchyValueDecodingError.malformedScalar(specifier: specifier, text: text) + throw XcodeViewHierarchyValueDecodingError.malformedScalar(specifier: specifier, text: text) } return .boolean(value != 0) case "CGf", "f", "d": guard let value = parsingFloatingPoint(text) else { - throw LKXcodeViewHierarchyValueDecodingError.malformedScalar(specifier: specifier, text: text) + throw XcodeViewHierarchyValueDecodingError.malformedScalar(specifier: specifier, text: text) } return .number(value) case "integer", "i", "l", "ll": guard let value = parsingSignedInteger(text, radix: 10) else { - throw LKXcodeViewHierarchyValueDecodingError.malformedScalar(specifier: specifier, text: text) + throw XcodeViewHierarchyValueDecodingError.malformedScalar(specifier: specifier, text: text) } return .integer(value) case "ui": // The one unsigned specifier Xcode reads as decimal (`%u`). guard let value = parsingUnsignedInteger(text, radix: 10) else { - throw LKXcodeViewHierarchyValueDecodingError.malformedScalar(specifier: specifier, text: text) + throw XcodeViewHierarchyValueDecodingError.malformedScalar(specifier: specifier, text: text) } return .unsignedInteger(value) case "uinteger", "ul", "ull": guard let value = parsingUnsignedInteger(text, radix: 16) else { - throw LKXcodeViewHierarchyValueDecodingError.malformedScalar(specifier: specifier, text: text) + throw XcodeViewHierarchyValueDecodingError.malformedScalar(specifier: specifier, text: text) } return .unsignedInteger(value) case "public.plain-text", "attrStr": return .text(text) case "public.data": guard let data = Data(base64Encoded: text) else { - throw LKXcodeViewHierarchyValueDecodingError.malformedScalar(specifier: specifier, text: text) + throw XcodeViewHierarchyValueDecodingError.malformedScalar(specifier: specifier, text: text) } return .binaryData(data) case "public.png", "public.tiff", "public.jpeg": guard let data = Data(base64Encoded: text) else { - throw LKXcodeViewHierarchyValueDecodingError.malformedScalar(specifier: specifier, text: text) + throw XcodeViewHierarchyValueDecodingError.malformedScalar(specifier: specifier, text: text) } - return .image(LKXcodeViewHierarchyImage(encodedData: data, typeIdentifier: specifier, metadata: nil)) + return .image(XcodeViewHierarchyImage(encodedData: data, typeIdentifier: specifier, metadata: nil)) default: - throw LKXcodeViewHierarchyValueDecodingError.unsupportedSpecifier(specifier) + throw XcodeViewHierarchyValueDecodingError.unsupportedSpecifier(specifier) } } @@ -340,22 +340,22 @@ enum LKXcodeViewHierarchyValueDecoder { private static func decodingStructure( _ structure: [String: Any], specifier: String - ) throws -> LKXcodeViewHierarchyValue { + ) throws -> XcodeViewHierarchyValue { switch specifier { case "objectInfo": guard let className = structure["className"] as? String, let memoryAddress = structure["memoryAddress"] as? String - else { throw LKXcodeViewHierarchyValueDecodingError.malformedStructure(specifier: specifier) } + else { throw XcodeViewHierarchyValueDecodingError.malformedStructure(specifier: specifier) } return .objectReference( - LKXcodeViewHierarchyObjectReference(className: className, objectIdentifier: memoryAddress) + XcodeViewHierarchyObjectReference(className: className, objectIdentifier: memoryAddress) ) case "image": guard let encodedText = structure["imageData"] as? String, let encodedData = Data(base64Encoded: encodedText) - else { throw LKXcodeViewHierarchyValueDecodingError.malformedStructure(specifier: specifier) } + else { throw XcodeViewHierarchyValueDecodingError.malformedStructure(specifier: specifier) } return .image( - LKXcodeViewHierarchyImage( + XcodeViewHierarchyImage( encodedData: encodedData, typeIdentifier: "public.png", metadata: decodingImageMetadata(structure["metadata"] as? [String: Any]) @@ -364,7 +364,7 @@ enum LKXcodeViewHierarchyValueDecoder { case "color": guard let colorSpaceName = structure["colorSpaceName"] as? String else { - throw LKXcodeViewHierarchyValueDecodingError.malformedStructure(specifier: specifier) + throw XcodeViewHierarchyValueDecodingError.malformedStructure(specifier: specifier) } let componentsFormat = structure["componentValuesFormat"] as? String ?? "" let decodedComponents = try decoding( @@ -373,7 +373,7 @@ enum LKXcodeViewHierarchyValueDecoder { let componentCount = specifiers(inFormat: componentsFormat).count let components = decodedComponents.numericComponents(expectedCount: componentCount) ?? [] return .color( - LKXcodeViewHierarchyColor( + XcodeViewHierarchyColor( colorSpaceName: colorSpaceName, components: components, colorName: structure["colorName"] as? String, @@ -384,14 +384,14 @@ enum LKXcodeViewHierarchyValueDecoder { case "font": guard let fontName = structure["fontName"] as? String, let familyName = structure["familyName"] as? String - else { throw LKXcodeViewHierarchyValueDecodingError.malformedStructure(specifier: specifier) } + else { throw XcodeViewHierarchyValueDecodingError.malformedStructure(specifier: specifier) } func metric(_ key: String) -> Double { guard let text = structure[key] as? String else { return 0 } return parsingFloatingPoint(text) ?? 0 } let lineHeight = (structure["lineHeight"] as? String).flatMap(parsingFloatingPoint) return .font( - LKXcodeViewHierarchyFont( + XcodeViewHierarchyFont( fontName: fontName, familyName: familyName, pointSize: metric("pointSize"), @@ -411,9 +411,9 @@ enum LKXcodeViewHierarchyValueDecoder { } } - private static func decodingImageMetadata(_ metadata: [String: Any]?) -> LKXcodeViewHierarchyImageMetadata? { + private static func decodingImageMetadata(_ metadata: [String: Any]?) -> XcodeViewHierarchyImageMetadata? { guard let metadata else { return nil } - return LKXcodeViewHierarchyImageMetadata( + return XcodeViewHierarchyImageMetadata( width: (metadata["width"] as? NSNumber)?.doubleValue ?? 0, height: (metadata["height"] as? NSNumber)?.doubleValue ?? 0, imageName: metadata["imageName"] as? String, diff --git a/Scripts/test-dashboard.sh b/Scripts/test-dashboard.sh index 87a2e806..69c02246 100755 --- a/Scripts/test-dashboard.sh +++ b/Scripts/test-dashboard.sh @@ -39,11 +39,11 @@ swiftc -parse-as-library \ -D SHOULD_COMPILE_LOOKIN_SERVER -D LOOKIN_CORE_STANDALONE \ -Xcc -I"$LOOKIN_CORE_DIR" -Xcc -I"$LOOKIN_CORE_DIR/include" \ -Xcc -I"$LOOKIN_SERVER_BASE_DIR" \ - "$SOURCE_DIR/LKDashboardModification.swift" \ - "$SOURCE_DIR/LKEnumListRegistry.swift" \ - "$SOURCE_DIR/AttributeView/JSON/LKJSONAttributeItem.swift" \ + "$SOURCE_DIR/DashboardModification.swift" \ + "$SOURCE_DIR/EnumListRegistry.swift" \ + "$SOURCE_DIR/AttributeView/JSON/JSONAttributeItem.swift" \ $(find "$LOOKIN_CORE_IMPL_DIR" -name '*.swift' | sort) \ - "$TEST_DIR/LKDashboardTests.swift" \ + "$TEST_DIR/DashboardTests.swift" \ "$TMPDIR"/lookin-core/*.o \ -framework AppKit -framework QuartzCore \ -o "$TMPDIR/dashboard-test" diff --git a/Scripts/test-gesture-models.sh b/Scripts/test-gesture-models.sh index ba5ceb0d..7fb4c9a1 100755 --- a/Scripts/test-gesture-models.sh +++ b/Scripts/test-gesture-models.sh @@ -7,5 +7,5 @@ trap 'rm -rf "$GESTURE_TEST_DIR"' EXIT swiftc -parse-as-library -import-objc-header "$ROOT/Sources/LookinCore/include/LookinHitTargetSize.h" \ "$ROOT/LookInside/GestureDebug/LKGestureCaptureModels.swift" \ "$ROOT/LookInside/GestureDebug/LKSuggestions.swift" \ - "$ROOT/Tests/GestureDebug/LKGestureCaptureModelsTests.swift" -o "$GESTURE_TEST_DIR/gesture-models" + "$ROOT/Tests/GestureDebug/GestureCaptureModelsTests.swift" -o "$GESTURE_TEST_DIR/gesture-models" "$GESTURE_TEST_DIR/gesture-models" diff --git a/Scripts/test-launch-toolbar-read.sh b/Scripts/test-launch-toolbar-read.sh index 60645549..de973b40 100755 --- a/Scripts/test-launch-toolbar-read.sh +++ b/Scripts/test-launch-toolbar-read.sh @@ -68,10 +68,10 @@ swiftc -parse-as-library \ -D SHOULD_COMPILE_LOOKIN_SERVER -D LOOKIN_CORE_STANDALONE \ -Xcc -I"$LOOKIN_CORE_DIR" -Xcc -I"$LOOKIN_CORE_DIR/include" \ -Xcc -I"$LOOKIN_SERVER_BASE_DIR" \ - "$SOURCE_DIR/Read/LookinArchiveCoding.swift" \ - "$SOURCE_DIR/Read/LKReadScreenshotLookup.swift" \ - "$SOURCE_DIR/Toolbar/LKToolbarRules.swift" \ - "$SOURCE_DIR/Launch/LKLaunchRules.swift" \ + "$SOURCE_DIR/Read/ArchiveCoding.swift" \ + "$SOURCE_DIR/Read/ReadScreenshotLookup.swift" \ + "$SOURCE_DIR/Toolbar/ToolbarRules.swift" \ + "$SOURCE_DIR/Launch/LaunchRules.swift" \ $(find "$LOOKIN_CORE_IMPL_DIR" -name '*.swift' | sort) \ "$TEST_DIR/LaunchToolbarReadTests.swift" \ "$WORK"/lookin-core/*.o \ diff --git a/Scripts/test-mcp-bridge.sh b/Scripts/test-mcp-bridge.sh index 619a3fd3..d77afb02 100755 --- a/Scripts/test-mcp-bridge.sh +++ b/Scripts/test-mcp-bridge.sh @@ -15,14 +15,14 @@ TMPDIR="${TMPDIR:-/tmp}/lookinside-mcp-bridge-tests.$$" mkdir -p "$TMPDIR" trap 'rm -rf "$TMPDIR"' EXIT -LISTEN_SOCKET="$ROOT/LookInside/MCPBridge/LKMCPBridgeListenSocket.swift" -LISTEN_SOCKET_TEST="$ROOT/Tests/MCPBridge/LKMCPBridgeListenSocketTests.swift" +LISTEN_SOCKET="$ROOT/LookInside/MCPBridge/MCPBridgeListenSocket.swift" +LISTEN_SOCKET_TEST="$ROOT/Tests/MCPBridge/MCPBridgeListenSocketTests.swift" swiftc -parse-as-library "$LISTEN_SOCKET" "$LISTEN_SOCKET_TEST" -o "$TMPDIR/listen-socket-test" "$TMPDIR/listen-socket-test" -SEARCH_QUERY="$ROOT/LookInside/MCPBridge/LKMCPBridgeSearchQuery.swift" -SEARCH_QUERY_TEST="$ROOT/Tests/MCPBridge/LKMCPBridgeSearchQueryTests.swift" +SEARCH_QUERY="$ROOT/LookInside/MCPBridge/MCPBridgeSearchQuery.swift" +SEARCH_QUERY_TEST="$ROOT/Tests/MCPBridge/MCPBridgeSearchQueryTests.swift" swiftc -parse-as-library "$SEARCH_QUERY" "$SEARCH_QUERY_TEST" -o "$TMPDIR/search-query-test" "$TMPDIR/search-query-test" @@ -30,8 +30,8 @@ swiftc -parse-as-library "$SEARCH_QUERY" "$SEARCH_QUERY_TEST" -o "$TMPDIR/search # The identifier list needs LKMCPBridgeFrame.swift alongside it for # LKMCPBridgeJSONValue; that file is Foundation-only, so it compiles here. FRAME="$ROOT/LookInside/MCPBridge/LKMCPBridgeFrame.swift" -OBJECT_IDENTIFIER_LIST="$ROOT/LookInside/MCPBridge/LKMCPBridgeObjectIdentifierList.swift" -OBJECT_IDENTIFIER_LIST_TEST="$ROOT/Tests/MCPBridge/LKMCPBridgeObjectIdentifierListTests.swift" +OBJECT_IDENTIFIER_LIST="$ROOT/LookInside/MCPBridge/MCPBridgeObjectIdentifierList.swift" +OBJECT_IDENTIFIER_LIST_TEST="$ROOT/Tests/MCPBridge/MCPBridgeObjectIdentifierListTests.swift" swiftc -parse-as-library "$FRAME" "$OBJECT_IDENTIFIER_LIST" "$OBJECT_IDENTIFIER_LIST_TEST" -o "$TMPDIR/object-identifier-list-test" "$TMPDIR/object-identifier-list-test" diff --git a/Scripts/test-security-gates.sh b/Scripts/test-security-gates.sh index 00ca31b6..cb6c1bc9 100755 --- a/Scripts/test-security-gates.sh +++ b/Scripts/test-security-gates.sh @@ -6,8 +6,8 @@ TMPDIR="${TMPDIR:-/tmp}/lookinside-security-tests.$$" mkdir -p "$TMPDIR" trap 'rm -rf "$TMPDIR"' EXIT -INJECTION_START_GATE="$ROOT/LookInside/Injection/LKInjectionStartGate.swift" -INJECTION_START_GATE_TEST="$ROOT/Tests/Security/LKInjectionStartGateTests.swift" +INJECTION_START_GATE="$ROOT/LookInside/Injection/InjectionStartGate.swift" +INJECTION_START_GATE_TEST="$ROOT/Tests/Security/InjectionStartGateTests.swift" swiftc -parse-as-library "$INJECTION_START_GATE" "$INJECTION_START_GATE_TEST" -o "$TMPDIR/injection-start-gate-test" "$TMPDIR/injection-start-gate-test" diff --git a/Scripts/test-xcode-viewhierarchy.sh b/Scripts/test-xcode-viewhierarchy.sh index 48713c1d..57f057e9 100755 --- a/Scripts/test-xcode-viewhierarchy.sh +++ b/Scripts/test-xcode-viewhierarchy.sh @@ -20,35 +20,35 @@ TEST_DIR="$ROOT/Tests/XcodeViewHierarchy" # Gzip inflation: response entries are gzip members whose header length varies, # and whose payload exceeds the inflater's buffer. swiftc -parse-as-library \ - "$SOURCE_DIR/LKXcodeViewHierarchyGzip.swift" \ - "$TEST_DIR/LKXcodeViewHierarchyGzipTests.swift" \ + "$SOURCE_DIR/XcodeViewHierarchyGzip.swift" \ + "$TEST_DIR/XcodeViewHierarchyGzipTests.swift" \ -o "$TMPDIR/gzip-test" "$TMPDIR/gzip-test" # Property value decoding: the format-specifier scheme, including the # hexadecimal floats and the per-specifier integer radix. swiftc -parse-as-library \ - "$SOURCE_DIR/LKXcodeViewHierarchyValue.swift" \ - "$TEST_DIR/LKXcodeViewHierarchyValueTests.swift" \ + "$SOURCE_DIR/XcodeViewHierarchyValue.swift" \ + "$TEST_DIR/XcodeViewHierarchyValueTests.swift" \ -o "$TMPDIR/value-test" "$TMPDIR/value-test" # Object graph assembly: merge rules across responses. swiftc -parse-as-library \ - "$SOURCE_DIR/LKXcodeViewHierarchyValue.swift" \ - "$SOURCE_DIR/LKXcodeViewHierarchyObjectGraph.swift" \ - "$TEST_DIR/LKXcodeViewHierarchyObjectGraphTests.swift" \ + "$SOURCE_DIR/XcodeViewHierarchyValue.swift" \ + "$SOURCE_DIR/XcodeViewHierarchyObjectGraph.swift" \ + "$TEST_DIR/XcodeViewHierarchyObjectGraphTests.swift" \ -o "$TMPDIR/object-graph-test" "$TMPDIR/object-graph-test" # Pixel recovery: the two-part orientation correction for y-down captures. swiftc -parse-as-library \ - "$SOURCE_DIR/LKXcodeViewHierarchyValue.swift" \ - "$SOURCE_DIR/LKXcodeViewHierarchyObjectGraph.swift" \ - "$SOURCE_DIR/LKXcodeViewHierarchyLayerArchive.swift" \ - "$SOURCE_DIR/LKXcodeViewHierarchyLayerTopology.swift" \ - "$SOURCE_DIR/LKXcodeViewHierarchyPixelRecovery.swift" \ - "$TEST_DIR/LKXcodeViewHierarchyPixelRecoveryTests.swift" \ + "$SOURCE_DIR/XcodeViewHierarchyValue.swift" \ + "$SOURCE_DIR/XcodeViewHierarchyObjectGraph.swift" \ + "$SOURCE_DIR/XcodeViewHierarchyLayerArchive.swift" \ + "$SOURCE_DIR/XcodeViewHierarchyLayerTopology.swift" \ + "$SOURCE_DIR/XcodeViewHierarchyPixelRecovery.swift" \ + "$TEST_DIR/XcodeViewHierarchyPixelRecoveryTests.swift" \ -o "$TMPDIR/pixel-recovery-test" "$TMPDIR/pixel-recovery-test" @@ -82,18 +82,18 @@ swiftc -parse-as-library \ -D SHOULD_COMPILE_LOOKIN_SERVER -D LOOKIN_CORE_STANDALONE \ -Xcc -I"$LOOKIN_CORE_DIR" -Xcc -I"$LOOKIN_CORE_DIR/include" \ -Xcc -I"$LOOKIN_SERVER_BASE_DIR" \ - "$SOURCE_DIR/LKXcodeViewHierarchyGzip.swift" \ - "$SOURCE_DIR/LKXcodeViewHierarchyValue.swift" \ - "$SOURCE_DIR/LKXcodeViewHierarchyObjectGraph.swift" \ - "$SOURCE_DIR/LKXcodeViewHierarchyBundleReader.swift" \ - "$SOURCE_DIR/LKXcodeViewHierarchyLayerArchive.swift" \ - "$SOURCE_DIR/LKXcodeViewHierarchyLayerTopology.swift" \ - "$SOURCE_DIR/LKXcodeViewHierarchyPixelRecovery.swift" \ - "$SOURCE_DIR/LKXcodeViewHierarchyAttributeCatalog.swift" \ - "$SOURCE_DIR/LKXcodeViewHierarchyAttributes.swift" \ - "$SOURCE_DIR/LKXcodeViewHierarchyConverter.swift" \ + "$SOURCE_DIR/XcodeViewHierarchyGzip.swift" \ + "$SOURCE_DIR/XcodeViewHierarchyValue.swift" \ + "$SOURCE_DIR/XcodeViewHierarchyObjectGraph.swift" \ + "$SOURCE_DIR/XcodeViewHierarchyBundleReader.swift" \ + "$SOURCE_DIR/XcodeViewHierarchyLayerArchive.swift" \ + "$SOURCE_DIR/XcodeViewHierarchyLayerTopology.swift" \ + "$SOURCE_DIR/XcodeViewHierarchyPixelRecovery.swift" \ + "$SOURCE_DIR/XcodeViewHierarchyAttributeCatalog.swift" \ + "$SOURCE_DIR/XcodeViewHierarchyAttributes.swift" \ + "$SOURCE_DIR/XcodeViewHierarchyConverter.swift" \ $(find "$LOOKIN_CORE_IMPL_DIR" -name '*.swift' | sort) \ - "$TEST_DIR/LKXcodeViewHierarchyConverterTests.swift" \ + "$TEST_DIR/XcodeViewHierarchyConverterTests.swift" \ "$TMPDIR"/lookin-core/*.o \ -framework AppKit -framework QuartzCore \ -o "$TMPDIR/converter-test" diff --git a/Sources/LookinCoreImpl/DisplayItem.swift b/Sources/LookinCoreImpl/DisplayItem.swift index e06417bf..e6e5fc35 100644 --- a/Sources/LookinCoreImpl/DisplayItem.swift +++ b/Sources/LookinCoreImpl/DisplayItem.swift @@ -163,16 +163,16 @@ public var screenshotEncodeType: LookinDisplayItemImageEncodeType = .none // `previewLayer` and `previewNode` keep their Objective-C accessors // (same selectors, same weak storage). Only the host app has the - // LKDisplayItemNode class, so only its build types previewNode; + // DisplayItemNode class, so only its build types previewNode; // SwiftPM builds and the host's standalone test builds // (LOOKIN_CORE_STANDALONE) store an untyped object. // LookinPreviewItemLayer no longer exists anywhere. #if SWIFT_PACKAGE || LOOKIN_CORE_STANDALONE @objc private weak var previewNode: AnyObject? #else - // Internal: LKDisplayItemNode is the host app's own class. + // Internal: DisplayItemNode is the host app's own class. @objc(previewNode) - weak var previewNode: LKDisplayItemNode? + weak var previewNode: DisplayItemNode? #endif @objc private weak var previewLayer: AnyObject? @objc(previewZIndex) diff --git a/Tests/Dashboard/LKDashboardTests.swift b/Tests/Dashboard/DashboardTests.swift similarity index 75% rename from Tests/Dashboard/LKDashboardTests.swift rename to Tests/Dashboard/DashboardTests.swift index c592508d..d6e0a8d1 100644 --- a/Tests/Dashboard/LKDashboardTests.swift +++ b/Tests/Dashboard/DashboardTests.swift @@ -6,11 +6,11 @@ import Foundation /// /// The modification payloads are compared, as keyed archives (the bytes /// that go over the wire), with payloads built the way the Objective-C -/// `LKDashboardViewController` built them before the Swift rewrite. The +/// `DashboardViewController` built them before the Swift rewrite. The /// enum lists are compared with a dump of the Objective-C -/// `LKEnumListRegistry` (`Fixtures/enum-list-registry.json`). +/// `EnumListRegistry` (`Fixtures/enum-list-registry.json`). @main -struct LKDashboardTests { +struct DashboardTests { static func main() { let fixturesDirectory = URL(fileURLWithPath: CommandLine.arguments.dropFirst().first ?? "Fixtures", isDirectory: true) @@ -108,7 +108,7 @@ struct LKDashboardTests { attribute.targetDisplayItem = item let newValue = sampleValue(for: attribute.attrType) - guard let payload = LKDashboardModification.inbuilt(attribute: attribute, newValue: newValue, clientReadableVersion: clientVersion) else { + guard let payload = DashboardModification.inbuilt(attribute: attribute, newValue: newValue, clientReadableVersion: clientVersion) else { fail("\(attrID) has a setter but no payload") } let expected = objectiveCInbuiltPayload(attribute: attribute, newValue: newValue) @@ -129,7 +129,7 @@ struct LKDashboardTests { attribute.identifier = LookinAttr_Class_Class_Class attribute.attrType = .customObj attribute.targetDisplayItem = makeItem() - expect(LKDashboardModification.inbuilt(attribute: attribute, newValue: nil, clientReadableVersion: clientVersion) == nil, + expect(DashboardModification.inbuilt(attribute: attribute, newValue: nil, clientReadableVersion: clientVersion) == nil, "an attribute without a setter must not be sent") } @@ -140,7 +140,7 @@ struct LKDashboardTests { attribute.customSetterID = "setter-7" let newValue = NSNumber(value: 3.25) - guard let payload = LKDashboardModification.custom(attribute: attribute, newValue: newValue) else { + guard let payload = DashboardModification.custom(attribute: attribute, newValue: newValue) else { fail("a custom attribute with a setter has no payload") } // -[LKDashboardViewController modifyCustomAttribute:newValue:] @@ -155,10 +155,10 @@ struct LKDashboardTests { let attribute = InspectedAttribute() attribute.identifier = LookinAttr_UserCustom attribute.attrType = .nsString - expect(LKDashboardModification.custom(attribute: attribute, newValue: "x") == nil, + expect(DashboardModification.custom(attribute: attribute, newValue: "x") == nil, "a read-only custom attribute must not be sent") attribute.customSetterID = "" - expect(LKDashboardModification.custom(attribute: attribute, newValue: "x") == nil, + expect(DashboardModification.custom(attribute: attribute, newValue: "x") == nil, "an empty setter id must not be sent") } @@ -166,20 +166,20 @@ struct LKDashboardTests { private static func testEditedGeometryValues() { let rect = NSRect(x: 1, y: 2, width: 3, height: 4) - expect(LKDashboardModification.rect(rect, replacingField: 0, with: 9) == NSRect(x: 9, y: 2, width: 3, height: 4), "rect x") - expect(LKDashboardModification.rect(rect, replacingField: 1, with: 9) == NSRect(x: 1, y: 9, width: 3, height: 4), "rect y") - expect(LKDashboardModification.rect(rect, replacingField: 2, with: 9) == NSRect(x: 1, y: 2, width: 9, height: 4), "rect width") - expect(LKDashboardModification.rect(rect, replacingField: 3, with: 9) == NSRect(x: 1, y: 2, width: 3, height: 9), "rect height") - expect(LKDashboardModification.rect(rect, replacingField: 4, with: 9) == nil, "rect field out of range") + expect(DashboardModification.rect(rect, replacingField: 0, with: 9) == NSRect(x: 9, y: 2, width: 3, height: 4), "rect x") + expect(DashboardModification.rect(rect, replacingField: 1, with: 9) == NSRect(x: 1, y: 9, width: 3, height: 4), "rect y") + expect(DashboardModification.rect(rect, replacingField: 2, with: 9) == NSRect(x: 1, y: 2, width: 9, height: 4), "rect width") + expect(DashboardModification.rect(rect, replacingField: 3, with: 9) == NSRect(x: 1, y: 2, width: 3, height: 9), "rect height") + expect(DashboardModification.rect(rect, replacingField: 4, with: 9) == nil, "rect field out of range") let insets = NSEdgeInsets(top: 1, left: 2, bottom: 3, right: 4) - let edited = LKDashboardModification.insets(insets, replacingField: 2, with: 7) + let edited = DashboardModification.insets(insets, replacingField: 2, with: 7) expect(edited.map { $0.top == 1 && $0.left == 2 && $0.bottom == 7 && $0.right == 4 } == true, "insets bottom") - expect(edited.map { LKDashboardModification.insetsDiffer(insets, $0) } == true, "edited insets differ") - expect(!LKDashboardModification.insetsDiffer(insets, insets), "equal insets do not differ") + expect(edited.map { DashboardModification.insetsDiffer(insets, $0) } == true, "edited insets differ") + expect(!DashboardModification.insetsDiffer(insets, insets), "equal insets do not differ") - expect(LKDashboardModification.point(NSPoint(x: 1, y: 2), replacingField: 1, with: 5) == NSPoint(x: 1, y: 5), "point y") - expect(LKDashboardModification.size(NSSize(width: 1, height: 2), replacingField: 0, with: 5) == NSSize(width: 5, height: 2), "size width") + expect(DashboardModification.point(NSPoint(x: 1, y: 2), replacingField: 1, with: 5) == NSPoint(x: 1, y: 5), "point y") + expect(DashboardModification.size(NSSize(width: 1, height: 2), replacingField: 0, with: 5) == NSSize(width: 5, height: 2), "size width") // The value sent for a rect edit is the NSValue the Objective-C view // built with +valueWithRect:. @@ -190,44 +190,44 @@ struct LKDashboardTests { attribute.identifier = LookinAttr_Layout_Frame_Frame attribute.attrType = .cgRect attribute.targetDisplayItem = item - let newRect = LKDashboardModification.rect(rect, replacingField: 2, with: 30)! - let payload = LKDashboardModification.inbuilt(attribute: attribute, newValue: NSValue(rect: newRect), clientReadableVersion: clientVersion)! + let newRect = DashboardModification.rect(rect, replacingField: 2, with: 30)! + let payload = DashboardModification.inbuilt(attribute: attribute, newValue: NSValue(rect: newRect), clientReadableVersion: clientVersion)! let expected = objectiveCInbuiltPayload(attribute: attribute, newValue: NSValue(rect: NSRect(x: 1, y: 2, width: 30, height: 4))) expect(payload.targetOid != 0, "frame edit has no target") expect(archive(payload) == archive(expected), "frame edit payload differs from the Objective-C one") } - expect(LKDashboardModification.boolValue(isOn: true) == NSNumber(value: true), "switch on") - expect(LKDashboardModification.boolValue(isOn: false) == NSNumber(value: false), "switch off") + expect(DashboardModification.boolValue(isOn: true) == NSNumber(value: true), "switch on") + expect(DashboardModification.boolValue(isOn: false) == NSNumber(value: false), "switch off") } private static func testNumberValueClampsOpacity() { let opacity = InspectedAttribute() opacity.identifier = LookinAttr_ViewLayer_Visibility_Opacity opacity.value = NSNumber(value: 0.5) - expect(LKDashboardModification.numberValue(NSNumber(value: 1.7), for: opacity) == NSNumber(value: 1.0), "opacity above 1") - expect(LKDashboardModification.numberValue(NSNumber(value: -0.2), for: opacity) == NSNumber(value: 0.0), "opacity below 0") - expect(LKDashboardModification.numberValue(NSNumber(value: 0.5), for: opacity) == nil, "unchanged opacity") + expect(DashboardModification.numberValue(NSNumber(value: 1.7), for: opacity) == NSNumber(value: 1.0), "opacity above 1") + expect(DashboardModification.numberValue(NSNumber(value: -0.2), for: opacity) == NSNumber(value: 0.0), "opacity below 0") + expect(DashboardModification.numberValue(NSNumber(value: 0.5), for: opacity) == nil, "unchanged opacity") let shadowOpacity = InspectedAttribute() shadowOpacity.identifier = LookinAttr_ViewLayer_Shadow_Opacity shadowOpacity.value = NSNumber(value: 1.0) - expect(LKDashboardModification.numberValue(NSNumber(value: 4), for: shadowOpacity) == nil, "shadow opacity clamps to the unchanged 1") + expect(DashboardModification.numberValue(NSNumber(value: 4), for: shadowOpacity) == nil, "shadow opacity clamps to the unchanged 1") let radius = InspectedAttribute() radius.identifier = LookinAttr_ViewLayer_Corner_Radius radius.value = NSNumber(value: 4) - expect(LKDashboardModification.numberValue(NSNumber(value: 12), for: radius) == NSNumber(value: 12), "radius is not clamped") - expect(LKDashboardModification.numberValue(NSNumber(value: 4), for: radius) == nil, "unchanged radius") + expect(DashboardModification.numberValue(NSNumber(value: 12), for: radius) == NSNumber(value: 12), "radius is not clamped") + expect(DashboardModification.numberValue(NSNumber(value: 4), for: radius) == nil, "unchanged radius") } private static func testRectEditRevertDetection() { let old = NSRect(x: 0, y: 0, width: 10, height: 10) let expected = NSRect(x: 0, y: 0, width: 20, height: 10) - expect(LKDashboardModification.rectEditWasReverted(old: old, expected: expected, current: NSRect(x: 0.05, y: 0, width: 10, height: 10)), + expect(DashboardModification.rectEditWasReverted(old: old, expected: expected, current: NSRect(x: 0.05, y: 0, width: 10, height: 10)), "the app set the frame back") - expect(!LKDashboardModification.rectEditWasReverted(old: old, expected: expected, current: expected), "the edit held") - expect(!LKDashboardModification.rectEditWasReverted(old: old, expected: old, current: old), "an edit to the same rect") + expect(!DashboardModification.rectEditWasReverted(old: old, expected: expected, current: expected), "the edit held") + expect(!DashboardModification.rectEditWasReverted(old: old, expected: old, current: old), "an edit to the same rect") } // MARK: - Constraints @@ -246,7 +246,7 @@ struct LKDashboardTests { let c = constraint(effective: true, type: .view, attribute: 7, constant: 3) let d = constraint(effective: true, type: .view, attribute: 3, constant: 4) let e = constraint(effective: true, type: .view, attribute: 3, constant: 5) - let sorted = LKDashboardConstraintOrder.sorted([a, b, c, d, e]).map(\.constant) + let sorted = DashboardConstraintOrder.sorted([a, b, c, d, e]).map(\.constant) expect(sorted == [4, 5, 3, 2, 1], "constraint order: \(sorted)") } @@ -259,7 +259,7 @@ struct LKDashboardTests { else { fail("cannot read \(url.path)") } - let registry = LKEnumListRegistry.shared + let registry = EnumListRegistry.shared expect(Set(registry.allEnumNames) == Set(fixture.keys), "enum list names differ: \(Set(registry.allEnumNames).symmetricDifference(fixture.keys).sorted())") for (name, expectedItems) in fixture { @@ -280,21 +280,21 @@ struct LKDashboardTests { private static func testJSONAttributeTree() { let json = #"[{"title":"a","desc":"1","details":[{"title":"a.1"},{"title":"a.2","details":[{"title":"a.2.x"}]}]},{"title":"b"},7]"# - guard let roots = LKJSONAttributeItem.rootItems(fromJSON: json) else { + guard let roots = JSONAttributeItem.rootItems(fromJSON: json) else { fail("valid JSON gave no items") } expect(roots.count == 2, "non-object entries are skipped") - var flat = LKJSONAttributeItem.flatItems(of: roots) + var flat = JSONAttributeItem.flatItems(of: roots) expect(flat.map { $0.titleText ?? "" } == ["a", "a.1", "a.2", "a.2.x", "b"], "flat order") expect(flat.map(\.indentation) == [0, 1, 1, 2, 0], "indentation") expect(flat[0].desc == "1" && flat[1].desc == nil, "descriptions") flat[2].expanded = false - flat = LKJSONAttributeItem.flatItems(of: roots) + flat = JSONAttributeItem.flatItems(of: roots) expect(flat.map { $0.titleText ?? "" } == ["a", "a.1", "a.2", "b"], "collapsed item hides its details") - expect(LKJSONAttributeItem.rootItems(fromJSON: nil) == nil, "nil JSON") - expect(LKJSONAttributeItem.rootItems(fromJSON: #"{"title":"a"}"#) == nil, "a JSON object is not a list") + expect(JSONAttributeItem.rootItems(fromJSON: nil) == nil, "nil JSON") + expect(JSONAttributeItem.rootItems(fromJSON: #"{"title":"a"}"#) == nil, "a JSON object is not a list") } // MARK: - Helpers diff --git a/Tests/GestureDebug/LKGestureCaptureModelsTests.swift b/Tests/GestureDebug/GestureCaptureModelsTests.swift similarity index 52% rename from Tests/GestureDebug/LKGestureCaptureModelsTests.swift rename to Tests/GestureDebug/GestureCaptureModelsTests.swift index 37c73feb..f8bdb22d 100644 --- a/Tests/GestureDebug/LKGestureCaptureModelsTests.swift +++ b/Tests/GestureDebug/GestureCaptureModelsTests.swift @@ -1,40 +1,40 @@ import Foundation @main -struct LKGestureCaptureModelsTests { +struct GestureCaptureModelsTests { static func main() throws { let legacy = Data(#"{"schemaVersion":1,"sessionID":"s","sequence":1,"snapshots":[],"records":[],"recordCount":0,"redactedCount":0,"droppedCount":0,"state":"capturing","message":"","pollDurationMS":0}"#.utf8) let decoder = JSONDecoder() - var batch = try decoder.decode(LKGestureCaptureBatch.self, from: legacy) + var batch = try decoder.decode(GestureCaptureBatch.self, from: legacy) precondition(batch.nativeRegions == nil, "Old Servers remain compatible") precondition(batch.interactions == nil) - batch.nativeRegions = [LKNativeInteractionRegion( + batch.nativeRegions = [NativeInteractionRegion( id: "0x1", source: "listSelection", viewClass: "SwiftUI.ListCollectionViewCell", viewAddress: "0x1", windowAddress: "0x2", - label: "List row 0:1", handlers: [LKNativeInteractionHandler(kind: "listSelection", name: "selectionBehavior.onSelect")], - geometry: LKGestureCaptureGeometry(x: 20, y: 40, width: 320, height: 44, source: "nativeViewBounds", coordinateSpace: "window"), + label: "List row 0:1", handlers: [NativeInteractionHandler(kind: "listSelection", name: "selectionBehavior.onSelect")], + geometry: GestureCaptureGeometry(x: 20, y: 40, width: 320, height: 44, source: "nativeViewBounds", coordinateSpace: "window"), isActive: false, geometryKind: "viewBounds" )] - let current = try decoder.decode(LKGestureCaptureBatch.self, from: JSONEncoder().encode(batch)) + let current = try decoder.decode(GestureCaptureBatch.self, from: JSONEncoder().encode(batch)) precondition(current.nativeRegions?.first?.handlers.first?.name == "selectionBehavior.onSelect") precondition(current.nativeRegions?.first?.geometry.width == 320) - let archive = LKGestureCaptureArchive(appName: "Fixture", bundleIdentifier: "fixture", sessionID: "s", snapshots: [], records: [], nativeRegions: current.nativeRegions) - let roundTrip = try decoder.decode(LKGestureCaptureArchive.self, from: JSONEncoder().encode(archive)) + let archive = GestureCaptureArchive(appName: "Fixture", bundleIdentifier: "fixture", sessionID: "s", snapshots: [], records: [], nativeRegions: current.nativeRegions) + let roundTrip = try decoder.decode(GestureCaptureArchive.self, from: JSONEncoder().encode(archive)) precondition(roundTrip.nativeRegions?.first?.id == "0x1", "Native-only captures can be exported") batch.nativeRegions = [] - let cleared = try decoder.decode(LKGestureCaptureBatch.self, from: JSONEncoder().encode(batch)) + let cleared = try decoder.decode(GestureCaptureBatch.self, from: JSONEncoder().encode(batch)) precondition(cleared.nativeRegions?.isEmpty == true) try testSuggestions() print("Gesture capture model compatibility and native archive tests passed") } static func testSuggestions() throws { - func target(_ width: Double, _ height: Double, id: String = "target", kind: String = "contentShapeBounds") -> LKInteractionTarget { - LKInteractionTarget(id: id, source: "swiftUI", name: "Test", targetAddress: "0x1", - geometry: LKGestureCaptureGeometry(x: 0, y: 0, width: width, height: height, + func target(_ width: Double, _ height: Double, id: String = "target", kind: String = "contentShapeBounds") -> InteractionTarget { + InteractionTarget(id: id, source: "swiftUI", name: "Test", targetAddress: "0x1", + geometry: GestureCaptureGeometry(x: 0, y: 0, width: width, height: height, source: kind, coordinateSpace: "window"), geometryKind: kind, shapeKind: "rectangle") } - for (platform, threshold) in [(LKSuggestionPlatform.iPhone, 44.0), (.mac, 28.0)] { + for (platform, threshold) in [(HitTargetSuggestionPlatform.iPhone, 44.0), (.mac, 28.0)] { for (width, height, warning) in [(threshold, threshold, false), (threshold - 0.1, threshold, true), (threshold.nextDown, threshold, false), (threshold, threshold.nextDown, false), (threshold - 0.0001, threshold, true), @@ -42,27 +42,27 @@ struct LKGestureCaptureModelsTests { (100, 100, false), (0, 20, false), (-1, 20, false), (Double.nan, 20, false), (20, Double.infinity, false)] { - precondition(LKHitTargetSuggestionRule.evaluate([target(width, height)], platform: platform).isEmpty != warning, + precondition(HitTargetSuggestionRule.evaluate([target(width, height)], platform: platform).isEmpty != warning, "\(platform) \(width) x \(height)") } } - precondition(LKHitTargetSuggestionRule.evaluate([target(40, 40)], platform: .iPhone).count == 1) - precondition(LKHitTargetSuggestionRule.evaluate([target(44, 43.99999999999994)], platform: .iPhone).isEmpty, + precondition(HitTargetSuggestionRule.evaluate([target(40, 40)], platform: .iPhone).count == 1) + precondition(HitTargetSuggestionRule.evaluate([target(44, 43.99999999999994)], platform: .iPhone).isEmpty, "Real fixture geometry after window-coordinate conversion must not warn at 44 pt") - precondition(LKHitTargetSuggestionRule.evaluate([target(40, 40)], platform: .mac).isEmpty) - precondition(LKHitTargetSuggestionRule.evaluate([target(20, 20)], platform: .unsupported).isEmpty) - precondition(LKHitTargetSuggestionRule.evaluate([target(20, 20), target(20, 20)], platform: .iPhone).count == 1) - precondition(LKHitTargetSuggestionRule.evaluate([target(20, 20, kind: "nativeViewBounds")], platform: .iPhone).first?.target.usesEstimatedBounds == true) - precondition(LKHitTargetSuggestionRule.evaluate([target(20, 20)], platform: .iPhone).first?.target.usesEstimatedBounds == false) - precondition(LKSuggestionPlatform.resolve(deviceType: 0, model: "iPhone17,3", deviceName: "Test", os: "iOS 18.5") == .iPhone) - precondition(LKSuggestionPlatform.resolve(deviceType: 0, model: "", deviceName: "iPhone 16 Pro", os: "iOS 18.5") == .iPhone) - precondition(LKSuggestionPlatform.resolve(deviceType: 4, model: "Mac16,12", deviceName: "Mac", os: "iOS") == .mac) - precondition(LKSuggestionPlatform.resolve(deviceType: 3, model: "", deviceName: "Test", os: "") == .mac) - precondition(LKSuggestionPlatform.resolve(deviceType: 0, model: "iPad16,1", deviceName: "iPad", os: "iOS") == .unsupported) - precondition(LKSuggestionPlatform.resolve(deviceType: 0, model: "", deviceName: "Test", os: "iOS") == .unsupported) + precondition(HitTargetSuggestionRule.evaluate([target(40, 40)], platform: .mac).isEmpty) + precondition(HitTargetSuggestionRule.evaluate([target(20, 20)], platform: .unsupported).isEmpty) + precondition(HitTargetSuggestionRule.evaluate([target(20, 20), target(20, 20)], platform: .iPhone).count == 1) + precondition(HitTargetSuggestionRule.evaluate([target(20, 20, kind: "nativeViewBounds")], platform: .iPhone).first?.target.usesEstimatedBounds == true) + precondition(HitTargetSuggestionRule.evaluate([target(20, 20)], platform: .iPhone).first?.target.usesEstimatedBounds == false) + precondition(HitTargetSuggestionPlatform.resolve(deviceType: 0, model: "iPhone17,3", deviceName: "Test", os: "iOS 18.5") == .iPhone) + precondition(HitTargetSuggestionPlatform.resolve(deviceType: 0, model: "", deviceName: "iPhone 16 Pro", os: "iOS 18.5") == .iPhone) + precondition(HitTargetSuggestionPlatform.resolve(deviceType: 4, model: "Mac16,12", deviceName: "Mac", os: "iOS") == .mac) + precondition(HitTargetSuggestionPlatform.resolve(deviceType: 3, model: "", deviceName: "Test", os: "") == .mac) + precondition(HitTargetSuggestionPlatform.resolve(deviceType: 0, model: "iPad16,1", deviceName: "iPad", os: "iOS") == .unsupported) + precondition(HitTargetSuggestionPlatform.resolve(deviceType: 0, model: "", deviceName: "Test", os: "iOS") == .unsupported) - let snapshot = LKInteractionSnapshot(targets: [target(24, 24)], swiftUIStatus: "available", nativeStatus: "available", truncated: false) - var report = LKSuggestionReport() + let snapshot = InteractionSnapshot(targets: [target(24, 24)], swiftUIStatus: "available", nativeStatus: "available", truncated: false) + var report = HitTargetSuggestionReport() report.replace(with: snapshot, platform: .iPhone, isCapturing: true) let id = report.warnings.first?.id for _ in 0 ..< 3 { @@ -82,9 +82,9 @@ struct LKGestureCaptureModelsTests { nextPage.truncated = true report.replace(with: nextPage, platform: .mac, isCapturing: true) precondition(report.coverageMessage.contains("unavailable") && report.coverageMessage.contains("partially")) - let archive = LKGestureCaptureArchive(appName: "Test", bundleIdentifier: "test", snapshots: [], records: [], + let archive = GestureCaptureArchive(appName: "Test", bundleIdentifier: "test", snapshots: [], records: [], interactions: snapshot, suggestionPlatform: .iPhone) - let decoded = try JSONDecoder().decode(LKGestureCaptureArchive.self, from: JSONEncoder().encode(archive)) + let decoded = try JSONDecoder().decode(GestureCaptureArchive.self, from: JSONEncoder().encode(archive)) precondition(decoded.interactions?.targets.first?.geometry.width == 24 && decoded.suggestionPlatform == .iPhone) print("Hit target rule boundaries, device selection, lifecycle and export tests passed") } diff --git a/Tests/MCPBridge/LKMCPBridgeListenSocketTests.swift b/Tests/MCPBridge/MCPBridgeListenSocketTests.swift similarity index 87% rename from Tests/MCPBridge/LKMCPBridgeListenSocketTests.swift rename to Tests/MCPBridge/MCPBridgeListenSocketTests.swift index 0433779f..1982cbcf 100644 --- a/Tests/MCPBridge/LKMCPBridgeListenSocketTests.swift +++ b/Tests/MCPBridge/MCPBridgeListenSocketTests.swift @@ -3,7 +3,7 @@ import Foundation /// Regression coverage for the MCPBridge listening socket. /// -/// The socket used to be created blocking. `LKMCPBridgeServer` drains +/// The socket used to be created blocking. `MCPBridgeServer` drains /// accepts in a `while true` loop that treats `EAGAIN` as "no more /// pending connections", so on a blocking descriptor the second /// `accept(2)` of each drain parked the server's serial state queue @@ -14,7 +14,7 @@ import Foundation /// fails (rather than hanging) if the descriptor ever goes back to /// blocking mode. @main -struct LKMCPBridgeListenSocketTests { +struct MCPBridgeListenSocketTests { static func main() { testDescriptorIsNonBlocking() testAcceptWithNoPendingConnectionsReturnsImmediately() @@ -31,13 +31,13 @@ struct LKMCPBridgeListenSocketTests { let socketPath = makeTemporarySocketPath() defer { unlink(socketPath) } - guard let descriptor = try? LKMCPBridgeListenSocket.makeListening(atPath: socketPath, backlog: 16) else { + guard let descriptor = try? MCPBridgeListenSocket.makeListening(atPath: socketPath, backlog: 16) else { fail("makeListening should succeed on a fresh path") } defer { Darwin.close(descriptor) } expect( - LKMCPBridgeListenSocket.isNonBlocking(descriptor: descriptor), + MCPBridgeListenSocket.isNonBlocking(descriptor: descriptor), "listening descriptor must be non-blocking so the accept drain loop can terminate" ) } @@ -46,7 +46,7 @@ struct LKMCPBridgeListenSocketTests { let socketPath = makeTemporarySocketPath() defer { unlink(socketPath) } - guard let descriptor = try? LKMCPBridgeListenSocket.makeListening(atPath: socketPath, backlog: 16) else { + guard let descriptor = try? MCPBridgeListenSocket.makeListening(atPath: socketPath, backlog: 16) else { fail("makeListening should succeed on a fresh path") } defer { Darwin.close(descriptor) } @@ -67,7 +67,7 @@ struct LKMCPBridgeListenSocketTests { let socketPath = makeTemporarySocketPath() defer { unlink(socketPath) } - guard let listenDescriptor = try? LKMCPBridgeListenSocket.makeListening(atPath: socketPath, backlog: 16) else { + guard let listenDescriptor = try? MCPBridgeListenSocket.makeListening(atPath: socketPath, backlog: 16) else { fail("makeListening should succeed on a fresh path") } defer { Darwin.close(listenDescriptor) } @@ -126,7 +126,7 @@ struct LKMCPBridgeListenSocketTests { /// /// On BSD-derived systems -- macOS included -- accept(2) inherits /// O_NONBLOCK from the listener, the opposite of Linux. Connection - /// writes are blocking by design (`LKMCPBridgeConnection.writeAll` + /// writes are blocking by design (`MCPBridgeConnection.writeAll` /// treats EAGAIN as fatal and closes), so an inherited flag turns /// any response larger than the socket send buffer into a dropped /// connection. Small frames still work, which is what makes this @@ -136,7 +136,7 @@ struct LKMCPBridgeListenSocketTests { let socketPath = makeTemporarySocketPath() defer { unlink(socketPath) } - guard let listenDescriptor = try? LKMCPBridgeListenSocket.makeListening(atPath: socketPath, backlog: 16) else { + guard let listenDescriptor = try? MCPBridgeListenSocket.makeListening(atPath: socketPath, backlog: 16) else { fail("makeListening should succeed on a fresh path") } defer { Darwin.close(listenDescriptor) } @@ -146,12 +146,12 @@ struct LKMCPBridgeListenSocketTests { } defer { Darwin.close(clientDescriptor) } - let accepted = LKMCPBridgeListenSocket.acceptConnection(listenDescriptor: listenDescriptor) + let accepted = MCPBridgeListenSocket.acceptConnection(listenDescriptor: listenDescriptor) expect(accepted >= 0, "the pending client connection must be accepted") defer { Darwin.close(accepted) } expect( - LKMCPBridgeListenSocket.isNonBlocking(descriptor: accepted) == false, + MCPBridgeListenSocket.isNonBlocking(descriptor: accepted) == false, "accepted connections must be blocking; a non-blocking one drops any frame larger than the send buffer" ) } @@ -160,7 +160,7 @@ struct LKMCPBridgeListenSocketTests { let socketPath = makeTemporarySocketPath() defer { unlink(socketPath) } - guard let descriptor = try? LKMCPBridgeListenSocket.makeListening(atPath: socketPath, backlog: 16) else { + guard let descriptor = try? MCPBridgeListenSocket.makeListening(atPath: socketPath, backlog: 16) else { fail("makeListening should succeed on a fresh path") } defer { Darwin.close(descriptor) } @@ -171,7 +171,7 @@ struct LKMCPBridgeListenSocketTests { } let permissionBits = fileStatus.st_mode & 0o777 expect( - permissionBits == LKMCPBridgeListenSocket.socketFilePermissions, + permissionBits == MCPBridgeListenSocket.socketFilePermissions, "socket must be owner-only, got \(String(permissionBits, radix: 8))" ) } @@ -182,13 +182,13 @@ struct LKMCPBridgeListenSocketTests { let socketPath = makeTemporarySocketPath() defer { unlink(socketPath) } - guard let firstDescriptor = try? LKMCPBridgeListenSocket.makeListening(atPath: socketPath, backlog: 16) else { + guard let firstDescriptor = try? MCPBridgeListenSocket.makeListening(atPath: socketPath, backlog: 16) else { fail("makeListening should succeed on a fresh path") } // Close without unlinking: exactly what a crash leaves behind. Darwin.close(firstDescriptor) - guard let secondDescriptor = try? LKMCPBridgeListenSocket.makeListening(atPath: socketPath, backlog: 16) else { + guard let secondDescriptor = try? MCPBridgeListenSocket.makeListening(atPath: socketPath, backlog: 16) else { fail("makeListening should replace a stale socket file rather than failing to bind") } Darwin.close(secondDescriptor) diff --git a/Tests/MCPBridge/LKMCPBridgeObjectIdentifierListTests.swift b/Tests/MCPBridge/MCPBridgeObjectIdentifierListTests.swift similarity index 82% rename from Tests/MCPBridge/LKMCPBridgeObjectIdentifierListTests.swift rename to Tests/MCPBridge/MCPBridgeObjectIdentifierListTests.swift index 1042ad71..92662f62 100644 --- a/Tests/MCPBridge/LKMCPBridgeObjectIdentifierListTests.swift +++ b/Tests/MCPBridge/MCPBridgeObjectIdentifierListTests.swift @@ -8,7 +8,7 @@ import Foundation /// an LLM-driven MCP client, so a list carrying the same identifier twice is /// routine input. Every de-duplication test here stands in for that crash. @main -struct LKMCPBridgeObjectIdentifierListTests { +struct MCPBridgeObjectIdentifierListTests { static func main() { testRepeatedIdentifierIsCollapsed() testEveryEntryIdenticalCollapsesToOne() @@ -81,7 +81,7 @@ struct LKMCPBridgeObjectIdentifierListTests { // MARK: - Rejection private static func testNonStringEntryIsRejected() { - let result = LKMCPBridgeObjectIdentifierList.parse( + let result = MCPBridgeObjectIdentifierList.parse( wireValues: [.string("0xaa"), .integer(7)], limit: 100 ) @@ -92,7 +92,7 @@ struct LKMCPBridgeObjectIdentifierListTests { } private static func testEmptyArrayIsRejected() { - let result = LKMCPBridgeObjectIdentifierList.parse(wireValues: [], limit: 100) + let result = MCPBridgeObjectIdentifierList.parse(wireValues: [], limit: 100) expect( failure(of: result) == .empty, "an empty identifier array must be rejected" @@ -105,9 +105,9 @@ struct LKMCPBridgeObjectIdentifierListTests { /// Duplicates cost nothing downstream, so a list that only *looks* too /// long must not be refused. private static func testCapAppliesToDistinctCountNotRawCount() { - let wireValues = (0 ..< 6).map { _ in LKMCPBridgeJSONValue.string("0xaa") } - + [LKMCPBridgeJSONValue.string("0xbb")] - let result = LKMCPBridgeObjectIdentifierList.parse(wireValues: wireValues, limit: 3) + let wireValues = (0 ..< 6).map { _ in MCPBridgeJSONValue.string("0xaa") } + + [MCPBridgeJSONValue.string("0xbb")] + let result = MCPBridgeObjectIdentifierList.parse(wireValues: wireValues, limit: 3) let parsed = expectSuccess(result) expect( parsed.identifiers == ["0xaa", "0xbb"], @@ -116,8 +116,8 @@ struct LKMCPBridgeObjectIdentifierListTests { } private static func testTooManyDistinctIdentifiersIsRejected() { - let wireValues = (0 ..< 5).map { LKMCPBridgeJSONValue.string("0x\($0)") } - let result = LKMCPBridgeObjectIdentifierList.parse(wireValues: wireValues, limit: 3) + let wireValues = (0 ..< 5).map { MCPBridgeJSONValue.string("0x\($0)") } + let result = MCPBridgeObjectIdentifierList.parse(wireValues: wireValues, limit: 3) expect( failure(of: result) == .tooMany(distinctCount: 5, limit: 3), "five distinct identifiers must be rejected against a cap of three" @@ -128,16 +128,16 @@ struct LKMCPBridgeObjectIdentifierListTests { private static func parse( _ identifiers: [String] - ) -> Result { - return LKMCPBridgeObjectIdentifierList.parse( - wireValues: identifiers.map(LKMCPBridgeJSONValue.string), + ) -> Result { + return MCPBridgeObjectIdentifierList.parse( + wireValues: identifiers.map(MCPBridgeJSONValue.string), limit: 100 ) } private static func expectSuccess( - _ result: Result - ) -> LKMCPBridgeObjectIdentifierList.Parsed { + _ result: Result + ) -> MCPBridgeObjectIdentifierList.Parsed { switch result { case let .success(parsed): return parsed @@ -147,8 +147,8 @@ struct LKMCPBridgeObjectIdentifierListTests { } private static func failure( - of result: Result - ) -> LKMCPBridgeObjectIdentifierList.ParseFailure? { + of result: Result + ) -> MCPBridgeObjectIdentifierList.ParseFailure? { switch result { case .success: return nil diff --git a/Tests/MCPBridge/LKMCPBridgeSearchQueryTests.swift b/Tests/MCPBridge/MCPBridgeSearchQueryTests.swift similarity index 78% rename from Tests/MCPBridge/LKMCPBridgeSearchQueryTests.swift rename to Tests/MCPBridge/MCPBridgeSearchQueryTests.swift index 6084e44f..2c0f727c 100644 --- a/Tests/MCPBridge/LKMCPBridgeSearchQueryTests.swift +++ b/Tests/MCPBridge/MCPBridgeSearchQueryTests.swift @@ -8,7 +8,7 @@ import Foundation /// about the inspected app rather than about the request. Every test here /// exists to make one of those silent outcomes loud. @main -struct LKMCPBridgeSearchQueryTests { +struct MCPBridgeSearchQueryTests { static func main() { testMatchesLeafClassName() testClassNameDoesNotMatchAncestorClass() @@ -30,7 +30,7 @@ struct LKMCPBridgeSearchQueryTests { // MARK: - Field semantics private static func testMatchesLeafClassName() { - let query = LKMCPBridgeSearchQuery(rawQuery: "UIButton") + let query = MCPBridgeSearchQuery(rawQuery: "UIButton") expect( query.matches(button()), "a query naming the leaf class must match that node" @@ -40,7 +40,7 @@ struct LKMCPBridgeSearchQueryTests { /// `className` is the narrow field: it is what lets an agent ask for /// `UIView` without getting back every view in the app. private static func testClassNameDoesNotMatchAncestorClass() { - let query = LKMCPBridgeSearchQuery(rawQuery: "UIControl", fields: [.className]) + let query = MCPBridgeSearchQuery(rawQuery: "UIControl", fields: [.className]) expect( query.matchedFields(in: button()).isEmpty, "className must consider only the leaf class, not the rest of the chain" @@ -48,7 +48,7 @@ struct LKMCPBridgeSearchQueryTests { } private static func testClassChainMatchesAncestorClass() { - let query = LKMCPBridgeSearchQuery(rawQuery: "UIControl", fields: [.classChain]) + let query = MCPBridgeSearchQuery(rawQuery: "UIControl", fields: [.classChain]) expect( query.matchedFields(in: button()) == [.classChain], "classChain must match any class in the chain so subclasses are findable by their base class" @@ -56,7 +56,7 @@ struct LKMCPBridgeSearchQueryTests { } private static func testMatchingIsCaseInsensitive() { - let query = LKMCPBridgeSearchQuery(rawQuery: "uibutton", fields: [.className]) + let query = MCPBridgeSearchQuery(rawQuery: "uibutton", fields: [.className]) expect( query.matches(button()), "an agent should not have to reproduce the exact casing of a class name" @@ -64,17 +64,17 @@ struct LKMCPBridgeSearchQueryTests { } private static func testMatchesTitleAndSubtitle() { - let titleQuery = LKMCPBridgeSearchQuery(rawQuery: "Play", fields: [.title]) + let titleQuery = MCPBridgeSearchQuery(rawQuery: "Play", fields: [.title]) expect(titleQuery.matches(button()), "title must be searchable") - let subtitleQuery = LKMCPBridgeSearchQuery(rawQuery: "PlayerViewController", fields: [.subtitle]) + let subtitleQuery = MCPBridgeSearchQuery(rawQuery: "PlayerViewController", fields: [.subtitle]) expect(subtitleQuery.matches(button()), "subtitle must be searchable") } /// Addresses arrive from a debugger or a crash log, where the caller /// often has only the tail of one. private static func testMatchesPartialMemoryAddress() { - let query = LKMCPBridgeSearchQuery(rawQuery: "abc123", fields: [.memoryAddress]) + let query = MCPBridgeSearchQuery(rawQuery: "abc123", fields: [.memoryAddress]) expect( query.matches(button()), "a substring of a memory address must match, not just the whole address" @@ -85,7 +85,7 @@ struct LKMCPBridgeSearchQueryTests { private static func testNarrowingFieldsExcludesOtherHits() { // "Play" appears in the title and in the subtitle, nowhere else. - let query = LKMCPBridgeSearchQuery(rawQuery: "Play", fields: [.className, .classChain]) + let query = MCPBridgeSearchQuery(rawQuery: "Play", fields: [.className, .classChain]) expect( query.matchedFields(in: button()).isEmpty, "restricting matchFields must actually exclude the fields left out" @@ -94,7 +94,7 @@ struct LKMCPBridgeSearchQueryTests { private static func testMatchedFieldsReportEveryHitInCanonicalOrder() { // "UIButton" is the leaf class, is in the chain, and is the title. - let query = LKMCPBridgeSearchQuery(rawQuery: "UIButton") + let query = MCPBridgeSearchQuery(rawQuery: "UIButton") let matched = query.matchedFields(in: plainButton()) expect( matched == [.className, .classChain, .title], @@ -103,15 +103,15 @@ struct LKMCPBridgeSearchQueryTests { } private static func testEmptyFieldListMeansEveryField() { - let query = LKMCPBridgeSearchQuery(rawQuery: "Play", fields: []) + let query = MCPBridgeSearchQuery(rawQuery: "Play", fields: []) expect( - query.fields == LKMCPBridgeSearchQuery.Field.allCases, + query.fields == MCPBridgeSearchQuery.Field.allCases, "an empty field list must widen to every field rather than matching nothing" ) } private static func testDuplicateFieldsAreCollapsed() { - let query = LKMCPBridgeSearchQuery(rawQuery: "UIButton", fields: [.title, .className, .title]) + let query = MCPBridgeSearchQuery(rawQuery: "UIButton", fields: [.title, .className, .title]) expect( query.fields == [.className, .title], "duplicates must collapse and order must be canonical; got \(query.fields)" @@ -125,7 +125,7 @@ struct LKMCPBridgeSearchQueryTests { // MARK: - Negative paths private static func testNoMatchReturnsEmpty() { - let query = LKMCPBridgeSearchQuery(rawQuery: "NSTableView") + let query = MCPBridgeSearchQuery(rawQuery: "NSTableView") expect( query.matchedFields(in: button()).isEmpty, "a query matching nothing must report no matched fields" @@ -135,14 +135,14 @@ struct LKMCPBridgeSearchQueryTests { /// Nodes configured through the in-app custom-debug-info hook can be /// missing a title, a subtitle, or any backing object at all. private static func testAbsentStringsNeverMatch() { - let bare = LKMCPBridgeSearchQuery.Candidate( + let bare = MCPBridgeSearchQuery.Candidate( className: "", classChain: [], title: nil, subtitle: nil, memoryAddresses: [] ) - let query = LKMCPBridgeSearchQuery(rawQuery: "anything") + let query = MCPBridgeSearchQuery(rawQuery: "anything") expect( query.matchedFields(in: bare).isEmpty, "a candidate with no strings at all must not match" @@ -150,7 +150,7 @@ struct LKMCPBridgeSearchQueryTests { // An empty query would otherwise match every empty string via // `contains("")`, turning a search into a full tree dump. - let emptyQuery = LKMCPBridgeSearchQuery(rawQuery: "") + let emptyQuery = MCPBridgeSearchQuery(rawQuery: "") expect( emptyQuery.matchedFields(in: bare).isEmpty, "empty strings must not be considered matchable content" @@ -161,21 +161,21 @@ struct LKMCPBridgeSearchQueryTests { private static func testUnknownWireFieldNameIsRejected() { expect( - LKMCPBridgeSearchQuery.fields(fromWireNames: ["className", "classname"]) == nil, + MCPBridgeSearchQuery.fields(fromWireNames: ["className", "classname"]) == nil, "a misspelled field must be rejected, not silently dropped into a no-results answer" ) expect( - LKMCPBridgeSearchQuery.firstUnrecognizedFieldName(in: ["className", "classname"]) == "classname", + MCPBridgeSearchQuery.firstUnrecognizedFieldName(in: ["className", "classname"]) == "classname", "the rejected name must be reported so the error message can quote it" ) expect( - LKMCPBridgeSearchQuery.firstUnrecognizedFieldName(in: ["className", "title"]) == nil, + MCPBridgeSearchQuery.firstUnrecognizedFieldName(in: ["className", "title"]) == nil, "a fully valid list must report no unrecognized name" ) } private static func testWireFieldNamesResolveInCanonicalOrder() { - let resolved = LKMCPBridgeSearchQuery.fields(fromWireNames: ["subtitle", "className"]) + let resolved = MCPBridgeSearchQuery.fields(fromWireNames: ["subtitle", "className"]) expect( resolved == [.className, .subtitle], "wire names must resolve into canonical order; got \(String(describing: resolved))" @@ -187,8 +187,8 @@ struct LKMCPBridgeSearchQueryTests { /// A button whose title and subtitle carry app-supplied text, so /// field-narrowing tests have something that matches on exactly one /// field at a time. - private static func button() -> LKMCPBridgeSearchQuery.Candidate { - return LKMCPBridgeSearchQuery.Candidate( + private static func button() -> MCPBridgeSearchQuery.Candidate { + return MCPBridgeSearchQuery.Candidate( className: "UIButton", classChain: ["UIButton", "UIControl", "UIView", "UIResponder", "NSObject"], title: "Play", @@ -200,8 +200,8 @@ struct LKMCPBridgeSearchQueryTests { /// The default shape: title is just the demangled class name, which /// is what the host inspector shows for a view with no custom debug /// info. - private static func plainButton() -> LKMCPBridgeSearchQuery.Candidate { - return LKMCPBridgeSearchQuery.Candidate( + private static func plainButton() -> MCPBridgeSearchQuery.Candidate { + return MCPBridgeSearchQuery.Candidate( className: "UIButton", classChain: ["UIButton", "UIControl", "UIView"], title: "UIButton", diff --git a/Tests/Read/LaunchToolbarReadTests.swift b/Tests/Read/LaunchToolbarReadTests.swift index 8a80e28f..3cc8ec78 100644 --- a/Tests/Read/LaunchToolbarReadTests.swift +++ b/Tests/Read/LaunchToolbarReadTests.swift @@ -130,18 +130,18 @@ struct LaunchToolbarReadTests { private static func testScreenshotLookupTakesBothFromOneOid() { let soloA = Data([1]), groupB = Data([2]), soloB = Data([3]) - var result = LKReadScreenshotLookup.screenshots( + var result = ReadScreenshotLookup.screenshots( forOids: [1, 2], solo: [1: soloA, 2: soloB], group: [2: groupB] ) expect(result.solo == soloA && result.group == nil, "first oid with a screenshot wins, alone") - result = LKReadScreenshotLookup.screenshots(forOids: [3, 2], solo: [1: soloA, 2: soloB], group: [2: groupB]) + result = ReadScreenshotLookup.screenshots(forOids: [3, 2], solo: [1: soloA, 2: soloB], group: [2: groupB]) expect(result.solo == soloB && result.group == groupB, "both screenshots of the matching oid") - result = LKReadScreenshotLookup.screenshots(forOids: [9], solo: [1: soloA], group: nil) + result = ReadScreenshotLookup.screenshots(forOids: [9], solo: [1: soloA], group: nil) expect(result.solo == nil && result.group == nil, "no screenshot") - result = LKReadScreenshotLookup.screenshots(forOids: [2], solo: nil, group: [2: groupB]) + result = ReadScreenshotLookup.screenshots(forOids: [2], solo: nil, group: [2: groupB]) expect(result.solo == nil && result.group == groupB, "group only") } @@ -163,61 +163,61 @@ struct LaunchToolbarReadTests { } private static func testSteppingClamps() { - expect(abs(LKToolbarRules.stepped(0.5, by: LKToolbarRules.step, lower: 0, upper: 1) - 0.6) < 1e-9, "step up") - expect(LKToolbarRules.stepped(0.95, by: LKToolbarRules.step, lower: 0, upper: 1) == 1, "clamped high") - expect(LKToolbarRules.stepped(0.05, by: -LKToolbarRules.step, lower: 0, upper: 1) == 0, "clamped low") - expect(LKToolbarRules.stepped(3, by: 0.1, lower: 0, upper: 1) == 1, "out of range value comes back in range") + expect(abs(ToolbarRules.stepped(0.5, by: ToolbarRules.step, lower: 0, upper: 1) - 0.6) < 1e-9, "step up") + expect(ToolbarRules.stepped(0.95, by: ToolbarRules.step, lower: 0, upper: 1) == 1, "clamped high") + expect(ToolbarRules.stepped(0.05, by: -ToolbarRules.step, lower: 0, upper: 1) == 0, "clamped low") + expect(ToolbarRules.stepped(3, by: 0.1, lower: 0, upper: 1) == 1, "out of range value comes back in range") } private static func testAppsPopoverCopy() { - var copy = LKToolbarRules.appsPopoverCopy(source: .reloadButton, appCount: 0) + var copy = ToolbarRules.appsPopoverCopy(source: .reloadButton, appCount: 0) expect(copy.title == "Connection lost" && copy.subtitle == "And no inspectable app was found", "reload, no apps") - copy = LKToolbarRules.appsPopoverCopy(source: .noConnectionTips, appCount: 1) + copy = ToolbarRules.appsPopoverCopy(source: .noConnectionTips, appCount: 1) expect(copy.title == "Connection lost" && copy.subtitle == "Click the screenshot below to Change App", "tips, one app") - copy = LKToolbarRules.appsPopoverCopy(source: .reloadButton, appCount: 3) + copy = ToolbarRules.appsPopoverCopy(source: .reloadButton, appCount: 3) expect(copy.subtitle == "Other 3 apps were found", "reload, several apps") - copy = LKToolbarRules.appsPopoverCopy(source: .appButton, appCount: 0) + copy = ToolbarRules.appsPopoverCopy(source: .appButton, appCount: 0) expect(copy.title == "No inspectable app was found" && copy.subtitle == nil, "app button, no apps") - copy = LKToolbarRules.appsPopoverCopy(source: .appButton, appCount: 1) + copy = ToolbarRules.appsPopoverCopy(source: .appButton, appCount: 1) expect(copy.title == "1 active app was found" && copy.subtitle == "Click the screenshot below to inspect", "app button, one app") - copy = LKToolbarRules.appsPopoverCopy(source: .appButton, appCount: 2) + copy = ToolbarRules.appsPopoverCopy(source: .appButton, appCount: 2) expect(copy.title == "2 active apps were found", "app button, several apps") } // MARK: - Launch private static func testLaunchAutoEnter() { - expect(LKLaunchRules.canAutoEnter(requested: true, appCount: 1, onlyAppHasServerVersionError: false, isActivated: true), "auto enter") - expect(!LKLaunchRules.canAutoEnter(requested: false, appCount: 1, onlyAppHasServerVersionError: false, isActivated: true), "not requested") - expect(!LKLaunchRules.canAutoEnter(requested: true, appCount: 2, onlyAppHasServerVersionError: false, isActivated: true), "two apps") - expect(!LKLaunchRules.canAutoEnter(requested: true, appCount: 0, onlyAppHasServerVersionError: false, isActivated: true), "no apps") - expect(!LKLaunchRules.canAutoEnter(requested: true, appCount: 1, onlyAppHasServerVersionError: true, isActivated: true), "version error") - expect(!LKLaunchRules.canAutoEnter(requested: true, appCount: 1, onlyAppHasServerVersionError: false, isActivated: false), "not activated") + expect(LaunchRules.canAutoEnter(requested: true, appCount: 1, onlyAppHasServerVersionError: false, isActivated: true), "auto enter") + expect(!LaunchRules.canAutoEnter(requested: false, appCount: 1, onlyAppHasServerVersionError: false, isActivated: true), "not requested") + expect(!LaunchRules.canAutoEnter(requested: true, appCount: 2, onlyAppHasServerVersionError: false, isActivated: true), "two apps") + expect(!LaunchRules.canAutoEnter(requested: true, appCount: 0, onlyAppHasServerVersionError: false, isActivated: true), "no apps") + expect(!LaunchRules.canAutoEnter(requested: true, appCount: 1, onlyAppHasServerVersionError: true, isActivated: true), "version error") + expect(!LaunchRules.canAutoEnter(requested: true, appCount: 1, onlyAppHasServerVersionError: false, isActivated: false), "not activated") } private static func testLaunchServerVersionErrors() { - expect(LKLaunchRules.serverVersionHelpPath(errorCode: LookinErrCode_ServerVersionTooLow) == "faq/server-version-too-low/", "too low page") - expect(LKLaunchRules.serverVersionHelpPath(errorCode: LookinErrCode_ServerVersionTooHigh) == "faq/server-version-too-high/", "too high page") - expect(LKLaunchRules.serverVersionHelpPath(errorCode: LookinErrCode_Inner) == "faq/server-version-too-high/", "other errors use the too high page") + expect(LaunchRules.serverVersionHelpPath(errorCode: LookinErrCode_ServerVersionTooLow) == "faq/server-version-too-low/", "too low page") + expect(LaunchRules.serverVersionHelpPath(errorCode: LookinErrCode_ServerVersionTooHigh) == "faq/server-version-too-high/", "too high page") + expect(LaunchRules.serverVersionHelpPath(errorCode: LookinErrCode_Inner) == "faq/server-version-too-high/", "other errors use the too high page") expect( - LKLaunchRules.serverVersionErrorTitle(errorCode: LookinErrCode_ServerVersionTooLow, localizedDescription: "x") + LaunchRules.serverVersionErrorTitle(errorCode: LookinErrCode_ServerVersionTooLow, localizedDescription: "x") == "The version of LookinServer linked with this iOS App is too low.", "too low title" ) expect( - LKLaunchRules.serverVersionErrorTitle(errorCode: LookinErrCode_ServerVersionTooHigh, localizedDescription: "x") + LaunchRules.serverVersionErrorTitle(errorCode: LookinErrCode_ServerVersionTooHigh, localizedDescription: "x") == "Unable to inspect this iOS App. Current version of LookInside app is too low.", "too high title" ) - expect(LKLaunchRules.serverVersionErrorTitle(errorCode: -1, localizedDescription: "Custom") == "Custom", "own description") - expect(LKLaunchRules.serverVersionErrorTitle(errorCode: -1, localizedDescription: "") == "Unable to inspect this app.", "fallback title") + expect(LaunchRules.serverVersionErrorTitle(errorCode: -1, localizedDescription: "Custom") == "Custom", "own description") + expect(LaunchRules.serverVersionErrorTitle(errorCode: -1, localizedDescription: "") == "Unable to inspect this app.", "fallback title") } // MARK: - Helpers private static func decode(_ data: Data) -> HierarchyFile { do { - return try LookinArchiveCoding.hierarchyFile(from: data) + return try ArchiveCoding.hierarchyFile(from: data) } catch { fail("decode failed: \(error)") } @@ -225,7 +225,7 @@ struct LaunchToolbarReadTests { private static func encode(_ file: HierarchyFile) -> Data { do { - return try LookinArchiveCoding.data(of: file) + return try ArchiveCoding.data(of: file) } catch { fail("encode failed: \(error)") } @@ -233,7 +233,7 @@ struct LaunchToolbarReadTests { private static func expectError(_ data: Data, code: Int, _ message: String) { do { - _ = try LookinArchiveCoding.hierarchyFile(from: data) + _ = try ArchiveCoding.hierarchyFile(from: data) fail("\(message): decoding should fail") } catch { let error = error as NSError diff --git a/Tests/Security/LKInjectionStartGateTests.swift b/Tests/Security/InjectionStartGateTests.swift similarity index 76% rename from Tests/Security/LKInjectionStartGateTests.swift rename to Tests/Security/InjectionStartGateTests.swift index ab5902d9..56653c72 100644 --- a/Tests/Security/LKInjectionStartGateTests.swift +++ b/Tests/Security/InjectionStartGateTests.swift @@ -1,9 +1,9 @@ import Foundation @main -struct LKInjectionStartGateTests { +struct InjectionStartGateTests { static func main() { - var gate = LKInjectionStartGate() + var gate = InjectionStartGate() var gateChecks = 0 let blocked = gate.begin { @@ -41,27 +41,27 @@ struct LKInjectionStartGateTests { expect(gateChecks == 3, "restart checks access") expect( - LKInjectionDaemonReadiness.nextStep(for: .enabled) == .proceed, + InjectionDaemonReadiness.nextStep(for: .enabled) == .proceed, "enabled daemon proceeds without prompting" ) expect( - LKInjectionDaemonReadiness.nextStep(for: .notRegistered) == .requestRegistrationConsent, + InjectionDaemonReadiness.nextStep(for: .notRegistered) == .requestRegistrationConsent, "unregistered daemon asks for explicit user consent" ) expect( - LKInjectionDaemonReadiness.nextStep(for: .requiresApproval) == .waitForApproval, + InjectionDaemonReadiness.nextStep(for: .requiresApproval) == .waitForApproval, "pending daemon approval waits for system approval" ) expect( - LKInjectionDaemonReadiness.nextStep(for: .notFound) == .reportMissingBundle, + InjectionDaemonReadiness.nextStep(for: .notFound) == .reportMissingBundle, "missing bundled daemon is reported as a damaged app bundle" ) expect( - LKInjectionDaemonReadiness.nextStep(for: .unavailableFromCurrentLocation) == .reportCurrentLocationUnsupported, + InjectionDaemonReadiness.nextStep(for: .unavailableFromCurrentLocation) == .reportCurrentLocationUnsupported, "bundled daemon outside /Applications reports an unsupported app location" ) expect( - LKInjectionDaemonReadiness.nextStep(for: .unknown(42)) == .reportUnsupportedStatus(42), + InjectionDaemonReadiness.nextStep(for: .unknown(42)) == .reportUnsupportedStatus(42), "unknown daemon status is surfaced as unsupported" ) } diff --git a/Tests/XcodeViewHierarchy/LKXcodeViewHierarchyConverterTests.swift b/Tests/XcodeViewHierarchy/XcodeViewHierarchyConverterTests.swift similarity index 98% rename from Tests/XcodeViewHierarchy/LKXcodeViewHierarchyConverterTests.swift rename to Tests/XcodeViewHierarchy/XcodeViewHierarchyConverterTests.swift index 38cd31ee..f924dda9 100644 --- a/Tests/XcodeViewHierarchy/LKXcodeViewHierarchyConverterTests.swift +++ b/Tests/XcodeViewHierarchy/XcodeViewHierarchyConverterTests.swift @@ -12,7 +12,7 @@ import Foundation /// built, and the reader is then unusable: an assertion while drawing the /// dashboard, and a preview that receives nothing. @main -struct LKXcodeViewHierarchyConverterTests { +struct XcodeViewHierarchyConverterTests { static func main() { testColorAttributesCarryRGBAComponents() testEveryConvertedNodeOptsIntoScreenshots() @@ -418,7 +418,7 @@ struct LKXcodeViewHierarchyConverterTests { /// wrapper → backing layer, with anything else parked on the wrapper as /// the wrapper's own child. private static func testWrappedUIKitViewsKeepXcodesNesting() { - let screenshots = LKXcodeViewHierarchyScreenshots( + let screenshots = XcodeViewHierarchyScreenshots( soloByObjectIdentifier: [:], groupByObjectIdentifier: ["0x1000": imageData("group-1000"), "0x1201": imageData("group-1201")], failedArchiveIdentifiers: [] @@ -471,8 +471,8 @@ struct LKXcodeViewHierarchyConverterTests { Data(label.utf8) } - private static func layerTreeScreenshots() -> LKXcodeViewHierarchyScreenshots { - LKXcodeViewHierarchyScreenshots( + private static func layerTreeScreenshots() -> XcodeViewHierarchyScreenshots { + XcodeViewHierarchyScreenshots( soloByObjectIdentifier: ["0x100": imageData("solo-100")], groupByObjectIdentifier: [ "0x100": imageData("group-100"), "0x101": imageData("group-101"), "0x102": imageData("group-102"), @@ -490,8 +490,8 @@ struct LKXcodeViewHierarchyConverterTests { /// container (AppKit's own drawing: no delegate, a backing store for /// contents) and an image layer the app assigned. The subview's backing /// layer holds the label's own drawing container. - private static func appKitLayerTreeFixture() -> LKXcodeViewHierarchyObjectGraph { - let builder = LKXcodeViewHierarchyObjectGraphBuilder() + private static func appKitLayerTreeFixture() -> XcodeViewHierarchyObjectGraph { + let builder = XcodeViewHierarchyObjectGraphBuilder() builder.ingesting(response: response( groups: [ group("com.apple.AppKit.NSWindow", objects: [ @@ -554,8 +554,8 @@ struct LKXcodeViewHierarchyConverterTests { /// A UIKit window with one root view and an image view whose backing /// layer UIKit wrapped in a `_UIMultiLayer`, with a second layer parked /// on the wrapper that belongs to someone else. - private static func uiKitWrapperFixture() -> LKXcodeViewHierarchyObjectGraph { - let builder = LKXcodeViewHierarchyObjectGraphBuilder() + private static func uiKitWrapperFixture() -> XcodeViewHierarchyObjectGraph { + let builder = XcodeViewHierarchyObjectGraphBuilder() builder.ingesting(response: response( groups: [ group("com.apple.UIKit.UIApplication", objects: [ @@ -635,8 +635,8 @@ struct LKXcodeViewHierarchyConverterTests { /// - root views: the four window frames, a detached `TStatusBar` (`0x50`) /// owned by a view controller, an `NSTouchBarView` with a child (`0x60`) /// and one without (`0x70`). - private static func appKitSidebarFixture() -> LKXcodeViewHierarchyObjectGraph { - let builder = LKXcodeViewHierarchyObjectGraphBuilder() + private static func appKitSidebarFixture() -> XcodeViewHierarchyObjectGraph { + let builder = XcodeViewHierarchyObjectGraphBuilder() builder.ingesting(response: response(groups: [ group("com.apple.AppKit.NSApplication", objects: [ object("0xa0", className: "NSApplication", additionalGroups: [ @@ -707,7 +707,7 @@ struct LKXcodeViewHierarchyConverterTests { /// - scene `0xf2` owns window `0x2`, the application's key window; /// - windows `0x4` (visible), `0x5` (invisible) and `0x7` (a system /// overlay window) belong to no scene. - private static func uiKitSidebarFixture() -> LKXcodeViewHierarchyObjectGraph { + private static func uiKitSidebarFixture() -> XcodeViewHierarchyObjectGraph { func window( _ objectIdentifier: String, className: String = "UIWindow", @@ -746,7 +746,7 @@ struct LKXcodeViewHierarchyConverterTests { ) } - let builder = LKXcodeViewHierarchyObjectGraphBuilder() + let builder = XcodeViewHierarchyObjectGraphBuilder() builder.ingesting(response: response(groups: [ group("com.apple.UIKit.UIApplication", objects: [ object("0xa0", className: "UIApplication", additionalGroups: [ @@ -797,8 +797,8 @@ struct LKXcodeViewHierarchyConverterTests { /// `MyViewController`), labels `0x12` / `0x16` (the second with nil /// text), image views `0x13` / `0x14` (the second with no image), a stack /// view `0x15`, and a layout guide `0x30`; constraints `0xd1`–`0xd5`. - private static func uiKitCardsFixture() -> LKXcodeViewHierarchyObjectGraph { - let builder = LKXcodeViewHierarchyObjectGraphBuilder() + private static func uiKitCardsFixture() -> XcodeViewHierarchyObjectGraph { + let builder = XcodeViewHierarchyObjectGraphBuilder() builder.ingesting(response: response( groups: [ group("com.apple.UIKit.UIApplication", objects: [ @@ -906,8 +906,8 @@ struct LKXcodeViewHierarchyConverterTests { /// An AppKit capture: panel `0x1` (key, owned by `MyWindowController` /// `0xc1`, delegate `MyDelegate`) → content view `0x10` → button `0x11` /// with cell `0x40` and text field `0x12` with cell `0x41`. - private static func appKitCardsFixture() -> LKXcodeViewHierarchyObjectGraph { - let builder = LKXcodeViewHierarchyObjectGraphBuilder() + private static func appKitCardsFixture() -> XcodeViewHierarchyObjectGraph { + let builder = XcodeViewHierarchyObjectGraphBuilder() builder.ingesting(response: response( groups: [ group("com.apple.AppKit.NSApplication", objects: [ @@ -1034,7 +1034,7 @@ struct LKXcodeViewHierarchyConverterTests { /// background and border colours and a layout guide, plus a control /// subview with a cell. Every node kind the converter emits appears once. private static func convertedFixture() -> HierarchyFile { - let builder = LKXcodeViewHierarchyObjectGraphBuilder() + let builder = XcodeViewHierarchyObjectGraphBuilder() builder.ingesting(response: response(groups: [ group("com.apple.AppKit.NSWindow", objects: [ object("0x1", className: "NSWindow", additionalGroups: [ @@ -1075,10 +1075,10 @@ struct LKXcodeViewHierarchyConverterTests { } /// Runs the converter over a graph with no recovered pixels. - private static func convert(_ graph: LKXcodeViewHierarchyObjectGraph) -> HierarchyFile { + private static func convert(_ graph: XcodeViewHierarchyObjectGraph) -> HierarchyFile { convert( graph, - screenshots: LKXcodeViewHierarchyScreenshots( + screenshots: XcodeViewHierarchyScreenshots( soloByObjectIdentifier: [:], groupByObjectIdentifier: [:], failedArchiveIdentifiers: [] ), showingBackingLayers: false @@ -1086,12 +1086,12 @@ struct LKXcodeViewHierarchyConverterTests { } private static func convert( - _ graph: LKXcodeViewHierarchyObjectGraph, - screenshots: LKXcodeViewHierarchyScreenshots, + _ graph: XcodeViewHierarchyObjectGraph, + screenshots: XcodeViewHierarchyScreenshots, showingBackingLayers: Bool ) -> HierarchyFile { - let bundle = LKXcodeViewHierarchyBundle( - metadata: LKXcodeViewHierarchyBundleMetadata( + let bundle = XcodeViewHierarchyBundle( + metadata: XcodeViewHierarchyBundleMetadata( documentVersion: "1", runnableDisplayName: "Fixture", runnableProcessIdentifier: 1 ), graph: graph, @@ -1099,7 +1099,7 @@ struct LKXcodeViewHierarchyConverterTests { succeededResponseCount: 2 ) do { - return try LKXcodeViewHierarchyConverter.makingHierarchyFile( + return try XcodeViewHierarchyConverter.makingHierarchyFile( from: bundle, screenshots: screenshots, showingBackingLayers: showingBackingLayers ) } catch { diff --git a/Tests/XcodeViewHierarchy/LKXcodeViewHierarchyGzipTests.swift b/Tests/XcodeViewHierarchy/XcodeViewHierarchyGzipTests.swift similarity index 92% rename from Tests/XcodeViewHierarchy/LKXcodeViewHierarchyGzipTests.swift rename to Tests/XcodeViewHierarchy/XcodeViewHierarchyGzipTests.swift index 6948d954..b30fb588 100644 --- a/Tests/XcodeViewHierarchy/LKXcodeViewHierarchyGzipTests.swift +++ b/Tests/XcodeViewHierarchy/XcodeViewHierarchyGzipTests.swift @@ -14,7 +14,7 @@ import Foundation /// Assuming the fixed 10-byte form feeds garbage to the decoder for any /// capture written with those flags set. @main -struct LKXcodeViewHierarchyGzipTests { +struct XcodeViewHierarchyGzipTests { static func main() { testMinimalMemberRoundTrips() testMemberWithNameAndCommentAndExtraFieldRoundTrips() @@ -79,7 +79,7 @@ struct LKXcodeViewHierarchyGzipTests { private static func testTruncatedHeaderIsRejected() { let truncated = Data([0x1F, 0x8B, 0x08, 0x08, 0x00, 0x00]) do { - _ = try LKXcodeViewHierarchyGzip.inflating(truncated) + _ = try XcodeViewHierarchyGzip.inflating(truncated) fail("a truncated gzip header must be rejected") } catch { // Expected. @@ -92,7 +92,7 @@ struct LKXcodeViewHierarchyGzipTests { member[1] = 0x8B member[2] = 0x07 // not DEFLATE do { - _ = try LKXcodeViewHierarchyGzip.inflating(Data(member)) + _ = try XcodeViewHierarchyGzip.inflating(Data(member)) fail("a non-DEFLATE compression method must be rejected") } catch { // Expected. @@ -101,10 +101,10 @@ struct LKXcodeViewHierarchyGzipTests { private static func testGzipMemberDetection() { let member = gzipMember(wrapping: Data("x".utf8)) - expect(LKXcodeViewHierarchyGzip.isGzipMember(member), "a real member should be detected") - expect(!LKXcodeViewHierarchyGzip.isGzipMember(Data("{\"a\":1}".utf8)), + expect(XcodeViewHierarchyGzip.isGzipMember(member), "a real member should be detected") + expect(!XcodeViewHierarchyGzip.isGzipMember(Data("{\"a\":1}".utf8)), "JSON should not be mistaken for a gzip member") - expect(!LKXcodeViewHierarchyGzip.isGzipMember(Data([0x1F, 0x8B])), + expect(!XcodeViewHierarchyGzip.isGzipMember(Data([0x1F, 0x8B])), "a two-byte payload is too short to be a member") } @@ -179,7 +179,7 @@ struct LKXcodeViewHierarchyGzipTests { private static func inflate(_ member: Data) -> Data { do { - return try LKXcodeViewHierarchyGzip.inflating(member) + return try XcodeViewHierarchyGzip.inflating(member) } catch { fail("inflating threw: \(error)") } @@ -187,7 +187,7 @@ struct LKXcodeViewHierarchyGzipTests { private static func inflateIfNeeded(_ payload: Data) -> Data { do { - return try LKXcodeViewHierarchyGzip.inflatingIfNeeded(payload) + return try XcodeViewHierarchyGzip.inflatingIfNeeded(payload) } catch { fail("inflatingIfNeeded threw: \(error)") } diff --git a/Tests/XcodeViewHierarchy/LKXcodeViewHierarchyObjectGraphTests.swift b/Tests/XcodeViewHierarchy/XcodeViewHierarchyObjectGraphTests.swift similarity index 95% rename from Tests/XcodeViewHierarchy/LKXcodeViewHierarchyObjectGraphTests.swift rename to Tests/XcodeViewHierarchy/XcodeViewHierarchyObjectGraphTests.swift index bdfdc5c0..6a2d285e 100644 --- a/Tests/XcodeViewHierarchy/LKXcodeViewHierarchyObjectGraphTests.swift +++ b/Tests/XcodeViewHierarchy/XcodeViewHierarchyObjectGraphTests.swift @@ -10,7 +10,7 @@ import Foundation /// promoted to a subview, a property blanked by a later response that only /// meant "unchanged", or a replaced view lingering beside its replacement. @main -struct LKXcodeViewHierarchyObjectGraphTests { +struct XcodeViewHierarchyObjectGraphTests { static func main() { testObjectDescribedTwiceIsOneNode() testChildGroupBecomesOwnedChildren() @@ -40,7 +40,7 @@ struct LKXcodeViewHierarchyObjectGraphTests { /// A capture writes the same object into several responses. Keying by /// `objectID` is what keeps one node instead of one per mention. private static func testObjectDescribedTwiceIsOneNode() { - let builder = LKXcodeViewHierarchyObjectGraphBuilder() + let builder = XcodeViewHierarchyObjectGraphBuilder() builder.ingesting(response: response(groups: [ group("com.apple.UIKit.UIView", objects: [object("0x1", className: "UIView")]), ])) @@ -122,7 +122,7 @@ struct LKXcodeViewHierarchyObjectGraphTests { // MARK: - Out-of-band properties private static func testTopLevelPropertyRoutesByKeyPath() { - let builder = LKXcodeViewHierarchyObjectGraphBuilder() + let builder = XcodeViewHierarchyObjectGraphBuilder() builder.ingesting(response: response(groups: [ group("com.apple.UIKit.UIView", objects: [object("0x1", className: "UIView")]), ])) @@ -140,7 +140,7 @@ struct LKXcodeViewHierarchyObjectGraphTests { /// Some descriptions omit `propertyName`; the key path is the fallback. private static func testPropertyNameIsRecoveredFromKeyPath() { - let builder = LKXcodeViewHierarchyObjectGraphBuilder() + let builder = XcodeViewHierarchyObjectGraphBuilder() builder.ingesting(response: response(properties: [ "0x1.alpha": ["propertyFormat": "CGf", "propertyValue": "0x1p-1", "fetchStatus": NSNumber(value: 4)], ])) @@ -168,7 +168,7 @@ struct LKXcodeViewHierarchyObjectGraphTests { } private static func testRetrievedStatusOverwrites() { - let builder = LKXcodeViewHierarchyObjectGraphBuilder() + let builder = XcodeViewHierarchyObjectGraphBuilder() builder.ingesting(response: response(properties: [ "0x1.frame": propertyDescription( name: "frame", format: "CGf, CGf, CGf, CGf", @@ -186,8 +186,8 @@ struct LKXcodeViewHierarchyObjectGraphTests { "a retrieved value must replace the earlier one") } - private static func graphWithFrameThenStatus(_ status: Int) -> LKXcodeViewHierarchyObjectGraph { - let builder = LKXcodeViewHierarchyObjectGraphBuilder() + private static func graphWithFrameThenStatus(_ status: Int) -> XcodeViewHierarchyObjectGraph { + let builder = XcodeViewHierarchyObjectGraphBuilder() builder.ingesting(response: response(properties: [ "0x1.frame": propertyDescription( name: "frame", format: "CGf, CGf, CGf, CGf", @@ -209,7 +209,7 @@ struct LKXcodeViewHierarchyObjectGraphTests { /// Version 1 spelled the outcome `propertyValueStatus` with different codes. /// Without the migration, every property in an old export reads as failed. private static func testLegacyPropertyValueStatusIsMigrated() { - let builder = LKXcodeViewHierarchyObjectGraphBuilder() + let builder = XcodeViewHierarchyObjectGraphBuilder() var legacyResponse = response(properties: [ "0x1.alpha": [ "propertyName": "alpha", @@ -228,7 +228,7 @@ struct LKXcodeViewHierarchyObjectGraphTests { /// Status 1 in version 1 meant "retrieved, but the value is not usable"; /// Xcode drops the value and keeps the status successful. private static func testLegacyStatusOneDropsItsValue() { - let builder = LKXcodeViewHierarchyObjectGraphBuilder() + let builder = XcodeViewHierarchyObjectGraphBuilder() var legacyResponse = response(properties: [ "0x1.alpha": [ "propertyName": "alpha", @@ -274,7 +274,7 @@ struct LKXcodeViewHierarchyObjectGraphTests { /// Properties can name an object no response described; keeping the value /// beats dropping it. private static func testPropertyForUnknownObjectStillLands() { - let builder = LKXcodeViewHierarchyObjectGraphBuilder() + let builder = XcodeViewHierarchyObjectGraphBuilder() builder.ingesting(response: response(properties: [ "0xDEAD.hidden": propertyDescription(name: "hidden", format: "b", value: "1"), ])) @@ -285,7 +285,7 @@ struct LKXcodeViewHierarchyObjectGraphTests { /// One unreadable property must not abort the import of the whole capture. private static func testMalformedValueIsReportedNotFatal() { - let builder = LKXcodeViewHierarchyObjectGraphBuilder() + let builder = XcodeViewHierarchyObjectGraphBuilder() builder.ingesting(response: response(properties: [ "0x1.frame": propertyDescription(name: "frame", format: "CGf, CGf, CGf, CGf", value: ["0x0p+0"]), "0x1.hidden": propertyDescription(name: "hidden", format: "b", value: "1"), @@ -301,7 +301,7 @@ struct LKXcodeViewHierarchyObjectGraphTests { /// The capture nests classes by subclass; the inspector reads the chain in /// the other direction, and shows and searches it. private static func testClassChainIsBuiltFromClassInformation() { - let builder = LKXcodeViewHierarchyObjectGraphBuilder() + let builder = XcodeViewHierarchyObjectGraphBuilder() builder.ingesting(response: [ "version": NSNumber(value: 2), "classInformation": [ @@ -324,7 +324,7 @@ struct LKXcodeViewHierarchyObjectGraphTests { } private static func testClassChainOfUnknownClassIsJustItself() { - let graph = LKXcodeViewHierarchyObjectGraphBuilder().build() + let graph = XcodeViewHierarchyObjectGraphBuilder().build() expect(graph.classChain(forClassName: "MysteryView") == ["MysteryView"], "an unknown class should still yield a one-element chain") } @@ -338,7 +338,7 @@ struct LKXcodeViewHierarchyObjectGraphTests { /// by address leaves stale views beside their replacements. The latest /// capture is the document; the earlier ones are discarded whole. private static func testNewCaptureReplacesTheEarlierOne() { - let builder = LKXcodeViewHierarchyObjectGraphBuilder() + let builder = XcodeViewHierarchyObjectGraphBuilder() builder.ingesting(response: response(groups: [ group("com.apple.AppKit.NSView", objects: [ object("0x1", className: "NSView", childGroup: group("com.apple.AppKit.NSView", objects: [ @@ -378,7 +378,7 @@ struct LKXcodeViewHierarchyObjectGraphTests { /// address, each is the other's child, and any walk of the tree recurses /// until the stack is gone. private static func testReusedAddressesDoNotFormACycle() { - let builder = LKXcodeViewHierarchyObjectGraphBuilder() + let builder = XcodeViewHierarchyObjectGraphBuilder() builder.ingesting(response: response(groups: [ group("com.apple.AppKit.NSView", objects: [ object("0x1", className: "NSView", childGroup: group("com.apple.AppKit.NSView", objects: [ @@ -459,8 +459,8 @@ struct LKXcodeViewHierarchyObjectGraphTests { ] } - private static func graphFrom(groups: [[String: Any]]) -> LKXcodeViewHierarchyObjectGraph { - let builder = LKXcodeViewHierarchyObjectGraphBuilder() + private static func graphFrom(groups: [[String: Any]]) -> XcodeViewHierarchyObjectGraph { + let builder = XcodeViewHierarchyObjectGraphBuilder() builder.ingesting(response: response(groups: groups)) return builder.build() } diff --git a/Tests/XcodeViewHierarchy/LKXcodeViewHierarchyPixelRecoveryTests.swift b/Tests/XcodeViewHierarchy/XcodeViewHierarchyPixelRecoveryTests.swift similarity index 94% rename from Tests/XcodeViewHierarchy/LKXcodeViewHierarchyPixelRecoveryTests.swift rename to Tests/XcodeViewHierarchy/XcodeViewHierarchyPixelRecoveryTests.swift index dba7d5af..01ef1bc8 100644 --- a/Tests/XcodeViewHierarchy/LKXcodeViewHierarchyPixelRecoveryTests.swift +++ b/Tests/XcodeViewHierarchy/XcodeViewHierarchyPixelRecoveryTests.swift @@ -15,7 +15,7 @@ import QuartzCore /// fine. The tests below place markers in known places and check where they /// land, which is the smallest thing that can tell those apart. @main -struct LKXcodeViewHierarchyPixelRecoveryTests { +struct XcodeViewHierarchyPixelRecoveryTests { static func main() { testUnflippedTreeKeepsSublayerPosition() testFlippedTreeInvertsSublayerPosition() @@ -71,7 +71,7 @@ struct LKXcodeViewHierarchyPixelRecoveryTests { guard let archiveData = archiveData(rootLayer: orientationFixture(), geometryFlipped: true) else { fail("could not build the archive fixture") } - let builder = LKXcodeViewHierarchyObjectGraphBuilder() + let builder = XcodeViewHierarchyObjectGraphBuilder() builder.ingesting(response: [ "version": NSNumber(value: 2), "topLevelGroups": [ @@ -90,7 +90,7 @@ struct LKXcodeViewHierarchyPixelRecoveryTests { ], ]) - let screenshots = LKXcodeViewHierarchyPixelRecovery.recovering(from: builder.build()) + let screenshots = XcodeViewHierarchyPixelRecovery.recovering(from: builder.build()) guard let groupImage = screenshots.groupByObjectIdentifier["0x1"] else { fail("recovery produced no image for the captured layer") } @@ -126,7 +126,7 @@ struct LKXcodeViewHierarchyPixelRecoveryTests { flippedChild.addSublayer(band) root.addSublayer(flippedChild) - guard let rootData = LKXcodeViewHierarchyPixelRecovery.renderingPNG( + guard let rootData = XcodeViewHierarchyPixelRecovery.renderingPNG( of: root, includingSublayers: true, isFlipped: false ), let rootImage = NSBitmapImageRep(data: rootData)?.cgImage, let childRegion = rootImage.cropping( @@ -137,7 +137,7 @@ struct LKXcodeViewHierarchyPixelRecoveryTests { guard let archiveData = archiveData(rootLayer: root, geometryFlipped: false) else { fail("could not build the archive fixture") } - let screenshots = LKXcodeViewHierarchyPixelRecovery.recovering( + let screenshots = XcodeViewHierarchyPixelRecovery.recovering( from: layerCapture(archiveData: archiveData, tree: LayerNodeFixture("0x1", [LayerNodeFixture("0x2")])) ) guard let childData = screenshots.groupByObjectIdentifier["0x2"], @@ -177,7 +177,7 @@ struct LKXcodeViewHierarchyPixelRecoveryTests { LayerNodeFixture("0x4", [LayerNodeFixture("0x5")]), ]), ])) - let screenshots = LKXcodeViewHierarchyPixelRecovery.recovering(from: capture) + let screenshots = XcodeViewHierarchyPixelRecovery.recovering(from: capture) expectRows(screenshots, "0x1", "the root", [(5, "red"), (15, "blue"), (22, "green"), (30, "yellow"), (50, "white")]) expectRows(screenshots, "0x2", "level one", [(5, "red"), (15, "blue"), (22, "green"), (30, "yellow")]) @@ -206,7 +206,7 @@ struct LKXcodeViewHierarchyPixelRecoveryTests { tree: LayerNodeFixture("0x1", [LayerNodeFixture("0x2"), LayerNodeFixture("0x3")]), hostedLayerIdentifiers: ["0x2"] ) - let screenshots = LKXcodeViewHierarchyPixelRecovery.recovering(from: capture) + let screenshots = XcodeViewHierarchyPixelRecovery.recovering(from: capture) expectRows(screenshots, "0x1", "the root's group", [(10, "red"), (90, "blue")]) guard let excludingData = screenshots.groupExcludingHostedViewsByObjectIdentifier["0x1"], let excludingBitmap = NSBitmapImageRep(data: excludingData) @@ -248,7 +248,7 @@ struct LKXcodeViewHierarchyPixelRecoveryTests { archiveData: archiveData, tree: LayerNodeFixture("0x1", [LayerNodeFixture("0x2", [LayerNodeFixture("0x3")]), LayerNodeFixture("0x4")]) ) - let screenshots = LKXcodeViewHierarchyPixelRecovery.recovering(from: capture) + let screenshots = XcodeViewHierarchyPixelRecovery.recovering(from: capture) guard let contentData = screenshots.groupByObjectIdentifier["0x2"], let contentBitmap = NSBitmapImageRep(data: contentData) else { fail("the sparse content layer should still render") } @@ -270,10 +270,10 @@ struct LKXcodeViewHierarchyPixelRecoveryTests { fail("could not build the archive fixture") } let capture = layerCapture(archiveData: archiveData, tree: LayerNodeFixture("0x1", [LayerNodeFixture("0x2")])) - let cancelled = LKXcodeViewHierarchyPixelRecovery.recovering(from: capture, isCancelled: { true }) + let cancelled = XcodeViewHierarchyPixelRecovery.recovering(from: capture, isCancelled: { true }) expect(cancelled.groupByObjectIdentifier.isEmpty && cancelled.soloByObjectIdentifier.isEmpty, "a cancelled recovery must not hand back images") - let completed = LKXcodeViewHierarchyPixelRecovery.recovering(from: capture) + let completed = XcodeViewHierarchyPixelRecovery.recovering(from: capture) expect(!completed.groupByObjectIdentifier.isEmpty, "the same capture renders when not cancelled") } @@ -284,7 +284,7 @@ struct LKXcodeViewHierarchyPixelRecoveryTests { private static func testEmptyLayerProducesNoImage() { let layer = CALayer() layer.bounds = CGRect(x: 0, y: 0, width: 40, height: 40) - expect(LKXcodeViewHierarchyPixelRecovery.renderingPNG( + expect(XcodeViewHierarchyPixelRecovery.renderingPNG( of: layer, includingSublayers: true, isFlipped: false ) == nil, "a fully transparent layer should not produce an image") } @@ -293,7 +293,7 @@ struct LKXcodeViewHierarchyPixelRecoveryTests { let layer = CALayer() layer.bounds = .zero layer.backgroundColor = NSColor.red.cgColor - expect(LKXcodeViewHierarchyPixelRecovery.renderingPNG( + expect(XcodeViewHierarchyPixelRecovery.renderingPNG( of: layer, includingSublayers: true, isFlipped: false ) == nil, "a zero-sized layer should not produce an image") } @@ -306,12 +306,12 @@ struct LKXcodeViewHierarchyPixelRecoveryTests { layer.contentsScale = 2 layer.backgroundColor = NSColor.red.cgColor layer.borderWidth = 1 // something to draw, so the plain-colour skip does not apply - guard let data = LKXcodeViewHierarchyPixelRecovery.renderingPNG( + guard let data = XcodeViewHierarchyPixelRecovery.renderingPNG( of: layer, includingSublayers: true, isFlipped: false ) else { fail("a large opaque layer should still render") } guard let image = NSBitmapImageRep(data: data) else { fail("rendered data was not a bitmap") } let renderedPixelCount = image.pixelsWide * image.pixelsHigh - expect(renderedPixelCount <= LKXcodeViewHierarchyPixelRecovery.maximumRenderedPixelCount, + expect(renderedPixelCount <= XcodeViewHierarchyPixelRecovery.maximumRenderedPixelCount, "rendered \(renderedPixelCount) pixels, above the cap") expect(image.pixelsWide > 4000, "the cap should reduce the scale, not the usefulness") } @@ -326,9 +326,9 @@ struct LKXcodeViewHierarchyPixelRecoveryTests { layer.contentsScale = 2 layer.backgroundColor = NSColor.red.cgColor layer.borderWidth = 1 - let scale = LKXcodeViewHierarchyPixelRecovery.renderingScale(for: layer) + let scale = XcodeViewHierarchyPixelRecovery.renderingScale(for: layer) expect(abs(scale - 16384.0 / 21530.0) < 0.001, "the longest side sets the scale; got \(scale)") - guard let data = LKXcodeViewHierarchyPixelRecovery.renderingPNG( + guard let data = XcodeViewHierarchyPixelRecovery.renderingPNG( of: layer, includingSublayers: true, isFlipped: false ) else { fail("a tall layer should still render") } guard let image = NSBitmapImageRep(data: data) else { fail("rendered data was not a bitmap") } @@ -354,7 +354,7 @@ struct LKXcodeViewHierarchyPixelRecoveryTests { archiveData: archiveData, tree: LayerNodeFixture("0x1", [LayerNodeFixture("0x2"), LayerNodeFixture("0x3")]) ) - let screenshots = LKXcodeViewHierarchyPixelRecovery.recovering(from: capture) + let screenshots = XcodeViewHierarchyPixelRecovery.recovering(from: capture) expect(screenshots.groupByObjectIdentifier["0x1"] != nil, "a plain layer with sublayers still needs its group image") expect(screenshots.soloByObjectIdentifier["0x1"] == nil, "a plain layer's own picture is its background colour: no solo") expect(screenshots.groupByObjectIdentifier["0x2"] == nil, "a plain leaf layer needs no image at all") @@ -370,7 +370,7 @@ struct LKXcodeViewHierarchyPixelRecoveryTests { guard let archiveData = archiveData(rootLayer: root, geometryFlipped: true) else { fail("could not build the archive fixture") } - guard let tree = LKXcodeViewHierarchyLayerArchive.decodingLayerTree( + guard let tree = XcodeViewHierarchyLayerArchive.decodingLayerTree( from: archiveData, rootObjectIdentifier: "0x1" ) else { fail("archive did not decode") } expect(tree.rootObjectIdentifier == "0x1", "root identifier should be carried through") @@ -380,7 +380,7 @@ struct LKXcodeViewHierarchyPixelRecoveryTests { private static func testMalformedArchiveIsRejected() { let garbage = Data("not an archive".utf8) - expect(LKXcodeViewHierarchyLayerArchive.decodingLayerTree( + expect(XcodeViewHierarchyLayerArchive.decodingLayerTree( from: garbage, rootObjectIdentifier: "0x1" ) == nil, "a malformed archive must be rejected rather than trapping") } @@ -447,7 +447,7 @@ struct LKXcodeViewHierarchyPixelRecoveryTests { archiveData: Data, tree: LayerNodeFixture, hostedLayerIdentifiers: [String] = [] - ) -> LKXcodeViewHierarchyObjectGraph { + ) -> XcodeViewHierarchyObjectGraph { func describing(_ node: LayerNodeFixture) -> [String: Any] { var object: [String: Any] = ["objectID": node.identifier, "className": "CALayer"] if !node.children.isEmpty { @@ -479,7 +479,7 @@ struct LKXcodeViewHierarchyPixelRecoveryTests { }, ] } - let builder = LKXcodeViewHierarchyObjectGraphBuilder() + let builder = XcodeViewHierarchyObjectGraphBuilder() builder.ingesting(response: [ "version": NSNumber(value: 2), "topLevelGroups": topLevelGroups, @@ -516,7 +516,7 @@ struct LKXcodeViewHierarchyPixelRecoveryTests { /// Samples the middle column of a recovered image at the given rows, /// counted from the top, and names the colour found. private static func expectRows( - _ screenshots: LKXcodeViewHierarchyScreenshots, + _ screenshots: XcodeViewHierarchyScreenshots, _ objectIdentifier: String, _ label: String, _ expectations: [(row: Int, color: String)] @@ -555,7 +555,7 @@ struct LKXcodeViewHierarchyPixelRecoveryTests { if shouldApplyGeometryFlip { applyGeometryFlip(to: root) } - guard let data = LKXcodeViewHierarchyPixelRecovery.renderingPNG( + guard let data = XcodeViewHierarchyPixelRecovery.renderingPNG( of: root, includingSublayers: true, isFlipped: flippingContext ), let bitmap = NSBitmapImageRep(data: data) else { return nil } return measuring(bitmap) diff --git a/Tests/XcodeViewHierarchy/LKXcodeViewHierarchyValueTests.swift b/Tests/XcodeViewHierarchy/XcodeViewHierarchyValueTests.swift similarity index 95% rename from Tests/XcodeViewHierarchy/LKXcodeViewHierarchyValueTests.swift rename to Tests/XcodeViewHierarchy/XcodeViewHierarchyValueTests.swift index 5061b561..278143c8 100644 --- a/Tests/XcodeViewHierarchy/LKXcodeViewHierarchyValueTests.swift +++ b/Tests/XcodeViewHierarchy/XcodeViewHierarchyValueTests.swift @@ -14,7 +14,7 @@ import Foundation /// every capture is encoded as a C99 hex float, so reading it with an ordinary /// decimal parser silently yields zero for the entire hierarchy. @main -struct LKXcodeViewHierarchyValueTests { +struct XcodeViewHierarchyValueTests { static func main() { testHexadecimalFloatIsParsed() testNegativeHexadecimalFloatIsParsed() @@ -295,23 +295,23 @@ struct LKXcodeViewHierarchyValueTests { /// deliberately omitted it because an earlier response already had it, and /// applying it as a value would blank the property. private static func testFetchStatusGatesValueApplication() { - expect(LKXcodeViewHierarchyFetchStatus.retrieved.skipsValueApplication == false, + expect(XcodeViewHierarchyFetchStatus.retrieved.skipsValueApplication == false, "retrieved values must be applied") - expect(LKXcodeViewHierarchyFetchStatus.noValue.skipsValueApplication == false, + expect(XcodeViewHierarchyFetchStatus.noValue.skipsValueApplication == false, "an explicit no-value must be applied as absent") - expect(LKXcodeViewHierarchyFetchStatus.unchanged.skipsValueApplication, + expect(XcodeViewHierarchyFetchStatus.unchanged.skipsValueApplication, "unchanged must not overwrite an existing value") - expect(LKXcodeViewHierarchyFetchStatus.failed.skipsValueApplication, + expect(XcodeViewHierarchyFetchStatus.failed.skipsValueApplication, "a failed fetch must not overwrite an existing value") - expect(LKXcodeViewHierarchyFetchStatus(rawValue: 4) == .retrieved, "4 is the retrieved status") - expect(LKXcodeViewHierarchyFetchStatus(rawValue: 8) == .unchanged, "8 is the unchanged status") + expect(XcodeViewHierarchyFetchStatus(rawValue: 4) == .retrieved, "4 is the retrieved status") + expect(XcodeViewHierarchyFetchStatus(rawValue: 8) == .unchanged, "8 is the unchanged status") } // MARK: - Helpers - private static func decode(jsonValue: Any?, format: String) -> LKXcodeViewHierarchyValue { + private static func decode(jsonValue: Any?, format: String) -> XcodeViewHierarchyValue { do { - return try LKXcodeViewHierarchyValueDecoder.decoding(jsonValue: jsonValue, format: format) + return try XcodeViewHierarchyValueDecoder.decoding(jsonValue: jsonValue, format: format) } catch { fail("decoding '\(format)' threw: \(error)") } @@ -319,7 +319,7 @@ struct LKXcodeViewHierarchyValueTests { private static func expectFailure(jsonValue: Any?, format: String, _ message: String) { do { - let value = try LKXcodeViewHierarchyValueDecoder.decoding(jsonValue: jsonValue, format: format) + let value = try XcodeViewHierarchyValueDecoder.decoding(jsonValue: jsonValue, format: format) fail("\(message) — but it decoded to \(value)") } catch { // Expected. From bcb255e64cf8c02540337acba59c8edbf61bd355 Mon Sep 17 00:00:00 2001 From: Mx-Iris Date: Fri, 9 Oct 2026 01:07:37 +0800 Subject: [PATCH 3/5] Drop the lk_ / lk / LK prefixes from the host's member and constant names The host's extension members, private helpers and file-level constants lose their prefixes (lk_isDarkMode -> isDarkMode, lkRunOnMain -> runOnMain, LKToolBarIdentifier_Reload -> toolbarIdentifierReload). Where the system or LookinCore already has the same thing, the host uses it: - NSLock's lkLock(_:) is gone; Foundation's withLock(_:) does the same. - NSColor's lk_rgbaComponents() and lk_color(fromRGBAComponents:) were line for line the LookinCore helpers sRGBAComponents() and sRGBColor(fromRGBAComponents:); the host calls those now. - SwiftUISupportActivationState conforms to CustomDebugStringConvertible instead of carrying lkDebugDescription. - lkLayout is frameLayout, lk_button(with:target:action:) is borderlessImageButton(with:target:action:), lk_capitalizedString() is capitalizingFirstLetter(). The number input heights are static members of NumberInputView. The values of persisted or posted strings (toolbar item identifiers, window size names, notification names) are unchanged. Files holding several types lose the prefix too (LKSuggestions.swift -> HitTargetSuggestions.swift), with the project's membershipExceptions and the test scripts following. Co-Authored-By: Claude Opus 5.5 --- LookInside.xcodeproj/project.pbxproj | 24 +++---- LookInside/Base/BaseControl.swift | 4 +- LookInside/Base/BaseView.swift | 16 ++--- LookInside/Base/BaseViewController.swift | 2 +- .../AutoLayoutConstraint+LookinClient.swift | 2 +- .../Category/DisplayItem+LookinClient.swift | 40 +++++------ .../InspectedObject+LookinClient.swift | 4 +- .../Category/NSAppearance+LookinClient.swift | 2 +- .../Base/Category/NSArray+LookinClient.swift | 4 +- .../Base/Category/NSButton+LookinClient.swift | 4 +- .../Base/Category/NSColor+LookinClient.swift | 30 ++------- .../Category/NSControl+LookinClient.swift | 8 +-- .../Base/Category/NSString+LookinClient.swift | 2 +- .../Base/Category/NSView+LookinClient.swift | 8 +-- LookInside/Base/ColorIndicatorLayer.swift | 4 +- LookInside/Base/FrameLayout.swift | 4 +- LookInside/Base/ImageTextView.swift | 4 +- LookInside/Base/NumberInputView.swift | 17 +++-- LookInside/Base/OutlineRowView.swift | 2 +- LookInside/Base/PopPanel.swift | 4 +- LookInside/Base/ProgressIndicatorView.swift | 2 +- LookInside/Base/TableRowView.swift | 8 +-- LookInside/Base/TableView.swift | 10 +-- LookInside/Base/TextControl.swift | 6 +- LookInside/Base/TextFieldView.swift | 12 ++-- LookInside/Base/TextsMenuView.swift | 18 ++--- LookInside/Base/TipsView.swift | 26 ++++---- LookInside/Base/TwoColors.swift | 2 +- LookInside/Base/UserActionManager.swift | 6 +- .../Installer/InstallerCancellation.swift | 6 +- .../Common/Installer/InstallerLogger.swift | 8 --- ...ionErrors.swift => ConnectionErrors.swift} | 2 +- LookInside/Connection/ConnectionManager.swift | 6 +- LookInside/Connection/InspectableApp.swift | 2 +- LookInside/Console/ConsoleDataSource.swift | 2 +- ...leRowViews.swift => ConsoleRowViews.swift} | 4 +- .../ConsoleSelectPopoverController.swift | 2 +- .../ConstraintPopoverController.swift | 6 +- .../DashboardAttributeConstraintsView.swift | 2 +- .../DashboardAttributeColorView.swift | 10 +-- ... => DashboardAttributeGeometryViews.swift} | 2 +- ...ardAttributePrivateDiscriminatorView.swift | 10 +-- ... => DashboardAttributeReadOnlyViews.swift} | 6 +- .../DashboardAttributeStringArrayView.swift | 2 +- ...teViews.swift => JSONAttributeViews.swift} | 2 +- LookInside/Dashboard/DashboardCardView.swift | 2 +- LookInside/Dashboard/DashboardLayout.swift | 4 +- .../Dashboard/DashboardViewController.swift | 2 +- ...Views.swift => DashboardSearchViews.swift} | 4 +- ...odels.swift => GestureCaptureModels.swift} | 0 ...tions.swift => HitTargetSuggestions.swift} | 0 .../Hierarchy/HierarchyDataSource.swift | 28 ++++---- .../Hierarchy/HierarchyFrameLayout.swift | 2 +- LookInside/Hierarchy/HierarchyView.swift | 4 +- LookInside/Launch/LaunchAppView.swift | 2 +- .../MCPBridge/MCPBridgeDetailsService.swift | 2 +- ...BridgeFrame.swift => MCPBridgeFrame.swift} | 2 +- ....swift => MCPBridgeInspectionModels.swift} | 2 +- .../MCPBridgeInvocationService.swift | 10 +-- .../MCPBridgeModificationService.swift | 2 +- .../MCPBridgeScreenshotService.swift | 2 +- LookInside/Manager/AppHelper.swift | 4 +- LookInside/Manager/NavigationManager.swift | 2 +- LookInside/Manager/PreferenceManager.swift | 22 +++---- ...ferenceView.swift => PreferenceView.swift} | 8 +-- .../PreferenceWindowController.swift | 2 +- LookInside/Read/ReadWindowController.swift | 28 ++++---- LookInside/Static/MessageManager.swift | 6 +- .../Static/Preview/DisplayItemNode.swift | 6 +- .../Static/Preview/PreviewController.swift | 6 +- LookInside/Static/Preview/PreviewView.swift | 6 +- .../Static/StaticAsyncUpdateManager.swift | 14 ++-- ...cConstants.swift => StaticConstants.swift} | 16 ++--- .../Static/StaticHierarchyDataSource.swift | 4 +- LookInside/Static/StaticViewController.swift | 4 +- .../Static/StaticWindowController.swift | 56 ++++++++-------- .../SwiftUIHierarchyDisplayMode.swift | 6 +- .../SwiftUISupportGatekeeper.swift | 8 +-- .../MenuPopoverSettingController.swift | 4 +- LookInside/Toolbar/ToolbarRules.swift | 30 ++++----- LookInside/Toolbar/WindowToolbarHelper.swift | 66 +++++++++---------- Scripts/test-gesture-models.sh | 4 +- Scripts/test-mcp-bridge.sh | 4 +- Tests/Read/LaunchToolbarReadTests.swift | 14 ++-- 84 files changed, 354 insertions(+), 381 deletions(-) rename LookInside/Connection/{LKConnectionErrors.swift => ConnectionErrors.swift} (99%) rename LookInside/Console/{LKConsoleRowViews.swift => ConsoleRowViews.swift} (98%) rename LookInside/Dashboard/AttributeView/{LKDashboardAttributeGeometryViews.swift => DashboardAttributeGeometryViews.swift} (99%) rename LookInside/Dashboard/AttributeView/{LKDashboardAttributeReadOnlyViews.swift => DashboardAttributeReadOnlyViews.swift} (98%) rename LookInside/Dashboard/AttributeView/JSON/{LKJSONAttributeViews.swift => JSONAttributeViews.swift} (99%) rename LookInside/Dashboard/Search/{LKDashboardSearchViews.swift => DashboardSearchViews.swift} (98%) rename LookInside/GestureDebug/{LKGestureCaptureModels.swift => GestureCaptureModels.swift} (100%) rename LookInside/GestureDebug/{LKSuggestions.swift => HitTargetSuggestions.swift} (100%) rename LookInside/MCPBridge/{LKMCPBridgeFrame.swift => MCPBridgeFrame.swift} (99%) rename LookInside/MCPBridge/{LKMCPBridgeInspectionModels.swift => MCPBridgeInspectionModels.swift} (99%) rename LookInside/Preference/{LKPreferenceView.swift => PreferenceView.swift} (98%) rename LookInside/Static/{LKStaticConstants.swift => StaticConstants.swift} (56%) diff --git a/LookInside.xcodeproj/project.pbxproj b/LookInside.xcodeproj/project.pbxproj index 979230f2..a69d2698 100644 --- a/LookInside.xcodeproj/project.pbxproj +++ b/LookInside.xcodeproj/project.pbxproj @@ -98,7 +98,7 @@ "Connection/ConnectionManager+License.swift", Connection/AppsManager.swift, Connection/ServerChannel.swift, - Connection/LKConnectionErrors.swift, + Connection/ConnectionErrors.swift, Connection/ConnectionManager.swift, Connection/ConnectionRequest.swift, Connection/InspectableApp.swift, @@ -106,20 +106,20 @@ Connection/LiveDocument.swift, Connection/LiveDocumentController.swift, Console/ConsoleDataSource.swift, - Console/LKConsoleRowViews.swift, + Console/ConsoleRowViews.swift, Console/ConsoleSelectPopoverController.swift, Console/ConsoleViewController.swift, DanceScript/DanceScriptManager.swift, Dashboard/AttributeView/Constraint/ConstraintPopoverController.swift, Dashboard/AttributeView/Constraint/DashboardAttributeConstraintsView.swift, Dashboard/AttributeView/JSON/JSONAttributeItem.swift, - Dashboard/AttributeView/JSON/LKJSONAttributeViews.swift, + Dashboard/AttributeView/JSON/JSONAttributeViews.swift, Dashboard/AttributeView/DashboardAttributeColorView.swift, Dashboard/AttributeView/DashboardAttributeEnumsView.swift, - Dashboard/AttributeView/LKDashboardAttributeGeometryViews.swift, + Dashboard/AttributeView/DashboardAttributeGeometryViews.swift, Dashboard/AttributeView/DashboardAttributeNumberInputView.swift, Dashboard/AttributeView/DashboardAttributePrivateDiscriminatorView.swift, - Dashboard/AttributeView/LKDashboardAttributeReadOnlyViews.swift, + Dashboard/AttributeView/DashboardAttributeReadOnlyViews.swift, Dashboard/AttributeView/DashboardAttributeStringArrayView.swift, Dashboard/AttributeView/DashboardAttributeSwitchView.swift, Dashboard/AttributeView/DashboardAttributeTextView.swift, @@ -132,7 +132,7 @@ Dashboard/DashboardViewController.swift, Dashboard/EnumListRegistry.swift, Dashboard/Search/DashboardHeaderView.swift, - Dashboard/Search/LKDashboardSearchViews.swift, + Dashboard/Search/DashboardSearchViews.swift, DebugE2E/DebugE2EDump.swift, DebugE2E/DebugE2EDumpWriter.swift, DebugE2E/DebugUISnapshots.swift, @@ -149,13 +149,13 @@ Hierarchy/HierarchyRowView.swift, Hierarchy/HierarchyView.swift, Hierarchy/SyncSignal.swift, - GestureDebug/LKGestureCaptureModels.swift, + GestureDebug/GestureCaptureModels.swift, GestureDebug/GestureDebugSession.swift, GestureDebug/GestureDebugView.swift, GestureDebug/GestureDebugWindowController.swift, GestureDebug/GestureNodeDetailView.swift, GestureDebug/NativeInteractionDetailView.swift, - GestureDebug/LKSuggestions.swift, + GestureDebug/HitTargetSuggestions.swift, GestureDebug/HitTargetSuggestionsView.swift, InfoPlist.xcstrings, Injection/Device/AttachedDeviceMonitor.swift, @@ -178,8 +178,8 @@ MCPBridge/MCPBridgeConnection.swift, MCPBridge/MCPBridgeDetailsService.swift, MCPBridge/MCPBridgeEventPublisher.swift, - MCPBridge/LKMCPBridgeFrame.swift, - MCPBridge/LKMCPBridgeInspectionModels.swift, + MCPBridge/MCPBridgeFrame.swift, + MCPBridge/MCPBridgeInspectionModels.swift, MCPBridge/MCPBridgeInspectionService.swift, MCPBridge/MCPBridgeInvocationService.swift, MCPBridge/MCPBridgeListenSocket.swift, @@ -200,7 +200,7 @@ Measure/MeasureController.swift, Measure/MeasureResultView.swift, Other/VersionComparer.swift, - Preference/LKPreferenceView.swift, + Preference/PreferenceView.swift, Preference/PreferenceWindowController.swift, PrivateDiscriminator/PrivateDiscriminatorSettingsWindowController.swift, PrivateDiscriminator/PrivateDiscriminatorStore.swift, @@ -213,7 +213,7 @@ Read/ArchiveDocument.swift, Static/MessageManager.swift, Static/StaticAsyncUpdateManager.swift, - Static/LKStaticConstants.swift, + Static/StaticConstants.swift, Static/StaticHierarchyController.swift, Static/StaticHierarchyDataSource.swift, Static/StaticLayout.swift, diff --git a/LookInside/Base/BaseControl.swift b/LookInside/Base/BaseControl.swift index 548e94b6..c4d13803 100644 --- a/LookInside/Base/BaseControl.swift +++ b/LookInside/Base/BaseControl.swift @@ -66,12 +66,12 @@ class BaseControl: NSControl { private func triggerDidChangeAppearanceBlock() { if let didChangeAppearance { - didChangeAppearance(self, effectiveAppearance.lk_isDarkMode) + didChangeAppearance(self, effectiveAppearance.isDarkMode) } } override func sizeToFit() { - lkLayout.size(bestSize()) + frameLayout.size(bestSize()) } /// 如果子类返回 true,则 mouseEntered: 和 mouseExited: 会被调用。默认为 false diff --git a/LookInside/Base/BaseView.swift b/LookInside/Base/BaseView.swift index cdfccbdc..6c589519 100644 --- a/LookInside/Base/BaseView.swift +++ b/LookInside/Base/BaseView.swift @@ -90,7 +90,7 @@ class BaseView: NSView, NSViewToolTipOwner { effectView.blendingMode = .withinWindow effectView.state = .active backgroundEffectView = effectView - lk_insertSubviewAtBottom(effectView) + insertSubviewAtBottom(effectView) needsLayout = true } else { backgroundEffectView?.removeFromSuperview() @@ -107,7 +107,7 @@ class BaseView: NSView, NSViewToolTipOwner { super.init(frame: frameRect) wantsLayer = true - borderColors = TwoColors(colorInLightMode: .lkBaseRGB(215, 215, 215), colorInDarkMode: .lkBaseRGB(67, 67, 69)) + borderColors = TwoColors(colorInLightMode: .rgb255(215, 215, 215), colorInDarkMode: .rgb255(67, 67, 69)) beginObservingAppearanceIfNeeded() } @@ -142,7 +142,7 @@ class BaseView: NSView, NSViewToolTipOwner { super.layout() if let backgroundEffectView { - backgroundEffectView.lkLayout.fullFrame() + backgroundEffectView.frameLayout.fullFrame() } if tooltipString != nil { @@ -153,13 +153,13 @@ class BaseView: NSView, NSViewToolTipOwner { switch borderPosition { case .top: - customBorderLayer?.lkLayout.fullWidth().height(1).y(0) + customBorderLayer?.frameLayout.fullWidth().height(1).y(0) case .left: - customBorderLayer?.lkLayout.fullHeight().width(1).x(0) + customBorderLayer?.frameLayout.fullHeight().width(1).x(0) case .bottom: - customBorderLayer?.lkLayout.fullFrame().height(1).bottom(0) + customBorderLayer?.frameLayout.fullFrame().height(1).bottom(0) case .right: - customBorderLayer?.lkLayout.fullHeight().width(1).right(0) + customBorderLayer?.frameLayout.fullHeight().width(1).right(0) default: break } @@ -215,7 +215,7 @@ class BaseView: NSView, NSViewToolTipOwner { } func isDarkMode() -> Bool { - effectiveAppearance.lk_isDarkMode + effectiveAppearance.isDarkMode } // MARK: - Subclassing hooks diff --git a/LookInside/Base/BaseViewController.swift b/LookInside/Base/BaseViewController.swift index 235edb7c..873b81cf 100644 --- a/LookInside/Base/BaseViewController.swift +++ b/LookInside/Base/BaseViewController.swift @@ -81,7 +81,7 @@ class BaseViewController: NSViewController { super.viewDidLayout() if let connectionTipsView, connectionTipsView.isVisible { let windowTitleHeight = NavigationManager.shared.windowTitleBarHeight - connectionTipsView.lkLayout.sizeToFit().horAlign().y(windowTitleHeight + 10) + connectionTipsView.frameLayout.sizeToFit().horAlign().y(windowTitleHeight + 10) } } diff --git a/LookInside/Base/Category/AutoLayoutConstraint+LookinClient.swift b/LookInside/Base/Category/AutoLayoutConstraint+LookinClient.swift index c1c8eb29..50ddec89 100644 --- a/LookInside/Base/Category/AutoLayoutConstraint+LookinClient.swift +++ b/LookInside/Base/Category/AutoLayoutConstraint+LookinClient.swift @@ -23,7 +23,7 @@ extension AutoLayoutConstraint { case .view, .layoutGuide: return detailed ? "<\(object?.rawClassName() ?? "(null)"): \(object?.memoryAddress ?? "(null)")>" - : "(\(object?.lk_simpleDemangledClassName() ?? "(null)")*)" + : "(\(object?.simpleDemangledClassName() ?? "(null)")*)" default: assertionFailure("unknown constraint item type \(type.rawValue)") return detailed diff --git a/LookInside/Base/Category/DisplayItem+LookinClient.swift b/LookInside/Base/Category/DisplayItem+LookinClient.swift index 72188223..3174f965 100644 --- a/LookInside/Base/Category/DisplayItem+LookinClient.swift +++ b/LookInside/Base/Category/DisplayItem+LookinClient.swift @@ -21,7 +21,7 @@ extension DisplayItem { } else if let customDisplayTitle, !customDisplayTitle.isEmpty { baseTitle = customDisplayTitle } else { - baseTitle = displayingObject()?.lk_simpleDemangledClassName() + baseTitle = displayingObject()?.simpleDemangledClassName() } return PrivateDiscriminatorStore.shared.displayTitle(for: self, fallback: baseTitle) ?? "" } @@ -32,10 +32,10 @@ extension DisplayItem { if let customInfo { return customInfo.subtitle } - if let windowControllerName = hostWindowControllerObject?.lk_simpleDemangledClassName(), !windowControllerName.isEmpty { + if let windowControllerName = hostWindowControllerObject?.simpleDemangledClassName(), !windowControllerName.isEmpty { return "\(windowControllerName).window" } - if let viewControllerName = hostViewControllerObject?.lk_simpleDemangledClassName(), !viewControllerName.isEmpty { + if let viewControllerName = hostViewControllerObject?.simpleDemangledClassName(), !viewControllerName.isEmpty { return "\(viewControllerName).view" } let representedObject = displayingObject() @@ -78,7 +78,7 @@ extension DisplayItem { // layer oid belongs to the separate BackingLayer child node — // requests keyed by it would land on that node on both ends. The // view node itself must route by its view oid. - if let viewOid = viewObject?.oid, viewOid != 0, lk_ownsSeparateBackingLayerNode() { + if let viewOid = viewObject?.oid, viewOid != 0, ownsSeparateBackingLayerNode() { return viewOid } // Prefer the layer oid, as upstream does: the server's detail @@ -99,7 +99,7 @@ extension DisplayItem { /// layer oid (backing-layer toggle ON); requests for this node must then /// route by the view oid. Read off the tree rather than the preference, /// so it stays false against servers that ignored the toggle. - @objc func lk_ownsSeparateBackingLayerNode() -> Bool { + @objc func ownsSeparateBackingLayerNode() -> Bool { guard let layerOid = layerObject?.oid, layerOid != 0, let viewOid = viewObject?.oid, viewOid != 0 else { return false } @@ -252,7 +252,7 @@ extension DisplayItem { // MARK: - SwiftUI - @objc func lk_isSwiftUISupportRelated() -> Bool { + @objc func isSwiftUISupportRelated() -> Bool { func looksLikeSwiftUISupport(_ object: InspectedObject?) -> Bool { guard let object else { return false } if ClientDisplayText.looksLikeSwiftUISupport(object.rawClassName()) { @@ -270,13 +270,13 @@ extension DisplayItem { /// Addresses of the layers named by "… Backed By" rows in the /// "SwiftUI Layers" group. - @objc func lk_swiftUIBackingLayerMemoryAddresses() -> [String] { + @objc func swiftUIBackingLayerMemoryAddresses() -> [String] { var addresses: [String] = [] for group in allAttributeGroups where group.userCustomTitle == "SwiftUI Layers" { - for attribute in group.lk_allAttributes { + for attribute in group.allAttributes { guard let title = attribute.displayTitle, title.hasSuffix("Backed By"), let value = attribute.value as? String, - let address = Self.lk_memoryAddress(inObjectDescription: value), + let address = Self.memoryAddress(inObjectDescription: value), !addresses.contains(address) else { continue } addresses.append(address) @@ -287,13 +287,13 @@ extension DisplayItem { /// Display-list IDs from "… Display List ID" rows of "SwiftUI Layers" /// and "Identity IDs" rows of "SwiftUI Display List". - @objc func lk_swiftUIBackingDisplayListIDs() -> [NSNumber] { + @objc func swiftUIBackingDisplayListIDs() -> [NSNumber] { var displayListIDs: [UInt64] = [] for group in allAttributeGroups { let isLayersGroup = group.userCustomTitle == "SwiftUI Layers" let isDisplayListGroup = group.userCustomTitle == "SwiftUI Display List" guard isLayersGroup || isDisplayListGroup else { continue } - for attribute in group.lk_allAttributes { + for attribute in group.allAttributes { guard let value = attribute.value as? String else { continue } let title = attribute.displayTitle ?? "" let isLayerDisplayListID = isLayersGroup && title.hasSuffix("Display List ID") @@ -308,10 +308,10 @@ extension DisplayItem { } /// The first "Display List ID" of the "SwiftUI" group, for layer nodes. - @objc func lk_swiftUILayerDisplayListID() -> NSNumber? { + @objc func swiftUILayerDisplayListID() -> NSNumber? { guard layerObject != nil else { return nil } for group in allAttributeGroups where group.userCustomTitle == "SwiftUI" { - for attribute in group.lk_allAttributes { + for attribute in group.allAttributes { guard attribute.displayTitle == "Display List ID", let value = attribute.value as? String else { continue } if let first = ClientDisplayText.swiftUIDisplayListIDs(in: value).first { return NSNumber(value: first) @@ -322,10 +322,10 @@ extension DisplayItem { } /// "Source" and "Full Source" values of the "SwiftUI" group. - @objc func lk_swiftUILayerSourceTypeNames() -> [String] { + @objc func swiftUILayerSourceTypeNames() -> [String] { var sourceNames: [String] = [] for group in allAttributeGroups where group.userCustomTitle == "SwiftUI" { - for attribute in group.lk_allAttributes { + for attribute in group.allAttributes { guard attribute.displayTitle == "Source" || attribute.displayTitle == "Full Source", let value = attribute.value as? String, !sourceNames.contains(value) else { continue } @@ -337,13 +337,13 @@ extension DisplayItem { /// The custom node's title, then "Type" and "Full Type" values of the /// "SwiftUI Type" group. - @objc func lk_swiftUITypeNames() -> [String] { + @objc func swiftUITypeNames() -> [String] { var typeNames: [String] = [] if let customTitle = customInfo?.title { typeNames.append(customTitle) } for group in allAttributeGroups where group.userCustomTitle == "SwiftUI Type" { - for attribute in group.lk_allAttributes { + for attribute in group.allAttributes { guard attribute.displayTitle == "Type" || attribute.displayTitle == "Full Type", let value = attribute.value as? String, !typeNames.contains(value) else { continue } @@ -354,12 +354,12 @@ extension DisplayItem { } @objc(lk_validSwiftUIDisplayListIDsInString:) - static func lk_validSwiftUIDisplayListIDs(in string: String) -> [NSNumber] { + static func validSwiftUIDisplayListIDs(in string: String) -> [NSNumber] { ClientDisplayText.swiftUIDisplayListIDs(in: string).map { NSNumber(value: $0) } } @objc(lk_memoryAddressInObjectDescription:) - static func lk_memoryAddress(inObjectDescription description: String) -> String? { + static func memoryAddress(inObjectDescription description: String) -> String? { ClientDisplayText.memoryAddress(inObjectDescription: description) } @@ -396,7 +396,7 @@ extension DisplayItem { private extension AttributesGroup { /// Every attribute of every section, in order. - var lk_allAttributes: [InspectedAttribute] { + var allAttributes: [InspectedAttribute] { (attrSections ?? []).flatMap { $0.attributes ?? [] } } } diff --git a/LookInside/Base/Category/InspectedObject+LookinClient.swift b/LookInside/Base/Category/InspectedObject+LookinClient.swift index fd4af35e..edce78b3 100644 --- a/LookInside/Base/Category/InspectedObject+LookinClient.swift +++ b/LookInside/Base/Category/InspectedObject+LookinClient.swift @@ -8,13 +8,13 @@ import LookInsideHostCore extension InspectedObject { /// The demangled class name, module prefix included. - @objc func lk_completedDemangledClassName() -> String { + @objc func completedDemangledClassName() -> String { SwiftDemangler.completedParse(input: rawClassName() ?? "") } /// The demangled class name without its module prefix; generic /// arguments keep theirs. - @objc func lk_simpleDemangledClassName() -> String { + @objc func simpleDemangledClassName() -> String { ClientDisplayText.removingModulePrefix(SwiftDemangler.simpleParse(input: rawClassName() ?? "")) } } diff --git a/LookInside/Base/Category/NSAppearance+LookinClient.swift b/LookInside/Base/Category/NSAppearance+LookinClient.swift index c1963bd5..3fb1cf64 100644 --- a/LookInside/Base/Category/NSAppearance+LookinClient.swift +++ b/LookInside/Base/Category/NSAppearance+LookinClient.swift @@ -8,7 +8,7 @@ import AppKit extension NSAppearance { /// Whether this is one of the dark appearances, including the vibrant /// and high-contrast variants. - @objc var lk_isDarkMode: Bool { + @objc var isDarkMode: Bool { [.darkAqua, .vibrantDark, .accessibilityHighContrastDarkAqua, .accessibilityHighContrastVibrantDark].contains(name) } } diff --git a/LookInside/Base/Category/NSArray+LookinClient.swift b/LookInside/Base/Category/NSArray+LookinClient.swift index d5173c0b..6d3ff62b 100644 --- a/LookInside/Base/Category/NSArray+LookinClient.swift +++ b/LookInside/Base/Category/NSArray+LookinClient.swift @@ -7,10 +7,10 @@ import AppKit extension NSArray { /// The views that are not hidden. Every element must be an NSView. - @objc func lk_visibleViews() -> [Any] { + @objc func visibleViews() -> [Any] { filter { object in guard let view = object as? NSView else { - assertionFailure("lk_visibleViews expects views only") + assertionFailure("visibleViews expects views only") return false } return !view.isHidden diff --git a/LookInside/Base/Category/NSButton+LookinClient.swift b/LookInside/Base/Category/NSButton+LookinClient.swift index c46eeb00..c0f03bf2 100644 --- a/LookInside/Base/Category/NSButton+LookinClient.swift +++ b/LookInside/Base/Category/NSButton+LookinClient.swift @@ -8,7 +8,7 @@ import AppKit extension NSButton { /// A rounded push button, already sized 84×40. @objc(lk_normalButtonWithTitle:target:action:) - static func lk_normalButton(withTitle title: String, target: AnyObject?, action: Selector?) -> NSButton { + static func normalButton(withTitle title: String, target: AnyObject?, action: Selector?) -> NSButton { let button = NSButton() button.bezelStyle = .rounded button.title = title @@ -21,7 +21,7 @@ extension NSButton { /// A borderless image-only button; size it yourself. @objc(lk_buttonWithImage:target:action:) - static func lk_button(with image: NSImage?, target: AnyObject?, action: Selector?) -> NSButton { + static func borderlessImageButton(with image: NSImage?, target: AnyObject?, action: Selector?) -> NSButton { let button = NSButton() button.image = image button.bezelStyle = .roundRect diff --git a/LookInside/Base/Category/NSColor+LookinClient.swift b/LookInside/Base/Category/NSColor+LookinClient.swift index e531b885..3a09e779 100644 --- a/LookInside/Base/Category/NSColor+LookinClient.swift +++ b/LookInside/Base/Category/NSColor+LookinClient.swift @@ -8,7 +8,7 @@ import LookInsideHostCore extension NSColor { /// sRGB components in 0...1; zeros when the colour has no sRGB form. - private var lk_sRGBComponents: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) { + private var sRGBComponentValues: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) { var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0 usingColorSpace(.sRGB)?.getRed(&red, green: &green, blue: &blue, alpha: &alpha) return (red, green, blue, alpha) @@ -16,43 +16,21 @@ extension NSColor { /// "(15, 17, 19)" when opaque, "(15, 17, 19, 0.50)" otherwise. @objc func rgbaString() -> String { - let rgba = lk_sRGBComponents + let rgba = sRGBComponentValues return ClientDisplayText.rgbaString(red: rgba.red, green: rgba.green, blue: rgba.blue, alpha: rgba.alpha) } /// "#0f1113" when opaque, "#0f111380" otherwise. @objc func hexString() -> String { - let rgba = lk_sRGBComponents + let rgba = sRGBComponentValues return ClientDisplayText.hexString(red: rgba.red, green: rgba.green, blue: rgba.blue, alpha: rgba.alpha) } - - /// [r, g, b, a] in sRGB. - @objc func lk_rgbaComponents() -> [NSNumber] { - let rgba = lk_sRGBComponents - return [rgba.red, rgba.green, rgba.blue, rgba.alpha].map { NSNumber(value: Double($0)) } - } - - /// The colour for [r, g, b, a]; nil for anything but four numbers. - @objc(lk_colorFromRGBAComponents:) - static func lk_color(fromRGBAComponents components: [NSNumber]?) -> NSColor? { - guard let components else { return nil } - guard components.count == 4 else { - assertionFailure("expected four RGBA components") - return nil - } - return NSColor( - red: components[0].doubleValue, - green: components[1].doubleValue, - blue: components[2].doubleValue, - alpha: components[3].doubleValue - ) - } } extension NSColor { /// `LookinColorMake` / `LookinColorRGBAMake` for Swift: 0...255 /// channels and a 0...1 alpha. - static func lkBaseRGB(_ red: CGFloat, _ green: CGFloat, _ blue: CGFloat, _ alpha: CGFloat = 1) -> NSColor { + static func rgb255(_ red: CGFloat, _ green: CGFloat, _ blue: CGFloat, _ alpha: CGFloat = 1) -> NSColor { NSColor(red: red / 255, green: green / 255, blue: blue / 255, alpha: alpha) } } diff --git a/LookInside/Base/Category/NSControl+LookinClient.swift b/LookInside/Base/Category/NSControl+LookinClient.swift index 583d9fdc..c5e1eadd 100644 --- a/LookInside/Base/Category/NSControl+LookinClient.swift +++ b/LookInside/Base/Category/NSControl+LookinClient.swift @@ -6,7 +6,7 @@ import AppKit extension NSControl { - private static let lk_unlimitedSize = NSSize(width: CGFloat.greatestFiniteMagnitude, height: .greatestFiniteMagnitude) + private static let unlimitedSize = NSSize(width: CGFloat.greatestFiniteMagnitude, height: .greatestFiniteMagnitude) @objc(heightForWidth:) func height(forWidth width: CGFloat) -> CGFloat { @@ -14,14 +14,14 @@ extension NSControl { } @objc func bestHeight() -> CGFloat { - sizeThatFits(Self.lk_unlimitedSize).height + sizeThatFits(Self.unlimitedSize).height } @objc func bestWidth() -> CGFloat { - sizeThatFits(Self.lk_unlimitedSize).width + sizeThatFits(Self.unlimitedSize).width } @objc func bestSize() -> NSSize { - sizeThatFits(Self.lk_unlimitedSize) + sizeThatFits(Self.unlimitedSize) } } diff --git a/LookInside/Base/Category/NSString+LookinClient.swift b/LookInside/Base/Category/NSString+LookinClient.swift index c9f874a3..0917812b 100644 --- a/LookInside/Base/Category/NSString+LookinClient.swift +++ b/LookInside/Base/Category/NSString+LookinClient.swift @@ -8,7 +8,7 @@ import LookInsideHostCore extension NSString { /// The string with its first UTF-16 unit uppercased; nil when empty. - @objc func lk_capitalizedString() -> String? { + @objc func capitalizingFirstLetter() -> String? { guard length > 0 else { return nil } return (substring(to: 1) as NSString).uppercased + substring(from: 1) } diff --git a/LookInside/Base/Category/NSView+LookinClient.swift b/LookInside/Base/Category/NSView+LookinClient.swift index 6a99026d..2e0c633e 100644 --- a/LookInside/Base/Category/NSView+LookinClient.swift +++ b/LookInside/Base/Category/NSView+LookinClient.swift @@ -5,7 +5,7 @@ import AppKit -private var lk_backgroundColorNameKey: UInt8 = 0 +private var backgroundColorNameKey: UInt8 = 0 extension NSView { /// Not hidden and not fully transparent. @@ -17,10 +17,10 @@ extension NSView { /// clears it. @objc var backgroundColorName: String? { get { - objc_getAssociatedObject(self, &lk_backgroundColorNameKey) as? String + objc_getAssociatedObject(self, &backgroundColorNameKey) as? String } set { - objc_setAssociatedObject(self, &lk_backgroundColorNameKey, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC) + objc_setAssociatedObject(self, &backgroundColorNameKey, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC) if let newValue { layer?.backgroundColor = NSColor(named: newValue)?.cgColor } else { @@ -31,7 +31,7 @@ extension NSView { /// Adds `view` below every existing subview. @objc(lk_insertSubviewAtBottom:) - func lk_insertSubviewAtBottom(_ view: NSView) { + func insertSubviewAtBottom(_ view: NSView) { if let first = subviews.first { addSubview(view, positioned: .below, relativeTo: first) } else { diff --git a/LookInside/Base/ColorIndicatorLayer.swift b/LookInside/Base/ColorIndicatorLayer.swift index c03adbdf..2efb9f71 100644 --- a/LookInside/Base/ColorIndicatorLayer.swift +++ b/LookInside/Base/ColorIndicatorLayer.swift @@ -13,7 +13,7 @@ class ColorIndicatorLayer: CALayer { private var imageLayer: CALayer? /// Defaults to black. - @objc var color: NSColor? = .lkBaseRGB(0, 0, 0) { + @objc var color: NSColor? = .rgb255(0, 0, 0) { didSet { updateForColor() } } @@ -57,7 +57,7 @@ class ColorIndicatorLayer: CALayer { } private func contrastColor(for color: NSColor?) -> NSColor { - guard let color else { return .lkBaseRGB(191, 191, 191) } + guard let color else { return .rgb255(191, 191, 191) } var hue: CGFloat = 0, saturation: CGFloat = 0, brightness: CGFloat = 0, alpha: CGFloat = 0 color.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha) let newBrightness = brightness > 0.5 ? brightness - 0.2 : brightness + 0.2 diff --git a/LookInside/Base/FrameLayout.swift b/LookInside/Base/FrameLayout.swift index 489933f3..819f57c6 100644 --- a/LookInside/Base/FrameLayout.swift +++ b/LookInside/Base/FrameLayout.swift @@ -466,14 +466,14 @@ final class FrameLayout: NSObject { extension NSView { /// Frame layout for this view, replacing ShortCocoa's `$(view)`. - var lkLayout: FrameLayout { + var frameLayout: FrameLayout { FrameLayout([self]) } } extension CALayer { /// Frame layout for this layer, replacing ShortCocoa's `$(layer)`. - var lkLayout: FrameLayout { + var frameLayout: FrameLayout { FrameLayout([self]) } } diff --git a/LookInside/Base/ImageTextView.swift b/LookInside/Base/ImageTextView.swift index b3857cd9..765e6ace 100644 --- a/LookInside/Base/ImageTextView.swift +++ b/LookInside/Base/ImageTextView.swift @@ -27,8 +27,8 @@ class ImageTextView: BaseView { override func layout() { super.layout() - imageView.lkLayout.sizeToFit().x(imageMargins.left).verAlign() - label.lkLayout.x(imageView.frame.maxX + imageMargins.right).toRight(0).heightToFit().verAlign() + imageView.frameLayout.sizeToFit().x(imageMargins.left).verAlign() + label.frameLayout.x(imageView.frame.maxX + imageMargins.right).toRight(0).heightToFit().verAlign() } override func sizeThatFits(_: NSSize) -> NSSize { diff --git a/LookInside/Base/NumberInputView.swift b/LookInside/Base/NumberInputView.swift index 09ddba3b..963533d2 100644 --- a/LookInside/Base/NumberInputView.swift +++ b/LookInside/Base/NumberInputView.swift @@ -5,8 +5,11 @@ import AppKit -let LKNumberInputHorizontalHeight: CGFloat = 21 -let LKNumberInputVerticalHeight: CGFloat = 38 +extension NumberInputView { + /// The field's height in the horizontal and the vertical style. + static let horizontalHeight: CGFloat = 21 + static let verticalHeight: CGFloat = 38 +} @objc enum NumberInputViewStyle: UInt { /// The title sits inside the field, on its right. @@ -74,17 +77,17 @@ class NumberInputView: BaseView { override func layout() { super.layout() - textFieldView.lkLayout.fullWidth().height(LKNumberInputHorizontalHeight) + textFieldView.frameLayout.fullWidth().height(NumberInputView.horizontalHeight) switch viewStyle { case .horizontal: - titleLabel.lkLayout.sizeToFit().minWidth(15).verAlign().right(2) + titleLabel.frameLayout.sizeToFit().minWidth(15).verAlign().right(2) var insets = textFieldView.insets insets.right = frame.width - titleLabel.frame.minX + 2 textFieldView.insets = insets case .vertical: // Clamped to the column width, so a title wider than its column // no longer overlaps whatever sits to its left and right. - titleLabel.lkLayout.width(frame.width).heightToFit().x(0).y(textFieldView.frame.maxY + 3) + titleLabel.frameLayout.width(frame.width).heightToFit().x(0).y(textFieldView.frame.maxY + 3) } } @@ -92,9 +95,9 @@ class NumberInputView: BaseView { var size = limitedSize switch viewStyle { case .horizontal: - size.height = LKNumberInputHorizontalHeight + size.height = NumberInputView.horizontalHeight case .vertical: - size.height = LKNumberInputVerticalHeight + size.height = NumberInputView.verticalHeight } return size } diff --git a/LookInside/Base/OutlineRowView.swift b/LookInside/Base/OutlineRowView.swift index c2f0152c..0ce26bff 100644 --- a/LookInside/Base/OutlineRowView.swift +++ b/LookInside/Base/OutlineRowView.swift @@ -95,7 +95,7 @@ class OutlineRowView: TableRowView { HierarchyFrameLayout(subtitleLabel).sizeToFit().x(titleLabel.frame.maxX + subtitleLeft).verAlign() maxX = subtitleLabel.frame.maxX } - for view: NSView in [disclosureButton!, titleLabel!, subtitleLabel!] where view.lkHierarchyIsLaidOutVisible { + for view: NSView in [disclosureButton!, titleLabel!, subtitleLabel!] where view.hierarchyIsLaidOutVisible { HierarchyFrameLayout(view).offsetY(-1) } diff --git a/LookInside/Base/PopPanel.swift b/LookInside/Base/PopPanel.swift index f592724c..a8656817 100644 --- a/LookInside/Base/PopPanel.swift +++ b/LookInside/Base/PopPanel.swift @@ -17,8 +17,8 @@ class PopPanel: NSPanel { contentView.layer?.cornerRadius = 6 contentView.layer?.borderWidth = 1 contentView.didChangeAppearanceBlock = { view, isDarkMode in - view?.backgroundColor = isDarkMode ? .lkBaseRGB(44, 44, 44) : .lkBaseRGB(236, 236, 236) - view?.layer?.borderColor = (isDarkMode ? NSColor.lkBaseRGB(67, 67, 69) : NSColor.lkBaseRGB(215, 215, 215)).cgColor + view?.backgroundColor = isDarkMode ? .rgb255(44, 44, 44) : .rgb255(236, 236, 236) + view?.layer?.borderColor = (isDarkMode ? NSColor.rgb255(67, 67, 69) : NSColor.rgb255(215, 215, 215)).cgColor } self.contentView = contentView backgroundColor = .clear diff --git a/LookInside/Base/ProgressIndicatorView.swift b/LookInside/Base/ProgressIndicatorView.swift index 07fb5c79..282e4d1a 100644 --- a/LookInside/Base/ProgressIndicatorView.swift +++ b/LookInside/Base/ProgressIndicatorView.swift @@ -42,7 +42,7 @@ class ProgressIndicatorView: BaseView { } private func layoutFillLayer() { - fillLayer.lkLayout.x(0).width(frame.width * progress).height(frame.height).y(0) + fillLayer.frameLayout.x(0).width(frame.width * progress).height(frame.height).y(0) } override func animation(forKey key: NSAnimatablePropertyKey) -> Any? { diff --git a/LookInside/Base/TableRowView.swift b/LookInside/Base/TableRowView.swift index 9dba9d99..341a9c3c 100644 --- a/LookInside/Base/TableRowView.swift +++ b/LookInside/Base/TableRowView.swift @@ -84,7 +84,7 @@ class TableRowView: NSTableRowView { addSubview(subtitleLabel) // Through the method, so subclasses see the initial value. - setIsDarkMode(effectiveAppearance.lk_isDarkMode) + setIsDarkMode(effectiveAppearance.isDarkMode) updateBackgroundLayerColor() } @@ -95,7 +95,7 @@ class TableRowView: NSTableRowView { override func layout() { super.layout() - backgroundColorLayer.lkLayout.fullFrame() + backgroundColorLayer.frameLayout.fullFrame() } override var isFlipped: Bool { @@ -104,7 +104,7 @@ class TableRowView: NSTableRowView { override func viewDidChangeEffectiveAppearance() { super.viewDidChangeEffectiveAppearance() - setIsDarkMode(effectiveAppearance.lk_isDarkMode) + setIsDarkMode(effectiveAppearance.isDarkMode) updateBackgroundLayerColor() } @@ -112,7 +112,7 @@ class TableRowView: NSTableRowView { if isRowSelected { backgroundColorLayer.backgroundColor = AppHelper.accentColor().cgColor } else if isHovered { - backgroundColorLayer.backgroundColor = isDarkMode ? NSColor.lkBaseRGB(255, 255, 255, 0.15).cgColor : NSColor.lkBaseRGB(0, 0, 0, 0.1).cgColor + backgroundColorLayer.backgroundColor = isDarkMode ? NSColor.rgb255(255, 255, 255, 0.15).cgColor : NSColor.rgb255(0, 0, 0, 0.1).cgColor } else { backgroundColorLayer.backgroundColor = NSColor.clear.cgColor } diff --git a/LookInside/Base/TableView.swift b/LookInside/Base/TableView.swift index 87bded8b..cfbe76e3 100644 --- a/LookInside/Base/TableView.swift +++ b/LookInside/Base/TableView.swift @@ -215,7 +215,7 @@ class TableView: NSScrollView { // MARK: - Hover and selection - private func lkRowView(at row: Int) -> TableRowView? { + private func tableRowView(at row: Int) -> TableRowView? { guard row >= 0, row < tableView.numberOfRows else { return nil } @@ -223,12 +223,12 @@ class TableView: NSScrollView { } private func hoveredRowDidChange(from previousRow: Int) { - lkRowView(at: previousRow)?.isHovered = false + tableRowView(at: previousRow)?.isHovered = false if hoveredRow >= 0, hoveredRow < tableView.numberOfRows { let canHover = delegate?.tableView?(tableView, shouldSelectRow: hoveredRow) ?? true if canHover { - lkRowView(at: hoveredRow)?.isHovered = true + tableRowView(at: hoveredRow)?.isHovered = true } } delegate?.tableView?(self, didHoverAtRow: hoveredRow) @@ -241,10 +241,10 @@ class TableView: NSScrollView { let previousRow = selectedRow selectedRow = row - lkRowView(at: previousRow)?.isRowSelected = false + tableRowView(at: previousRow)?.isRowSelected = false if row >= 0, row < tableView.numberOfRows { - lkRowView(at: row)?.isRowSelected = true + tableRowView(at: row)?.isRowSelected = true delegate?.tableView?(self, didSelectRow: row) } } diff --git a/LookInside/Base/TextControl.swift b/LookInside/Base/TextControl.swift index eafd003e..f9a51200 100644 --- a/LookInside/Base/TextControl.swift +++ b/LookInside/Base/TextControl.swift @@ -66,12 +66,12 @@ class TextControl: BaseControl { super.layout() var labelMaxX = frame.width - insets.right if let rightImageView { - rightImageView.lkLayout.sizeToFit().verAlign().right(insets.right).offsetY(rightImageOffsetY) + rightImageView.frameLayout.sizeToFit().verAlign().right(insets.right).offsetY(rightImageOffsetY) labelMaxX = rightImageView.frame.minX - spaceBetweenLabelAndImage } - label.lkLayout.x(insets.left).toMaxX(labelMaxX).heightToFit().verAlign() + label.frameLayout.x(insets.left).toMaxX(labelMaxX).heightToFit().verAlign() if insets.top != insets.bottom { - label.lkLayout.offsetY(insets.top - insets.bottom) + label.frameLayout.offsetY(insets.top - insets.bottom) } } diff --git a/LookInside/Base/TextFieldView.swift b/LookInside/Base/TextFieldView.swift index 5c1d15c0..90d5ddbf 100644 --- a/LookInside/Base/TextFieldView.swift +++ b/LookInside/Base/TextFieldView.swift @@ -63,21 +63,21 @@ class TextFieldView: BaseView { if let imageView { if textField.isEditable { // An input, like the hierarchy's filter field. - imageView.lkLayout.sizeToFit().x(insets.left).verAlign().offsetY(1) + imageView.frameLayout.sizeToFit().x(insets.left).verAlign().offsetY(1) if let closeButton { - closeButton.lkLayout.y(1).toBottom(0).width(100).right(insets.right) - textField.lkLayout.x(imageView.frame.maxX + 5).toMaxX(closeButton.frame.minX - 5).heightToFit().verAlign() + closeButton.frameLayout.y(1).toBottom(0).width(100).right(insets.right) + textField.frameLayout.x(imageView.frame.maxX + 5).toMaxX(closeButton.frame.minX - 5).heightToFit().verAlign() } else { - textField.lkLayout.x(imageView.frame.maxX + 5).toRight(insets.right).heightToFit().verAlign() + textField.frameLayout.x(imageView.frame.maxX + 5).toRight(insets.right).heightToFit().verAlign() } } else { // A plain label, like the constraint popover's title. FrameLayout([imageView, textField]).sizeToFit().verAlign() - textField.lkLayout.x(imageView.frame.maxX) + textField.frameLayout.x(imageView.frame.maxX) FrameLayout([imageView, textField]).groupHorAlign() } } else { - textField.lkLayout.x(insets.left).toRight(insets.right).heightToFit().verAlign().offsetY(insets.top - insets.bottom) + textField.frameLayout.x(insets.left).toRight(insets.right).heightToFit().verAlign().offsetY(insets.top - insets.bottom) } } diff --git a/LookInside/Base/TextsMenuView.swift b/LookInside/Base/TextsMenuView.swift index 61f87afc..23b1d7c6 100644 --- a/LookInside/Base/TextsMenuView.swift +++ b/LookInside/Base/TextsMenuView.swift @@ -48,33 +48,33 @@ class TextsMenuView: BaseView { var leftLabelMaxWidth = insets.left for (idx, leftLabel) in visibleLeftLabels.enumerated() { let y = idx > 0 ? visibleLeftLabels[idx - 1].frame.maxY + verSpace : 0 - leftLabel.lkLayout.sizeToFit().y(y) + leftLabel.frameLayout.sizeToFit().y(y) leftLabelMaxWidth = max(leftLabelMaxWidth, leftLabel.frame.width + insets.left) } for (idx, leftLabel) in visibleLeftLabels.enumerated() { - leftLabel.lkLayout.maxX(leftLabelMaxWidth) + leftLabel.frameLayout.maxX(leftLabelMaxWidth) let midY = leftLabel.frame.midY let rightLabel = visibleRightLabels[idx] - rightLabel.lkLayout.x(leftLabelMaxWidth + horSpace).sizeToFit().midY(midY) + rightLabel.frameLayout.x(leftLabelMaxWidth + horSpace).sizeToFit().midY(midY) if let button = buttons[idx] { var x = rightLabel.frame.maxX if !rightLabel.stringValue.isEmpty { x += buttonMarginLeft } - button.lkLayout.sizeToFit().x(x).midY(midY + 1) + button.frameLayout.sizeToFit().x(x).midY(midY + 1) } } } else { for (idx, rightLabel) in visibleRightLabels.enumerated() { let leftLabel = visibleLeftLabels[idx] let y = idx > 0 ? visibleLeftLabels[idx - 1].frame.maxY + verSpace : 0 - leftLabel.lkLayout.sizeToFit().x(0).y(y) + leftLabel.frameLayout.sizeToFit().x(0).y(y) var rightLabelMaxX = frame.width if let button = buttons[idx] { - button.lkLayout.sizeToFit().right(0).midY(leftLabel.frame.midY) + button.frameLayout.sizeToFit().right(0).midY(leftLabel.frame.midY) rightLabelMaxX = button.frame.minX - buttonMarginLeft } - rightLabel.lkLayout.x(leftLabel.frame.maxX + horSpace).toMaxX(rightLabelMaxX).heightToFit().midY(leftLabel.frame.midY) + rightLabel.frameLayout.x(leftLabel.frame.maxX + horSpace).toMaxX(rightLabelMaxX).heightToFit().midY(leftLabel.frame.midY) } } } @@ -155,10 +155,10 @@ class TextsMenuView: BaseView { super.updateColors() let isDarkMode = isDarkMode() for label in leftLabels { - label.textColor = (isDarkMode ? NSColor.lkBaseRGB(216, 220, 228) : NSColor.lkBaseRGB(53, 60, 70)).withAlphaComponent(0.7) + label.textColor = (isDarkMode ? NSColor.rgb255(216, 220, 228) : NSColor.rgb255(53, 60, 70)).withAlphaComponent(0.7) } for label in rightLabels { - label.textColor = isDarkMode ? .lkBaseRGB(250, 251, 252) : .lkBaseRGB(13, 20, 30) + label.textColor = isDarkMode ? .rgb255(250, 251, 252) : .rgb255(13, 20, 30) } } diff --git a/LookInside/Base/TipsView.swift b/LookInside/Base/TipsView.swift index 432067ac..2b137790 100644 --- a/LookInside/Base/TipsView.swift +++ b/LookInside/Base/TipsView.swift @@ -89,20 +89,20 @@ class TipsView: BaseView { var x = insetLeft if !imageView.isHidden { - imageView.lkLayout.size(imageSize).verAlign().x(x) + imageView.frameLayout.size(imageSize).verAlign().x(x) x = imageView.frame.maxX + imageRight } - titleLabel.lkLayout.sizeToFit().verAlign().x(x) + titleLabel.frameLayout.sizeToFit().verAlign().x(x) x = titleLabel.frame.maxX if !sepLayer.isHidden { - sepLayer.lkLayout.width(1).fullHeight().x(x + sepLeft) + sepLayer.frameLayout.width(1).fullHeight().x(x + sepLeft) x = sepLayer.frame.maxX } if !button.isHidden { - button.lkLayout.x(x).toRight(insetRightWithButton).fullHeight() + button.frameLayout.x(x).toRight(insetRightWithButton).fullHeight() } } @@ -127,9 +127,9 @@ class TipsView: BaseView { override func updateColors() { super.updateColors() let isDarkMode = isDarkMode() - backgroundColor = isDarkMode ? .lkBaseRGB(0, 0, 0, 0.8) : .lkBaseRGB(255, 255, 255, 0.9) - titleLabel.textColor = isDarkMode ? .lkBaseRGB(197, 198, 199) : .lkBaseRGB(108, 109, 110) - let borderColor: NSColor = isDarkMode ? .lkBaseRGB(43, 44, 45) : .lkBaseRGB(216, 217, 218) + backgroundColor = isDarkMode ? .rgb255(0, 0, 0, 0.8) : .rgb255(255, 255, 255, 0.9) + titleLabel.textColor = isDarkMode ? .rgb255(197, 198, 199) : .rgb255(108, 109, 110) + let borderColor: NSColor = isDarkMode ? .rgb255(43, 44, 45) : .rgb255(216, 217, 218) layer?.borderColor = borderColor.cgColor sepLayer.backgroundColor = borderColor.cgColor updateButton() @@ -204,7 +204,7 @@ class TipsView: BaseView { /// Subclasses override this to recolour the button text. func buttonTextColor() -> NSColor { - isDarkMode() ? .lkBaseRGB(64, 134, 216) : .lkBaseRGB(74, 145, 228) + isDarkMode() ? .rgb255(64, 134, 216) : .rgb255(74, 145, 228) } } @@ -216,7 +216,7 @@ class YellowTipsView: TipsView { @objc func startAnimation() { guard !isAnimating else { return } let animation = CABasicAnimation(keyPath: "backgroundColor") - if effectiveAppearance.lk_isDarkMode { + if effectiveAppearance.isDarkMode { animation.fromValue = NSColor.systemOrange.withAlphaComponent(0.7).cgColor animation.toValue = NSColor.systemOrange.withAlphaComponent(0.64).cgColor } else { @@ -240,7 +240,7 @@ class YellowTipsView: TipsView { super.updateColors() titleLabel.textColor = .white layer?.borderColor = NSColor.clear.cgColor - sepLayer.backgroundColor = NSColor.lkBaseRGB(255, 255, 255, 0.5).cgColor + sepLayer.backgroundColor = NSColor.rgb255(255, 255, 255, 0.5).cgColor } override func buttonTextColor() -> NSColor { @@ -253,8 +253,8 @@ class YellowTipsView: TipsView { class RedTipsView: TipsView { @objc func startAnimation() { let animation = CABasicAnimation(keyPath: "backgroundColor") - animation.fromValue = NSColor.lkBaseRGB(208, 2, 27, 0.9).cgColor - animation.toValue = NSColor.lkBaseRGB(208, 2, 27, 0.7).cgColor + animation.fromValue = NSColor.rgb255(208, 2, 27, 0.9).cgColor + animation.toValue = NSColor.rgb255(208, 2, 27, 0.7).cgColor animation.duration = 0.8 animation.repeatCount = .infinity animation.autoreverses = true @@ -270,7 +270,7 @@ class RedTipsView: TipsView { super.updateColors() titleLabel.textColor = .white layer?.borderColor = NSColor.clear.cgColor - sepLayer.backgroundColor = NSColor.lkBaseRGB(255, 255, 255, 0.5).cgColor + sepLayer.backgroundColor = NSColor.rgb255(255, 255, 255, 0.5).cgColor } override func buttonTextColor() -> NSColor { diff --git a/LookInside/Base/TwoColors.swift b/LookInside/Base/TwoColors.swift index 0131f3bb..b33e6a90 100644 --- a/LookInside/Base/TwoColors.swift +++ b/LookInside/Base/TwoColors.swift @@ -30,7 +30,7 @@ final class TwoColors: NSObject { /// The dark colour while the app's effective appearance is dark, the /// light one otherwise. @objc var color: NSColor? { - let isDarkMode = NSApp?.effectiveAppearance.lk_isDarkMode ?? false + let isDarkMode = NSApp?.effectiveAppearance.isDarkMode ?? false return isDarkMode ? colorInDarkMode : colorInLightMode } } diff --git a/LookInside/Base/UserActionManager.swift b/LookInside/Base/UserActionManager.swift index f2a15740..77961468 100644 --- a/LookInside/Base/UserActionManager.swift +++ b/LookInside/Base/UserActionManager.swift @@ -18,7 +18,7 @@ import Foundation @objc protocol UserActionManagerDelegate: NSObjectProtocol { /// Called for every `sendAction:`. @objc(LKUserActionManager:didAct:) - func lkUserActionManager(_ manager: UserActionManager, didAct type: UserActionType) + func userActionManager(_ manager: UserActionManager, didAct type: UserActionType) } /// Broadcasts user actions (preview gestures, Dashboard clicks) to weakly @@ -50,9 +50,9 @@ final class UserActionManager: NSObject { return } for case let delegate as UserActionManagerDelegate in delegates.allObjects - where delegate.responds(to: #selector(UserActionManagerDelegate.lkUserActionManager(_:didAct:))) + where delegate.responds(to: #selector(UserActionManagerDelegate.userActionManager(_:didAct:))) { - delegate.lkUserActionManager(self, didAct: type) + delegate.userActionManager(self, didAct: type) } } } diff --git a/LookInside/Common/Installer/InstallerCancellation.swift b/LookInside/Common/Installer/InstallerCancellation.swift index 92963d3a..09711648 100644 --- a/LookInside/Common/Installer/InstallerCancellation.swift +++ b/LookInside/Common/Installer/InstallerCancellation.swift @@ -13,7 +13,7 @@ final class InstallerCancellation { private weak var unzipProcess: Process? var isCancelled: Bool { - lock.lkLock { cancelled } + lock.withLock { cancelled } } func cancel() { @@ -32,7 +32,7 @@ final class InstallerCancellation { } func register(downloadTask task: URLSessionDownloadTask?) { - let shouldCancel = lock.lkLock { + let shouldCancel = lock.withLock { downloadTask = task return cancelled } @@ -42,7 +42,7 @@ final class InstallerCancellation { } func register(unzipProcess process: Process?) { - let shouldCancel = lock.lkLock { + let shouldCancel = lock.withLock { unzipProcess = process return cancelled } diff --git a/LookInside/Common/Installer/InstallerLogger.swift b/LookInside/Common/Installer/InstallerLogger.swift index 13e3b807..976ac101 100644 --- a/LookInside/Common/Installer/InstallerLogger.swift +++ b/LookInside/Common/Installer/InstallerLogger.swift @@ -6,11 +6,3 @@ enum InstallerLogger { private static let subsystem = "com.lookinside.app" } - -extension NSLock { - func lkLock(_ work: () throws -> T) rethrows -> T { - lock() - defer { unlock() } - return try work() - } -} diff --git a/LookInside/Connection/LKConnectionErrors.swift b/LookInside/Connection/ConnectionErrors.swift similarity index 99% rename from LookInside/Connection/LKConnectionErrors.swift rename to LookInside/Connection/ConnectionErrors.swift index 6d591b03..8609476f 100644 --- a/LookInside/Connection/LKConnectionErrors.swift +++ b/LookInside/Connection/ConnectionErrors.swift @@ -1,5 +1,5 @@ // -// LKConnectionErrors.swift +// ConnectionErrors.swift // LookInside // // The NSErrors the Connection layer reports. Swift does not import the diff --git a/LookInside/Connection/ConnectionManager.swift b/LookInside/Connection/ConnectionManager.swift index c42b4b30..70dd0e23 100644 --- a/LookInside/Connection/ConnectionManager.swift +++ b/LookInside/Connection/ConnectionManager.swift @@ -100,14 +100,14 @@ final class ConnectionManager: NSObject { object: nil, queue: nil ) { [weak self] _ in - lkRunOnMain { self?.handleActivationStateDidChange() } + runOnMain { self?.handleActivationStateDidChange() } } center.addObserver( forName: SwiftUISupportGatekeeper.licenseHandshakeAvailabilityDidChangeNotification, object: nil, queue: .main ) { [weak self] _ in - lkRunOnMain { self?.handleLicenseHandshakeAvailabilityDidChange() } + runOnMain { self?.handleLicenseHandshakeAvailabilityDidChange() } } } @@ -581,7 +581,7 @@ extension ConnectionManager: ServerChannelDelegate { /// Runs `body` on the main actor: at once on the main thread, otherwise on /// the next turn of the main queue. -func lkRunOnMain(_ body: @escaping @MainActor () -> Void) { +func runOnMain(_ body: @escaping @MainActor () -> Void) { if Thread.isMainThread { MainActor.assumeIsolated(body) } else { diff --git a/LookInside/Connection/InspectableApp.swift b/LookInside/Connection/InspectableApp.swift index e7b845f9..8e8e60f0 100644 --- a/LookInside/Connection/InspectableApp.swift +++ b/LookInside/Connection/InspectableApp.swift @@ -148,7 +148,7 @@ final class InspectableApp: NSObject { /// 1.0.4), the SwiftUI display mode, and whether to include backing /// layers (old Servers ignore the keys they do not know). static func hierarchyRequestParameters() -> NSDictionary { - let parameters = NSMutableDictionary(dictionary: ["clientVersion": AppHelper.lookinReadableVersion() as NSString]) + let parameters = NSMutableDictionary(dictionary: ["clientVersion": AppHelper.readableVersion() as NSString]) parameters[LookinParam_SwiftUIDisplayMode] = NSNumber(value: SwiftUIHierarchyDisplayModeStore.currentMode().rawValue) parameters["showBackingLayers"] = NSNumber(value: PreferenceManager.shared.showBackingLayers.currentBOOLValue) return parameters diff --git a/LookInside/Console/ConsoleDataSource.swift b/LookInside/Console/ConsoleDataSource.swift index 14afc725..101ba2f4 100644 --- a/LookInside/Console/ConsoleDataSource.swift +++ b/LookInside/Console/ConsoleDataSource.swift @@ -124,7 +124,7 @@ final class ConsoleDataSource { let result = try await inspectableApp.invokeMethod(oid: object.oid, text: text) let returnDescription = result["description"] as? String let returnObject = result["object"] as? InspectedObject - let target = "<\(object.lk_simpleDemangledClassName()): \(object.memoryAddress ?? "(null)")>" + let target = "<\(object.simpleDemangledClassName()): \(object.memoryAddress ?? "(null)")>" var rows = rowItems rows.insert(ConsoleRowItem(kind: .submit, highlightText: target, normalText: text), at: rows.count - 1) diff --git a/LookInside/Console/LKConsoleRowViews.swift b/LookInside/Console/ConsoleRowViews.swift similarity index 98% rename from LookInside/Console/LKConsoleRowViews.swift rename to LookInside/Console/ConsoleRowViews.swift index c3257490..522644f4 100644 --- a/LookInside/Console/LKConsoleRowViews.swift +++ b/LookInside/Console/ConsoleRowViews.swift @@ -1,5 +1,5 @@ // -// LKConsoleRowViews.swift +// ConsoleRowViews.swift // LookInside // // The Console transcript rows: the input row (target picker and text @@ -103,7 +103,7 @@ final class ConsoleInputRowView: TableRowView, InputSearchViewDelegate { let color = lkpConsoleTargetColor(isDarkMode: isDarkMode) let title: String if let object = dataSource.currentObject { - title = "<\(object.lk_simpleDemangledClassName()): \(object.memoryAddress ?? "(null)")>" + title = "<\(object.simpleDemangledClassName()): \(object.memoryAddress ?? "(null)")>" inputView.textField.isEditable = true inputView.textField.placeholderString = NSLocalizedString("Type property or method name here", comment: "") } else { diff --git a/LookInside/Console/ConsoleSelectPopoverController.swift b/LookInside/Console/ConsoleSelectPopoverController.swift index 773caa23..2e9cefdf 100644 --- a/LookInside/Console/ConsoleSelectPopoverController.swift +++ b/LookInside/Console/ConsoleSelectPopoverController.swift @@ -169,7 +169,7 @@ final class ConsoleSelectPopoverController: BaseViewController { } private static func title(of object: InspectedObject) -> String { - "<\(object.lk_simpleDemangledClassName()): \(object.memoryAddress ?? "(null)")>" + "<\(object.simpleDemangledClassName()): \(object.memoryAddress ?? "(null)")>" } /// Keeps the first `count` controls, adds new ones as needed, removes the diff --git a/LookInside/Dashboard/AttributeView/Constraint/ConstraintPopoverController.swift b/LookInside/Dashboard/AttributeView/Constraint/ConstraintPopoverController.swift index e431b075..3fc028d6 100644 --- a/LookInside/Dashboard/AttributeView/Constraint/ConstraintPopoverController.swift +++ b/LookInside/Dashboard/AttributeView/Constraint/ConstraintPopoverController.swift @@ -53,10 +53,10 @@ final class ConstraintPopoverController: BaseViewController { } let texts = [ tuple("FirstItem", AutoLayoutConstraint.description(withItemObject: constraint.firstItem, type: constraint.firstItemType, detailed: true)), - tuple("FirstAttribute", (AutoLayoutConstraint.description(withAttributeInt: constraint.firstAttribute) as NSString).lk_capitalizedString()), + tuple("FirstAttribute", (AutoLayoutConstraint.description(withAttributeInt: constraint.firstAttribute) as NSString).capitalizingFirstLetter()), tuple("Relation", AutoLayoutConstraint.description(with: constraint.relation)), tuple("SecondItem", AutoLayoutConstraint.description(withItemObject: constraint.secondItem, type: constraint.secondItemType, detailed: true)), - tuple("SecondAttribute", (AutoLayoutConstraint.description(withAttributeInt: constraint.secondAttribute) as NSString).lk_capitalizedString()), + tuple("SecondAttribute", (AutoLayoutConstraint.description(withAttributeInt: constraint.secondAttribute) as NSString).capitalizingFirstLetter()), tuple("Multiplier", "\(NSNumber(value: Double(constraint.multiplier)))"), tuple("Constant", "\(NSNumber(value: Double(constraint.constant)))"), tuple("Priority", "\(NSNumber(value: Double(constraint.priority)))"), @@ -99,7 +99,7 @@ final class ConstraintPopoverController: BaseViewController { } private func jumpButton(for jumpObject: InspectedObject, canJumpToObject: ((InspectedObject) -> Bool)?) -> NSButton { - let button = NSButton.lk_button(with: DashboardStyle.image("Icon_JumpDisclosure"), target: self, action: #selector(handleJumpButton(_:))) + let button = NSButton.borderlessImageButton(with: DashboardStyle.image("Icon_JumpDisclosure"), target: self, action: #selector(handleJumpButton(_:))) jumpObjects[ObjectIdentifier(button)] = jumpObject if let canJumpToObject, !canJumpToObject(jumpObject) { button.isEnabled = false diff --git a/LookInside/Dashboard/AttributeView/Constraint/DashboardAttributeConstraintsView.swift b/LookInside/Dashboard/AttributeView/Constraint/DashboardAttributeConstraintsView.swift index 0d04ed04..b7debfa7 100644 --- a/LookInside/Dashboard/AttributeView/Constraint/DashboardAttributeConstraintsView.swift +++ b/LookInside/Dashboard/AttributeView/Constraint/DashboardAttributeConstraintsView.swift @@ -34,7 +34,7 @@ final class DashboardAttributeConstraintsItemControl: TextControl { private func updateLabelColor() { if constraint?.effective == true { label.textColor = .labelColor - } else if effectiveAppearance.lk_isDarkMode { + } else if effectiveAppearance.isDarkMode { label.textColor = DashboardStyle.rgb(130, 131, 132) } else { label.textColor = DashboardStyle.rgb(150, 151, 152) diff --git a/LookInside/Dashboard/AttributeView/DashboardAttributeColorView.swift b/LookInside/Dashboard/AttributeView/DashboardAttributeColorView.swift index 4c74c9f9..50dd30f2 100644 --- a/LookInside/Dashboard/AttributeView/DashboardAttributeColorView.swift +++ b/LookInside/Dashboard/AttributeView/DashboardAttributeColorView.swift @@ -58,7 +58,7 @@ final class DashboardAttributeColorView: DashboardAttributeView, NSMenuDelegate // Re-render when the user switches between hex and RGBA. rgbaFormatObservation = PreferenceManager.shared.observe(\.rgbaFormat, options: [.new]) { [weak self] _, _ in - lkRunOnMain { self?.renderWithAttribute() } + runOnMain { self?.renderWithAttribute() } } } @@ -80,7 +80,7 @@ final class DashboardAttributeColorView: DashboardAttributeView, NSMenuDelegate override func renderWithAttribute() { iconImageView.isHidden = !canEdit() - let color = NSColor.lk_color(fromRGBAComponents: attribute?.value as? [NSNumber]) + let color = NSColor.sRGBColor(fromRGBAComponents: attribute?.value as? [NSNumber]) indicatorLayer.color = color if let color { @@ -164,7 +164,7 @@ final class DashboardAttributeColorView: DashboardAttributeView, NSMenuDelegate let currentValue = attribute?.value as? NSObject let isCurrent: Bool if let color { - isCurrent = currentValue?.isEqual(color.lk_rgbaComponents()) ?? false + isCurrent = currentValue?.isEqual(color.sRGBAComponents()) ?? false } else { // Both nil: the item for "no colour" while the value is nil. isCurrent = currentValue == nil @@ -177,7 +177,7 @@ final class DashboardAttributeColorView: DashboardAttributeView, NSMenuDelegate } @objc private func handleCustomColorMenuItem() { - let initialColor = NSColor.lk_color(fromRGBAComponents: attribute?.value as? [NSNumber]) + let initialColor = NSColor.sRGBColor(fromRGBAComponents: attribute?.value as? [NSNumber]) let panel = NSColorPanel.shared panel.showsAlpha = true panel.isContinuous = false @@ -199,7 +199,7 @@ final class DashboardAttributeColorView: DashboardAttributeView, NSMenuDelegate } private func modify(to targetColor: NSColor?) { - let expectedValue = targetColor?.lk_rgbaComponents() + let expectedValue = targetColor?.sRGBAComponents() if let currentValue = attribute?.value as? NSObject, let expectedValue, currentValue.isEqual(expectedValue) { NSLog("修改没有变化,不做任何提交") return diff --git a/LookInside/Dashboard/AttributeView/LKDashboardAttributeGeometryViews.swift b/LookInside/Dashboard/AttributeView/DashboardAttributeGeometryViews.swift similarity index 99% rename from LookInside/Dashboard/AttributeView/LKDashboardAttributeGeometryViews.swift rename to LookInside/Dashboard/AttributeView/DashboardAttributeGeometryViews.swift index 48897db1..a2dc1d5c 100644 --- a/LookInside/Dashboard/AttributeView/LKDashboardAttributeGeometryViews.swift +++ b/LookInside/Dashboard/AttributeView/DashboardAttributeGeometryViews.swift @@ -1,5 +1,5 @@ // -// LKDashboardAttributeGeometryViews.swift +// DashboardAttributeGeometryViews.swift // LookInside // // Created by Li Kai on 2019/6/10. diff --git a/LookInside/Dashboard/AttributeView/DashboardAttributePrivateDiscriminatorView.swift b/LookInside/Dashboard/AttributeView/DashboardAttributePrivateDiscriminatorView.swift index 0a9d7f00..05e3e9db 100644 --- a/LookInside/Dashboard/AttributeView/DashboardAttributePrivateDiscriminatorView.swift +++ b/LookInside/Dashboard/AttributeView/DashboardAttributePrivateDiscriminatorView.swift @@ -129,13 +129,13 @@ final class DashboardAttributePrivateDiscriminatorView: DashboardAttributeView { messageLabel.maximumNumberOfLines = 0 messageLabel.lineBreakMode = .byWordWrapping - importButton = NSButton.lk_normalButton(withTitle: NSLocalizedString("Import from your codebase", comment: ""), target: self, action: #selector(handleImportButton(_:))) + importButton = NSButton.normalButton(withTitle: NSLocalizedString("Import from your codebase", comment: ""), target: self, action: #selector(handleImportButton(_:))) importButton.font = DashboardStyle.font(12) - guessButton = NSButton.lk_normalButton(withTitle: NSLocalizedString("Guess by swift-pd-guess", comment: ""), target: self, action: #selector(handleGuessButton(_:))) + guessButton = NSButton.normalButton(withTitle: NSLocalizedString("Guess by swift-pd-guess", comment: ""), target: self, action: #selector(handleGuessButton(_:))) guessButton.font = DashboardStyle.font(12) - cancelButton = NSButton.lk_normalButton(withTitle: NSLocalizedString("Cancel", comment: ""), target: self, action: #selector(handleCancelButton(_:))) + cancelButton = NSButton.normalButton(withTitle: NSLocalizedString("Cancel", comment: ""), target: self, action: #selector(handleCancelButton(_:))) cancelButton.font = DashboardStyle.font(12) toastView.layer?.cornerRadius = DashboardMetrics.cardControlCornerRadius @@ -164,7 +164,7 @@ final class DashboardAttributePrivateDiscriminatorView: DashboardAttributeView { updateColors() stateObserver = NotificationCenter.default.addObserver(forName: Self.dashboardStateDidChangeNotification, object: nil, queue: nil) { [weak self] _ in - lkRunOnMain { self?.dashboardViewController?.reloadCurrentDisplayItem() } + runOnMain { self?.dashboardViewController?.reloadCurrentDisplayItem() } } } @@ -456,7 +456,7 @@ final class DashboardAttributePrivateDiscriminatorView: DashboardAttributeView { private func makeCopyButton() -> NSButton { let image = NSImage(systemSymbolName: "doc.on.doc", accessibilityDescription: NSLocalizedString("Copy", comment: "")) - let button = NSButton.lk_button(with: image ?? NSImage(), target: self, action: #selector(handleCopyButton(_:))) + let button = NSButton.borderlessImageButton(with: image ?? NSImage(), target: self, action: #selector(handleCopyButton(_:))) button.imagePosition = .imageOnly button.toolTip = NSLocalizedString("Copy", comment: "") image?.isTemplate = true diff --git a/LookInside/Dashboard/AttributeView/LKDashboardAttributeReadOnlyViews.swift b/LookInside/Dashboard/AttributeView/DashboardAttributeReadOnlyViews.swift similarity index 98% rename from LookInside/Dashboard/AttributeView/LKDashboardAttributeReadOnlyViews.swift rename to LookInside/Dashboard/AttributeView/DashboardAttributeReadOnlyViews.swift index 92653c1e..cd467a0b 100644 --- a/LookInside/Dashboard/AttributeView/LKDashboardAttributeReadOnlyViews.swift +++ b/LookInside/Dashboard/AttributeView/DashboardAttributeReadOnlyViews.swift @@ -1,5 +1,5 @@ // -// LKDashboardAttributeReadOnlyViews.swift +// DashboardAttributeReadOnlyViews.swift // LookInside // // Created by Li Kai on 2019/6/12. @@ -94,7 +94,7 @@ final class DashboardAttributeShadowView: DashboardAttributeView { // Re-render when the user switches between hex and RGBA. rgbaFormatObservation = PreferenceManager.shared.observe(\.rgbaFormat, options: [.new]) { [weak self] _, _ in - lkRunOnMain { self?.renderWithAttribute() } + runOnMain { self?.renderWithAttribute() } } } @@ -134,7 +134,7 @@ final class DashboardAttributeShadowView: DashboardAttributeView { return } // The colour may be nil. - let color = NSColor.lk_color(fromRGBAComponents: info["color"] as? [NSNumber]) + let color = NSColor.sRGBColor(fromRGBAComponents: info["color"] as? [NSNumber]) let offset = offsetValue.sizeValue colorIndicatorLayer.color = color diff --git a/LookInside/Dashboard/AttributeView/DashboardAttributeStringArrayView.swift b/LookInside/Dashboard/AttributeView/DashboardAttributeStringArrayView.swift index fb776393..70da4bf2 100644 --- a/LookInside/Dashboard/AttributeView/DashboardAttributeStringArrayView.swift +++ b/LookInside/Dashboard/AttributeView/DashboardAttributeStringArrayView.swift @@ -117,7 +117,7 @@ class DashboardAttributeStringArrayView: DashboardAttributeView { if let danceButton { return danceButton } - let button = NSButton.lk_normalButton(withTitle: "", target: self, action: #selector(handleDanceButton)) + let button = NSButton.normalButton(withTitle: "", target: self, action: #selector(handleDanceButton)) button.font = DashboardStyle.font(12) addSubview(button) danceButton = button diff --git a/LookInside/Dashboard/AttributeView/JSON/LKJSONAttributeViews.swift b/LookInside/Dashboard/AttributeView/JSON/JSONAttributeViews.swift similarity index 99% rename from LookInside/Dashboard/AttributeView/JSON/LKJSONAttributeViews.swift rename to LookInside/Dashboard/AttributeView/JSON/JSONAttributeViews.swift index 9c90cd36..d7749a32 100644 --- a/LookInside/Dashboard/AttributeView/JSON/LKJSONAttributeViews.swift +++ b/LookInside/Dashboard/AttributeView/JSON/JSONAttributeViews.swift @@ -1,5 +1,5 @@ // -// LKJSONAttributeViews.swift +// JSONAttributeViews.swift // LookInside // // Created by likai.123 on 2023/11/30. diff --git a/LookInside/Dashboard/DashboardCardView.swift b/LookInside/Dashboard/DashboardCardView.swift index c11c8a95..8a69669f 100644 --- a/LookInside/Dashboard/DashboardCardView.swift +++ b/LookInside/Dashboard/DashboardCardView.swift @@ -404,7 +404,7 @@ final class DashboardCardView: BaseView, UserActionManagerDelegate, DashboardAcc // MARK: - UserActionManagerDelegate - func lkUserActionManager(_: UserActionManager, didAct type: UserActionType) { + func userActionManager(_: UserActionManager, didAct type: UserActionType) { guard let accessoryWindowController else { return } guard [.previewOperation, .dashboardClick, .selectedItemChange].contains(type) else { return } accessoryWindowController.close() diff --git a/LookInside/Dashboard/DashboardLayout.swift b/LookInside/Dashboard/DashboardLayout.swift index d0d824d6..8184de17 100644 --- a/LookInside/Dashboard/DashboardLayout.swift +++ b/LookInside/Dashboard/DashboardLayout.swift @@ -325,8 +325,8 @@ enum DashboardMetrics { static let cardCornerRadius = DashboardCardCornerRadius static let searchCardInset = DashboardSearchCardInset - static let numberInputHorizontalHeight = LKNumberInputHorizontalHeight - static let numberInputVerticalHeight = LKNumberInputVerticalHeight + static let numberInputHorizontalHeight = NumberInputView.horizontalHeight + static let numberInputVerticalHeight = NumberInputView.verticalHeight static let maxSize = NSSize(width: CGFloat.greatestFiniteMagnitude, height: .greatestFiniteMagnitude) } diff --git a/LookInside/Dashboard/DashboardViewController.swift b/LookInside/Dashboard/DashboardViewController.swift index 26ca0603..65996565 100644 --- a/LookInside/Dashboard/DashboardViewController.swift +++ b/LookInside/Dashboard/DashboardViewController.swift @@ -294,7 +294,7 @@ final class DashboardViewController: BaseViewController, DashboardCardViewDelega private func modifyInbuiltAttribute(_ attribute: InspectedAttribute, newValue: Any?) async throws { let modifyingItem = attribute.targetDisplayItem - guard let modification = DashboardModification.inbuilt(attribute: attribute, newValue: newValue, clientReadableVersion: AppHelper.lookinReadableVersion()) else { + guard let modification = DashboardModification.inbuilt(attribute: attribute, newValue: newValue, clientReadableVersion: AppHelper.readableVersion()) else { assertionFailure() throw failModification(ConnectionError.inner) } diff --git a/LookInside/Dashboard/Search/LKDashboardSearchViews.swift b/LookInside/Dashboard/Search/DashboardSearchViews.swift similarity index 98% rename from LookInside/Dashboard/Search/LKDashboardSearchViews.swift rename to LookInside/Dashboard/Search/DashboardSearchViews.swift index 6f2443b3..7f27b179 100644 --- a/LookInside/Dashboard/Search/LKDashboardSearchViews.swift +++ b/LookInside/Dashboard/Search/DashboardSearchViews.swift @@ -1,5 +1,5 @@ // -// LKDashboardSearchViews.swift +// DashboardSearchViews.swift // LookInside // // Created by Li Kai on 2019/9/5. @@ -147,7 +147,7 @@ final class DashboardSearchPropertyView: DashboardSearchCardView { return EnumListRegistry.shared.desc(forEnumName: enumListName, value: enumValue) ?? "" case .uiColor: - guard let color = NSColor.lk_color(fromRGBAComponents: attribute.value as? [NSNumber]) else { + guard let color = NSColor.sRGBColor(fromRGBAComponents: attribute.value as? [NSNumber]) else { return "nil" } return PreferenceManager.shared.rgbaFormat ? color.rgbaString() : color.hexString() diff --git a/LookInside/GestureDebug/LKGestureCaptureModels.swift b/LookInside/GestureDebug/GestureCaptureModels.swift similarity index 100% rename from LookInside/GestureDebug/LKGestureCaptureModels.swift rename to LookInside/GestureDebug/GestureCaptureModels.swift diff --git a/LookInside/GestureDebug/LKSuggestions.swift b/LookInside/GestureDebug/HitTargetSuggestions.swift similarity index 100% rename from LookInside/GestureDebug/LKSuggestions.swift rename to LookInside/GestureDebug/HitTargetSuggestions.swift diff --git a/LookInside/Hierarchy/HierarchyDataSource.swift b/LookInside/Hierarchy/HierarchyDataSource.swift index 68f5d13c..08213dfa 100644 --- a/LookInside/Hierarchy/HierarchyDataSource.swift +++ b/LookInside/Hierarchy/HierarchyDataSource.swift @@ -74,7 +74,7 @@ private func swiftUINode(_ item: DisplayItem, matchesSourceTypes sourceTypes: [S guard !sourceTypes.isEmpty else { return true } - let itemTypes = item.lk_swiftUITypeNames() + let itemTypes = item.swiftUITypeNames() return sourceTypes.contains { itemTypes.contains($0) } } @@ -280,7 +280,7 @@ class HierarchyDataSource: NSObject { node.doNotFetchScreenshotReason = .doNotFetchScreenshotForUserConfig } } - if !serverSideIsSwiftProject, item.displayingObject()?.lk_completedDemangledClassName().contains(".") == true { + if !serverSideIsSwiftProject, item.displayingObject()?.completedDemangledClassName().contains(".") == true { storedServerSideIsSwiftProject = true } if let source = item.customInfo?.danceuiSource, !source.isEmpty { @@ -896,10 +896,10 @@ class HierarchyDataSource: NSObject { result.append(candidate) } } - for address in item.lk_swiftUIBackingLayerMemoryAddresses() { + for address in item.swiftUIBackingLayerMemoryAddresses() { add(layerItem(withMemoryAddress: address)) } - for displayListID in item.lk_swiftUIBackingDisplayListIDs() { + for displayListID in item.swiftUIBackingDisplayListIDs() { add(layerItem(withDisplayListID: displayListID)) } return result @@ -908,7 +908,7 @@ class HierarchyDataSource: NSObject { /// CALayer node -> its SwiftUI node, or nil. @objc(swiftUISourceItemForLayerItem:) func swiftUISourceItem(forLayerItem item: DisplayItem!) -> DisplayItem! { - guard let item, let displayListID = item.lk_swiftUILayerDisplayListID() else { + guard let item, let displayListID = item.swiftUILayerDisplayListID() else { return nil } return swiftUIItem(withDisplayListID: displayListID) ?? swiftUIItemForLayerItemByFrameAndSource(item) @@ -923,15 +923,15 @@ class HierarchyDataSource: NSObject { } let title = attribute.displayTitle ?? "" let sourceIsSwiftUI = sourceItem.customInfo?.isSwiftUI == true - || !sourceItem.lk_swiftUIBackingDisplayListIDs().isEmpty - || !sourceItem.lk_swiftUIBackingLayerMemoryAddresses().isEmpty + || !sourceItem.swiftUIBackingDisplayListIDs().isEmpty + || !sourceItem.swiftUIBackingLayerMemoryAddresses().isEmpty if sourceIsSwiftUI { if title.hasSuffix("Backed By") { - return layerItem(withMemoryAddress: DisplayItem.lk_memoryAddress(inObjectDescription: value)) + return layerItem(withMemoryAddress: DisplayItem.memoryAddress(inObjectDescription: value)) } if title.hasSuffix("Display List ID") || title == "Identity IDs" { - for displayListID in DisplayItem.lk_validSwiftUIDisplayListIDs(in: value) { + for displayListID in DisplayItem.validSwiftUIDisplayListIDs(in: value) { if let target = layerItem(withDisplayListID: displayListID) { return target } @@ -945,8 +945,8 @@ class HierarchyDataSource: NSObject { } if sourceItem.layerObject != nil, title == "Display List ID" { - let displayListID = DisplayItem.lk_validSwiftUIDisplayListIDs(in: value).first - ?? sourceItem.lk_swiftUILayerDisplayListID() + let displayListID = DisplayItem.validSwiftUIDisplayListIDs(in: value).first + ?? sourceItem.swiftUILayerDisplayListID() return swiftUIItem(withDisplayListID: displayListID) ?? swiftUIItemForLayerItemByFrameAndSource(sourceItem) } return nil @@ -965,7 +965,7 @@ class HierarchyDataSource: NSObject { return nil } return (rawFlatItems ?? []).first { item in - item.layerObject != nil && item.lk_swiftUILayerDisplayListID()?.isEqual(to: displayListID) == true + item.layerObject != nil && item.swiftUILayerDisplayListID()?.isEqual(to: displayListID) == true } } @@ -975,7 +975,7 @@ class HierarchyDataSource: NSObject { return nil } var result: DisplayItem? - for item in rawFlatItems ?? [] where item.lk_swiftUIBackingDisplayListIDs().contains(displayListID) { + for item in rawFlatItems ?? [] where item.swiftUIBackingDisplayListIDs().contains(displayListID) { if result == nil || item.indentLevel() > result!.indentLevel() { result = item } @@ -989,7 +989,7 @@ class HierarchyDataSource: NSObject { return nil } let layerFrame = layerItem.calculateFrameToRoot() - let sourceTypes = layerItem.lk_swiftUILayerSourceTypeNames() + let sourceTypes = layerItem.swiftUILayerSourceTypeNames() var result: DisplayItem? for item in rawFlatItems ?? [] { guard item.customInfo?.isSwiftUI == true, item.hasValidFrameToRoot() else { diff --git a/LookInside/Hierarchy/HierarchyFrameLayout.swift b/LookInside/Hierarchy/HierarchyFrameLayout.swift index 487f0261..5c9e3222 100644 --- a/LookInside/Hierarchy/HierarchyFrameLayout.swift +++ b/LookInside/Hierarchy/HierarchyFrameLayout.swift @@ -257,7 +257,7 @@ struct HierarchyFrameLayout { extension NSView { /// ShortCocoa's visibility test for layout: shown, in a superview and /// not transparent. - var lkHierarchyIsLaidOutVisible: Bool { + var hierarchyIsLaidOutVisible: Bool { !isHidden && superview != nil && alphaValue >= 0.01 } } diff --git a/LookInside/Hierarchy/HierarchyView.swift b/LookInside/Hierarchy/HierarchyView.swift index 399dacb1..a8398424 100644 --- a/LookInside/Hierarchy/HierarchyView.swift +++ b/LookInside/Hierarchy/HierarchyView.swift @@ -549,10 +549,10 @@ extension HierarchyView: NSMenuDelegate { if !((title.hasPrefix("UI") || title.hasPrefix("CA")) && (title as NSString).length < 10) { stringsToCopy.append(title) } - if let name = displayItem.hostViewControllerObject?.lk_simpleDemangledClassName(), !name.isEmpty { + if let name = displayItem.hostViewControllerObject?.simpleDemangledClassName(), !name.isEmpty { stringsToCopy.append(name) } - if let name = displayItem.hostWindowControllerObject?.lk_simpleDemangledClassName(), !name.isEmpty { + if let name = displayItem.hostWindowControllerObject?.simpleDemangledClassName(), !name.isEmpty { stringsToCopy.append(name) } let ivarTraces = displayItem.displayingObject()?.ivarTraces ?? [] diff --git a/LookInside/Launch/LaunchAppView.swift b/LookInside/Launch/LaunchAppView.swift index 11767385..13512763 100644 --- a/LookInside/Launch/LaunchAppView.swift +++ b/LookInside/Launch/LaunchAppView.swift @@ -193,7 +193,7 @@ final class LaunchAppView: BaseControl { override func updateLayer() { super.updateLayer() - let isDarkMode = effectiveAppearance.lk_isDarkMode + let isDarkMode = effectiveAppearance.isDarkMode hoverBgLayer.backgroundColor = NSColor(red: 0, green: 0, blue: 0, alpha: isDarkMode ? 0.17 : 0.08).cgColor if hasServerVersionError { layer?.backgroundColor = NSColor(red: 0, green: 0, blue: 0, alpha: isDarkMode ? 0.13 : 0.05).cgColor diff --git a/LookInside/MCPBridge/MCPBridgeDetailsService.swift b/LookInside/MCPBridge/MCPBridgeDetailsService.swift index 1b0c0db4..4dacf646 100644 --- a/LookInside/MCPBridge/MCPBridgeDetailsService.swift +++ b/LookInside/MCPBridge/MCPBridgeDetailsService.swift @@ -162,7 +162,7 @@ final class MCPBridgeDetailsService { // Build the RPC 203 task package. Single package — we already // cap the batch at 100 entries, so the host inspector's own // pixel/count packing thresholds never need to come into play. - let clientReadableVersion = AppHelper.lookinReadableVersion() + let clientReadableVersion = AppHelper.readableVersion() let tasks = resolvedItems.map { resolved -> StaticAsyncUpdateTask in let task = StaticAsyncUpdateTask() task.oid = resolved.nativeOid diff --git a/LookInside/MCPBridge/LKMCPBridgeFrame.swift b/LookInside/MCPBridge/MCPBridgeFrame.swift similarity index 99% rename from LookInside/MCPBridge/LKMCPBridgeFrame.swift rename to LookInside/MCPBridge/MCPBridgeFrame.swift index 4e8a2ade..7cfe985e 100644 --- a/LookInside/MCPBridge/LKMCPBridgeFrame.swift +++ b/LookInside/MCPBridge/MCPBridgeFrame.swift @@ -1,4 +1,4 @@ -// LKMCPBridgeFrame.swift +// MCPBridgeFrame.swift // // Newline-delimited JSON wire frames spoken on the MCPBridge Unix domain socket. // diff --git a/LookInside/MCPBridge/LKMCPBridgeInspectionModels.swift b/LookInside/MCPBridge/MCPBridgeInspectionModels.swift similarity index 99% rename from LookInside/MCPBridge/LKMCPBridgeInspectionModels.swift rename to LookInside/MCPBridge/MCPBridgeInspectionModels.swift index 844d8c19..aa2fabb7 100644 --- a/LookInside/MCPBridge/LKMCPBridgeInspectionModels.swift +++ b/LookInside/MCPBridge/MCPBridgeInspectionModels.swift @@ -1,4 +1,4 @@ -// LKMCPBridgeInspectionModels.swift +// MCPBridgeInspectionModels.swift // // Codable DTOs returned in MCPBridge response frames. These are deliberately // flat, JSON-friendly value types so the wire format stays self-describing diff --git a/LookInside/MCPBridge/MCPBridgeInvocationService.swift b/LookInside/MCPBridge/MCPBridgeInvocationService.swift index 02b58b5a..e59015e6 100644 --- a/LookInside/MCPBridge/MCPBridgeInvocationService.swift +++ b/LookInside/MCPBridge/MCPBridgeInvocationService.swift @@ -186,13 +186,13 @@ final class MCPBridgeInvocationService { } private func makeReturnedObject(from rawObject: Any?) -> MCPBridgeReturnedObject? { - guard let lookinObject = rawObject as? InspectedObject else { return nil } - let oidString = String(format: "0x%lx", lookinObject.oid) + guard let inspectedObject = rawObject as? InspectedObject else { return nil } + let oidString = String(format: "0x%lx", inspectedObject.oid) return MCPBridgeReturnedObject( objectIdentifier: oidString, - memoryAddress: lookinObject.memoryAddress ?? "", - classChainList: lookinObject.classChainList ?? [], - specialTrace: lookinObject.specialTrace + memoryAddress: inspectedObject.memoryAddress ?? "", + classChainList: inspectedObject.classChainList ?? [], + specialTrace: inspectedObject.specialTrace ) } diff --git a/LookInside/MCPBridge/MCPBridgeModificationService.swift b/LookInside/MCPBridge/MCPBridgeModificationService.swift index a944cb4f..b711e123 100644 --- a/LookInside/MCPBridge/MCPBridgeModificationService.swift +++ b/LookInside/MCPBridge/MCPBridgeModificationService.swift @@ -175,7 +175,7 @@ final class MCPBridgeModificationService { modification.setterSelector = setterSelector modification.attrType = attribute.attrType modification.value = nativeValue - modification.clientReadableVersion = AppHelper.lookinReadableVersion() + modification.clientReadableVersion = AppHelper.readableVersion() let detail: DisplayItemDetail do { diff --git a/LookInside/MCPBridge/MCPBridgeScreenshotService.swift b/LookInside/MCPBridge/MCPBridgeScreenshotService.swift index 1ed13ae5..f576bfee 100644 --- a/LookInside/MCPBridge/MCPBridgeScreenshotService.swift +++ b/LookInside/MCPBridge/MCPBridgeScreenshotService.swift @@ -258,7 +258,7 @@ final class MCPBridgeScreenshotService { task.attrRequest = .notNeed task.needBasisVisualInfo = false task.needSubitems = false - task.clientReadableVersion = AppHelper.lookinReadableVersion() + task.clientReadableVersion = AppHelper.readableVersion() let package = StaticAsyncUpdateTasksPackage() package.tasks = [task] diff --git a/LookInside/Manager/AppHelper.swift b/LookInside/Manager/AppHelper.swift index 2ce5a830..d2b580d2 100644 --- a/LookInside/Manager/AppHelper.swift +++ b/LookInside/Manager/AppHelper.swift @@ -38,7 +38,7 @@ final class AppHelper { private init() {} /// 使用 UIImageView 的 “使用预览打开该图片” 功能时会创建临时图片文件,它们的路径会保存在这里,Lookin 退出时应当删除这些临时文件 - /// 创建图片的相关逻辑见 LKDashboardAttributeReadOnlyViews.swift + /// 创建图片的相关逻辑见 DashboardAttributeReadOnlyViews.swift var tempImageFiles: [String] = [] static func showDisabledExternalLinkAlert(withMessage message: String) { @@ -54,7 +54,7 @@ final class AppHelper { return NSFont(descriptor: fontDescriptor, size: fontSize) } - static func lookinReadableVersion() -> String { + static func readableVersion() -> String { Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "" } diff --git a/LookInside/Manager/NavigationManager.swift b/LookInside/Manager/NavigationManager.swift index b09ff6c9..8408d41c 100644 --- a/LookInside/Manager/NavigationManager.swift +++ b/LookInside/Manager/NavigationManager.swift @@ -123,7 +123,7 @@ final class NavigationManager: NSObject, NSWindowDelegate { aboutWindowController = nil } // Live and archive document windows belong to NSDocumentController, - // and live windows save their own frame (`LKWindowSizeName_Static`), + // and live windows save their own frame (`windowSizeNameStatic`), // so inspection windows need nothing here. } } diff --git a/LookInside/Manager/PreferenceManager.swift b/LookInside/Manager/PreferenceManager.swift index 28587f82..372efbee 100644 --- a/LookInside/Manager/PreferenceManager.swift +++ b/LookInside/Manager/PreferenceManager.swift @@ -16,15 +16,15 @@ import AppKit import LookInsideHostCore -let LKWindowSizeName_Dynamic = "LKWindowSizeName_Dynamic" -let LKWindowSizeName_Static = "LKWindowSizeName_Static" +let windowSizeNameDynamic = "LKWindowSizeName_Dynamic" +let windowSizeNameStatic = "LKWindowSizeName_Static" /// The initial preview scale. -let LKInitialPreviewScale: CGFloat = 0.27 +let initialPreviewScale: CGFloat = 0.27 /// The default hierarchy request timeout, in seconds. -let LKDefaultHierarchyRequestTimeoutInterval: TimeInterval = 15 -let LKDefaultLicenseHandshakeTimeoutInterval: TimeInterval = 5 +let defaultHierarchyRequestTimeoutInterval: TimeInterval = 15 +let defaultLicenseHandshakeTimeoutInterval: TimeInterval = 5 /// Posted when a dashboard section is added or removed. let NotificationName_DidChangeSectionShowing = "NotificationName_DidChangeSectionShowing" @@ -193,7 +193,7 @@ final class PreferenceManager: NSObject { @objc dynamic var hierarchyRequestTimeoutInterval: TimeInterval { get { storedHierarchyRequestTimeoutInterval } set { - let value = newValue <= 0 ? LKDefaultHierarchyRequestTimeoutInterval : newValue + let value = newValue <= 0 ? defaultHierarchyRequestTimeoutInterval : newValue guard storedHierarchyRequestTimeoutInterval != value else { return } storedHierarchyRequestTimeoutInterval = value store(value, forKey: Key.hierarchyRequestTimeoutInterval) @@ -206,7 +206,7 @@ final class PreferenceManager: NSObject { @objc dynamic var licenseHandshakeTimeoutInterval: TimeInterval { get { storedLicenseHandshakeTimeoutInterval } set { - let value = newValue <= 0 ? LKDefaultLicenseHandshakeTimeoutInterval : newValue + let value = newValue <= 0 ? defaultLicenseHandshakeTimeoutInterval : newValue guard storedLicenseHandshakeTimeoutInterval != value else { return } storedLicenseHandshakeTimeoutInterval = value store(value, forKey: Key.licenseHandshakeTimeoutInterval) @@ -267,7 +267,7 @@ final class PreferenceManager: NSObject { override init() { let defaults = UserDefaults.standard - previewScale = DoubleMessageAttribute(double: Double(LKInitialPreviewScale)) + previewScale = DoubleMessageAttribute(double: Double(initialPreviewScale)) previewDimension = IntegerMessageAttribute(integer: Int(PreviewDimension.dimension3D.rawValue)) measureState = IntegerMessageAttribute(integer: MeasureState.no.rawValue) isQuickSelecting = BoolMessageAttribute(bool: false) @@ -294,7 +294,7 @@ final class PreferenceManager: NSObject { // 默认值为 0.22 let zInterspaceValue = number(Key.zInterspace, default: 0.22).doubleValue - zInterspace = DoubleMessageAttribute(double: max(min(zInterspaceValue, Double(LookinPreviewMaxZInterspace)), Double(LookinPreviewMinZInterspace))) + zInterspace = DoubleMessageAttribute(double: max(min(zInterspaceValue, Double(previewMaxZInterspace)), Double(previewMinZInterspace))) appearanceType = PreferredAppearanceType(rawValue: number(Key.appearanceType, default: NSNumber(value: PreferredAppearanceType.system.rawValue)).intValue) ?? .system expansionIndex = number(Key.expansionIndex, default: 3).intValue @@ -317,10 +317,10 @@ final class PreferenceManager: NSObject { preferredExportCompression = CGFloat(number(Key.preferredExportCompression, default: 0.5).doubleValue) storedHierarchyRequestTimeoutInterval = Self.positiveInterval( - defaults, key: Key.hierarchyRequestTimeoutInterval, fallback: LKDefaultHierarchyRequestTimeoutInterval + defaults, key: Key.hierarchyRequestTimeoutInterval, fallback: defaultHierarchyRequestTimeoutInterval ) storedLicenseHandshakeTimeoutInterval = Self.positiveInterval( - defaults, key: Key.licenseHandshakeTimeoutInterval, fallback: LKDefaultLicenseHandshakeTimeoutInterval + defaults, key: Key.licenseHandshakeTimeoutInterval, fallback: defaultLicenseHandshakeTimeoutInterval ) receivingConfigTime_Color = defaults.double(forKey: Key.receivingConfigTimeColor) diff --git a/LookInside/Preference/LKPreferenceView.swift b/LookInside/Preference/PreferenceView.swift similarity index 98% rename from LookInside/Preference/LKPreferenceView.swift rename to LookInside/Preference/PreferenceView.swift index 9969a1f7..9d760a47 100644 --- a/LookInside/Preference/LKPreferenceView.swift +++ b/LookInside/Preference/PreferenceView.swift @@ -317,8 +317,8 @@ private final class PreferenceViewModel: ObservableObject { setImageContrast(0) setDoubleClickBehavior(DoubleClickBehavior.collapse.rawValue) setRememberExpansionState(true) - setHierarchyTimeout(LKDefaultHierarchyRequestTimeoutInterval) - setLicenseTimeoutIfAvailable(LKDefaultLicenseHandshakeTimeoutInterval) + setHierarchyTimeout(defaultHierarchyRequestTimeoutInterval) + setLicenseTimeoutIfAvailable(defaultLicenseHandshakeTimeoutInterval) #if DEBUG MessageManager.sharedInstance().reset() @@ -360,7 +360,7 @@ private final class PreferenceViewModel: ObservableObject { } private func setHierarchyTimeout(_ value: Double) { - let sanitizedValue = sanitizedTimeout(value, defaultValue: LKDefaultHierarchyRequestTimeoutInterval) + let sanitizedValue = sanitizedTimeout(value, defaultValue: defaultHierarchyRequestTimeoutInterval) hierarchyTimeout = sanitizedValue manager.hierarchyRequestTimeoutInterval = sanitizedValue } @@ -375,7 +375,7 @@ private final class PreferenceViewModel: ObservableObject { #if DEBUG private func setLicenseTimeout(_ value: Double) { - let sanitizedValue = sanitizedTimeout(value, defaultValue: LKDefaultLicenseHandshakeTimeoutInterval) + let sanitizedValue = sanitizedTimeout(value, defaultValue: defaultLicenseHandshakeTimeoutInterval) licenseTimeout = sanitizedValue manager.licenseHandshakeTimeoutInterval = sanitizedValue } diff --git a/LookInside/Preference/PreferenceWindowController.swift b/LookInside/Preference/PreferenceWindowController.swift index 9161f8d3..cc8253bb 100644 --- a/LookInside/Preference/PreferenceWindowController.swift +++ b/LookInside/Preference/PreferenceWindowController.swift @@ -3,7 +3,7 @@ // LookInside // // The Preferences window. Its content is the SwiftUI preference form -// (LKPreferenceView.swift) hosted inside an BaseViewController. +// (PreferenceView.swift) hosted inside an BaseViewController. // import AppKit diff --git a/LookInside/Read/ReadWindowController.swift b/LookInside/Read/ReadWindowController.swift index 8ab17cad..e34a00b8 100644 --- a/LookInside/Read/ReadWindowController.swift +++ b/LookInside/Read/ReadWindowController.swift @@ -107,7 +107,7 @@ final class ReadWindowController: WindowController, NSToolbarDelegate { selectedItemObservation = viewController.hierarchyDataSource.observe(\.selectedItem, options: [.initial, .new]) { [weak self] dataSource, _ in MainActor.assumeIsolated { - let measureButton = self?.toolbarItemsMap[LKToolBarIdentifier_Measure]?.view as? NSButton + let measureButton = self?.toolbarItemsMap[toolbarIdentifierMeasure]?.view as? NSButton measureButton?.isEnabled = dataSource.selectedItem != nil } } @@ -127,15 +127,15 @@ final class ReadWindowController: WindowController, NSToolbarDelegate { func toolbarDefaultItemIdentifiers(_: NSToolbar) -> [NSToolbarItem.Identifier] { [ - LKToolBarIdentifier_AppInReadMode, + toolbarIdentifierAppInReadMode, NSToolbarItem.Identifier.flexibleSpace.rawValue, - LKToolBarIdentifier_Dimension, - LKToolBarIdentifier_Rotation, - LKToolBarIdentifier_Setting, + toolbarIdentifierDimension, + toolbarIdentifierRotation, + toolbarIdentifierSetting, NSToolbarItem.Identifier.flexibleSpace.rawValue, - LKToolBarIdentifier_Scale, + toolbarIdentifierScale, NSToolbarItem.Identifier.flexibleSpace.rawValue, - LKToolBarIdentifier_Measure, + toolbarIdentifierMeasure, ].map { NSToolbarItem.Identifier($0) } } @@ -150,7 +150,7 @@ final class ReadWindowController: WindowController, NSToolbarDelegate { } let helper = WindowToolbarHelper.shared let item: NSToolbarItem? - if identifier == LKToolBarIdentifier_AppInReadMode { + if identifier == toolbarIdentifierAppInReadMode { item = helper.makeAppInReadModeItem(with: viewController?.hierarchyDataSource.rawHierarchyInfo?.appInfo) } else { item = helper.makeToolBarItem(identifier: identifier, preferenceManager: preferenceManager) @@ -158,11 +158,11 @@ final class ReadWindowController: WindowController, NSToolbarDelegate { guard let item else { return nil } toolbarItemsMap[identifier] = item - if identifier == LKToolBarIdentifier_Setting { + if identifier == toolbarIdentifierSetting { item.label = NSLocalizedString("View", comment: "") item.target = self item.action = #selector(handleSetting(_:)) - } else if identifier == LKToolBarIdentifier_Rotation { + } else if identifier == toolbarIdentifierRotation { item.target = self item.action = #selector(handleFreeRotation) } @@ -228,8 +228,8 @@ final class ReadWindowController: WindowController, NSToolbarDelegate { let value = ToolbarRules.stepped( scale.currentDoubleValue, by: delta, - lower: Double(LookinPreviewMinScale), - upper: Double(LookinPreviewMaxScale) + lower: Double(previewMinScale), + upper: Double(previewMaxScale) ) scale.setDoubleValue(value, ignoreSubscriber: nil) } @@ -239,8 +239,8 @@ final class ReadWindowController: WindowController, NSToolbarDelegate { let value = ToolbarRules.stepped( interspace.currentDoubleValue, by: delta, - lower: Double(LookinPreviewMinZInterspace), - upper: Double(LookinPreviewMaxZInterspace) + lower: Double(previewMinZInterspace), + upper: Double(previewMaxZInterspace) ) interspace.setDoubleValue(value, ignoreSubscriber: nil) } diff --git a/LookInside/Static/MessageManager.swift b/LookInside/Static/MessageManager.swift index 3881e01d..4361348c 100644 --- a/LookInside/Static/MessageManager.swift +++ b/LookInside/Static/MessageManager.swift @@ -9,8 +9,8 @@ import Foundation /// The notices the inspector window shows under its toolbar message -/// button. Identifiers are `LKMessage_Jobs` and `LKMessage_SwiftSubspec` -/// (LKStaticConstants.swift). +/// button. Identifiers are `jobsMessageIdentifier` and `swiftSubspecMessageIdentifier` +/// (StaticConstants.swift). @objc(LKMessageManager) final class MessageManager: NSObject { /// Set once the jobs notice was dismissed. @@ -36,7 +36,7 @@ final class MessageManager: NSObject { @objc(removeMessage:) func removeMessage(_ message: String) { messages.remove(message) - if message == LKMessage_Jobs { + if message == jobsMessageIdentifier { UserDefaults.standard.set(true, forKey: Self.hasReadJobsDefaultsKey) } } diff --git a/LookInside/Static/Preview/DisplayItemNode.swift b/LookInside/Static/Preview/DisplayItemNode.swift index d7b63f47..b9fd2a3b 100644 --- a/LookInside/Static/Preview/DisplayItemNode.swift +++ b/LookInside/Static/Preview/DisplayItemNode.swift @@ -268,7 +268,7 @@ final class DisplayItemNode: SCNNode, DisplayItemDelegate { let isSelected = dataSource?.selectedItem === displayItem let isHovered = dataSource?.hoveredItem === displayItem - let screenshot = displayItem?.lkOptionalAppropriateScreenshot + let screenshot = displayItem?.optionalAppropriateScreenshot if let rep = screenshot?.representations.first { assert(CGFloat(Swift.max(rep.pixelsWide, rep.pixelsHigh)) <= CGFloat(LookinNodeImageMaxLengthInPx), "image is too large") } @@ -378,7 +378,7 @@ final class DisplayItemNode: SCNNode, DisplayItemDelegate { maskPlane.width = contentPlane.width maskPlane.height = contentPlane.height if !regionNode.isHidden { - let region = region(of: self.displayItem?.lkOptionalAppropriateScreenshot) ?? .zero + let region = region(of: self.displayItem?.optionalAppropriateScreenshot) ?? .zero layoutRegionNode(region: region, frameToRoot: frameToRoot) } @@ -412,7 +412,7 @@ extension DisplayItem { /// `-appropriateScreenshot`, which returns nil for an item without a /// screenshot although its header (inside NS_ASSUME_NONNULL) says it /// never does; read through the runtime so Swift sees the nil. - var lkOptionalAppropriateScreenshot: NSImage? { + var optionalAppropriateScreenshot: NSImage? { value(forKey: "appropriateScreenshot") as? NSImage } } diff --git a/LookInside/Static/Preview/PreviewController.swift b/LookInside/Static/Preview/PreviewController.swift index 3d906b29..97f5853b 100644 --- a/LookInside/Static/Preview/PreviewController.swift +++ b/LookInside/Static/Preview/PreviewController.swift @@ -382,7 +382,7 @@ final class PreviewController: BaseViewController, NSGestureRecognizerDelegate, return } // The app's screen size changed: reset the scale. - dataSource?.preferenceManager().previewScale.setDoubleValue(Double(LKInitialPreviewScale), ignoreSubscriber: nil) + dataSource?.preferenceManager().previewScale.setDoubleValue(Double(initialPreviewScale), ignoreSubscriber: nil) } // MARK: - Gestures @@ -502,7 +502,7 @@ final class PreviewController: BaseViewController, NSGestureRecognizerDelegate, guard let manager = dataSource?.preferenceManager() else { return } let targetScale = manager.previewScale.currentDoubleValue - event.deltaY * 0.005 manager.previewScale.setDoubleValue( - min(max(targetScale, LookinPreviewMinScale), LookinPreviewMaxScale), + min(max(targetScale, previewMinScale), previewMaxScale), ignoreSubscriber: nil ) } else { @@ -597,7 +597,7 @@ final class PreviewController: BaseViewController, NSGestureRecognizerDelegate, @objc private func handlePrintItem(_: NSMenuItem) { NotificationCenter.default.post( - name: NSNotification.Name(LKAppShowConsoleNotificationName), + name: NSNotification.Name(appShowConsoleNotificationName), object: rightClickingDisplayItem ) } diff --git a/LookInside/Static/Preview/PreviewView.swift b/LookInside/Static/Preview/PreviewView.swift index 72557f96..2d38bd5c 100644 --- a/LookInside/Static/Preview/PreviewView.swift +++ b/LookInside/Static/Preview/PreviewView.swift @@ -53,7 +53,7 @@ final class PreviewView: SCNView { } } - /// Zoom, from LookinPreviewMinScale to LookinPreviewMaxScale. + /// Zoom, from previewMinScale to previewMaxScale. var scale: CGFloat = 0 { didSet { // A smaller focal length shows a smaller image. @@ -61,8 +61,8 @@ final class PreviewView: SCNView { } } - /// The spacing between layers, from LookinPreviewMinZInterspace to - /// LookinPreviewMaxZInterspace. + /// The spacing between layers, from previewMinZInterspace to + /// previewMaxZInterspace. var zInterspace: CGFloat { get { storedZInterspace } set { diff --git a/LookInside/Static/StaticAsyncUpdateManager.swift b/LookInside/Static/StaticAsyncUpdateManager.swift index 97f6642c..1f959866 100644 --- a/LookInside/Static/StaticAsyncUpdateManager.swift +++ b/LookInside/Static/StaticAsyncUpdateManager.swift @@ -234,7 +234,7 @@ final class StaticAsyncUpdateManager: NSObject { if item.isUserCustom() { return nil } - if item.lkOptionalAppropriateScreenshot != nil { + if item.optionalAppropriateScreenshot != nil { // Has its image, and so its attributes too. return nil } @@ -314,7 +314,7 @@ final class StaticAsyncUpdateManager: NSObject { // layers on): then the view node has to use the view oid. let viewOid = item.viewObject?.oid ?? 0 let layerOid = item.layerObject?.oid ?? 0 - let prefersViewOid = AppHelper.appInfoLooksLikeMacTarget(appInfo) || item.lk_ownsSeparateBackingLayerNode() + let prefersViewOid = AppHelper.appInfoLooksLikeMacTarget(appInfo) || item.ownsSeparateBackingLayerNode() if prefersViewOid, viewOid != 0 { oid = viewOid } else if layerOid != 0 { @@ -330,12 +330,12 @@ final class StaticAsyncUpdateManager: NSObject { task.frameSize = item.frame.size task.taskType = type task.needBasisVisualInfo = true - task.clientReadableVersion = AppHelper.lookinReadableVersion() + task.clientReadableVersion = AppHelper.readableVersion() return task } private static func allowsSwiftUISupportAccess(for item: DisplayItem, appInfo: InspectedAppInfo?) -> Bool { - guard AppHelper.appInfoLooksLikeMacTarget(appInfo), item.lk_isSwiftUISupportRelated() else { + guard AppHelper.appInfoLooksLikeMacTarget(appInfo), item.isSwiftUISupportRelated() else { return true } return SwiftUISupportGatekeeper.sharedInstance().allowProtectedFeatureAccess(for: NSApplication.shared.keyWindow) @@ -454,7 +454,7 @@ final class StaticAsyncUpdateManager: NSObject { comment: "" ) if SwiftUISupportGatekeeper.sharedInstance().activationState == .activated, - (dataSource?.flatItems ?? []).contains(where: { $0.lk_isSwiftUISupportRelated() }) + (dataSource?.flatItems ?? []).contains(where: { $0.isSwiftUISupportRelated() }) { detail += "\n" + NSLocalizedString( "First-time loading of SwiftUI details may take longer because LookInside needs to collect and match SwiftUI debug data.", @@ -562,7 +562,7 @@ extension StaticAsyncUpdateManager { return false } if AppHelper.appInfoLooksLikeMacTarget(appInfo), - item.lk_isSwiftUISupportRelated(), + item.isSwiftUISupportRelated(), !SwiftUISupportGatekeeper.sharedInstance().allowProtectedFeatureAccess(for: NSApplication.shared.keyWindow) { return false @@ -576,7 +576,7 @@ extension StaticAsyncUpdateManager { let task = StaticAsyncUpdateTask() task.oid = oid task.frameSize = item.frame.size - task.clientReadableVersion = AppHelper.lookinReadableVersion() + task.clientReadableVersion = AppHelper.readableVersion() return task } } diff --git a/LookInside/Static/LKStaticConstants.swift b/LookInside/Static/StaticConstants.swift similarity index 56% rename from LookInside/Static/LKStaticConstants.swift rename to LookInside/Static/StaticConstants.swift index 73930f4d..ebbb793a 100644 --- a/LookInside/Static/LKStaticConstants.swift +++ b/LookInside/Static/StaticConstants.swift @@ -1,5 +1,5 @@ // -// LKStaticConstants.swift +// StaticConstants.swift // LookInside // // The constants of the inspector window and its 3D preview, shared by the @@ -10,18 +10,18 @@ import CoreGraphics /// Posted with a DisplayItem as the object to show the console and /// print that item's view in it. -let LKAppShowConsoleNotificationName = "LKAppShowConsoleNotificationName" +let appShowConsoleNotificationName = "LKAppShowConsoleNotificationName" /// Message identifiers of MessageManager. -let LKMessage_Jobs = "LKMessage_Jobs" -let LKMessage_SwiftSubspec = "LKMessage_SwiftSubspec" +let jobsMessageIdentifier = "LKMessage_Jobs" +let swiftSubspecMessageIdentifier = "LKMessage_SwiftSubspec" /// Bounds of PreviewView's scale and zInterspace (and of the preference /// values that drive them). -let LookinPreviewMinScale: CGFloat = 0 -let LookinPreviewMaxScale: CGFloat = 1 -let LookinPreviewMinZInterspace: CGFloat = 0 -let LookinPreviewMaxZInterspace: CGFloat = 1 +let previewMinScale: CGFloat = 0 +let previewMaxScale: CGFloat = 1 +let previewMinZInterspace: CGFloat = 0 +let previewMaxZInterspace: CGFloat = 1 @objc enum PreviewDimension: UInt { case dimension2D diff --git a/LookInside/Static/StaticHierarchyDataSource.swift b/LookInside/Static/StaticHierarchyDataSource.swift index 504e24ec..e4fe277a 100644 --- a/LookInside/Static/StaticHierarchyDataSource.swift +++ b/LookInside/Static/StaticHierarchyDataSource.swift @@ -206,9 +206,9 @@ class StaticHierarchyDataSource: HierarchyDataSource { private func updateMessageStatus() { if serverSideIsSwiftProject, appInfo?.swiftEnabledInLookinServer == -1 { - MessageManager.sharedInstance().addMessage(LKMessage_SwiftSubspec) + MessageManager.sharedInstance().addMessage(swiftSubspecMessageIdentifier) } else { - MessageManager.sharedInstance().removeMessage(LKMessage_SwiftSubspec) + MessageManager.sharedInstance().removeMessage(swiftSubspecMessageIdentifier) } } } diff --git a/LookInside/Static/StaticViewController.swift b/LookInside/Static/StaticViewController.swift index 8a2616a0..31a7180e 100644 --- a/LookInside/Static/StaticViewController.swift +++ b/LookInside/Static/StaticViewController.swift @@ -181,7 +181,7 @@ final class StaticViewController: BaseViewController, NSSplitViewDelegate { preferenceManager.fastMode.subscribe(self, action: #selector(handleFastModeChange(_:)), relatedObject: nil, sendAtOnce: true) notificationObservers.append(NotificationCenter.default.addObserver( - forName: NSNotification.Name(LKAppShowConsoleNotificationName), + forName: NSNotification.Name(appShowConsoleNotificationName), object: nil, queue: nil ) { [weak self] note in @@ -573,7 +573,7 @@ final class StaticViewController: BaseViewController, NSSplitViewDelegate { let item = dataSource?.selectedItem let showsTooLargeTip = item != nil - && item?.lkOptionalAppropriateScreenshot == nil + && item?.optionalAppropriateScreenshot == nil && item?.doNotFetchScreenshotReason == .doNotFetchScreenshotForTooLarge if tooLargeToSyncScreenshotTipsView.isHidden != !showsTooLargeTip { tooLargeToSyncScreenshotTipsView.isHidden = !showsTooLargeTip diff --git a/LookInside/Static/StaticWindowController.swift b/LookInside/Static/StaticWindowController.swift index 62b5abbb..08d4561f 100644 --- a/LookInside/Static/StaticWindowController.swift +++ b/LookInside/Static/StaticWindowController.swift @@ -124,12 +124,12 @@ final class StaticWindowController: WindowController, NSToolbarDelegate, @precon window.toolbarStyle = .unified window.minSize = NSSize(width: HierarchyMinWidth + DashboardViewWidth + 200, height: 500) window.center() - window.setFrameUsingName(LKWindowSizeName_Static) + window.setFrameUsingName(windowSizeNameStatic) super.init(window: window) // Saves this window's frame across launches. - windowFrameAutosaveName = LKWindowSizeName_Static + windowFrameAutosaveName = windowSizeNameStatic let dataSource = StaticHierarchyDataSource() let updateManager = StaticAsyncUpdateManager(hierarchyDataSource: dataSource, inspectableApp: nil) @@ -140,7 +140,7 @@ final class StaticWindowController: WindowController, NSToolbarDelegate, @precon NotificationCenter.default.addObserver( self, selector: #selector(handleSwiftUIModeDidChange(_:)), - name: .LKSwiftUIHierarchyDisplayModeDidChange, + name: .swiftUIHierarchyDisplayModeDidChange, object: nil ) @@ -165,13 +165,13 @@ final class StaticWindowController: WindowController, NSToolbarDelegate, @precon toolbar.delegate = self window.toolbar = toolbar - fetchingStateReloadItem = toolbarItemsMap[NSToolbarItem.Identifier(LKToolBarIdentifier_Reload)] + fetchingStateReloadItem = toolbarItemsMap[NSToolbarItem.Identifier(toolbarIdentifierReload)] updateManager.delegate = self updateToolbarForFetchingState() observations.append(dataSource.observe(\.selectedItem, options: [.initial, .new]) { [weak self] dataSource, _ in MainActor.assumeIsolated { - let measureButton = self?.toolbarItemsMap[NSToolbarItem.Identifier(LKToolBarIdentifier_Measure)]?.view as? NSButton + let measureButton = self?.toolbarItemsMap[NSToolbarItem.Identifier(toolbarIdentifierMeasure)]?.view as? NSButton measureButton?.isEnabled = dataSource.selectedItem != nil } }) @@ -193,14 +193,14 @@ final class StaticWindowController: WindowController, NSToolbarDelegate, @precon private func updateToolbarForFetchingState() { let isFetching = isFetchingHierarchy || isFetchingDetails - for identifier in [NSToolbarItem.Identifier(LKToolBarIdentifier_App), NSToolbarItem.Identifier(LKToolBarIdentifier_Console), NSToolbarItem.Identifier(LKToolBarIdentifier_FastMode)] { + for identifier in [NSToolbarItem.Identifier(toolbarIdentifierApp), NSToolbarItem.Identifier(toolbarIdentifierConsole), NSToolbarItem.Identifier(toolbarIdentifierFastMode)] { toolbarItemsMap[identifier]?.isEnabled = !isFetching } fetchingStateReloadItem?.isEnabled = !isFetchingHierarchy } private func updateAppButton() { - let appButton = toolbarItemsMap[NSToolbarItem.Identifier(LKToolBarIdentifier_App)]?.view as? WindowToolbarAppButton + let appButton = toolbarItemsMap[NSToolbarItem.Identifier(toolbarIdentifierApp)]?.view as? WindowToolbarAppButton appButton?.appInfo = inspectableApp?.appInfo } @@ -268,7 +268,7 @@ final class StaticWindowController: WindowController, NSToolbarDelegate, @precon @objc(popupAllInspectableAppsWithSource:) func popupAllInspectableApps(with source: MenuPopoverAppsListControllerEventSource) { - let appItemView = toolbarItemsMap[NSToolbarItem.Identifier(LKToolBarIdentifier_App)]?.view + let appItemView = toolbarItemsMap[NSToolbarItem.Identifier(toolbarIdentifierApp)]?.view Task { [weak self] in let apps = await AppsManager.shared.fetchAppInfos(needImages: true, localInfos: nil) @@ -450,17 +450,17 @@ final class StaticWindowController: WindowController, NSToolbarDelegate, @precon func toolbarDefaultItemIdentifiers(_: NSToolbar) -> [NSToolbarItem.Identifier] { var identifiers: [NSToolbarItem.Identifier] = [ - NSToolbarItem.Identifier(LKToolBarIdentifier_Reload), NSToolbarItem.Identifier(LKToolBarIdentifier_FastMode), NSToolbarItem.Identifier(LKToolBarIdentifier_App), NSToolbarItem.Identifier(LKToolBarIdentifier_SwiftUIMode), - NSToolbarItem.Identifier(LKToolBarIdentifier_GestureDebug), + NSToolbarItem.Identifier(toolbarIdentifierReload), NSToolbarItem.Identifier(toolbarIdentifierFastMode), NSToolbarItem.Identifier(toolbarIdentifierApp), NSToolbarItem.Identifier(toolbarIdentifierSwiftUIMode), + NSToolbarItem.Identifier(toolbarIdentifierGestureDebug), .flexibleSpace, - NSToolbarItem.Identifier(LKToolBarIdentifier_Dimension), NSToolbarItem.Identifier(LKToolBarIdentifier_Rotation), NSToolbarItem.Identifier(LKToolBarIdentifier_Setting), + NSToolbarItem.Identifier(toolbarIdentifierDimension), NSToolbarItem.Identifier(toolbarIdentifierRotation), NSToolbarItem.Identifier(toolbarIdentifierSetting), .flexibleSpace, - NSToolbarItem.Identifier(LKToolBarIdentifier_Scale), + NSToolbarItem.Identifier(toolbarIdentifierScale), .flexibleSpace, - NSToolbarItem.Identifier(LKToolBarIdentifier_Measure), NSToolbarItem.Identifier(LKToolBarIdentifier_Console), + NSToolbarItem.Identifier(toolbarIdentifierMeasure), NSToolbarItem.Identifier(toolbarIdentifierConsole), ] if !MessageManager.sharedInstance().queryMessages().isEmpty { - identifiers.append(NSToolbarItem.Identifier(LKToolBarIdentifier_Message)) + identifiers.append(NSToolbarItem.Identifier(toolbarIdentifierMessage)) } return identifiers } @@ -482,26 +482,26 @@ final class StaticWindowController: WindowController, NSToolbarDelegate, @precon toolbarItemsMap[itemIdentifier] = item switch item.itemIdentifier { - case NSToolbarItem.Identifier(LKToolBarIdentifier_Reload): + case NSToolbarItem.Identifier(toolbarIdentifierReload): item.target = self item.action = #selector(handleReload) - case NSToolbarItem.Identifier(LKToolBarIdentifier_GestureDebug): + case NSToolbarItem.Identifier(toolbarIdentifierGestureDebug): item.target = self item.action = #selector(handleGestureDebug) - case NSToolbarItem.Identifier(LKToolBarIdentifier_App): + case NSToolbarItem.Identifier(toolbarIdentifierApp): item.target = self item.action = #selector(handleApp) // Shows the bound app's icon; `inspectableApp` updates it when // LiveDocument swaps in the reconnected app. updateAppButton() - case NSToolbarItem.Identifier(LKToolBarIdentifier_Rotation): + case NSToolbarItem.Identifier(toolbarIdentifierRotation): item.target = self item.action = #selector(handleFreeRotation) - case NSToolbarItem.Identifier(LKToolBarIdentifier_Setting): + case NSToolbarItem.Identifier(toolbarIdentifierSetting): item.label = NSLocalizedString("View", comment: "") item.target = self item.action = #selector(handleSetting(_:)) - case NSToolbarItem.Identifier(LKToolBarIdentifier_Console): + case NSToolbarItem.Identifier(toolbarIdentifierConsole): item.target = self item.action = #selector(handleConsole) observations.append(viewController.observe(\.showConsole, options: [.old, .new]) { [weak item] _, change in @@ -510,11 +510,11 @@ final class StaticWindowController: WindowController, NSToolbarDelegate, @precon (item?.view as? NSButton)?.state = showConsole ? .on : .off } }) - case NSToolbarItem.Identifier(LKToolBarIdentifier_Message): + case NSToolbarItem.Identifier(toolbarIdentifierMessage): item.label = NSLocalizedString("Notifications", comment: "") item.target = self item.action = #selector(handleMessage(_:)) - case NSToolbarItem.Identifier(LKToolBarIdentifier_FastMode): + case NSToolbarItem.Identifier(toolbarIdentifierFastMode): item.target = self item.action = #selector(handleFastMode) default: @@ -595,7 +595,7 @@ final class StaticWindowController: WindowController, NSToolbarDelegate, @precon private func handleMessage(_ button: NSButton) { let menu = NSMenu() for message in MessageManager.sharedInstance().queryMessages() { - if message == LKMessage_Jobs { + if message == jobsMessageIdentifier { let item = NSMenuItem() item.image = NSImage(named: "Icon_Inspiration_small") item.title = NSLocalizedString("Job openings…(China)", comment: "") @@ -603,7 +603,7 @@ final class StaticWindowController: WindowController, NSToolbarDelegate, @precon item.action = #selector(handleJobsMenuItem) menu.addItem(item) menu.addItem(.separator()) - } else if message == LKMessage_SwiftSubspec { + } else if message == swiftSubspecMessageIdentifier { let tipItem = NSMenuItem() tipItem.image = NSImage(named: "Icon_Inspiration_small") tipItem.title = NSLocalizedString("Your iOS project seems to use Swift, but you haven't turn on Swift optimization for LookInside", comment: "") @@ -637,7 +637,7 @@ final class StaticWindowController: WindowController, NSToolbarDelegate, @precon @objc func handleJobsMenuItem() { AppHelper.showDisabledExternalLinkAlert(withMessage: NSLocalizedString("This upstream community link is not available in this build.", comment: "")) - MessageManager.sharedInstance().removeMessage(LKMessage_Jobs) + MessageManager.sharedInstance().removeMessage(jobsMessageIdentifier) } @objc func handleTurnOnSwift() { @@ -680,7 +680,7 @@ final class StaticWindowController: WindowController, NSToolbarDelegate, @precon private func adjustPreviewScale(by delta: Double) { let scale = PreferenceManager.shared.previewScale - let target = min(max(scale.currentDoubleValue + delta, Double(LookinPreviewMinScale)), Double(LookinPreviewMaxScale)) + let target = min(max(scale.currentDoubleValue + delta, Double(previewMinScale)), Double(previewMaxScale)) scale.setDoubleValue(target, ignoreSubscriber: nil) } @@ -694,7 +694,7 @@ final class StaticWindowController: WindowController, NSToolbarDelegate, @precon private func adjustZInterspace(by delta: Double) { let interspace = PreferenceManager.shared.zInterspace - let target = min(max(interspace.currentDoubleValue + delta, Double(LookinPreviewMinZInterspace)), Double(LookinPreviewMaxZInterspace)) + let target = min(max(interspace.currentDoubleValue + delta, Double(previewMinZInterspace)), Double(previewMaxZInterspace)) interspace.setDoubleValue(target, ignoreSubscriber: nil) } @@ -766,7 +766,7 @@ final class StaticWindowController: WindowController, NSToolbarDelegate, @precon // MARK: - StaticAsyncUpdateManagerDelegate func detailUpdateTasksTotalCount(_ totalCount: UInt, finishedCount: UInt) { - let reloadItem = toolbarItemsMap[NSToolbarItem.Identifier(LKToolBarIdentifier_Reload)] + let reloadItem = toolbarItemsMap[NSToolbarItem.Identifier(toolbarIdentifierReload)] let reloadButton = reloadItem?.view as? NSButton if totalCount > finishedCount { diff --git a/LookInside/SwiftUISupport/SwiftUIHierarchyDisplayMode.swift b/LookInside/SwiftUISupport/SwiftUIHierarchyDisplayMode.swift index d357b8a8..e5f81278 100644 --- a/LookInside/SwiftUISupport/SwiftUIHierarchyDisplayMode.swift +++ b/LookInside/SwiftUISupport/SwiftUIHierarchyDisplayMode.swift @@ -14,7 +14,7 @@ extension Notification.Name { /// Posted on the main thread whenever /// `SwiftUIHierarchyDisplayModeStore.currentMode()` changes. /// Notification object: the store class. - static let LKSwiftUIHierarchyDisplayModeDidChange = Notification.Name("LKSwiftUIHierarchyDisplayModeDidChangeNotification") + static let swiftUIHierarchyDisplayModeDidChange = Notification.Name("LKSwiftUIHierarchyDisplayModeDidChangeNotification") } @objc(LKSwiftUIHierarchyDisplayModeStore) @@ -31,13 +31,13 @@ final class SwiftUIHierarchyDisplayModeStore: NSObject { } /// Persist the new mode to UserDefaults and post - /// LKSwiftUIHierarchyDisplayModeDidChange if the value actually changed. + /// swiftUIHierarchyDisplayModeDidChange if the value actually changed. static func setCurrentMode(_ mode: SwiftUIHierarchyDisplayMode) { guard currentMode() != mode else { return } UserDefaults.standard.set(mode.rawValue, forKey: defaultsKey) - NotificationCenter.default.post(name: .LKSwiftUIHierarchyDisplayModeDidChange, object: self) + NotificationCenter.default.post(name: .swiftUIHierarchyDisplayModeDidChange, object: self) } /// Action of an NSSegmentedControl whose segment 0 is Compact and diff --git a/LookInside/SwiftUISupport/SwiftUISupportGatekeeper.swift b/LookInside/SwiftUISupport/SwiftUISupportGatekeeper.swift index a704ecec..7ab4d79c 100644 --- a/LookInside/SwiftUISupport/SwiftUISupportGatekeeper.swift +++ b/LookInside/SwiftUISupport/SwiftUISupportGatekeeper.swift @@ -3,7 +3,7 @@ import Foundation import LookInsideActivation import LookInsideActivationUI -@objc public enum SwiftUISupportActivationState: Int { +@objc public enum SwiftUISupportActivationState: Int, CustomDebugStringConvertible { case unknown case notActivated case activated @@ -16,7 +16,7 @@ import LookInsideActivationUI self = decision.grantsAccess ? .activated : .notActivated } - var lkDebugDescription: String { + public var debugDescription: String { switch self { case .unknown: return "unknown" case .notActivated: return "notActivated" @@ -99,7 +99,7 @@ public final class SwiftUISupportGatekeeper: NSObject { SwiftUISupportLogger.activation.info( // Logger interpolations are escaping autoclosures. // swiftformat:disable:next redundantSelf - "activation runtime ready, state=\(self.publishedState.lkDebugDescription, privacy: .public)" + "activation runtime ready, state=\(self.publishedState.debugDescription, privacy: .public)" ) decisionObservation = runtime.addDecisionObserver { [weak self] decision in self?.recordDecision(decision) @@ -226,7 +226,7 @@ public final class SwiftUISupportGatekeeper: NSObject { } guard shouldNotify else { return } SwiftUISupportLogger.activation.info( - "activation state changed: \(previousState.lkDebugDescription, privacy: .public) -> \(newState.lkDebugDescription, privacy: .public) (decision=\(decision.decision.rawValue, privacy: .public))" + "activation state changed: \(previousState.debugDescription, privacy: .public) -> \(newState.debugDescription, privacy: .public) (decision=\(decision.decision.rawValue, privacy: .public))" ) DispatchQueue.main.async { NotificationCenter.default.post( diff --git a/LookInside/Toolbar/MenuPopoverSettingController.swift b/LookInside/Toolbar/MenuPopoverSettingController.swift index 48e74fbd..54ad4daa 100644 --- a/LookInside/Toolbar/MenuPopoverSettingController.swift +++ b/LookInside/Toolbar/MenuPopoverSettingController.swift @@ -58,8 +58,8 @@ final class MenuPopoverSettingController: BaseViewController { isOn: manager.showBackingLayers.currentBOOLValue ) - spaceSlider.minValue = Double(LookinPreviewMinZInterspace) - spaceSlider.maxValue = Double(LookinPreviewMaxZInterspace) + spaceSlider.minValue = Double(previewMinZInterspace) + spaceSlider.maxValue = Double(previewMaxZInterspace) spaceSlider.target = self spaceSlider.action = #selector(handleSpaceSlider(_:)) view.addSubview(spaceSlider) diff --git a/LookInside/Toolbar/ToolbarRules.swift b/LookInside/Toolbar/ToolbarRules.swift index e28b9052..a7f344ac 100644 --- a/LookInside/Toolbar/ToolbarRules.swift +++ b/LookInside/Toolbar/ToolbarRules.swift @@ -10,21 +10,21 @@ import Foundation // Toolbar item identifiers. The values are stored in the toolbar // configuration; never change them. -let LKToolBarIdentifier_Dimension = "0" -let LKToolBarIdentifier_Scale = "1" -let LKToolBarIdentifier_Setting = "2" -let LKToolBarIdentifier_Reload = "3" -let LKToolBarIdentifier_App = "5" -let LKToolBarIdentifier_AppInReadMode = "12" -let LKToolBarIdentifier_Add = "13" -let LKToolBarIdentifier_Remove = "14" -let LKToolBarIdentifier_Console = "15" -let LKToolBarIdentifier_Rotation = "16" -let LKToolBarIdentifier_Measure = "17" -let LKToolBarIdentifier_Message = "18" -let LKToolBarIdentifier_FastMode = "19" -let LKToolBarIdentifier_SwiftUIMode = "20" -let LKToolBarIdentifier_GestureDebug = "21" +let toolbarIdentifierDimension = "0" +let toolbarIdentifierScale = "1" +let toolbarIdentifierSetting = "2" +let toolbarIdentifierReload = "3" +let toolbarIdentifierApp = "5" +let toolbarIdentifierAppInReadMode = "12" +let toolbarIdentifierAdd = "13" +let toolbarIdentifierRemove = "14" +let toolbarIdentifierConsole = "15" +let toolbarIdentifierRotation = "16" +let toolbarIdentifierMeasure = "17" +let toolbarIdentifierMessage = "18" +let toolbarIdentifierFastMode = "19" +let toolbarIdentifierSwiftUIMode = "20" +let toolbarIdentifierGestureDebug = "21" /// What opened the apps popover. @objc enum MenuPopoverAppsListControllerEventSource: Int { diff --git a/LookInside/Toolbar/WindowToolbarHelper.swift b/LookInside/Toolbar/WindowToolbarHelper.swift index 355d2a6f..41c57669 100644 --- a/LookInside/Toolbar/WindowToolbarHelper.swift +++ b/LookInside/Toolbar/WindowToolbarHelper.swift @@ -27,17 +27,17 @@ final class WindowToolbarHelper: NSObject { /// reader's app item. @objc(makeToolBarItemWithIdentifier:preferenceManager:) func makeToolBarItem(identifier: String, preferenceManager manager: PreferenceManager) -> NSToolbarItem? { - assert(identifier != LKToolBarIdentifier_AppInReadMode, "Use makeAppInReadModeItemWithAppInfo:") + assert(identifier != toolbarIdentifierAppInReadMode, "Use makeAppInReadModeItemWithAppInfo:") switch identifier { - case LKToolBarIdentifier_GestureDebug: + case toolbarIdentifierGestureDebug: let item = NSToolbarItem(itemIdentifier: NSToolbarItem.Identifier(identifier)) item.label = NSLocalizedString("Gestures", comment: "") item.toolTip = NSLocalizedString("Inspect SwiftUI responders and gesture events", comment: "") item.image = NSImage(systemSymbolName: "hand.point.up.left", accessibilityDescription: item.label) return item - case LKToolBarIdentifier_Measure: + case toolbarIdentifierMeasure: let button = ToolbarPreferenceButton() button.preferenceManager = manager button.image = Self.templateImage("icon_measure") @@ -46,14 +46,14 @@ final class WindowToolbarHelper: NSObject { button.target = self button.action = #selector(handleToggleMeasureButton(_:)) manager.measureState.subscribe(self, action: #selector(handleMeasureStateDidChange(_:)), relatedObject: button, sendAtOnce: true) - return Self.item(LKToolBarIdentifier_Measure, label: NSLocalizedString("Measure", comment: ""), view: button) + return Self.item(toolbarIdentifierMeasure, label: NSLocalizedString("Measure", comment: ""), view: button) - case LKToolBarIdentifier_Rotation: + case toolbarIdentifierRotation: let button = Self.imageButton("icon_rotation", buttonType: .pushOnPushOff) manager.freeRotation.subscribe(self, action: #selector(handleOnOffDidChange(_:)), relatedObject: button, sendAtOnce: true) - return Self.item(LKToolBarIdentifier_Rotation, label: NSLocalizedString("Free Rotation", comment: ""), view: button) + return Self.item(toolbarIdentifierRotation, label: NSLocalizedString("Free Rotation", comment: ""), view: button) - case LKToolBarIdentifier_Dimension: + case toolbarIdentifierDimension: let images = [Self.templateImage("icon_2d"), Self.templateImage("icon_3d")].compactMap { $0 } let control = ToolbarPreferenceSegmentedControl( images: images, @@ -66,14 +66,14 @@ final class WindowToolbarHelper: NSObject { control.setWidth(45, forSegment: 0) control.setWidth(45, forSegment: 1) manager.previewDimension.subscribe(self, action: #selector(handleDimensionDidChange(_:)), relatedObject: control, sendAtOnce: true) - return Self.item(LKToolBarIdentifier_Dimension, label: "2D / 3D", view: control) + return Self.item(toolbarIdentifierDimension, label: "2D / 3D", view: control) - case LKToolBarIdentifier_Scale: + case toolbarIdentifierScale: let scaleView = WindowToolbarScaleView() let slider = scaleView.slider slider.preferenceManager = manager - slider.minValue = Double(LookinPreviewMinScale) - slider.maxValue = Double(LookinPreviewMaxScale) + slider.minValue = Double(previewMinScale) + slider.maxValue = Double(previewMaxScale) slider.doubleValue = manager.previewScale.currentDoubleValue slider.target = self slider.action = #selector(handleScaleSlider(_:)) @@ -84,22 +84,22 @@ final class WindowToolbarHelper: NSObject { scaleView.decreaseButton.action = #selector(handleScaleDecreaseButton(_:)) scaleView.decreaseButton.preferenceManager = manager manager.previewScale.subscribe(self, action: #selector(handlePreviewScaleDidChange(_:)), relatedObject: slider, sendAtOnce: true) - return Self.item(LKToolBarIdentifier_Scale, label: NSLocalizedString("Zoom", comment: ""), view: scaleView) + return Self.item(toolbarIdentifierScale, label: NSLocalizedString("Zoom", comment: ""), view: scaleView) - case LKToolBarIdentifier_Setting: - return Self.item(LKToolBarIdentifier_Setting, label: nil, view: Self.imageButton("icon_setting")) + case toolbarIdentifierSetting: + return Self.item(toolbarIdentifierSetting, label: nil, view: Self.imageButton("icon_setting")) - case LKToolBarIdentifier_Reload: - return Self.item(LKToolBarIdentifier_Reload, label: NSLocalizedString("Reload", comment: ""), view: Self.imageButton("icon_reload")) + case toolbarIdentifierReload: + return Self.item(toolbarIdentifierReload, label: NSLocalizedString("Reload", comment: ""), view: Self.imageButton("icon_reload")) - case LKToolBarIdentifier_App: + case toolbarIdentifierApp: let button = WindowToolbarAppButton() button.bezelStyle = .texturedRounded // The owning live document's window controller binds the button // to its inspected app. - return Self.item(LKToolBarIdentifier_App, label: NSLocalizedString("Select App", comment: ""), view: button) + return Self.item(toolbarIdentifierApp, label: NSLocalizedString("Select App", comment: ""), view: button) - case LKToolBarIdentifier_SwiftUIMode: + case toolbarIdentifierSwiftUIMode: let segmented = NSSegmentedControl( labels: [NSLocalizedString("Compact", comment: ""), NSLocalizedString("Verbose", comment: "")], trackingMode: .selectOne, @@ -107,30 +107,30 @@ final class WindowToolbarHelper: NSObject { action: #selector(SwiftUIHierarchyDisplayModeStore.swiftUIModeSegmentChanged(_:)) ) segmented.selectedSegment = SwiftUIHierarchyDisplayModeStore.currentMode() == .compact ? 0 : 1 - return Self.item(LKToolBarIdentifier_SwiftUIMode, label: NSLocalizedString("SwiftUI", comment: ""), view: segmented) + return Self.item(toolbarIdentifierSwiftUIMode, label: NSLocalizedString("SwiftUI", comment: ""), view: segmented) - case LKToolBarIdentifier_Console: + case toolbarIdentifierConsole: let button = Self.imageButton("icon_console", buttonType: .pushOnPushOff) - return Self.item(LKToolBarIdentifier_Console, label: NSLocalizedString("Console", comment: ""), view: button) + return Self.item(toolbarIdentifierConsole, label: NSLocalizedString("Console", comment: ""), view: button) - case LKToolBarIdentifier_FastMode: + case toolbarIdentifierFastMode: let button = Self.imageButton("icon_turbo", buttonType: .pushOnPushOff) manager.fastMode.subscribe(self, action: #selector(handleOnOffDidChange(_:)), relatedObject: button, sendAtOnce: true) - return Self.item(LKToolBarIdentifier_FastMode, label: NSLocalizedString("Fast Mode", comment: ""), view: button) + return Self.item(toolbarIdentifierFastMode, label: NSLocalizedString("Fast Mode", comment: ""), view: button) - case LKToolBarIdentifier_Add: + case toolbarIdentifierAdd: let button = NSButton() let image = NSImage(named: NSImage.addTemplateName) image?.isTemplate = true button.image = image button.bezelStyle = .texturedRounded - return Self.item(LKToolBarIdentifier_Add, label: nil, view: button) + return Self.item(toolbarIdentifierAdd, label: nil, view: button) - case LKToolBarIdentifier_Remove: - return Self.item(LKToolBarIdentifier_Remove, label: nil, view: Self.imageButton("icon_delete")) + case toolbarIdentifierRemove: + return Self.item(toolbarIdentifierRemove, label: nil, view: Self.imageButton("icon_delete")) - case LKToolBarIdentifier_Message: - return Self.item(LKToolBarIdentifier_Message, label: nil, view: Self.imageButton("icon_notification")) + case toolbarIdentifierMessage: + return Self.item(toolbarIdentifierMessage, label: nil, view: Self.imageButton("icon_notification")) default: assertionFailure("Unknown toolbar item identifier \(identifier)") @@ -144,7 +144,7 @@ final class WindowToolbarHelper: NSObject { let button = WindowToolbarAppButton() button.bezelStyle = .texturedRounded button.appInfo = appInfo - return Self.item(LKToolBarIdentifier_AppInReadMode, label: "iOS App", view: button) + return Self.item(toolbarIdentifierAppInReadMode, label: "iOS App", view: button) } // MARK: - Building @@ -197,8 +197,8 @@ final class WindowToolbarHelper: NSObject { let scale = ToolbarRules.stepped( manager.previewScale.currentDoubleValue, by: delta, - lower: Double(LookinPreviewMinScale), - upper: Double(LookinPreviewMaxScale) + lower: Double(previewMinScale), + upper: Double(previewMaxScale) ) manager.previewScale.setDoubleValue(scale, ignoreSubscriber: nil) } diff --git a/Scripts/test-gesture-models.sh b/Scripts/test-gesture-models.sh index 7fb4c9a1..fd71745f 100755 --- a/Scripts/test-gesture-models.sh +++ b/Scripts/test-gesture-models.sh @@ -5,7 +5,7 @@ ROOT="$(cd "$(dirname "$0")/.." && pwd)" GESTURE_TEST_DIR="$(mktemp -d "${TMPDIR:-/tmp}/lookinside-gesture-models.XXXXXX")" trap 'rm -rf "$GESTURE_TEST_DIR"' EXIT swiftc -parse-as-library -import-objc-header "$ROOT/Sources/LookinCore/include/LookinHitTargetSize.h" \ - "$ROOT/LookInside/GestureDebug/LKGestureCaptureModels.swift" \ - "$ROOT/LookInside/GestureDebug/LKSuggestions.swift" \ + "$ROOT/LookInside/GestureDebug/GestureCaptureModels.swift" \ + "$ROOT/LookInside/GestureDebug/HitTargetSuggestions.swift" \ "$ROOT/Tests/GestureDebug/GestureCaptureModelsTests.swift" -o "$GESTURE_TEST_DIR/gesture-models" "$GESTURE_TEST_DIR/gesture-models" diff --git a/Scripts/test-mcp-bridge.sh b/Scripts/test-mcp-bridge.sh index d77afb02..5f290bd7 100755 --- a/Scripts/test-mcp-bridge.sh +++ b/Scripts/test-mcp-bridge.sh @@ -27,9 +27,9 @@ SEARCH_QUERY_TEST="$ROOT/Tests/MCPBridge/MCPBridgeSearchQueryTests.swift" swiftc -parse-as-library "$SEARCH_QUERY" "$SEARCH_QUERY_TEST" -o "$TMPDIR/search-query-test" "$TMPDIR/search-query-test" -# The identifier list needs LKMCPBridgeFrame.swift alongside it for +# The identifier list needs MCPBridgeFrame.swift alongside it for # LKMCPBridgeJSONValue; that file is Foundation-only, so it compiles here. -FRAME="$ROOT/LookInside/MCPBridge/LKMCPBridgeFrame.swift" +FRAME="$ROOT/LookInside/MCPBridge/MCPBridgeFrame.swift" OBJECT_IDENTIFIER_LIST="$ROOT/LookInside/MCPBridge/MCPBridgeObjectIdentifierList.swift" OBJECT_IDENTIFIER_LIST_TEST="$ROOT/Tests/MCPBridge/MCPBridgeObjectIdentifierListTests.swift" diff --git a/Tests/Read/LaunchToolbarReadTests.swift b/Tests/Read/LaunchToolbarReadTests.swift index 3cc8ec78..a785e454 100644 --- a/Tests/Read/LaunchToolbarReadTests.swift +++ b/Tests/Read/LaunchToolbarReadTests.swift @@ -149,13 +149,13 @@ struct LaunchToolbarReadTests { private static func testToolbarIdentifiersKeepTheirValues() { let identifiers: [(String, String)] = [ - (LKToolBarIdentifier_Dimension, "0"), (LKToolBarIdentifier_Scale, "1"), - (LKToolBarIdentifier_Setting, "2"), (LKToolBarIdentifier_Reload, "3"), - (LKToolBarIdentifier_App, "5"), (LKToolBarIdentifier_AppInReadMode, "12"), - (LKToolBarIdentifier_Add, "13"), (LKToolBarIdentifier_Remove, "14"), - (LKToolBarIdentifier_Console, "15"), (LKToolBarIdentifier_Rotation, "16"), - (LKToolBarIdentifier_Measure, "17"), (LKToolBarIdentifier_Message, "18"), - (LKToolBarIdentifier_FastMode, "19"), (LKToolBarIdentifier_SwiftUIMode, "20"), + (toolbarIdentifierDimension, "0"), (toolbarIdentifierScale, "1"), + (toolbarIdentifierSetting, "2"), (toolbarIdentifierReload, "3"), + (toolbarIdentifierApp, "5"), (toolbarIdentifierAppInReadMode, "12"), + (toolbarIdentifierAdd, "13"), (toolbarIdentifierRemove, "14"), + (toolbarIdentifierConsole, "15"), (toolbarIdentifierRotation, "16"), + (toolbarIdentifierMeasure, "17"), (toolbarIdentifierMessage, "18"), + (toolbarIdentifierFastMode, "19"), (toolbarIdentifierSwiftUIMode, "20"), ] for (identifier, value) in identifiers { expect(identifier == value, "toolbar identifier \(value)") From f5733bd6277826203558d080a1fcd475ebe6a0e5 Mon Sep 17 00:00:00 2001 From: Mx-Iris Date: Fri, 9 Oct 2026 01:22:17 +0800 Subject: [PATCH 4/5] Replace the host's implicitly unwrapped optionals Each declaration now says whether it can be nil: - Views and controllers that always exist are non-optional. The subviews StaticViewController, DashboardViewController, PreviewController and the JSON attribute view used to create during view setup are created where they are declared; the controls whose target is self are lazy and still created where init first touches them. StaticViewController creates its child controllers in init, before the superclass initializer builds its view (which is when buildContent() used to create them), and StaticWindowController creates its data source, update manager and view controller before super.init(window:). - HierarchyView, HierarchyController and HierarchyRowView take their data source non-optionally and cannot fail to initialize. - HierarchyViewDelegate says which item can be nil: the selection, the hovered row and the search string can; the double-clicked, expanded, collapsed and previewed items cannot, and the menu handlers check before they call. TableViewDelegate passes its sender non-optionally. - HierarchyDataSource.preferenceManager() always returns one. - reload(with:keepState:) accepts the nil it is handed when the server's reply is not a hierarchy, where the implicit unwrap used to trap. - InjectableFrameworkInstaller runs the main-thread install with DispatchQueue.main.sync's return value instead of a captured result. Co-Authored-By: Claude Opus 5.5 --- LookInside/Base/OutlineRowView.swift | 6 +- LookInside/Base/TableRowView.swift | 4 +- LookInside/Base/TableView.swift | 10 +-- LookInside/Connection/LiveDocument.swift | 4 +- ...ardAttributePrivateDiscriminatorView.swift | 26 +++---- .../DashboardAttributeTextView.swift | 3 +- .../JSON/JSONAttributeViews.swift | 5 +- LookInside/Dashboard/DashboardCardView.swift | 3 +- .../Dashboard/DashboardViewController.swift | 16 ++-- LookInside/DebugE2E/DebugUISnapshots.swift | 9 ++- .../Hierarchy/HierarchyController.swift | 26 +++---- .../Hierarchy/HierarchyDataSource.swift | 76 +++++++++---------- LookInside/Hierarchy/HierarchyRowView.swift | 2 +- LookInside/Hierarchy/HierarchyView.swift | 54 +++++++------ .../InjectableFrameworkInstaller.swift | 17 ++--- LookInside/Read/ReadHierarchyController.swift | 2 +- LookInside/Read/ReadHierarchyDataSource.swift | 2 +- LookInside/Read/ReadViewController.swift | 4 +- .../Static/Preview/PreviewController.swift | 21 +++-- .../Static/StaticAsyncUpdateManager.swift | 2 +- .../Static/StaticHierarchyController.swift | 12 +-- .../Static/StaticHierarchyDataSource.swift | 14 ++-- LookInside/Static/StaticViewController.swift | 72 ++++++++---------- .../Static/StaticWindowController.swift | 26 +++---- 24 files changed, 194 insertions(+), 222 deletions(-) diff --git a/LookInside/Base/OutlineRowView.swift b/LookInside/Base/OutlineRowView.swift index 0ce26bff..8d8bf36d 100644 --- a/LookInside/Base/OutlineRowView.swift +++ b/LookInside/Base/OutlineRowView.swift @@ -20,8 +20,8 @@ private let disclosureWidth: CGFloat = 16 @objc(LKOutlineRowView) @objcMembers class OutlineRowView: TableRowView { - let disclosureButton: NSButton! - let imageView: NSImageView! + let disclosureButton: NSButton + let imageView: NSImageView var image: NSImage? { didSet { @@ -95,7 +95,7 @@ class OutlineRowView: TableRowView { HierarchyFrameLayout(subtitleLabel).sizeToFit().x(titleLabel.frame.maxX + subtitleLeft).verAlign() maxX = subtitleLabel.frame.maxX } - for view: NSView in [disclosureButton!, titleLabel!, subtitleLabel!] where view.hierarchyIsLaidOutVisible { + for view: NSView in [disclosureButton, titleLabel, subtitleLabel] where view.hierarchyIsLaidOutVisible { HierarchyFrameLayout(view).offsetY(-1) } diff --git a/LookInside/Base/TableRowView.swift b/LookInside/Base/TableRowView.swift index 341a9c3c..9da0eb8e 100644 --- a/LookInside/Base/TableRowView.swift +++ b/LookInside/Base/TableRowView.swift @@ -11,8 +11,8 @@ import AppKit @objc(LKTableRowView) @objcMembers class TableRowView: NSTableRowView { - let titleLabel: TextLabel! - let subtitleLabel: TextLabel! + let titleLabel: TextLabel + let subtitleLabel: TextLabel /// The selection TableView draws. NSTableView's own row selection /// (setSelected:) does not change it, but isSelected reports this value. diff --git a/LookInside/Base/TableView.swift b/LookInside/Base/TableView.swift index cfbe76e3..0602ec8e 100644 --- a/LookInside/Base/TableView.swift +++ b/LookInside/Base/TableView.swift @@ -22,14 +22,14 @@ private final class KeyForwardingTableView: NSTableView { @objc(LKTableViewDelegate) protocol TableViewDelegate: NSTableViewDelegate { @objc(tableView:didSelectRow:) - optional func tableView(_ tableView: TableView!, didSelectRow row: Int) + optional func tableView(_ tableView: TableView, didSelectRow row: Int) @objc(tableView:didHoverAtRow:) - optional func tableView(_ tableView: TableView!, didHoverAtRow row: Int) + optional func tableView(_ tableView: TableView, didHoverAtRow row: Int) @objc(tableView:didDoubleClickAtRow:) - optional func tableView(_ tableView: TableView!, didDoubleClickAtRow row: Int) + optional func tableView(_ tableView: TableView, didDoubleClickAtRow row: Int) /// A click on the blank area below the rows. @objc(tableViewDidClickBlankArea:) - optional func tableViewDidClickBlankArea(_ tableView: TableView!) + optional func tableViewDidClickBlankArea(_ tableView: TableView) } @objc(LKTableViewDataSource) @@ -37,7 +37,7 @@ protocol TableViewDataSource: NSTableViewDataSource {} @objc(LKTableView) class TableView: NSScrollView { - @objc let tableView: NSTableView! + @objc let tableView: NSTableView /// Defaults to true. @objc var canScrollHorizontally: Bool = true { diff --git a/LookInside/Connection/LiveDocument.swift b/LookInside/Connection/LiveDocument.swift index 850eb658..00333da1 100644 --- a/LookInside/Connection/LiveDocument.swift +++ b/LookInside/Connection/LiveDocument.swift @@ -77,7 +77,7 @@ final class LiveDocument: NSDocument { // MARK: - NSDocument - override var displayName: String! { + override var displayName: String? { get { let info = inspectableApp.appInfo let appName = info?.appName ?? "" @@ -205,7 +205,7 @@ final class LiveDocument: NSDocument { // here would leave them with nil, so they get the new app too. for case let windowController as StaticWindowController in windowControllers { windowController.inspectableApp = newApp - windowController.asyncUpdateManager?.inspectableApp = newApp + windowController.asyncUpdateManager.inspectableApp = newApp } connectionLossBannerMessage = nil reconnectTask = nil diff --git a/LookInside/Dashboard/AttributeView/DashboardAttributePrivateDiscriminatorView.swift b/LookInside/Dashboard/AttributeView/DashboardAttributePrivateDiscriminatorView.swift index 05e3e9db..aab1c830 100644 --- a/LookInside/Dashboard/AttributeView/DashboardAttributePrivateDiscriminatorView.swift +++ b/LookInside/Dashboard/AttributeView/DashboardAttributePrivateDiscriminatorView.swift @@ -61,26 +61,28 @@ final class DashboardAttributePrivateDiscriminatorView: DashboardAttributeView { private let idCard = BaseView() private let idTitleLabel = TextLabel() private let idValueLabel = PrivateDiscriminatorCopyLabel() - private var idCopyButton: NSButton! + private lazy var idCopyButton = makeCopyButton() private let moduleCard = BaseView() private let moduleTitleLabel = TextLabel() private let moduleField = NSTextField() private let moduleValueLabel = PrivateDiscriminatorCopyLabel() - private var moduleCopyButton: NSButton! + private lazy var moduleCopyButton = makeCopyButton() private let filenameCard = BaseView() private let filenameTitleLabel = TextLabel() private let filenameField = NSTextField() private let filenameValueLabel = PrivateDiscriminatorCopyLabel() - private var filenameCopyButton: NSButton! + private lazy var filenameCopyButton = makeCopyButton() private let sourceLabel = TextLabel() private let messageLabel = TextLabel() - private var importButton: NSButton! - private var guessButton: NSButton! - private var cancelButton: NSButton! + // Lazy because their target is self; init touches each of them where it + // used to create it. + private lazy var importButton = NSButton.normalButton(withTitle: NSLocalizedString("Import from your codebase", comment: ""), target: self, action: #selector(handleImportButton(_:))) + private lazy var guessButton = NSButton.normalButton(withTitle: NSLocalizedString("Guess by swift-pd-guess", comment: ""), target: self, action: #selector(handleGuessButton(_:))) + private lazy var cancelButton = NSButton.normalButton(withTitle: NSLocalizedString("Cancel", comment: ""), target: self, action: #selector(handleCancelButton(_:))) private let toastView = BaseView() private let toastLabel = TextLabel() @@ -97,7 +99,6 @@ final class DashboardAttributePrivateDiscriminatorView: DashboardAttributeView { setUpCard(idCard, titleLabel: idTitleLabel, title: NSLocalizedString("ID", comment: "")) setUpCopyLabel(idValueLabel, name: NSLocalizedString("ID", comment: "")) idValueLabel.font = .monospacedSystemFont(ofSize: 12, weight: .regular) - idCopyButton = makeCopyButton() idCard.addSubview(idTitleLabel) idCard.addSubview(idValueLabel) idCard.addSubview(idCopyButton) @@ -105,7 +106,6 @@ final class DashboardAttributePrivateDiscriminatorView: DashboardAttributeView { setUpCard(moduleCard, titleLabel: moduleTitleLabel, title: NSLocalizedString("Module", comment: "")) setUpTextField(moduleField, placeholder: NSLocalizedString("ModuleName", comment: "")) setUpCopyLabel(moduleValueLabel, name: NSLocalizedString("Module", comment: "")) - moduleCopyButton = makeCopyButton() moduleCard.addSubview(moduleTitleLabel) moduleCard.addSubview(moduleField) moduleCard.addSubview(moduleValueLabel) @@ -114,7 +114,6 @@ final class DashboardAttributePrivateDiscriminatorView: DashboardAttributeView { setUpCard(filenameCard, titleLabel: filenameTitleLabel, title: NSLocalizedString("Filename", comment: "")) setUpTextField(filenameField, placeholder: NSLocalizedString("File.swift", comment: "")) setUpCopyLabel(filenameValueLabel, name: NSLocalizedString("Filename", comment: "")) - filenameCopyButton = makeCopyButton() filenameCard.addSubview(filenameTitleLabel) filenameCard.addSubview(filenameField) filenameCard.addSubview(filenameValueLabel) @@ -129,13 +128,10 @@ final class DashboardAttributePrivateDiscriminatorView: DashboardAttributeView { messageLabel.maximumNumberOfLines = 0 messageLabel.lineBreakMode = .byWordWrapping - importButton = NSButton.normalButton(withTitle: NSLocalizedString("Import from your codebase", comment: ""), target: self, action: #selector(handleImportButton(_:))) importButton.font = DashboardStyle.font(12) - guessButton = NSButton.normalButton(withTitle: NSLocalizedString("Guess by swift-pd-guess", comment: ""), target: self, action: #selector(handleGuessButton(_:))) guessButton.font = DashboardStyle.font(12) - cancelButton = NSButton.normalButton(withTitle: NSLocalizedString("Cancel", comment: ""), target: self, action: #selector(handleCancelButton(_:))) cancelButton.font = DashboardStyle.font(12) toastView.layer?.cornerRadius = DashboardMetrics.cardControlCornerRadius @@ -513,9 +509,9 @@ final class DashboardAttributePrivateDiscriminatorView: DashboardAttributeView { super.updateColors() let isDarkMode = isDarkMode() let iconColor: NSColor = isDarkMode ? .secondaryLabelColor : .tertiaryLabelColor - idCopyButton?.contentTintColor = iconColor - moduleCopyButton?.contentTintColor = iconColor - filenameCopyButton?.contentTintColor = iconColor + idCopyButton.contentTintColor = iconColor + moduleCopyButton.contentTintColor = iconColor + filenameCopyButton.contentTintColor = iconColor toastView.backgroundColor = NSColor.controlAccentColor.withAlphaComponent(isDarkMode ? 0.9 : 0.85) } diff --git a/LookInside/Dashboard/AttributeView/DashboardAttributeTextView.swift b/LookInside/Dashboard/AttributeView/DashboardAttributeTextView.swift index 0ef6f34a..5579aaee 100644 --- a/LookInside/Dashboard/AttributeView/DashboardAttributeTextView.swift +++ b/LookInside/Dashboard/AttributeView/DashboardAttributeTextView.swift @@ -15,7 +15,7 @@ final class DashboardAttributeTextView: DashboardAttributeView, NSTextViewDelega private let titleLabel = TextLabel() private let scrollView: NSScrollView private let textView: NSTextView - private var jumpButton: NSButton! + private lazy var jumpButton = NSButton(image: DashboardStyle.image("Icon_JumpDisclosure") ?? NSImage(), target: self, action: #selector(handleJumpButton(_:))) private var initialText = "" @@ -41,7 +41,6 @@ final class DashboardAttributeTextView: DashboardAttributeView, NSTextViewDelega textView.delegate = self addSubview(scrollView) - jumpButton = NSButton(image: DashboardStyle.image("Icon_JumpDisclosure") ?? NSImage(), target: self, action: #selector(handleJumpButton(_:))) jumpButton.bezelStyle = .roundRect jumpButton.isBordered = false jumpButton.toolTip = NSLocalizedString("Jump in hierarchy", comment: "") diff --git a/LookInside/Dashboard/AttributeView/JSON/JSONAttributeViews.swift b/LookInside/Dashboard/AttributeView/JSON/JSONAttributeViews.swift index d7749a32..14d0fed0 100644 --- a/LookInside/Dashboard/AttributeView/JSON/JSONAttributeViews.swift +++ b/LookInside/Dashboard/AttributeView/JSON/JSONAttributeViews.swift @@ -204,13 +204,13 @@ final class DashboardAttributeJSONView: DashboardAttributeView { final class JSONAttributeViewController: BaseViewController, TableViewDelegate, TableViewDataSource { private static let rowIdentifier = NSUserInterfaceItemIdentifier("myView") - private var tableView: TableView! + private let tableView = TableView() private let tree = JSONAttributeTree() override func makeContainerView() -> NSView { let containerView = BaseView() - let tableView = TableView() + let tableView = self.tableView tableView.drawsBackground = false tableView.delegate = self tableView.dataSource = self @@ -220,7 +220,6 @@ final class JSONAttributeViewController: BaseViewController, TableViewDelegate, tableView.automaticallyAdjustsContentInsets = false tableView.contentInsets = NSEdgeInsets(top: 5, left: 0, bottom: 5, right: 0) containerView.addSubview(tableView) - self.tableView = tableView return containerView } diff --git a/LookInside/Dashboard/DashboardCardView.swift b/LookInside/Dashboard/DashboardCardView.swift index 8a69669f..d7914575 100644 --- a/LookInside/Dashboard/DashboardCardView.swift +++ b/LookInside/Dashboard/DashboardCardView.swift @@ -64,7 +64,7 @@ final class DashboardCardView: BaseView, UserActionManagerDelegate, DashboardAcc private let backgroundEffectView = VisualEffectView() private let titleControl = DashboardCardTitleControl() - private var detailButton: NSButton! + private lazy var detailButton = NSButton(image: DashboardStyle.image("icon_more") ?? NSImage(), target: self, action: #selector(handleClickDetailButton)) private var relationHelpButton: NSButton? private var fadeView: BaseView? @@ -95,7 +95,6 @@ final class DashboardCardView: BaseView, UserActionManagerDelegate, DashboardAcc titleControl.addTarget(self, clickAction: #selector(handleClickTitle)) addSubview(titleControl) - detailButton = NSButton(image: DashboardStyle.image("icon_more") ?? NSImage(), target: self, action: #selector(handleClickDetailButton)) detailButton.bezelStyle = .roundRect detailButton.isBordered = false addSubview(detailButton) diff --git a/LookInside/Dashboard/DashboardViewController.swift b/LookInside/Dashboard/DashboardViewController.swift index 65996565..c797ca35 100644 --- a/LookInside/Dashboard/DashboardViewController.swift +++ b/LookInside/Dashboard/DashboardViewController.swift @@ -15,11 +15,11 @@ import AppKit @objc(LKDashboardViewController) final class DashboardViewController: BaseViewController, DashboardCardViewDelegate, DashboardHeaderViewDelegate, DashboardSearchPropertyViewDelegate, DashboardSearchMethodsViewDelegate { /// Read by key by the DEBUG UI snapshots. - @objc private(set) var scrollView: NSScrollView! - private var documentView: BaseView! - private var cardContainerView: BaseView! - private var searchContainerView: BaseView! - private var headerView: DashboardHeaderView! + @objc let scrollView = NSScrollView() + private let documentView = BaseView() + private let cardContainerView = BaseView() + private let searchContainerView = BaseView() + private let headerView = DashboardHeaderView() private var groupList: [AttributesGroup] = [] /// Keyed by `AttributesGroup.uniqueKey`. @@ -83,9 +83,6 @@ final class DashboardViewController: BaseViewController, DashboardCardViewDelega override func makeContainerView() -> NSView { let containerView = BaseView() - documentView = BaseView() - - scrollView = NSScrollView() scrollView.drawsBackground = false scrollView.hasVerticalScroller = true scrollView.hasHorizontalScroller = false @@ -93,14 +90,11 @@ final class DashboardViewController: BaseViewController, DashboardCardViewDelega scrollView.contentView.documentView = documentView containerView.addSubview(scrollView) - headerView = DashboardHeaderView() headerView.delegate = self documentView.addSubview(headerView) - cardContainerView = BaseView() documentView.addSubview(cardContainerView) - searchContainerView = BaseView() searchContainerView.isHidden = true documentView.addSubview(searchContainerView) diff --git a/LookInside/DebugE2E/DebugUISnapshots.swift b/LookInside/DebugE2E/DebugUISnapshots.swift index 6291158e..6a691fac 100644 --- a/LookInside/DebugE2E/DebugUISnapshots.swift +++ b/LookInside/DebugE2E/DebugUISnapshots.swift @@ -152,9 +152,9 @@ private func documentScenes(_ document: LiveDocument) async throws { guard let windowController = document.windowControllers.first as? StaticWindowController, let window = windowController.window, - let viewController = windowController.viewController, let dataSource = document.hierarchyDataSource else { throw SnapshotError("the live document has no inspector window") } + let viewController = windowController.viewController let preferences = PreferenceManager.shared quietWindows() pinSize(of: window, to: Self.documentContentSize) @@ -242,9 +242,10 @@ let readViewController = try await waitFor("the reader to load the file") { (document.windowControllers.first?.contentViewController as? ReadViewController) } - guard let window = document.windowControllers.first?.window, - let dataSource = readViewController.hierarchyDataSource - else { throw SnapshotError("the reader has no window") } + guard let window = document.windowControllers.first?.window else { + throw SnapshotError("the reader has no window") + } + let dataSource = readViewController.hierarchyDataSource quietWindows() pinSize(of: window, to: Self.documentContentSize) let nodes = SnapshotNormalizer.collectNodes(roots: dataSource.rawHierarchyInfo?.displayItems ?? []) diff --git a/LookInside/Hierarchy/HierarchyController.swift b/LookInside/Hierarchy/HierarchyController.swift index 0da4c21b..17ba72a7 100644 --- a/LookInside/Hierarchy/HierarchyController.swift +++ b/LookInside/Hierarchy/HierarchyController.swift @@ -11,24 +11,24 @@ import AppKit @objc(LKHierarchyController) @objcMembers class HierarchyController: BaseViewController, HierarchyViewDelegate { - private(set) var dataSource: HierarchyDataSource! - private(set) var hierarchyView: HierarchyView! + private(set) var dataSource: HierarchyDataSource + private(set) var hierarchyView: HierarchyView - init!(dataSource: HierarchyDataSource!) { + init(dataSource: HierarchyDataSource) { let hierarchyView = HierarchyView(dataSource: dataSource) self.dataSource = dataSource self.hierarchyView = hierarchyView super.init(containerView: hierarchyView) - hierarchyView?.delegate = self + hierarchyView.delegate = self } required init?(coder _: NSCoder) { fatalError("HierarchyController is not loaded from archives") } - func currentSelectedRowView() -> NSView! { + func currentSelectedRowView() -> NSView? { guard let selectedItem = dataSource.selectedItem, - let row = dataSource.displayingFlatItems.firstIndex(where: { $0 === selectedItem }) + let row = (dataSource.displayingFlatItems ?? []).firstIndex(where: { $0 === selectedItem }) else { return nil } @@ -49,12 +49,12 @@ class HierarchyController: BaseViewController, HierarchyViewDelegate { // MARK: - HierarchyViewDelegate @objc(hierarchyView:didSelectItem:) - func hierarchyView(_: HierarchyView!, didSelect item: DisplayItem!) { + func hierarchyView(_: HierarchyView, didSelect item: DisplayItem?) { dataSource.selectedItem = item } @objc(hierarchyView:didDoubleClickItem:) - func hierarchyView(_: HierarchyView!, didDoubleClick item: DisplayItem!) { + func hierarchyView(_: HierarchyView, didDoubleClick item: DisplayItem) { switch PreferenceManager.shared.doubleClickBehavior { case .collapse: guard item.isExpandable else { @@ -74,22 +74,22 @@ class HierarchyController: BaseViewController, HierarchyViewDelegate { /// `item` is nil when the mouse leaves the rows. @objc(hierarchyView:didHoverAtItem:) - func hierarchyView(_: HierarchyView!, didHoverAt item: DisplayItem!) { + func hierarchyView(_: HierarchyView, didHoverAt item: DisplayItem?) { dataSource.hoveredItem = item } @objc(hierarchyView:needToCollapseItem:) - func hierarchyView(_: HierarchyView!, needToCollapse item: DisplayItem!) { + func hierarchyView(_: HierarchyView, needToCollapse item: DisplayItem) { dataSource.collapse(item) } @objc(hierarchyView:needToCollapseChildrenOfItem:) - func hierarchyView(_: HierarchyView!, needToCollapseChildrenOf item: DisplayItem!) { + func hierarchyView(_: HierarchyView, needToCollapseChildrenOf item: DisplayItem) { dataSource.collapseAllChildren(of: item) } @objc(hierarchyView:needToExpandItem:recursively:) - func hierarchyView(_: HierarchyView!, needToExpand item: DisplayItem!, recursively: Bool) { + func hierarchyView(_: HierarchyView, needToExpand item: DisplayItem, recursively: Bool) { if recursively { dataSource.expandItemsRooted(by: item) } else { @@ -98,7 +98,7 @@ class HierarchyController: BaseViewController, HierarchyViewDelegate { } @objc(hierarchyView:didInputSearchString:) - func hierarchyView(_: HierarchyView!, didInputSearch string: String!) { + func hierarchyView(_: HierarchyView, didInputSearch string: String?) { NSLog("search string:%@", string ?? "(null)") if let string, !string.isEmpty { dataSource.search(with: string) diff --git a/LookInside/Hierarchy/HierarchyDataSource.swift b/LookInside/Hierarchy/HierarchyDataSource.swift index 08213dfa..ffe4228d 100644 --- a/LookInside/Hierarchy/HierarchyDataSource.swift +++ b/LookInside/Hierarchy/HierarchyDataSource.swift @@ -117,7 +117,7 @@ class HierarchyDataSource: NSObject { final let didReloadFlatItemsWithSearchOrFocus = SyncSignal() /// Every display item of the tree, visible or not. - @objc var rawFlatItems: [DisplayItem]! { + @objc var rawFlatItems: [DisplayItem]? { get { storedRawFlatItems } set { storedRawFlatItems = newValue @@ -127,11 +127,11 @@ class HierarchyDataSource: NSObject { /// All items in normal state; the shown subset while searching or /// focusing. - @objc dynamic var flatItems: [DisplayItem]! + @objc dynamic var flatItems: [DisplayItem]? /// The rows: the items of `flatItems` that no collapsed ancestor hides. /// KVO-observable. - @objc dynamic var displayingFlatItems: [DisplayItem]! { + @objc dynamic var displayingFlatItems: [DisplayItem]? { storedDisplayingFlatItems } @@ -147,7 +147,7 @@ class HierarchyDataSource: NSObject { } } - @objc var selectColorMenu: NSMenu! { + @objc var selectColorMenu: NSMenu? { storedSelectColorMenu } @@ -162,7 +162,7 @@ class HierarchyDataSource: NSObject { } /// KVO-observable. - @objc dynamic var rawHierarchyInfo: HierarchyInfo! { + @objc dynamic var rawHierarchyInfo: HierarchyInfo? { storedRawHierarchyInfo } @@ -222,7 +222,7 @@ class HierarchyDataSource: NSObject { // MARK: - Reload @objc(reloadWithHierarchyInfo:keepState:) - func reload(with info: HierarchyInfo!, keepState: Bool) { + func reload(with info: HierarchyInfo?, keepState: Bool) { // Path identifiers of the old items resolve their root index against // the old root items, so take them before replacing the info. let previousRootItems = rawHierarchyInfo?.displayItems ?? [] @@ -231,16 +231,16 @@ class HierarchyDataSource: NSObject { willReloadHierarchyInfo.send() - if !(info.colorAlias ?? [:]).isEmpty { + if !(info?.colorAlias ?? [:]).isEmpty { PreferenceManager.shared.receivingConfigTime_Color = Date().timeIntervalSince1970 } - if !(info.collapsedClassList ?? []).isEmpty { + if !(info?.collapsedClassList ?? []).isEmpty { PreferenceManager.shared.receivingConfigTime_Class = Date().timeIntervalSince1970 } var previousSelectedOid: UInt = 0 var previousExpansion: [String: NSNumber] = [:] - let prefersViewOID = AppHelper.appInfoLooksLikeMacTarget(info.appInfo) + let prefersViewOID = AppHelper.appInfoLooksLikeMacTarget(info?.appInfo) if keepState { previousSelectedOid = selectedItem?.bestObjectOidPreferView(prefersViewOID) ?? 0 for item in flatItems ?? [] { @@ -253,10 +253,10 @@ class HierarchyDataSource: NSObject { setUpColors() // Flatten the tree; this also sets every item's indentLevel. - rawFlatItems = DisplayItem.flatItems(fromHierarchicalItems: info.displayItems ?? []) + rawFlatItems = DisplayItem.flatItems(fromHierarchicalItems: info?.displayItems ?? []) let items = rawFlatItems ?? [] - let collapsedClasses = classesPreferredToCollapse.union(info.collapsedClassList ?? []) + let collapsedClasses = classesPreferredToCollapse.union(info?.collapsedClassList ?? []) for item in items { if item.itemIsKindOfClasses(withNames: collapsedClasses) { item.enumerateSelfAndChildren { $0.preferToBeCollapsed = true } @@ -308,8 +308,8 @@ class HierarchyDataSource: NSObject { // (expanded and user-collapsed items). Paths it lacks keep the // preset's behavior. let preferences = preferenceManager() - if let preferences, preferences.rememberExpansionState, - let bundleIdentifier = info.appInfo?.appBundleIdentifier, !bundleIdentifier.isEmpty + if preferences.rememberExpansionState, + let bundleIdentifier = info?.appInfo?.appBundleIdentifier, !bundleIdentifier.isEmpty { let stored = preferences.expansionState(forBundleIdentifier: bundleIdentifier) if !stored.isEmpty { @@ -342,7 +342,7 @@ class HierarchyDataSource: NSObject { } @objc(itemAtRow:) - func item(atRow index: Int) -> DisplayItem! { + func item(atRow index: Int) -> DisplayItem? { guard let rows = displayingFlatItems, rows.indices.contains(index) else { return nil } @@ -350,12 +350,12 @@ class HierarchyDataSource: NSObject { } @objc(rowForItem:) - func row(for item: DisplayItem!) -> Int { + func row(for item: DisplayItem?) -> Int { displayingFlatItems?.firstIndex { $0 === item } ?? NSNotFound } @objc(displayItemWithOid:) - func displayItem(withOid oid: UInt) -> DisplayItem! { + func displayItem(withOid oid: UInt) -> DisplayItem? { oidToDisplayItem[oid] } @@ -404,9 +404,8 @@ class HierarchyDataSource: NSObject { } // Clearing the selection ends measuring. - if item == nil, let measureState = preferenceManager()?.measureState, - measureState.currentIntegerValue != MeasureState.no.rawValue - { + let measureState = preferenceManager().measureState + if item == nil, measureState.currentIntegerValue != MeasureState.no.rawValue { measureState.setIntegerValue(MeasureState.no.rawValue, ignoreSubscriber: nil) } } @@ -421,7 +420,7 @@ class HierarchyDataSource: NSObject { } @objc(selectAndRevealItem:) - func selectAndRevealItem(_ item: DisplayItem!) { + func selectAndRevealItem(_ item: DisplayItem?) { guard let item else { return } @@ -459,8 +458,8 @@ class HierarchyDataSource: NSObject { @objc(adjustExpansionByIndex:referenceDict:selectedItem:) func adjustExpansion( by index: Int, - referenceDict: [String: NSNumber]!, - selectedItem: AutoreleasingUnsafeMutablePointer! + referenceDict: [String: NSNumber]?, + selectedItem: AutoreleasingUnsafeMutablePointer? ) { var index = index if index < 0 || index > 4 { @@ -663,7 +662,7 @@ class HierarchyDataSource: NSObject { } @objc(collapseItem:) - func collapse(_ item: DisplayItem!) { + func collapse(_ item: DisplayItem?) { guard let item, item.isExpandable, item.isExpanded else { return } @@ -673,7 +672,7 @@ class HierarchyDataSource: NSObject { } @objc(expandItem:) - func expand(_ item: DisplayItem!) { + func expand(_ item: DisplayItem?) { guard let item, item.isExpandable, !item.isExpanded else { return } @@ -683,7 +682,7 @@ class HierarchyDataSource: NSObject { } @objc(expandToShowItem:) - func expand(toShow item: DisplayItem!) { + func expand(toShow item: DisplayItem?) { var didChange = false item?.enumerateAncestors { ancestor, _ in guard !ancestor.isExpanded else { @@ -699,7 +698,7 @@ class HierarchyDataSource: NSObject { } @objc(expandItemsRootedByItem:) - func expandItemsRooted(by item: DisplayItem!) { + func expandItemsRooted(by item: DisplayItem?) { let includePreferredCollapsed = item?.preferToBeCollapsed ?? false item?.enumerateSelfAndChildren { node in guard node.isExpandable, !node.isExpanded else { @@ -714,7 +713,7 @@ class HierarchyDataSource: NSObject { } @objc(collapseAllChildrenOfItem:) - func collapseAllChildren(of item: DisplayItem!) { + func collapseAllChildren(of item: DisplayItem?) { item?.enumerateSelfAndChildren { node in guard node !== item, node.isExpandable, node.isExpanded else { return @@ -731,7 +730,7 @@ class HierarchyDataSource: NSObject { /// when a node of the chain has no class (UserCustom-only nodes), when /// a sibling index cannot be resolved, or when `rootItems` is empty. @objc(pathIdentifierForItem:inRootItems:) - class func pathIdentifier(for item: DisplayItem!, inRootItems rootItems: [DisplayItem]!) -> String! { + class func pathIdentifier(for item: DisplayItem?, inRootItems rootItems: [DisplayItem]?) -> String? { guard let item else { return nil } @@ -750,7 +749,8 @@ class HierarchyDataSource: NSObject { /// user's collapses too. Does nothing when remembering is off or there is /// no bundle identifier. @objc func persistExpansionStateToPreferences() { - guard let preferences = preferenceManager(), preferences.rememberExpansionState else { + let preferences = preferenceManager() + guard preferences.rememberExpansionState else { return } guard let bundleIdentifier = rawHierarchyInfo?.appInfo?.appBundleIdentifier, !bundleIdentifier.isEmpty else { @@ -778,7 +778,7 @@ class HierarchyDataSource: NSObject { /// Call while the user types a non-empty search string; replaces /// `flatItems` and `displayingFlatItems`. @objc(searchWithString:) - func search(with string: String!) { + func search(with string: String?) { guard let string, !string.isEmpty else { assertionFailure("searching for an empty string") return @@ -838,7 +838,7 @@ class HierarchyDataSource: NSObject { /// Entered from the normal or the search state. @objc(focusDisplayItem:) - func focus(_ item: DisplayItem!) { + func focus(_ item: DisplayItem?) { guard let item else { assertionFailure("focusing nil") return @@ -886,7 +886,7 @@ class HierarchyDataSource: NSObject { /// SwiftUI node -> its matched CALayer nodes; empty when there is none. @objc(swiftUIBackingLayerItemsForItem:) - func swiftUIBackingLayerItems(for item: DisplayItem!) -> [DisplayItem]! { + func swiftUIBackingLayerItems(for item: DisplayItem?) -> [DisplayItem]? { guard let item else { return [] } @@ -907,7 +907,7 @@ class HierarchyDataSource: NSObject { /// CALayer node -> its SwiftUI node, or nil. @objc(swiftUISourceItemForLayerItem:) - func swiftUISourceItem(forLayerItem item: DisplayItem!) -> DisplayItem! { + func swiftUISourceItem(forLayerItem item: DisplayItem?) -> DisplayItem? { guard let item, let displayListID = item.swiftUILayerDisplayListID() else { return nil } @@ -917,8 +917,8 @@ class HierarchyDataSource: NSObject { /// Dashboard row -> its SwiftUI / CALayer jump target, or nil when the /// row has none. @objc(swiftUIJumpTargetForAttribute:) - func swiftUIJumpTarget(for attribute: InspectedAttribute!) -> DisplayItem! { - guard let sourceItem = attribute?.targetDisplayItem, let value = attribute.value as? String else { + func swiftUIJumpTarget(for attribute: InspectedAttribute?) -> DisplayItem? { + guard let attribute, let sourceItem = attribute.targetDisplayItem, let value = attribute.value as? String else { return nil } let title = attribute.displayTitle ?? "" @@ -1011,7 +1011,7 @@ class HierarchyDataSource: NSObject { /// The hierarchy's alias names of `color`, or nil. @objc(aliasForColor:) - func alias(for color: NSColor!) -> [String]! { + func alias(for color: NSColor?) -> [String]? { guard let color else { return nil } @@ -1124,9 +1124,9 @@ class HierarchyDataSource: NSObject { // MARK: - Others /// Subclasses return their preference manager. - @objc func preferenceManager() -> PreferenceManager! { + @objc func preferenceManager() -> PreferenceManager { assertionFailure("should implement by subclass") - return nil + return PreferenceManager.shared } /// YES in read-only mode, such as an opened file. diff --git a/LookInside/Hierarchy/HierarchyRowView.swift b/LookInside/Hierarchy/HierarchyRowView.swift index 29bcaa1b..9a869765 100644 --- a/LookInside/Hierarchy/HierarchyRowView.swift +++ b/LookInside/Hierarchy/HierarchyRowView.swift @@ -101,7 +101,7 @@ class HierarchyRowView: OutlineRowView { } } - init!(dataSource: HierarchyDataSource!) { + init(dataSource: HierarchyDataSource) { self.dataSource = dataSource super.init(compactUI: false) } diff --git a/LookInside/Hierarchy/HierarchyView.swift b/LookInside/Hierarchy/HierarchyView.swift index a8398424..5a59721f 100644 --- a/LookInside/Hierarchy/HierarchyView.swift +++ b/LookInside/Hierarchy/HierarchyView.swift @@ -42,42 +42,42 @@ private final class HierarchyDebouncer { @objc protocol HierarchyViewDelegate: NSObjectProtocol { @objc(hierarchyView:didSelectItem:) - func hierarchyView(_ view: HierarchyView!, didSelect item: DisplayItem!) + func hierarchyView(_ view: HierarchyView, didSelect item: DisplayItem?) @objc(hierarchyView:didDoubleClickItem:) - func hierarchyView(_ view: HierarchyView!, didDoubleClick item: DisplayItem!) + func hierarchyView(_ view: HierarchyView, didDoubleClick item: DisplayItem) @objc(hierarchyView:didHoverAtItem:) - func hierarchyView(_ view: HierarchyView!, didHoverAt item: DisplayItem!) + func hierarchyView(_ view: HierarchyView, didHoverAt item: DisplayItem?) @objc(hierarchyView:needToExpandItem:recursively:) - func hierarchyView(_ view: HierarchyView!, needToExpand item: DisplayItem!, recursively: Bool) + func hierarchyView(_ view: HierarchyView, needToExpand item: DisplayItem, recursively: Bool) @objc(hierarchyView:needToCollapseItem:) - func hierarchyView(_ view: HierarchyView!, needToCollapse item: DisplayItem!) + func hierarchyView(_ view: HierarchyView, needToCollapse item: DisplayItem) @objc(hierarchyView:needToCollapseChildrenOfItem:) - func hierarchyView(_ view: HierarchyView!, needToCollapseChildrenOf item: DisplayItem!) + func hierarchyView(_ view: HierarchyView, needToCollapseChildrenOf item: DisplayItem) /// 在底部的搜索框里输入了文字,string 可能为空字符串或 nil /// 当用户通过搜索框的关闭按钮、ESC 等方式手动结束搜索时,该方法同样会被调用,参数是 nil @objc(hierarchyView:didInputSearchString:) - func hierarchyView(_ view: HierarchyView!, didInputSearch string: String!) + func hierarchyView(_ view: HierarchyView, didInputSearch string: String?) @objc(hierarchyView:needToCancelPreviewOfItem:) - optional func hierarchyView(_ view: HierarchyView!, needToCancelPreviewOf item: DisplayItem!) + optional func hierarchyView(_ view: HierarchyView, needToCancelPreviewOf item: DisplayItem) @objc(hierarchyView:needToShowPreviewOfItem:) - optional func hierarchyView(_ view: HierarchyView!, needToShowPreviewOf item: DisplayItem!) + optional func hierarchyView(_ view: HierarchyView, needToShowPreviewOf item: DisplayItem) } @objc(LKHierarchyView) @objcMembers class HierarchyView: BaseView { - let tableView: TableView! + let tableView: TableView /// The filter field under the rows. The DEBUG UI snapshots type into it. - let searchTextFieldView: TextFieldView! - var dataSource: HierarchyDataSource! + let searchTextFieldView: TextFieldView + var dataSource: HierarchyDataSource /// Phase A 引入:由 owner(StaticHierarchyController / StaticViewController 链路)注入的 per-instance update manager(weak)。 /// 若 nil 则 fallback 到 +sharedInstance,以保留 read-only / archive workspace 的 legacy 行为。 weak var asyncUpdateManager: StaticAsyncUpdateManager? @@ -93,7 +93,7 @@ class HierarchyView: BaseView { private let searchDebouncer = HierarchyDebouncer(delay: 0.5) private let guidesDebouncer = HierarchyDebouncer(delay: 0.75) - init!(dataSource: HierarchyDataSource!) { + init(dataSource: HierarchyDataSource) { self.dataSource = dataSource tableView = TableView() searchTextFieldView = TextFieldView() @@ -154,7 +154,7 @@ class HierarchyView: BaseView { } @objc(scrollToMakeItemVisible:) - func scroll(toMakeItemVisible item: DisplayItem!) { + func scroll(toMakeItemVisible item: DisplayItem?) { guard let item, let row = displayItems.firstIndex(where: { $0 === item }) else { return } @@ -308,7 +308,7 @@ class HierarchyView: BaseView { // MARK: - Guides - func updateGuides(withHoveredItem item: DisplayItem!) { + func updateGuides(withHoveredItem item: DisplayItem?) { guard let item, let rootItem = item.super, let rootRow = displayItems.firstIndex(where: { $0 === rootItem }) else { @@ -402,11 +402,13 @@ class HierarchyView: BaseView { } @objc fileprivate func handleShowPreview(_ menuItem: NSMenuItem) { - delegate?.hierarchyView?(self, needToShowPreviewOf: displayItem(of: menuItem)) + guard let item = displayItem(of: menuItem) else { return } + delegate?.hierarchyView?(self, needToShowPreviewOf: item) } @objc fileprivate func handleCancelPreview(_ menuItem: NSMenuItem) { - delegate?.hierarchyView?(self, needToCancelPreviewOf: displayItem(of: menuItem)) + guard let item = displayItem(of: menuItem) else { return } + delegate?.hierarchyView?(self, needToCancelPreviewOf: item) } @objc fileprivate func handleExportScreenshot(_ menuItem: NSMenuItem) { @@ -422,14 +424,18 @@ class HierarchyView: BaseView { } @objc fileprivate func handleExpandRecursively(_ menuItem: NSMenuItem) { - let item = displayItem(of: menuItem) - assert(item != nil) + guard let item = displayItem(of: menuItem) else { + assertionFailure("the menu item carries no display item") + return + } delegate?.hierarchyView(self, needToExpand: item, recursively: true) } @objc fileprivate func handleCollapseChildren(_ menuItem: NSMenuItem) { - let item = displayItem(of: menuItem) - assert(item != nil) + guard let item = displayItem(of: menuItem) else { + assertionFailure("the menu item carries no display item") + return + } delegate?.hierarchyView(self, needToCollapseChildrenOf: item) } @@ -456,7 +462,7 @@ class HierarchyView: BaseView { // MARK: - TableViewDataSource / TableViewDelegate extension HierarchyView: TableViewDataSource, TableViewDelegate { - func tableView(_: TableView!, didHoverAtRow row: Int) { + func tableView(_: TableView, didHoverAtRow row: Int) { // nil when the mouse is not over a row. delegate?.hierarchyView(self, didHoverAt: item(atRow: row)) } @@ -495,7 +501,7 @@ extension HierarchyView: TableViewDataSource, TableViewDelegate { return rowView } - func tableView(_: TableView!, didSelectRow row: Int) { + func tableView(_: TableView, didSelectRow row: Int) { guard let item = item(atRow: row) else { return } @@ -505,7 +511,7 @@ extension HierarchyView: TableViewDataSource, TableViewDelegate { } } - func tableView(_: TableView!, didDoubleClickAtRow row: Int) { + func tableView(_: TableView, didDoubleClickAtRow row: Int) { guard let item = item(atRow: row) else { return } diff --git a/LookInside/Injection/InjectableFrameworkInstaller.swift b/LookInside/Injection/InjectableFrameworkInstaller.swift index 660f7c60..fa6d8c62 100644 --- a/LookInside/Injection/InjectableFrameworkInstaller.swift +++ b/LookInside/Injection/InjectableFrameworkInstaller.swift @@ -125,16 +125,9 @@ final class InjectableFrameworkInstaller { /// extracting, signature-verifying and moving the framework into place. func ensureInstalled(presentingWindow: NSWindow?) throws -> InjectableFrameworkInstallation { if !Thread.isMainThread { - var captured: Result! - DispatchQueue.main.sync { - do { - let installation = try self.ensureInstalled(presentingWindow: presentingWindow) - captured = .success(installation) - } catch { - captured = .failure(error) - } + return try DispatchQueue.main.sync { + try self.ensureInstalled(presentingWindow: presentingWindow) } - return try captured.get() } installLock.lock() @@ -282,7 +275,7 @@ final class InjectableFrameworkInstaller { controller.showWindow(self) InstallerLogger.installer.info("runInstallWithModal: progress window shown") - var captured: Result! + var captured: Result? let semaphore = DispatchSemaphore(value: 0) Thread.detachNewThread { @@ -323,6 +316,10 @@ final class InjectableFrameworkInstaller { cancellation.cancel() throw InjectableFrameworkInstallerError.cancelled } + // The worker stores a result before it signals. + guard let captured else { + throw InjectableFrameworkInstallerError.cancelled + } return try captured.get() } diff --git a/LookInside/Read/ReadHierarchyController.swift b/LookInside/Read/ReadHierarchyController.swift index d6f7bcde..1e206cd7 100644 --- a/LookInside/Read/ReadHierarchyController.swift +++ b/LookInside/Read/ReadHierarchyController.swift @@ -30,6 +30,6 @@ final class ReadHierarchyController: HierarchyController { } private func notifyNoPreviewDidChange() { - dataSource?.itemDidChangeNoPreview.send() + dataSource.itemDidChangeNoPreview.send() } } diff --git a/LookInside/Read/ReadHierarchyDataSource.swift b/LookInside/Read/ReadHierarchyDataSource.swift index c588958e..b0730326 100644 --- a/LookInside/Read/ReadHierarchyDataSource.swift +++ b/LookInside/Read/ReadHierarchyDataSource.swift @@ -43,7 +43,7 @@ final class ReadHierarchyDataSource: HierarchyDataSource { } } - override func preferenceManager() -> PreferenceManager! { + override func preferenceManager() -> PreferenceManager { readPreferenceManager } } diff --git a/LookInside/Read/ReadViewController.swift b/LookInside/Read/ReadViewController.swift index a6d37aba..5975fddd 100644 --- a/LookInside/Read/ReadViewController.swift +++ b/LookInside/Read/ReadViewController.swift @@ -13,9 +13,7 @@ import AppKit /// while the tree is in focus mode. @objc(LKReadViewController) final class ReadViewController: BaseViewController, NSSplitViewDelegate { - /// Implicitly unwrapped as the Objective-C property was; Swift callers - /// bind it with `guard let`. - @objc var hierarchyDataSource: ReadHierarchyDataSource! + @objc let hierarchyDataSource: ReadHierarchyDataSource private let splitView = SplitView() private let hierarchyController: ReadHierarchyController diff --git a/LookInside/Static/Preview/PreviewController.swift b/LookInside/Static/Preview/PreviewController.swift index 97f5853b..c24fe7c5 100644 --- a/LookInside/Static/Preview/PreviewController.swift +++ b/LookInside/Static/Preview/PreviewController.swift @@ -19,13 +19,15 @@ final class PreviewController: BaseViewController, NSGestureRecognizerDelegate, private let dataSource: HierarchyDataSource? private let previewView: PreviewView - /// Made by makeContainerView() during the superclass initializer. - private var stageView: PreviewStageView! + /// Configured by makeContainerView() during the superclass initializer. + private let stageView = PreviewStageView() - private var panRecognizer: PreviewPanGestureRecognizer! - private var clickRecognizer: NSClickGestureRecognizer! - private var doubleClickRecognizer: NSClickGestureRecognizer! - private var rightClickRecognizer: NSClickGestureRecognizer! + // Lazy because their target is self; they are first touched where they + // used to be created. + private lazy var panRecognizer = PreviewPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:))) + private lazy var clickRecognizer = NSClickGestureRecognizer(target: self, action: #selector(handleClickGesture(_:))) + private lazy var doubleClickRecognizer = NSClickGestureRecognizer(target: self, action: #selector(handleDoubleClick(_:))) + private lazy var rightClickRecognizer = NSClickGestureRecognizer(target: self, action: #selector(handleRightClick(_:))) private let rightClickMenu = NSMenu() private var rightClickingDisplayItem: DisplayItem? @@ -95,14 +97,13 @@ final class PreviewController: BaseViewController, NSGestureRecognizerDelegate, } override func makeContainerView() -> NSView { - let stageView = PreviewStageView() + let stageView = self.stageView stageView.didChangeAppearanceBlock = { view, isDarkMode in view?.backgroundColor = isDarkMode ? NSColor(red: 0, green: 0, blue: 0, alpha: 1) : NSColor(red: 1, green: 1, blue: 1, alpha: 1) } stageView.delegate = self - self.stageView = stageView return stageView } @@ -157,20 +158,16 @@ final class PreviewController: BaseViewController, NSGestureRecognizerDelegate, } } - panRecognizer = PreviewPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:))) panRecognizer.delegate = self previewView.addGestureRecognizer(panRecognizer) - clickRecognizer = NSClickGestureRecognizer(target: self, action: #selector(handleClickGesture(_:))) clickRecognizer.numberOfClicksRequired = 1 clickRecognizer.delegate = self previewView.addGestureRecognizer(clickRecognizer) - doubleClickRecognizer = NSClickGestureRecognizer(target: self, action: #selector(handleDoubleClick(_:))) doubleClickRecognizer.numberOfClicksRequired = 2 previewView.addGestureRecognizer(doubleClickRecognizer) - rightClickRecognizer = NSClickGestureRecognizer(target: self, action: #selector(handleRightClick(_:))) rightClickRecognizer.buttonMask = 0x2 rightClickRecognizer.numberOfClicksRequired = 1 previewView.addGestureRecognizer(rightClickRecognizer) diff --git a/LookInside/Static/StaticAsyncUpdateManager.swift b/LookInside/Static/StaticAsyncUpdateManager.swift index 1f959866..7b74bf65 100644 --- a/LookInside/Static/StaticAsyncUpdateManager.swift +++ b/LookInside/Static/StaticAsyncUpdateManager.swift @@ -75,7 +75,7 @@ final class StaticAsyncUpdateManager: NSObject { /// With fast mode off: after a reload, fetches the details of every item. @objc func updateAll() { assert(!PreferenceManager.shared.fastMode.currentBOOLValue) - guard inspectableApp != nil, let dataSource, !dataSource.flatItems.isEmpty else { + guard inspectableApp != nil, let dataSource, !(dataSource.flatItems ?? []).isEmpty else { return } endUpdating() diff --git a/LookInside/Static/StaticHierarchyController.swift b/LookInside/Static/StaticHierarchyController.swift index f53d45d9..7d550510 100644 --- a/LookInside/Static/StaticHierarchyController.swift +++ b/LookInside/Static/StaticHierarchyController.swift @@ -14,18 +14,18 @@ final class StaticHierarchyController: HierarchyController { // MARK: - HierarchyViewDelegate @objc(hierarchyView:needToCancelPreviewOfItem:) - func hierarchyView(_: HierarchyView?, needToCancelPreviewOf item: DisplayItem?) { - item?.noPreview = true - dataSource?.itemDidChangeNoPreview.send() + func hierarchyView(_: HierarchyView, needToCancelPreviewOf item: DisplayItem) { + item.noPreview = true + dataSource.itemDidChangeNoPreview.send() } @objc(hierarchyView:needToShowPreviewOfItem:) - func hierarchyView(_: HierarchyView?, needToShowPreviewOf item: DisplayItem?) { - item?.enumerateSelfAndAncestors { item, _ in + func hierarchyView(_: HierarchyView, needToShowPreviewOf item: DisplayItem) { + item.enumerateSelfAndAncestors { item, _ in if item.noPreview { item.noPreview = false } } - dataSource?.itemDidChangeNoPreview.send() + dataSource.itemDidChangeNoPreview.send() } } diff --git a/LookInside/Static/StaticHierarchyDataSource.swift b/LookInside/Static/StaticHierarchyDataSource.swift index e4fe277a..5315d676 100644 --- a/LookInside/Static/StaticHierarchyDataSource.swift +++ b/LookInside/Static/StaticHierarchyDataSource.swift @@ -12,7 +12,7 @@ import AppKit /// tasks deliver and starts those tasks. @objc(LKStaticHierarchyDataSource) class StaticHierarchyDataSource: HierarchyDataSource { - @objc var appInfo: InspectedAppInfo! { + @objc var appInfo: InspectedAppInfo? { storedAppInfo } @@ -42,13 +42,13 @@ class StaticHierarchyDataSource: HierarchyDataSource { // MARK: - Reload @objc(reloadWithHierarchyInfo:keepState:) - override func reload(with info: HierarchyInfo!, keepState: Bool) { + override func reload(with info: HierarchyInfo?, keepState: Bool) { super.reload(with: info, keepState: keepState) - storedAppInfo = info.appInfo + storedAppInfo = info?.appInfo - assert((info.appInfo?.screenScale ?? 0) > 0) - let screenScale = max(CGFloat(info.appInfo?.screenScale ?? 0), 1) + assert(info == nil || (info?.appInfo?.screenScale ?? 0) > 0) + let screenScale = max(CGFloat(info?.appInfo?.screenScale ?? 0), 1) // An SCNNode image is at most 16384 px on each side; keep 100 px // clear of that. Pixels, not points. @@ -77,7 +77,7 @@ class StaticHierarchyDataSource: HierarchyDataSource { } @objc(modifyWithDisplayItemDetail:) - func modify(with detail: DisplayItemDetail!) { + func modify(with detail: DisplayItemDetail?) { guard let detail else { return } @@ -185,7 +185,7 @@ class StaticHierarchyDataSource: HierarchyDataSource { } } - override func preferenceManager() -> PreferenceManager! { + override func preferenceManager() -> PreferenceManager { PreferenceManager.shared } diff --git a/LookInside/Static/StaticViewController.swift b/LookInside/Static/StaticViewController.swift index 31a7180e..83f536e8 100644 --- a/LookInside/Static/StaticViewController.swift +++ b/LookInside/Static/StaticViewController.swift @@ -22,48 +22,51 @@ final class StaticViewController: BaseViewController, NSSplitViewDelegate { /// The per-document update manager, owned by StaticWindowController. @objc private(set) weak var asyncUpdateManager: StaticAsyncUpdateManager? - @objc private(set) var viewsPreviewController: PreviewController! + @objc let viewsPreviewController: PreviewController - @objc var progressView: ProgressIndicatorView! + @objc let progressView = ProgressIndicatorView() /// Shows or hides the console under the preview. Observable with KVO. @objc dynamic var showConsole = false { didSet { applyShowConsole() } } - private var mainSplitView: SplitView! - private var rightSplitView: SplitView! - private var splitTopView: BaseView! + private let mainSplitView = SplitView() + private let rightSplitView = SplitView() + private let splitTopView = BaseView() - private var imageSyncTipsView: TipsView! - private var tooLargeToSyncScreenshotTipsView: RedTipsView! - private var userConfigNoPreviewTipsView: TipsView! - private var noPreviewTipView: TipsView! - private var customViewTipView: TipsView! - private var focusTipView: YellowTipsView! - private var fastModeTipView: TipsView! - private var serverUpgradeTipView: TipsView! + private let imageSyncTipsView = TipsView() + private let tooLargeToSyncScreenshotTipsView = RedTipsView() + private let userConfigNoPreviewTipsView = TipsView() + private let noPreviewTipView = TipsView() + private let customViewTipView = TipsView() + private let focusTipView = YellowTipsView() + private let fastModeTipView = TipsView() + private let serverUpgradeTipView = TipsView() /// Read with KVC by the DEBUG UI snapshots. - @objc private(set) var dashboardController: DashboardViewController! - private var hierarchyController: StaticHierarchyController! + @objc let dashboardController: DashboardViewController + private let hierarchyController: StaticHierarchyController private var consoleController: ConsoleViewController? - private var measureController: MeasureController! + private let measureController: MeasureController private var notificationObservers: [NSObjectProtocol] = [] private var keyValueObservations: [NSKeyValueObservation] = [] private let dataSourceSignals = SyncSubscriptionBag() private var modifyingUpdatesTask: Task? - /// Both arguments must be non-nil. The superclass initializer sets the - /// view, and setting it builds the children that read them, so they are - /// stored first. + /// The superclass initializer sets the view, and setting it builds the + /// children that read the data source and the update manager, so they + /// are stored first, and the child controllers are created here, in the + /// order buildContent() used to create them. @objc(initWithHierarchyDataSource:asyncUpdateManager:) - init(hierarchyDataSource: StaticHierarchyDataSource?, asyncUpdateManager: StaticAsyncUpdateManager?) { - assert(hierarchyDataSource != nil && asyncUpdateManager != nil, - "StaticViewController requires non-nil per-doc data source and update manager") + init(hierarchyDataSource: StaticHierarchyDataSource, asyncUpdateManager: StaticAsyncUpdateManager) { self.hierarchyDataSource = hierarchyDataSource self.asyncUpdateManager = asyncUpdateManager + hierarchyController = StaticHierarchyController(dataSource: hierarchyDataSource) + viewsPreviewController = PreviewController(dataSource: hierarchyDataSource) + dashboardController = DashboardViewController(staticDataSource: hierarchyDataSource) + measureController = MeasureController(dataSource: hierarchyDataSource) super.init(containerView: nil) } @@ -80,7 +83,7 @@ final class StaticViewController: BaseViewController, NSSplitViewDelegate { } override func makeContainerView() -> NSView { - let splitView = SplitView() + let splitView = mainSplitView splitView.didFinishFirstLayout = { view in let x = min(max(350, view.bounds.size.width * 0.3), 700) view.setPosition(x, ofDividerAt: 0) @@ -89,7 +92,6 @@ final class StaticViewController: BaseViewController, NSSplitViewDelegate { splitView.isVertical = true splitView.dividerStyle = .thin splitView.delegate = self - mainSplitView = splitView return splitView } @@ -111,32 +113,27 @@ final class StaticViewController: BaseViewController, NSSplitViewDelegate { let preferenceManager = PreferenceManager.shared preferenceManager.measureState.subscribe(self, action: #selector(handleMeasureStateChange(_:)), relatedObject: nil) - // The initializer requires a data source (see its assert). + // Set by the initializer, which takes a non-optional data source. let dataSource = hierarchyDataSource! - hierarchyController = StaticHierarchyController(dataSource: dataSource) addChild(hierarchyController) mainSplitView.addArrangedSubview(hierarchyController.view) // Hand the per-document update manager down the owner chain. hierarchyController.hierarchyView.asyncUpdateManager = asyncUpdateManager - rightSplitView = SplitView() rightSplitView.arrangesAllSubviews = true rightSplitView.isVertical = false rightSplitView.dividerStyle = .thin rightSplitView.delegate = self mainSplitView.addArrangedSubview(rightSplitView) - splitTopView = BaseView() rightSplitView.addArrangedSubview(splitTopView) - viewsPreviewController = PreviewController(dataSource: dataSource) viewsPreviewController.staticViewController = self viewsPreviewController.asyncUpdateManager = asyncUpdateManager splitTopView.addSubview(viewsPreviewController.view) addChild(viewsPreviewController) - dashboardController = DashboardViewController(staticDataSource: dataSource) dashboardController.asyncUpdateManager = asyncUpdateManager splitTopView.addSubview(dashboardController.view) addChild(dashboardController) @@ -150,14 +147,12 @@ final class StaticViewController: BaseViewController, NSSplitViewDelegate { consoleController?.liveDocument = document } - measureController = MeasureController(dataSource: dataSource) measureController.view.isHidden = true splitTopView.addSubview(measureController.view) addChild(measureController) buildTips() - progressView = ProgressIndicatorView() view.addSubview(progressView) observeDataSource(dataSource) @@ -192,17 +187,14 @@ final class StaticViewController: BaseViewController, NSSplitViewDelegate { } private func buildTips() { - imageSyncTipsView = TipsView() imageSyncTipsView.isHidden = true view.addSubview(imageSyncTipsView) - tooLargeToSyncScreenshotTipsView = RedTipsView() tooLargeToSyncScreenshotTipsView.image = NSImage(named: "icon_info") tooLargeToSyncScreenshotTipsView.title = NSLocalizedString("Image is too large to be displayed.", comment: "") tooLargeToSyncScreenshotTipsView.isHidden = true view.addSubview(tooLargeToSyncScreenshotTipsView) - focusTipView = YellowTipsView() focusTipView.image = NSImage(named: "icon_info") focusTipView.title = NSLocalizedString("Currently in focus mode", comment: "") focusTipView.isHidden = true @@ -211,7 +203,6 @@ final class StaticViewController: BaseViewController, NSSplitViewDelegate { focusTipView.clickAction = #selector(handleExitFocusTipView) view.addSubview(focusTipView) - fastModeTipView = TipsView() fastModeTipView.image = NSImage(named: "Icon_Inspiration_small") fastModeTipView.title = NSLocalizedString("Fast refresh mode is enabled, which may result in layer consistency issues.", comment: "") fastModeTipView.isHidden = true @@ -220,7 +211,6 @@ final class StaticViewController: BaseViewController, NSSplitViewDelegate { fastModeTipView.clickAction = #selector(handleFastModeTipViewClick) view.addSubview(fastModeTipView) - noPreviewTipView = TipsView() noPreviewTipView.image = NSImage(named: "icon_hide") noPreviewTipView.title = NSLocalizedString("The screenshot of selected item is not displayed.", comment: "") noPreviewTipView.buttonText = NSLocalizedString("Display", comment: "") @@ -229,7 +219,6 @@ final class StaticViewController: BaseViewController, NSSplitViewDelegate { noPreviewTipView.isHidden = true view.addSubview(noPreviewTipView) - customViewTipView = TipsView() customViewTipView.image = NSImage(named: "Icon_Inspiration_small") // The view class name depends on the inspected app, which is unknown // until a hierarchy arrives; handleSelectItemDidChange() refreshes @@ -241,7 +230,6 @@ final class StaticViewController: BaseViewController, NSSplitViewDelegate { customViewTipView.isHidden = true view.addSubview(customViewTipView) - userConfigNoPreviewTipsView = TipsView() userConfigNoPreviewTipsView.image = NSImage(named: "icon_hide") userConfigNoPreviewTipsView.title = NSLocalizedString("The screenshot is not displayed due to the config in iOS App.", comment: "") userConfigNoPreviewTipsView.buttonText = NSLocalizedString("Details", comment: "") @@ -250,7 +238,6 @@ final class StaticViewController: BaseViewController, NSSplitViewDelegate { userConfigNoPreviewTipsView.isHidden = true view.addSubview(userConfigNoPreviewTipsView) - serverUpgradeTipView = TipsView() serverUpgradeTipView.image = NSImage(named: "Icon_Inspiration_small") serverUpgradeTipView.title = NSLocalizedString("The app's integrator should upgrade LookInside Server.", comment: "Tip shown once per inspected app whose LookInside Server is 0.2.9 or older") serverUpgradeTipView.buttonText = NSLocalizedString("OK", comment: "") @@ -497,7 +484,8 @@ final class StaticViewController: BaseViewController, NSSplitViewDelegate { } @objc private func handleNoPreviewTipView() { - hierarchyController.hierarchyView(nil, needToShowPreviewOf: noPreviewTipView.bindingObject as? DisplayItem) + guard let item = noPreviewTipView.bindingObject as? DisplayItem else { return } + hierarchyController.hierarchyView(hierarchyController.hierarchyView, needToShowPreviewOf: item) } @objc private func handleCustomViewTipsView() { @@ -596,7 +584,7 @@ final class StaticViewController: BaseViewController, NSSplitViewDelegate { } private func customViewTipTitle() -> String { - let inspectedAppInfo = hierarchyController?.dataSource?.rawHierarchyInfo?.appInfo + let inspectedAppInfo = hierarchyController.dataSource.rawHierarchyInfo?.appInfo return String( format: NSLocalizedString("This object may not be a %@ or CALayer.", comment: ""), AppHelper.viewClassName(for: inspectedAppInfo) diff --git a/LookInside/Static/StaticWindowController.swift b/LookInside/Static/StaticWindowController.swift index 08d4561f..0a6af7ff 100644 --- a/LookInside/Static/StaticWindowController.swift +++ b/LookInside/Static/StaticWindowController.swift @@ -63,15 +63,13 @@ final class StaticWindowController: WindowController, NSToolbarDelegate, @precon case noResponse } - /// Implicitly unwrapped for the Swift callers written against the - /// Objective-C header; set before init returns. - @objc private(set) var viewController: StaticViewController! + @objc let viewController: StaticViewController /// Per-window hierarchy data source. - @objc private(set) var hierarchyDataSource: StaticHierarchyDataSource! + @objc let hierarchyDataSource: StaticHierarchyDataSource /// Per-window async update manager. - @objc private(set) var asyncUpdateManager: StaticAsyncUpdateManager! + @objc let asyncUpdateManager: StaticAsyncUpdateManager /// Injected by the owning LiveDocument, which also swaps it when /// the app reconnects; every request uses it. @@ -126,16 +124,20 @@ final class StaticWindowController: WindowController, NSToolbarDelegate, @precon window.center() window.setFrameUsingName(windowSizeNameStatic) - super.init(window: window) - - // Saves this window's frame across launches. - windowFrameAutosaveName = windowSizeNameStatic - let dataSource = StaticHierarchyDataSource() let updateManager = StaticAsyncUpdateManager(hierarchyDataSource: dataSource, inspectableApp: nil) dataSource.asyncUpdateManager = updateManager hierarchyDataSource = dataSource asyncUpdateManager = updateManager + // The view controller builds its view inside its initializer, so the + // data source and update manager go in up front. + let viewController = StaticViewController(hierarchyDataSource: dataSource, asyncUpdateManager: updateManager) + self.viewController = viewController + + super.init(window: window) + + // Saves this window's frame across launches. + windowFrameAutosaveName = windowSizeNameStatic NotificationCenter.default.addObserver( self, @@ -152,10 +154,6 @@ final class StaticWindowController: WindowController, NSToolbarDelegate, @precon relatedObject: nil ) - // The view controller builds its view inside its initializer, so the - // data source and update manager go in up front. - let viewController = StaticViewController(hierarchyDataSource: dataSource, asyncUpdateManager: updateManager) - self.viewController = viewController window.contentView = viewController.view contentViewController = viewController From 20eed037c2abde0a95f1f5e4c5c094a5a1f7fa79 Mon Sep 17 00:00:00 2001 From: Mx-Iris Date: Fri, 9 Oct 2026 01:39:25 +0800 Subject: [PATCH 5/5] Log through @Loggable, drop the host's Objective-C names and @objc protocols - Logging: the NSLog calls and the hand-written os.Logger properties use FrameworkToolbox's @Loggable and #log. The MCP bridge services, the installer ("Installer") and the SwiftUI support gatekeeper ("Activation") keep their subsystem and category; the types that used NSLog log under com.lookinside.app with their type name as the category, at NSLog's default level and with every interpolation public, as NSLog printed it. The target depends on FrameworkToolbox's FoundationToolbox product directly (0.9.x, the version UIFoundation already resolves). JSONAttributeItem.swift keeps its NSLog: Scripts/test-dashboard.sh compiles it on its own, without the package. - The host's classes lose their @objc(LK...) / @objc(Lookin...) names and the classes their @objcMembers. Nothing looks them up by name: the archives hold LookinCore classes only, there are no nibs, and the SwiftUI support gatekeeper checks `is StaticWindowController` instead of comparing the class name. The three document classes that Info.plist names keep theirs. HierarchyView.searchTextFieldView, which the DEBUG UI snapshots read by key, is @objc explicitly. - HierarchyViewDelegate, UserActionManagerDelegate and StaticAsyncUpdateManagerDelegate are Swift protocols. The two optional preview methods of HierarchyViewDelegate are required, with empty implementations in HierarchyController that the static and read controllers override; UserActionType is a Swift enum. Co-Authored-By: Claude Opus 5.5 --- LookInside.xcodeproj/project.pbxproj | 19 +++++- LookInside/About/AboutWindowController.swift | 2 - LookInside/AppDelegate.swift | 6 +- LookInside/Base/AppWindow.swift | 1 - LookInside/Base/BaseControl.swift | 1 - LookInside/Base/BaseView.swift | 3 - LookInside/Base/BaseViewController.swift | 6 +- LookInside/Base/ColorIndicatorLayer.swift | 1 - LookInside/Base/ConnectionTipsBinding.swift | 1 - LookInside/Base/DeviceIconProvider.swift | 1 - LookInside/Base/FrameLayout.swift | 1 - LookInside/Base/ImageTextView.swift | 1 - .../Base/Message/MessageAttribute.swift | 10 --- LookInside/Base/NumberInputView.swift | 1 - LookInside/Base/OutlineRowView.swift | 2 - LookInside/Base/PerformanceReporter.swift | 1 - LookInside/Base/PopPanel.swift | 1 - LookInside/Base/ProgressIndicatorView.swift | 1 - LookInside/Base/SplitView.swift | 1 - LookInside/Base/TableRowView.swift | 3 - LookInside/Base/TableView.swift | 5 +- ...ableViewHorizontalScrollWidthManager.swift | 1 - LookInside/Base/TextControl.swift | 1 - LookInside/Base/TextFieldView.swift | 1 - LookInside/Base/TextLabel.swift | 1 - LookInside/Base/TextsMenuView.swift | 1 - LookInside/Base/TipsView.swift | 3 - LookInside/Base/TwoColors.swift | 1 - LookInside/Base/UserActionManager.swift | 26 +++----- LookInside/Base/WindowController.swift | 5 +- .../Installer/InstallerCodeSignature.swift | 6 +- .../Installer/InstallerDownloader.swift | 14 ++-- .../Common/Installer/InstallerLogger.swift | 8 --- LookInside/Connection/AppsManager.swift | 10 +-- .../ConnectionManager+License.swift | 15 ++--- LookInside/Connection/ConnectionManager.swift | 27 ++++---- LookInside/Connection/InspectableApp.swift | 1 - .../Connection/LiveDocumentController.swift | 1 - .../Console/ConsoleViewController.swift | 5 +- .../DanceScript/DanceScriptManager.swift | 6 +- .../DashboardAttributeConstraintsView.swift | 1 - .../DashboardAttributeColorView.swift | 5 +- .../DashboardAttributeEnumsView.swift | 5 +- .../DashboardAttributeGeometryViews.swift | 15 ++--- .../DashboardAttributeNumberInputView.swift | 9 +-- ...ardAttributePrivateDiscriminatorView.swift | 1 - .../DashboardAttributeReadOnlyViews.swift | 3 - .../DashboardAttributeStringArrayView.swift | 2 - .../DashboardAttributeSwitchView.swift | 1 - .../DashboardAttributeTextView.swift | 5 +- .../DashboardAttributeView.swift | 6 +- .../JSON/JSONAttributeViews.swift | 4 -- .../Dashboard/DashboardSectionView.swift | 4 +- .../Dashboard/DashboardViewController.swift | 7 +- LookInside/Dashboard/EnumListRegistry.swift | 2 - .../Search/DashboardSearchViews.swift | 4 +- LookInside/DebugE2E/DebugE2EDumpWriter.swift | 1 - LookInside/DebugE2E/DebugUISnapshots.swift | 1 - LookInside/DebugE2E/DebugWindowImage.swift | 1 - LookInside/Export/ExportAccessoryView.swift | 1 - LookInside/Export/ExportManager.swift | 1 - .../GestureDebugWindowController.swift | 1 - .../Hierarchy/HierarchyController.swift | 18 +++--- .../Hierarchy/HierarchyDataSource.swift | 5 +- LookInside/Hierarchy/HierarchyRowView.swift | 2 - LookInside/Hierarchy/HierarchyView.swift | 26 +++----- .../Device/DeviceInjectionFlow.swift | 1 - .../InjectableFrameworkInstaller.swift | 64 ++++++++++--------- LookInside/Injection/InjectionFlow.swift | 1 - LookInside/Launch/LaunchAppView.swift | 1 - LookInside/Launch/LaunchViewController.swift | 1 - .../Launch/LaunchWindowController.swift | 1 - .../MCPBridge/MCPBridgeConnection.swift | 9 +-- .../MCPBridge/MCPBridgeDetailsService.swift | 9 +-- .../MCPBridge/MCPBridgeEventPublisher.swift | 3 +- .../MCPBridgeInspectionService.swift | 9 +-- .../MCPBridgeInvocationService.swift | 7 +- .../MCPBridgeModificationService.swift | 9 +-- .../MCPBridge/MCPBridgeRefreshService.swift | 9 +-- .../MCPBridgeScreenshotService.swift | 7 +- .../MCPBridge/MCPBridgeSearchService.swift | 5 +- .../MCPBridge/MCPBridgeSelectorService.swift | 7 +- LookInside/MCPBridge/MCPBridgeServer.swift | 14 ++-- LookInside/Manager/AppMenuManager.swift | 3 +- LookInside/Manager/NavigationManager.swift | 1 - LookInside/Manager/PreferenceManager.swift | 1 - LookInside/Measure/MeasureController.swift | 1 - LookInside/Other/VersionComparer.swift | 1 - LookInside/Preference/PreferenceView.swift | 1 - .../PreferenceWindowController.swift | 2 - ...iscriminatorSettingsWindowController.swift | 1 - .../PrivateDiscriminatorStore.swift | 2 - LookInside/Read/ReadHierarchyController.swift | 11 ++-- LookInside/Read/ReadHierarchyDataSource.swift | 1 - LookInside/Read/ReadViewController.swift | 1 - LookInside/Read/ReadWindowController.swift | 1 - LookInside/Static/MessageManager.swift | 1 - .../Static/Preview/DisplayItemNode.swift | 1 - .../Static/Preview/PreviewController.swift | 1 - .../Static/Preview/PreviewStageView.swift | 2 - LookInside/Static/Preview/PreviewView.swift | 5 +- .../Static/StaticAsyncUpdateManager.swift | 28 +++----- .../Static/StaticHierarchyController.swift | 7 +- .../Static/StaticHierarchyDataSource.swift | 1 - LookInside/Static/StaticViewController.swift | 1 - .../Static/StaticWindowController.swift | 5 +- .../SwiftUIHierarchyDisplayMode.swift | 1 - .../SwiftUISupportGatekeeper.swift | 20 +++--- .../SwiftUISupport/SwiftUISupportLogger.swift | 8 --- .../MenuPopoverAppsListController.swift | 1 - .../MenuPopoverSettingController.swift | 1 - .../Toolbar/WindowToolbarAppButton.swift | 1 - LookInside/Toolbar/WindowToolbarHelper.swift | 1 - 113 files changed, 244 insertions(+), 357 deletions(-) delete mode 100644 LookInside/Common/Installer/InstallerLogger.swift delete mode 100644 LookInside/SwiftUISupport/SwiftUISupportLogger.swift diff --git a/LookInside.xcodeproj/project.pbxproj b/LookInside.xcodeproj/project.pbxproj index a69d2698..1373a2f1 100644 --- a/LookInside.xcodeproj/project.pbxproj +++ b/LookInside.xcodeproj/project.pbxproj @@ -19,6 +19,7 @@ E972100D2FC2E5C0003AAEA6 /* InjectionServiceInterface in Frameworks */ = {isa = PBXBuildFile; productRef = E972100C2FC2E5C0003AAEA6 /* InjectionServiceInterface */; }; E9FE990C3026C657008692AF /* UIFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = E9FE990B3026C657008692AF /* UIFoundation */; }; E9FE990E3026C657008692AF /* UIFoundationToolbox in Frameworks */ = {isa = PBXBuildFile; productRef = E9FE990D3026C657008692AF /* UIFoundationToolbox */; }; + F0F0A10E2FD0000100A1B2C3 /* FoundationToolbox in Frameworks */ = {isa = PBXBuildFile; productRef = F0F0A10D2FD0000100A1B2C3 /* FoundationToolbox */; }; 15FFB4D96CB7375162952FFE /* LookInsideActivation in Frameworks */ = {isa = PBXBuildFile; productRef = 4CF60A9D44E04A6BE91035EF /* LookInsideActivation */; }; 79CC3F736CA547232F1827F4 /* LookInsideActivationUI in Frameworks */ = {isa = PBXBuildFile; productRef = F05DCA7C93CF923C02603F72 /* LookInsideActivationUI */; }; C0DE5A1E2FA0000100A1B2C3 /* LookInsideHostCore in Frameworks */ = {isa = PBXBuildFile; productRef = C0DE5A1F2FA0000100A1B2C3 /* LookInsideHostCore */; }; @@ -93,7 +94,6 @@ Common/Installer/InstallerCodeSignature.swift, Common/Installer/InstallerDownloader.swift, Common/Installer/InstallerFilesystem.swift, - Common/Installer/InstallerLogger.swift, Common/Installer/InstallerProgressWindowController.swift, "Connection/ConnectionManager+License.swift", Connection/AppsManager.swift, @@ -225,7 +225,6 @@ Static/Preview/PreviewView.swift, SwiftUISupport/SwiftUIHierarchyDisplayMode.swift, SwiftUISupport/SwiftUISupportGatekeeper.swift, - SwiftUISupport/SwiftUISupportLogger.swift, Toolbar/MenuPopoverAppsListController.swift, Toolbar/MenuPopoverSettingController.swift, Toolbar/ToolbarRules.swift, @@ -300,6 +299,7 @@ E972100B2FC2E5C0003AAEA6 /* HelperCommunication in Frameworks */, E972100D2FC2E5C0003AAEA6 /* InjectionServiceInterface in Frameworks */, E9FE990E3026C657008692AF /* UIFoundationToolbox in Frameworks */, + F0F0A10E2FD0000100A1B2C3 /* FoundationToolbox in Frameworks */, 15FFB4D96CB7375162952FFE /* LookInsideActivation in Frameworks */, 79CC3F736CA547232F1827F4 /* LookInsideActivationUI in Frameworks */, C0DE5A1E2FA0000100A1B2C3 /* LookInsideHostCore in Frameworks */, @@ -366,6 +366,7 @@ E972100C2FC2E5C0003AAEA6 /* InjectionServiceInterface */, E9FE990B3026C657008692AF /* UIFoundation */, E9FE990D3026C657008692AF /* UIFoundationToolbox */, + F0F0A10D2FD0000100A1B2C3 /* FoundationToolbox */, 4CF60A9D44E04A6BE91035EF /* LookInsideActivation */, F05DCA7C93CF923C02603F72 /* LookInsideActivationUI */, C0DE5A1F2FA0000100A1B2C3 /* LookInsideHostCore */, @@ -426,6 +427,7 @@ E97210042FC2D5C0003AAEA6 /* XCRemoteSwiftPackageReference "RunningApplicationKit" */, E97210072FC2E3FC003AAEA6 /* XCRemoteSwiftPackageReference "swift-helper-service" */, E9FE990A3026C657008692AF /* XCRemoteSwiftPackageReference "UIFoundation" */, + F0F0A10A2FD0000100A1B2C3 /* XCRemoteSwiftPackageReference "FrameworkToolbox" */, E81BCA16A46AEA38803B27B7 /* XCLocalSwiftPackageReference "Packages/LookInsideActivation" */, C0DE5A1D2FA0000100A1B2C3 /* XCLocalSwiftPackageReference "Packages/LookInsideHostCore" */, ); @@ -884,6 +886,14 @@ AppleInternal, ); }; + F0F0A10A2FD0000100A1B2C3 /* XCRemoteSwiftPackageReference "FrameworkToolbox" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/Mx-Iris/FrameworkToolbox"; + requirement = { + kind = upToNextMinorVersion; + minimumVersion = 0.9.0; + }; + }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ @@ -932,6 +942,11 @@ package = E9FE990A3026C657008692AF /* XCRemoteSwiftPackageReference "UIFoundation" */; productName = UIFoundationToolbox; }; + F0F0A10D2FD0000100A1B2C3 /* FoundationToolbox */ = { + isa = XCSwiftPackageProductDependency; + package = F0F0A10A2FD0000100A1B2C3 /* XCRemoteSwiftPackageReference "FrameworkToolbox" */; + productName = FoundationToolbox; + }; 4CF60A9D44E04A6BE91035EF /* LookInsideActivation */ = { isa = XCSwiftPackageProductDependency; package = E81BCA16A46AEA38803B27B7 /* XCLocalSwiftPackageReference "Packages/LookInsideActivation" */; diff --git a/LookInside/About/AboutWindowController.swift b/LookInside/About/AboutWindowController.swift index 4446d822..ae3401bf 100644 --- a/LookInside/About/AboutWindowController.swift +++ b/LookInside/About/AboutWindowController.swift @@ -8,7 +8,6 @@ import AppKit -@objc(LKAboutWindowController) final class AboutWindowController: WindowController { @objc init() { let window = AppWindow(contentRect: NSRect(x: 0, y: 0, width: 480, height: 460), @@ -33,7 +32,6 @@ final class AboutWindowController: WindowController { } } -@objc(LKAboutViewController) final class AboutViewController: BaseViewController { private static let upstreamURL = "https://github.com/QMUI/LookinServer" private static let homeURL = "https://lookinside-app.com" diff --git a/LookInside/AppDelegate.swift b/LookInside/AppDelegate.swift index daf99284..3204d7f5 100644 --- a/LookInside/AppDelegate.swift +++ b/LookInside/AppDelegate.swift @@ -7,7 +7,9 @@ // import AppKit +import FoundationToolbox +@Loggable(subsystem: "com.lookinside.app") @main @objc(AppDelegate) @MainActor @@ -115,7 +117,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate { private func installActivationStateObserver() { let gatekeeper = SwiftUISupportGatekeeper.sharedInstance() - NSLog("[LK-Activation] initial state=%ld (re-evaluated every 60s in process)", gatekeeper.activationState.rawValue) + #log(.default, "[LK-Activation] initial state=\(gatekeeper.activationState.rawValue, privacy: .public) (re-evaluated every 60s in process)") NotificationCenter.default.addObserver( self, @@ -134,7 +136,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate { case .activated: label = "activated" default: label = "(null)" } - NSLog("[LK-Activation] state changed -> %@ (raw=%@)", label, state?.description ?? "(null)") + #log(.default, "[LK-Activation] state changed -> \(label, privacy: .public) (raw=\(state?.description ?? "(null)", privacy: .public))") } func applicationShouldTerminateAfterLastWindowClosed(_: NSApplication) -> Bool { diff --git a/LookInside/Base/AppWindow.swift b/LookInside/Base/AppWindow.swift index 07a66521..e495d101 100644 --- a/LookInside/Base/AppWindow.swift +++ b/LookInside/Base/AppWindow.swift @@ -6,7 +6,6 @@ import AppKit /// The app's window class: dropping a file onto it opens it in the reader. -@objc(LKWindow) class AppWindow: NSWindow { override init(contentRect: NSRect, styleMask style: NSWindow.StyleMask, backing backingStoreType: NSWindow.BackingStoreType, defer flag: Bool) { super.init(contentRect: contentRect, styleMask: style, backing: backingStoreType, defer: flag) diff --git a/LookInside/Base/BaseControl.swift b/LookInside/Base/BaseControl.swift index c4d13803..c31962e3 100644 --- a/LookInside/Base/BaseControl.swift +++ b/LookInside/Base/BaseControl.swift @@ -8,7 +8,6 @@ import AppKit -@objc(LKBaseControl) class BaseControl: NSControl { @objc var clickAction: Selector? diff --git a/LookInside/Base/BaseView.swift b/LookInside/Base/BaseView.swift index 6c589519..60df43fc 100644 --- a/LookInside/Base/BaseView.swift +++ b/LookInside/Base/BaseView.swift @@ -18,8 +18,6 @@ private let effectiveAppearanceContext = UnsafeMutableRawPointer.allocate(byteCo case right } -@objc(LKBaseView) -@objcMembers class BaseView: NSView, NSViewToolTipOwner { var tooltipString: String? { didSet { @@ -227,7 +225,6 @@ class BaseView: NSView, NSViewToolTipOwner { func sizeToFit() {} } -@objc(LKVisualEffectView) class VisualEffectView: NSVisualEffectView { override var isFlipped: Bool { true diff --git a/LookInside/Base/BaseViewController.swift b/LookInside/Base/BaseViewController.swift index 873b81cf..faf6364b 100644 --- a/LookInside/Base/BaseViewController.swift +++ b/LookInside/Base/BaseViewController.swift @@ -7,9 +7,9 @@ // import AppKit +import FoundationToolbox -@objc(LKBaseViewController) -@objcMembers +@Loggable(subsystem: "com.lookinside.app") class BaseViewController: NSViewController { private(set) var isViewAppeared = false @@ -33,7 +33,7 @@ class BaseViewController: NSViewController { } deinit { - NSLog("%@ dealloc", NSStringFromClass(type(of: self))) + #log(.default, "\(NSStringFromClass(type(of: self)), privacy: .public) dealloc") } override func viewDidAppear() { diff --git a/LookInside/Base/ColorIndicatorLayer.swift b/LookInside/Base/ColorIndicatorLayer.swift index 2efb9f71..736198f0 100644 --- a/LookInside/Base/ColorIndicatorLayer.swift +++ b/LookInside/Base/ColorIndicatorLayer.swift @@ -7,7 +7,6 @@ import AppKit /// A round colour swatch: a checkerboard behind translucent colours, a /// "no colour" image for nil, and a contrasting border. -@objc(LKColorIndicatorLayer) class ColorIndicatorLayer: CALayer { private var colorLayer: CALayer? private var imageLayer: CALayer? diff --git a/LookInside/Base/ConnectionTipsBinding.swift b/LookInside/Base/ConnectionTipsBinding.swift index 652877ac..50f10703 100644 --- a/LookInside/Base/ConnectionTipsBinding.swift +++ b/LookInside/Base/ConnectionTipsBinding.swift @@ -11,7 +11,6 @@ import AppKit -@objc(LKConnectionTipsBinding) final class ConnectionTipsBinding: NSObject { private var observations: [NSKeyValueObservation] = [] diff --git a/LookInside/Base/DeviceIconProvider.swift b/LookInside/Base/DeviceIconProvider.swift index 3dbf0ae2..658572cc 100644 --- a/LookInside/Base/DeviceIconProvider.swift +++ b/LookInside/Base/DeviceIconProvider.swift @@ -13,7 +13,6 @@ import UIFoundationToolbox /// their asset catalog artwork. That happens for a LookinServer predating /// `deviceModelIdentifier`, for a host appInfo cached before this field existed, and for /// a model this macOS does not declare (hardware newer than the host OS, or a VM). -@objc(LKDeviceIconProvider) final class DeviceIconProvider: NSObject { /// Height of the device icon in the window toolbar, matching the legacy /// `icon_*_small` assets (32 pixels at 2x). diff --git a/LookInside/Base/FrameLayout.swift b/LookInside/Base/FrameLayout.swift index 819f57c6..9540c2b9 100644 --- a/LookInside/Base/FrameLayout.swift +++ b/LookInside/Base/FrameLayout.swift @@ -11,7 +11,6 @@ import AppKit -@objc(LKFrameLayout) final class FrameLayout: NSObject { private enum Target { case view(NSView) diff --git a/LookInside/Base/ImageTextView.swift b/LookInside/Base/ImageTextView.swift index 765e6ace..ccc34ce3 100644 --- a/LookInside/Base/ImageTextView.swift +++ b/LookInside/Base/ImageTextView.swift @@ -6,7 +6,6 @@ import AppKit /// An image followed by a one-line label, centred vertically. -@objc(LKImageTextView) class ImageTextView: BaseView { @objc let imageView = NSImageView() @objc let label = TextLabel() diff --git a/LookInside/Base/Message/MessageAttribute.swift b/LookInside/Base/Message/MessageAttribute.swift index d3fa4840..dfb33383 100644 --- a/LookInside/Base/Message/MessageAttribute.swift +++ b/LookInside/Base/Message/MessageAttribute.swift @@ -14,8 +14,6 @@ import AppKit /// The sender of a subscriber's action. -@objc(LookinMsgActionParams) -@objcMembers final class MessageActionParameters: NSObject { var value: Any? weak var relatedObject: AnyObject? @@ -46,8 +44,6 @@ final class MessageActionParameters: NSObject { } } -@objc(LookinMsgAttribute) -@objcMembers class MessageAttribute: NSObject { /// One target-action pair. Two subscriptions are the same when the target /// and the related object are the same objects and the action has the same name. @@ -136,8 +132,6 @@ class MessageAttribute: NSObject { } } -@objc(LookinDoubleMsgAttribute) -@objcMembers final class DoubleMessageAttribute: MessageAttribute { convenience init(double value: Double) { self.init(value: NSNumber(value: value)) @@ -157,8 +151,6 @@ final class DoubleMessageAttribute: MessageAttribute { } } -@objc(LookinIntegerMsgAttribute) -@objcMembers final class IntegerMessageAttribute: MessageAttribute { convenience init(integer value: Int) { self.init(value: NSNumber(value: value)) @@ -178,8 +170,6 @@ final class IntegerMessageAttribute: MessageAttribute { } } -@objc(LookinBOOLMsgAttribute) -@objcMembers final class BoolMessageAttribute: MessageAttribute { convenience init(bool value: Bool) { self.init(value: NSNumber(value: value)) diff --git a/LookInside/Base/NumberInputView.swift b/LookInside/Base/NumberInputView.swift index 963533d2..113c1faf 100644 --- a/LookInside/Base/NumberInputView.swift +++ b/LookInside/Base/NumberInputView.swift @@ -19,7 +19,6 @@ extension NumberInputView { } /// A Dashboard number field with a short title. -@objc(LKNumberInputView) class NumberInputView: BaseView { @objc let textFieldView = TextFieldView() private let titleLabel = TextLabel() diff --git a/LookInside/Base/OutlineRowView.swift b/LookInside/Base/OutlineRowView.swift index 8d8bf36d..0f6c2720 100644 --- a/LookInside/Base/OutlineRowView.swift +++ b/LookInside/Base/OutlineRowView.swift @@ -17,8 +17,6 @@ private let disclosureWidth: CGFloat = 16 case collapsed } -@objc(LKOutlineRowView) -@objcMembers class OutlineRowView: TableRowView { let disclosureButton: NSButton let imageView: NSImageView diff --git a/LookInside/Base/PerformanceReporter.swift b/LookInside/Base/PerformanceReporter.swift index 82147f81..bf2718ec 100644 --- a/LookInside/Base/PerformanceReporter.swift +++ b/LookInside/Base/PerformanceReporter.swift @@ -7,7 +7,6 @@ import QuartzCore /// Timestamps of the current hierarchy reload. Nothing reads them yet; the /// hooks stay so reload timing can be reported again. -@objc(LKPerformanceReporter) final class PerformanceReporter: NSObject { private static let shared = PerformanceReporter() diff --git a/LookInside/Base/PopPanel.swift b/LookInside/Base/PopPanel.swift index a8656817..56698609 100644 --- a/LookInside/Base/PopPanel.swift +++ b/LookInside/Base/PopPanel.swift @@ -6,7 +6,6 @@ import AppKit /// A borderless rounded panel for small editors that pop up over a window. -@objc(LKPopPanel) class PopPanel: NSPanel { @objc(initWithSize:) init(size: NSSize) { diff --git a/LookInside/Base/ProgressIndicatorView.swift b/LookInside/Base/ProgressIndicatorView.swift index 282e4d1a..4af63c3d 100644 --- a/LookInside/Base/ProgressIndicatorView.swift +++ b/LookInside/Base/ProgressIndicatorView.swift @@ -10,7 +10,6 @@ import AppKit let InitialIndicatorProgressWhenFetchHierarchy: CGFloat = 0.7 /// A thin accent-coloured bar that fills from the left. -@objc(LKProgressIndicatorView) class ProgressIndicatorView: BaseView { private let fillLayer = CALayer() diff --git a/LookInside/Base/SplitView.swift b/LookInside/Base/SplitView.swift index f7becc65..ef02ea66 100644 --- a/LookInside/Base/SplitView.swift +++ b/LookInside/Base/SplitView.swift @@ -6,7 +6,6 @@ import AppKit /// A split view without visible dividers that reports its first layout. -@objc(LKSplitView) class SplitView: NSSplitView { /// Called once, after the first `layout`. @objc var didFinishFirstLayout: ((SplitView) -> Void)? diff --git a/LookInside/Base/TableRowView.swift b/LookInside/Base/TableRowView.swift index 9da0eb8e..480ac7b5 100644 --- a/LookInside/Base/TableRowView.swift +++ b/LookInside/Base/TableRowView.swift @@ -8,8 +8,6 @@ import AppKit -@objc(LKTableRowView) -@objcMembers class TableRowView: NSTableRowView { let titleLabel: TextLabel let subtitleLabel: TextLabel @@ -119,5 +117,4 @@ class TableRowView: NSTableRowView { } } -@objc(LKTableBlankRowView) final class TableBlankRowView: TableRowView {} diff --git a/LookInside/Base/TableView.swift b/LookInside/Base/TableView.swift index 0602ec8e..1925c66f 100644 --- a/LookInside/Base/TableView.swift +++ b/LookInside/Base/TableView.swift @@ -19,7 +19,7 @@ private final class KeyForwardingTableView: NSTableView { } /// Every row argument may be -1. -@objc(LKTableViewDelegate) +@objc protocol TableViewDelegate: NSTableViewDelegate { @objc(tableView:didSelectRow:) optional func tableView(_ tableView: TableView, didSelectRow row: Int) @@ -32,10 +32,9 @@ protocol TableViewDelegate: NSTableViewDelegate { optional func tableViewDidClickBlankArea(_ tableView: TableView) } -@objc(LKTableViewDataSource) +@objc protocol TableViewDataSource: NSTableViewDataSource {} -@objc(LKTableView) class TableView: NSScrollView { @objc let tableView: NSTableView diff --git a/LookInside/Base/TableViewHorizontalScrollWidthManager.swift b/LookInside/Base/TableViewHorizontalScrollWidthManager.swift index 18a41334..fa6ddcb4 100644 --- a/LookInside/Base/TableViewHorizontalScrollWidthManager.swift +++ b/LookInside/Base/TableViewHorizontalScrollWidthManager.swift @@ -8,7 +8,6 @@ import Foundation -@objc(LKTableViewHorizontalScrollWidthManager) class TableViewHorizontalScrollWidthManager: NSObject { @objc var maxRowWidth: CGFloat = 0 diff --git a/LookInside/Base/TextControl.swift b/LookInside/Base/TextControl.swift index f9a51200..76bd8422 100644 --- a/LookInside/Base/TextControl.swift +++ b/LookInside/Base/TextControl.swift @@ -8,7 +8,6 @@ import AppKit -@objc(LKTextControl) class TextControl: BaseControl { @objc let label = TextLabel() diff --git a/LookInside/Base/TextFieldView.swift b/LookInside/Base/TextFieldView.swift index 90d5ddbf..e41599a8 100644 --- a/LookInside/Base/TextFieldView.swift +++ b/LookInside/Base/TextFieldView.swift @@ -7,7 +7,6 @@ import AppKit /// A text field with insets, an optional leading image and an optional /// trailing button that clears a search. -@objc(LKTextFieldView) class TextFieldView: BaseView { @objc let textField = NSTextField() diff --git a/LookInside/Base/TextLabel.swift b/LookInside/Base/TextLabel.swift index 71acd688..e8f62c68 100644 --- a/LookInside/Base/TextLabel.swift +++ b/LookInside/Base/TextLabel.swift @@ -8,7 +8,6 @@ import AppKit -@objc(LKLabel) class TextLabel: NSTextField { /// 默认为 nil @objc var textColors: TwoColors? { diff --git a/LookInside/Base/TextsMenuView.swift b/LookInside/Base/TextsMenuView.swift index 23b1d7c6..f15dc3bc 100644 --- a/LookInside/Base/TextsMenuView.swift +++ b/LookInside/Base/TextsMenuView.swift @@ -14,7 +14,6 @@ import AppKit /// Two columns of key / value labels, optionally with a button after a /// value. -@objc(LKTextsMenuView) class TextsMenuView: BaseView { /// Defaults to {0, 3, 0, 5}. @objc var insets = NSEdgeInsets(top: 0, left: 3, bottom: 0, right: 5) diff --git a/LookInside/Base/TipsView.swift b/LookInside/Base/TipsView.swift index 2b137790..b2cd5bb7 100644 --- a/LookInside/Base/TipsView.swift +++ b/LookInside/Base/TipsView.swift @@ -7,7 +7,6 @@ import AppKit /// A pill-shaped notice: optional image, a title, and an optional button /// after a separator. -@objc(LKTipsView) class TipsView: BaseView { @objc weak var bindingObject: AnyObject? @@ -209,7 +208,6 @@ class TipsView: BaseView { } /// An orange notice that can pulse. -@objc(LKYellowTipsView) class YellowTipsView: TipsView { private var isAnimating = false @@ -249,7 +247,6 @@ class YellowTipsView: TipsView { } /// A red notice that pulses, used for connection loss. -@objc(LKRedTipsView) class RedTipsView: TipsView { @objc func startAnimation() { let animation = CABasicAnimation(keyPath: "backgroundColor") diff --git a/LookInside/Base/TwoColors.swift b/LookInside/Base/TwoColors.swift index b33e6a90..a74af635 100644 --- a/LookInside/Base/TwoColors.swift +++ b/LookInside/Base/TwoColors.swift @@ -6,7 +6,6 @@ import AppKit /// A colour pair resolved against the app's current appearance. -@objc(LKTwoColors) final class TwoColors: NSObject { @objc var colorInLightMode: NSColor? @objc var colorInDarkMode: NSColor? diff --git a/LookInside/Base/UserActionManager.swift b/LookInside/Base/UserActionManager.swift index 77961468..e3a8bf6b 100644 --- a/LookInside/Base/UserActionManager.swift +++ b/LookInside/Base/UserActionManager.swift @@ -5,29 +5,27 @@ import Foundation -@objc enum UserActionType: Int { - @objc(LKUserActionType_None) case none +enum UserActionType { + case none /// A click, double click, pan or similar in the preview. - @objc(LKUserActionType_PreviewOperation) case previewOperation + case previewOperation /// A click in the Dashboard. - @objc(LKUserActionType_DashboardClick) case dashboardClick + case dashboardClick /// The selected item changed. - @objc(LKUserActionType_SelectedItemChange) case selectedItemChange + case selectedItemChange } -@objc protocol UserActionManagerDelegate: NSObjectProtocol { - /// Called for every `sendAction:`. - @objc(LKUserActionManager:didAct:) +protocol UserActionManagerDelegate: AnyObject { + /// Called for every `send(_:)`. func userActionManager(_ manager: UserActionManager, didAct type: UserActionType) } /// Broadcasts user actions (preview gestures, Dashboard clicks) to weakly /// held delegates, for example so an open Dashboard editor can close. -@objc(LKUserActionManager) final class UserActionManager: NSObject { private static let shared = UserActionManager() - @objc static func sharedInstance() -> UserActionManager { + static func sharedInstance() -> UserActionManager { shared } @@ -35,7 +33,6 @@ final class UserActionManager: NSObject { /// Delegates are held weakly and need no removal; adding one twice /// keeps a single entry. - @objc(addDelegate:) func add(_ delegate: UserActionManagerDelegate) { if delegates.allObjects.contains(where: { ($0 as AnyObject) === delegate }) { return @@ -43,15 +40,12 @@ final class UserActionManager: NSObject { delegates.addPointer(Unmanaged.passUnretained(delegate as AnyObject).toOpaque()) } - @objc(sendAction:) func send(_ type: UserActionType) { guard type != .none else { - assertionFailure("sendAction: needs an action") + assertionFailure("send(_:) needs an action") return } - for case let delegate as UserActionManagerDelegate in delegates.allObjects - where delegate.responds(to: #selector(UserActionManagerDelegate.userActionManager(_:didAct:))) - { + for case let delegate as UserActionManagerDelegate in delegates.allObjects { delegate.userActionManager(self, didAct: type) } } diff --git a/LookInside/Base/WindowController.swift b/LookInside/Base/WindowController.swift index d9f824a8..82ed355c 100644 --- a/LookInside/Base/WindowController.swift +++ b/LookInside/Base/WindowController.swift @@ -7,10 +7,11 @@ // import AppKit +import FoundationToolbox -@objc(LKWindowController) +@Loggable(subsystem: "com.lookinside.app") class WindowController: NSWindowController, AppMenuManagerDelegate { deinit { - NSLog("%@ dealloc", NSStringFromClass(type(of: self))) + #log(.default, "\(NSStringFromClass(type(of: self)), privacy: .public) dealloc") } } diff --git a/LookInside/Common/Installer/InstallerCodeSignature.swift b/LookInside/Common/Installer/InstallerCodeSignature.swift index 12151797..860de8f4 100644 --- a/LookInside/Common/Installer/InstallerCodeSignature.swift +++ b/LookInside/Common/Installer/InstallerCodeSignature.swift @@ -1,6 +1,8 @@ import Foundation import Security +import FoundationToolbox +@Loggable(subsystem: "com.lookinside.app", category: "Installer") enum InstallerCodeSignature { struct TeamIdentifierMismatch: LocalizedError { let expected: String @@ -72,7 +74,7 @@ enum InstallerCodeSignature { ) throws { let hostTeamID = try? teamIdentifier(atPath: Bundle.main.bundlePath) guard let hostTeamID, hostTeamID.isEmpty == false else { - InstallerLogger.installer.info( + #log(.info, "verifyTeamIdentifierMatchesHost: host has no team identifier (dev build); skipping target team check at \(targetURL.path, privacy: .public)" ) return @@ -87,7 +89,7 @@ enum InstallerCodeSignature { guard hostTeamID == targetTeamID else { throw mismatchErrorBuilder(hostTeamID, targetTeamID) } - InstallerLogger.installer.info( + #log(.info, "verifyTeamIdentifierMatchesHost: host=\(hostTeamID, privacy: .public) matches target at \(targetURL.path, privacy: .public)" ) } diff --git a/LookInside/Common/Installer/InstallerDownloader.swift b/LookInside/Common/Installer/InstallerDownloader.swift index c7bdfafc..a6e6cf6a 100644 --- a/LookInside/Common/Installer/InstallerDownloader.swift +++ b/LookInside/Common/Installer/InstallerDownloader.swift @@ -1,5 +1,7 @@ import Foundation +import FoundationToolbox +@Loggable(subsystem: "com.lookinside.app", category: "Installer") enum InstallerDownloader { static func download( from url: URL, @@ -10,7 +12,7 @@ enum InstallerDownloader { ) throws { try cancellation.checkCancellation() - InstallerLogger.installer.info( + #log(.info, "downloader: start url=\(url.absoluteString, privacy: .public) timeout=\(timeout)" ) @@ -25,7 +27,7 @@ enum InstallerDownloader { let task = URLSession.shared.downloadTask(with: request) { tempURL, response, error in defer { semaphore.signal() } let status = (response as? HTTPURLResponse)?.statusCode ?? -1 - InstallerLogger.installer.info( + #log(.info, "downloader: completion status=\(status) error=\(error?.localizedDescription ?? "nil", privacy: .public)" ) if let error { @@ -58,7 +60,7 @@ enum InstallerDownloader { } try FileManager.default.moveItem(at: tempURL, to: destination) let movedSize = (try? FileManager.default.attributesOfItem(atPath: destination.path)[.size] as? Int) ?? -1 - InstallerLogger.installer.info("downloader: moved to destination bytes=\(movedSize)") + #log(.info, "downloader: moved to destination bytes=\(movedSize)") downloadedToDestination = true } catch { capturedError = errorBuilder(error.localizedDescription) @@ -66,14 +68,14 @@ enum InstallerDownloader { } cancellation.register(downloadTask: task) task.resume() - InstallerLogger.installer.info("downloader: task.resume() called, waiting on semaphore") + #log(.info, "downloader: task.resume() called, waiting on semaphore") semaphore.wait() - InstallerLogger.installer.info("downloader: semaphore released") + #log(.info, "downloader: semaphore released") cancellation.register(downloadTask: nil) try cancellation.checkCancellation() if let capturedError { - InstallerLogger.installer.error( + #log(.error, "downloader: throwing error=\(capturedError.localizedDescription, privacy: .public)" ) throw capturedError diff --git a/LookInside/Common/Installer/InstallerLogger.swift b/LookInside/Common/Installer/InstallerLogger.swift deleted file mode 100644 index 976ac101..00000000 --- a/LookInside/Common/Installer/InstallerLogger.swift +++ /dev/null @@ -1,8 +0,0 @@ -import Foundation -import os - -enum InstallerLogger { - static let installer = Logger(subsystem: subsystem, category: "Installer") - - private static let subsystem = "com.lookinside.app" -} diff --git a/LookInside/Connection/AppsManager.swift b/LookInside/Connection/AppsManager.swift index 0464c2ff..9d822937 100644 --- a/LookInside/Connection/AppsManager.swift +++ b/LookInside/Connection/AppsManager.swift @@ -11,8 +11,9 @@ import Foundation import LookInsideHostCore +import FoundationToolbox -@objc(LKAppsManager) +@Loggable(subsystem: "com.lookinside.app") @MainActor final class AppsManager: NSObject { @objc(sharedInstance) @@ -122,12 +123,7 @@ final class AppsManager: NSObject { return app case let .response(response): if let error = response?.error as NSError? { - NSLog( - "LookinClient - app info request failed, domain:%@, code:%@, description:%@", - error.domain, - NSNumber(value: error.code), - error.localizedDescription - ) + #log(.default, "LookinClient - app info request failed, domain:\(error.domain, privacy: .public), code:\(NSNumber(value: error.code), privacy: .public), description:\(error.localizedDescription, privacy: .public)") if error.code == LookinErrCode_LicenseRequired { return nil } diff --git a/LookInside/Connection/ConnectionManager+License.swift b/LookInside/Connection/ConnectionManager+License.swift index 4cee48e8..50888656 100644 --- a/LookInside/Connection/ConnectionManager+License.swift +++ b/LookInside/Connection/ConnectionManager+License.swift @@ -9,6 +9,7 @@ import Foundation import LookInsideHostCore +import FoundationToolbox extension ConnectionManager { /// Makes sure the license handshake has run on `channel`, then calls @@ -45,12 +46,7 @@ extension ConnectionManager { LicenseHandshakeFlow.run(in: environment, channelDescription: String(format: "%p", channel)) { failure in if let failure { let error = ConnectionError.licenseHandshakeError(failure) - NSLog( - "LookinClient - license handshake failed, domain:%@, code:%@, description:%@", - error.domain, - NSNumber(value: error.code), - error.localizedDescription - ) + #log(.default, "LookinClient - license handshake failed, domain:\(error.domain, privacy: .public), code:\(NSNumber(value: error.code), privacy: .public), description:\(error.localizedDescription, privacy: .public)") } state.licenseHandshake.finish(verified: failure == nil) } @@ -71,7 +67,7 @@ extension ConnectionManager { } for channel in channels { ensureLicenseHandshake(on: channel, force: true) { verified in - NSLog("LookinClient - activation-state license handshake finished, verified:%@", NSNumber(value: verified)) + #log(.default, "LookinClient - activation-state license handshake finished, verified:\(NSNumber(value: verified), privacy: .public)") } } } @@ -85,7 +81,7 @@ extension ConnectionManager { guard SwiftUISupportGatekeeper.sharedInstance().activationState == .activated else { return } for channel in connectedChannels() { ensureLicenseHandshake(on: channel, force: false) { verified in - NSLog("LookinClient - resumed license handshake finished, verified:%@", NSNumber(value: verified)) + #log(.default, "LookinClient - resumed license handshake finished, verified:\(NSNumber(value: verified), privacy: .public)") } } } @@ -94,6 +90,7 @@ extension ConnectionManager { /// The Host side of `LicenseHandshakeFlow` for one channel: Lookin /// frames through the connection manager, and the activation runtime's /// signing policy and license key through the gatekeeper. +@Loggable(subsystem: "com.lookinside.app") @MainActor private final class ServerChannelLicenseEnvironment: LicenseHandshakeEnvironment { private let channel: ServerChannel @@ -174,7 +171,7 @@ private final class ServerChannelLicenseEnvironment: LicenseHandshakeEnvironment } func log(_ message: String) { - NSLog("%@", message) + #log(.default, "\(message, privacy: .public)") } private func send(type: UInt32, data: NSObject?, completion: @escaping (LicenseExchangeResult) -> Void) { diff --git a/LookInside/Connection/ConnectionManager.swift b/LookInside/Connection/ConnectionManager.swift index 70dd0e23..3e4fecd3 100644 --- a/LookInside/Connection/ConnectionManager.swift +++ b/LookInside/Connection/ConnectionManager.swift @@ -23,6 +23,7 @@ import AppKit import LookInsideHostCore +import FoundationToolbox /// A push frame the Server sent without a request. struct ConnectionPush { @@ -66,7 +67,7 @@ private final class ConnectionPort { } } -@objc(LKConnectionManager) +@Loggable(.internal, subsystem: "com.lookinside.app") @MainActor final class ConnectionManager: NSObject { @objc(sharedInstance) @@ -223,7 +224,7 @@ final class ConnectionManager: NSObject { for number in Int32(LookinUSBDeviceIPv4PortNumberStart) ... Int32(LookinUSBDeviceIPv4PortNumberEnd) { self.usbPorts.append(ConnectionPort(number: number, kind: .usb(deviceID: deviceID))) } - NSLog("Lookin - USB device attached, DeviceID: %@", NSNumber(value: deviceID)) + #log(.default, "Lookin - USB device attached, DeviceID: \(NSNumber(value: deviceID), privacy: .public)") case let .detached(deviceID): self.usbPorts.removeAll { port in if case let .usb(portDeviceID) = port.kind { @@ -231,7 +232,7 @@ final class ConnectionManager: NSObject { } return false } - NSLog("Lookin - USB device detached, DeviceID: %@", NSNumber(value: deviceID)) + #log(.default, "Lookin - USB device detached, DeviceID: \(NSNumber(value: deviceID), privacy: .public)") } } } @@ -244,7 +245,7 @@ final class ConnectionManager: NSObject { func push(type: UInt32, data: NSObject?, channel: ServerChannel?) { guard let channel, channel.isConnected else { return } let payload = archivedPayload(rootObject: data) - NSLog("LookinClient - pushData, type:%@", NSNumber(value: type)) + #log(.default, "LookinClient - pushData, type:\(NSNumber(value: type), privacy: .public)") channel.send(type: type, tag: 0, payload: payload) } @@ -303,7 +304,7 @@ final class ConnectionManager: NSObject { request.endTimeoutCount() state.remove(request) request.sink.send(.completion) - NSLog("Lookin - request cancelled by the user, type:%@", NSNumber(value: type)) + #log(.default, "Lookin - request cancelled by the user, type:\(NSNumber(value: type), privacy: .public)") } /// Response frames of one request, until it completes. The stream @@ -418,7 +419,7 @@ final class ConnectionManager: NSObject { discarded.sink.send(.failure(ConnectionError.discarded)) discarded.endTimeoutCount() state.remove(discarded) - NSLog("LookinClient - will discard request, type:%@, tag:%@", NSNumber(value: discarded.type), NSNumber(value: discarded.tag)) + #log(.default, "LookinClient - will discard request, type:\(NSNumber(value: discarded.type), privacy: .public), tag:\(NSNumber(value: discarded.tag), privacy: .public)") } } @@ -459,7 +460,7 @@ final class ConnectionManager: NSObject { if channel.connectionState.activeRequest(type: type, tag: tag) != nil { return true } - NSLog("LookinClient - will refuse, type:%@, tag:%@", NSNumber(value: type), NSNumber(value: tag)) + #log(.default, "LookinClient - will refuse, type:\(NSNumber(value: type), privacy: .public), tag:\(NSNumber(value: tag), privacy: .public)") return false } @@ -492,7 +493,7 @@ final class ConnectionManager: NSObject { request.endTimeoutCount() state.remove(request) request.sink.send(.failure(ConnectionError.appInBackground)) - NSLog("Lookin - the iOS app reported that it is in the background; request failed") + #log(.default, "Lookin - the iOS app reported that it is in the background; request failed") return } @@ -516,13 +517,7 @@ final class ConnectionManager: NSObject { let duration = CACurrentMediaTime() - responseStartTime let megabytes = Double(receivedResponseBytes) / 1024 / 1024 if megabytes > 0.5 { - NSLog( - "Lookin - received all responses %@ / %@, %.2fs, %.2fM", - NSNumber(value: request.frameProgress.receivedDataCount), - NSNumber(value: attachment?.dataTotalCount ?? 0), - duration, - megabytes - ) + #log(.default, "Lookin - received all responses \(NSNumber(value: request.frameProgress.receivedDataCount), privacy: .public) / \(NSNumber(value: attachment?.dataTotalCount ?? 0), privacy: .public), \(duration, format: .fixed(precision: 2), privacy: .public)s, \(megabytes, format: .fixed(precision: 2), privacy: .public)M") } } else { // A multi-frame response restarts the timeout with each frame. @@ -541,7 +536,7 @@ final class ConnectionManager: NSObject { private func handlePush(type: UInt32, data: Any?, channel: ServerChannel) { guard type == UInt32(LookinPush_SwiftUISupportDetected) else { return } - NSLog("LookinClient - received SwiftUI support detection push from channel:%@ data:%@", channel, data.map { String(describing: $0) } ?? "(null)") + #log(.default, "LookinClient - received SwiftUI support detection push from channel:\(channel, privacy: .public) data:\(data.map { String(describing: $0) } ?? "(null)", privacy: .public)") DispatchQueue.main.async { let gatekeeper = SwiftUISupportGatekeeper.sharedInstance() gatekeeper.noteDetectedSwiftUISupport() diff --git a/LookInside/Connection/InspectableApp.swift b/LookInside/Connection/InspectableApp.swift index 8e8e60f0..175fd7b0 100644 --- a/LookInside/Connection/InspectableApp.swift +++ b/LookInside/Connection/InspectableApp.swift @@ -19,7 +19,6 @@ enum AppResponseEvent { case completion } -@objc(LKInspectableApp) final class InspectableApp: NSObject { /// Set when the app's Server is too old or too new for this Host, or /// answered the app info request with another error. diff --git a/LookInside/Connection/LiveDocumentController.swift b/LookInside/Connection/LiveDocumentController.swift index 5a6e53f0..312f569e 100644 --- a/LookInside/Connection/LiveDocumentController.swift +++ b/LookInside/Connection/LiveDocumentController.swift @@ -11,7 +11,6 @@ import AppKit -@objc(LookinLiveDocumentController) @MainActor final class LiveDocumentController: NSObject { @objc(sharedInstance) diff --git a/LookInside/Console/ConsoleViewController.swift b/LookInside/Console/ConsoleViewController.swift index c8338b59..55983a7b 100644 --- a/LookInside/Console/ConsoleViewController.swift +++ b/LookInside/Console/ConsoleViewController.swift @@ -8,8 +8,9 @@ // import AppKit +import FoundationToolbox -@objc(LKConsoleViewController) +@Loggable(subsystem: "com.lookinside.app") final class ConsoleViewController: BaseViewController, TableViewDelegate, TableViewDataSource { private let dataSource: ConsoleDataSource private let tableView = TableView() @@ -125,7 +126,7 @@ final class ConsoleViewController: BaseViewController, TableViewDelegate, TableV do { try await dataSource.submit(object: obj, text: text) } catch { - NSLog("Submit error: %@", String(describing: error)) + #log(.default, "Submit error: \(String(describing: error), privacy: .public)") } } } diff --git a/LookInside/DanceScript/DanceScriptManager.swift b/LookInside/DanceScript/DanceScriptManager.swift index 7d6a33d0..c4aaa2c3 100644 --- a/LookInside/DanceScript/DanceScriptManager.swift +++ b/LookInside/DanceScript/DanceScriptManager.swift @@ -10,7 +10,9 @@ // import AppKit +import FoundationToolbox +@Loggable(subsystem: "com.lookinside.app") @objc(DanceScriptManager) final class DanceScriptManager: NSObject { private static let sharedManager = DanceScriptManager() @@ -101,11 +103,11 @@ final class DanceScriptManager: NSObject { do { try task.run() } catch { - NSLog("DanceScript failed to launch: %@", String(describing: error)) + #log(.default, "DanceScript failed to launch: \(String(describing: error), privacy: .public)") return } let data = pipe.fileHandleForReading.readDataToEndOfFile() let output = String(data: data, encoding: .utf8) ?? "" - NSLog("脚本执行输出:%@", output) + #log(.default, "脚本执行输出:\(output, privacy: .public)") } } diff --git a/LookInside/Dashboard/AttributeView/Constraint/DashboardAttributeConstraintsView.swift b/LookInside/Dashboard/AttributeView/Constraint/DashboardAttributeConstraintsView.swift index b7debfa7..c4b8e66c 100644 --- a/LookInside/Dashboard/AttributeView/Constraint/DashboardAttributeConstraintsView.swift +++ b/LookInside/Dashboard/AttributeView/Constraint/DashboardAttributeConstraintsView.swift @@ -84,7 +84,6 @@ final class DashboardAttributeConstraintsItemControl: TextControl { /// The constraints that affect (or mention) the view; a click shows the /// details of one. -@objc(LKDashboardAttributeConstraintsView) final class DashboardAttributeConstraintsView: DashboardAttributeView { private let verInterSpace: CGFloat = 8 private var textControls: [DashboardAttributeConstraintsItemControl] = [] diff --git a/LookInside/Dashboard/AttributeView/DashboardAttributeColorView.swift b/LookInside/Dashboard/AttributeView/DashboardAttributeColorView.swift index 50dd30f2..41423766 100644 --- a/LookInside/Dashboard/AttributeView/DashboardAttributeColorView.swift +++ b/LookInside/Dashboard/AttributeView/DashboardAttributeColorView.swift @@ -7,6 +7,7 @@ // import AppKit +import FoundationToolbox /// The rounded box of a colour attribute; a click opens the colour menu. private final class DashboardAttributeColorContainerView: BaseView { @@ -20,7 +21,7 @@ private final class DashboardAttributeColorContainerView: BaseView { /// A colour: swatch, hex or RGBA text, and the colour's alias names from /// the app's colour configuration. -@objc(LKDashboardAttributeColorView) +@Loggable(subsystem: "com.lookinside.app") final class DashboardAttributeColorView: DashboardAttributeView, NSMenuDelegate { private let mainContainerHeight: CGFloat = 30 private let aliasLabelMarginTop: CGFloat = 1 @@ -201,7 +202,7 @@ final class DashboardAttributeColorView: DashboardAttributeView, NSMenuDelegate private func modify(to targetColor: NSColor?) { let expectedValue = targetColor?.sRGBAComponents() if let currentValue = attribute?.value as? NSObject, let expectedValue, currentValue.isEqual(expectedValue) { - NSLog("修改没有变化,不做任何提交") + #log(.default, "修改没有变化,不做任何提交") return } submitRenderingOnSuccess(expectedValue) diff --git a/LookInside/Dashboard/AttributeView/DashboardAttributeEnumsView.swift b/LookInside/Dashboard/AttributeView/DashboardAttributeEnumsView.swift index 06e7c764..bab826ef 100644 --- a/LookInside/Dashboard/AttributeView/DashboardAttributeEnumsView.swift +++ b/LookInside/Dashboard/AttributeView/DashboardAttributeEnumsView.swift @@ -7,9 +7,10 @@ // import AppKit +import FoundationToolbox /// An enum attribute: the case name, and a menu of the cases on click. -@objc(LKDashboardAttributeEnumsView) +@Loggable(subsystem: "com.lookinside.app") final class DashboardAttributeEnumsView: DashboardAttributeView { private let labelX: CGFloat = 5 private let labelRight: CGFloat = 20 @@ -145,7 +146,7 @@ final class DashboardAttributeEnumsView: DashboardAttributeView { @objc private func handleMenuItem(_ item: NSMenuItem) { let expectedValue = item.representedObject as? NSObject if let expectedValue, let current = attribute?.value, expectedValue.isEqual(current) { - NSLog("修改没有变化,不做任何提交") + #log(.default, "修改没有变化,不做任何提交") return } submitRenderingOnSuccess(expectedValue) diff --git a/LookInside/Dashboard/AttributeView/DashboardAttributeGeometryViews.swift b/LookInside/Dashboard/AttributeView/DashboardAttributeGeometryViews.swift index a2dc1d5c..5fcda4a1 100644 --- a/LookInside/Dashboard/AttributeView/DashboardAttributeGeometryViews.swift +++ b/LookInside/Dashboard/AttributeView/DashboardAttributeGeometryViews.swift @@ -10,9 +10,11 @@ // import AppKit +import FoundationToolbox /// Number fields, two per row. Subclasses fill them from the attribute's /// `NSValue` and turn an edited field into the value to submit. +@Loggable(subsystem: "com.lookinside.app") class DashboardAttributeFieldsView: DashboardAttributeView, NSTextFieldDelegate { /// The field titles, in field order. class var fieldTitles: [String] { @@ -103,20 +105,20 @@ class DashboardAttributeFieldsView: DashboardAttributeView, NSTextFieldDelegate // flag changes, although textShouldBeginEditing refused input. guard canEdit() else { return } if DashboardTextControlEditingFlag.shared.shouldIgnoreTextEditingChangeEvent { - NSLog("忽略 controlTextDidEndEditing 事件,驳回") + #log(.default, "忽略 controlTextDidEndEditing 事件,驳回") return } guard let editingTextField = notification.object as? NSTextField, let parsed = NumberInputView.parsedValue(with: editingTextField.stringValue, attrType: .double) as? NSNumber else { - NSLog("输入格式校验不通过,驳回") + #log(.default, "输入格式校验不通过,驳回") renderWithAttribute() return } guard let oldValue = attribute?.value as? NSValue else { return } let index = inputViews.firstIndex { $0.textFieldView.textField === editingTextField } ?? NSNotFound guard let newValue = editedValue(from: oldValue, field: index, number: parsed.doubleValue) else { - NSLog("修改没有变化,不做任何提交") + #log(.default, "修改没有变化,不做任何提交") renderWithAttribute() return } @@ -130,7 +132,7 @@ class DashboardAttributeFieldsView: DashboardAttributeView, NSTextFieldDelegate } } -@objc(LKDashboardAttributeRectView) +@Loggable(subsystem: "com.lookinside.app") final class DashboardAttributeRectView: DashboardAttributeFieldsView { override class var fieldTitles: [String] { ["X", "Y", "W", "H"] @@ -177,14 +179,13 @@ final class DashboardAttributeRectView: DashboardAttributeFieldsView { ) } } catch { - NSLog("修改返回 error") + #log(.default, "修改返回 error") self?.renderWithAttribute() } } } } -@objc(LKDashboardAttributeInsetsView) final class DashboardAttributeInsetsView: DashboardAttributeFieldsView { override class var fieldTitles: [String] { ["T", "L", "B", "R"] @@ -216,7 +217,6 @@ final class DashboardAttributeInsetsView: DashboardAttributeFieldsView { } } -@objc(LKDashboardAttributePointView) final class DashboardAttributePointView: DashboardAttributeFieldsView { override class var fieldTitles: [String] { ["X", "Y"] @@ -236,7 +236,6 @@ final class DashboardAttributePointView: DashboardAttributeFieldsView { } } -@objc(LKDashboardAttributeSizeView) final class DashboardAttributeSizeView: DashboardAttributeFieldsView { override class var fieldTitles: [String] { ["W", "H"] diff --git a/LookInside/Dashboard/AttributeView/DashboardAttributeNumberInputView.swift b/LookInside/Dashboard/AttributeView/DashboardAttributeNumberInputView.swift index aec1e0d6..1fd85015 100644 --- a/LookInside/Dashboard/AttributeView/DashboardAttributeNumberInputView.swift +++ b/LookInside/Dashboard/AttributeView/DashboardAttributeNumberInputView.swift @@ -7,9 +7,10 @@ // import AppKit +import FoundationToolbox /// A single number: opacity, corner radius, font size and the like. -@objc(LKDashboardAttributeNumberInputView) +@Loggable(subsystem: "com.lookinside.app") final class DashboardAttributeNumberInputView: DashboardAttributeView, NSTextFieldDelegate { @objc let inputView = NumberInputView() @@ -179,16 +180,16 @@ final class DashboardAttributeNumberInputView: DashboardAttributeView, NSTextFie // flag changes, although textShouldBeginEditing refused input. guard canEdit(), let attribute else { return } if DashboardTextControlEditingFlag.shared.shouldIgnoreTextEditingChangeEvent { - NSLog("忽略 controlTextDidEndEditing 事件,驳回") + #log(.default, "忽略 controlTextDidEndEditing 事件,驳回") return } guard let parsed = NumberInputView.parsedValue(with: inputView.textFieldView.textField.stringValue, attrType: attribute.attrType) as? NSNumber else { - NSLog("输入格式校验不通过,驳回") + #log(.default, "输入格式校验不通过,驳回") renderWithAttribute() return } guard let expectedValue = DashboardModification.numberValue(parsed, for: attribute) else { - NSLog("修改没有变化,不做任何提交") + #log(.default, "修改没有变化,不做任何提交") renderWithAttribute() return } diff --git a/LookInside/Dashboard/AttributeView/DashboardAttributePrivateDiscriminatorView.swift b/LookInside/Dashboard/AttributeView/DashboardAttributePrivateDiscriminatorView.swift index aab1c830..03205e9e 100644 --- a/LookInside/Dashboard/AttributeView/DashboardAttributePrivateDiscriminatorView.swift +++ b/LookInside/Dashboard/AttributeView/DashboardAttributePrivateDiscriminatorView.swift @@ -52,7 +52,6 @@ private final class PrivateDiscriminatorCopyLabel: TextLabel { } } -@objc(LKDashboardAttributePrivateDiscriminatorView) final class DashboardAttributePrivateDiscriminatorView: DashboardAttributeView { private typealias Metrics = PrivateDiscriminatorMetrics diff --git a/LookInside/Dashboard/AttributeView/DashboardAttributeReadOnlyViews.swift b/LookInside/Dashboard/AttributeView/DashboardAttributeReadOnlyViews.swift index cd467a0b..b2345af2 100644 --- a/LookInside/Dashboard/AttributeView/DashboardAttributeReadOnlyViews.swift +++ b/LookInside/Dashboard/AttributeView/DashboardAttributeReadOnlyViews.swift @@ -12,7 +12,6 @@ import AppKit /// The number of rows in each section of a table view. -@objc(LKDashboardAttributeRowsCountView) final class DashboardAttributeRowsCountView: DashboardAttributeView { private var inputViews: [NumberInputView] = [] @@ -63,7 +62,6 @@ final class DashboardAttributeRowsCountView: DashboardAttributeView { } /// A layer shadow: colour, then opacity, radius and offset. -@objc(LKDashboardAttributeShadowView) final class DashboardAttributeShadowView: DashboardAttributeView { private let colorContainerView = BaseView() private let colorIndicatorLayer = ColorIndicatorLayer() @@ -155,7 +153,6 @@ final class DashboardAttributeShadowView: DashboardAttributeView { /// Opens the image of an image view in Preview, fetched from the app (or /// taken from an imported Xcode capture). -@objc(LKDashboardAttributeOpenImageView) final class DashboardAttributeOpenImageView: DashboardAttributeView { private let control = TextControl() diff --git a/LookInside/Dashboard/AttributeView/DashboardAttributeStringArrayView.swift b/LookInside/Dashboard/AttributeView/DashboardAttributeStringArrayView.swift index 70da4bf2..3c3aa72f 100644 --- a/LookInside/Dashboard/AttributeView/DashboardAttributeStringArrayView.swift +++ b/LookInside/Dashboard/AttributeView/DashboardAttributeStringArrayView.swift @@ -130,7 +130,6 @@ class DashboardAttributeStringArrayView: DashboardAttributeView { } /// The class chain of the object, one class list per entry, demangled. -@objc(LKDashboardAttributeClassView) final class DashboardAttributeClassView: DashboardAttributeStringArrayView { override func stringList(with attribute: InspectedAttribute) -> [String] { let lists = attribute.value as? [[String]] ?? [] @@ -142,7 +141,6 @@ final class DashboardAttributeClassView: DashboardAttributeStringArrayView { /// The relations of the object ("(AAA : BBB *)" and "(AAA *)" texts), with /// the Swift class names demangled. Cached on the attribute. -@objc(LKDashboardAttributeRelationView) final class DashboardAttributeRelationView: DashboardAttributeStringArrayView { private static let cacheKey = "cachedDemangled" diff --git a/LookInside/Dashboard/AttributeView/DashboardAttributeSwitchView.swift b/LookInside/Dashboard/AttributeView/DashboardAttributeSwitchView.swift index 02b70839..b1495ed8 100644 --- a/LookInside/Dashboard/AttributeView/DashboardAttributeSwitchView.swift +++ b/LookInside/Dashboard/AttributeView/DashboardAttributeSwitchView.swift @@ -9,7 +9,6 @@ import AppKit /// A BOOL attribute as a checkbox. -@objc(LKDashboardAttributeSwitchView) final class DashboardAttributeSwitchView: DashboardAttributeView { private let button = NSButton() diff --git a/LookInside/Dashboard/AttributeView/DashboardAttributeTextView.swift b/LookInside/Dashboard/AttributeView/DashboardAttributeTextView.swift index 5579aaee..61eb624b 100644 --- a/LookInside/Dashboard/AttributeView/DashboardAttributeTextView.swift +++ b/LookInside/Dashboard/AttributeView/DashboardAttributeTextView.swift @@ -7,10 +7,11 @@ // import AppKit +import FoundationToolbox /// A string attribute in an editable text view. SwiftUI attributes that /// name another node get a button that jumps to it. -@objc(LKDashboardAttributeTextView) +@Loggable(subsystem: "com.lookinside.app") final class DashboardAttributeTextView: DashboardAttributeView, NSTextViewDelegate { private let titleLabel = TextLabel() private let scrollView: NSScrollView @@ -128,7 +129,7 @@ final class DashboardAttributeTextView: DashboardAttributeView, NSTextViewDelega func textDidEndEditing(_: Notification) { let expectedValue = textView.string if expectedValue == initialText { - NSLog("修改没有变化,不做任何提交") + #log(.default, "修改没有变化,不做任何提交") renderWithAttribute() return } diff --git a/LookInside/Dashboard/AttributeView/DashboardAttributeView.swift b/LookInside/Dashboard/AttributeView/DashboardAttributeView.swift index f860904c..1eedfdfa 100644 --- a/LookInside/Dashboard/AttributeView/DashboardAttributeView.swift +++ b/LookInside/Dashboard/AttributeView/DashboardAttributeView.swift @@ -7,11 +7,12 @@ // import AppKit +import FoundationToolbox /// One attribute row on a Dashboard card. Subclasses render `attribute`, /// size themselves through `sizeThatFits(_:)` and say how many of them fit /// in a row. -@objc(LKDashboardAttributeView) +@Loggable(subsystem: "com.lookinside.app") class DashboardAttributeView: BaseView { /// Setting the attribute renders it. @objc var attribute: InspectedAttribute? { @@ -70,7 +71,7 @@ class DashboardAttributeView: BaseView { do { try await self?.submit(newValue) } catch { - NSLog("修改返回 error") + #log(.default, "修改返回 error") self?.renderWithAttribute() } } @@ -90,7 +91,6 @@ class DashboardAttributeView: BaseView { /// removes the editing card, which ends text editing again; the text /// fields ignore that second end-of-editing so the value is not submitted /// twice. -@objc(LKDashboardTextControlEditingFlag) final class DashboardTextControlEditingFlag: NSObject { @objc(sharedInstance) static let shared = DashboardTextControlEditingFlag() diff --git a/LookInside/Dashboard/AttributeView/JSON/JSONAttributeViews.swift b/LookInside/Dashboard/AttributeView/JSON/JSONAttributeViews.swift index 14d0fed0..71efe329 100644 --- a/LookInside/Dashboard/AttributeView/JSON/JSONAttributeViews.swift +++ b/LookInside/Dashboard/AttributeView/JSON/JSONAttributeViews.swift @@ -60,7 +60,6 @@ private final class JSONAttributeTree { } /// The tree on a Dashboard card. -@objc(LKJSONAttributeContentView) final class JSONAttributeContentView: BaseView, TableViewDelegate, TableViewDataSource { private static let rowIdentifier = NSUserInterfaceItemIdentifier("myView") @@ -153,7 +152,6 @@ final class JSONAttributeContentView: BaseView, TableViewDelegate, TableViewData /// A JSON attribute on a card; the section's pop-out button shows it in a /// window. -@objc(LKDashboardAttributeJsonView) final class DashboardAttributeJSONView: DashboardAttributeView { private let contentView = JSONAttributeContentView(bigFont: false) @@ -200,7 +198,6 @@ final class DashboardAttributeJSONView: DashboardAttributeView { } /// The JSON tree in a window of its own, with the bigger font. -@objc(LKJSONAttributeViewController) final class JSONAttributeViewController: BaseViewController, TableViewDelegate, TableViewDataSource { private static let rowIdentifier = NSUserInterfaceItemIdentifier("myView") @@ -275,7 +272,6 @@ final class JSONAttributeViewController: BaseViewController, TableViewDelegate, } /// The window of `JSONAttributeViewController`. -@objc(LKJSONAttributeWindowController) final class JSONAttributeWindowController: WindowController { @objc convenience init() { let window = AppWindow( diff --git a/LookInside/Dashboard/DashboardSectionView.swift b/LookInside/Dashboard/DashboardSectionView.swift index d8435724..9a584c58 100644 --- a/LookInside/Dashboard/DashboardSectionView.swift +++ b/LookInside/Dashboard/DashboardSectionView.swift @@ -7,6 +7,7 @@ // import AppKit +import FoundationToolbox /// Whether a section shows a button that adds it to, or removes it from, /// its card. @@ -18,6 +19,7 @@ enum DashboardSectionManageState { /// One section of a card: an optional title and separator, then the /// attribute views flowed into rows. +@Loggable(subsystem: "com.lookinside.app") final class DashboardSectionView: BaseView { private let titleMarginTop: CGFloat = 6 @@ -208,7 +210,7 @@ final class DashboardSectionView: BaseView { guard let viewClass = Self.attrViewClass(for: attr.attrType, identifier: attr.identifier) else { // Debug builds stop here so a missing case surfaces at once; // release builds skip the attribute and log it. - NSLog("LookInside dashboard: skipping attribute with unsupported attrType=%ld identifier=%@", attr.attrType.rawValue, attr.identifier ?? "nil") + #log(.default, "LookInside dashboard: skipping attribute with unsupported attrType=\(attr.attrType.rawValue, privacy: .public) identifier=\(attr.identifier ?? "nil", privacy: .public)") assertionFailure("LookInside dashboard: no attrView class for attrType=\(attr.attrType.rawValue) identifier=\(attr.identifier ?? "nil")") continue } diff --git a/LookInside/Dashboard/DashboardViewController.swift b/LookInside/Dashboard/DashboardViewController.swift index c797ca35..d245d374 100644 --- a/LookInside/Dashboard/DashboardViewController.swift +++ b/LookInside/Dashboard/DashboardViewController.swift @@ -7,12 +7,13 @@ // import AppKit +import FoundationToolbox /// The attribute panel on the right of the inspector: one card per /// attribute group of the selected item, and a search over attributes and /// methods. Edits are sent to the inspected app on a live document; a /// document read from a file is read-only. -@objc(LKDashboardViewController) +@Loggable(subsystem: "com.lookinside.app") final class DashboardViewController: BaseViewController, DashboardCardViewDelegate, DashboardHeaderViewDelegate, DashboardSearchPropertyViewDelegate, DashboardSearchMethodsViewDelegate { /// Read by key by the DEBUG UI snapshots. @objc let scrollView = NSScrollView() @@ -282,7 +283,7 @@ final class DashboardViewController: BaseViewController, DashboardCardViewDelega } catch { throw failModification(error) } - NSLog("custom modification - succ") + #log(.default, "custom modification - succ") attribute.value = newValue } @@ -302,7 +303,7 @@ final class DashboardViewController: BaseViewController, DashboardCardViewDelega } catch { throw failModification(error) } - NSLog("modification - succ") + #log(.default, "modification - succ") guard let staticDataSource else { assertionFailure() return diff --git a/LookInside/Dashboard/EnumListRegistry.swift b/LookInside/Dashboard/EnumListRegistry.swift index 65e55616..78e138e1 100644 --- a/LookInside/Dashboard/EnumListRegistry.swift +++ b/LookInside/Dashboard/EnumListRegistry.swift @@ -14,7 +14,6 @@ import Foundation /// One case of an enum: its name, raw value, and the first OS major /// version that has it (0 for every version). -@objc(LKEnumListRegistryKeyValueItem) final class EnumListRegistryKeyValueItem: NSObject { @objc let desc: String @objc let value: Int @@ -27,7 +26,6 @@ final class EnumListRegistryKeyValueItem: NSObject { } } -@objc(LKEnumListRegistry) final class EnumListRegistry: NSObject { @objc(sharedInstance) static let shared = EnumListRegistry() diff --git a/LookInside/Dashboard/Search/DashboardSearchViews.swift b/LookInside/Dashboard/Search/DashboardSearchViews.swift index 7f27b179..3ca893c0 100644 --- a/LookInside/Dashboard/Search/DashboardSearchViews.swift +++ b/LookInside/Dashboard/Search/DashboardSearchViews.swift @@ -10,6 +10,7 @@ // import AppKit +import FoundationToolbox /// A search result card on a blurred background. class DashboardSearchCardView: BaseView { @@ -168,6 +169,7 @@ protocol DashboardSearchMethodsViewDelegate: AnyObject { /// The methods without arguments that match the search; a click invokes /// one. +@Loggable(subsystem: "com.lookinside.app") final class DashboardSearchMethodsView: DashboardSearchCardView { private let insetTop: CGFloat = 5 private let contentMarginTop: CGFloat = 10 @@ -256,7 +258,7 @@ final class DashboardSearchMethodsView: DashboardSearchCardView { } func render(error: Error) { - NSLog("%@", String(describing: error)) + #log(.default, "\(String(describing: error), privacy: .public)") itemViews.forEach { $0.isHidden = true } titleLabel.isHidden = true let label: TextLabel diff --git a/LookInside/DebugE2E/DebugE2EDumpWriter.swift b/LookInside/DebugE2E/DebugE2EDumpWriter.swift index 7f4a274a..2178a70a 100644 --- a/LookInside/DebugE2E/DebugE2EDumpWriter.swift +++ b/LookInside/DebugE2E/DebugE2EDumpWriter.swift @@ -13,7 +13,6 @@ /// The Host decodes screenshots into images it does not archive, so a /// node's `host` record names their pixel sizes; the pixels themselves are /// covered by lookin-probe. - @objc(LKDebugE2EDumpWriter) final class DebugE2EDumpWriter: NSObject { @objc(writeSnapshotForDataSource:app:platform:toDirectory:error:) static func writeSnapshot( diff --git a/LookInside/DebugE2E/DebugUISnapshots.swift b/LookInside/DebugE2E/DebugUISnapshots.swift index 6a691fac..244933b9 100644 --- a/LookInside/DebugE2E/DebugUISnapshots.swift +++ b/LookInside/DebugE2E/DebugUISnapshots.swift @@ -41,7 +41,6 @@ /// Host was active and the window key, the window's backing scale). The /// comparison (`lookin-probe ui-diff`) skips a scene whose state differs /// from the baseline's, and never loosens a threshold for it. - @objc(LKDebugUISnapshots) @MainActor final class DebugUISnapshots: NSObject { static let directoryVariable = "LOOKINSIDE_DEBUG_UI_SNAPSHOT_DIR" diff --git a/LookInside/DebugE2E/DebugWindowImage.swift b/LookInside/DebugE2E/DebugWindowImage.swift index 4a89c214..0429bb74 100644 --- a/LookInside/DebugE2E/DebugWindowImage.swift +++ b/LookInside/DebugE2E/DebugWindowImage.swift @@ -11,7 +11,6 @@ /// not capture, so each one's `SCNView.snapshot()` is drawn over its area, /// clipped away from the views that sit on top of it (outline, dashboard, /// toolbar). - @objc(LKDebugWindowImage) final class DebugWindowImage: NSObject { /// PNG of `window`'s frame view: title bar and toolbar included. @objc(pngDataOfWindow:) diff --git a/LookInside/Export/ExportAccessoryView.swift b/LookInside/Export/ExportAccessoryView.swift index 3416806c..08424671 100644 --- a/LookInside/Export/ExportAccessoryView.swift +++ b/LookInside/Export/ExportAccessoryView.swift @@ -9,7 +9,6 @@ import AppKit import LookInsideHostCore -@objc(LKExportAccessoryView) final class ExportAccessoryView: BaseView { private static let insetTop: CGFloat = 20 private static let insetBottom: CGFloat = 10 diff --git a/LookInside/Export/ExportManager.swift b/LookInside/Export/ExportManager.swift index 95f825f1..cba4cd69 100644 --- a/LookInside/Export/ExportManager.swift +++ b/LookInside/Export/ExportManager.swift @@ -11,7 +11,6 @@ import AppKit import LookInsideHostCore import UniformTypeIdentifiers -@objc(LKExportManager) final class ExportManager: NSObject { private static let shared = ExportManager() diff --git a/LookInside/GestureDebug/GestureDebugWindowController.swift b/LookInside/GestureDebug/GestureDebugWindowController.swift index a1b9355a..faa3160d 100644 --- a/LookInside/GestureDebug/GestureDebugWindowController.swift +++ b/LookInside/GestureDebug/GestureDebugWindowController.swift @@ -3,7 +3,6 @@ import SwiftUI import UniformTypeIdentifiers @MainActor -@objc(LKGestureDebugWindowController) final class GestureDebugWindowController: NSWindowController, NSWindowDelegate { private let session = GestureDebugSession() private var appObservation: NSKeyValueObservation? diff --git a/LookInside/Hierarchy/HierarchyController.swift b/LookInside/Hierarchy/HierarchyController.swift index 17ba72a7..5cb91aef 100644 --- a/LookInside/Hierarchy/HierarchyController.swift +++ b/LookInside/Hierarchy/HierarchyController.swift @@ -7,9 +7,9 @@ // import AppKit +import FoundationToolbox -@objc(LKHierarchyController) -@objcMembers +@Loggable(subsystem: "com.lookinside.app") class HierarchyController: BaseViewController, HierarchyViewDelegate { private(set) var dataSource: HierarchyDataSource private(set) var hierarchyView: HierarchyView @@ -48,12 +48,10 @@ class HierarchyController: BaseViewController, HierarchyViewDelegate { // MARK: - HierarchyViewDelegate - @objc(hierarchyView:didSelectItem:) func hierarchyView(_: HierarchyView, didSelect item: DisplayItem?) { dataSource.selectedItem = item } - @objc(hierarchyView:didDoubleClickItem:) func hierarchyView(_: HierarchyView, didDoubleClick item: DisplayItem) { switch PreferenceManager.shared.doubleClickBehavior { case .collapse: @@ -73,22 +71,18 @@ class HierarchyController: BaseViewController, HierarchyViewDelegate { } /// `item` is nil when the mouse leaves the rows. - @objc(hierarchyView:didHoverAtItem:) func hierarchyView(_: HierarchyView, didHoverAt item: DisplayItem?) { dataSource.hoveredItem = item } - @objc(hierarchyView:needToCollapseItem:) func hierarchyView(_: HierarchyView, needToCollapse item: DisplayItem) { dataSource.collapse(item) } - @objc(hierarchyView:needToCollapseChildrenOfItem:) func hierarchyView(_: HierarchyView, needToCollapseChildrenOf item: DisplayItem) { dataSource.collapseAllChildren(of: item) } - @objc(hierarchyView:needToExpandItem:recursively:) func hierarchyView(_: HierarchyView, needToExpand item: DisplayItem, recursively: Bool) { if recursively { dataSource.expandItemsRooted(by: item) @@ -97,9 +91,8 @@ class HierarchyController: BaseViewController, HierarchyViewDelegate { } } - @objc(hierarchyView:didInputSearchString:) func hierarchyView(_: HierarchyView, didInputSearch string: String?) { - NSLog("search string:%@", string ?? "(null)") + #log(.default, "search string:\(string ?? "(null)", privacy: .public)") if let string, !string.isEmpty { dataSource.search(with: string) return @@ -112,4 +105,9 @@ class HierarchyController: BaseViewController, HierarchyViewDelegate { } } } + + /// Subclasses that show previews override these two. + func hierarchyView(_: HierarchyView, needToCancelPreviewOf _: DisplayItem) {} + + func hierarchyView(_: HierarchyView, needToShowPreviewOf _: DisplayItem) {} } diff --git a/LookInside/Hierarchy/HierarchyDataSource.swift b/LookInside/Hierarchy/HierarchyDataSource.swift index ffe4228d..c61bc87c 100644 --- a/LookInside/Hierarchy/HierarchyDataSource.swift +++ b/LookInside/Hierarchy/HierarchyDataSource.swift @@ -8,6 +8,7 @@ import AppKit import LookInsideHostCore +import FoundationToolbox /// What the data source is showing. KVO-observable through `state`. @objc enum HierarchyDataSourceState: UInt { @@ -96,7 +97,7 @@ private func selfAndDescendants(of item: DisplayItem) -> [DisplayItem] { /// The hierarchy tree of a document: the flat rows, selection, hover, /// expansion, search and focus. Subclasses supply the preference manager. -@objc(LKHierarchyDataSource) +@Loggable(subsystem: "com.lookinside.app") class HierarchyDataSource: NSObject { /// KVO-observable. @objc dynamic var state: HierarchyDataSourceState { @@ -216,7 +217,7 @@ class HierarchyDataSource: NSObject { deinit { eventBroadcaster.finish() - NSLog("%@ dealloc", NSStringFromClass(type(of: self))) + #log(.default, "\(NSStringFromClass(type(of: self)), privacy: .public) dealloc") } // MARK: - Reload diff --git a/LookInside/Hierarchy/HierarchyRowView.swift b/LookInside/Hierarchy/HierarchyRowView.swift index 9a869765..cb4e2311 100644 --- a/LookInside/Hierarchy/HierarchyRowView.swift +++ b/LookInside/Hierarchy/HierarchyRowView.swift @@ -70,8 +70,6 @@ private func rgba(_ red: CGFloat, _ green: CGFloat, _ blue: CGFloat, _ alpha: CG NSColor(red: red / 255, green: green / 255, blue: blue / 255, alpha: alpha) } -@objc(LKHierarchyRowView) -@objcMembers class HierarchyRowView: OutlineRowView { /// Weak: the table keeps many row views around, and a strong reference /// would keep display items (and their screenshots) alive across diff --git a/LookInside/Hierarchy/HierarchyView.swift b/LookInside/Hierarchy/HierarchyView.swift index 5a59721f..d11c13e5 100644 --- a/LookInside/Hierarchy/HierarchyView.swift +++ b/LookInside/Hierarchy/HierarchyView.swift @@ -40,43 +40,33 @@ private final class HierarchyDebouncer { } } -@objc protocol HierarchyViewDelegate: NSObjectProtocol { - @objc(hierarchyView:didSelectItem:) +protocol HierarchyViewDelegate: AnyObject { func hierarchyView(_ view: HierarchyView, didSelect item: DisplayItem?) - @objc(hierarchyView:didDoubleClickItem:) func hierarchyView(_ view: HierarchyView, didDoubleClick item: DisplayItem) - @objc(hierarchyView:didHoverAtItem:) func hierarchyView(_ view: HierarchyView, didHoverAt item: DisplayItem?) - @objc(hierarchyView:needToExpandItem:recursively:) func hierarchyView(_ view: HierarchyView, needToExpand item: DisplayItem, recursively: Bool) - @objc(hierarchyView:needToCollapseItem:) func hierarchyView(_ view: HierarchyView, needToCollapse item: DisplayItem) - @objc(hierarchyView:needToCollapseChildrenOfItem:) func hierarchyView(_ view: HierarchyView, needToCollapseChildrenOf item: DisplayItem) /// 在底部的搜索框里输入了文字,string 可能为空字符串或 nil /// 当用户通过搜索框的关闭按钮、ESC 等方式手动结束搜索时,该方法同样会被调用,参数是 nil - @objc(hierarchyView:didInputSearchString:) func hierarchyView(_ view: HierarchyView, didInputSearch string: String?) - @objc(hierarchyView:needToCancelPreviewOfItem:) - optional func hierarchyView(_ view: HierarchyView, needToCancelPreviewOf item: DisplayItem) + func hierarchyView(_ view: HierarchyView, needToCancelPreviewOf item: DisplayItem) - @objc(hierarchyView:needToShowPreviewOfItem:) - optional func hierarchyView(_ view: HierarchyView, needToShowPreviewOf item: DisplayItem) + func hierarchyView(_ view: HierarchyView, needToShowPreviewOf item: DisplayItem) } -@objc(LKHierarchyView) -@objcMembers class HierarchyView: BaseView { let tableView: TableView - /// The filter field under the rows. The DEBUG UI snapshots type into it. - let searchTextFieldView: TextFieldView + /// The filter field under the rows. The DEBUG UI snapshots type into it + /// and read it by key. + @objc let searchTextFieldView: TextFieldView var dataSource: HierarchyDataSource /// Phase A 引入:由 owner(StaticHierarchyController / StaticViewController 链路)注入的 per-instance update manager(weak)。 /// 若 nil 则 fallback 到 +sharedInstance,以保留 read-only / archive workspace 的 legacy 行为。 @@ -403,12 +393,12 @@ class HierarchyView: BaseView { @objc fileprivate func handleShowPreview(_ menuItem: NSMenuItem) { guard let item = displayItem(of: menuItem) else { return } - delegate?.hierarchyView?(self, needToShowPreviewOf: item) + delegate?.hierarchyView(self, needToShowPreviewOf: item) } @objc fileprivate func handleCancelPreview(_ menuItem: NSMenuItem) { guard let item = displayItem(of: menuItem) else { return } - delegate?.hierarchyView?(self, needToCancelPreviewOf: item) + delegate?.hierarchyView(self, needToCancelPreviewOf: item) } @objc fileprivate func handleExportScreenshot(_ menuItem: NSMenuItem) { diff --git a/LookInside/Injection/Device/DeviceInjectionFlow.swift b/LookInside/Injection/Device/DeviceInjectionFlow.swift index cd11e3a4..e2c4727e 100644 --- a/LookInside/Injection/Device/DeviceInjectionFlow.swift +++ b/LookInside/Injection/Device/DeviceInjectionFlow.swift @@ -19,7 +19,6 @@ import RunningApplicationKit /// leaves the foreground, so the ordinary path stops running into them. They /// are still bugs and still need fixing; this just stops them being hit every /// single time. -@objc(LKDeviceInjectionFlow) final class DeviceInjectionFlow: NSObject { @objc(sharedInstance) static let shared = DeviceInjectionFlow() diff --git a/LookInside/Injection/InjectableFrameworkInstaller.swift b/LookInside/Injection/InjectableFrameworkInstaller.swift index fa6d8c62..12c077f4 100644 --- a/LookInside/Injection/InjectableFrameworkInstaller.swift +++ b/LookInside/Injection/InjectableFrameworkInstaller.swift @@ -1,5 +1,6 @@ import AppKit import Foundation +import FoundationToolbox enum InjectableFrameworkInstallerError: LocalizedError { case downloadFailed(String) @@ -104,6 +105,7 @@ struct InjectableFrameworkInstallation { let frameworkURL: URL } +@Loggable(subsystem: "com.lookinside.app", category: "Installer") final class InjectableFrameworkInstaller { static let shared = InjectableFrameworkInstaller() @@ -133,32 +135,32 @@ final class InjectableFrameworkInstaller { installLock.lock() defer { installLock.unlock() } - InstallerLogger.installer.info("ensureInstalled: entered") + #log(.info, "ensureInstalled: entered") let targetVersion = resolveTargetVersion() - InstallerLogger.installer.info( + #log(.info, "ensureInstalled: resolved target version=\(targetVersion, privacy: .public)" ) let installedURL = InjectableFrameworkInstallerLayout.installedFrameworkURL(for: targetVersion) - InstallerLogger.installer.info( + #log(.info, "ensureInstalled: checking existing path=\(installedURL.path, privacy: .public)" ) if FileManager.default.fileExists(atPath: installedURL.path) { do { try verifyTeamIdentifier(of: installedURL) - InstallerLogger.installer.info( + #log(.info, "ensureInstalled: existing framework valid; reusing version=\(targetVersion, privacy: .public)" ) return InjectableFrameworkInstallation(version: targetVersion, frameworkURL: installedURL) } catch { - InstallerLogger.installer.notice( + #log(.default, "ensureInstalled: existing framework signature invalid (\(error.localizedDescription, privacy: .public)); will re-download" ) try? FileManager.default.removeItem(at: installedURL) } } else { - InstallerLogger.installer.info("ensureInstalled: no existing framework; running modal install") + #log(.info, "ensureInstalled: no existing framework; running modal install") } return try runInstallWithModal(version: targetVersion, presentingWindow: presentingWindow) @@ -179,7 +181,7 @@ final class InjectableFrameworkInstaller { private func resolveTargetVersion() -> String { let minimum = InjectableFrameworkInstallerLayout.minimumServerVersion guard let latest = fetchLatestVersionFromGitHub() else { - InstallerLogger.installer.info( + #log(.info, "GH latest-release lookup unavailable, falling back to minimum version=\(minimum, privacy: .public)" ) return minimum @@ -187,7 +189,7 @@ final class InjectableFrameworkInstaller { if compareSemver(latest, minimum) >= 0 { return latest } - InstallerLogger.installer.notice( + #log(.default, "GH latest=\(latest, privacy: .public) is older than minimum=\(minimum, privacy: .public); using minimum" ) return minimum @@ -206,7 +208,7 @@ final class InjectableFrameworkInstaller { let task = URLSession.shared.dataTask(with: request) { data, response, error in defer { semaphore.signal() } if let error { - InstallerLogger.installer.warning( + #log(.error, "GH latest fetch failed: \(error.localizedDescription, privacy: .public)" ) return @@ -216,7 +218,7 @@ final class InjectableFrameworkInstaller { let data else { let status = (response as? HTTPURLResponse)?.statusCode ?? -1 - InstallerLogger.installer.warning("GH latest fetch returned status=\(status)") + #log(.error, "GH latest fetch returned status=\(status)") return } do { @@ -225,7 +227,7 @@ final class InjectableFrameworkInstaller { capturedTag = tag } } catch { - InstallerLogger.installer.warning( + #log(.error, "GH latest JSON parse failed: \(error.localizedDescription, privacy: .public)" ) } @@ -259,7 +261,7 @@ final class InjectableFrameworkInstaller { private func runInstallWithModal(version: String, presentingWindow _: NSWindow?) throws -> InjectableFrameworkInstallation { precondition(Thread.isMainThread, "runInstallWithModal must run on the main thread") - InstallerLogger.installer.info("runInstallWithModal: start version=\(version, privacy: .public)") + #log(.info, "runInstallWithModal: start version=\(version, privacy: .public)") let cancellation = InstallerCancellation() let controller = InstallerProgressWindowController( @@ -273,24 +275,24 @@ final class InjectableFrameworkInstaller { NSApp.stopModal() } controller.showWindow(self) - InstallerLogger.installer.info("runInstallWithModal: progress window shown") + #log(.info, "runInstallWithModal: progress window shown") var captured: Result? let semaphore = DispatchSemaphore(value: 0) Thread.detachNewThread { - InstallerLogger.installer.info("install worker: thread started") + #log(.info, "install worker: thread started") do { let installation = try self.performInstall(version: version, cancellation: cancellation) { stage in - InstallerLogger.installer.info("install worker: stage=\(String(describing: stage), privacy: .public)") + #log(.info, "install worker: stage=\(String(describing: stage), privacy: .public)") RunLoop.main.perform(inModes: [.default, .modalPanel, .common]) { controller.updateStatus(stage.localizedDescription) } } - InstallerLogger.installer.info("install worker: success") + #log(.info, "install worker: success") captured = .success(installation) } catch { - InstallerLogger.installer.error( + #log(.error, "install worker: failed error=\(error.localizedDescription, privacy: .public)" ) captured = .failure(error) @@ -301,18 +303,18 @@ final class InjectableFrameworkInstaller { } } - InstallerLogger.installer.info("runInstallWithModal: entering runModal") + #log(.info, "runInstallWithModal: entering runModal") NSApp.runModal(for: controller.window!) - InstallerLogger.installer.info("runInstallWithModal: runModal returned") + #log(.info, "runInstallWithModal: runModal returned") let waitResult = semaphore.wait(timeout: .now() + 5) controller.close() if cancelledByUser { - InstallerLogger.installer.info("runInstallWithModal: cancelled by user") + #log(.info, "runInstallWithModal: cancelled by user") throw InjectableFrameworkInstallerError.cancelled } if waitResult == .timedOut { - InstallerLogger.installer.error("runInstallWithModal: worker did not signal within 5s after modal stop") + #log(.error, "runInstallWithModal: worker did not signal within 5s after modal stop") cancellation.cancel() throw InjectableFrameworkInstallerError.cancelled } @@ -335,7 +337,7 @@ final class InjectableFrameworkInstaller { let stagingRoot = fileManager.temporaryDirectory .appendingPathComponent("LookInsideServerFramework-\(UUID().uuidString)", isDirectory: true) try fileManager.createDirectory(at: stagingRoot, withIntermediateDirectories: true) - InstallerLogger.installer.info( + #log(.info, "performInstall: staging root=\(stagingRoot.path, privacy: .public)" ) defer { @@ -346,7 +348,7 @@ final class InjectableFrameworkInstaller { onStage(.downloading) let zipURL = stagingRoot.appendingPathComponent("server.xcframework.zip", isDirectory: false) let downloadURL = InjectableFrameworkInstallerLayout.assetDownloadURL(for: version) - InstallerLogger.installer.info( + #log(.info, "performInstall: starting download url=\(downloadURL.absoluteString, privacy: .public)" ) try InstallerDownloader.download( @@ -357,30 +359,30 @@ final class InjectableFrameworkInstaller { errorBuilder: { InjectableFrameworkInstallerError.downloadFailed($0) } ) let zipSize = (try? fileManager.attributesOfItem(atPath: zipURL.path)[.size] as? Int) ?? -1 - InstallerLogger.installer.info("performInstall: download complete bytes=\(zipSize)") + #log(.info, "performInstall: download complete bytes=\(zipSize)") try cancellation.checkCancellation() onStage(.extracting) let extractDir = stagingRoot.appendingPathComponent("extracted", isDirectory: true) try fileManager.createDirectory(at: extractDir, withIntermediateDirectories: true) - InstallerLogger.installer.info("performInstall: starting unzip into=\(extractDir.path, privacy: .public)") + #log(.info, "performInstall: starting unzip into=\(extractDir.path, privacy: .public)") try InstallerArchiveExtractor.unzip( zipURL, into: extractDir, cancellation: cancellation, errorBuilder: { InjectableFrameworkInstallerError.unzipFailed($0) } ) - InstallerLogger.installer.info("performInstall: unzip complete") + #log(.info, "performInstall: unzip complete") try cancellation.checkCancellation() let stagedFramework = try locateMacFramework(in: extractDir) - InstallerLogger.installer.info( + #log(.info, "performInstall: located macOS framework path=\(stagedFramework.path, privacy: .public)" ) onStage(.verifying) try verifyTeamIdentifier(of: stagedFramework) - InstallerLogger.installer.info("performInstall: signature verified") + #log(.info, "performInstall: signature verified") try cancellation.checkCancellation() onStage(.installing) @@ -398,7 +400,7 @@ final class InjectableFrameworkInstaller { } catch { throw InjectableFrameworkInstallerError.installFailed(error.localizedDescription) } - InstallerLogger.installer.info( + #log(.info, "performInstall: moved into place path=\(destinationFramework.path, privacy: .public)" ) @@ -406,12 +408,12 @@ final class InjectableFrameworkInstaller { onStage(.finishing) try verifyTeamIdentifier(of: destinationFramework) - InstallerLogger.installer.info( + #log(.info, "performInstall: done version=\(version, privacy: .public)" ) return InjectableFrameworkInstallation(version: version, frameworkURL: destinationFramework) } catch is InstallerCancelled { - InstallerLogger.installer.info("performInstall: cancelled") + #log(.info, "performInstall: cancelled") throw InjectableFrameworkInstallerError.cancelled } } diff --git a/LookInside/Injection/InjectionFlow.swift b/LookInside/Injection/InjectionFlow.swift index 065068ea..b2449b17 100644 --- a/LookInside/Injection/InjectionFlow.swift +++ b/LookInside/Injection/InjectionFlow.swift @@ -14,7 +14,6 @@ import Foundation /// 5. Brief sleep so the target app's Server listener can bind; the existing /// `LaunchViewController` 1.5s refresh tick then discovers the newly /// inspectable app automatically. -@objc(LKInjectionFlow) final class InjectionFlow: NSObject { @objc(sharedInstance) static let shared = InjectionFlow() diff --git a/LookInside/Launch/LaunchAppView.swift b/LookInside/Launch/LaunchAppView.swift index 13512763..64fa517a 100644 --- a/LookInside/Launch/LaunchAppView.swift +++ b/LookInside/Launch/LaunchAppView.swift @@ -12,7 +12,6 @@ import AppKit /// screenshot over the device icon, device name and OS. An app whose Server /// version is unsupported shows the error and a link to the explanation /// instead. -@objc(LKLaunchAppView) final class LaunchAppView: BaseControl { private let hoverBgLayer = CALayer() private let previewImageView = NSImageView() diff --git a/LookInside/Launch/LaunchViewController.swift b/LookInside/Launch/LaunchViewController.swift index 473ee9b1..598e569e 100644 --- a/LookInside/Launch/LaunchViewController.swift +++ b/LookInside/Launch/LaunchViewController.swift @@ -11,7 +11,6 @@ import AppKit /// The launch window's content: the inspectable apps found so far, rescanned /// every 1.5 seconds, and the attach-to-running-app button. Picking an app /// fetches its hierarchy and opens a live document for it. -@objc(LKLaunchViewController) final class LaunchViewController: BaseViewController { private static let appViewInterSpace: CGFloat = 10 private static let contentHorInset: CGFloat = 30 diff --git a/LookInside/Launch/LaunchWindowController.swift b/LookInside/Launch/LaunchWindowController.swift index 19eb4d4b..913fc95b 100644 --- a/LookInside/Launch/LaunchWindowController.swift +++ b/LookInside/Launch/LaunchWindowController.swift @@ -9,7 +9,6 @@ import AppKit /// The small launch window that lists the inspectable apps. -@objc(LKLaunchWindowController) final class LaunchWindowController: WindowController { @objc let launchViewController: LaunchViewController diff --git a/LookInside/MCPBridge/MCPBridgeConnection.swift b/LookInside/MCPBridge/MCPBridgeConnection.swift index ff1e740c..70a04aa2 100644 --- a/LookInside/MCPBridge/MCPBridgeConnection.swift +++ b/LookInside/MCPBridge/MCPBridgeConnection.swift @@ -26,7 +26,9 @@ import Darwin import Dispatch import Foundation import os +import FoundationToolbox +@Loggable(subsystem: "com.lookinside.app", category: "MCPBridge.Connection") final class MCPBridgeConnection { typealias RequestHandler = @Sendable (MCPBridgeRequest) async -> MCPBridgeResponse @@ -35,7 +37,6 @@ final class MCPBridgeConnection { /// limit is generous; this is purely a safety cap against runaway peers. private static let maximumFrameBytes = 8 * 1024 * 1024 - private static let logger = Logger(subsystem: "com.lookinside.app", category: "MCPBridge.Connection") private let fileDescriptor: Int32 private let connectionQueue: DispatchQueue @@ -101,7 +102,7 @@ final class MCPBridgeConnection { dispatchPrecondition(condition: .onQueue(connectionQueue)) guard isClosed == false else { return } isClosed = true - Self.logger.notice("Connection closed: \(reason, privacy: .public)") + #log(.default, "Connection closed: \(reason, privacy: .public)") readSource?.cancel() readSource = nil onClose(self) @@ -157,7 +158,7 @@ final class MCPBridgeConnection { self.send(response: response) } } catch { - Self.logger.error("Failed to decode inbound frame as request: \(error.localizedDescription, privacy: .public)") + #log(.error, "Failed to decode inbound frame as request: \(error.localizedDescription, privacy: .public)") // No identifier available — push a generic error event so the peer // can observe the malformed frame without correlating to a request. let event = MCPBridgeEvent( @@ -187,7 +188,7 @@ final class MCPBridgeConnection { encoded.append(UInt8(ascii: "\n")) data = encoded } catch { - Self.logger.error("Failed to encode outbound frame: \(error.localizedDescription, privacy: .public)") + #log(.error, "Failed to encode outbound frame: \(error.localizedDescription, privacy: .public)") return } connectionQueue.async { [weak self] in diff --git a/LookInside/MCPBridge/MCPBridgeDetailsService.swift b/LookInside/MCPBridge/MCPBridgeDetailsService.swift index 4dacf646..97b04f49 100644 --- a/LookInside/MCPBridge/MCPBridgeDetailsService.swift +++ b/LookInside/MCPBridge/MCPBridgeDetailsService.swift @@ -28,7 +28,9 @@ import AppKit import CoreGraphics import Foundation import os +import FoundationToolbox +@Loggable(subsystem: "com.lookinside.app", category: "MCPBridge.Details") @MainActor final class MCPBridgeDetailsService { /// Hard cap on per-call batch size. Matches the host inspector's @@ -37,7 +39,6 @@ final class MCPBridgeDetailsService { /// need more issue multiple calls. private static let maximumObjectIdentifiersPerCall = 100 - private static let logger = Logger(subsystem: "com.lookinside.app", category: "MCPBridge.Details") init() {} @@ -80,7 +81,7 @@ final class MCPBridgeDetailsService { case let .success(parsed): requestedIdentifiers = parsed.identifiers if parsed.droppedDuplicateCount > 0 { - Self.logger.debug( + #log(.debug, "details.read collapsed \(parsed.droppedDuplicateCount, privacy: .public) duplicate object identifier(s)" ) } @@ -310,7 +311,7 @@ final class MCPBridgeDetailsService { let payload = try encodeAsJSONValue(result) return .success(identifier: identifier, result: payload) } catch { - Self.logger.error("details.read encode failed: \(error.localizedDescription, privacy: .public)") + #log(.error, "details.read encode failed: \(error.localizedDescription, privacy: .public)") return .failure(identifier: identifier, error: .internalError) } } @@ -340,7 +341,7 @@ final class MCPBridgeDetailsService { message: "The target app did not respond within the request timeout. Reduce the batch size or check whether the target is paused in Xcode." ) default: - Self.logger.error("details.read received unmapped error code \(error.code, privacy: .public): \(error.localizedDescription, privacy: .public)") + #log(.error, "details.read received unmapped error code \(error.code, privacy: .public): \(error.localizedDescription, privacy: .public)") return MCPBridgeErrorPayload( code: "details.internalError", message: "The target app reported an unexpected error (code \(error.code))." diff --git a/LookInside/MCPBridge/MCPBridgeEventPublisher.swift b/LookInside/MCPBridge/MCPBridgeEventPublisher.swift index c489ca9c..f87de246 100644 --- a/LookInside/MCPBridge/MCPBridgeEventPublisher.swift +++ b/LookInside/MCPBridge/MCPBridgeEventPublisher.swift @@ -40,10 +40,11 @@ import AppKit import Foundation import os +import FoundationToolbox +@Loggable(subsystem: "com.lookinside.app", category: "MCPBridge.Events") @MainActor final class MCPBridgeEventPublisher { - private static let logger = Logger(subsystem: "com.lookinside.app", category: "MCPBridge.Events") /// Where finished events go. Injected rather than reaching for the /// server singleton so this type can be exercised without a socket. diff --git a/LookInside/MCPBridge/MCPBridgeInspectionService.swift b/LookInside/MCPBridge/MCPBridgeInspectionService.swift index 4b41493b..fa0a19f4 100644 --- a/LookInside/MCPBridge/MCPBridgeInspectionService.swift +++ b/LookInside/MCPBridge/MCPBridgeInspectionService.swift @@ -12,10 +12,11 @@ import AppKit import CoreGraphics import Foundation import os +import FoundationToolbox +@Loggable(subsystem: "com.lookinside.app", category: "MCPBridge.Inspection") @MainActor final class MCPBridgeInspectionService { - private static let logger = Logger(subsystem: "com.lookinside.app", category: "MCPBridge.Inspection") init() {} @@ -44,7 +45,7 @@ final class MCPBridgeInspectionService { let payload = try encodeAsJSONValue(infos) return .success(identifier: identifier, result: .object(["targets": payload])) } catch { - Self.logger.error("targets.list encode failed: \(error.localizedDescription, privacy: .public)") + #log(.error, "targets.list encode failed: \(error.localizedDescription, privacy: .public)") return .failure(identifier: identifier, error: .internalError) } } @@ -160,7 +161,7 @@ final class MCPBridgeInspectionService { let payload = try encodeAsJSONValue(nodes) return .success(identifier: identifier, result: .object(["roots": payload])) } catch { - Self.logger.error("hierarchy.read encode failed: \(error.localizedDescription, privacy: .public)") + #log(.error, "hierarchy.read encode failed: \(error.localizedDescription, privacy: .public)") return .failure(identifier: identifier, error: .internalError) } } @@ -306,7 +307,7 @@ final class MCPBridgeInspectionService { ]) ) } catch { - Self.logger.error("attributes.read encode failed: \(error.localizedDescription, privacy: .public)") + #log(.error, "attributes.read encode failed: \(error.localizedDescription, privacy: .public)") return .failure(identifier: identifier, error: .internalError) } } diff --git a/LookInside/MCPBridge/MCPBridgeInvocationService.swift b/LookInside/MCPBridge/MCPBridgeInvocationService.swift index e59015e6..5bff2ccf 100644 --- a/LookInside/MCPBridge/MCPBridgeInvocationService.swift +++ b/LookInside/MCPBridge/MCPBridgeInvocationService.swift @@ -17,10 +17,11 @@ import AppKit import Foundation import os +import FoundationToolbox +@Loggable(subsystem: "com.lookinside.app", category: "MCPBridge.Invocation") @MainActor final class MCPBridgeInvocationService { - private static let logger = Logger(subsystem: "com.lookinside.app", category: "MCPBridge.Invocation") init() {} @@ -152,7 +153,7 @@ final class MCPBridgeInvocationService { let payload = try encodeAsJSONValue(invocationResult) return .success(identifier: identifier, result: payload) } catch { - Self.logger.error("invoke.method encode failed: \(error.localizedDescription, privacy: .public)") + #log(.error, "invoke.method encode failed: \(error.localizedDescription, privacy: .public)") return .failure(identifier: identifier, error: .internalError) } } @@ -223,7 +224,7 @@ final class MCPBridgeInvocationService { message: "The target app did not respond within the request timeout. Check whether it is paused in Xcode or blocked on the main thread." ) default: - Self.logger.error("invoke.method received unmapped error code \(error.code, privacy: .public): \(error.localizedDescription, privacy: .public)") + #log(.error, "invoke.method received unmapped error code \(error.code, privacy: .public): \(error.localizedDescription, privacy: .public)") return MCPBridgeErrorPayload( code: "invoke.internalError", message: "The target app reported an unexpected error (code \(error.code))." diff --git a/LookInside/MCPBridge/MCPBridgeModificationService.swift b/LookInside/MCPBridge/MCPBridgeModificationService.swift index b711e123..bb6dd9cf 100644 --- a/LookInside/MCPBridge/MCPBridgeModificationService.swift +++ b/LookInside/MCPBridge/MCPBridgeModificationService.swift @@ -23,10 +23,11 @@ import AppKit import CoreGraphics import Foundation import os +import FoundationToolbox +@Loggable(subsystem: "com.lookinside.app", category: "MCPBridge.Modification") @MainActor final class MCPBridgeModificationService { - private static let logger = Logger(subsystem: "com.lookinside.app", category: "MCPBridge.Modification") init() {} @@ -165,7 +166,7 @@ final class MCPBridgeModificationService { ) ) } catch { - Self.logger.error("Unexpected decode error: \(error.localizedDescription, privacy: .public)") + #log(.error, "Unexpected decode error: \(error.localizedDescription, privacy: .public)") return .failure(identifier: identifier, error: .internalError) } @@ -250,7 +251,7 @@ final class MCPBridgeModificationService { let payload = try encodeAsJSONValue(result) return .success(identifier: identifier, result: payload) } catch { - Self.logger.error("attribute.modify encode failed: \(error.localizedDescription, privacy: .public)") + #log(.error, "attribute.modify encode failed: \(error.localizedDescription, privacy: .public)") return .failure(identifier: identifier, error: .internalError) } } @@ -329,7 +330,7 @@ final class MCPBridgeModificationService { message: "The target app did not respond within the request timeout. Check whether it is paused in Xcode or blocked on the main thread." ) default: - Self.logger.error("attribute.modify received unmapped error code \(error.code, privacy: .public): \(error.localizedDescription, privacy: .public)") + #log(.error, "attribute.modify received unmapped error code \(error.code, privacy: .public): \(error.localizedDescription, privacy: .public)") return MCPBridgeErrorPayload( code: "modify.internalError", message: "The target app reported an unexpected error (code \(error.code))." diff --git a/LookInside/MCPBridge/MCPBridgeRefreshService.swift b/LookInside/MCPBridge/MCPBridgeRefreshService.swift index e2d2e8e0..9b97faa0 100644 --- a/LookInside/MCPBridge/MCPBridgeRefreshService.swift +++ b/LookInside/MCPBridge/MCPBridgeRefreshService.swift @@ -28,10 +28,11 @@ import AppKit import Foundation import os +import FoundationToolbox +@Loggable(subsystem: "com.lookinside.app", category: "MCPBridge.Refresh") @MainActor final class MCPBridgeRefreshService { - private static let logger = Logger(subsystem: "com.lookinside.app", category: "MCPBridge.Refresh") init() {} @@ -120,7 +121,7 @@ final class MCPBridgeRefreshService { let payload = try encodeAsJSONValue(result) return .success(identifier: identifier, result: payload) } catch { - Self.logger.error("hierarchy.refresh encode failed: \(error.localizedDescription, privacy: .public)") + #log(.error, "hierarchy.refresh encode failed: \(error.localizedDescription, privacy: .public)") return .failure(identifier: identifier, error: .internalError) } } @@ -162,7 +163,7 @@ final class MCPBridgeRefreshService { message: "The target app finished the hierarchy request without returning a hierarchy. The channel may have been closed mid-request." ) default: - Self.logger.error("hierarchy.refresh received unmapped host refusal \(error.code, privacy: .public)") + #log(.error, "hierarchy.refresh received unmapped host refusal \(error.code, privacy: .public)") return MCPBridgeErrorPayload( code: "refresh.internalError", message: "The inspector declined the reload for an unexpected reason (code \(error.code))." @@ -184,7 +185,7 @@ final class MCPBridgeRefreshService { message: "The target app did not return its hierarchy within the request timeout. Check whether it is paused in Xcode or blocked on the main thread." ) default: - Self.logger.error("hierarchy.refresh received unmapped error code \(error.code, privacy: .public): \(error.localizedDescription, privacy: .public)") + #log(.error, "hierarchy.refresh received unmapped error code \(error.code, privacy: .public): \(error.localizedDescription, privacy: .public)") return MCPBridgeErrorPayload( code: "refresh.internalError", message: "The target app reported an unexpected error (code \(error.code))." diff --git a/LookInside/MCPBridge/MCPBridgeScreenshotService.swift b/LookInside/MCPBridge/MCPBridgeScreenshotService.swift index f576bfee..3b01a017 100644 --- a/LookInside/MCPBridge/MCPBridgeScreenshotService.swift +++ b/LookInside/MCPBridge/MCPBridgeScreenshotService.swift @@ -37,7 +37,9 @@ import AppKit import CoreGraphics import Foundation import os +import FoundationToolbox +@Loggable(subsystem: "com.lookinside.app", category: "MCPBridge.Screenshot") @MainActor final class MCPBridgeScreenshotService { // MARK: - Configuration @@ -57,7 +59,6 @@ final class MCPBridgeScreenshotService { /// Lower bound, purely to reject nonsense input (0, negatives). private static let minimumPixelDimension = 16 - private static let logger = Logger(subsystem: "com.lookinside.app", category: "MCPBridge.Screenshot") init() {} @@ -364,7 +365,7 @@ final class MCPBridgeScreenshotService { let payload = try encodeAsJSONValue(result) return .success(identifier: identifier, result: payload) } catch { - Self.logger.error("screenshot.read encode failed: \(error.localizedDescription, privacy: .public)") + #log(.error, "screenshot.read encode failed: \(error.localizedDescription, privacy: .public)") return .failure(identifier: identifier, error: .internalError) } } @@ -475,7 +476,7 @@ final class MCPBridgeScreenshotService { message: "The target app did not render within the request timeout. Check whether the target is paused in Xcode." ) default: - Self.logger.error("screenshot.read received unmapped error code \(error.code, privacy: .public): \(error.localizedDescription, privacy: .public)") + #log(.error, "screenshot.read received unmapped error code \(error.code, privacy: .public): \(error.localizedDescription, privacy: .public)") return MCPBridgeErrorPayload( code: "screenshot.internalError", message: "The target app reported an unexpected error (code \(error.code))." diff --git a/LookInside/MCPBridge/MCPBridgeSearchService.swift b/LookInside/MCPBridge/MCPBridgeSearchService.swift index cee93aa0..1e332213 100644 --- a/LookInside/MCPBridge/MCPBridgeSearchService.swift +++ b/LookInside/MCPBridge/MCPBridgeSearchService.swift @@ -22,7 +22,9 @@ import AppKit import Foundation import os +import FoundationToolbox +@Loggable(subsystem: "com.lookinside.app", category: "MCPBridge.Search") @MainActor final class MCPBridgeSearchService { /// Default number of matches returned when the caller doesn't ask. @@ -35,7 +37,6 @@ final class MCPBridgeSearchService { /// asking for the whole tree and should use `hierarchy.read`. private static let maximumMatchLimit = 500 - private static let logger = Logger(subsystem: "com.lookinside.app", category: "MCPBridge.Search") init() {} @@ -225,7 +226,7 @@ final class MCPBridgeSearchService { let payload = try encodeAsJSONValue(result) return .success(identifier: identifier, result: payload) } catch { - Self.logger.error("hierarchy.find encode failed: \(error.localizedDescription, privacy: .public)") + #log(.error, "hierarchy.find encode failed: \(error.localizedDescription, privacy: .public)") return .failure(identifier: identifier, error: .internalError) } } diff --git a/LookInside/MCPBridge/MCPBridgeSelectorService.swift b/LookInside/MCPBridge/MCPBridgeSelectorService.swift index f522b446..d9d57a34 100644 --- a/LookInside/MCPBridge/MCPBridgeSelectorService.swift +++ b/LookInside/MCPBridge/MCPBridgeSelectorService.swift @@ -19,7 +19,9 @@ import AppKit import Foundation import os +import FoundationToolbox +@Loggable(subsystem: "com.lookinside.app", category: "MCPBridge.Selectors") @MainActor final class MCPBridgeSelectorService { /// Default cap on returned selectors. Deliberately far below the @@ -31,7 +33,6 @@ final class MCPBridgeSelectorService { /// Ceiling on `limit`. private static let maximumSelectorLimit = 2000 - private static let logger = Logger(subsystem: "com.lookinside.app", category: "MCPBridge.Selectors") init() {} @@ -228,7 +229,7 @@ final class MCPBridgeSelectorService { let payload = try encodeAsJSONValue(result) return .success(identifier: identifier, result: payload) } catch { - Self.logger.error("selectors.list encode failed: \(error.localizedDescription, privacy: .public)") + #log(.error, "selectors.list encode failed: \(error.localizedDescription, privacy: .public)") return .failure(identifier: identifier, error: .internalError) } } @@ -257,7 +258,7 @@ final class MCPBridgeSelectorService { message: "The target app did not respond within the request timeout. Check whether it is paused in Xcode or blocked on the main thread." ) default: - Self.logger.error("selectors.list received unmapped error code \(error.code, privacy: .public): \(error.localizedDescription, privacy: .public)") + #log(.error, "selectors.list received unmapped error code \(error.code, privacy: .public): \(error.localizedDescription, privacy: .public)") return MCPBridgeErrorPayload( code: "selectors.internalError", message: "The target app reported an unexpected error (code \(error.code))." diff --git a/LookInside/MCPBridge/MCPBridgeServer.swift b/LookInside/MCPBridge/MCPBridgeServer.swift index b683a969..2a1dd06d 100644 --- a/LookInside/MCPBridge/MCPBridgeServer.swift +++ b/LookInside/MCPBridge/MCPBridgeServer.swift @@ -19,8 +19,9 @@ import Darwin import Dispatch import Foundation import os +import FoundationToolbox -@objc(LKMCPBridgeServer) +@Loggable(subsystem: "com.lookinside.app", category: "MCPBridge.Server") final class MCPBridgeServer: NSObject { // MARK: - Singleton @@ -31,7 +32,6 @@ final class MCPBridgeServer: NSObject { /// Maximum number of pending connections in the kernel accept queue. private static let listenBacklog: Int32 = 16 - private static let logger = Logger(subsystem: "com.lookinside.app", category: "MCPBridge.Server") // MARK: - State @@ -115,10 +115,10 @@ final class MCPBridgeServer: NSObject { do { try self.bindAndListen() self.isRunning = true - Self.logger.notice("MCPBridge started at \(MCPBridgeServer.socketURL.path, privacy: .public)") + #log(.default, "MCPBridge started at \(MCPBridgeServer.socketURL.path, privacy: .public)") self.startEventPublisher() } catch { - Self.logger.error("MCPBridge failed to start: \(error.localizedDescription, privacy: .public)") + #log(.error, "MCPBridge failed to start: \(error.localizedDescription, privacy: .public)") self.cleanUpListenSocket() } } @@ -145,7 +145,7 @@ final class MCPBridgeServer: NSObject { } self.openConnections.removeAll() self.activeConnections.removeAll() - Self.logger.notice("MCPBridge stopped") + #log(.default, "MCPBridge stopped") Task { @MainActor in Self.eventPublisher?.stop() Self.eventPublisher = nil @@ -221,7 +221,7 @@ final class MCPBridgeServer: NSObject { if errorNumber == EAGAIN || errorNumber == EWOULDBLOCK { return } - Self.logger.error("accept() failed (errno \(errorNumber))") + #log(.error, "accept() failed (errno \(errorNumber))") return } let connection = MCPBridgeConnection( @@ -240,7 +240,7 @@ final class MCPBridgeServer: NSObject { let key = ObjectIdentifier(connection) openConnections[key] = connection activeConnections.insert(key) - Self.logger.notice("Accepted connection (fd=\(clientDescriptor))") + #log(.default, "Accepted connection (fd=\(clientDescriptor))") connection.start() } } diff --git a/LookInside/Manager/AppMenuManager.swift b/LookInside/Manager/AppMenuManager.swift index 5a793ab7..9b49439a 100644 --- a/LookInside/Manager/AppMenuManager.swift +++ b/LookInside/Manager/AppMenuManager.swift @@ -16,7 +16,7 @@ import Sparkle /// The menu sends each command to the key window's controller, and enables /// the item only when the controller implements the method. -@objc(LKAppMenuManagerDelegate) +@objc @MainActor protocol AppMenuManagerDelegate: NSObjectProtocol { @objc optional func appMenuManagerDidSelectReload() @@ -33,7 +33,6 @@ protocol AppMenuManagerDelegate: NSObjectProtocol { @objc optional func appMenuManagerDidSelectOpenInNewWindow() } -@objc(LKAppMenuManager) @MainActor final class AppMenuManager: NSObject, NSMenuDelegate { static let shared = AppMenuManager() diff --git a/LookInside/Manager/NavigationManager.swift b/LookInside/Manager/NavigationManager.swift index 8408d41c..01c1da71 100644 --- a/LookInside/Manager/NavigationManager.swift +++ b/LookInside/Manager/NavigationManager.swift @@ -11,7 +11,6 @@ import AppKit -@objc(LKNavigationManager) @MainActor final class NavigationManager: NSObject, NSWindowDelegate { static let shared = NavigationManager() diff --git a/LookInside/Manager/PreferenceManager.swift b/LookInside/Manager/PreferenceManager.swift index 372efbee..78c524ae 100644 --- a/LookInside/Manager/PreferenceManager.swift +++ b/LookInside/Manager/PreferenceManager.swift @@ -61,7 +61,6 @@ let NotificationName_DidChangeSectionShowing = "NotificationName_DidChangeSectio case locked } -@objc(LKPreferenceManager) final class PreferenceManager: NSObject { /// User-defaults keys. Never rename: they hold existing users' settings. private enum Key { diff --git a/LookInside/Measure/MeasureController.swift b/LookInside/Measure/MeasureController.swift index a9c3976d..e22e928b 100644 --- a/LookInside/Measure/MeasureController.swift +++ b/LookInside/Measure/MeasureController.swift @@ -10,7 +10,6 @@ import AppKit import LookInsideHostCore -@objc(LKMeasureController) final class MeasureController: BaseViewController { private static let placeholderInsets = NSEdgeInsets(top: 15, left: 5, bottom: 12, right: 5) diff --git a/LookInside/Other/VersionComparer.swift b/LookInside/Other/VersionComparer.swift index 0c65d9af..db83fd97 100644 --- a/LookInside/Other/VersionComparer.swift +++ b/LookInside/Other/VersionComparer.swift @@ -9,7 +9,6 @@ import Foundation import LookInsideHostCore -@objc(LKVersionComparer) final class VersionComparer: NSObject { /// latest 指网上最高的 LookinServer 版本号,user 指用户真实的版本号。如果用户版本号低于最高版本号,则该方法返回 NO,此时应该提示用户升级。 @objc(compareWithNewest:user:) diff --git a/LookInside/Preference/PreferenceView.swift b/LookInside/Preference/PreferenceView.swift index 9d760a47..5daf5d61 100644 --- a/LookInside/Preference/PreferenceView.swift +++ b/LookInside/Preference/PreferenceView.swift @@ -1,7 +1,6 @@ import AppKit import SwiftUI -@objc(LKPreferenceHostingController) public final class PreferenceHostingController: NSViewController { override public func loadView() { view = NSHostingView(rootView: PreferenceRootView()) diff --git a/LookInside/Preference/PreferenceWindowController.swift b/LookInside/Preference/PreferenceWindowController.swift index cc8253bb..cd33ca53 100644 --- a/LookInside/Preference/PreferenceWindowController.swift +++ b/LookInside/Preference/PreferenceWindowController.swift @@ -8,7 +8,6 @@ import AppKit -@objc(LKPreferenceWindowController) final class PreferenceWindowController: WindowController { @objc init() { #if DEBUG @@ -36,7 +35,6 @@ final class PreferenceWindowController: WindowController { } } -@objc(LKPreferenceViewController) final class PreferenceViewController: BaseViewController { init() { super.init(containerView: nil) diff --git a/LookInside/PrivateDiscriminator/PrivateDiscriminatorSettingsWindowController.swift b/LookInside/PrivateDiscriminator/PrivateDiscriminatorSettingsWindowController.swift index 871d9fdc..7de0cd97 100644 --- a/LookInside/PrivateDiscriminator/PrivateDiscriminatorSettingsWindowController.swift +++ b/LookInside/PrivateDiscriminator/PrivateDiscriminatorSettingsWindowController.swift @@ -1,7 +1,6 @@ import AppKit import SwiftUI -@objc(LKPrivateDiscriminatorSettingsWindowController) final class PrivateDiscriminatorSettingsWindowController: NSWindowController { private static let sharedController = PrivateDiscriminatorSettingsWindowController() diff --git a/LookInside/PrivateDiscriminator/PrivateDiscriminatorStore.swift b/LookInside/PrivateDiscriminator/PrivateDiscriminatorStore.swift index 56f6cf41..b344c357 100644 --- a/LookInside/PrivateDiscriminator/PrivateDiscriminatorStore.swift +++ b/LookInside/PrivateDiscriminator/PrivateDiscriminatorStore.swift @@ -62,7 +62,6 @@ struct PrivateDiscriminatorInvalidDiagnostic: Identifiable, Hashable { /// The private-discriminator indexes and settings. The settings window /// observes the state below through Observation. -@objc(LKPrivateDiscriminatorStore) @Observable final class PrivateDiscriminatorStore: NSObject { @objc(shared) static let shared = PrivateDiscriminatorStore() @@ -1384,7 +1383,6 @@ private enum GuessState { } } -@objc(LKPrivateDiscriminatorDashboardPayload) final class PrivateDiscriminatorDashboardPayload: NSObject { @objc let discriminatorID: String @objc let module: String diff --git a/LookInside/Read/ReadHierarchyController.swift b/LookInside/Read/ReadHierarchyController.swift index 1e206cd7..e0f29ae2 100644 --- a/LookInside/Read/ReadHierarchyController.swift +++ b/LookInside/Read/ReadHierarchyController.swift @@ -10,18 +10,15 @@ import AppKit /// The reader's hierarchy list. Hiding or showing an item's preview only /// changes the in-memory tree; there is no app to tell. -@objc(LKReadHierarchyController) final class ReadHierarchyController: HierarchyController { - @objc(hierarchyView:needToCancelPreviewOfItem:) - func hierarchyView(_: HierarchyView?, needToCancelPreviewOf item: DisplayItem?) { - item?.noPreview = true + override func hierarchyView(_: HierarchyView, needToCancelPreviewOf item: DisplayItem) { + item.noPreview = true notifyNoPreviewDidChange() } - @objc(hierarchyView:needToShowPreviewOfItem:) - func hierarchyView(_: HierarchyView?, needToShowPreviewOf item: DisplayItem?) { + override func hierarchyView(_: HierarchyView, needToShowPreviewOf item: DisplayItem) { // A preview shows only when none of its ancestors hides theirs. - item?.enumerateSelfAndAncestors { item, _ in + item.enumerateSelfAndAncestors { item, _ in if item.noPreview { item.noPreview = false } diff --git a/LookInside/Read/ReadHierarchyDataSource.swift b/LookInside/Read/ReadHierarchyDataSource.swift index b0730326..40c6ce18 100644 --- a/LookInside/Read/ReadHierarchyDataSource.swift +++ b/LookInside/Read/ReadHierarchyDataSource.swift @@ -11,7 +11,6 @@ import AppKit /// The hierarchy of a `.lookin` file: the tree the file holds, with the /// stored screenshots put back on the items. It uses the reader window's own /// preference set. -@objc(LKReadHierarchyDataSource) final class ReadHierarchyDataSource: HierarchyDataSource { private let readPreferenceManager: PreferenceManager diff --git a/LookInside/Read/ReadViewController.swift b/LookInside/Read/ReadViewController.swift index 5975fddd..b95b0c07 100644 --- a/LookInside/Read/ReadViewController.swift +++ b/LookInside/Read/ReadViewController.swift @@ -11,7 +11,6 @@ import AppKit /// The reader window's content: the hierarchy list on the left; the /// preview, the dashboard or the measure panel on the right; and a tip /// while the tree is in focus mode. -@objc(LKReadViewController) final class ReadViewController: BaseViewController, NSSplitViewDelegate { @objc let hierarchyDataSource: ReadHierarchyDataSource diff --git a/LookInside/Read/ReadWindowController.swift b/LookInside/Read/ReadWindowController.swift index e34a00b8..0faf461a 100644 --- a/LookInside/Read/ReadWindowController.swift +++ b/LookInside/Read/ReadWindowController.swift @@ -14,7 +14,6 @@ import AppKit /// `NavigationManager.showReaderWithHierarchyFile:title:` wraps in-memory /// hierarchies in an untitled document, and archives on disk open through /// `NSDocumentController.openDocumentWithContentsOfURL:`. -@objc(LKReadWindowController) final class ReadWindowController: WindowController, NSToolbarDelegate { /// This window's own preference set: the reader's view settings, including /// the show-backing-layers toggle, are per document window. A document that diff --git a/LookInside/Static/MessageManager.swift b/LookInside/Static/MessageManager.swift index 4361348c..2933a329 100644 --- a/LookInside/Static/MessageManager.swift +++ b/LookInside/Static/MessageManager.swift @@ -11,7 +11,6 @@ import Foundation /// The notices the inspector window shows under its toolbar message /// button. Identifiers are `jobsMessageIdentifier` and `swiftSubspecMessageIdentifier` /// (StaticConstants.swift). -@objc(LKMessageManager) final class MessageManager: NSObject { /// Set once the jobs notice was dismissed. private static let hasReadJobsDefaultsKey = "LKMessageManager_HasReadJobs" diff --git a/LookInside/Static/Preview/DisplayItemNode.swift b/LookInside/Static/Preview/DisplayItemNode.swift index b9fd2a3b..0cd7fa40 100644 --- a/LookInside/Static/Preview/DisplayItemNode.swift +++ b/LookInside/Static/Preview/DisplayItemNode.swift @@ -11,7 +11,6 @@ import SceneKit /// One item's plane in the 3D preview: the screenshot (or background /// colour), a tint mask for hover and selection, and an outline. -@objc(LKDisplayItemNode) final class DisplayItemNode: SCNNode, DisplayItemDelegate { /// Rendering order added to a coplanar overlay node's border so it draws /// after every ordinary node. Paired with a depth-test-free material, diff --git a/LookInside/Static/Preview/PreviewController.swift b/LookInside/Static/Preview/PreviewController.swift index c24fe7c5..87f18dcf 100644 --- a/LookInside/Static/Preview/PreviewController.swift +++ b/LookInside/Static/Preview/PreviewController.swift @@ -10,7 +10,6 @@ import AppKit /// Hosts the 3D preview and turns mouse, trackpad and keyboard input into /// rotation, translation, zoom, selection and the context menu. -@objc(LKPreviewController) final class PreviewController: BaseViewController, NSGestureRecognizerDelegate, NSMenuDelegate, PreviewStageViewDelegate { @objc weak var staticViewController: StaticViewController? diff --git a/LookInside/Static/Preview/PreviewStageView.swift b/LookInside/Static/Preview/PreviewStageView.swift index d08e67a4..cd29369e 100644 --- a/LookInside/Static/Preview/PreviewStageView.swift +++ b/LookInside/Static/Preview/PreviewStageView.swift @@ -16,7 +16,6 @@ protocol PreviewStageViewDelegate: AnyObject { /// The preview controller's root view: reports mouse moves anywhere over it /// and lets the delegate add cursor rects. -@objc(LKPreviewStageView) final class PreviewStageView: BaseView { weak var delegate: PreviewStageViewDelegate? @@ -46,7 +45,6 @@ final class PreviewStageView: BaseView { /// The preview's pan gesture: rotates the preview, or moves it while space /// is held. -@objc(LKPreviewPanGestureRecognizer) final class PreviewPanGestureRecognizer: NSPanGestureRecognizer { enum Purpose { case rotate diff --git a/LookInside/Static/Preview/PreviewView.swift b/LookInside/Static/Preview/PreviewView.swift index 2d38bd5c..1e2e45e8 100644 --- a/LookInside/Static/Preview/PreviewView.swift +++ b/LookInside/Static/Preview/PreviewView.swift @@ -13,10 +13,11 @@ import AppKit import LookInsideHostCore import SceneKit +import FoundationToolbox /// The 3D (or flat) preview of the hierarchy: one DisplayItemNode per /// item, stacked along the z axis. -@objc(LKPreviewView) +@Loggable(subsystem: "com.lookinside.app") final class PreviewView: SCNView { private let dataSource: HierarchyDataSource? @@ -185,7 +186,7 @@ final class PreviewView: SCNView { /// use are dropped; otherwise they are only removed from the scene and /// kept for later renders. func render(displayItems items: [DisplayItem], discardCache: Bool) { - NSLog("LKPreviewView - render %@ items", NSNumber(value: items.count)) + #log(.default, "LKPreviewView - render \(NSNumber(value: items.count), privacy: .public) items") flatDisplayItems = items diff --git a/LookInside/Static/StaticAsyncUpdateManager.swift b/LookInside/Static/StaticAsyncUpdateManager.swift index 7b74bf65..85a466bd 100644 --- a/LookInside/Static/StaticAsyncUpdateManager.swift +++ b/LookInside/Static/StaticAsyncUpdateManager.swift @@ -8,15 +8,13 @@ import AppKit import LookInsideHostCore +import FoundationToolbox -@objc(LKStaticAsyncUpdateManagerDelegate) -protocol StaticAsyncUpdateManagerDelegate: NSObjectProtocol { +protocol StaticAsyncUpdateManagerDelegate: AnyObject { /// Called whenever the number of unfinished tasks changes: `totalCount` /// tasks in all, `finishedCount` of them done. - @objc(detailUpdateTasksTotalCount:finishedCount:) func detailUpdateTasksTotalCount(_ totalCount: UInt, finishedCount: UInt) - @objc(detailUpdateReceivedError:) func detailUpdateReceivedError(_ error: Error) } @@ -29,7 +27,7 @@ enum ModifyingUpdateEvent { /// Fetches the details (screenshots, attributes, sub items) of the items in /// one inspector window's hierarchy from the inspected app. -@objc(LKStaticAsyncUpdateManager) +@Loggable(subsystem: "com.lookinside.app") @MainActor final class StaticAsyncUpdateManager: NSObject { /// Set by the owner (window controller / live document), which holds it @@ -40,7 +38,7 @@ final class StaticAsyncUpdateManager: NSObject { /// hierarchy arrives or the document reconnects. @objc weak var inspectableApp: InspectableApp? - @objc weak var delegate: StaticAsyncUpdateManagerDelegate? + weak var delegate: StaticAsyncUpdateManagerDelegate? /// Events of `updateAfterModifyingDisplayItem(_:)`. let modifyingUpdates = AsyncBroadcaster() @@ -99,7 +97,7 @@ final class StaticAsyncUpdateManager: NSObject { /// Stops the running fetch. @objc func endUpdating() { guard ongoingRequest != nil else { return } - NSLog("AsyncUpdate - endUpdating") + #log(.default, "AsyncUpdate - endUpdating") // Completes the running details request synchronously, which runs // its completion below and notifies the delegate. inspectableApp?.cancelHierarchyDetailFetching() @@ -387,7 +385,7 @@ final class StaticAsyncUpdateManager: NSObject { ongoingRequest = request notifyTasksCountToDelegate() - NSLog("AsyncUpdate - Will send %@ tasks.", NSNumber(value: newTasks.count)) + #log(.default, "AsyncUpdate - Will send \(NSNumber(value: newTasks.count), privacy: .public) tasks.") startRequest(app: app, type: LookinRequestTypeHierarchyDetails, tasks: packages as NSArray) { [weak self] event in guard let self else { return } @@ -425,17 +423,7 @@ final class StaticAsyncUpdateManager: NSObject { let viewAddress: String = failedItem?.viewObject?.memoryAddress ?? "-" let layerClass: String = failedItem?.layerObject?.rawClassName() ?? "-" let layerAddress: String = failedItem?.layerObject?.memoryAddress ?? "-" - NSLog( - "AsyncUpdate - task %@: oid %lu, item %@ (nodeKind %ld, view %@ %@, layer %@ %@)", - outcome as NSString, - detail.displayItemOid, - title as NSString, - nodeKind, - viewClass as NSString, - viewAddress as NSString, - layerClass as NSString, - layerAddress as NSString - ) + #log(.default, "AsyncUpdate - task \(outcome as NSString, privacy: .public): oid \(detail.displayItemOid, privacy: .public), item \(title as NSString, privacy: .public) (nodeKind \(nodeKind, privacy: .public), view \(viewClass as NSString, privacy: .public) \(viewAddress as NSString, privacy: .public), layer \(layerClass as NSString, privacy: .public) \(layerAddress as NSString, privacy: .public))") } else { dataSource?.modify(with: detail) } @@ -496,7 +484,7 @@ final class StaticAsyncUpdateManager: NSObject { private func notifyTasksCountToDelegate() { let totalCount = ongoingRequest?.tasksTotalCount ?? 0 let finishedCount = ongoingRequest?.finishedTasksCount ?? 0 - NSLog("AsyncUpdate - notify delagate: %@/%@", NSNumber(value: finishedCount), NSNumber(value: totalCount)) + #log(.default, "AsyncUpdate - notify delagate: \(NSNumber(value: finishedCount), privacy: .public)/\(NSNumber(value: totalCount), privacy: .public)") delegate?.detailUpdateTasksTotalCount(UInt(totalCount), finishedCount: UInt(max(finishedCount, 0))) } } diff --git a/LookInside/Static/StaticHierarchyController.swift b/LookInside/Static/StaticHierarchyController.swift index 7d550510..c2352954 100644 --- a/LookInside/Static/StaticHierarchyController.swift +++ b/LookInside/Static/StaticHierarchyController.swift @@ -9,18 +9,15 @@ import AppKit /// The hierarchy tree of a live inspector window. -@objc(LKStaticHierarchyController) final class StaticHierarchyController: HierarchyController { // MARK: - HierarchyViewDelegate - @objc(hierarchyView:needToCancelPreviewOfItem:) - func hierarchyView(_: HierarchyView, needToCancelPreviewOf item: DisplayItem) { + override func hierarchyView(_: HierarchyView, needToCancelPreviewOf item: DisplayItem) { item.noPreview = true dataSource.itemDidChangeNoPreview.send() } - @objc(hierarchyView:needToShowPreviewOfItem:) - func hierarchyView(_: HierarchyView, needToShowPreviewOf item: DisplayItem) { + override func hierarchyView(_: HierarchyView, needToShowPreviewOf item: DisplayItem) { item.enumerateSelfAndAncestors { item, _ in if item.noPreview { item.noPreview = false diff --git a/LookInside/Static/StaticHierarchyDataSource.swift b/LookInside/Static/StaticHierarchyDataSource.swift index 5315d676..440f8cf6 100644 --- a/LookInside/Static/StaticHierarchyDataSource.swift +++ b/LookInside/Static/StaticHierarchyDataSource.swift @@ -10,7 +10,6 @@ import AppKit /// The data source of a live document: applies the details the update /// tasks deliver and starts those tasks. -@objc(LKStaticHierarchyDataSource) class StaticHierarchyDataSource: HierarchyDataSource { @objc var appInfo: InspectedAppInfo? { storedAppInfo diff --git a/LookInside/Static/StaticViewController.swift b/LookInside/Static/StaticViewController.swift index 83f536e8..a01c37c4 100644 --- a/LookInside/Static/StaticViewController.swift +++ b/LookInside/Static/StaticViewController.swift @@ -11,7 +11,6 @@ import AppKit /// The content of a live inspector window: the hierarchy tree on the left; /// on the right the preview with the dashboard (or measure panel) over it, /// and the console under them; tips float above the preview. -@objc(LKStaticViewController) final class StaticViewController: BaseViewController, NSSplitViewDelegate { /// Set when the fast mode tip is dismissed for good. private static let ignoreFastModeTipsDefaultsKey = "IgnoreFastModeTips" diff --git a/LookInside/Static/StaticWindowController.swift b/LookInside/Static/StaticWindowController.swift index 0a6af7ff..368c7722 100644 --- a/LookInside/Static/StaticWindowController.swift +++ b/LookInside/Static/StaticWindowController.swift @@ -14,8 +14,9 @@ import AppKit import LookInsideHostCore import UniformTypeIdentifiers +import FoundationToolbox -@objc(LKStaticWindowController) +@Loggable(subsystem: "com.lookinside.app") @MainActor final class StaticWindowController: WindowController, NSToolbarDelegate, @preconcurrency StaticAsyncUpdateManagerDelegate { /// Who asked for a hierarchy reload. Recorded when a reload actually @@ -744,7 +745,7 @@ final class StaticWindowController: WindowController, NSToolbarDelegate, @precon do { try exportedData.write(to: url) } catch { - NSLog("LookinClient - write fail:%@", error as NSError) + #log(.default, "LookinClient - write fail:\(error as NSError, privacy: .public)") } } } diff --git a/LookInside/SwiftUISupport/SwiftUIHierarchyDisplayMode.swift b/LookInside/SwiftUISupport/SwiftUIHierarchyDisplayMode.swift index e5f81278..3c17d54c 100644 --- a/LookInside/SwiftUISupport/SwiftUIHierarchyDisplayMode.swift +++ b/LookInside/SwiftUISupport/SwiftUIHierarchyDisplayMode.swift @@ -17,7 +17,6 @@ extension Notification.Name { static let swiftUIHierarchyDisplayModeDidChange = Notification.Name("LKSwiftUIHierarchyDisplayModeDidChangeNotification") } -@objc(LKSwiftUIHierarchyDisplayModeStore) final class SwiftUIHierarchyDisplayModeStore: NSObject { private static let defaultsKey = "LookInside.SwiftUIHierarchyDisplayMode" diff --git a/LookInside/SwiftUISupport/SwiftUISupportGatekeeper.swift b/LookInside/SwiftUISupport/SwiftUISupportGatekeeper.swift index 7ab4d79c..58c6d978 100644 --- a/LookInside/SwiftUISupport/SwiftUISupportGatekeeper.swift +++ b/LookInside/SwiftUISupport/SwiftUISupportGatekeeper.swift @@ -2,6 +2,7 @@ import AppKit import Foundation import LookInsideActivation import LookInsideActivationUI +import FoundationToolbox @objc public enum SwiftUISupportActivationState: Int, CustomDebugStringConvertible { case unknown @@ -38,7 +39,7 @@ private enum SwiftUISupportGatekeeperConstants { /// connection, menu, launch and static-update code call it unchanged. The /// runtime reads and writes the helper's `state.json` and keychain key; this /// class never launches, updates or removes the helper. -@objcMembers +@Loggable(subsystem: "com.lookinside.app", category: "Activation") public final class SwiftUISupportGatekeeper: NSObject { private static let shared = SwiftUISupportGatekeeper(runtime: ActivationRuntime()) @@ -96,7 +97,7 @@ public final class SwiftUISupportGatekeeper: NSObject { publishedStatusSummary = initialDecision?.statusSummary presentsKeychainExplainer = monitorsState super.init() - SwiftUISupportLogger.activation.info( + #log(.info, // Logger interpolations are escaping autoclosures. // swiftformat:disable:next redundantSelf "activation runtime ready, state=\(self.publishedState.debugDescription, privacy: .public)" @@ -155,7 +156,7 @@ public final class SwiftUISupportGatekeeper: NSObject { return handshakeGeneration != status.handshakeGeneration } guard shouldNotify else { return } - SwiftUISupportLogger.activation.info( + #log(.info, "license handshakes may start again (generation \(status.handshakeGeneration, privacy: .public))" ) DispatchQueue.main.async { @@ -173,7 +174,7 @@ public final class SwiftUISupportGatekeeper: NSObject { onMain { coordinator in guard runtime.signingStatus.needsKeychainAccessExplainer else { return } let window = NSApp.mainWindow ?? NSApp.keyWindow ?? NSApp.windows.first { $0.isVisible } - SwiftUISupportLogger.activation.info("showing the keychain access explainer") + #log(.info, "showing the keychain access explainer") coordinator.showKeychainAccessExplainer(over: window) } } @@ -225,7 +226,7 @@ public final class SwiftUISupportGatekeeper: NSObject { return true } guard shouldNotify else { return } - SwiftUISupportLogger.activation.info( + #log(.info, "activation state changed: \(previousState.debugDescription, privacy: .public) -> \(newState.debugDescription, privacy: .public) (decision=\(decision.decision.rawValue, privacy: .public))" ) DispatchQueue.main.async { @@ -384,7 +385,7 @@ public final class SwiftUISupportGatekeeper: NSObject { result = measured.signature keyUseDurationOut?.pointee = measured.keyUseDuration } catch let error as ActivationError { - SwiftUISupportLogger.activation.error( + #log(.error, "sign_challenge failed code=\(error.errorCode, privacy: .public)" ) throw error @@ -440,7 +441,7 @@ public final class SwiftUISupportGatekeeper: NSObject { ActivationAlert(title: decision.title, message: decision.message, style: .warning) ) } catch { - SwiftUISupportLogger.activation.error( + #log(.error, "license status refresh failed: \(error.localizedDescription, privacy: .public)" ) coordinator.showAlert( @@ -528,8 +529,7 @@ public final class SwiftUISupportGatekeeper: NSObject { } private func isInspectorWindow(_ window: NSWindow?) -> Bool { - guard let wc = window?.windowController else { return false } - return NSStringFromClass(type(of: wc)) == "LKStaticWindowController" + window?.windowController is StaticWindowController } /// Shown as a sheet on the inspector window that triggered it. As in @@ -540,7 +540,7 @@ public final class SwiftUISupportGatekeeper: NSObject { let runtime = runtime Task { [weak self, weak window] in guard await runtime.hasLicenseMaterial() else { - SwiftUISupportLogger.activation.info( + #log(.info, "activation prompt skipped: no local license material" ) return diff --git a/LookInside/SwiftUISupport/SwiftUISupportLogger.swift b/LookInside/SwiftUISupport/SwiftUISupportLogger.swift deleted file mode 100644 index 9139960b..00000000 --- a/LookInside/SwiftUISupport/SwiftUISupportLogger.swift +++ /dev/null @@ -1,8 +0,0 @@ -import Foundation -import os - -enum SwiftUISupportLogger { - static let activation = Logger(subsystem: subsystem, category: "Activation") - - private static let subsystem = "com.lookinside.app" -} diff --git a/LookInside/Toolbar/MenuPopoverAppsListController.swift b/LookInside/Toolbar/MenuPopoverAppsListController.swift index 74b3669e..7e3d5e8c 100644 --- a/LookInside/Toolbar/MenuPopoverAppsListController.swift +++ b/LookInside/Toolbar/MenuPopoverAppsListController.swift @@ -10,7 +10,6 @@ import AppKit /// The popover that lists the inspectable apps, opened from the app button, /// the reload button or the connection-lost tips. -@objc(LKMenuPopoverAppsListController) final class MenuPopoverAppsListController: BaseViewController { private let insets = NSEdgeInsets(top: 9, left: 18, bottom: 35, right: 14) private let titleMarginBottom: CGFloat = 3 diff --git a/LookInside/Toolbar/MenuPopoverSettingController.swift b/LookInside/Toolbar/MenuPopoverSettingController.swift index 54ad4daa..cf38032b 100644 --- a/LookInside/Toolbar/MenuPopoverSettingController.swift +++ b/LookInside/Toolbar/MenuPopoverSettingController.swift @@ -11,7 +11,6 @@ import AppKit /// The View popover of a window toolbar: outline, hidden items, system /// layout guides, backing layers, item separation, and a way to the /// preferences. -@objc(LKMenuPopoverSettingController) final class MenuPopoverSettingController: BaseViewController { private let manager: PreferenceManager diff --git a/LookInside/Toolbar/WindowToolbarAppButton.swift b/LookInside/Toolbar/WindowToolbarAppButton.swift index 3f6d98c3..82184782 100644 --- a/LookInside/Toolbar/WindowToolbarAppButton.swift +++ b/LookInside/Toolbar/WindowToolbarAppButton.swift @@ -11,7 +11,6 @@ import AppKit /// The toolbar button that names the inspected app and its device: app /// icon, app name, a chevron, device icon, device and OS. Without an app it /// shows a plain app icon. -@objc(LKWindowToolbarAppButton) final class WindowToolbarAppButton: NSButton { private let appImageView = NSImageView() private let appNameLabel = TextLabel() diff --git a/LookInside/Toolbar/WindowToolbarHelper.swift b/LookInside/Toolbar/WindowToolbarHelper.swift index 41c57669..6e347975 100644 --- a/LookInside/Toolbar/WindowToolbarHelper.swift +++ b/LookInside/Toolbar/WindowToolbarHelper.swift @@ -13,7 +13,6 @@ import AppKit /// The items for dimension, rotation, scale, measure and fast mode follow a /// preference manager both ways. The window sets the click action of the /// others itself: Reload, App, Setting, Console, Add, Remove and Message. -@objc(LKWindowToolbarHelper) @MainActor final class WindowToolbarHelper: NSObject { @objc(sharedInstance)