Skip to content

Commit

Permalink
Fix/accessibility (#38)
Browse files Browse the repository at this point in the history
* fix: optimisation

* fix: entitlements and accessibility

* fixes

* merge
gluonfield authored Mar 10, 2024
1 parent 0a618fc commit 84ba492
Showing 13 changed files with 78 additions and 157 deletions.
8 changes: 4 additions & 4 deletions Enchanted.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
@@ -782,7 +782,7 @@
CODE_SIGN_ENTITLEMENTS = Enchanted/Enchanted.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 12;
CURRENT_PROJECT_VERSION = 14;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "\"Enchanted/Preview Content\"";
DEVELOPMENT_TEAM = JDDZ55DT74;
@@ -808,7 +808,7 @@
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 14.0;
MARKETING_VERSION = 1.5.4;
MARKETING_VERSION = 1.5.5;
PRODUCT_BUNDLE_IDENTIFIER = subj.Enchanted;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -831,7 +831,7 @@
CODE_SIGN_ENTITLEMENTS = Enchanted/Enchanted.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 12;
CURRENT_PROJECT_VERSION = 14;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = "\"Enchanted/Preview Content\"";
DEVELOPMENT_TEAM = JDDZ55DT74;
@@ -857,7 +857,7 @@
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 14.0;
MARKETING_VERSION = 1.5.4;
MARKETING_VERSION = 1.5.5;
PRODUCT_BUNDLE_IDENTIFIER = subj.Enchanted;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";

This file was deleted.

Original file line number Diff line number Diff line change
@@ -33,6 +33,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
enableThreadSanitizer = "YES"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
2 changes: 0 additions & 2 deletions Enchanted/Enchanted.entitlements
Original file line number Diff line number Diff line change
@@ -2,8 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.temporary-exception.apple-events</key>
<true/>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.network.client</key>
3 changes: 1 addition & 2 deletions Enchanted/Helpers/Accessibility.swift
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ import AppKit
import ApplicationServices
import CoreGraphics

class Accessibility {
final class Accessibility {
static let shared = Accessibility()

/// Check if Enchanted has the right permissions
@@ -20,7 +20,6 @@ class Accessibility {
return AXIsProcessTrustedWithOptions(options as CFDictionary)
}

@MainActor
func showAccessibilityInstructionsWindow() {
if checkAccessibility() {
return
8 changes: 5 additions & 3 deletions Enchanted/Stores/AppStore.swift
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@ final class AppStore {

private var cancellables = Set<AnyCancellable>()
private var timer: Timer?
var isReachable: Bool = true
@MainActor var isReachable: Bool = true

init() {
startCheckingReachability()
@@ -35,8 +35,10 @@ final class AppStore {
}

private func updateReachable(_ isReachable: Bool) {
withAnimation {
self.isReachable = isReachable
DispatchQueue.main.async {
withAnimation {
self.isReachable = isReachable
}
}
}

68 changes: 39 additions & 29 deletions Enchanted/Stores/ConversationStore.swift
Original file line number Diff line number Diff line change
@@ -21,15 +21,15 @@ final class ConversationStore: Sendable {
/// For some reason (SwiftUI bug / too frequent UI updates) updating UI for each stream message sometimes freezes the UI.
/// Throttling UI updates seem to fix the issue.
private var currentMessageBuffer: String = ""
#if os(macOS)
#if os(macOS)
private let throttler = Throttler(delay: 0.1)
#else
#else
private let throttler = Throttler(delay: 0.1)
#endif
#endif

var conversationState: ConversationState = .completed
var conversations: [ConversationSD] = []
var selectedConversation: ConversationSD?
@MainActor var conversationState: ConversationState = .completed
@MainActor var conversations: [ConversationSD] = []
@MainActor var selectedConversation: ConversationSD?
@MainActor var messages: [MessageSD] = []

init(swiftDataService: SwiftDataService) {
@@ -38,16 +38,19 @@ final class ConversationStore: Sendable {

func loadConversations() async throws {
print("loading conversations")
conversations = try await swiftDataService.fetchConversations()
let fetchedConversations = try await swiftDataService.fetchConversations()
DispatchQueue.main.async {
self.conversations = fetchedConversations
}
print("loaded conversations")
}

func deleteAllConversations() {
Task {
DispatchQueue.main.async { [weak self] in
self?.messages = []
self?.selectedConversation = nil
}
selectedConversation = nil
try? await swiftDataService.deleteConversations()
try? await loadConversations()
}
@@ -57,8 +60,8 @@ final class ConversationStore: Sendable {
Task {
DispatchQueue.main.async { [self] in
messages = []
selectedConversation = nil
}
selectedConversation = nil
try? await swiftDataService.deleteConversations()
try? await loadConversations()
}
@@ -69,29 +72,33 @@ final class ConversationStore: Sendable {
try await swiftDataService.createConversation(conversation)
}

@MainActor func reloadConversation(_ conversation: ConversationSD) async throws {
func reloadConversation(_ conversation: ConversationSD) async throws {
let (messages, selectedConversation) = try await (
swiftDataService.fetchMessages(conversation.id),
swiftDataService.getConversation(conversation.id)
)

withAnimation(.easeInOut(duration: 0.3)) {
self.messages = messages
self.selectedConversation = selectedConversation
DispatchQueue.main.async {
withAnimation(.easeInOut(duration: 0.3)) {
self.messages = messages
self.selectedConversation = selectedConversation
}
}
}

@MainActor func selectConversation(_ conversation: ConversationSD) async throws {
func selectConversation(_ conversation: ConversationSD) async throws {
try await reloadConversation(conversation)
}

func delete(_ conversation: ConversationSD) async throws {
selectedConversation = nil
try await swiftDataService.deleteConversation(conversation)
conversations = try await swiftDataService.fetchConversations()
let fetchedConversations = try await swiftDataService.fetchConversations()
DispatchQueue.main.async {
self.selectedConversation = nil
self.conversations = fetchedConversations
}
}

// @MainActor
@MainActor func stopGenerate() {
generation?.cancel()
handleComplete()
@@ -158,18 +165,21 @@ final class ConversationStore: Sendable {
try? await loadConversations()

if await OllamaService.shared.ollamaKit.reachable() {
let request = OKChatRequestData(model: model.name, messages: messageHistory)
generation = OllamaService.shared.ollamaKit.chat(data: request)
.sink(receiveCompletion: { [weak self] completion in
switch completion {
case .finished:
self?.handleComplete()
case .failure(let error):
self?.handleError(error.localizedDescription)
}
}, receiveValue: { [weak self] response in
self?.handleReceive(response)
})
DispatchQueue.global(qos: .background).async {
let request = OKChatRequestData(model: model.name, messages: messageHistory)
self.generation = OllamaService.shared.ollamaKit.chat(data: request)
.sink(receiveCompletion: { [weak self] completion in
switch completion {
case .finished:
self?.handleComplete()
case .failure(let error):
self?.handleError(error.localizedDescription)
}
}, receiveValue: { [weak self] response in
self?.handleReceive(response)
})

}
} else {
self.handleError("Server unreachable")
}
17 changes: 12 additions & 5 deletions Enchanted/Stores/LanguageModelStore.swift
Original file line number Diff line number Diff line change
@@ -13,9 +13,9 @@ final class LanguageModelStore {
static let shared = LanguageModelStore(swiftDataService: SwiftDataService.shared)

private var swiftDataService: SwiftDataService
var models: [LanguageModelSD] = []
var supportsImages = false
var selectedModel: LanguageModelSD?
@MainActor var models: [LanguageModelSD] = []
@MainActor var supportsImages = false
@MainActor var selectedModel: LanguageModelSD?

init(swiftDataService: SwiftDataService) {
self.swiftDataService = swiftDataService
@@ -49,6 +49,7 @@ final class LanguageModelStore {
print("completed loadLocal()")
let remoteModels = try await OllamaService.shared.getModels()
print("completed loadRemote()")
print(remoteModels)

_ = localModels.map { model in
model.isAvailable == remoteModels.contains(model)
@@ -58,11 +59,17 @@ final class LanguageModelStore {
try await swiftDataService.saveModels(models: updateModelsList)
print("completed saveModels()")

models = try await swiftDataService.fetchModels()
let fetchedModels = try await swiftDataService.fetchModels()

DispatchQueue.main.async {
self.models = fetchedModels
}
}

func deleteAllModels() async throws {
models = []
DispatchQueue.main.async {
self.models = []
}
try await swiftDataService.deleteModels()
}
}
6 changes: 4 additions & 2 deletions Enchanted/UI/Shared/Chat/Chat.swift
Original file line number Diff line number Diff line change
@@ -65,8 +65,10 @@ struct Chat: View {
}

func newConversation() {
withAnimation(.easeOut(duration: 0.3)) {
conversationStore.selectedConversation = nil
DispatchQueue.main.async {
withAnimation(.easeOut(duration: 0.3)) {
self.conversationStore.selectedConversation = nil
}
}

Task {
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ import SwiftUI
import AVFoundation

struct RecordingView: View {
@StateObject var speechRecognizer = SpeechRecognizer()
@StateObject var speechRecognizer: SpeechRecognizer
@Binding var isRecording: Bool
var onComplete: (_ transcription: String) -> () = {_ in}

@@ -64,7 +64,7 @@ struct RecordingView: View {

struct MeetingView_Previews: PreviewProvider {
static var previews: some View {
RecordingView(isRecording: .constant(true))
RecordingView(speechRecognizer: SpeechRecognizer(), isRecording: .constant(true))
}
}

Loading

0 comments on commit 84ba492

Please sign in to comment.