diff --git a/Passepartout.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Passepartout.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index f9a6a407c..34bf07a71 100644 --- a/Passepartout.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Passepartout.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -32,8 +32,7 @@ "kind" : "remoteSourceControl", "location" : "git@github.com:passepartoutvpn/passepartoutkit-source", "state" : { - "revision" : "2e61214462dcf6ad9e211d8fdbd611c6755845c4", - "version" : "0.8.0" + "revision" : "779910e268e79f1004a95285ac2485255d88bb21" } }, { diff --git a/Passepartout/App/PassepartoutApp.swift b/Passepartout/App/PassepartoutApp.swift index 6e0ca21c4..923fe30a2 100644 --- a/Passepartout/App/PassepartoutApp.swift +++ b/Passepartout/App/PassepartoutApp.swift @@ -70,9 +70,10 @@ private extension PassepartoutApp { registry: context.registry ) .onLoad { - CommonLibrary.configureLogging( + PassepartoutConfiguration.shared.configureLogging( to: BundleConfiguration.urlForAppLog, - parameters: Constants.shared.log + parameters: Constants.shared.log, + logsPrivateData: UserDefaults.appGroup.bool(forKey: AppPreference.logsPrivateData.key) ) AppUI.configure(with: context) } diff --git a/Passepartout/Library/Package.swift b/Passepartout/Library/Package.swift index 10d0ae7fa..6618f1f62 100644 --- a/Passepartout/Library/Package.swift +++ b/Passepartout/Library/Package.swift @@ -30,8 +30,8 @@ let package = Package( ) ], dependencies: [ - .package(url: "git@github.com:passepartoutvpn/passepartoutkit-source", from: "0.8.0"), -// .package(url: "git@github.com:passepartoutvpn/passepartoutkit-source", revision: "2e61214462dcf6ad9e211d8fdbd611c6755845c4"), +// .package(url: "git@github.com:passepartoutvpn/passepartoutkit-source", from: "0.8.0"), + .package(url: "git@github.com:passepartoutvpn/passepartoutkit-source", revision: "779910e268e79f1004a95285ac2485255d88bb21"), // .package(path: "../../../passepartoutkit-source"), .package(url: "git@github.com:passepartoutvpn/passepartoutkit-source-openvpn-openssl", from: "0.8.0"), // .package(url: "git@github.com:passepartoutvpn/passepartoutkit-source-openvpn-openssl", revision: "031863a1cd683962a7dfe68e20b91fa820a1ecce"), diff --git a/Passepartout/Library/Sources/AppDataProfiles/CDProfileRepositoryV3.swift b/Passepartout/Library/Sources/AppDataProfiles/CDProfileRepositoryV3.swift index c26dbef9f..a919a1d52 100644 --- a/Passepartout/Library/Sources/AppDataProfiles/CDProfileRepositoryV3.swift +++ b/Passepartout/Library/Sources/AppDataProfiles/CDProfileRepositoryV3.swift @@ -30,8 +30,6 @@ import PassepartoutKit import UtilsLibrary extension AppData { - - // TODO: #656, make non-static public static func cdProfileRepositoryV3( registry: Registry, coder: ProfileCoder, diff --git a/Passepartout/Library/Sources/AppUI/AppUI.swift b/Passepartout/Library/Sources/AppUI/AppUI.swift index f2742aebe..d511203aa 100644 --- a/Passepartout/Library/Sources/AppUI/AppUI.swift +++ b/Passepartout/Library/Sources/AppUI/AppUI.swift @@ -26,11 +26,7 @@ import Foundation import PassepartoutKit -// TODO: #656, make non-static -public struct AppUI { - private init() { - } - +public enum AppUI { public static func configure(with context: AppContext) { assertMissingModuleImplementations() } @@ -40,11 +36,11 @@ private extension AppUI { static func assertMissingModuleImplementations() { ModuleType.allCases.forEach { moduleType in let module = moduleType.newModule() - guard module as? ModuleTypeProviding != nil else { - fatalError("\(moduleType): does not implement ModuleTypeProviding") + guard module is ModuleTypeProviding else { + fatalError("\(moduleType): is not ModuleTypeProviding") } - guard module as? any ModuleViewProviding != nil else { - fatalError("\(moduleType): does not implement ModuleViewProviding") + guard module is any ModuleViewProviding else { + fatalError("\(moduleType): is not ModuleViewProviding") } } } diff --git a/Passepartout/Library/Sources/AppUI/Domain/Issue+App.swift b/Passepartout/Library/Sources/AppUI/Domain/Issue+Metadata.swift similarity index 65% rename from Passepartout/Library/Sources/AppUI/Domain/Issue+App.swift rename to Passepartout/Library/Sources/AppUI/Domain/Issue+Metadata.swift index 0fc8f4f59..da1aeb11c 100644 --- a/Passepartout/Library/Sources/AppUI/Domain/Issue+App.swift +++ b/Passepartout/Library/Sources/AppUI/Domain/Issue+Metadata.swift @@ -1,5 +1,5 @@ // -// Issue+App.swift +// Issue+Metadata.swift // Passepartout // // Created by Davide De Rosa on 9/18/24. @@ -28,23 +28,35 @@ import Foundation import PassepartoutKit extension Issue { + struct Metadata { + let configuration: PassepartoutConfiguration - // TODO: #656, make non-static - static func with(versionString: String, purchasedProducts: Set, tunnel: Tunnel) async -> Self { - let appLog = CommonLibrary.currentLog(parameters: Constants.shared.log) + let versionString: String + + let purchasedProducts: Set + + let tunnel: Tunnel + + let urlForTunnelLog: URL + + let parameters: Constants.Log + } + + static func withMetadata(_ metadata: Metadata) async -> Issue { + let appLog = metadata.configuration.currentLog(parameters: metadata.parameters) .joined(separator: "\n") .data(using: .utf8) let tunnelLog: Data? // live tunnel log - if await tunnel.status != .inactive { - tunnelLog = await tunnel.currentLog(parameters: Constants.shared.log) + if await metadata.tunnel.status != .inactive { + tunnelLog = await metadata.tunnel.currentLog(parameters: metadata.parameters) .joined(separator: "\n") .data(using: .utf8) } // latest persisted tunnel log - else if let latestTunnelEntry = CommonLibrary.availableLogs(at: BundleConfiguration.urlForTunnelLog) + else if let latestTunnelEntry = metadata.configuration.availableLogs(at: metadata.urlForTunnelLog) .max(by: { $0.key < $1.key }) { tunnelLog = try? Data(contentsOf: latestTunnelEntry.value) @@ -55,13 +67,15 @@ extension Issue { } return Issue( - appLine: "\(Strings.Unlocalized.appName) \(versionString)", - purchasedProducts: purchasedProducts, + appLine: "\(Strings.Unlocalized.appName) \(metadata.versionString)", + purchasedProducts: metadata.purchasedProducts, appLog: appLog, tunnelLog: tunnelLog ) } +} +extension Issue { var to: String { Constants.shared.emails.issues } diff --git a/Passepartout/Library/Sources/AppUI/Views/Diagnostics/DebugLogView.swift b/Passepartout/Library/Sources/AppUI/Views/Diagnostics/DebugLogView.swift index d222ed1ee..6b9a92faf 100644 --- a/Passepartout/Library/Sources/AppUI/Views/Diagnostics/DebugLogView.swift +++ b/Passepartout/Library/Sources/AppUI/Views/Diagnostics/DebugLogView.swift @@ -29,22 +29,18 @@ import SwiftUI import UtilsLibrary extension DebugLogView { - - // TODO: #656, make non-static static func withApp(parameters: Constants.Log) -> DebugLogView { DebugLogView { - CommonLibrary.currentLog(parameters: parameters) + PassepartoutConfiguration.shared.currentLog(parameters: parameters) } } - // TODO: #656, make non-static static func withTunnel(_ tunnel: Tunnel, parameters: Constants.Log) -> DebugLogView { DebugLogView { await tunnel.currentLog(parameters: parameters) } } - // TODO: #656, make non-static static func withURL(_ url: URL) -> DebugLogView { DebugLogView { do { diff --git a/Passepartout/Library/Sources/AppUI/Views/Diagnostics/DiagnosticsView.swift b/Passepartout/Library/Sources/AppUI/Views/Diagnostics/DiagnosticsView.swift index 841a18217..35c013817 100644 --- a/Passepartout/Library/Sources/AppUI/Views/Diagnostics/DiagnosticsView.swift +++ b/Passepartout/Library/Sources/AppUI/Views/Diagnostics/DiagnosticsView.swift @@ -47,11 +47,11 @@ struct DiagnosticsView: View { @EnvironmentObject var iapManager: IAPManager - @AppStorage(AppPreference.logsPrivateData.key, store: .group) + @AppStorage(AppPreference.logsPrivateData.key, store: .appGroup) private var logsPrivateData = false var availableTunnelLogs: () -> [LogEntry] = { - CommonLibrary.availableLogs(at: BundleConfiguration.urlForTunnelLog) + PassepartoutConfiguration.shared.availableLogs(at: BundleConfiguration.urlForTunnelLog) .sorted { $0.key > $1.key } diff --git a/Passepartout/Library/Sources/AppUI/Views/Diagnostics/iOS/ReportIssueButton+iOS.swift b/Passepartout/Library/Sources/AppUI/Views/Diagnostics/iOS/ReportIssueButton+iOS.swift index 77d50682d..1db7ecaca 100644 --- a/Passepartout/Library/Sources/AppUI/Views/Diagnostics/iOS/ReportIssueButton+iOS.swift +++ b/Passepartout/Library/Sources/AppUI/Views/Diagnostics/iOS/ReportIssueButton+iOS.swift @@ -25,6 +25,7 @@ #if os(iOS) +import CommonLibrary import PassepartoutKit import SwiftUI import UIKit @@ -33,24 +34,7 @@ import UtilsLibrary extension ReportIssueButton: View { var body: some View { HStack { - Button(title) { - Task { - isPending = true - defer { - isPending = false - } - let issue = await Issue.with( - versionString: BundleConfiguration.mainVersionString, - purchasedProducts: purchasedProducts, - tunnel: tunnel - ) - guard MailComposerView.canSendMail() else { - openMailTo(with: issue) - return - } - issueBeingReported = issue - } - } + Button(title, action: sendEmail) if isPending { Spacer() ProgressView() @@ -75,21 +59,29 @@ extension ReportIssueButton: View { } } -private extension Issue { - var attachments: [MailComposerView.Attachment] { - var list: [MailComposerView.Attachment] = [] - let mimeType = Strings.Unlocalized.Issues.attachmentMimeType - if let appLog { - list.append(.init(data: appLog, mimeType: mimeType, fileName: Strings.Unlocalized.Issues.appLogFilename)) - } - if let tunnelLog { - list.append(.init(data: tunnelLog, mimeType: mimeType, fileName: Strings.Unlocalized.Issues.tunnelLogFilename)) +private extension ReportIssueButton { + func sendEmail() { + Task { + isPending = true + defer { + isPending = false + } + let issue = await Issue.withMetadata(.init( + configuration: .shared, + versionString: BundleConfiguration.mainVersionString, + purchasedProducts: purchasedProducts, + tunnel: tunnel, + urlForTunnelLog: BundleConfiguration.urlForTunnelLog, + parameters: Constants.shared.log + )) + guard MailComposerView.canSendMail() else { + openMailTo(with: issue) + return + } + issueBeingReported = issue } - return list } -} -private extension ReportIssueButton { func openMailTo(with issue: Issue) { guard let url = URL.mailto(to: issue.to, subject: issue.subject, body: issue.body) else { return @@ -102,4 +94,18 @@ private extension ReportIssueButton { } } +private extension Issue { + var attachments: [MailComposerView.Attachment] { + var list: [MailComposerView.Attachment] = [] + let mimeType = Strings.Unlocalized.Issues.attachmentMimeType + if let appLog { + list.append(.init(data: appLog, mimeType: mimeType, fileName: Strings.Unlocalized.Issues.appLogFilename)) + } + if let tunnelLog { + list.append(.init(data: tunnelLog, mimeType: mimeType, fileName: Strings.Unlocalized.Issues.tunnelLogFilename)) + } + return list + } +} + #endif diff --git a/Passepartout/Library/Sources/AppUI/Views/Diagnostics/macOS/ReportIssueButton+macOS.swift b/Passepartout/Library/Sources/AppUI/Views/Diagnostics/macOS/ReportIssueButton+macOS.swift index e393ffc2a..dd01532b1 100644 --- a/Passepartout/Library/Sources/AppUI/Views/Diagnostics/macOS/ReportIssueButton+macOS.swift +++ b/Passepartout/Library/Sources/AppUI/Views/Diagnostics/macOS/ReportIssueButton+macOS.swift @@ -25,26 +25,39 @@ #if os(macOS) +import CommonLibrary import PassepartoutKit import SwiftUI extension ReportIssueButton: View { var body: some View { - Button(title) { + Button(title, action: sendEmail) + .disabled(isPending) + } +} + +private extension ReportIssueButton { + func sendEmail() { + Task { guard let service = NSSharingService(named: .composeEmail) else { isUnableToEmail = true return } - Task { - let issue = await Issue.with( - versionString: BundleConfiguration.mainVersionString, - purchasedProducts: purchasedProducts, - tunnel: tunnel - ) - service.recipients = [issue.to] - service.subject = issue.subject - service.perform(withItems: issue.items) + isPending = true + defer { + isPending = false } + let issue = await Issue.withMetadata(.init( + configuration: .shared, + versionString: BundleConfiguration.mainVersionString, + purchasedProducts: purchasedProducts, + tunnel: tunnel, + urlForTunnelLog: BundleConfiguration.urlForTunnelLog, + parameters: Constants.shared.log + )) + service.recipients = [issue.to] + service.subject = issue.subject + service.perform(withItems: issue.items) } } } diff --git a/Passepartout/Library/Sources/CommonLibrary/CommonLibrary.swift b/Passepartout/Library/Sources/CommonLibrary/Business/PassepartoutConfiguration+Extensions.swift similarity index 73% rename from Passepartout/Library/Sources/CommonLibrary/CommonLibrary.swift rename to Passepartout/Library/Sources/CommonLibrary/Business/PassepartoutConfiguration+Extensions.swift index e70a78456..6fadc9c4a 100644 --- a/Passepartout/Library/Sources/CommonLibrary/CommonLibrary.swift +++ b/Passepartout/Library/Sources/CommonLibrary/Business/PassepartoutConfiguration+Extensions.swift @@ -1,8 +1,8 @@ // -// CommonLibrary.swift +// PassepartoutConfiguration+Extensions.swift // Passepartout // -// Created by Davide De Rosa on 8/31/24. +// Created by Davide De Rosa on 10/4/24. // Copyright (c) 2024 Davide De Rosa. All rights reserved. // // https://github.com/passepartoutvpn @@ -26,24 +26,20 @@ import Foundation import PassepartoutKit -// TODO: #656, make non-static -public struct CommonLibrary { - private init() { - } - - public static func configureLogging(to url: URL, parameters: Constants.Log) { +extension PassepartoutConfiguration { + public func configureLogging(to url: URL, parameters: Constants.Log, logsPrivateData: Bool) { pp_log(.common, .debug, "Log to: \(url)") - PassepartoutConfiguration.shared.setLocalLogger(options: .init( + setLocalLogger(options: .init( url: url, maxNumberOfLines: parameters.maxNumberOfLines, maxLevel: parameters.maxLevel, mapper: parameters.formatter.formattedLine )) - if UserDefaults.group.bool(forKey: AppPreference.logsPrivateData.key) { - PassepartoutConfiguration.shared.logsAddresses = true - PassepartoutConfiguration.shared.logsModules = true + if logsPrivateData { + logsAddresses = true + logsModules = true } if let maxAge = parameters.maxAge { @@ -51,15 +47,15 @@ public struct CommonLibrary { } } - public static func currentLog(parameters: Constants.Log) -> [String] { - PassepartoutConfiguration.shared.currentLogLines( + public func currentLog(parameters: Constants.Log) -> [String] { + currentLogLines( sinceLast: parameters.sinceLast, maxLevel: parameters.maxLevel ) .map(parameters.formatter.formattedLine) } - public static func availableLogs(at url: URL) -> [Date: URL] { + public func availableLogs(at url: URL) -> [Date: URL] { let parent = url.deletingLastPathComponent() let prefix = url.lastPathComponent do { @@ -81,13 +77,13 @@ public struct CommonLibrary { } } - public static func flushLog() { - try? PassepartoutConfiguration.shared.saveLog() + public func flushLog() { + try? saveLog() } } -private extension CommonLibrary { - static func purgeLogs(at url: URL, beyond maxAge: TimeInterval) { +private extension PassepartoutConfiguration { + func purgeLogs(at url: URL, beyond maxAge: TimeInterval) { let logs = availableLogs(at: url) let minDate = Date().addingTimeInterval(-maxAge) logs.forEach { date, url in diff --git a/Passepartout/Library/Sources/CommonLibrary/Domain/BundleConfiguration+AppGroup.swift b/Passepartout/Library/Sources/CommonLibrary/Domain/BundleConfiguration+AppGroup.swift new file mode 100644 index 000000000..073642af4 --- /dev/null +++ b/Passepartout/Library/Sources/CommonLibrary/Domain/BundleConfiguration+AppGroup.swift @@ -0,0 +1,49 @@ +// +// BundleConfiguration+AppGroup.swift +// Passepartout +// +// Created by Davide De Rosa on 10/4/24. +// Copyright (c) 2024 Davide De Rosa. All rights reserved. +// +// https://github.com/passepartoutvpn +// +// This file is part of Passepartout. +// +// Passepartout is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Passepartout is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Passepartout. If not, see . +// + +import Foundation +import PassepartoutKit + +// WARNING: beware of Constants.shared dependency + +extension BundleConfiguration { + public static var urlForAppLog: URL { + cachesURL.appending(path: Constants.shared.log.appPath) + } + + public static var urlForTunnelLog: URL { + cachesURL.appending(path: Constants.shared.log.tunnelPath) + } +} + +private extension BundleConfiguration { + static var cachesURL: URL { + let groupId = mainString(for: .groupId) + guard let url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: groupId) else { + fatalError("Unable to access App Group container") + } + return url.appending(components: "Library", "Caches") + } +} diff --git a/Passepartout/Library/Sources/CommonLibrary/Domain/BundleConfiguration+Main.swift b/Passepartout/Library/Sources/CommonLibrary/Domain/BundleConfiguration+Main.swift index d598f562d..e161b6a58 100644 --- a/Passepartout/Library/Sources/CommonLibrary/Domain/BundleConfiguration+Main.swift +++ b/Passepartout/Library/Sources/CommonLibrary/Domain/BundleConfiguration+Main.swift @@ -26,7 +26,8 @@ import Foundation import PassepartoutKit -// TODO: #656, make non-static +// WARNING: beware of Constants.shared dependency + extension BundleConfiguration { public enum BundleKey: String { case appStoreId @@ -92,21 +93,13 @@ extension BundleConfiguration { } return url } - - public static var urlForAppLog: URL { - cachesURL.appending(path: Constants.shared.log.appPath) - } - - public static var urlForTunnelLog: URL { - cachesURL.appending(path: Constants.shared.log.tunnelPath) - } } private extension BundleConfiguration { // WARNING: fails from package itself, e.g. in previews static var main: BundleConfiguration { - guard let bundle = BundleConfiguration(.main, key: Constants.shared.bundle) else { + guard let bundle = BundleConfiguration(.main, key: Constants.shared.bundleKey) else { fatalError("Missing main bundle") } return bundle @@ -115,12 +108,4 @@ private extension BundleConfiguration { static var isPreview: Bool { ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1" } - - static var cachesURL: URL { - let groupId = mainString(for: .groupId) - guard let url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: groupId) else { - fatalError("Unable to access App Group container") - } - return url.appending(components: "Library", "Caches") - } } diff --git a/Passepartout/Library/Sources/CommonLibrary/Domain/Constants.swift b/Passepartout/Library/Sources/CommonLibrary/Domain/Constants.swift index 975bc1019..afd55847f 100644 --- a/Passepartout/Library/Sources/CommonLibrary/Domain/Constants.swift +++ b/Passepartout/Library/Sources/CommonLibrary/Domain/Constants.swift @@ -128,7 +128,7 @@ public struct Constants: Decodable, Sendable { public let maxAge: TimeInterval? } - public let bundle: String + public let bundleKey: String public let websites: Websites diff --git a/Passepartout/Library/Sources/CommonLibrary/Resources/Constants.json b/Passepartout/Library/Sources/CommonLibrary/Resources/Constants.json index 2bbcff3ad..ad967731a 100644 --- a/Passepartout/Library/Sources/CommonLibrary/Resources/Constants.json +++ b/Passepartout/Library/Sources/CommonLibrary/Resources/Constants.json @@ -1,5 +1,5 @@ { - "bundle": "AppConfig", + "bundleKey": "AppConfig", "websites": { "home": "https://passepartoutvpn.app", "subreddit": "https://www.reddit.com/r/passepartout/", diff --git a/Passepartout/Library/Sources/CommonLibrary/Shared.swift b/Passepartout/Library/Sources/CommonLibrary/Shared.swift index 00b665d58..1ea4bd8e7 100644 --- a/Passepartout/Library/Sources/CommonLibrary/Shared.swift +++ b/Passepartout/Library/Sources/CommonLibrary/Shared.swift @@ -31,7 +31,7 @@ extension LoggerDestination { } extension UserDefaults { - public static let group: UserDefaults = { + public static let appGroup: UserDefaults = { let appGroup = BundleConfiguration.mainString(for: .groupId) guard let defaults = UserDefaults(suiteName: appGroup) else { fatalError("No access to App Group: \(appGroup)") diff --git a/Passepartout/Library/Sources/UtilsLibrary/Views/GenericCreditsView.swift b/Passepartout/Library/Sources/UtilsLibrary/Views/GenericCreditsView.swift index 7f3d957d5..5c889666e 100644 --- a/Passepartout/Library/Sources/UtilsLibrary/Views/GenericCreditsView.swift +++ b/Passepartout/Library/Sources/UtilsLibrary/Views/GenericCreditsView.swift @@ -219,7 +219,7 @@ private extension GenericCreditsView.LicenseView { do { let session = URLSession(configuration: .ephemeral) let response = try await session.data(from: url) - let string = String(decoding: response.0, as: UTF8.self) + let string = String(data: response.0, encoding: .utf8) withAnimation { content = string } diff --git a/Passepartout/Library/Tests/AppUITests/IAPManagerTests.swift b/Passepartout/Library/Tests/AppUITests/IAPManagerTests.swift index 9f27aeb15..169d39842 100644 --- a/Passepartout/Library/Tests/AppUITests/IAPManagerTests.swift +++ b/Passepartout/Library/Tests/AppUITests/IAPManagerTests.swift @@ -188,70 +188,8 @@ extension IAPManagerTests { // MARK: Purchasable -// func test_givenNoPurchase_thenCanBuyFullAndPlatformVersion() { -// let reader = MockReceiptReader() -// reader.setReceipt(withBuild: defaultBuildNumber, products: []) -// let sut = IAPManager(receiptReader: reader) -// -//#if targetEnvironment(macCatalyst) -// XCTAssertEqual(sut.purchasableProducts(withFeature: nil), [.fullVersion, .fullVersion_macOS]) -//#else -// XCTAssertEqual(sut.purchasableProducts(withFeature: nil), [.fullVersion, .fullVersion_iOS]) -//#endif -// } -// -// func test_givenFullVersion_thenCannotPurchase() { -// let reader = MockReceiptReader() -// reader.setReceipt(withBuild: defaultBuildNumber, products: [.fullVersion]) -// let sut = IAPManager(receiptReader: reader) -// -// XCTAssertEqual(sut.purchasableProducts(withFeature: nil), []) -// } -// -// func test_givenPlatformVersion_thenCannotPurchaseSamePlatform() { -// let reader = MockReceiptReader() -// -//#if targetEnvironment(macCatalyst) -// reader.setReceipt(withBuild: defaultBuildNumber, products: [.fullVersion_macOS]) -// let sut = IAPManager(receiptReader: reader) -// XCTAssertEqual(sut.purchasableProducts(withFeature: nil), []) -//#else -// reader.setReceipt(withBuild: defaultBuildNumber, products: [.fullVersion_iOS]) -// let sut = IAPManager(receiptReader: reader) -// XCTAssertEqual(sut.purchasableProducts(withFeature: nil), []) -//#endif -// } -// -// func test_givenOtherPlatformVersion_thenCanOnlyPurchaseMissingPlatform() { -// let reader = MockReceiptReader() -// -//#if targetEnvironment(macCatalyst) -// reader.setReceipt(withBuild: defaultBuildNumber, products: [.fullVersion_iOS]) -// let sut = IAPManager(receiptReader: reader) -// XCTAssertEqual(sut.purchasableProducts(withFeature: nil), [.fullVersion_macOS]) -//#else -// reader.setReceipt(withBuild: defaultBuildNumber, products: [.fullVersion_macOS]) -// let sut = IAPManager(receiptReader: reader) -// XCTAssertEqual(sut.purchasableProducts(withFeature: nil), [.fullVersion_iOS]) -//#endif -// } -// -// func test_givenAppleTV_whenDidNotPurchase_thenCanPurchase() { -// let reader = MockReceiptReader() -// reader.setReceipt(withBuild: defaultBuildNumber, products: []) -// let sut = IAPManager(receiptReader: reader) -// -// XCTAssertEqual(sut.purchasableProducts(withFeature: .appleTV), [.appleTV]) -// } -// -// func test_givenAppleTV_whenDidPurchase_thenCannotPurchase() { -// let reader = MockReceiptReader() -// reader.setReceipt(withBuild: defaultBuildNumber, products: [.appleTV]) -// let sut = IAPManager(receiptReader: reader) -// -// XCTAssertEqual(sut.purchasableProducts(withFeature: .appleTV), []) -// } -// + // TODO: #570, test app library + // MARK: App level func test_givenBetaApp_thenIsRestricted() async { diff --git a/Passepartout/Tunnel/PacketTunnelProvider.swift b/Passepartout/Tunnel/PacketTunnelProvider.swift index 3906e84a7..f583f178d 100644 --- a/Passepartout/Tunnel/PacketTunnelProvider.swift +++ b/Passepartout/Tunnel/PacketTunnelProvider.swift @@ -31,9 +31,10 @@ final class PacketTunnelProvider: NEPacketTunnelProvider, @unchecked Sendable { private var fwd: NEPTPForwarder? override func startTunnel(options: [String: NSObject]? = nil) async throws { - CommonLibrary.configureLogging( + PassepartoutConfiguration.shared.configureLogging( to: BundleConfiguration.urlForTunnelLog, - parameters: Constants.shared.log + parameters: Constants.shared.log, + logsPrivateData: UserDefaults.appGroup.bool(forKey: AppPreference.logsPrivateData.key) ) fwd = try await NEPTPForwarder( provider: self, @@ -44,7 +45,7 @@ final class PacketTunnelProvider: NEPacketTunnelProvider, @unchecked Sendable { do { try await fwd?.startTunnel(options: options) } catch { - CommonLibrary.flushLog() + PassepartoutConfiguration.shared.flushLog() throw error } } @@ -52,11 +53,11 @@ final class PacketTunnelProvider: NEPacketTunnelProvider, @unchecked Sendable { override func stopTunnel(with reason: NEProviderStopReason) async { await fwd?.stopTunnel(with: reason) fwd = nil - CommonLibrary.flushLog() + PassepartoutConfiguration.shared.flushLog() } override func cancelTunnelWithError(_ error: (any Error)?) { - CommonLibrary.flushLog() + PassepartoutConfiguration.shared.flushLog() super.cancelTunnelWithError(error) }