fix: correct link highlighting, update app store validation
This commit is contained in:
@@ -9,6 +9,12 @@ import Foundation
|
||||
|
||||
enum AppStoreDetector {
|
||||
/// Returns true if the app was downloaded from the Mac App Store
|
||||
///
|
||||
/// Uses a heuristic approach that checks for the presence of a valid App Store receipt.
|
||||
/// This is sufficient for distinguishing App Store builds from direct distribution.
|
||||
///
|
||||
/// Note: This does not perform full cryptographic validation of the receipt signature, its
|
||||
/// only used to determine if we should show the 'buy me a coffee' link.
|
||||
static var isAppStoreVersion: Bool {
|
||||
#if DEBUG
|
||||
return false
|
||||
@@ -17,12 +23,30 @@ enum AppStoreDetector {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check if receipt exists and is in the expected App Store location
|
||||
let fileManager = FileManager.default
|
||||
let receiptExists = fileManager.fileExists(atPath: receiptURL.path)
|
||||
let isInMASReceipt = receiptURL.path.contains("_MASReceipt")
|
||||
guard FileManager.default.fileExists(atPath: receiptURL.path) else {
|
||||
return false
|
||||
}
|
||||
|
||||
return receiptExists && isInMASReceipt
|
||||
guard let receiptData = try? Data(contentsOf: receiptURL),
|
||||
receiptData.count > 2
|
||||
else {
|
||||
return false
|
||||
}
|
||||
|
||||
// Verify receipt has PKCS#7 signature format (starts with ASN.1 SEQUENCE tag)
|
||||
let bytes = [UInt8](receiptData.prefix(2))
|
||||
return bytes[0] == 0x30 && bytes[1] == 0x82
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Checks if the app is running in TestFlight
|
||||
///
|
||||
/// TestFlight builds have a receipt named "sandboxReceipt" instead of "receipt"
|
||||
static var isTestFlight: Bool {
|
||||
#if DEBUG
|
||||
return false
|
||||
#else
|
||||
return Bundle.main.appStoreReceiptURL?.lastPathComponent == "sandboxReceipt"
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// Created by Mike Freno on 1/7/26.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import AppKit
|
||||
import SwiftUI
|
||||
|
||||
struct PostureSetupView: View {
|
||||
@Binding var enabled: Bool
|
||||
@@ -33,9 +33,11 @@ struct PostureSetupView: View {
|
||||
VStack(spacing: 30) {
|
||||
HStack(spacing: 12) {
|
||||
Button(action: {
|
||||
// Using properly URL-encoded text fragment
|
||||
// Points to key findings about sitting posture and behavior relationship with LBP
|
||||
if let url = URL(
|
||||
string:
|
||||
"https://pubmed.ncbi.nlm.nih.gov/40111906/#:~:text=For studies exploring sitting posture, seven found a relationship with LBP. Regarding studies on sitting behavior, only one showed no relationship between LBP prevalence, while twelve indicated a relationship."
|
||||
"https://pubmed.ncbi.nlm.nih.gov/40111906/#:~:text=For%20studies%20exploring%20sitting%20posture%2C%20seven%20found%20a%20relationship%20with%20LBP.%20Regarding%20studies%20on%20sitting%20behavior%2C%20only%20one%20showed%20no%20relationship%20between%20LBP%20prevalence"
|
||||
) {
|
||||
#if os(iOS)
|
||||
UIApplication.shared.open(url)
|
||||
@@ -96,7 +98,7 @@ struct PostureSetupView: View {
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
|
||||
|
||||
// Preview button
|
||||
Button(action: {
|
||||
showPreviewWindow()
|
||||
@@ -120,34 +122,34 @@ struct PostureSetupView: View {
|
||||
.padding()
|
||||
.background(.clear)
|
||||
}
|
||||
|
||||
|
||||
private func showPreviewWindow() {
|
||||
guard let screen = NSScreen.main else { return }
|
||||
|
||||
|
||||
let window = NSWindow(
|
||||
contentRect: screen.frame,
|
||||
styleMask: [.borderless, .fullSizeContentView],
|
||||
backing: .buffered,
|
||||
defer: false
|
||||
)
|
||||
|
||||
|
||||
window.level = .floating
|
||||
window.isOpaque = false
|
||||
window.backgroundColor = .clear
|
||||
window.collectionBehavior = [.canJoinAllSpaces, .fullScreenAuxiliary]
|
||||
window.acceptsMouseMovedEvents = true
|
||||
|
||||
|
||||
let contentView = PostureReminderView(sizePercentage: 10.0) { [weak window] in
|
||||
window?.close()
|
||||
}
|
||||
|
||||
|
||||
window.contentView = NSHostingView(rootView: contentView)
|
||||
window.makeFirstResponder(window.contentView)
|
||||
|
||||
|
||||
let windowController = NSWindowController(window: window)
|
||||
windowController.showWindow(nil)
|
||||
window.makeKeyAndOrderFront(nil)
|
||||
|
||||
|
||||
previewWindowController = windowController
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,9 +9,21 @@
|
||||
import Testing
|
||||
|
||||
struct AppStoreDetectorTests {
|
||||
|
||||
|
||||
@Test func isAppStoreVersionReturnsFalseInDebug() {
|
||||
// In test/debug builds, should always return false
|
||||
#expect(AppStoreDetector.isAppStoreVersion == false)
|
||||
}
|
||||
|
||||
@Test func isTestFlightReturnsFalseInDebug() {
|
||||
// In test/debug builds, should always return false
|
||||
#expect(AppStoreDetector.isTestFlight == false)
|
||||
}
|
||||
|
||||
@Test func receiptValidationHandlesMissingReceipt() {
|
||||
// When there's no receipt (development build), should return false
|
||||
// This is implicitly tested by isAppStoreVersionReturnsFalseInDebug
|
||||
// but we're documenting the expected behavior
|
||||
#expect(AppStoreDetector.isAppStoreVersion == false)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user