mirror of
https://github.com/h3pdesign/Neon-Vision-Editor
synced 2026-04-21 13:27:16 +00:00
114 lines
3.9 KiB
Swift
114 lines
3.9 KiB
Swift
import Foundation
|
|
import SwiftUI
|
|
|
|
|
|
|
|
/// MARK: - Types
|
|
|
|
enum ReleaseRuntimePolicy {
|
|
static let safeModeFailureThreshold = 2
|
|
|
|
static var isUpdaterEnabledForCurrentDistribution: Bool {
|
|
#if os(macOS)
|
|
return !isMacAppStoreDistribution
|
|
#else
|
|
return false
|
|
#endif
|
|
}
|
|
|
|
#if os(macOS)
|
|
static var isMacAppStoreDistribution: Bool {
|
|
// Treat both production and sandbox App Store receipts as App Store distribution.
|
|
if let appStoreReceiptURL = Bundle.main.appStoreReceiptURL,
|
|
FileManager.default.fileExists(atPath: appStoreReceiptURL.path) {
|
|
return true
|
|
}
|
|
|
|
let legacyReceiptURL = Bundle.main.bundleURL
|
|
.appendingPathComponent("Contents", isDirectory: true)
|
|
.appendingPathComponent("_MASReceipt", isDirectory: true)
|
|
.appendingPathComponent("receipt", isDirectory: false)
|
|
return FileManager.default.fileExists(atPath: legacyReceiptURL.path)
|
|
}
|
|
#endif
|
|
|
|
static func settingsTab(from requested: String?) -> String {
|
|
let trimmed = requested?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
|
return trimmed.isEmpty ? "general" : trimmed
|
|
}
|
|
|
|
static func preferredColorScheme(for appearance: String) -> ColorScheme? {
|
|
switch appearance {
|
|
case "light":
|
|
return .light
|
|
case "dark":
|
|
return .dark
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
|
|
static func nextFindMatch(
|
|
in source: String,
|
|
query: String,
|
|
useRegex: Bool,
|
|
caseSensitive: Bool,
|
|
cursorLocation: Int
|
|
) -> (range: NSRange, nextCursorLocation: Int)? {
|
|
guard !query.isEmpty else { return nil }
|
|
let ns = source as NSString
|
|
let clampedStart = min(max(0, cursorLocation), ns.length)
|
|
let forwardRange = NSRange(location: clampedStart, length: max(0, ns.length - clampedStart))
|
|
let wrapRange = NSRange(location: 0, length: max(0, clampedStart))
|
|
|
|
let match: NSRange?
|
|
if useRegex {
|
|
guard let regex = try? NSRegularExpression(
|
|
pattern: query,
|
|
options: caseSensitive ? [] : [.caseInsensitive]
|
|
) else {
|
|
return nil
|
|
}
|
|
match = regex.firstMatch(in: source, options: [], range: forwardRange)?.range
|
|
?? regex.firstMatch(in: source, options: [], range: wrapRange)?.range
|
|
} else {
|
|
let options: NSString.CompareOptions = caseSensitive ? [] : [.caseInsensitive]
|
|
match = ns.range(of: query, options: options, range: forwardRange).toOptional()
|
|
?? ns.range(of: query, options: options, range: wrapRange).toOptional()
|
|
}
|
|
|
|
guard let found = match else { return nil }
|
|
return (range: found, nextCursorLocation: found.upperBound)
|
|
}
|
|
|
|
static func subscriptionButtonsEnabled(
|
|
canUseInAppPurchases: Bool,
|
|
isPurchasing: Bool,
|
|
isLoadingProducts: Bool
|
|
) -> Bool {
|
|
canUseInAppPurchases && !isPurchasing && !isLoadingProducts
|
|
}
|
|
|
|
static func shouldEnterSafeMode(
|
|
consecutiveFailedLaunches: Int,
|
|
requestedManually: Bool
|
|
) -> Bool {
|
|
requestedManually || consecutiveFailedLaunches >= safeModeFailureThreshold
|
|
}
|
|
|
|
static func safeModeStartupMessage(
|
|
consecutiveFailedLaunches: Int,
|
|
requestedManually: Bool
|
|
) -> String? {
|
|
guard shouldEnterSafeMode(
|
|
consecutiveFailedLaunches: consecutiveFailedLaunches,
|
|
requestedManually: requestedManually
|
|
) else {
|
|
return nil
|
|
}
|
|
if requestedManually {
|
|
return "Safe Mode is active for this launch. Session restore and startup diagnostics are paused."
|
|
}
|
|
return "Safe Mode is active because the last \(consecutiveFailedLaunches) launch attempts did not finish cleanly. Session restore and startup diagnostics are paused."
|
|
}
|
|
}
|