From 1c0bada843ce24ffcdc40270e6dacedb71aa2258 Mon Sep 17 00:00:00 2001 From: kchro3 Date: Mon, 8 Jan 2024 14:22:41 -0800 Subject: [PATCH] still wip for improving accessibility --- Localizable.xcstrings | 18 +++++++++++++++ TypeaheadAI.xcodeproj/project.pbxproj | 8 +++++++ TypeaheadAI/Traits/CanGetUIElements.swift | 6 ++++- .../Views/Modal/ConversationView.swift | 2 ++ .../Views/Modal/Message/ChatBubble.swift | 23 ++++++++++++++++--- TypeaheadAI/Views/Modal/ModalView.swift | 6 +---- 6 files changed, 54 insertions(+), 9 deletions(-) diff --git a/Localizable.xcstrings b/Localizable.xcstrings index a6c6dc9..a742a02 100644 --- a/Localizable.xcstrings +++ b/Localizable.xcstrings @@ -297,6 +297,9 @@ } } } + }, + "Configure Quick Action" : { + }, "Confirm clearing history" : { "localizations" : { @@ -347,6 +350,9 @@ } } } + }, + "Create or edit a Quick Action" : { + }, "Date" : { "localizations" : { @@ -407,6 +413,12 @@ } } } + }, + "Edit message" : { + + }, + "Edit Typeahead's message" : { + }, "Edit your email by clicking the edit button next to the Typeahead response. Press **Enter** to save or **Shift-Enter** for a new line.\n\nAlternatively, you can type feedback like \"make it more concise\" or \"more casual,\" and it will provide a revised draft.\n\nIf you want it to remember detailed instructions for the future, you can click on the wrench icon to configure a Quick Action.\n\nClick continue when you're satisfied." : { "localizations" : { @@ -417,6 +429,9 @@ } } } + }, + "Edit your previous message" : { + }, "Email" : { "localizations" : { @@ -1095,6 +1110,9 @@ } } } + }, + "Retry" : { + }, "Sample Input" : { "localizations" : { diff --git a/TypeaheadAI.xcodeproj/project.pbxproj b/TypeaheadAI.xcodeproj/project.pbxproj index 7a6f9ab..27bd476 100644 --- a/TypeaheadAI.xcodeproj/project.pbxproj +++ b/TypeaheadAI.xcodeproj/project.pbxproj @@ -378,6 +378,13 @@ path = Onboarding; sourceTree = ""; }; + 2B79DFB42B4CA75A0038E577 /* New Group */ = { + isa = PBXGroup; + children = ( + ); + path = "New Group"; + sourceTree = ""; + }; 2B7BBABE2AF2B47900E4CE1F /* QuickActions */ = { isa = PBXGroup; children = ( @@ -539,6 +546,7 @@ isa = PBXGroup; children = ( 2B92BDBA2AA3D10800E65CFA /* ModalManager.swift */, + 2B79DFB42B4CA75A0038E577 /* New Group */, 2B92BDB82AA3A2DD00E65CFA /* CustomModalWindow.swift */, 2B0B301A2ADE8E2A00338B76 /* SettingsManager.swift */, 2BAA97902B0366C400EC6A63 /* OnboardingWindowManager.swift */, diff --git a/TypeaheadAI/Traits/CanGetUIElements.swift b/TypeaheadAI/Traits/CanGetUIElements.swift index c729709..878a116 100644 --- a/TypeaheadAI/Traits/CanGetUIElements.swift +++ b/TypeaheadAI/Traits/CanGetUIElements.swift @@ -19,7 +19,11 @@ extension CanGetUIElements { element = AXUIElementCreateApplication(pid) // Narrow down to the first (top-most) window - if let windowElement = element?.children().first(where: { + if NSWorkspace.shared.isVoiceOverEnabled, + let focusedElement = element?.subelement(forAttribute: kAXFocusedUIElementAttribute) { + // This works when VoiceOver is enabled + element = focusedElement + } else if let windowElement = element?.children().first(where: { $0.stringValue(forAttribute: kAXRoleAttribute) == "AXWindow" && !$0.children().isEmpty }) { diff --git a/TypeaheadAI/Views/Modal/ConversationView.swift b/TypeaheadAI/Views/Modal/ConversationView.swift index 75211cf..2ccbdc5 100644 --- a/TypeaheadAI/Views/Modal/ConversationView.swift +++ b/TypeaheadAI/Views/Modal/ConversationView.swift @@ -67,6 +67,8 @@ struct ConversationView: View { } ) .id(message.id.uuidString) + .accessibilityElement(children: .contain) + .accessibilityAddTraits(.isHeader) .padding(3) } } diff --git a/TypeaheadAI/Views/Modal/Message/ChatBubble.swift b/TypeaheadAI/Views/Modal/Message/ChatBubble.swift index fb9cefa..4fbd940 100644 --- a/TypeaheadAI/Views/Modal/Message/ChatBubble.swift +++ b/TypeaheadAI/Views/Modal/Message/ChatBubble.swift @@ -43,11 +43,12 @@ struct ChatBubble: View where Content: View { HStack(alignment: .bottom) { Spacer() - userButtons - .padding(.leading, 10) - content() + .accessibilityHeading(.h1) .clipShape(ChatBubbleShape(direction: direction)) + + userButtons + .padding(.trailing, 10) } } @@ -55,6 +56,7 @@ struct ChatBubble: View where Content: View { var aiMessage: some View { HStack(alignment: .bottom) { content() + .accessibilityHeading(.h1) .clipShape(ChatBubbleShape(direction: direction)) aiButtons @@ -75,6 +77,10 @@ struct ChatBubble: View where Content: View { .padding(.bottom, 10) }) .buttonStyle(.plain) + .accessibilityElement() + .accessibilityLabel("Edit message") + .accessibilityHint("Edit Typeahead's message") + .accessibilityAddTraits(.isButton) } if let onButtonDown = onRefresh { @@ -85,6 +91,9 @@ struct ChatBubble: View where Content: View { .padding(.bottom, 8) }) .buttonStyle(.plain) + .accessibilityElement() + .accessibilityLabel("Retry") + .accessibilityAddTraits(.isButton) } } } @@ -100,6 +109,10 @@ struct ChatBubble: View where Content: View { }) .padding(.bottom, 10) .buttonStyle(.plain) + .accessibilityElement() + .accessibilityLabel("Edit message") + .accessibilityHint("Edit your previous message") + .accessibilityAddTraits(.isButton) } if let onConfigure = onConfigure { @@ -110,6 +123,10 @@ struct ChatBubble: View where Content: View { } .buttonStyle(.plain) .padding(.bottom, 7) + .accessibilityElement() + .accessibilityLabel("Configure Quick Action") + .accessibilityHint("Create or edit a Quick Action") + .accessibilityAddTraits(.isButton) } } } diff --git a/TypeaheadAI/Views/Modal/ModalView.swift b/TypeaheadAI/Views/Modal/ModalView.swift index c35904b..e57ef3e 100644 --- a/TypeaheadAI/Views/Modal/ModalView.swift +++ b/TypeaheadAI/Views/Modal/ModalView.swift @@ -80,11 +80,7 @@ struct ModalView: View { } } } else { - if modalManager.messages.isEmpty { - RecentConversationsView(modalManager: modalManager) - } else { - ConversationView(modalManager: modalManager) - } + ConversationView(modalManager: modalManager) if let lastMessage = modalManager.messages.last, !lastMessage.isCurrentUser,