Automation of appstore screenshots

- This doesn't completely automate the process but makes it
easier to create screenshots across devices.
This commit is contained in:
Jackson Harper
2022-09-30 14:02:54 +08:00
parent f6cb7a279d
commit c109f80d30
5 changed files with 647 additions and 1 deletions

View File

@ -0,0 +1,105 @@
//
// AppStoreScreenshots.swift
// AppStoreScreenshots
//
// Created by Jackson Harper on 9/28/22.
//
import XCTest
// swiftlint:disable line_length
final class AppStoreScreenshots: XCTestCase {
override func setUpWithError() throws {}
override func tearDownWithError() throws {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
func testScreenshotLibrary() throws {
let app = XCUIApplication()
setupSnapshot(app)
snapshot("Library")
}
func testScreenshotLibraryActions() throws {
let app = XCUIApplication()
setupSnapshot(app)
// Display the context menu of the first item in the libary
app.collectionViews.cells.firstMatch.press(forDuration: 2)
snapshot("LibraryActions")
app.children(matching: .window).element(boundBy: 0).tap()
}
func testScreenshotReader() throws {
let app = XCUIApplication()
setupSnapshot(app)
// Move into the reader
app.collectionViews.cells.firstMatch.tap()
snapshot("Reader")
}
// For this screenshot we manually set the reader position, highlight
// the text, and then run the test to take the screenshot
func testScreenshotReaderHighlight() throws {
let app = XCUIApplication()
setupSnapshot(app)
// app.collectionViews.cells.firstMatch.tap()
snapshot("ReaderHighlight")
// let webViewsQuery = app.webViews.element.swipeUp()
}
// For this screenshot we manually setup the audio player then run the test
func testScreenshotReaderPlayer() throws {
let app = XCUIApplication()
setupSnapshot(app)
// app.collectionViews.cells.firstMatch.tap()
// print("BUTTONS: ", app.buttons.allElementsBoundByIndex.count)
// app.buttons["Audiobook"].tap()
//
// print("MINIPLAYER BUTTONS: ", app.buttons.allElementsBoundByIndex)
//
snapshot("ReaderTTSPlayer")
/// app.children(matching: .window).element(boundBy: 0).tap()
// XCUIApplication().buttons["Back"].tap()
}
func testScreenshotReaderActions() throws {
let app = XCUIApplication()
setupSnapshot(app)
app.collectionViews.cells.firstMatch.tap()
app.buttons["_profile"].tap()
snapshot("ReaderActions")
app.children(matching: .window).element(boundBy: 0).tap()
XCUIApplication().buttons["Back"].tap()
}
func testScreenshotSubscriptions() throws {
let app = XCUIApplication()
setupSnapshot(app)
app.navigationBars["Home"]/*@START_MENU_TOKEN@*/ .buttons["_profile"]/*[[".otherElements[\"_profile\"].buttons[\"_profile\"]",".buttons[\"_profile\"]"],[[[-1,1],[-1,0]]],[0]]@END_MENU_TOKEN@*/ .tap()
app.collectionViews.buttons["Subscriptions"].tap()
snapshot("Newsletters")
app.navigationBars["Profile"].buttons["Home"].tap()
}
// Manually open Safari and then run the extension and then this test
func testScreenshotExtension() throws {
let app = XCUIApplication()
setupSnapshot(app)
// app.navigationBars["Home"]/*@START_MENU_TOKEN@*/ .buttons["_profile"]/*[[".otherElements[\"_profile\"].buttons[\"_profile\"]",".buttons[\"_profile\"]"],[[[-1,1],[-1,0]]],[0]]@END_MENU_TOKEN@*/ .tap()
// app.collectionViews.buttons["Subscriptions"].tap()
snapshot("SaveExtension")
// app.navigationBars["Profile"].buttons["Home"].tap()
}
}

View File

@ -0,0 +1,309 @@
//
// SnapshotHelper.swift
// Example
//
// Created by Felix Krause on 10/8/15.
//
// -----------------------------------------------------
// IMPORTANT: When modifying this file, make sure to
// increment the version number at the very
// bottom of the file to notify users about
// the new SnapshotHelper.swift
// -----------------------------------------------------
import Foundation
import XCTest
var deviceLanguage = ""
var locale = ""
func setupSnapshot(_ app: XCUIApplication, waitForAnimations: Bool = true) {
Snapshot.setupSnapshot(app, waitForAnimations: waitForAnimations)
}
func snapshot(_ name: String, waitForLoadingIndicator: Bool) {
if waitForLoadingIndicator {
Snapshot.snapshot(name)
} else {
Snapshot.snapshot(name, timeWaitingForIdle: 0)
}
}
/// - Parameters:
/// - name: The name of the snapshot
/// - timeout: Amount of seconds to wait until the network loading indicator disappears. Pass `0` if you don't want to wait.
func snapshot(_ name: String, timeWaitingForIdle timeout: TimeInterval = 20) {
Snapshot.snapshot(name, timeWaitingForIdle: timeout)
}
enum SnapshotError: Error, CustomDebugStringConvertible {
case cannotFindSimulatorHomeDirectory
case cannotRunOnPhysicalDevice
var debugDescription: String {
switch self {
case .cannotFindSimulatorHomeDirectory:
return "Couldn't find simulator home location. Please, check SIMULATOR_HOST_HOME env variable."
case .cannotRunOnPhysicalDevice:
return "Can't use Snapshot on a physical device."
}
}
}
@objcMembers
open class Snapshot: NSObject {
static var app: XCUIApplication?
static var waitForAnimations = true
static var cacheDirectory: URL?
static var screenshotsDirectory: URL? {
cacheDirectory?.appendingPathComponent("screenshots", isDirectory: true)
}
open class func setupSnapshot(_ app: XCUIApplication, waitForAnimations: Bool = true) {
Snapshot.app = app
Snapshot.waitForAnimations = waitForAnimations
do {
let cacheDir = try getCacheDirectory()
Snapshot.cacheDirectory = cacheDir
setLanguage(app)
setLocale(app)
setLaunchArguments(app)
} catch {
NSLog(error.localizedDescription)
}
}
class func setLanguage(_ app: XCUIApplication) {
guard let cacheDirectory = self.cacheDirectory else {
NSLog("CacheDirectory is not set - probably running on a physical device?")
return
}
let path = cacheDirectory.appendingPathComponent("language.txt")
do {
let trimCharacterSet = CharacterSet.whitespacesAndNewlines
deviceLanguage = try String(contentsOf: path, encoding: .utf8).trimmingCharacters(in: trimCharacterSet)
app.launchArguments += ["-AppleLanguages", "(\(deviceLanguage))"]
} catch {
NSLog("Couldn't detect/set language...")
}
}
class func setLocale(_ app: XCUIApplication) {
guard let cacheDirectory = self.cacheDirectory else {
NSLog("CacheDirectory is not set - probably running on a physical device?")
return
}
let path = cacheDirectory.appendingPathComponent("locale.txt")
do {
let trimCharacterSet = CharacterSet.whitespacesAndNewlines
locale = try String(contentsOf: path, encoding: .utf8).trimmingCharacters(in: trimCharacterSet)
} catch {
NSLog("Couldn't detect/set locale...")
}
if locale.isEmpty, !deviceLanguage.isEmpty {
locale = Locale(identifier: deviceLanguage).identifier
}
if !locale.isEmpty {
app.launchArguments += ["-AppleLocale", "\"\(locale)\""]
}
}
class func setLaunchArguments(_ app: XCUIApplication) {
guard let cacheDirectory = self.cacheDirectory else {
NSLog("CacheDirectory is not set - probably running on a physical device?")
return
}
let path = cacheDirectory.appendingPathComponent("snapshot-launch_arguments.txt")
app.launchArguments += ["-FASTLANE_SNAPSHOT", "YES", "-ui_testing"]
do {
let launchArguments = try String(contentsOf: path, encoding: String.Encoding.utf8)
let regex = try NSRegularExpression(pattern: "(\\\".+?\\\"|\\S+)", options: [])
let matches = regex.matches(in: launchArguments, options: [], range: NSRange(location: 0, length: launchArguments.count))
let results = matches.map { result -> String in
(launchArguments as NSString).substring(with: result.range)
}
app.launchArguments += results
} catch {
NSLog("Couldn't detect/set launch_arguments...")
}
}
open class func snapshot(_ name: String, timeWaitingForIdle timeout: TimeInterval = 20) {
if timeout > 0 {
waitForLoadingIndicatorToDisappear(within: timeout)
}
NSLog("snapshot: \(name)") // more information about this, check out https://docs.fastlane.tools/actions/snapshot/#how-does-it-work
if Snapshot.waitForAnimations {
sleep(1) // Waiting for the animation to be finished (kind of)
}
#if os(OSX)
guard let app = self.app else {
NSLog("XCUIApplication is not set. Please call setupSnapshot(app) before snapshot().")
return
}
app.typeKey(XCUIKeyboardKeySecondaryFn, modifierFlags: [])
#else
guard self.app != nil else {
NSLog("XCUIApplication is not set. Please call setupSnapshot(app) before snapshot().")
return
}
let screenshot = XCUIScreen.main.screenshot()
#if os(iOS) && !targetEnvironment(macCatalyst)
let image = XCUIDevice.shared.orientation.isLandscape ? fixLandscapeOrientation(image: screenshot.image) : screenshot.image
#else
let image = screenshot.image
#endif
guard var simulator = ProcessInfo().environment["SIMULATOR_DEVICE_NAME"], let screenshotsDir = screenshotsDirectory else { return }
do {
// The simulator name contains "Clone X of " inside the screenshot file when running parallelized UI Tests on concurrent devices
let regex = try NSRegularExpression(pattern: "Clone [0-9]+ of ")
let range = NSRange(location: 0, length: simulator.count)
simulator = regex.stringByReplacingMatches(in: simulator, range: range, withTemplate: "")
let path = screenshotsDir.appendingPathComponent("\(simulator)-\(name).png")
print("WRITING TO PATH ", path)
#if swift(<5.0)
UIImagePNGRepresentation(image)?.write(to: path, options: .atomic)
#else
try image.pngData()?.write(to: path, options: .atomic)
#endif
} catch {
print("Problem writing screenshot: \(name) to \(screenshotsDir)/\(simulator)-\(name).png")
NSLog(error.localizedDescription)
}
#endif
}
class func fixLandscapeOrientation(image: UIImage) -> UIImage {
#if os(watchOS)
return image
#else
if #available(iOS 10.0, *) {
let format = UIGraphicsImageRendererFormat()
format.scale = image.scale
let renderer = UIGraphicsImageRenderer(size: image.size, format: format)
return renderer.image { _ in
image.draw(in: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height))
}
} else {
return image
}
#endif
}
class func waitForLoadingIndicatorToDisappear(within timeout: TimeInterval) {
#if os(tvOS)
return
#endif
guard let app = self.app else {
NSLog("XCUIApplication is not set. Please call setupSnapshot(app) before snapshot().")
return
}
let networkLoadingIndicator = app.otherElements.deviceStatusBars.networkLoadingIndicators.element
let networkLoadingIndicatorDisappeared = XCTNSPredicateExpectation(predicate: NSPredicate(format: "exists == false"), object: networkLoadingIndicator)
_ = XCTWaiter.wait(for: [networkLoadingIndicatorDisappeared], timeout: timeout)
}
class func getCacheDirectory() throws -> URL {
let cachePath = "Library/Caches/tools.fastlane"
// on OSX config is stored in /Users/<username>/Library
// and on iOS/tvOS/WatchOS it's in simulator's home dir
#if os(OSX)
let homeDir = URL(fileURLWithPath: NSHomeDirectory())
return homeDir.appendingPathComponent(cachePath)
#elseif arch(i386) || arch(x86_64) || arch(arm64)
guard let simulatorHostHome = ProcessInfo().environment["SIMULATOR_HOST_HOME"] else {
throw SnapshotError.cannotFindSimulatorHomeDirectory
}
let homeDir = URL(fileURLWithPath: simulatorHostHome)
return homeDir.appendingPathComponent(cachePath)
#else
throw SnapshotError.cannotRunOnPhysicalDevice
#endif
}
}
private extension XCUIElementAttributes {
var isNetworkLoadingIndicator: Bool {
if hasAllowListedIdentifier { return false }
let hasOldLoadingIndicatorSize = frame.size == CGSize(width: 10, height: 20)
let hasNewLoadingIndicatorSize = frame.size.width.isBetween(46, and: 47) && frame.size.height.isBetween(2, and: 3)
return hasOldLoadingIndicatorSize || hasNewLoadingIndicatorSize
}
var hasAllowListedIdentifier: Bool {
let allowListedIdentifiers = ["GeofenceLocationTrackingOn", "StandardLocationTrackingOn"]
return allowListedIdentifiers.contains(identifier)
}
func isStatusBar(_ deviceWidth: CGFloat) -> Bool {
if elementType == .statusBar { return true }
guard frame.origin == .zero else { return false }
let oldStatusBarSize = CGSize(width: deviceWidth, height: 20)
let newStatusBarSize = CGSize(width: deviceWidth, height: 44)
return [oldStatusBarSize, newStatusBarSize].contains(frame.size)
}
}
private extension XCUIElementQuery {
var networkLoadingIndicators: XCUIElementQuery {
let isNetworkLoadingIndicator = NSPredicate { evaluatedObject, _ in
guard let element = evaluatedObject as? XCUIElementAttributes else { return false }
return element.isNetworkLoadingIndicator
}
return containing(isNetworkLoadingIndicator)
}
var deviceStatusBars: XCUIElementQuery {
guard let app = Snapshot.app else {
fatalError("XCUIApplication is not set. Please call setupSnapshot(app) before snapshot().")
}
let deviceWidth = app.windows.firstMatch.frame.width
let isStatusBar = NSPredicate { evaluatedObject, _ in
guard let element = evaluatedObject as? XCUIElementAttributes else { return false }
return element.isStatusBar(deviceWidth)
}
return containing(isStatusBar)
}
}
private extension CGFloat {
func isBetween(_ numberA: CGFloat, and numberB: CGFloat) -> Bool {
numberA ... numberB ~= self
}
}
// Please don't remove the lines below
// They are used to detect outdated configuration files
// SnapshotHelperVersion [1.28]

View File

@ -42,6 +42,8 @@
42321E882714E6B00056429F /* styles in Resources */ = {isa = PBXBuildFile; fileRef = 42321E832714E6B00056429F /* styles */; };
42321E892714E6B00056429F /* views in Resources */ = {isa = PBXBuildFile; fileRef = 42321E842714E6B00056429F /* views */; };
42321E8A2714E6B00056429F /* views in Resources */ = {isa = PBXBuildFile; fileRef = 42321E842714E6B00056429F /* views */; };
42704E7328E6BDB000C8C73E /* SnapshotHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42704E7228E6BDAF00C8C73E /* SnapshotHelper.swift */; };
42E2BFB428E458E0007F29B2 /* AppStoreScreenshots.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42E2BFB328E458E0007F29B2 /* AppStoreScreenshots.swift */; };
42FF1B33271154A700B38C38 /* SafariWebExtensionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42FF1AEB271154A600B38C38 /* SafariWebExtensionHandler.swift */; };
42FF1B34271154A700B38C38 /* SafariWebExtensionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42FF1AEB271154A600B38C38 /* SafariWebExtensionHandler.swift */; };
42FF1B35271154A700B38C38 /* _locales in Resources */ = {isa = PBXBuildFile; fileRef = 42FF1AED271154A600B38C38 /* _locales */; };
@ -101,6 +103,13 @@
remoteGlobalIDString = 42FF1B1F271154A700B38C38;
remoteInfo = "SafariExtension (macOS)";
};
42E2BFB728E458E0007F29B2 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = AFFD4158DD5DF9B387039311 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 8260E9C026EF983F8970EC05;
remoteInfo = "Omnivore-iOS";
};
9DEDC1A5B4AFF9CA06136F13 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = AFFD4158DD5DF9B387039311 /* Project object */;
@ -209,6 +218,9 @@
42321E822714E6B00056429F /* scripts */ = {isa = PBXFileReference; lastKnownFileType = folder; path = scripts; sourceTree = "<group>"; };
42321E832714E6B00056429F /* styles */ = {isa = PBXFileReference; lastKnownFileType = folder; path = styles; sourceTree = "<group>"; };
42321E842714E6B00056429F /* views */ = {isa = PBXFileReference; lastKnownFileType = folder; path = views; sourceTree = "<group>"; };
42704E7228E6BDAF00C8C73E /* SnapshotHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SnapshotHelper.swift; sourceTree = "<group>"; };
42E2BFB128E458E0007F29B2 /* AppStoreScreenshots.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AppStoreScreenshots.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
42E2BFB328E458E0007F29B2 /* AppStoreScreenshots.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppStoreScreenshots.swift; sourceTree = "<group>"; };
42FF1AEB271154A600B38C38 /* SafariWebExtensionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariWebExtensionHandler.swift; sourceTree = "<group>"; };
42FF1AED271154A600B38C38 /* _locales */ = {isa = PBXFileReference; lastKnownFileType = folder; path = _locales; sourceTree = "<group>"; };
42FF1AEE271154A600B38C38 /* images */ = {isa = PBXFileReference; lastKnownFileType = folder; path = images; sourceTree = "<group>"; };
@ -276,6 +288,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
42E2BFAE28E458E0007F29B2 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
42FF1B13271154A700B38C38 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@ -417,6 +436,7 @@
0480E70B26D8A07A006CAE2F /* Omnivore-Mac.xctestplan */,
0480E70C26D8A22D006CAE2F /* Omnivore-iOS.xctestplan */,
490C83F2909A01FFE92848AF /* Project */,
42E2BFB228E458E0007F29B2 /* AppStoreScreenshots */,
E601FA26367162479B614F0F /* Products */,
4958DE83E1725D3E7A166B8E /* OmnivoreKit */,
4214F6EE2714D2260096B644 /* Frameworks */,
@ -431,6 +451,15 @@
name = Frameworks;
sourceTree = "<group>";
};
42E2BFB228E458E0007F29B2 /* AppStoreScreenshots */ = {
isa = PBXGroup;
children = (
42E2BFB328E458E0007F29B2 /* AppStoreScreenshots.swift */,
42704E7228E6BDAF00C8C73E /* SnapshotHelper.swift */,
);
path = AppStoreScreenshots;
sourceTree = "<group>";
};
42FF1AEA271154A600B38C38 /* SafariExtension */ = {
isa = PBXGroup;
children = (
@ -521,6 +550,7 @@
42FF1B0A271154A700B38C38 /* SafariExtension.app */,
42FF1B16271154A700B38C38 /* SafariExtension.appex */,
42FF1B20271154A700B38C38 /* SafariExtension.appex */,
42E2BFB128E458E0007F29B2 /* AppStoreScreenshots.xctest */,
);
name = Products;
sourceTree = "<group>";
@ -648,6 +678,24 @@
productReference = 95D337DDCEA2007A9705A969 /* ShareExtension.appex */;
productType = "com.apple.product-type.app-extension";
};
42E2BFB028E458E0007F29B2 /* AppStoreScreenshots */ = {
isa = PBXNativeTarget;
buildConfigurationList = 42E2BFBB28E458E0007F29B2 /* Build configuration list for PBXNativeTarget "AppStoreScreenshots" */;
buildPhases = (
42E2BFAD28E458E0007F29B2 /* Sources */,
42E2BFAE28E458E0007F29B2 /* Frameworks */,
42E2BFAF28E458E0007F29B2 /* Resources */,
);
buildRules = (
);
dependencies = (
42E2BFB828E458E0007F29B2 /* PBXTargetDependency */,
);
name = AppStoreScreenshots;
productName = AppStoreScreenshots;
productReference = 42E2BFB128E458E0007F29B2 /* AppStoreScreenshots.xctest */;
productType = "com.apple.product-type.bundle.ui-testing";
};
42FF1B15271154A700B38C38 /* SafariExtension (iOS) */ = {
isa = PBXNativeTarget;
buildConfigurationList = 42FF1B4F271154A700B38C38 /* Build configuration list for PBXNativeTarget "SafariExtension (iOS)" */;
@ -743,7 +791,7 @@
AFFD4158DD5DF9B387039311 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1300;
LastSwiftUpdateCheck = 1400;
LastUpgradeCheck = 1300;
TargetAttributes = {
0411792626A22860004AE24F = {
@ -764,6 +812,10 @@
048ECFFB26A0B1CB00469E57 = {
CreatedOnToolsVersion = 12.5;
};
42E2BFB028E458E0007F29B2 = {
CreatedOnToolsVersion = 14.0;
TestTargetID = 8260E9C026EF983F8970EC05;
};
42FF1B15271154A700B38C38 = {
CreatedOnToolsVersion = 13.0;
};
@ -802,6 +854,7 @@
042F48D826DFD10E00BF98FC /* UITests-iOS */,
42FF1B15271154A700B38C38 /* SafariExtension (iOS) */,
42FF1B1F271154A700B38C38 /* SafariExtension (macOS) */,
42E2BFB028E458E0007F29B2 /* AppStoreScreenshots */,
);
};
/* End PBXProject section */
@ -845,6 +898,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
42E2BFAF28E458E0007F29B2 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
42FF1B14271154A700B38C38 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@ -1031,6 +1091,15 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
42E2BFAD28E458E0007F29B2 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
42E2BFB428E458E0007F29B2 /* AppStoreScreenshots.swift in Sources */,
42704E7328E6BDB000C8C73E /* SnapshotHelper.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
42FF1B12271154A700B38C38 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@ -1104,6 +1173,11 @@
target = 42FF1B1F271154A700B38C38 /* SafariExtension (macOS) */;
targetProxy = 4214F6F32714D28E0096B644 /* PBXContainerItemProxy */;
};
42E2BFB828E458E0007F29B2 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 8260E9C026EF983F8970EC05 /* Omnivore-iOS */;
targetProxy = 42E2BFB728E458E0007F29B2 /* PBXContainerItemProxy */;
};
5062BFE08129B9B110FB8AF7 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = ShareExtension;
@ -1460,6 +1534,53 @@
};
name = Release;
};
42E2BFB928E458E0007F29B2 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = QJF2XZ86HB;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
MARKETING_VERSION = 1.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = app.omnivore.AppStoreScreenshots;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_TARGET_NAME = "Omnivore-iOS";
};
name = Debug;
};
42E2BFBA28E458E0007F29B2 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = QJF2XZ86HB;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
MARKETING_VERSION = 1.0;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = app.omnivore.AppStoreScreenshots;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_TARGET_NAME = "Omnivore-iOS";
};
name = Release;
};
42FF1B4B271154A700B38C38 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -1907,6 +2028,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
42E2BFBB28E458E0007F29B2 /* Build configuration list for PBXNativeTarget "AppStoreScreenshots" */ = {
isa = XCConfigurationList;
buildConfigurations = (
42E2BFB928E458E0007F29B2 /* Debug */,
42E2BFBA28E458E0007F29B2 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
42FF1B4F271154A700B38C38 /* Build configuration list for PBXNativeTarget "SafariExtension (iOS)" */ = {
isa = XCConfigurationList;
buildConfigurations = (

View File

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1400"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "42E2BFB028E458E0007F29B2"
BuildableName = "AppStoreScreenshots.xctest"
BlueprintName = "AppStoreScreenshots"
ReferencedContainer = "container:Omnivore.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "42E2BFB028E458E0007F29B2"
BuildableName = "AppStoreScreenshots.xctest"
BlueprintName = "AppStoreScreenshots"
ReferencedContainer = "container:Omnivore.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "42E2BFB028E458E0007F29B2"
BuildableName = "AppStoreScreenshots.xctest"
BlueprintName = "AppStoreScreenshots"
ReferencedContainer = "container:Omnivore.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -20,6 +20,20 @@
ReferencedContainer = "container:Omnivore.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "42E2BFB028E458E0007F29B2"
BuildableName = "AppStoreScreenshots.xctest"
BlueprintName = "AppStoreScreenshots"
ReferencedContainer = "container:Omnivore.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
@ -54,6 +68,17 @@
ReferencedContainer = "container:Omnivore.xcodeproj">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO"
parallelizable = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "42E2BFB028E458E0007F29B2"
BuildableName = "AppStoreScreenshots.xctest"
BlueprintName = "AppStoreScreenshots"
ReferencedContainer = "container:Omnivore.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction