8000 Release 1.11.0 by kamillobinski · Pull Request #21 · kamillobinski/thock · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Release 1.11.0 #21

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Mar 29, 2025
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
21 changes: 17 additions & 4 deletions Thock.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
7709B6642D98A08C00E5E6E9 /* thock-cli */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "thock-cli"; sourceTree = "<group>"; };
772D9F2D2D817942003DA1A4 /* Resources */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Resources; path = Thock/Resources; sourceTree = "<group>"; };
7762F4902D7A83BA0033AE42 /* Thock.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Thock.app; sourceTree = BUILT_PRODUCTS_DIR; };
7762F4A12D7A83BC0033AE42 /* ThockTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ThockTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
Expand All @@ -38,6 +39,7 @@
777D591E2D7B0B7600A1B71F /* Exceptions for "Thock" folder in "Thock" target */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
Info.plist,
"Preview Content/Preview Assets.xcassets",
Resources/Sounds/Alps/tplai/SKCM_Blue/1.mp3,
Resources/Sounds/Alps/tplai/SKCM_Blue/2.mp3,
Expand Down Expand Up @@ -1208,6 +1210,14 @@
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
7709B6652D98A08C00E5E6E9 /* cli */ = {
isa = PBXGroup;
children = (
7709B6642D98A08C00E5E6E9 /* thock-cli */,
);
path = cli;
sourceTree = "<group>";
};
7762F4872D7A83BA0033AE42 = {
isa = PBXGroup;
children = (
Expand All @@ -1216,6 +1226,7 @@
7762F4A42D7A83BC0033AE42 /* ThockTests */,
7762F4AE2D7A83BC0033AE42 /* ThockUITests */,
7762F4912D7A83BA0033AE42 /* Products */,
7709B6652D98A08C00E5E6E9 /* cli */,
);
indentWidth = 4;
sourceTree = "<group>";
Expand Down Expand Up @@ -1536,20 +1547,21 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 9;
CURRENT_PROJECT_VERSION = 10;
DEVELOPMENT_ASSET_PATHS = "\"Thock/Preview Content\"";
DEVELOPMENT_TEAM = 2CF8T4CQ6S;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = Thock/Info.plist;
INFOPLIST_KEY_LSUIElement = YES;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 13.5;
MARKETING_VERSION = 1.10.0;
MARKETING_VERSION = 1.11.0;
PRODUCT_BUNDLE_IDENTIFIER = dev.kamillobinski.Thock;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
Expand All @@ -1566,20 +1578,21 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 9;
CURRENT_PROJECT_VERSION = 10;
DEVELOPMENT_ASSET_PATHS = "\"Thock/Preview Content\"";
DEVELOPMENT_TEAM = 2CF8T4CQ6S;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = Thock/Info.plist;
INFOPLIST_KEY_LSUIElement = YES;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 13.5;
MARKETING_VERSION = 1.10.0;
MARKETING_VERSION = 1.11.0;
PRODUCT_BUNDLE_IDENTIFIER = dev.kamillobinski.Thock;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
Expand Down
53 changes: 27 additions & 26 deletions Thock/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,37 @@ import AppKit

class AppDelegate: NSObject, NSApplicationDelegate, MenuBarControllerDelegate {
private var statusBarItem: NSStatusItem!
private var menuManager: MenuBarController!
private var menuBarController: MenuBarController!
private var keyTracker: KeyTracker!

// MARK: - App Lifecycle

func applicationDidFinishLaunching(_ notification: Notification) {
guard requestAccessibilityPermissions() else {
exit(1)
}

_ = PipeListenerService.shared
initializeKeyTracker()
loadInitialModeConfig()

ModeEngine.shared.loadInitialMode()
setupMenuBar()
}

/// Quits the application cleanly.
func applicationWillTerminate(_ notification: Notification) {
keyTracker?.stopTrackingKeys()
PipeListenerService.shared.cleanUp()
}

// MARK: - MenuBarControllerDelegate

func quitApp() {
NSApplication.shared.terminate(nil)
}

// MARK: - Setup Methods

/// Checks and requests accessibility permissions.
private func requestAccessibilityPermissions() -> Bool {
let promptKey = kAXTrustedCheckOptionPrompt.takeUnretainedValue() as String
Expand All @@ -32,34 +50,17 @@ class AppDelegate: NSObject, NSApplicationDelegate, MenuBarControllerDelegate {

/// Initializes and starts tracking keyboard events.
private func initializeKeyTracker() {
keyTracker = KeyTracker()
keyTracker.startTrackingKeys()
}

/// Loads the current mode’s configuration.
private func loadInitialModeConfig() {
let currentMode = ModeManager.shared.getCurrentMode()
ModeConfigManager.shared.loadModeConfig(for: currentMode)
SoundManager.shared.preloadSounds(for: currentMode)
if keyTracker == nil {
keyTracker = KeyTracker()
keyTracker.startTrackingKeys()
}
}

/// Sets up the macOS menu bar.
private func setupMenuBar() {
statusBarItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
menuManager = MenuBarController(statusBarItem: statusBarItem, delegate: self)
menuManager.updateMenuBarIcon()
}

/// Changes the sound mode.
func changeMode(to mode: Mode) {
ModeManager.shared.setCurrentMode(mode)
ModeConfigManager.shared.loadModeConfig(for: mode)
SoundManager.shared.preloadSounds(for: mode)
}

/// Quits the application cleanly.
func quitApp() {
keyTracker?.stopTrackingKeys()
NSApplication.shared.terminate(nil)
menuBarController = MenuBarController(statusBarItem: statusBarItem, delegate: self)
menuBarController.updateMenuBarIcon(for: AppEngine.shared.isEnabled())
}
}

30 changes: 30 additions & 0 deletions Thock/Engines/AppEngine.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// AppEngine.swift
// Thock
//
// Created by Kamil Łobiński on 29/03/2025.
//

import Foundation

final class AppEngine {
static let shared = AppEngine()

private init() {}

func toggleIsEnabled() -> Bool {
print("Toggle enabled")
return setEnabled(!isEnabled())
}

func isEnabled() -> Bool {
// print("Get enabled: \(AppStateManager.shared.isEnabled)")
return AppStateManager.shared.isEnabled
}

func setEnabled(_ enabled: Bool) -> Bool {
print("Set enabled: \(enabled)")
AppStateManager.shared.isEnabled = enabled
return enabled
}
}
44 changes: 44 additions & 0 deletions Thock/Engines/ModeEngine.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// ModeEngine.swift
// Thock
//
// Created by Kamil Łobiński on 28/03/2025.
//

import Foundation

final class ModeEngine {
static let shared = ModeEngine()

private init() {}

func apply(mode: Mode) {
print("Apply mode: \(mode.name)")
ModeManager.shared.setCurrentMode(mode)
ModeConfigManager.shared.loadModeConfig(for: mode)
SoundEngine.shared.preloadSounds(for: mode)
SettingsEngine.shared.refreshMenu()
}

func loadInitialMode() {
print("Load initial mode config")
let mode = ModeManager.shared.getCurrentMode()
ModeConfigManager.shared.loadModeConfig(for: mode)
SoundEngine.shared.preloadSounds(for: mode)
}

func getKeyDownSounds(for key: String) -> [String] {
print("Get key down sounds for \(key)")
return ModeConfigManager.shared.getKeyDownSounds(for: key)
}

func getKeyUpSounds(for key: String) -> [String] {
print("Get key up sounds for \(key)")
return ModeConfigManager.shared.getKeyUpSounds(for: key)
}

func getModeCurrentMode() -> Mode {
print("Get current mode")
return ModeManager.shared.getCurrentMode()
}
}
65 changes: 65 additions & 0 deletions Thock/Engines/SettingsEngine.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//
// SettingsEngine.swift
// Thock
//
// Created by Kamil Łobiński on 28/03/2025.
//

import Foundation

final class SettingsEngine {
static let shared = SettingsEngine()

private init() {}

func toggleOpenAtLogin() -> Bool {
print("Toggle open at login")
let newState = !SettingsManager.shared.openAtLogin
SettingsManager.shared.openAtLogin = newState
OpenAtLoginManager.setEnabled(newState)
return newState
}

func isOpenAtLoginEnabled() -> Bool {
print("Get open at login state")
return SettingsManager.shared.openAtLogin
}

func toggleModifierKeySound() -> Bool {
print("Toggle sound modifier keys")
let newState = !SettingsManager.shared.disableModifierKeys
SettingsManager.shared.disableModifierKeys = newState
return newState
}

func isModifierKeySoundDisabled() -> Bool {
print("Get sound modifier keys state")
return SettingsManager.shared.disableModifierKeys
}

func selectMode(mode: Mode) {
print("Select mode: \(mode)")
ModeEngine.shared.apply(mode: mode)
}

func refreshMenu() {
print("Refresh menu")
NotificationCenter.default.post(name: .settingsDidChange, object: nil)
}

func toggleIgnoreRapidKeyEvents() -> Bool {
print("Toggle ignore rapid key events")
let newState = !SettingsManager.shared.ignoreRapidKeyEvents
SettingsManager.shared.ignoreRapidKeyEvents = newState
return newState
}

func isIgnoreRapidKeyEventsEnabled() -> Bool {
print("Get ignore rapid key events state")
return SettingsManager.shared.ignoreRapidKeyEvents
}
}

extension Notification.Name {
static let settingsDidChange = Notification.Name("settingsDidChange")
}
52 changes: 52 additions & 0 deletions Thock/Engines/SoundEngine.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//
// SoundEngine.swift
// Thock
//
// Created by Kamil Łobiński on 29/03/2025.
//

import Foundation

final class SoundEngine {
static let shared = SoundEngine()

private init() {}

func preloadSounds(for mode: Mode) {
print("Preload sounds")
SoundManager.shared.preloadSounds(for: mode)
}

/// Plays sound for a key press event.
func play(for keyCode: Int64, isKeyDown: Bool) {
guard AppEngine.shared.isEnabled() else { return }
print("Play sound for keyCode: \(keyCode)")

let keyType = KeyMapper.fromKeyCode(keyCode)
let keySoundList = isKeyDown
? ModeEngine.shared.getKeyDownSounds(for: keyType)
: ModeEngine.shared.getKeyUpSounds(for: keyType)

if let soundFileName = keySoundList.randomElement() {
play(sound: soundFileName)
} else {
// print("Warning: (keydown: \(isKeyDown)) No available sound for keyCode: \(keyCode)")
}
}

func play(sound name: String) {
print("Play sound: \(name)")
SoundManager.shared.play(sound: name)
}

func setVolume(_ volume: Float) {
print("Set volume: \(volume)")
SoundManager.shared.setVolume(volume)
}

func getVolume() -> Float {
print("Get volume")
return SoundManager.shared.getVolume()
}

}
6 changes: 6 additions & 0 deletions Thock/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
</dict>
</plist>
2 changes: 1 addition & 1 deletion Thock/Managers/ModeManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ final class ModeManager {
static let shared = ModeManager()
private static let defaultId: UUID = UUID(uuidString: "8f6a8074-e5a5-49f3-b3e9-f9f735b98476")!
private var currentMode: Mode = ModeDatabase().getMode(by: (UserDefaults.standard.currentMode ?? ModeManager.defaultId))!

func setCurrentMode(_ newMode: Mode) {
currentMode = newMode
UserDefaults.standard.currentMode = newMode.id
Expand Down
4 changes: 2 additions & 2 deletions Thock/Managers/OpenAtLoginManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ enum OpenAtLoginManager {
private static var appService: SMAppService {
SMAppService.mainApp
}

/// Registers or unregisters the app as a login item based on the user's preference.
/// - Parameter enabled: If `true`, app is added to login items. If `false`, it's removed.
static func setEnabled(_ enabled: Bool) {
Expand All @@ -29,7 +29,7 @@ enum OpenAtLoginManager {
print("Failed to \(enabled ? "enable" : "disable") login item: \(error.localizedDescription)")
}
}

/// Returns whether the app is currently set to launch at login.
static func isEnabled() -> Bool {
return appService.status == .enabled
Expand Down
Loading
0