diff --git a/AppStoreSnapshotTestPlan.xctestplan b/AppStoreSnapshotTestPlan.xctestplan index 02e1644e6..8761c4c01 100644 --- a/AppStoreSnapshotTestPlan.xctestplan +++ b/AppStoreSnapshotTestPlan.xctestplan @@ -9,12 +9,19 @@ } ], "defaultOptions" : { + "defaultTestExecutionTimeAllowance" : 1800, "testTimeoutsEnabled" : true }, "testTargets" : [ { "selectedTests" : [ - "MastodonUISnapshotTests\/testSmoke()" + "MastodonUISnapshotTests\/testSmoke()", + "MastodonUISnapshotTests\/testSnapshotCompose()", + "MastodonUISnapshotTests\/testSnapshotHome()", + "MastodonUISnapshotTests\/testSnapshotProfile()", + "MastodonUISnapshotTests\/testSnapshotSearch()", + "MastodonUISnapshotTests\/testSnapshotServerRules()", + "MastodonUISnapshotTests\/testSnapshotThread()" ], "target" : { "containerPath" : "container:Mastodon.xcodeproj", diff --git a/Documentation/Snapshot.md b/Documentation/Snapshot.md index 5d794923b..10fececc2 100644 --- a/Documentation/Snapshot.md +++ b/Documentation/Snapshot.md @@ -8,12 +8,13 @@ The app use the Xcode UITest generate snapshots attachments. Then use the `xcpar # install xcparse from Homebrew brew install chargepoint/xcparse/xcparse ``` -## Take Snapshots -We use `xcodebuild` CLI tool to trigger UITest. To change device for snapshot. +## How it works +We use `xcodebuild` CLI tool to trigger UITest. -Replace the `name` in `-destinatio` option to change device. For example: +Set the `name` in `-destinatio` option to add device for snapshot. For example: `-destination 'platform=iOS Simulator,name=iPad Pro (12.9-inch) (5th generation)' \` +You can list the avaiable simulator: ```zsh # list the destinations xcodebuild \ @@ -22,16 +23,27 @@ xcodebuild \ -derivedDataPath '~/Downloads/MastodonBuild/Derived' \ -workspace Mastodon.xcworkspace \ -scheme 'Mastodon - Snapshot' + +# output +Available destinations for the "Mastodon - Snapshot" scheme: + { platform:iOS Simulator, id:7F6D7727-AD49-4B79-B6F5-AEC538925576, OS:15.2, name:iPad (9th generation) } + { platform:iOS Simulator, id:BEB9533C-F786-40E6-8C38-248F6A11FC37, OS:15.2, name:iPad Air (4th generation) } + … ``` -#### Auto-Login before make snapshots +#### Note: +Multiple lines for destination will dispatches the parallel snapshot jobs. + + +## Login before make snapshots This script trigger the `MastodonUITests/MastodonUISnapshotTests/testSignInAccount` test case to sign-in the account. The test case may wait for 2FA code or email code. Please input it if needed. Also, you can skip this and sign-in the test account manually. Replace the `` and `` for test account. ```zsh # build and run test case for auto sign-in -TEST_RUNNER_email='' \ - TEST_RUNNER_password='' \ +TEST_RUNNER_login_domain='' \ + TEST_RUNNER_login_email='' \ + TEST_RUNNER_login_password='' \ xcodebuild \ test \ -derivedDataPath '~/Downloads/MastodonBuild/Derived' \ @@ -48,16 +60,31 @@ TEST_RUNNER_email='' \ Note: UITest may running silent. Open the Simulator.app to make the device display. -#### Take and extract snapshots +## Take and extract snapshots + +### 1. Setup status bar ```zsh +# boot devices +xcrun simctl boot 'iPhone 8 Plus' +xcrun simctl boot 'iPhone 13 Pro Max' +xcrun simctl boot 'iPad Pro (12.9-inch) (5th generation)' + # setup magic status bar xcrun simctl status_bar 'iPhone 13 Pro Max' override --time "9:41" --batteryState charged --batteryLevel 100 xcrun simctl status_bar 'iPhone 8 Plus' override --time "9:41" --batteryState charged --batteryLevel 100 xcrun simctl status_bar 'iPad Pro (12.9-inch) (5th generation)' override --time "9:41" --batteryState charged --batteryLevel 100 +``` +### 2. Take snapshots +The `TEST_RUNNER_` prefix will sets env value into test runner. + +```zsh # take snapshots -TEST_RUNNER_domain='' \ - TEST_RUNNER_username_snapshot='username@domain.com' \ +TEST_RUNNER_login_domain='' \ + TEST_RUNNER_login_email='' \ + TEST_RUNNER_login_password='' \ + TEST_RUNNER_thread_id='' \ + TEST_RUNNER_profile_id='' \ xcodebuild \ test \ -derivedDataPath '~/Downloads/MastodonBuild/Derived' \ @@ -67,8 +94,9 @@ TEST_RUNNER_domain='' \ -destination 'platform=iOS Simulator,name=iPhone 13 Pro Max' \ -destination 'platform=iOS Simulator,name=iPhone 8 Plus' \ -destination 'platform=iOS Simulator,name=iPad Pro (12.9-inch) (5th generation)' \ - -testPlan 'AppStoreSnapshotTestPlan' \ - -only-testing:MastodonUITests/MastodonUISnapshotTests/testSnapshot + -test-iterations 3 \ + -retry-tests-on-failure \ + -testPlan 'AppStoreSnapshotTestPlan' # output: Test session results, code coverage, and logs: @@ -77,6 +105,18 @@ Test session results, code coverage, and logs: ** TEST SUCCEEDED ** ``` +#### Note: +Add `-only-testing:MastodonUITests/MastodonUISnapshotTests/testSnapshot…` to run specific test case. + +| Task | key | value | +| ------------------- | -------------- | ----------------------------------------------------- | +| testSignInAccount | login_domain | The server domain for user login | +| testSignInAccount | login_email | The user email for login | +| testSignInAccount | login_password | The user password for login | +| testSnapshotThread | thread_id | The ID for post which used for thread scene snapshot | +| testSnapshotProfile | profile_id | The ID for user which used for profile scene snapshot | + +### 3. Extract snapshots Use `xcparse screenshots ` extracts snapshots. ```zsh @@ -86,4 +126,11 @@ xcparse screenshots '' ~/Downloads/MastodonBuild/Screenshots/ # output 100% [============] 🎊 Export complete! 🎊 + +# group +mkdir 'iPhone 8 Plus' 'iPhone 13 Pro Max' 'iPad Pro (12.9-inch) (5th generation)' +find . -name "*iPad*" -type file -print0 | xargs -0 -I {} mv {} './iPad Pro (12.9-inch) (5th generation)' +find . -name "*iPhone 8*" -type file -print0 | xargs -0 -I {} mv {} './iPhone 8 Plus' +find . -name "*iPhone 13*" -type file -print0 | xargs -0 -I {} mv {} './iPhone 13 Pro Max' + ``` diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 8a5ae97c4..c08dd9805 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -700,6 +700,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 0655B257371274BEB7EB1C19 /* Pods-Mastodon.release snapshot.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon.release snapshot.xcconfig"; path = "Target Support Files/Pods-Mastodon/Pods-Mastodon.release snapshot.xcconfig"; sourceTree = ""; }; + 0827D1674B2523503E8605F6 /* Pods-Mastodon-MastodonUITests.release snapshot.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-MastodonUITests.release snapshot.xcconfig"; path = "Target Support Files/Pods-Mastodon-MastodonUITests/Pods-Mastodon-MastodonUITests.release snapshot.xcconfig"; sourceTree = ""; }; 0F1E2D0A2615C39400C38565 /* DoubleTitleLabelNavigationBarTitleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DoubleTitleLabelNavigationBarTitleView.swift; sourceTree = ""; }; 0F2021FA2613262F000C64BF /* HashtagTimelineViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HashtagTimelineViewController.swift; sourceTree = ""; }; 0F202200261326E6000C64BF /* HashtagTimelineViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HashtagTimelineViewModel.swift; sourceTree = ""; }; @@ -719,6 +721,7 @@ 159AC43EFE0A1F95FCB358A4 /* Pods-MastodonIntent.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MastodonIntent.release.xcconfig"; path = "Target Support Files/Pods-MastodonIntent/Pods-MastodonIntent.release.xcconfig"; sourceTree = ""; }; 164F0EBB267D4FE400249499 /* BoopSound.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = BoopSound.caf; sourceTree = ""; }; 1D6D967E77A5357E2C6110D9 /* Pods-Mastodon.asdk - debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon.asdk - debug.xcconfig"; path = "Target Support Files/Pods-Mastodon/Pods-Mastodon.asdk - debug.xcconfig"; sourceTree = ""; }; + 2C12EB4B3699D5D597027962 /* Pods-MastodonIntent.release snapshot.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MastodonIntent.release snapshot.xcconfig"; path = "Target Support Files/Pods-MastodonIntent/Pods-MastodonIntent.release snapshot.xcconfig"; sourceTree = ""; }; 2D198642261BF09500F0B013 /* SearchResultItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultItem.swift; sourceTree = ""; }; 2D198648261C0B8500F0B013 /* SearchResultSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultSection.swift; sourceTree = ""; }; 2D206B8525F5FB0900143C56 /* Double.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Double.swift; sourceTree = ""; }; @@ -783,6 +786,7 @@ 374AA339A20E0FAC75BCDA6D /* Pods_NotificationService.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NotificationService.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3B7FD8F28DDA8FBCE5562B78 /* Pods-NotificationService.asdk - debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.asdk - debug.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.asdk - debug.xcconfig"; sourceTree = ""; }; 3C030226D3C73DCC23D67452 /* Pods_Mastodon_MastodonUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Mastodon_MastodonUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 3E08A432F40BA7B9CAA9DB68 /* Pods-AppShared.release snapshot.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AppShared.release snapshot.xcconfig"; path = "Target Support Files/Pods-AppShared/Pods-AppShared.release snapshot.xcconfig"; sourceTree = ""; }; 452147B2903DF38070FE56A2 /* Pods_MastodonTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MastodonTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 459EA4F43058CAB47719E963 /* Pods-Mastodon-MastodonUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-MastodonUITests.debug.xcconfig"; path = "Target Support Files/Pods-Mastodon-MastodonUITests/Pods-Mastodon-MastodonUITests.debug.xcconfig"; sourceTree = ""; }; 46DAB0EBDDFB678347CD96FF /* Pods-MastodonTests.asdk - release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MastodonTests.asdk - release.xcconfig"; path = "Target Support Files/Pods-MastodonTests/Pods-MastodonTests.asdk - release.xcconfig"; sourceTree = ""; }; @@ -814,6 +818,8 @@ 819CEC9DCAD8E8E7BD85A7BB /* Pods-Mastodon.asdk.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon.asdk.xcconfig"; path = "Target Support Files/Pods-Mastodon/Pods-Mastodon.asdk.xcconfig"; sourceTree = ""; }; 861BE60ED27430771CFD578D /* Pods-MastodonIntent.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MastodonIntent.debug.xcconfig"; path = "Target Support Files/Pods-MastodonIntent/Pods-MastodonIntent.debug.xcconfig"; sourceTree = ""; }; 8850E70A1D5FF51432E43653 /* Pods-Mastodon-MastodonUITests.asdk - release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-MastodonUITests.asdk - release.xcconfig"; path = "Target Support Files/Pods-Mastodon-MastodonUITests/Pods-Mastodon-MastodonUITests.asdk - release.xcconfig"; sourceTree = ""; }; + 8ADD558BE5B8255E5764A54F /* Pods-NotificationService.release snapshot.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.release snapshot.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.release snapshot.xcconfig"; sourceTree = ""; }; + 8E79CCBE51FBC3F7FE8CF49F /* Pods-MastodonTests.release snapshot.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MastodonTests.release snapshot.xcconfig"; path = "Target Support Files/Pods-MastodonTests/Pods-MastodonTests.release snapshot.xcconfig"; sourceTree = ""; }; 8ED8C4B1F1BA2DCFF2926BB1 /* Pods-Mastodon-NotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-NotificationService.debug.xcconfig"; path = "Target Support Files/Pods-Mastodon-NotificationService/Pods-Mastodon-NotificationService.debug.xcconfig"; sourceTree = ""; }; 9553C689FFA9EBC880CAB78D /* Pods-NotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.debug.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.debug.xcconfig"; sourceTree = ""; }; 95AD0663479892A2109EEFD0 /* Pods-ShareActionExtension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShareActionExtension.release.xcconfig"; path = "Target Support Files/Pods-ShareActionExtension/Pods-ShareActionExtension.release.xcconfig"; sourceTree = ""; }; @@ -1340,6 +1346,7 @@ ECA373ABA86BE3C2D7ED878E /* Pods-AppShared.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AppShared.release.xcconfig"; path = "Target Support Files/Pods-AppShared/Pods-AppShared.release.xcconfig"; sourceTree = ""; }; EE13214BC0246BE5210CCC10 /* Pods-AppShared.asdk.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AppShared.asdk.xcconfig"; path = "Target Support Files/Pods-AppShared/Pods-AppShared.asdk.xcconfig"; sourceTree = ""; }; F31E7502A7E3945B98C6CBAF /* Pods-NotificationService.asdk.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.asdk.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.asdk.xcconfig"; sourceTree = ""; }; + F43DF6E8AB8C87914A64FC48 /* Pods-ShareActionExtension.release snapshot.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShareActionExtension.release snapshot.xcconfig"; path = "Target Support Files/Pods-ShareActionExtension/Pods-ShareActionExtension.release snapshot.xcconfig"; sourceTree = ""; }; F4A2A2D7000E477CA459ADA9 /* Pods_AppShared.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AppShared.framework; sourceTree = BUILT_PRODUCTS_DIR; }; F4C94BD75C96D0EFF5F6D961 /* Pods_MastodonIntent.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MastodonIntent.framework; sourceTree = BUILT_PRODUCTS_DIR; }; F920AD4EC23B0D00F5CCA58E /* Pods-MastodonIntent.asdk - release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MastodonIntent.asdk - release.xcconfig"; path = "Target Support Files/Pods-MastodonIntent/Pods-MastodonIntent.asdk - release.xcconfig"; sourceTree = ""; }; @@ -1541,6 +1548,13 @@ C3789232A52F43529CA67E95 /* Pods-MastodonIntent.asdk - debug.xcconfig */, F920AD4EC23B0D00F5CCA58E /* Pods-MastodonIntent.asdk - release.xcconfig */, 159AC43EFE0A1F95FCB358A4 /* Pods-MastodonIntent.release.xcconfig */, + 3E08A432F40BA7B9CAA9DB68 /* Pods-AppShared.release snapshot.xcconfig */, + 0655B257371274BEB7EB1C19 /* Pods-Mastodon.release snapshot.xcconfig */, + 0827D1674B2523503E8605F6 /* Pods-Mastodon-MastodonUITests.release snapshot.xcconfig */, + 2C12EB4B3699D5D597027962 /* Pods-MastodonIntent.release snapshot.xcconfig */, + 8E79CCBE51FBC3F7FE8CF49F /* Pods-MastodonTests.release snapshot.xcconfig */, + 8ADD558BE5B8255E5764A54F /* Pods-NotificationService.release snapshot.xcconfig */, + F43DF6E8AB8C87914A64FC48 /* Pods-ShareActionExtension.release snapshot.xcconfig */, ); path = Pods; sourceTree = ""; @@ -3430,22 +3444,22 @@ ); mainGroup = DB427DC925BAA00100D1B89D; packageReferences = ( - DB3D0FF125BAA61700EAA174 /* XCRemoteSwiftPackageReference "AlamofireImage" */, + DB3D0FF125BAA61700EAA174 /* XCRemoteSwiftPackageReference "AlamofireImage.git" */, 2D61336725C18A4F00CAE157 /* XCRemoteSwiftPackageReference "AlamofireNetworkActivityIndicator" */, DB0140BB25C40D7500F9F3CF /* XCRemoteSwiftPackageReference "CommonOSLog" */, - 2D5981B825E4D7F8000FB903 /* XCRemoteSwiftPackageReference "ThirdPartyMailer" */, - 2D939AC625EE14620076FA61 /* XCRemoteSwiftPackageReference "TOCropViewController" */, + 2D5981B825E4D7F8000FB903 /* XCRemoteSwiftPackageReference "ThirdPartyMailer.git" */, + 2D939AC625EE14620076FA61 /* XCRemoteSwiftPackageReference "TOCropViewController.git" */, DB9A487C2603456B008B817C /* XCRemoteSwiftPackageReference "UITextView-Placeholder" */, DBB525062611EAC0002F1F29 /* XCRemoteSwiftPackageReference "Tabman" */, - DB6804722637CC1200430867 /* XCRemoteSwiftPackageReference "KeychainAccess" */, - DBAC6481267D0B21007FE9FD /* XCRemoteSwiftPackageReference "DifferenceKit" */, - DBAC649C267DFE43007FE9FD /* XCRemoteSwiftPackageReference "DiffableDataSources" */, - DBAC649F267E6D01007FE9FD /* XCRemoteSwiftPackageReference "Fuzi" */, - DBF7A0FA26830C33004176A2 /* XCRemoteSwiftPackageReference "FPSIndicator" */, - DB0E2D2C26833FF600865C3C /* XCRemoteSwiftPackageReference "Nuke-FLAnimatedImage-Plugin" */, - DB01E23126A98F0900C3965B /* XCRemoteSwiftPackageReference "MetaTextKit" */, - DB552D4D26BBD10C00E481F6 /* XCRemoteSwiftPackageReference "swift-collections" */, - DBA5A52D26F07ED800CACBAA /* XCRemoteSwiftPackageReference "PanModal" */, + DB6804722637CC1200430867 /* XCRemoteSwiftPackageReference "KeychainAccess.git" */, + DBAC6481267D0B21007FE9FD /* XCRemoteSwiftPackageReference "DifferenceKit.git" */, + DBAC649C267DFE43007FE9FD /* XCRemoteSwiftPackageReference "DiffableDataSources.git" */, + DBAC649F267E6D01007FE9FD /* XCRemoteSwiftPackageReference "Fuzi.git" */, + DBF7A0FA26830C33004176A2 /* XCRemoteSwiftPackageReference "FPSIndicator.git" */, + DB0E2D2C26833FF600865C3C /* XCRemoteSwiftPackageReference "Nuke-FLAnimatedImage-Plugin.git" */, + DB01E23126A98F0900C3965B /* XCRemoteSwiftPackageReference "MetaTextKit.git" */, + DB552D4D26BBD10C00E481F6 /* XCRemoteSwiftPackageReference "swift-collections.git" */, + DBA5A52D26F07ED800CACBAA /* XCRemoteSwiftPackageReference "PanModal.git" */, ); productRefGroup = DB427DD325BAA00100D1B89D /* Products */; projectDirPath = ""; @@ -4925,6 +4939,237 @@ }; name = Release; }; + DBEB19E127E4658E00B0E80E /* Release Snapshot */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INTENTS_CODEGEN_LANGUAGE = Swift; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = SNAPSHOT; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = "Release Snapshot"; + }; + DBEB19E227E4658E00B0E80E /* Release Snapshot */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0655B257371274BEB7EB1C19 /* Pods-Mastodon.release snapshot.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 108; + DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; + DEVELOPMENT_TEAM = 5Z4GVSS33P; + INFOPLIST_FILE = Mastodon/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0.7; + PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "Mastodon/Vender/Mastodon-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = "Release Snapshot"; + }; + DBEB19E327E4658E00B0E80E /* Release Snapshot */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8E79CCBE51FBC3F7FE8CF49F /* Pods-MastodonTests.release snapshot.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 5Z4GVSS33P; + INFOPLIST_FILE = MastodonTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.MastodonTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Mastodon.app/Mastodon"; + }; + name = "Release Snapshot"; + }; + DBEB19E427E4658E00B0E80E /* Release Snapshot */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0827D1674B2523503E8605F6 /* Pods-Mastodon-MastodonUITests.release snapshot.xcconfig */; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 5Z4GVSS33P; + INFOPLIST_FILE = MastodonUITests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.MastodonUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = Mastodon; + }; + name = "Release Snapshot"; + }; + DBEB19E527E4658E00B0E80E /* Release Snapshot */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3E08A432F40BA7B9CAA9DB68 /* Pods-AppShared.release snapshot.xcconfig */; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 108; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = 5Z4GVSS33P; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 108; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = AppShared/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.AppShared; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = "Release Snapshot"; + }; + DBEB19E627E4658E00B0E80E /* Release Snapshot */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8ADD558BE5B8255E5764A54F /* Pods-NotificationService.release snapshot.xcconfig */; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 108; + DEVELOPMENT_TEAM = 5Z4GVSS33P; + INFOPLIST_FILE = NotificationService/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 1.0.7; + PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.NotificationService; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = "Release Snapshot"; + }; + DBEB19E727E4658E00B0E80E /* Release Snapshot */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F43DF6E8AB8C87914A64FC48 /* Pods-ShareActionExtension.release snapshot.xcconfig */; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 108; + DEVELOPMENT_TEAM = 5Z4GVSS33P; + INFOPLIST_FILE = ShareActionExtension/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 1.0.7; + PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.ShareActionExtension; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = "Release Snapshot"; + }; + DBEB19E827E4658E00B0E80E /* Release Snapshot */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 2C12EB4B3699D5D597027962 /* Pods-MastodonIntent.release snapshot.xcconfig */; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 108; + DEVELOPMENT_TEAM = 5Z4GVSS33P; + INFOPLIST_FILE = MastodonIntent/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 1.0.7; + PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.MastodonIntent; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = "Release Snapshot"; + }; DBF8AE1C263293E400C9C23C /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 9553C689FFA9EBC880CAB78D /* Pods-NotificationService.debug.xcconfig */; @@ -4981,6 +5226,7 @@ buildConfigurations = ( DB427DFA25BAA00100D1B89D /* Debug */, DB427DFB25BAA00100D1B89D /* Release */, + DBEB19E127E4658E00B0E80E /* Release Snapshot */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -4990,6 +5236,7 @@ buildConfigurations = ( DB427DFD25BAA00100D1B89D /* Debug */, DB427DFE25BAA00100D1B89D /* Release */, + DBEB19E227E4658E00B0E80E /* Release Snapshot */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -4999,6 +5246,7 @@ buildConfigurations = ( DB427E0025BAA00100D1B89D /* Debug */, DB427E0125BAA00100D1B89D /* Release */, + DBEB19E327E4658E00B0E80E /* Release Snapshot */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -5008,6 +5256,7 @@ buildConfigurations = ( DB427E0325BAA00100D1B89D /* Debug */, DB427E0425BAA00100D1B89D /* Release */, + DBEB19E427E4658E00B0E80E /* Release Snapshot */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -5017,6 +5266,7 @@ buildConfigurations = ( DB6804892637CD4C00430867 /* Debug */, DB68048A2637CD4C00430867 /* Release */, + DBEB19E527E4658E00B0E80E /* Release Snapshot */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -5026,6 +5276,7 @@ buildConfigurations = ( DB8FABD026AEC7B2008E5AF4 /* Debug */, DB8FABD326AEC7B2008E5AF4 /* Release */, + DBEB19E827E4658E00B0E80E /* Release Snapshot */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -5035,6 +5286,7 @@ buildConfigurations = ( DBC6461D26A170AB00B0E31B /* Debug */, DBC6462026A170AB00B0E31B /* Release */, + DBEB19E727E4658E00B0E80E /* Release Snapshot */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -5044,6 +5296,7 @@ buildConfigurations = ( DBF8AE1C263293E400C9C23C /* Debug */, DBF8AE1D263293E400C9C23C /* Release */, + DBEB19E627E4658E00B0E80E /* Release Snapshot */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -5051,7 +5304,7 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ - 2D5981B825E4D7F8000FB903 /* XCRemoteSwiftPackageReference "ThirdPartyMailer" */ = { + 2D5981B825E4D7F8000FB903 /* XCRemoteSwiftPackageReference "ThirdPartyMailer.git" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/vtourraine/ThirdPartyMailer.git"; requirement = { @@ -5067,7 +5320,7 @@ minimumVersion = 3.1.0; }; }; - 2D939AC625EE14620076FA61 /* XCRemoteSwiftPackageReference "TOCropViewController" */ = { + 2D939AC625EE14620076FA61 /* XCRemoteSwiftPackageReference "TOCropViewController.git" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/TimOliver/TOCropViewController.git"; requirement = { @@ -5083,7 +5336,7 @@ minimumVersion = 0.1.1; }; }; - DB01E23126A98F0900C3965B /* XCRemoteSwiftPackageReference "MetaTextKit" */ = { + DB01E23126A98F0900C3965B /* XCRemoteSwiftPackageReference "MetaTextKit.git" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/TwidereProject/MetaTextKit.git"; requirement = { @@ -5091,7 +5344,7 @@ version = 2.2.1; }; }; - DB0E2D2C26833FF600865C3C /* XCRemoteSwiftPackageReference "Nuke-FLAnimatedImage-Plugin" */ = { + DB0E2D2C26833FF600865C3C /* XCRemoteSwiftPackageReference "Nuke-FLAnimatedImage-Plugin.git" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/kean/Nuke-FLAnimatedImage-Plugin.git"; requirement = { @@ -5099,7 +5352,7 @@ minimumVersion = 8.0.0; }; }; - DB3D0FF125BAA61700EAA174 /* XCRemoteSwiftPackageReference "AlamofireImage" */ = { + DB3D0FF125BAA61700EAA174 /* XCRemoteSwiftPackageReference "AlamofireImage.git" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/Alamofire/AlamofireImage.git"; requirement = { @@ -5107,7 +5360,7 @@ minimumVersion = 4.1.0; }; }; - DB552D4D26BBD10C00E481F6 /* XCRemoteSwiftPackageReference "swift-collections" */ = { + DB552D4D26BBD10C00E481F6 /* XCRemoteSwiftPackageReference "swift-collections.git" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/apple/swift-collections.git"; requirement = { @@ -5115,7 +5368,7 @@ minimumVersion = 0.0.5; }; }; - DB6804722637CC1200430867 /* XCRemoteSwiftPackageReference "KeychainAccess" */ = { + DB6804722637CC1200430867 /* XCRemoteSwiftPackageReference "KeychainAccess.git" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/kishikawakatsumi/KeychainAccess.git"; requirement = { @@ -5131,7 +5384,7 @@ minimumVersion = 1.4.1; }; }; - DBA5A52D26F07ED800CACBAA /* XCRemoteSwiftPackageReference "PanModal" */ = { + DBA5A52D26F07ED800CACBAA /* XCRemoteSwiftPackageReference "PanModal.git" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/slackhq/PanModal.git"; requirement = { @@ -5139,7 +5392,7 @@ minimumVersion = 1.2.7; }; }; - DBAC6481267D0B21007FE9FD /* XCRemoteSwiftPackageReference "DifferenceKit" */ = { + DBAC6481267D0B21007FE9FD /* XCRemoteSwiftPackageReference "DifferenceKit.git" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/ra1028/DifferenceKit.git"; requirement = { @@ -5147,7 +5400,7 @@ version = 1.2.0; }; }; - DBAC649C267DFE43007FE9FD /* XCRemoteSwiftPackageReference "DiffableDataSources" */ = { + DBAC649C267DFE43007FE9FD /* XCRemoteSwiftPackageReference "DiffableDataSources.git" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/MainasuK/DiffableDataSources.git"; requirement = { @@ -5155,7 +5408,7 @@ kind = branch; }; }; - DBAC649F267E6D01007FE9FD /* XCRemoteSwiftPackageReference "Fuzi" */ = { + DBAC649F267E6D01007FE9FD /* XCRemoteSwiftPackageReference "Fuzi.git" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/cezheng/Fuzi.git"; requirement = { @@ -5171,7 +5424,7 @@ minimumVersion = 2.11.0; }; }; - DBF7A0FA26830C33004176A2 /* XCRemoteSwiftPackageReference "FPSIndicator" */ = { + DBF7A0FA26830C33004176A2 /* XCRemoteSwiftPackageReference "FPSIndicator.git" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/MainasuK/FPSIndicator.git"; requirement = { @@ -5184,7 +5437,7 @@ /* Begin XCSwiftPackageProductDependency section */ 2D5981B925E4D7F8000FB903 /* ThirdPartyMailer */ = { isa = XCSwiftPackageProductDependency; - package = 2D5981B825E4D7F8000FB903 /* XCRemoteSwiftPackageReference "ThirdPartyMailer" */; + package = 2D5981B825E4D7F8000FB903 /* XCRemoteSwiftPackageReference "ThirdPartyMailer.git" */; productName = ThirdPartyMailer; }; 2D61336825C18A4F00CAE157 /* AlamofireNetworkActivityIndicator */ = { @@ -5194,7 +5447,7 @@ }; 2D939AC725EE14620076FA61 /* CropViewController */ = { isa = XCSwiftPackageProductDependency; - package = 2D939AC625EE14620076FA61 /* XCRemoteSwiftPackageReference "TOCropViewController" */; + package = 2D939AC625EE14620076FA61 /* XCRemoteSwiftPackageReference "TOCropViewController.git" */; productName = CropViewController; }; 5D526FE125BE9AC400460CB9 /* MastodonSDK */ = { @@ -5213,17 +5466,17 @@ }; DB01E23226A98F0900C3965B /* MastodonMeta */ = { isa = XCSwiftPackageProductDependency; - package = DB01E23126A98F0900C3965B /* XCRemoteSwiftPackageReference "MetaTextKit" */; + package = DB01E23126A98F0900C3965B /* XCRemoteSwiftPackageReference "MetaTextKit.git" */; productName = MastodonMeta; }; DB01E23426A98F0900C3965B /* MetaTextKit */ = { isa = XCSwiftPackageProductDependency; - package = DB01E23126A98F0900C3965B /* XCRemoteSwiftPackageReference "MetaTextKit" */; + package = DB01E23126A98F0900C3965B /* XCRemoteSwiftPackageReference "MetaTextKit.git" */; productName = MetaTextKit; }; DB0C946426A6FD4D0088FB11 /* AlamofireImage */ = { isa = XCSwiftPackageProductDependency; - package = DB3D0FF125BAA61700EAA174 /* XCRemoteSwiftPackageReference "AlamofireImage" */; + package = DB3D0FF125BAA61700EAA174 /* XCRemoteSwiftPackageReference "AlamofireImage.git" */; productName = AlamofireImage; }; DB179266278D5A4A00B71DEB /* MastodonSDK */ = { @@ -5232,22 +5485,22 @@ }; DB3D0FF225BAA61700EAA174 /* AlamofireImage */ = { isa = XCSwiftPackageProductDependency; - package = DB3D0FF125BAA61700EAA174 /* XCRemoteSwiftPackageReference "AlamofireImage" */; + package = DB3D0FF125BAA61700EAA174 /* XCRemoteSwiftPackageReference "AlamofireImage.git" */; productName = AlamofireImage; }; DB552D4E26BBD10C00E481F6 /* OrderedCollections */ = { isa = XCSwiftPackageProductDependency; - package = DB552D4D26BBD10C00E481F6 /* XCRemoteSwiftPackageReference "swift-collections" */; + package = DB552D4D26BBD10C00E481F6 /* XCRemoteSwiftPackageReference "swift-collections.git" */; productName = OrderedCollections; }; DB68050F2637D0F800430867 /* KeychainAccess */ = { isa = XCSwiftPackageProductDependency; - package = DB6804722637CC1200430867 /* XCRemoteSwiftPackageReference "KeychainAccess" */; + package = DB6804722637CC1200430867 /* XCRemoteSwiftPackageReference "KeychainAccess.git" */; productName = KeychainAccess; }; DB6D9F41263527CE008423CD /* AlamofireImage */ = { isa = XCSwiftPackageProductDependency; - package = DB3D0FF125BAA61700EAA174 /* XCRemoteSwiftPackageReference "AlamofireImage" */; + package = DB3D0FF125BAA61700EAA174 /* XCRemoteSwiftPackageReference "AlamofireImage.git" */; productName = AlamofireImage; }; DB9A487D2603456B008B817C /* UITextView+Placeholder */ = { @@ -5257,22 +5510,22 @@ }; DBA5A52E26F07ED800CACBAA /* PanModal */ = { isa = XCSwiftPackageProductDependency; - package = DBA5A52D26F07ED800CACBAA /* XCRemoteSwiftPackageReference "PanModal" */; + package = DBA5A52D26F07ED800CACBAA /* XCRemoteSwiftPackageReference "PanModal.git" */; productName = PanModal; }; DBAC6482267D0B21007FE9FD /* DifferenceKit */ = { isa = XCSwiftPackageProductDependency; - package = DBAC6481267D0B21007FE9FD /* XCRemoteSwiftPackageReference "DifferenceKit" */; + package = DBAC6481267D0B21007FE9FD /* XCRemoteSwiftPackageReference "DifferenceKit.git" */; productName = DifferenceKit; }; DBAC649D267DFE43007FE9FD /* DiffableDataSources */ = { isa = XCSwiftPackageProductDependency; - package = DBAC649C267DFE43007FE9FD /* XCRemoteSwiftPackageReference "DiffableDataSources" */; + package = DBAC649C267DFE43007FE9FD /* XCRemoteSwiftPackageReference "DiffableDataSources.git" */; productName = DiffableDataSources; }; DBAC64A0267E6D02007FE9FD /* Fuzi */ = { isa = XCSwiftPackageProductDependency; - package = DBAC649F267E6D01007FE9FD /* XCRemoteSwiftPackageReference "Fuzi" */; + package = DBAC649F267E6D01007FE9FD /* XCRemoteSwiftPackageReference "Fuzi.git" */; productName = Fuzi; }; DBB525072611EAC0002F1F29 /* Tabman */ = { @@ -5300,7 +5553,7 @@ }; DBF7A0FB26830C33004176A2 /* FPSIndicator */ = { isa = XCSwiftPackageProductDependency; - package = DBF7A0FA26830C33004176A2 /* XCRemoteSwiftPackageReference "FPSIndicator" */; + package = DBF7A0FA26830C33004176A2 /* XCRemoteSwiftPackageReference "FPSIndicator.git" */; productName = FPSIndicator; }; /* End XCSwiftPackageProductDependency section */ diff --git a/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon - Snapshot.xcscheme b/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon - Snapshot.xcscheme index 192847c1e..96cbba566 100644 --- a/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon - Snapshot.xcscheme +++ b/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon - Snapshot.xcscheme @@ -51,7 +51,7 @@ @@ -63,7 +63,7 @@ isShown orderHint - 16 + 15 CoreDataStack.xcscheme_^#shared#^_ @@ -104,7 +104,7 @@ MastodonIntent.xcscheme_^#shared#^_ orderHint - 32 + 37 MastodonIntents.xcscheme_^#shared#^_ @@ -119,12 +119,12 @@ NotificationService.xcscheme_^#shared#^_ orderHint - 33 + 36 ShareActionExtension.xcscheme_^#shared#^_ orderHint - 31 + 38 SuppressBuildableAutocreation diff --git a/Mastodon/Resources/Preview Assets.xcassets/Athens.imageset/Contents.json b/Mastodon/Resources/Preview Assets.xcassets/Athens.imageset/Contents.json new file mode 100644 index 000000000..786051dd9 --- /dev/null +++ b/Mastodon/Resources/Preview Assets.xcassets/Athens.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "IMG_1010.jpg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mastodon/Resources/Preview Assets.xcassets/Athens.imageset/IMG_1010.jpg b/Mastodon/Resources/Preview Assets.xcassets/Athens.imageset/IMG_1010.jpg new file mode 100644 index 000000000..0fce96bdd Binary files /dev/null and b/Mastodon/Resources/Preview Assets.xcassets/Athens.imageset/IMG_1010.jpg differ diff --git a/Mastodon/Scene/Compose/ComposeViewController.swift b/Mastodon/Scene/Compose/ComposeViewController.swift index aa581c860..f5dfc8ba3 100644 --- a/Mastodon/Scene/Compose/ComposeViewController.swift +++ b/Mastodon/Scene/Compose/ComposeViewController.swift @@ -381,7 +381,7 @@ extension ComposeViewController { // bind publish bar button state viewModel.$isPublishBarButtonItemEnabled .receive(on: DispatchQueue.main) - .assign(to: \.isEnabled, on: publishBarButtonItem) + .assign(to: \.isEnabled, on: publishButton) .store(in: &disposeBag) // bind media button toolbar state @@ -915,14 +915,25 @@ extension ComposeViewController: UITextViewDelegate { // MARK: - ComposeToolbarViewDelegate extension ComposeViewController: ComposeToolbarViewDelegate { - func composeToolbarView(_ composeToolbarView: ComposeToolbarView, cameraButtonDidPressed sender: Any, mediaSelectionType type: ComposeToolbarView.MediaSelectionType) { + func composeToolbarView(_ composeToolbarView: ComposeToolbarView, mediaButtonDidPressed sender: Any, mediaSelectionType type: ComposeToolbarView.MediaSelectionType) { switch type { case .photoLibrary: present(photoLibraryPicker, animated: true, completion: nil) case .camera: present(imagePickerController, animated: true, completion: nil) case .browse: + #if SNAPSHOT + guard let image = UIImage(named: "Athens") else { return } + + let attachmentService = MastodonAttachmentService( + context: context, + image: image, + initialAuthenticationBox: viewModel.authenticationBox + ) + viewModel.attachmentServices = viewModel.attachmentServices + [attachmentService] + #else present(documentPickerController, animated: true, completion: nil) + #endif } } diff --git a/Mastodon/Scene/Compose/View/ComposeToolbarView.swift b/Mastodon/Scene/Compose/View/ComposeToolbarView.swift index 66bde158d..4ed84be7c 100644 --- a/Mastodon/Scene/Compose/View/ComposeToolbarView.swift +++ b/Mastodon/Scene/Compose/View/ComposeToolbarView.swift @@ -13,7 +13,7 @@ import MastodonAsset import MastodonLocalization protocol ComposeToolbarViewDelegate: AnyObject { - func composeToolbarView(_ composeToolbarView: ComposeToolbarView, cameraButtonDidPressed sender: Any, mediaSelectionType type: ComposeToolbarView.MediaSelectionType) + func composeToolbarView(_ composeToolbarView: ComposeToolbarView, mediaButtonDidPressed sender: Any, mediaSelectionType type: ComposeToolbarView.MediaSelectionType) func composeToolbarView(_ composeToolbarView: ComposeToolbarView, pollButtonDidPressed sender: Any) func composeToolbarView(_ composeToolbarView: ComposeToolbarView, emojiButtonDidPressed sender: Any) func composeToolbarView(_ composeToolbarView: ComposeToolbarView, contentWarningButtonDidPressed sender: Any) @@ -304,21 +304,21 @@ extension ComposeToolbarView { let photoLibraryAction = UIAction(title: L10n.Scene.Compose.MediaSelection.photoLibrary, image: UIImage(systemName: "rectangle.on.rectangle"), identifier: nil, discoverabilityTitle: nil, attributes: [], state: .off) { [weak self] _ in guard let self = self else { return } os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: mediaSelectionType: .photoLibrary", ((#file as NSString).lastPathComponent), #line, #function) - self.delegate?.composeToolbarView(self, cameraButtonDidPressed: self.mediaButton, mediaSelectionType: .photoLibrary) + self.delegate?.composeToolbarView(self, mediaButtonDidPressed: self.mediaButton, mediaSelectionType: .photoLibrary) } children.append(photoLibraryAction) if UIImagePickerController.isSourceTypeAvailable(.camera) { let cameraAction = UIAction(title: L10n.Scene.Compose.MediaSelection.camera, image: UIImage(systemName: "camera"), identifier: nil, discoverabilityTitle: nil, attributes: [], state: .off, handler: { [weak self] _ in guard let self = self else { return } os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: mediaSelectionType: .camera", ((#file as NSString).lastPathComponent), #line, #function) - self.delegate?.composeToolbarView(self, cameraButtonDidPressed: self.mediaButton, mediaSelectionType: .camera) + self.delegate?.composeToolbarView(self, mediaButtonDidPressed: self.mediaButton, mediaSelectionType: .camera) }) children.append(cameraAction) } let browseAction = UIAction(title: L10n.Scene.Compose.MediaSelection.browse, image: UIImage(systemName: "ellipsis"), identifier: nil, discoverabilityTitle: nil, attributes: [], state: .off) { [weak self] _ in guard let self = self else { return } os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: mediaSelectionType: .browse", ((#file as NSString).lastPathComponent), #line, #function) - self.delegate?.composeToolbarView(self, cameraButtonDidPressed: self.mediaButton, mediaSelectionType: .browse) + self.delegate?.composeToolbarView(self, mediaButtonDidPressed: self.mediaButton, mediaSelectionType: .browse) } children.append(browseAction) diff --git a/Mastodon/Scene/HomeTimeline/HomeTimelineViewController+DebugAction.swift b/Mastodon/Scene/HomeTimeline/HomeTimelineViewController+DebugAction.swift index d4783045c..8b1d390f5 100644 --- a/Mastodon/Scene/HomeTimeline/HomeTimelineViewController+DebugAction.swift +++ b/Mastodon/Scene/HomeTimeline/HomeTimelineViewController+DebugAction.swift @@ -6,7 +6,7 @@ // -#if DEBUG +#if DEBUG || SNAPSHOT import os.log import UIKit import CoreData diff --git a/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift b/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift index d49235c81..7b7f35e5d 100644 --- a/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift +++ b/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift @@ -127,6 +127,11 @@ extension HomeTimelineViewController { settingBarButtonItem.action = #selector(HomeTimelineViewController.settingBarButtonItemPressed(_:)) #endif + #if SNAPSHOT + titleView.logoButton.menu = self.debugMenu + titleView.button.menu = self.debugMenu + #endif + viewModel.$displayComposeBarButtonItem .receive(on: DispatchQueue.main) .sink { [weak self] displayComposeBarButtonItem in diff --git a/Mastodon/Scene/HomeTimeline/View/HomeTimelineNavigationBarTitleView.swift b/Mastodon/Scene/HomeTimeline/View/HomeTimelineNavigationBarTitleView.swift index a1940640e..e67ee0106 100644 --- a/Mastodon/Scene/HomeTimeline/View/HomeTimelineNavigationBarTitleView.swift +++ b/Mastodon/Scene/HomeTimeline/View/HomeTimelineNavigationBarTitleView.swift @@ -65,6 +65,9 @@ extension HomeTimelineNavigationBarTitleView { configure(state: .logo) logoButton.addTarget(self, action: #selector(HomeTimelineNavigationBarTitleView.logoButtonDidPressed(_:)), for: .touchUpInside) button.addTarget(self, action: #selector(HomeTimelineNavigationBarTitleView.buttonDidPressed(_:)), for: .touchUpInside) + + logoButton.accessibilityIdentifier = "TitleButton" + button.accessibilityIdentifier = "TitleButton" } } diff --git a/Mastodon/Scene/Onboarding/ConfirmEmail/MastodonConfirmEmailViewModel.swift b/Mastodon/Scene/Onboarding/ConfirmEmail/MastodonConfirmEmailViewModel.swift index 7ddcefbbf..35480ba98 100644 --- a/Mastodon/Scene/Onboarding/ConfirmEmail/MastodonConfirmEmailViewModel.swift +++ b/Mastodon/Scene/Onboarding/ConfirmEmail/MastodonConfirmEmailViewModel.swift @@ -38,7 +38,7 @@ final class MastodonConfirmEmailViewModel { self.updateCredentialQuery = updateCredentialQuery } - #if DEBUG + #if DEBUG || SNAPSHOT init() { self.context = AppContext.shared self.email = "example.com" diff --git a/Mastodon/Scene/Profile/CachedProfileViewModel.swift b/Mastodon/Scene/Profile/CachedProfileViewModel.swift index 083724be1..c33a905a7 100644 --- a/Mastodon/Scene/Profile/CachedProfileViewModel.swift +++ b/Mastodon/Scene/Profile/CachedProfileViewModel.swift @@ -12,6 +12,8 @@ final class CachedProfileViewModel: ProfileViewModel { init(context: AppContext, mastodonUser: MastodonUser) { super.init(context: context, optionalMastodonUser: mastodonUser) + + logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): [Profile] user[\(mastodonUser.id)] profile: \(mastodonUser.acctWithDomain)") } } diff --git a/Mastodon/Supporting Files/SceneDelegate.swift b/Mastodon/Supporting Files/SceneDelegate.swift index 79ce1543a..d178cd0d3 100644 --- a/Mastodon/Supporting Files/SceneDelegate.swift +++ b/Mastodon/Supporting Files/SceneDelegate.swift @@ -59,6 +59,14 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { sceneCoordinator.setup() sceneCoordinator.setupOnboardingIfNeeds(animated: false) window.makeKeyAndVisible() + + #if SNAPSHOT + // speedup animation + // window.layer.speed = 999 + + // disable animation + UIView.setAnimationsEnabled(false) + #endif if let shortcutItem = connectionOptions.shortcutItem { // Save it off for later when we become active. @@ -67,7 +75,15 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { UserDefaults.shared.observe(\.customUserInterfaceStyle, options: [.initial, .new]) { [weak self] defaults, _ in guard let self = self else { return } + #if SNAPSHOT + // toggle Dark Mode + // https://stackoverflow.com/questions/32988241/how-to-access-launchenvironment-and-launcharguments-set-in-xcuiapplication-runn + if ProcessInfo.processInfo.arguments.contains("UIUserInterfaceStyleForceDark") { + self.window?.overrideUserInterfaceStyle = .dark + } + #else self.window?.overrideUserInterfaceStyle = defaults.customUserInterfaceStyle + #endif } .store(in: &observations) diff --git a/MastodonUITests/MastodonUISnapshotTests.swift b/MastodonUITests/MastodonUISnapshotTests.swift index 182ed1810..d3c5d2bf3 100644 --- a/MastodonUITests/MastodonUISnapshotTests.swift +++ b/MastodonUITests/MastodonUISnapshotTests.swift @@ -45,6 +45,19 @@ extension MastodonUISnapshotTests { extension MastodonUISnapshotTests { + func takeSnapshot(name: String) { + let snapshot = XCUIScreen.main.screenshot() + let attachment = XCTAttachment( + uniformTypeIdentifier: "public.png", + name: "\(name).\(UIDevice.current.name).png", + payload: snapshot.pngRepresentation, + userInfo: nil + ) + attachment.lifetime = .keepAlways + add(attachment) + } + + // make tab display by tap it private func tapTab(app: XCUIApplication, tab: String) { let searchTab = app.tabBars.buttons[tab] if searchTab.exists { searchTab.tap() } @@ -52,159 +65,223 @@ extension MastodonUISnapshotTests { let searchCell = app.collectionViews.cells[tab] if searchCell.exists { searchCell.tap() } } + + private func showTitleButtonMenu(app: XCUIApplication) async throws { + let titleButton = app.navigationBars.buttons["TitleButton"].firstMatch + XCTAssert(titleButton.waitForExistence(timeout: 5)) + titleButton.press(forDuration: 1.0) + try await Task.sleep(nanoseconds: .second * 1) + } - func testSnapshot() async throws { - let app = XCUIApplication() - app.launch() + private func snapshot( + name: String, + count: Int = 3, + task: (_ app: XCUIApplication) async throws -> Void + ) async rethrows { + var app = XCUIApplication() - try await testSnapshotHome() - try await testSnapshotSearch() - try await testSnapshotNotification() - try await testSnapshotProfile() - try await testSnapshotCompose() - } - - func testSnapshotHome() async throws { - let app = XCUIApplication() - app.launch() - - tapTab(app: app, tab: "Home") - try await Task.sleep(nanoseconds: .second * 3) - takeSnapshot(name: "Home - 1") - - tapTab(app: app, tab: "Home") - try await Task.sleep(nanoseconds: .second * 3) - takeSnapshot(name: "Home - 2") - - tapTab(app: app, tab: "Home") - try await Task.sleep(nanoseconds: .second * 3) - takeSnapshot(name: "Home - 3") - } - - func testSnapshotSearch() async throws { - let app = XCUIApplication() - app.launch() - - tapTab(app: app, tab: "Search") - try await Task.sleep(nanoseconds: .second * 3) - takeSnapshot(name: "Search - 1") - - tapTab(app: app, tab: "Search") - try await Task.sleep(nanoseconds: .second * 3) - takeSnapshot(name: "Search - 2") - - tapTab(app: app, tab: "Search") - try await Task.sleep(nanoseconds: .second * 3) - takeSnapshot(name: "Search - 3") - } - - func testSnapshotNotification() async throws { - let app = XCUIApplication() - app.launch() - - tapTab(app: app, tab: "Notification") - try await Task.sleep(nanoseconds: .second * 3) - takeSnapshot(name: "Notification - 1") - - tapTab(app: app, tab: "Notification") - try await Task.sleep(nanoseconds: .second * 3) - takeSnapshot(name: "Notification - 2") - - tapTab(app: app, tab: "Notification") - try await Task.sleep(nanoseconds: .second * 3) - takeSnapshot(name: "Notification - 3") - } - - func testSnapshotProfile() async throws { - let username = ProcessInfo.processInfo.environment["username_snapshot"] ?? "Gargron" - - let app = XCUIApplication() - app.launch() - - // Go to Search tab - tapTab(app: app, tab: "Search") - - // Tap and search user - let searchField = app.navigationBars.searchFields.firstMatch - XCTAssert(searchField.waitForExistence(timeout: 5)) - searchField.tap() - searchField.typeText(username) - - // Tap the cell and display user profile - let cell = app.tables.cells.firstMatch - XCTAssert(cell.waitForExistence(timeout: 5)) - cell.tap() - - try await Task.sleep(nanoseconds: .second * 5) - - takeSnapshot(name: "Profile") - } - - func testSnapshotCompose() async throws { - let app = XCUIApplication() - app.launch() - - // open Compose scene - let composeBarButtonItem = app.navigationBars.buttons["Compose"].firstMatch - let composeCollectionViewCell = app.collectionViews.cells["Compose"] - if composeBarButtonItem.waitForExistence(timeout: 5) { - composeBarButtonItem.tap() - } else if composeCollectionViewCell.waitForExistence(timeout: 5) { - composeCollectionViewCell.tap() - } else { - XCTFail() + // pass -1 to debug test case + guard count >= 0 else { + app.launch() + try await task(app) + takeSnapshot(name: name) + return } - - // type text - let textView = app.textViews.firstMatch - XCTAssert(textView.waitForExistence(timeout: 5)) - textView.tap() - textView.typeText("Look at that view! #Athens ") - // tap Add Attachment toolbar button - let addAttachmentButton = app.buttons["Add Attachment"].firstMatch - XCTAssert(addAttachmentButton.waitForExistence(timeout: 5)) - addAttachmentButton.tap() + // Light Mode + for index in 0.. 1.6.1' # DEBUG - pod 'FLEX', '~> 4.4.0', :configurations => ['Debug'] + pod 'FLEX', '~> 4.4.0', :configurations => ['Debug', "Release Snapshot"] target 'MastodonTests' do inherit! :search_paths diff --git a/Podfile.lock b/Podfile.lock index 0593a8e24..336caf883 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -40,6 +40,6 @@ SPEC CHECKSUMS: SwiftGen: 67860cc7c3cfc2ed25b9b74cfd55495fc89f9108 "UITextField+Shake": 298ac5a0f239d731bdab999b19b628c956ca0ac3 -PODFILE CHECKSUM: 1426a4b78d8d711a5ae7600b9deea8986ddfdf7d +PODFILE CHECKSUM: c471d1f9c923dc63bf8684415c79b85adb2ac36b COCOAPODS: 1.11.2