Skip to content
Open
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
36 changes: 36 additions & 0 deletions ScreenTextGrab/AppState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ final class AppState: ObservableObject {
@Published var speechState: SpeechPlaybackState
@Published var ocrLanguageSelection: OCRLanguageSelection
@Published var captureOutputPreset: CaptureOutputPreset
@Published var monospaceLayoutSettings: MonospaceLayoutSettings
@Published var interfaceLanguage: InterfaceLanguage
@Published var watchConfiguration: WatchConfiguration
@Published var appProfiles: [AppCaptureProfile]
Expand Down Expand Up @@ -76,6 +77,9 @@ final class AppState: ObservableObject {
self.captureOutputPreset = persistsUserPreferences
? CaptureOutputPresetStore.load(defaults: defaults)
: .smart
self.monospaceLayoutSettings = persistsUserPreferences
? MonospaceLayoutSettingsStore.load(defaults: defaults)
: .defaultValue
self.interfaceLanguage = persistsUserPreferences
? InterfaceLanguageStore.load(defaults: defaults)
: .system
Expand Down Expand Up @@ -249,6 +253,33 @@ final class AppState: ObservableObject {
persistCaptureOutputPresetIfNeeded()
}

func setMonospaceLayoutEnabled(_ enabled: Bool) {
monospaceLayoutSettings = MonospaceLayoutSettings(
isEnabled: enabled,
columns: monospaceLayoutSettings.columns,
multicolumnSortingEnabled: monospaceLayoutSettings.multicolumnSortingEnabled
)
persistMonospaceLayoutSettingsIfNeeded()
}

func setMonospaceLayoutColumns(_ columns: Int) {
monospaceLayoutSettings = MonospaceLayoutSettings(
isEnabled: monospaceLayoutSettings.isEnabled,
columns: columns,
multicolumnSortingEnabled: monospaceLayoutSettings.multicolumnSortingEnabled
)
persistMonospaceLayoutSettingsIfNeeded()
}

func setMonospaceMulticolumnSorting(_ enabled: Bool) {
monospaceLayoutSettings = MonospaceLayoutSettings(
isEnabled: monospaceLayoutSettings.isEnabled,
columns: monospaceLayoutSettings.columns,
multicolumnSortingEnabled: enabled
)
persistMonospaceLayoutSettingsIfNeeded()
}

func setInterfaceLanguage(_ language: InterfaceLanguage) {
interfaceLanguage = language
persistInterfaceLanguageIfNeeded()
Expand Down Expand Up @@ -647,6 +678,11 @@ final class AppState: ObservableObject {
CaptureOutputPresetStore.save(captureOutputPreset, defaults: defaults)
}

private func persistMonospaceLayoutSettingsIfNeeded() {
guard persistsUserPreferences else { return }
MonospaceLayoutSettingsStore.save(monospaceLayoutSettings, defaults: defaults)
}

private func persistInterfaceLanguageIfNeeded() {
guard persistsUserPreferences else { return }
InterfaceLanguageStore.save(interfaceLanguage, defaults: defaults)
Expand Down
52 changes: 52 additions & 0 deletions ScreenTextGrab/Models/AppModels.swift
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,58 @@ enum CaptureOutputPresetStore {
}
}

struct MonospaceLayoutSettings: Codable, Equatable, Sendable {
var isEnabled: Bool
var columns: Int
var multicolumnSortingEnabled: Bool

static let defaultColumns = 120
static let defaultValue = MonospaceLayoutSettings(
isEnabled: false,
columns: defaultColumns,
multicolumnSortingEnabled: false
)

init(isEnabled: Bool = false, columns: Int = defaultColumns, multicolumnSortingEnabled: Bool = false) {
self.isEnabled = isEnabled
self.columns = max(20, min(300, columns))
self.multicolumnSortingEnabled = multicolumnSortingEnabled
}

private enum CodingKeys: String, CodingKey {
case isEnabled
case columns
case multicolumnSortingEnabled
}

init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let isEnabled = try container.decodeIfPresent(Bool.self, forKey: .isEnabled) ?? false
let columns = try container.decodeIfPresent(Int.self, forKey: .columns) ?? Self.defaultColumns
let multicolumnSortingEnabled = try container.decodeIfPresent(Bool.self, forKey: .multicolumnSortingEnabled) ?? false
self.init(isEnabled: isEnabled, columns: columns, multicolumnSortingEnabled: multicolumnSortingEnabled)
}
}

enum MonospaceLayoutSettingsStore {
static let key = "screenTextGrab.monospaceLayoutSettings"

static func load(defaults: UserDefaults = .standard) -> MonospaceLayoutSettings {
guard let data = defaults.data(forKey: key),
let settings = try? JSONDecoder().decode(MonospaceLayoutSettings.self, from: data) else {
return .defaultValue
}
return settings
}

static func save(_ settings: MonospaceLayoutSettings, defaults: UserDefaults = .standard) {
guard let data = try? JSONEncoder().encode(settings) else {
return
}
defaults.set(data, forKey: key)
}
}

struct ClipboardHistoryEntry: Identifiable, Equatable, Sendable, Codable {
enum ContentKind: String, CaseIterable, Identifiable, Codable, Sendable {
case text
Expand Down
Loading