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
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,8 @@ class AccessibilityNotificationsManager: ObservableObject {

static let shared = AccessibilityNotificationsManager()

// MARK: - ScreenResult

struct ScreenResult {
struct UserInteractions {
var selectedText: String?
var input: String?
}

var elapsedTime: String?
var applicationName: String?
var applicationTitle: String?
var userInteraction: UserInteractions = .init()
var others: [String: String]?
var errorMessage: String? // Renamed field for error message
var errorCode: Int32?
var appBundleUrl: URL?
}

// MARK: - Properties

@Published var screenResult: ScreenResult = .init()

let windowsManager = AccessibilityWindowsManager()

private let highlightedTextCoordinator = HighlightedTextCoordinator()
Expand All @@ -54,6 +34,9 @@ class AccessibilityNotificationsManager: ObservableObject {
private var valueDebounceWorkItem: DispatchWorkItem?
private var selectionDebounceWorkItem: DispatchWorkItem?
private var parseDebounceWorkItem: DispatchWorkItem?

// Published property for selected text that QuickEditManager can observe
@Published var selectedText: String?

// MARK: - Private initializer

Expand Down Expand Up @@ -124,7 +107,6 @@ class AccessibilityNotificationsManager: ObservableObject {

func reset() {
windowsManager.reset()
screenResult = .init()

Task.detached {
await self.highlightedTextCoordinator.reset()
Expand All @@ -137,6 +119,8 @@ class AccessibilityNotificationsManager: ObservableObject {
selectionDebounceWorkItem?.cancel()
parseDebounceWorkItem?.cancel()

selectedText = nil

ContextFetchingService.shared.reset()
}

Expand Down Expand Up @@ -318,12 +302,10 @@ class AccessibilityNotificationsManager: ObservableObject {
dispatchPrecondition(condition: .onQueue(.main))

guard let value = element.value() else {
screenResult.userInteraction.input = nil
showDebug()
return
}

screenResult.userInteraction.input = value
showDebug()
}

Expand Down Expand Up @@ -365,14 +347,15 @@ class AccessibilityNotificationsManager: ObservableObject {
let selectedText = text,
HighlightedTextValidator.isValid(text: selectedText) else {

screenResult.userInteraction.selectedText = nil
PanelStateCoordinator.shared.state.pendingInput = nil
PanelStateCoordinator.shared.state.trackedPendingInput = nil
self.selectedText = nil
return
}

screenResult.userInteraction.selectedText = selectedText

// Update the published selectedText property
self.selectedText = selectedText

let input = Input(selectedText: selectedText, application: currentSource ?? "")

if Defaults[.autoAddHighlightedTextToContext] {
Expand All @@ -397,42 +380,8 @@ class AccessibilityNotificationsManager: ObservableObject {
// MARK: Debug

private func showDebug() {
var debugText = """
===== Debug Information =====

Elapsed Time: \(screenResult.elapsedTime ?? "N/A")

Application Name: \(screenResult.applicationName ?? "N/A")

Application Title: \(screenResult.applicationTitle ?? "N/A")

Selected Text: \(screenResult.userInteraction.selectedText ?? "N/A")

User Input: \(screenResult.userInteraction.input ?? "N/A")

Error Message: \(screenResult.errorMessage ?? "N/A")

=============================

"""

if let results = screenResult.others {
debugText += "\n======== Additional Data ========\n"
for result in results.sorted(by: { $0.key < $1.key }) {
debugText += """

---------------------------------
Key: \(result.key)
---------------------------------
\(result.value)
"""
}
debugText += "\n=================================\n"
} else {
debugText += "\nNo additional data available.\n"
}

DebugManager.shared.debugText = debugText
// Debug information is now handled by ContextFetchingService
DebugManager.shared.debugText = "Debug information moved to ContextFetchingService"
}
}

Expand Down
71 changes: 36 additions & 35 deletions macos/Onit/Context/ContextFetchingService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -101,16 +101,17 @@ class ContextFetchingService {
errorCode = 1500
}

// Update screenResult with error information
AccessibilityNotificationsManager.shared.screenResult.applicationName = appName
AccessibilityNotificationsManager.shared.screenResult.applicationTitle = appTitle
AccessibilityNotificationsManager.shared.screenResult.errorMessage = errorMessage
AccessibilityNotificationsManager.shared.screenResult.errorCode = errorCode
AccessibilityNotificationsManager.shared.screenResult.appBundleUrl = appBundleUrl
AccessibilityNotificationsManager.shared.screenResult.others = nil
// Create ScreenResult with error information
let screenResult = ScreenResult(
applicationName: appName,
applicationTitle: appTitle,
errorMessage: errorMessage,
errorCode: errorCode,
appBundleUrl: appBundleUrl
)

// Call addAutoContext to handle the error case
state.addAutoContext(trackedWindow: trackedWindow)
state.addAutoContext(trackedWindow: trackedWindow, screenResult: screenResult)
}
} else {
// This creates an error state for when google drive is not authorized
Expand All @@ -122,16 +123,17 @@ class ContextFetchingService {
}
}

// Update screenResult with unauthorized error
AccessibilityNotificationsManager.shared.screenResult.applicationName = appName
AccessibilityNotificationsManager.shared.screenResult.applicationTitle = appTitle
AccessibilityNotificationsManager.shared.screenResult.errorMessage = "Google Drive Plugin Required"
AccessibilityNotificationsManager.shared.screenResult.errorCode = 1500
AccessibilityNotificationsManager.shared.screenResult.appBundleUrl = appBundleUrl
AccessibilityNotificationsManager.shared.screenResult.others = nil
// Create ScreenResult with unauthorized error
let screenResult = ScreenResult(
applicationName: appName,
applicationTitle: appTitle,
errorMessage: "Google Drive Plugin Required",
errorCode: 1500,
appBundleUrl: appBundleUrl
)

// Call addAutoContext to handle the error case
state.addAutoContext(trackedWindow: trackedWindow)
state.addAutoContext(trackedWindow: trackedWindow, screenResult: screenResult)
}
} else {
parseAccessibility(
Expand Down Expand Up @@ -263,16 +265,16 @@ class ContextFetchingService {
self.timedOutWindowHash.insert(windowHash)
AnalyticsManager.Accessibility.parseTimedOut(appName: appName)

// Update screenResult with timeout error
AccessibilityNotificationsManager.shared.screenResult.applicationName = appName
AccessibilityNotificationsManager.shared.screenResult.applicationTitle = ""
AccessibilityNotificationsManager.shared.screenResult.errorMessage = "Timeout occurred, could not read application in reasonable amount of time."
AccessibilityNotificationsManager.shared.screenResult.errorCode = 1500
AccessibilityNotificationsManager.shared.screenResult.appBundleUrl = nil
AccessibilityNotificationsManager.shared.screenResult.others = nil
// Create ScreenResult with timeout error
let screenResult = ScreenResult(
applicationName: appName,
applicationTitle: "",
errorMessage: "Timeout occurred, could not read application in reasonable amount of time.",
errorCode: 1500
)

// Call addAutoContext to handle the error case
state.addAutoContext(trackedWindow: trackedWindow)
state.addAutoContext(trackedWindow: trackedWindow, screenResult: screenResult)
}
}
}
Expand All @@ -296,16 +298,16 @@ class ContextFetchingService {
let appName = results?[AccessibilityParsedElements.applicationName] ?? ""
let appTitle = results?[AccessibilityParsedElements.applicationTitle] ?? ""

// Update screenResult with the parsed content
AccessibilityNotificationsManager.shared.screenResult.applicationName = appName
AccessibilityNotificationsManager.shared.screenResult.applicationTitle = appTitle
AccessibilityNotificationsManager.shared.screenResult.errorMessage = nil
AccessibilityNotificationsManager.shared.screenResult.errorCode = nil
AccessibilityNotificationsManager.shared.screenResult.appBundleUrl = appBundleUrl
AccessibilityNotificationsManager.shared.screenResult.others = results
// Create ScreenResult object
let screenResult = ScreenResult(
applicationName: appName,
applicationTitle: appTitle,
others: results,
appBundleUrl: appBundleUrl
)

// Call addAutoContext to handle the context creation and cleanup
state.addAutoContext(trackedWindow: trackedWindow)
state.addAutoContext(trackedWindow: trackedWindow, screenResult: screenResult)
}

func reset() {
Expand All @@ -317,8 +319,7 @@ class ContextFetchingService {
// MARK: - Debug

private func showDebug() {
// This method is called to update debug information
// Since we're no longer using screenResult, we'll just clear the debug text
DebugManager.shared.debugText = "Context fetching moved to ContextFetchingService"
// Debug information is now handled by individual ScreenResult objects
DebugManager.shared.debugText = "Context fetching using ScreenResult objects"
}
}
44 changes: 44 additions & 0 deletions macos/Onit/Data/Structures/ScreenResult.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// ScreenResult.swift
// Onit
//
// Created by Kévin Naudin on 22/01/2025.
//

import Foundation

struct ScreenResult {
struct UserInteractions {
var selectedText: String?
var input: String?
}
Comment thread
timlenardo marked this conversation as resolved.

var elapsedTime: String?
var applicationName: String?
var applicationTitle: String?
var userInteraction: UserInteractions = .init()
var others: [String: String]?
var errorMessage: String? // Renamed field for error message
Comment thread
Niduank marked this conversation as resolved.
var errorCode: Int32?
var appBundleUrl: URL?

init(
elapsedTime: String? = nil,
applicationName: String? = nil,
applicationTitle: String? = nil,
userInteraction: UserInteractions = UserInteractions(),
others: [String: String]? = nil,
errorMessage: String? = nil,
errorCode: Int32? = nil,
appBundleUrl: URL? = nil
) {
self.elapsedTime = elapsedTime
self.applicationName = applicationName
self.applicationTitle = applicationTitle
self.userInteraction = userInteraction
self.others = others
self.errorMessage = errorMessage
self.errorCode = errorCode
self.appBundleUrl = appBundleUrl
}
}
Comment thread
Niduank marked this conversation as resolved.
18 changes: 9 additions & 9 deletions macos/Onit/UI/Panels/State/OnitPanelState+Input.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,25 @@ import AppKit
import Defaults

extension OnitPanelState {
func addAutoContext(trackedWindow: TrackedWindow? = nil) {
func addAutoContext(trackedWindow: TrackedWindow? = nil, screenResult: ScreenResult? = nil) {
guard Defaults[.autoContextFromCurrentWindow] else { return }

let appName = AccessibilityNotificationsManager.shared.screenResult.applicationName ?? "AutoContext"
let appName = screenResult?.applicationName ?? "AutoContext"
let trackedWindowTitle = trackedWindow?.title
let trackedWindowHash = trackedWindow?.hash ?? 0 // This is all all horrible. There's no reason why we should be putting these things on the 'screenResult"
if let errorMessage = AccessibilityNotificationsManager.shared.screenResult.errorMessage {
let trackedWindowHash = trackedWindow?.hash ?? 0
if let errorMessage = screenResult?.errorMessage {
let errorContext = Context(
appName: appName,
appHash: trackedWindow?.hash ?? 0,
appTitle: trackedWindowTitle ?? "Unknown",
appContent: ["error": errorMessage, "errorCode" : String(AccessibilityNotificationsManager.shared.screenResult.errorCode ?? 0)],
appBundleUrl: AccessibilityNotificationsManager.shared.screenResult.appBundleUrl)
appContent: ["error": errorMessage, "errorCode" : String(screenResult?.errorCode ?? 0)],
appBundleUrl: screenResult?.appBundleUrl)
pendingContextList.insert(errorContext, at: 0)
cleanupWindowContextTask(uniqueWindowIdentifier: trackedWindowHash)
return
}

guard var appContent = AccessibilityNotificationsManager.shared.screenResult.others else {
guard var appContent = screenResult?.others else {
let errorContext = Context(appName: "Unable to add \(appName)", appHash: 0, appTitle: "", appContent: ["error": "Empty text"])
pendingContextList.insert(errorContext, at: 0)
cleanupWindowContextTask(uniqueWindowIdentifier: trackedWindowHash)
Expand Down Expand Up @@ -69,7 +69,7 @@ extension OnitPanelState {
appHash: appHash,
appTitle: appTitle,
appContent: appContent,
appBundleUrl: AccessibilityNotificationsManager.shared.screenResult.appBundleUrl,
appBundleUrl: screenResult?.appBundleUrl,
ocrMatchingPercentage: ocrMatchingPercentage
)
let newContext = Context.auto(autoContext)
Expand Down Expand Up @@ -106,7 +106,7 @@ extension OnitPanelState {
appHash: appHash,
appTitle: appTitle,
appContent: appContent,
appBundleUrl: AccessibilityNotificationsManager.shared.screenResult.appBundleUrl,
appBundleUrl: screenResult?.appBundleUrl,
ocrMatchingPercentage: ocrMatchingPercentage
)

Expand Down
6 changes: 3 additions & 3 deletions macos/Onit/UI/QuickEdit/QuickEditManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ class QuickEditManager: ObservableObject, CaretPositionDelegate {
}

private func setupTextSelectionMonitoring() {
accessibilityManager.$screenResult
.map(\.userInteraction.selectedText)
// Monitor the selectedText property from AccessibilityNotificationsManager
AccessibilityNotificationsManager.shared.$selectedText
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can use our accessibilityManager property here

.removeDuplicates()
.sink { [weak self] selectedText in
self?.handleTextSelectionChange(selectedText)
Expand Down Expand Up @@ -284,7 +284,7 @@ extension QuickEditManager {
}

func caretDidDisappear() {
if !hasTextSelection(accessibilityManager.screenResult.userInteraction.selectedText) {
if !hasTextSelection(PanelStateCoordinator.shared.state.pendingInput?.selectedText ?? PanelStateCoordinator.shared.state.trackedPendingInput?.selectedText) {
hideHint()
Comment thread
timlenardo marked this conversation as resolved.
}
}
Comment thread
timlenardo marked this conversation as resolved.
Expand Down