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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions Sources/ClickIt/Lite/LoggingConstants.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// LoggingConstants.swift
// ClickIt Lite
//
// Shared logging constants for consistent logging across the Lite module.
//

import Foundation

/// Shared logging constants to ensure consistency and prevent typos
enum LoggingConstants {
/// The subsystem identifier for all ClickIt Lite logging
static let subsystem = "com.jsonify.clickit.lite"
}
13 changes: 11 additions & 2 deletions Sources/ClickIt/Lite/SimpleClickEngine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,29 @@

import Foundation
import CoreGraphics
import os.log

/// Simple click engine for basic auto-clicking
@MainActor
final class SimpleClickEngine {

// MARK: - Types

enum ClickType {
enum ClickType: CustomStringConvertible {
case left
case right

var description: String {
switch self {
case .left: return "left"
case .right: return "right"
}
}
}

// MARK: - Properties

private let logger = Logger(subsystem: LoggingConstants.subsystem, category: "SimpleClickEngine")
private var isRunning = false
private var clickTask: Task<Void, Never>?
private var clickCount = 0
Expand Down Expand Up @@ -105,7 +114,7 @@ final class SimpleClickEngine {
}

// Debug logging
print("🖱️ Performing \(type) click at (\(Int(point.x)), \(Int(point.y)))")
logger.debug("🖱️ Performing \(type) click at (\(Int(point.x)), \(Int(point.y)))")

// Create and post mouse down event
if let mouseDown = CGEvent(
Expand Down
75 changes: 30 additions & 45 deletions Sources/ClickIt/Lite/SimpleCursorManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import AppKit
import SwiftUI
import os.log

class SimpleCursorManager {

Expand All @@ -16,6 +17,7 @@ class SimpleCursorManager {

// MARK: - Properties

private let logger = Logger(subsystem: LoggingConstants.subsystem, category: "SimpleCursorManager")
private var customCursor: NSCursor?
private var originalCursor: NSCursor?
private var cursorUpdateTimer: Timer?
Expand All @@ -32,14 +34,14 @@ class SimpleCursorManager {
/// Activates the custom target cursor system-wide
func activateCustomCursor() {
guard let customCursor = customCursor else {
print("❌ Custom cursor not available")
logger.error("❌ Custom cursor not available")
showDebugAlert("Cursor Failed", "Custom cursor could not be loaded. Check console for details.")
return
}

// Prevent double activation
if isCursorActive {
print("ℹ️ Custom cursor already active")
logger.info("ℹ️ Custom cursor already active")
return
}

Expand All @@ -58,7 +60,7 @@ class SimpleCursorManager {
self.customCursor?.set()
}

print("✅ Custom target cursor activated with continuous refresh")
logger.info("✅ Custom target cursor activated with continuous refresh")
// Optional: Uncomment to show success alert
// showDebugAlert("Cursor Active", "Custom target cursor has been activated")
}
Expand Down Expand Up @@ -86,81 +88,64 @@ class SimpleCursorManager {
// Restore arrow cursor
NSCursor.arrow.set()

print("✅ Default cursor restored")
logger.info("✅ Default cursor restored")
}

// MARK: - Private Methods

/// Finds the correct resource bundle for Swift Package Manager
private func findResourceBundle() -> Bundle {
// Strategy 1: Look for SPM resource bundle (swift run / debug builds)
if let bundleURL = Bundle.main.url(forResource: "ClickIt_ClickItLite", withExtension: "bundle"),
let resourceBundle = Bundle(url: bundleURL) {
print("✅ Found SPM resource bundle at: \(bundleURL.path)")
return resourceBundle
}

// Strategy 2: Look in Contents/Resources for packaged .app builds
if let resourcePath = Bundle.main.resourcePath,
let bundlePath = Bundle(path: resourcePath + "/ClickIt_ClickItLite.bundle") {
print("✅ Found resource bundle in app Resources: \(resourcePath)/ClickIt_ClickItLite.bundle")
return bundlePath
}

// Strategy 3: Try Module.bundle (for Xcode builds)
if let bundleURL = Bundle.main.url(forResource: "ClickItLite_ClickItLite", withExtension: "bundle"),
let resourceBundle = Bundle(url: bundleURL) {
print("✅ Found module resource bundle at: \(bundleURL.path)")
return resourceBundle
}

// Fallback to Bundle.main (resources might be directly in app bundle)
print("⚠️ Using Bundle.main as fallback")
return Bundle.main
// For Swift 5.3+, Swift Package Manager automatically synthesizes a `Bundle.module` static property
// for any target that includes resources. This is the modern and recommended way to access them.
return Bundle.module
}

private func setupCustomCursor() {
// Debug: Print bundle path
print("🔍 Bundle path: \(Bundle.main.bundlePath)")
print("🔍 Resource path: \(Bundle.main.resourcePath ?? "nil")")
// Define cursor properties at the top for easy modification
let cursorDimension: CGFloat = 64
let cursorImageName = "target-\(Int(cursorDimension))"

// Debug: Log bundle path
logger.debug("🔍 Bundle path: \(Bundle.main.bundlePath)")
logger.debug("🔍 Resource path: \(Bundle.main.resourcePath ?? "nil")")

// Find the correct resource bundle for Swift Package Manager
let bundle = findResourceBundle()
print("🔍 Using bundle: \(bundle.bundlePath)")
logger.debug("🔍 Using bundle: \(bundle.bundlePath)")

// Try to load the target image from resources
guard let imageURL = bundle.url(forResource: "target-64", withExtension: "png") else {
print("❌ Failed to find target-64.png in bundle")
print("🔍 Searched in: \(bundle.bundleURL)")
guard let imageURL = bundle.url(forResource: cursorImageName, withExtension: "png") else {
logger.error("❌ Failed to find \(cursorImageName).png in bundle")
logger.error("🔍 Searched in: \(bundle.bundleURL)")

// Try to list all resources
if let resourcePath = bundle.resourcePath {
do {
let items = try FileManager.default.contentsOfDirectory(atPath: resourcePath)
print("📁 Available resources in bundle: \(items)")
logger.debug("📁 Available resources in bundle: \(items)")
} catch {
print("❌ Could not list resources: \(error)")
logger.error("❌ Could not list resources: \(error)")
}
}
return
}

print("✅ Found image at: \(imageURL.path)")
logger.debug("✅ Found image at: \(imageURL.path)")

guard let image = NSImage(contentsOf: imageURL) else {
print("❌ Failed to load NSImage from: \(imageURL.path)")
logger.error("❌ Failed to load NSImage from: \(imageURL.path)")
return
}

print("✅ NSImage loaded, original size: \(image.size)")
logger.debug("✅ NSImage loaded, original size: \(String(describing: image.size))")

// Set the cursor size (64x64 pixels)
image.size = NSSize(width: 64, height: 64)
// Set the cursor size
image.size = NSSize(width: cursorDimension, height: cursorDimension)

// Create cursor with hotspot at center (32, 32)
let hotspot = NSPoint(x: 32, y: 32)
// Create cursor with hotspot at center
let hotspot = NSPoint(x: cursorDimension / 2, y: cursorDimension / 2)
customCursor = NSCursor(image: image, hotSpot: hotspot)

print("✅ Custom cursor created successfully")
logger.info("✅ Custom cursor created successfully")
}
}
Loading