2026-02-12 23:58:32 +00:00
import Foundation
import SwiftUI
2026-03-09 16:47:50 +00:00
// / MARK: - T y p e s
2026-02-12 23:58:32 +00:00
enum ReleaseRuntimePolicy {
2026-03-17 17:40:32 +00:00
static let safeModeFailureThreshold = 2
2026-02-14 13:24:01 +00:00
static var isUpdaterEnabledForCurrentDistribution : Bool {
#if os ( macOS )
return ! isMacAppStoreDistribution
#else
return false
#endif
}
#if os ( macOS )
static var isMacAppStoreDistribution : Bool {
2026-04-17 08:08:57 +00:00
// T r e a t b o t h p r o d u c t i o n a n d s a n d b o x A p p S t o r e r e c e i p t s a s A p p S t o r e d i s t r i b u t i o n .
if let appStoreReceiptURL = Bundle . main . appStoreReceiptURL ,
FileManager . default . fileExists ( atPath : appStoreReceiptURL . path ) {
return true
}
let legacyReceiptURL = Bundle . main . bundleURL
2026-02-14 13:24:01 +00:00
. appendingPathComponent ( " Contents " , isDirectory : true )
. appendingPathComponent ( " _MASReceipt " , isDirectory : true )
. appendingPathComponent ( " receipt " , isDirectory : false )
2026-04-17 08:08:57 +00:00
return FileManager . default . fileExists ( atPath : legacyReceiptURL . path )
2026-02-14 13:24:01 +00:00
}
#endif
2026-02-12 23:58:32 +00:00
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
}
2026-03-17 17:40:32 +00:00
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. "
}
2026-02-12 23:58:32 +00:00
}