Merge pull request #1263 from omnivore-app/feat/appstore-screenshots
Automation of appstore screenshots
This commit is contained in:
105
apple/AppStoreScreenshots/AppStoreScreenshots.swift
Normal file
105
apple/AppStoreScreenshots/AppStoreScreenshots.swift
Normal 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()
|
||||
}
|
||||
}
|
||||
309
apple/AppStoreScreenshots/SnapshotHelper.swift
Normal file
309
apple/AppStoreScreenshots/SnapshotHelper.swift
Normal 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]
|
||||
@ -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 = (
|
||||
|
||||
@ -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>
|
||||
@ -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
|
||||
|
||||
Reference in New Issue
Block a user