diff --git a/Podfile b/Podfile index 85d58a7..7555a03 100644 --- a/Podfile +++ b/Podfile @@ -36,8 +36,8 @@ target 'SynthReel' do pod 'Adjust' # # AdMob SDK -# pod 'Google-Mobile-Ads-SDK' + pod 'Google-Mobile-Ads-SDK' # # # AppLovin SDK -# pod 'AppLovinSDK' + pod 'AppLovinSDK' end diff --git a/SynthReel.xcodeproj/project.pbxproj b/SynthReel.xcodeproj/project.pbxproj index c02d323..9976690 100644 --- a/SynthReel.xcodeproj/project.pbxproj +++ b/SynthReel.xcodeproj/project.pbxproj @@ -205,6 +205,25 @@ 85AE54782EE8106F0058FEA3 /* SRApnsAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85AE54772EE8106F0058FEA3 /* SRApnsAlert.swift */; }; 85AE547A2EE8154A0058FEA3 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 85AE54792EE8154A0058FEA3 /* GoogleService-Info.plist */; }; 85AE549C2EE81E730058FEA3 /* SRAppStartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85AE549B2EE81E730058FEA3 /* SRAppStartViewController.swift */; }; + 85DFB3B12EE957A800CBD0FC /* SRUpdatesAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85DFB3B02EE957A800CBD0FC /* SRUpdatesAlert.swift */; }; + 85DFB3B32EE95EFB00CBD0FC /* SRVersionUpdateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85DFB3B22EE95EFB00CBD0FC /* SRVersionUpdateModel.swift */; }; + 85DFB3B52EE96B8600CBD0FC /* SRLogoutAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85DFB3B42EE96B8600CBD0FC /* SRLogoutAlert.swift */; }; + 85DFB3B72EE9766000CBD0FC /* SRRemoveCollectAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85DFB3B62EE9766000CBD0FC /* SRRemoveCollectAlert.swift */; }; + 85DFB3BB2EE97A1E00CBD0FC /* SRWalletViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85DFB3BA2EE97A1E00CBD0FC /* SRWalletViewController.swift */; }; + 85DFB3BF2EE991D400CBD0FC /* SROpenAdManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85DFB3BE2EE991D400CBD0FC /* SROpenAdManager.swift */; }; + 85DFB3CE2EEA51A900CBD0FC /* VPBannerAdManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85DFB3C42EEA51A900CBD0FC /* VPBannerAdManager.swift */; }; + 85DFB3CF2EEA51A900CBD0FC /* VPAdInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85DFB3CA2EEA51A900CBD0FC /* VPAdInfo.swift */; }; + 85DFB3D02EEA51A900CBD0FC /* VPAdManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85DFB3CB2EEA51A900CBD0FC /* VPAdManager.swift */; }; + 85DFB3D12EEA51A900CBD0FC /* VPGoogleRewardedAd.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85DFB3C72EEA51A900CBD0FC /* VPGoogleRewardedAd.swift */; }; + 85DFB3D22EEA51A900CBD0FC /* VPApplovinRewardedAd.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85DFB3C62EEA51A900CBD0FC /* VPApplovinRewardedAd.swift */; }; + 85DFB3D32EEA51A900CBD0FC /* VPApplovinBannerAd.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85DFB3C32EEA51A900CBD0FC /* VPApplovinBannerAd.swift */; }; + 85DFB3D42EEA51A900CBD0FC /* VPStatAdModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85DFB3CC2EEA51A900CBD0FC /* VPStatAdModel.swift */; }; + 85DFB3D52EEA51A900CBD0FC /* VPAppOpenAdManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85DFB3C12EEA51A900CBD0FC /* VPAppOpenAdManager.swift */; }; + 85DFB3D62EEA51A900CBD0FC /* VPRewardedAdManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85DFB3C82EEA51A900CBD0FC /* VPRewardedAdManager.swift */; }; + 85DFB3D72EEA51A900CBD0FC /* VPApplovinAppOpenAd.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85DFB3C02EEA51A900CBD0FC /* VPApplovinAppOpenAd.swift */; }; + 85DFB3D92EEA523B00CBD0FC /* SRAdManger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85DFB3D82EEA523B00CBD0FC /* SRAdManger.swift */; }; + 85DFB3DD2EEA5D5A00CBD0FC /* SRAdmobOpenAd.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85DFB3DC2EEA5D5A00CBD0FC /* SRAdmobOpenAd.swift */; }; + 85DFB3DF2EEA671C00CBD0FC /* SRAppOpenAdViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85DFB3DE2EEA671C00CBD0FC /* SRAppOpenAdViewController.swift */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -534,6 +553,25 @@ 85AE54822EE818180058FEA3 /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; }; 85AE549A2EE8183A0058FEA3 /* SynthReel.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SynthReel.entitlements; sourceTree = ""; }; 85AE549B2EE81E730058FEA3 /* SRAppStartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRAppStartViewController.swift; sourceTree = ""; }; + 85DFB3B02EE957A800CBD0FC /* SRUpdatesAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRUpdatesAlert.swift; sourceTree = ""; }; + 85DFB3B22EE95EFB00CBD0FC /* SRVersionUpdateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRVersionUpdateModel.swift; sourceTree = ""; }; + 85DFB3B42EE96B8600CBD0FC /* SRLogoutAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRLogoutAlert.swift; sourceTree = ""; }; + 85DFB3B62EE9766000CBD0FC /* SRRemoveCollectAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRRemoveCollectAlert.swift; sourceTree = ""; }; + 85DFB3BA2EE97A1E00CBD0FC /* SRWalletViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRWalletViewController.swift; sourceTree = ""; }; + 85DFB3BE2EE991D400CBD0FC /* SROpenAdManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SROpenAdManager.swift; sourceTree = ""; }; + 85DFB3C02EEA51A900CBD0FC /* VPApplovinAppOpenAd.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPApplovinAppOpenAd.swift; sourceTree = ""; }; + 85DFB3C12EEA51A900CBD0FC /* VPAppOpenAdManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPAppOpenAdManager.swift; sourceTree = ""; }; + 85DFB3C32EEA51A900CBD0FC /* VPApplovinBannerAd.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPApplovinBannerAd.swift; sourceTree = ""; }; + 85DFB3C42EEA51A900CBD0FC /* VPBannerAdManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPBannerAdManager.swift; sourceTree = ""; }; + 85DFB3C62EEA51A900CBD0FC /* VPApplovinRewardedAd.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPApplovinRewardedAd.swift; sourceTree = ""; }; + 85DFB3C72EEA51A900CBD0FC /* VPGoogleRewardedAd.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPGoogleRewardedAd.swift; sourceTree = ""; }; + 85DFB3C82EEA51A900CBD0FC /* VPRewardedAdManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPRewardedAdManager.swift; sourceTree = ""; }; + 85DFB3CA2EEA51A900CBD0FC /* VPAdInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPAdInfo.swift; sourceTree = ""; }; + 85DFB3CB2EEA51A900CBD0FC /* VPAdManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPAdManager.swift; sourceTree = ""; }; + 85DFB3CC2EEA51A900CBD0FC /* VPStatAdModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPStatAdModel.swift; sourceTree = ""; }; + 85DFB3D82EEA523B00CBD0FC /* SRAdManger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRAdManger.swift; sourceTree = ""; }; + 85DFB3DC2EEA5D5A00CBD0FC /* SRAdmobOpenAd.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRAdmobOpenAd.swift; sourceTree = ""; }; + 85DFB3DE2EEA671C00CBD0FC /* SRAppOpenAdViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRAppOpenAdViewController.swift; sourceTree = ""; }; AA88214030574193B51DE563 /* Pods-SynthReel.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SynthReel.release.xcconfig"; path = "Target Support Files/Pods-SynthReel/Pods-SynthReel.release.xcconfig"; sourceTree = ""; }; F9255BF4D4B1CFDDB5CFFB43 /* Pods_SynthReel.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SynthReel.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -604,6 +642,7 @@ 03B1A8442EC5CBBB006C353F /* SRNavigationController.swift */, 03B1A8462EC5CBCF006C353F /* SRViewController.swift */, 85AE549B2EE81E730058FEA3 /* SRAppStartViewController.swift */, + 85DFB3DE2EEA671C00CBD0FC /* SRAppOpenAdViewController.swift */, ); path = ViewController; sourceTree = ""; @@ -835,6 +874,8 @@ 03E9A7D22EC47204000D1067 /* Base */ = { isa = PBXGroup; children = ( + 85DFB3CD2EEA51A900CBD0FC /* AdManager */, + 85DFB3BC2EE9919000CBD0FC /* Admanger */, 85AE54742EE80D7A0058FEA3 /* Model */, 3754ACE22ED93E04009EBCAD /* webview */, 03B1A8412EC5CB4F006C353F /* ViewController */, @@ -850,6 +891,7 @@ 03E9A7D32EC4720F000D1067 /* Class */ = { isa = PBXGroup; children = ( + 85DFB3B82EE979FE00CBD0FC /* wallet */, 3754ACFF2EDA8A43009EBCAD /* Login */, 3754ACF92ED9A34E009EBCAD /* Store */, 3754ACDD2ED93C14009EBCAD /* Coinpack */, @@ -1020,6 +1062,9 @@ children = ( 3754ACD02ED81F55009EBCAD /* SRBaseAlert.swift */, 85AE54772EE8106F0058FEA3 /* SRApnsAlert.swift */, + 85DFB3B02EE957A800CBD0FC /* SRUpdatesAlert.swift */, + 85DFB3B42EE96B8600CBD0FC /* SRLogoutAlert.swift */, + 85DFB3B62EE9766000CBD0FC /* SRRemoveCollectAlert.swift */, ); path = Alert; sourceTree = ""; @@ -1586,10 +1631,102 @@ isa = PBXGroup; children = ( 85AE54752EE80D900058FEA3 /* SROpenAppModel.swift */, + 85DFB3B22EE95EFB00CBD0FC /* SRVersionUpdateModel.swift */, ); path = Model; sourceTree = ""; }; + 85DFB3B82EE979FE00CBD0FC /* wallet */ = { + isa = PBXGroup; + children = ( + 85DFB3B92EE97A0700CBD0FC /* VC */, + ); + path = wallet; + sourceTree = ""; + }; + 85DFB3B92EE97A0700CBD0FC /* VC */ = { + isa = PBXGroup; + children = ( + 85DFB3BA2EE97A1E00CBD0FC /* SRWalletViewController.swift */, + ); + path = VC; + sourceTree = ""; + }; + 85DFB3BC2EE9919000CBD0FC /* Admanger */ = { + isa = PBXGroup; + children = ( + 85DFB3DB2EEA563700CBD0FC /* RewardAd */, + 85DFB3DA2EEA562700CBD0FC /* BannerAd */, + 85DFB3BD2EE991B400CBD0FC /* OpenAd */, + 85DFB3D82EEA523B00CBD0FC /* SRAdManger.swift */, + ); + path = Admanger; + sourceTree = ""; + }; + 85DFB3BD2EE991B400CBD0FC /* OpenAd */ = { + isa = PBXGroup; + children = ( + 85DFB3BE2EE991D400CBD0FC /* SROpenAdManager.swift */, + ); + path = OpenAd; + sourceTree = ""; + }; + 85DFB3C22EEA51A900CBD0FC /* AppOpen */ = { + isa = PBXGroup; + children = ( + 85DFB3C02EEA51A900CBD0FC /* VPApplovinAppOpenAd.swift */, + 85DFB3C12EEA51A900CBD0FC /* VPAppOpenAdManager.swift */, + ); + path = AppOpen; + sourceTree = ""; + }; + 85DFB3C52EEA51A900CBD0FC /* Banner */ = { + isa = PBXGroup; + children = ( + 85DFB3C32EEA51A900CBD0FC /* VPApplovinBannerAd.swift */, + 85DFB3C42EEA51A900CBD0FC /* VPBannerAdManager.swift */, + ); + path = Banner; + sourceTree = ""; + }; + 85DFB3C92EEA51A900CBD0FC /* Rewarded */ = { + isa = PBXGroup; + children = ( + 85DFB3C62EEA51A900CBD0FC /* VPApplovinRewardedAd.swift */, + 85DFB3C72EEA51A900CBD0FC /* VPGoogleRewardedAd.swift */, + 85DFB3C82EEA51A900CBD0FC /* VPRewardedAdManager.swift */, + ); + path = Rewarded; + sourceTree = ""; + }; + 85DFB3CD2EEA51A900CBD0FC /* AdManager */ = { + isa = PBXGroup; + children = ( + 85DFB3C22EEA51A900CBD0FC /* AppOpen */, + 85DFB3C52EEA51A900CBD0FC /* Banner */, + 85DFB3C92EEA51A900CBD0FC /* Rewarded */, + 85DFB3CA2EEA51A900CBD0FC /* VPAdInfo.swift */, + 85DFB3CB2EEA51A900CBD0FC /* VPAdManager.swift */, + 85DFB3CC2EEA51A900CBD0FC /* VPStatAdModel.swift */, + ); + path = AdManager; + sourceTree = ""; + }; + 85DFB3DA2EEA562700CBD0FC /* BannerAd */ = { + isa = PBXGroup; + children = ( + 85DFB3DC2EEA5D5A00CBD0FC /* SRAdmobOpenAd.swift */, + ); + path = BannerAd; + sourceTree = ""; + }; + 85DFB3DB2EEA563700CBD0FC /* RewardAd */ = { + isa = PBXGroup; + children = ( + ); + path = RewardAd; + sourceTree = ""; + }; 8CAFCEC2C631CAE75726D90C /* Pods */ = { isa = PBXGroup; children = ( @@ -1622,6 +1759,7 @@ 03E9A7A52EC4716A000D1067 /* Resources */, 92A47CFFAED31670C9452A17 /* [CP] Embed Pods Frameworks */, 85AE54992EE818190058FEA3 /* Embed Foundation Extensions */, + E78E68FAEB858A89EA05FB90 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -1729,6 +1867,23 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + E78E68FAEB858A89EA05FB90 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-SynthReel/Pods-SynthReel-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-SynthReel/Pods-SynthReel-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SynthReel/Pods-SynthReel-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -1740,6 +1895,7 @@ 85AE54682EE7F7940058FEA3 /* SRCoinPackCanReceiveModel.swift in Sources */, 03E9A7EA2EC4995D000D1067 /* SRKeychain.swift in Sources */, 03E9A7D92EC47B90000D1067 /* SRNetworkReachableManager.swift in Sources */, + 85DFB3B32EE95EFB00CBD0FC /* SRVersionUpdateModel.swift in Sources */, 3754ACF82ED9A32C009EBCAD /* SRCoinPackHeaderView.swift in Sources */, 3754ACD72ED82774009EBCAD /* SRDetailRecommendCell.swift in Sources */, 370D2F2D2ED5AA9700571E77 /* SRViralHitCell.swift in Sources */, @@ -1750,6 +1906,7 @@ 03B1A8E12EC6D6D3006C353F /* SRHomeMenuDataSource.swift in Sources */, 03E9A7F82EC4AA54000D1067 /* SRUserDefaultsKey.swift in Sources */, 3754B0312EE2C9D4009EBCAD /* SRVideoRechargeView.swift in Sources */, + 85DFB3BB2EE97A1E00CBD0FC /* SRWalletViewController.swift in Sources */, 3754AF1C2EDEF112009EBCAD /* SRStoreCoinsView.swift in Sources */, 03B1A8452EC5CBBB006C353F /* SRNavigationController.swift in Sources */, 85AE54712EE80AFE0058FEA3 /* adjustManger.swift in Sources */, @@ -1760,6 +1917,17 @@ 3754B0112EE1248D009EBCAD /* SRCoinsPackBuyView.swift in Sources */, 03B1A9462ECC5679006C353F /* SRSearchResultCell.swift in Sources */, 03B1A9502ECEB4E6006C353F /* SRRecommendPlayerViewController.swift in Sources */, + 85DFB3CE2EEA51A900CBD0FC /* VPBannerAdManager.swift in Sources */, + 85DFB3CF2EEA51A900CBD0FC /* VPAdInfo.swift in Sources */, + 85DFB3D02EEA51A900CBD0FC /* VPAdManager.swift in Sources */, + 85DFB3DD2EEA5D5A00CBD0FC /* SRAdmobOpenAd.swift in Sources */, + 85DFB3D12EEA51A900CBD0FC /* VPGoogleRewardedAd.swift in Sources */, + 85DFB3D22EEA51A900CBD0FC /* VPApplovinRewardedAd.swift in Sources */, + 85DFB3D32EEA51A900CBD0FC /* VPApplovinBannerAd.swift in Sources */, + 85DFB3D42EEA51A900CBD0FC /* VPStatAdModel.swift in Sources */, + 85DFB3D52EEA51A900CBD0FC /* VPAppOpenAdManager.swift in Sources */, + 85DFB3D62EEA51A900CBD0FC /* VPRewardedAdManager.swift in Sources */, + 85DFB3D72EEA51A900CBD0FC /* VPApplovinAppOpenAd.swift in Sources */, 03B1A83E2EC5C91E006C353F /* SRTool.swift in Sources */, 03B1A9172ECAF14F006C353F /* SRHomeHotView.swift in Sources */, 03B1A8FD2EC81C62006C353F /* SRHomeBannerCell.swift in Sources */, @@ -1781,6 +1949,7 @@ 3754B0152EE12521009EBCAD /* SRCoinPackConfirmView.swift in Sources */, 370D2F2F2ED5AB2500571E77 /* SRViralHitController.swift in Sources */, 3754ACDA2ED8374D009EBCAD /* SRPagerViewTransformer.swift in Sources */, + 85DFB3BF2EE991D400CBD0FC /* SROpenAdManager.swift in Sources */, 3754AF282EDEF3CC009EBCAD /* SRPackCoinViewCell.swift in Sources */, 3754ACFE2ED9A3A0009EBCAD /* SRCoinsPackReceiveModel.swift in Sources */, 3754ACF22ED975B9009EBCAD /* SRRewardController.swift in Sources */, @@ -1793,7 +1962,9 @@ 03B1A8F32EC809C5006C353F /* SRHomeHeaderView.swift in Sources */, 03B1A9482ECC6669006C353F /* SRProgressView.swift in Sources */, 370D2F1A2ED45CCA00571E77 /* SRUserSettingCell.swift in Sources */, + 85DFB3B72EE9766000CBD0FC /* SRRemoveCollectAlert.swift in Sources */, 03B1A91D2ECB2424006C353F /* UIScrollView+SRAdd.swift in Sources */, + 85DFB3D92EEA523B00CBD0FC /* SRAdManger.swift in Sources */, 3754ACE62ED93E7C009EBCAD /* SRWebView.swift in Sources */, 3754ACEE2ED945A1009EBCAD /* Dictionary+SRAdd.swift in Sources */, 03E9A7C92EC47177000D1067 /* AppDelegate.swift in Sources */, @@ -1822,6 +1993,7 @@ 03B1A9152ECAEE63006C353F /* SRHomeViralHitsCell.swift in Sources */, 85AE546E2EE809850058FEA3 /* AppDelegate+SRAPNS.swift in Sources */, 03B1A8472EC5CBCF006C353F /* SRViewController.swift in Sources */, + 85DFB3B52EE96B8600CBD0FC /* SRLogoutAlert.swift in Sources */, 3754AF192EDEF0AF009EBCAD /* SRStoreController.swift in Sources */, 370D2F052ED3FEE700571E77 /* SRHistoryCell.swift in Sources */, 3754AF202EDEF133009EBCAD /* SRStoreVipView.swift in Sources */, @@ -1838,6 +2010,7 @@ 3754ACEC2ED943AB009EBCAD /* SRAppWebViewController.swift in Sources */, 03B1A9442ECC4ED9006C353F /* SRSearchResultView.swift in Sources */, 3754ACBF2ED5B839009EBCAD /* SRNavgationTitleView.swift in Sources */, + 85DFB3B12EE957A800CBD0FC /* SRUpdatesAlert.swift in Sources */, 3754B00B2EE12040009EBCAD /* SRCoinsPackClaimListView.swift in Sources */, 03B1A8FF2EC81C92006C353F /* SRImageView.swift in Sources */, 3754B00F2EE120C5009EBCAD /* SRCoinsPackClaimListCell.swift in Sources */, @@ -1874,6 +2047,7 @@ 3754AF042EDED773009EBCAD /* SRIapManager.swift in Sources */, 03B1A92E2ECC0D7E006C353F /* SRShortDetailControlView.swift in Sources */, 03B1A9382ECC210D006C353F /* SRSearchRecordCell.swift in Sources */, + 85DFB3DF2EEA671C00CBD0FC /* SRAppOpenAdViewController.swift in Sources */, 03E9A7D72EC47A23000D1067 /* SRResponseCryptor.swift in Sources */, 03B1A8502EC5DB2E006C353F /* SRHomeViewController.swift in Sources */, 03B1A8E52EC715E1006C353F /* SRHomeApi.swift in Sources */, @@ -1968,7 +2142,7 @@ CODE_SIGN_ENTITLEMENTS = SynthReel/SynthReel.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1.1; + CURRENT_PROJECT_VERSION = 1.2; DEVELOPMENT_TEAM = 9JR2Y32ZU3; EXCLUDED_ARCHS = ""; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; @@ -2012,7 +2186,7 @@ CODE_SIGN_ENTITLEMENTS = SynthReel/SynthReel.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1.1; + CURRENT_PROJECT_VERSION = 1.2; DEVELOPMENT_TEAM = 9JR2Y32ZU3; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = SynthReel/Source/Info.plist; diff --git a/SynthReel/Base/API/SRUserApi.swift b/SynthReel/Base/API/SRUserApi.swift index f6d36bb..dedc235 100644 --- a/SynthReel/Base/API/SRUserApi.swift +++ b/SynthReel/Base/API/SRUserApi.swift @@ -124,4 +124,17 @@ struct SRUserApi { } } } + + static func requestVersionUpdateData() async -> SRVersionUpdateModel?{ + await withCheckedContinuation { continuation in + var param = SRNetwork.Parameters(path: "/customer/versionControl") + param.method = .get + SRNetwork.request(parameters: param) { (response: SRNetwork.Response) in + continuation.resume(returning: response.data) + } + } + } + + + } diff --git a/SynthReel/Base/AdManager/AppOpen/VPAppOpenAdManager.swift b/SynthReel/Base/AdManager/AppOpen/VPAppOpenAdManager.swift new file mode 100644 index 0000000..e763c36 --- /dev/null +++ b/SynthReel/Base/AdManager/AppOpen/VPAppOpenAdManager.swift @@ -0,0 +1,225 @@ +//// +//// VPAppOpenAdManager.swift +//// Veloria +//// +//// Created by 湖南秦九 on 2025/7/15. +//// +// +//import UIKit +// +// +//@objc protocol VPAppOpenAdManagerDelegate: NSObjectProtocol { +// +// ///广告加载成功 +// @objc optional func appOpenAdManagerDidLoadFinish(adManager: VPAppOpenAdManager) +// ///广告加载失败 +// @objc optional func appOpenAdManager(adManager: VPAppOpenAdManager, didLoadFail error: Error) +// ///广告展示失败 +// @objc optional func appOpenAdManager(adManager: VPAppOpenAdManager, didDisplayFail error: Error) +// ///广告被展示 +// @objc optional func appOpenAdManagerDidShow(adManager: VPAppOpenAdManager) +// ///广告被关闭 +// @objc optional func appOpenAdManagerDidDismiss(adManager: VPAppOpenAdManager) +// ///广告被点击 +// @objc optional func appOpenAdManagerDidClick(adManager: VPAppOpenAdManager) +// ///其它错误 +// @objc optional func appOpenAdManager(adManager: VPAppOpenAdManager, didOtherFail error: Error) +// +//} +// +// +//@objc protocol VPAppOpenAdDelegate: NSObjectProtocol { +// +// ///广告加载失败 +// @objc optional func appOpenAd(ad: VPAppOpenAd, didLoadFail error: Error) +// ///广告加载成功 +// @objc optional func appOpenAdDidLoadFinish(ad: VPAppOpenAd) +// ///广告展示失败 +// @objc optional func appOpenAd(ad: VPAppOpenAd, didDisplayFail error: Error) +// ///广告被展示 +// @objc optional func appOpenAdDidShow(ad: VPAppOpenAd) +// ///广告被关闭 +// @objc optional func appOpenAdDidDismiss(ad: VPAppOpenAd) +// ///广告被点击 +// @objc optional func appOpenAdDidClick(ad: VPAppOpenAd) +//} +// +//@objc protocol VPAppOpenAd: NSObjectProtocol { +// +// weak var delegate: VPAppOpenAdDelegate? { get set } +// +// var adPlatformKey: String { get } +// +// var adUnitID: String { get } +// +// var isReady: Bool { get } +// +// func loadAd() +// func showAd() +// +//} +// +//class VPAppOpenAdManager: NSObject { +// +// static let manager = VPAppOpenAdManager() +// +// weak var delegate: VPAppOpenAdManagerDelegate? +// +// private(set) var appOpenAd: VPAppOpenAd? { +// didSet { +// oldValue?.delegate = nil +// appOpenAd?.delegate = self +// } +// } +// +// private var isLoading = false +// private var isShowing = false +// ///允许自动展示 +// private var needAutoShow = false +// +// private var timeOutTimer: Timer? +// +// private var adsDate: Date? +// +// deinit { +// NotificationCenter.default.removeObserver(self) +// } +// +// override init() { +// super.init() +// NotificationCenter.default.addObserver(self, selector: #selector(didEnterBackgroundNotification), name: UIApplication.didEnterBackgroundNotification, object: nil) +// } +// +// func showAdIfAvailable() { +// +// if self.appOpenAd?.isReady == true { +// self.showAd() +// } else { +// self.timeOutTimer = Timer.scheduledTimer(timeInterval: 5, target: (self), selector: #selector(handleTimeOutTimer), userInfo: nil, repeats: false) +// +// self.needAutoShow = true +// self.loadAd() +// } +// } +// +// func loadAd() { +// guard !isLoading else { return } +// +// self.isLoading = true +// appOpenAd = VPApplovinAppOpenAd() +// appOpenAd?.loadAd() +// } +// +// func showAd() { +// guard self.appOpenAd?.isReady == true else { return } +// guard !self.isShowing else { return } +// +// +// self.isShowing = true +// self.appOpenAd?.showAd() +// } +// +// @objc private func handleTimeOutTimer() { +// self.needAutoShow = false +// cleanTimer() +// +// let error = NSError(domain: "time-out", code: -1) +// requestStatAd(type: "load_failed", errorMsg: error.localizedDescription) +// self.delegate?.appOpenAdManager?(adManager: self, didOtherFail: error) +// } +// +// private func cleanTimer() { +// self.timeOutTimer?.invalidate() +// self.timeOutTimer = nil +// } +// +// private func clean() { +// appOpenAd = nil +// delegate = nil +// isShowing = false +// self.adsDate = nil +// } +//} +// +////MARK: -------------- VPAppOpenAdDelegate -------------- +//extension VPAppOpenAdManager: VPAppOpenAdDelegate { +// +// ///广告加载失败 +// func appOpenAd(ad: VPAppOpenAd, didLoadFail error: Error) { +// cleanTimer() +// isLoading = false +// requestStatAd(type: "load_failed", errorMsg: error.localizedDescription) +// +// self.delegate?.appOpenAdManager?(adManager: self, didLoadFail: error) +// +// clean() +// } +// ///广告加载成功 +// func appOpenAdDidLoadFinish(ad: VPAppOpenAd) { +// cleanTimer() +// self.isLoading = false +// self.delegate?.appOpenAdManagerDidLoadFinish?(adManager: self) +// +// if needAutoShow { +// self.needAutoShow = false +// self.showAd() +// } +// +// } +// ///广告展示失败 +// func appOpenAd(ad: VPAppOpenAd, didDisplayFail error: Error) { +// requestStatAd(type: "show_failed", errorMsg: error.localizedDescription) +// self.delegate?.appOpenAdManager?(adManager: self, didDisplayFail: error) +// clean() +// } +// ///广告被展示 +// func appOpenAdDidShow(ad: VPAppOpenAd) { +// adsDate = Date() +// requestStatAd(type: "start", errorMsg: nil) +// self.delegate?.appOpenAdManagerDidShow?(adManager: self) +// } +// ///广告被关闭 +// func appOpenAdDidDismiss(ad: VPAppOpenAd) { +// requestStatAd(type: "close", errorMsg: nil) +// self.delegate?.appOpenAdManagerDidDismiss?(adManager: self) +// clean() +// } +// ///广告被点击 +// func appOpenAdDidClick(ad: VPAppOpenAd) { +// requestStatAd(type: "click", errorMsg: nil) +// self.delegate?.appOpenAdManagerDidClick?(adManager: self) +// } +//} +// +// +//extension VPAppOpenAdManager { +// +// private func requestStatAd(type: String, errorMsg: String?) { +// guard let appOpenAd = self.appOpenAd else { return } +// +// var seconds = 0 +// if let adsDate = self.adsDate { +// if type == "click" || type == "close" { +// seconds = Int(Date().timeIntervalSince(adsDate)) +// } +// } +// +// +// let model = VPStatAdModel() +// model.type = type +// model.view_seconds = seconds +// model.ads_id = appOpenAd.adUnitID +// model.ad_platform_key = VPAdPlatformKey(rawValue: appOpenAd.adPlatformKey) +// model.error_msg = errorMsg +// model.scene = .splash +// +//// VPStatAPI.requestStatAd(model: model) +// } +// +// +// @objc private func didEnterBackgroundNotification() { +// guard self.isShowing else { return } +// +// self.requestStatAd(type: "Interrupt", errorMsg: nil) +// } +//} diff --git a/SynthReel/Base/AdManager/AppOpen/VPApplovinAppOpenAd.swift b/SynthReel/Base/AdManager/AppOpen/VPApplovinAppOpenAd.swift new file mode 100644 index 0000000..89cc27a --- /dev/null +++ b/SynthReel/Base/AdManager/AppOpen/VPApplovinAppOpenAd.swift @@ -0,0 +1,84 @@ +//// +//// VPApplovinAppOpenAd.swift +//// Veloria +//// +//// Created by 湖南秦九 on 2025/7/15. +//// +// +//import UIKit +//#if canImport(AppLovinSDK) +//import AppLovinSDK +//#endif +// +//class VPApplovinAppOpenAd: NSObject, VPAppOpenAd { +// +// +// +// private lazy var appOpenAd = MAAppOpenAd(adUnitIdentifier: adUnitID) +// +// weak var delegate: (any VPAppOpenAdDelegate)? +// +// var adPlatformKey: String { +// return VPAdPlatformKey.applovin.rawValue +// } +// +// var adUnitID: String { +// return VPAdManager.applovin_appOpenAdUnitID +// } +// +// var isReady: Bool { +// if ALSdk.shared().isInitialized && appOpenAd.isReady { +// return true +// } else { +// return false +// } +// } +// +// func loadAd() { +// +// VPAdManager.initialize_applovinSdk { [weak self] in +// guard let self = self else { return } +// appOpenAd.delegate = self +// appOpenAd.load() +// } +// } +// +// func showAd() { +// guard isReady else { return } +// +// appOpenAd.show() +// } +//} +// +// +//extension VPApplovinAppOpenAd: MAAdDelegate { +// func didLoad(_ ad: MAAd) { +// self.delegate?.appOpenAdDidLoadFinish?(ad: self) +// } +// +// func didFailToLoadAd(forAdUnitIdentifier adUnitIdentifier: String, withError error: MAError) { +// let nsError = NSError(domain: error.message, code: error.code.rawValue) +// self.delegate?.appOpenAd?(ad: self, didLoadFail: nsError) +// } +// +// func didDisplay(_ ad: MAAd) { +// self.delegate?.appOpenAdDidShow?(ad: self) +// } +// +// func didHide(_ ad: MAAd) { +// self.delegate?.appOpenAdDidDismiss?(ad: self) +// } +// +// func didClick(_ ad: MAAd) { +// self.delegate?.appOpenAdDidClick?(ad: self) +// } +// +// func didFail(toDisplay ad: MAAd, withError error: MAError) { +// let nsError = NSError(domain: error.message, code: error.code.rawValue) +// self.delegate?.appOpenAd?(ad: self, didDisplayFail: nsError) +// } +// +// +// +//} +// diff --git a/SynthReel/Base/AdManager/Banner/VPApplovinBannerAd.swift b/SynthReel/Base/AdManager/Banner/VPApplovinBannerAd.swift new file mode 100644 index 0000000..9249e97 --- /dev/null +++ b/SynthReel/Base/AdManager/Banner/VPApplovinBannerAd.swift @@ -0,0 +1,88 @@ +//// +//// VPApplovinBannerAd.swift +//// Veloria +//// +//// Created by 湖南秦九 on 2025/7/17. +//// +// +//import UIKit +//import AppLovinSDK +// +//class VPApplovinBannerAd: NSObject, VPBannerAd { +// +// let size = CGSize.init(width: UIScreen.width, height: 59) +// +// var delegate: (any VPBannerAdDelegate)? +// +// ///是否加载过 +// private var isLoaded = false +// +// private(set) lazy var _adView: MAAdView = { +// let view = MAAdView(adUnitIdentifier: adUnitID) +// view.frame = .init(x: 0, y: 0, width: size.width, height: size.height) +// view.delegate = self +// return view +// }() +// +// var adView: UIView { +// return _adView +// } +// +// var adPlatformKey: String { +// return VPAdPlatformKey.applovin.rawValue +// } +// +// var adUnitID: String { +// return VPAdManager.applovin_bannerAdUnitID +// } +// +// func loadAd() { +// _adView.loadAd() +// } +//} +// +////MARK: -------------- MAAdViewAdDelegate -------------- +//extension VPApplovinBannerAd: MAAdViewAdDelegate { +// func didExpand(_ ad: MAAd) { +// +// } +// +// func didCollapse(_ ad: MAAd) { +// +// } +// +// func didLoad(_ ad: MAAd) { +// if !isLoaded { +// isLoaded = true +// self.delegate?.bannerAdDidLoadFinish?(bannerAd: self) +// } +// } +// +// func didFailToLoadAd(forAdUnitIdentifier adUnitIdentifier: String, withError error: MAError) { +// if !isLoaded { +// isLoaded = true +// let nsError = NSError(domain: error.message, code: error.code.rawValue) +// self.delegate?.bannerAd?(bannerAd: self, didLoadFail: nsError) +// } +// } +// +// func didDisplay(_ ad: MAAd) { +// self.delegate?.bannerAdDidShow?(bannerAd: self) +// } +// +// func didHide(_ ad: MAAd) { +// self.delegate?.bannerAdDidDismiss?(bannerAd: self) +// } +// +// func didClick(_ ad: MAAd) { +// self.delegate?.bannerAdDidClick?(ad: self) +// } +// +// func didFail(toDisplay ad: MAAd, withError error: MAError) { +// +// } +// +// +// +//} +// diff --git a/SynthReel/Base/AdManager/Banner/VPBannerAdManager.swift b/SynthReel/Base/AdManager/Banner/VPBannerAdManager.swift new file mode 100644 index 0000000..51bbcdf --- /dev/null +++ b/SynthReel/Base/AdManager/Banner/VPBannerAdManager.swift @@ -0,0 +1,131 @@ +//// +//// VPBannerAdManager.swift +//// Veloria +//// +//// Created by 湖南秦九 on 2025/7/15. +//// +// +//import UIKit +//#if canImport(AppLovinSDK) +//import AppLovinSDK +//#endif +// +// +//@objc protocol VPBannerAdDelegate: NSObjectProtocol { +// ///广告加载失败 +// @objc optional func bannerAd(bannerAd: VPBannerAd, didLoadFail error: Error) +// ///广告加载成功 +// @objc optional func bannerAdDidLoadFinish(bannerAd: VPBannerAd) +// ///广告被展示 +// @objc optional func bannerAdDidShow(bannerAd: VPBannerAd) +// ///广告被关闭 +// @objc optional func bannerAdDidDismiss(bannerAd: VPBannerAd) +// ///广告被点击 +// @objc optional func bannerAdDidClick(ad: VPBannerAd) +//} +// +//@objc protocol VPBannerAd: NSObjectProtocol { +// +// weak var delegate: VPBannerAdDelegate? { get set } +// +// var adView: UIView { get } +// +// var adPlatformKey: String { get } +// +// var adUnitID: String { get } +// +// func loadAd() +// +//} +// +//class VPBannerAdManager: NSObject { +// +// let size = CGSize.init(width: UIScreen.width, height: 59) +// +// var videoInfo: VPVideoInfoModel? +// +// private var adsDate: Date? +// +// private(set) lazy var bannerAd: VPBannerAd = { +// let ad = VPApplovinBannerAd() +// ad.delegate = self +// return ad +// }() +// +// var adView: UIView { +// return bannerAd.adView +// } +// +// deinit { +// NotificationCenter.default.removeObserver(self) +// } +// +// override init() { +// super.init() +// NotificationCenter.default.addObserver(self, selector: #selector(didEnterBackgroundNotification), name: UIApplication.didEnterBackgroundNotification, object: nil) +// +// bannerAd.loadAd() +// } +// +// +//} +// +////MARK: -------------- VPBannerAdDelegate -------------- +//extension VPBannerAdManager: VPBannerAdDelegate { +// +// ///广告加载失败 +// func bannerAd(bannerAd: VPBannerAd, didLoadFail error: Error) { +// requestStatAd(type: "load_failed", errorMsg: error.localizedDescription) +// } +// ///广告加载成功 +// func bannerAdDidLoadFinish(bannerAd: VPBannerAd) { +// adsDate = Date() +// requestStatAd(type: "start", errorMsg: nil) +// } +// ///广告被展示 +// func bannerAdDidShow(bannerAd: VPBannerAd) { +// +// } +// ///广告被关闭 +// func bannerAdDidDismiss(bannerAd: VPBannerAd) { +// requestStatAd(type: "close", errorMsg: nil) +// } +// ///广告被点击 +// func bannerAdDidClick(ad: VPBannerAd) { +// requestStatAd(type: "click", errorMsg: nil) +// } +// +//} +// +//extension VPBannerAdManager { +// +// func requestStatAd(type: String, errorMsg: String?) { +// +// var seconds = 0 +// if let adsDate = self.adsDate { +// if type == "click" || type == "close" { +// seconds = Int(Date().timeIntervalSince(adsDate)) +// } +// } +// +// if type == "close" && self.adsDate == nil { return } +// +// let model = VPStatAdModel() +// model.view_seconds = seconds +// model.type = type +// model.ads_id = bannerAd.adUnitID +// model.ad_platform_key = VPAdPlatformKey(rawValue: bannerAd.adPlatformKey) +// model.error_msg = errorMsg +// model.scene = .banner +// model.short_play_id = self.videoInfo?.short_play_id +// model.short_play_video_id = self.videoInfo?.short_play_video_id +// +// VPStatAPI.requestStatAd(model: model) +// } +// +// +// @objc private func didEnterBackgroundNotification() { +// +// self.requestStatAd(type: "Interrupt", errorMsg: nil) +// } +//} diff --git a/SynthReel/Base/AdManager/Rewarded/VPApplovinRewardedAd.swift b/SynthReel/Base/AdManager/Rewarded/VPApplovinRewardedAd.swift new file mode 100644 index 0000000..fada746 --- /dev/null +++ b/SynthReel/Base/AdManager/Rewarded/VPApplovinRewardedAd.swift @@ -0,0 +1,91 @@ +//// +//// VPApplovinRewardedAd.swift +//// Veloria +//// +//// Created by 湖南秦九 on 2025/7/15. +//// +// +//import UIKit +//#if canImport(AppLovinSDK) +//import AppLovinSDK +//#endif +// +//class VPApplovinRewardedAd: NSObject, VPRewardedAd { +// +// +//#if canImport(AppLovinSDK) +// private var rewardedAd: MARewardedAd? +//#endif +// +// weak var delegate: (any VPRewardedAdDelegate)? +// +// var adInfo: VPAdInfo? = nil +// +// var isReady: Bool { +//#if canImport(AppLovinSDK) +// return rewardedAd?.isReady ?? false +//#else +// return false +//#endif +// } +// +// func loadAd(adInfo: VPAdInfo) { +// self.adInfo = adInfo +//#if canImport(AppLovinSDK) +// rewardedAd = MARewardedAd.shared(withAdUnitIdentifier: adInfo.ads_id ?? "") +// rewardedAd?.delegate = self +// rewardedAd?.load() +//#endif +// } +// +// func showAd() { +//#if canImport(AppLovinSDK) +// if isReady { +// rewardedAd?.show() +// } +//#endif +// } +// +// +//} +// +//#if canImport(AppLovinSDK) +////MARK: -------------- MARewardedAdDelegate -------------- +//extension VPApplovinRewardedAd: MARewardedAdDelegate { +// +// func didLoad(_ ad: MAAd) { +// self.delegate?.rewardedAdDidLoadFinish?(ad: self) +// } +// +// func didFailToLoadAd(forAdUnitIdentifier adUnitIdentifier: String, withError error: MAError) { +// +// let nsError = NSError(domain: error.message, code: error.code.rawValue) +// self.delegate?.rewardedAd?(ad: self, didLoadFail: nsError) +// } +// +// func didDisplay(_ ad: MAAd) { +// self.delegate?.rewardedAdDidShow?(ad: self) +// } +// +// func didHide(_ ad: MAAd) { +// self.delegate?.rewardedAdDidDismiss?(ad: self) +// } +// +// func didClick(_ ad: MAAd) { +// self.delegate?.rewardedAdDidClick?(ad: self) +// } +// +// func didFail(toDisplay ad: MAAd, withError error: MAError) { +// let nsError = NSError(domain: error.message, code: error.code.rawValue) +// self.delegate?.rewardedAd?(ad: self, didDisplayFail: nsError) +// } +// +// func didRewardUser(for ad: MAAd, with reward: MAReward) { +// if let adInfo = self.adInfo { +// self.delegate?.rewardedAd?(ad: self, userDidEarnReward: adInfo) +// } +// } +//} +//#endif +// +// diff --git a/SynthReel/Base/AdManager/Rewarded/VPGoogleRewardedAd.swift b/SynthReel/Base/AdManager/Rewarded/VPGoogleRewardedAd.swift new file mode 100644 index 0000000..cdbe71d --- /dev/null +++ b/SynthReel/Base/AdManager/Rewarded/VPGoogleRewardedAd.swift @@ -0,0 +1,101 @@ +//// +//// VPGoogleRewardedAd.swift +//// Veloria +//// +//// Created by 湖南秦九 on 2025/7/14. +//// +// +//import UIKit +//#if canImport(GoogleMobileAds) +//import GoogleMobileAds +//#endif +// +//class VPGoogleRewardedAd: NSObject, VPRewardedAd { +// +// +// +//#if canImport(GoogleMobileAds) +// private var rewardedAd: RewardedAd? +//#endif +// +// weak var delegate: VPRewardedAdDelegate? +// +// var adInfo: VPAdInfo? +// +// var isReady: Bool { +//#if canImport(GoogleMobileAds) +// if rewardedAd != nil { +// return true +// } else { +// return false +// } +//#else +// return false +//#endif +// } +// +// func loadAd(adInfo: VPAdInfo) { +//#if canImport(GoogleMobileAds) +// self.adInfo = adInfo +//#if DEBUG +// adInfo.ads_id = VPAdManager.google_rewardedAdUnitID +//#endif +// let adUnitID = adInfo.ads_id ?? "" +// let request = Request() +// +// RewardedAd.load(with: adUnitID, request: request) { [weak self] rewardedAd, error in +// guard let self = self else { return } +// if let error = error { +// self.delegate?.rewardedAd?(ad: self, didLoadFail: error) +// return +// } +// self.rewardedAd = rewardedAd +// self.rewardedAd?.fullScreenContentDelegate = self +// self.delegate?.rewardedAdDidLoadFinish?(ad: self) +// } +//#endif +// } +// +// func showAd() { +//#if canImport(GoogleMobileAds) +// guard let rewardedAd = rewardedAd else { return } +// +// rewardedAd.present(from: nil) { [weak self] in +// guard let self = self else { return } +// guard let adInfo = self.adInfo else { return } +// self.delegate?.rewardedAd?(ad: self, userDidEarnReward: adInfo) +// } +//#endif +// } +// +// +// +//} +// +////MARK: -------------- FullScreenContentDelegate -------------- +//#if canImport(GoogleMobileAds) +//extension VPGoogleRewardedAd: FullScreenContentDelegate { +// +// /// Tells the delegate that the ad failed to present full screen content. +// func ad(_ ad: FullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) { +// self.delegate?.rewardedAd?(ad: self, didDisplayFail: error) +// } +// +// /// Tells the delegate that the ad will present full screen content. +// func adWillPresentFullScreenContent(_ ad: FullScreenPresentingAd) { +// print("====Ad will present full screen content.") +// self.delegate?.rewardedAdDidShow?(ad: self) +// } +// +// /// Tells the delegate that the ad dismissed full screen content. +// func adDidDismissFullScreenContent(_ ad: FullScreenPresentingAd) { +// print("====Ad did dismiss full screen content.") +// self.delegate?.rewardedAdDidDismiss?(ad: self) +// } +// +// func adDidRecordClick(_ ad: any FullScreenPresentingAd) { +// self.delegate?.rewardedAdDidClick?(ad: self) +// } +// +//} +//#endif diff --git a/SynthReel/Base/AdManager/Rewarded/VPRewardedAdManager.swift b/SynthReel/Base/AdManager/Rewarded/VPRewardedAdManager.swift new file mode 100644 index 0000000..731cc9c --- /dev/null +++ b/SynthReel/Base/AdManager/Rewarded/VPRewardedAdManager.swift @@ -0,0 +1,292 @@ +//// +//// VPRewardedAdManager.swift +//// Veloria +//// +//// Created by 湖南秦九 on 2025/7/14. +//// +// +//import UIKit +// +// +//@objc protocol VPRewardedAdManagerDelegate: NSObjectProtocol { +// +// ///发放奖励 +// @objc optional func rewardedAdManager(adManager: VPRewardedAdManager, userDidEarnReward adInfo: VPAdInfo) +// ///广告加载成功 +// @objc optional func rewardedAdManagerDidLoadFinish(adManager: VPRewardedAdManager) +// ///广告加载失败 +// @objc optional func rewardedAdManager(adManager: VPRewardedAdManager, didLoadFail error: Error) +// ///广告展示失败 +// @objc optional func rewardedAdManager(adManager: VPRewardedAdManager, didDisplayFail error: Error) +// ///广告被展示 +// @objc optional func rewardedAdManagerDidShow(adManager: VPRewardedAdManager) +// ///广告被关闭 +// @objc optional func rewardedAdManager(adManager: VPRewardedAdManager, didDismiss adInfo: VPAdInfo) +// ///广告被点击 +// @objc optional func rewardedAdManagerDidClick(adManager: VPRewardedAdManager) +// ///其它错误 +// @objc optional func rewardedAdManager(adManager: VPRewardedAdManager, didOtherFail error: Error) +// +//} +// +//@objc protocol VPRewardedAdDelegate: NSObjectProtocol { +// +// ///发放奖励 +// @objc optional func rewardedAd(ad: VPRewardedAd, userDidEarnReward adInfo: VPAdInfo) +// ///广告加载失败 +// @objc optional func rewardedAd(ad: VPRewardedAd, didLoadFail error: Error) +// ///广告加载成功 +// @objc optional func rewardedAdDidLoadFinish(ad: VPRewardedAd) +// ///广告展示失败 +// @objc optional func rewardedAd(ad: VPRewardedAd, didDisplayFail error: Error) +// ///广告被展示 +// @objc optional func rewardedAdDidShow(ad: VPRewardedAd) +// ///广告被关闭 +// @objc optional func rewardedAdDidDismiss(ad: VPRewardedAd) +// ///广告被点击 +// @objc optional func rewardedAdDidClick(ad: VPRewardedAd) +//} +// +//@objc protocol VPRewardedAd: NSObjectProtocol { +// +// weak var delegate: VPRewardedAdDelegate? { get set } +// var adInfo: VPAdInfo? { get set } +// var isReady: Bool { get } +// +// func loadAd(adInfo: VPAdInfo) +// func showAd() +// +//} +// +//class VPRewardedAdManager: NSObject { +// +// static let manager = VPRewardedAdManager() +// +// private weak var delegate: VPRewardedAdManagerDelegate? +// +// ///广告在加载中 +// private var isLoadingAd = false +// ///广告激活状态 +// private(set) var isEnable = true +// +// private var adInfo: VPAdInfo? +// +// private var adsDate: Date? +// ///统计场景 +// var statScene: VPStatAdModel.AdScene? +// var videoInfo: VPVideoInfoModel? +// +// var rewardedAd: VPRewardedAd? { +// didSet { +// rewardedAd?.delegate = self +// } +// } +// +// var isReady: Bool { +// return rewardedAd?.isReady ?? false +// } +// +// deinit { +// NotificationCenter.default.removeObserver(self) +// } +// +// override init() { +// super.init() +// NotificationCenter.default.addObserver(self, selector: #selector(didEnterBackgroundNotification), name: UIApplication.didEnterBackgroundNotification, object: nil) +// } +// +// func loadAd() { +// if isReady || isLoadingAd { return } +// +// self.isLoadingAd = true +// +// self.getAdInfo { [weak self] adInfo in +// guard let self = self else { return } +// +// switch adInfo.platform_key { +// case .google: +// let ad = VPGoogleRewardedAd() +// self.rewardedAd = ad +// ad.loadAd(adInfo: adInfo) +// +// case .applovin: +// let ad = VPApplovinRewardedAd() +// self.rewardedAd = ad +// ad.loadAd(adInfo: adInfo) +// +// default: +// self.adInfo = nil +// break +// } +// } +// +// } +// +// func showAd(delegate: VPRewardedAdManagerDelegate? = nil) { +// if isEnable && !isLoadingAd && !isReady {//没有任何广告,并且没有正在加载的广告,需要出发加载广告 +// loadAd() +// } +// +// if !isEnable || !isReady { +// VPToast.show(text: "veloria_no_ads_tip".localized) +// let error = NSError(domain: "veloria_no_ads_tip".localized, code: -1) +// self.delegate?.rewardedAdManager?(adManager: self, didOtherFail: error) +// return +// } +// +// guard let rewardedAd = self.rewardedAd else { return } +// self.delegate = delegate +// +// rewardedAd.showAd() +// } +// +// private func clean() { +// self.rewardedAd = nil +// self.statScene = nil +// self.videoInfo = nil +// self.delegate = nil +// } +//} +// +////MARK: -------------- VPRewardedAdDelegate -------------- +//extension VPRewardedAdManager: VPRewardedAdDelegate { +// +// ///发放奖励 +// func rewardedAd(ad: VPRewardedAd, userDidEarnReward adInfo: VPAdInfo) { +// self.requestStatAd(type: "reward", errorMsg: nil) +// self.delegate?.rewardedAdManager?(adManager: self, userDidEarnReward: adInfo) +// } +// ///广告加载失败 +// func rewardedAd(ad: VPRewardedAd, didLoadFail error: Error) { +// isEnable = false +// isLoadingAd = false +// +// self.requestStatAd(type: "load_failed", errorMsg: error.localizedDescription) +// self.delegate?.rewardedAdManager?(adManager: self, didLoadFail: error) +// +// self.clean() +// } +// ///广告加载成功 +// func rewardedAdDidLoadFinish(ad: VPRewardedAd) { +// isLoadingAd = false +// +// self.delegate?.rewardedAdManagerDidLoadFinish?(adManager: self) +// } +// ///广告展示失败 +// func rewardedAd(ad: VPRewardedAd, didDisplayFail error: Error) { +// +// self.requestStatAd(type: "show_failed", errorMsg: error.localizedDescription) +// self.delegate?.rewardedAdManager?(adManager: self, didDisplayFail: error) +// +// self.isEnable = false +// self.clean() +// +// /* +// if self.adInfo?.platform_key != .google { +// let adInfo = VPAdInfo() +// adInfo.platform_key = .google +// adInfo.ads_id = VPAdManager.google_rewardedAdUnitID +// +// let ad = VPGoogleRewardedAd() +// self.rewardedAd = ad +// ad.loadAd(adInfo: adInfo) +// +// } else { +// self.isEnable = false +// } +// */ +// +// } +// ///广告被展示 +// func rewardedAdDidShow(ad: VPRewardedAd) { +// self.adsDate = Date() +// +// self.requestStatAd(type: "start", errorMsg: nil) +// self.delegate?.rewardedAdManagerDidShow?(adManager: self) +// } +// ///广告被关闭 +// func rewardedAdDidDismiss(ad: VPRewardedAd) { +// +// +// var seconds = 0 +// if let adsDate = self.adsDate { +// seconds = Int(Date().timeIntervalSince(adsDate)) +// } +// +// +// self.requestStatAd(type: "close", seconds: seconds, errorMsg: nil) { [weak self] in +// guard let self = self else { return } +// if let adInfo = ad.adInfo { +// self.delegate?.rewardedAdManager?(adManager: self, didDismiss: adInfo) +// } +// +// self.clean() +// //加载新的广告 +// self.loadAd() +// } +// +// } +// +// ///广告被点击 +// func rewardedAdDidClick(ad: VPRewardedAd) { +// +// var seconds = 0 +// if let adsDate = self.adsDate { +// seconds = Int(Date().timeIntervalSince(adsDate)) +// } +// self.requestStatAd(type: "click", seconds: seconds, errorMsg: nil) +// +// self.delegate?.rewardedAdManagerDidClick?(adManager: self) +// } +// +//} +// +// +//extension VPRewardedAdManager { +// private func requestStatAd(type: String, seconds: Int = 0, errorMsg: String?, completer: (() -> Void)? = nil) { +// guard let adInfo = adInfo else { return } +// +// let model = VPStatAdModel() +// model.type = type +// model.ads_id = adInfo.ads_id +// model.view_seconds = seconds +// model.ad_platform_key = adInfo.platform_key +// model.error_msg = errorMsg +// model.scene = self.statScene +// model.short_play_id = self.videoInfo?.short_play_id +// model.short_play_video_id = self.videoInfo?.short_play_video_id +// +// VPStatAPI.requestStatAd(model: model) { finish in +// completer?() +// } +// } +// +// @objc private func didEnterBackgroundNotification() { +// if self.statScene == nil { return } +// +// self.requestStatAd(type: "Interrupt", seconds: 0, errorMsg: nil) +// } +// +// +// private func getAdInfo(completer: ((_ adInfo: VPAdInfo) -> Void)?) { +// +// if let adInfo = self.adInfo { +// completer?(adInfo) +// } +// VPAdAPI.requestShowAdInfo { [weak self] adInfo in +// guard let self = self else { return } +// +// if let adInfo = adInfo { +// self.adInfo = adInfo +// completer?(adInfo) +// } else { +// let adInfo = VPAdInfo.createNormalAdInfo() +// self.adInfo = adInfo +// completer?(adInfo) +// } +// +// } +// } +//} +// +// diff --git a/SynthReel/Base/AdManager/VPAdInfo.swift b/SynthReel/Base/AdManager/VPAdInfo.swift new file mode 100644 index 0000000..a4e07ce --- /dev/null +++ b/SynthReel/Base/AdManager/VPAdInfo.swift @@ -0,0 +1,40 @@ +// +// VPAdInfo.swift +// Veloria +// +// Created by 湖南秦九 on 2025/7/14. +// + +import UIKit +import SmartCodable + +enum VPAdPlatformKey: String, SmartCaseDefaultable { + case google = "google" + case applovin = "applovin" +} + +struct VPAdDataModel: SmartCodable { + var ad: VPAdInfo? +} + +class VPAdInfo:NSObject, SmartCodable { + + required override init() { + super.init() + } + + var id: String? + var platform_name: String? + var ads_id: String? + var status: String? + var platform_key: VPAdPlatformKey? + + + static func createNormalAdInfo() -> VPAdInfo { + var adInfo = VPAdInfo() + adInfo.platform_key = .applovin + adInfo.ads_id = VPAdManager.applovin_rewardedAdUnitID + return adInfo + } + +} diff --git a/SynthReel/Base/AdManager/VPAdManager.swift b/SynthReel/Base/AdManager/VPAdManager.swift new file mode 100644 index 0000000..9be29c6 --- /dev/null +++ b/SynthReel/Base/AdManager/VPAdManager.swift @@ -0,0 +1,100 @@ +// +// VPAdManager.swift +// Veloria +// +// Created by 湖南秦九 on 2025/7/14. +// + +import UIKit +#if canImport(GoogleMobileAds) +import GoogleMobileAds +#endif +#if canImport(AppLovinSDK) +import AppLovinSDK +#endif + +class VPAdManager: NSObject { + + + static var completer: (() -> Void)? + + static func start() { +#if canImport(GoogleMobileAds) + MobileAds.shared.start() +#endif + + initialize_applovinSdk() + } + + ///初始化AppLovinSDK + static func initialize_applovinSdk(completer: (() -> Void)? = nil) { + if completer != nil { + self.completer = completer + } +#if canImport(AppLovinSDK) + if !ALSdk.shared().isInitialized { + //初始化 + let initConfig = ALSdkInitializationConfiguration(sdkKey: "XW2aulJv9urKD4MIIFT1xcSCuyTHaDZ9qUbDqygnTLS04GkdX7WMQJviGP5vDRWGsk4OJJIyLGRV3mbLqOWx0W") { builder in + builder.mediationProvider = ALMediationProviderMAX +//#if DEBUG +// builder.testDeviceAdvertisingIdentifiers = [JXUUID.idfa()] +//#endif + } + + ALSdk.shared().initialize(with: initConfig) { sdkConfig in + // Start loading ads + self.completer?() + } + } else { + self.completer?() + } +#endif + } + +} + +//MARK: -------------- 单元ID -------------- +extension VPAdManager { + + ///谷歌激励广告单元ID + static var google_rewardedAdUnitID: String { +#if DEBUG + return "ca-app-pub-3940256099942544/1712485313" +#else + return "" +#endif + } + + ///开屏广告的单元ID + static var google_appOpenAdUnitID: String { +#if DEBUG + return "ca-app-pub-3940256099942544/5575463023" +#else + return "" +#endif + } + ///横幅广告单元ID + static var google_bannerAdUnitID: String { +#if DEBUG + return "ca-app-pub-3940256099942544/2435281174" +#else + return "" +#endif + } + + ///激励广告的单元ID + static var applovin_rewardedAdUnitID: String { + return "39bf981e27728eae" + } + + ///开屏广告的单元ID + static var applovin_appOpenAdUnitID: String { + return "d587df0fd75ff03b" + } + ///横幅广告单元ID + static var applovin_bannerAdUnitID: String { + return "1eb6278843149711" + } + + +} diff --git a/SynthReel/Base/AdManager/VPStatAdModel.swift b/SynthReel/Base/AdManager/VPStatAdModel.swift new file mode 100644 index 0000000..a746644 --- /dev/null +++ b/SynthReel/Base/AdManager/VPStatAdModel.swift @@ -0,0 +1,33 @@ +// +// VPStatAdModel.swift +// Veloria +// +// Created by 湖南秦九 on 2025/7/14. +// + +import UIKit +import SmartCodable + +class VPStatAdModel: NSObject, SmartCodable { + + required override init() { + super.init() + } + + enum AdScene: String, SmartCaseDefaultable { + case detail = "detail" + case me = "me" + case reward = "reward" + case splash = "splash" + case banner = "banner" + } + + var type: String? //start click error click show_failed load_failed Interrupt(退到后台) close + var ads_id: String? + var view_seconds: Int? + var ad_platform_key: VPAdPlatformKey? + var scene: AdScene? // splash reward banner detail me turntable + var short_play_id: String? + var short_play_video_id: String? + var error_msg: String? +} diff --git a/SynthReel/Base/Admanger/BannerAd/SRAdmobOpenAd.swift b/SynthReel/Base/Admanger/BannerAd/SRAdmobOpenAd.swift new file mode 100644 index 0000000..caf104d --- /dev/null +++ b/SynthReel/Base/Admanger/BannerAd/SRAdmobOpenAd.swift @@ -0,0 +1,137 @@ +// +// SRAdmobOpenAd.swift +// SynthReel +// +// Created by 澜声世纪 on 2025/12/11. +// Copyright © 2025 SR. All rights reserved. +// + +import UIKit +#if canImport(GoogleMobileAds) +import GoogleMobileAds +#endif + +class SRAdmobOpenAd: NSObject, SRAppOpenAd { + + #if canImport(GoogleMobileAds) + private var appOpenAd: AppOpenAd? + #endif + + weak var delegate: SRAppOpenAdDelegate? + + var adInfo: VPAdInfo? + var isShowingAd: Bool = false + + // 实现 SRAppOpenAd 协议中的 adPlatformKey 属性 + var adPlatformKey: String { + return "AdMob" // 这里可以改成适合你应用的广告平台标识 + } + + var isReady: Bool { + #if canImport(GoogleMobileAds) + return appOpenAd != nil + #else + return false + #endif + } + + // 实现 SRAppOpenAd 协议中的 adUnitID 属性 + var adUnitID: String { + return adInfo?.ads_id ?? "" + } + + // 加载广告 + func loadAd() { + #if canImport(GoogleMobileAds) + guard let adInfo = self.adInfo else { return } + + let adUnitID = adInfo.ads_id ?? "" + let request = Request() + + AppOpenAd.load(with: adUnitID, request: request) { [weak self] appOpenAd, error in + guard let self = self else { return } + + if let error = error { + self.delegate?.appOpenAd?(ad: self, didLoadFail: error) + return + } + + self.appOpenAd = appOpenAd + appOpenAd?.fullScreenContentDelegate = self + if let error = error { + self.delegate?.appOpenAd?(ad: self, didLoadFail: error) + } else { + // 如果没有错误,调用加载成功的回调 + self.delegate?.appOpenAdDidLoadFinish?(ad: self) + } + } + #endif + } + + // 显示广告 + func showAd() { + #if canImport(GoogleMobileAds) + guard let appOpenAd = appOpenAd else { + print("App open ad is not ready yet.") + return + } + + if isShowingAd { + return print("App open ad is already showing.") + } + + appOpenAd.present(from: nil) + isShowingAd = true + #endif + } +} + +// MARK: - FullScreenContentDelegate +#if canImport(GoogleMobileAds) +extension SRAdmobOpenAd: FullScreenContentDelegate { + + func adDidRecordImpression(_ ad: FullScreenPresentingAd) { + print("App open ad recorded an impression.") + delegate?.appOpenAdDidShow?(ad: self) + } + + func adDidRecordClick(_ ad: FullScreenPresentingAd) { + print("App open ad recorded a click.") + delegate?.appOpenAdDidClick?(ad: self) + } + + func adWillDismissFullScreenContent(_ ad: FullScreenPresentingAd) { + print("App open ad will be dismissed.") + } + + func adWillPresentFullScreenContent(_ ad: FullScreenPresentingAd) { + print("App open ad will be presented.") + delegate?.appOpenAdDidShow?(ad: self) + } + + func adDidDismissFullScreenContent(_ ad: FullScreenPresentingAd) { + print("App open ad was dismissed.") + + // 确保调用正确的委托方法 + delegate?.appOpenAdDidDismiss?(ad: self) + + appOpenAd = nil + isShowingAd = false + + // 重新加载广告 + + loadAd() + + } + + func ad(_ ad: FullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) { + print("App open ad failed to present with error: \(error.localizedDescription)") + appOpenAd = nil + isShowingAd = false + delegate?.appOpenAd?(ad: self, didDisplayFail: error) + // 重新加载广告 + loadAd() + + } +} +#endif diff --git a/SynthReel/Base/Admanger/OpenAd/SROpenAdManager.swift b/SynthReel/Base/Admanger/OpenAd/SROpenAdManager.swift new file mode 100644 index 0000000..4212b77 --- /dev/null +++ b/SynthReel/Base/Admanger/OpenAd/SROpenAdManager.swift @@ -0,0 +1,227 @@ +//// +//// SROpenAdManager.swift +//// SynthReel +//// +//// Created by 澜声世纪 on 2025/12/10. +//// Copyright © 2025 SR. All rights reserved. +//// +// +import UIKit +import Foundation +import GoogleMobileAds + +@objc protocol SRAppOpenAdManagerDelegate: NSObjectProtocol { + + ///广告加载成功 + @objc optional func appOpenAdManagerDidLoadFinish(adManager: SRAppOpenAdDelegate) + ///广告加载失败 + @objc optional func appOpenAdManager(adManager: SRAppOpenAdDelegate, didLoadFail error: Error) + ///广告展示失败 + @objc optional func appOpenAdManager(adManager: SRAppOpenAdDelegate, didDisplayFail error: Error) + ///广告被展示 + @objc optional func appOpenAdManagerDidShow(adManager: SRAppOpenAdDelegate) + ///广告被关闭 + @objc optional func appOpenAdManagerDidDismiss(adManager: SRAppOpenAdDelegate) + ///广告被点击 + @objc optional func appOpenAdManagerDidClick(adManager: SRAppOpenAdDelegate) + ///其它错误 + @objc optional func appOpenAdManager(adManager: SRAppOpenAdDelegate, didOtherFail error: Error) + +} + + +@objc protocol SRAppOpenAdDelegate: NSObjectProtocol { + + ///广告加载失败 + @objc optional func appOpenAd(ad: SRAppOpenAd, didLoadFail error: Error) + ///广告加载成功 + @objc optional func appOpenAdDidLoadFinish(ad: SRAppOpenAd) + ///广告展示失败 + @objc optional func appOpenAd(ad: SRAppOpenAd, didDisplayFail error: Error) + ///广告被展示 + @objc optional func appOpenAdDidShow(ad: SRAppOpenAd) + ///广告被关闭 + @objc optional func appOpenAdDidDismiss(ad: SRAppOpenAd) + ///广告被点击 + @objc optional func appOpenAdDidClick(ad: SRAppOpenAd) +} + +@objc protocol SRAppOpenAd: NSObjectProtocol { + + weak var delegate: SRAppOpenAdDelegate? { get set } + + var adPlatformKey: String { get } + + var adUnitID: String { get } + + var isReady: Bool { get } + + func loadAd() + func showAd() + +} + +class SRAppOpenAdManager: NSObject { + + static let manager = SRAppOpenAdManager() + + weak var delegate: SRAppOpenAdManagerDelegate? + + private(set) var appOpenAd: SRAppOpenAd? { + didSet { + oldValue?.delegate = nil + appOpenAd?.delegate = self + } + } + + private var isLoading = false + private var isShowing = false + ///允许自动展示 + private var needAutoShow = false + + private var timeOutTimer: Timer? + + private var adsDate: Date? + + deinit { + NotificationCenter.default.removeObserver(self) + } + + override init() { + super.init() + NotificationCenter.default.addObserver(self, selector: #selector(didEnterBackgroundNotification), name: UIApplication.didEnterBackgroundNotification, object: nil) + } + + func showAdIfAvailable() { + + if self.appOpenAd?.isReady == true { + self.showAd() + } else { + self.timeOutTimer = Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(handleTimeOutTimer), userInfo: nil, repeats: false) + + self.needAutoShow = true + self.loadAd() + } + } + + func loadAd() { + guard !isLoading else { return } + + self.isLoading = true + appOpenAd = SRAdmobOpenAd() + appOpenAd?.loadAd() + } + + func showAd() { + guard self.appOpenAd?.isReady == true else { return } + guard !self.isShowing else { return } + + + self.isShowing = true + self.appOpenAd?.showAd() + } + + @objc private func handleTimeOutTimer() { + self.needAutoShow = false + cleanTimer() + + let error = NSError(domain: "time-out", code: -1) + requestStatAd(type: "load_failed", errorMsg: error.localizedDescription) + self.delegate?.appOpenAdManager?(adManager: self, didOtherFail: error) + } + + private func cleanTimer() { + self.timeOutTimer?.invalidate() + self.timeOutTimer = nil + } + + private func clean() { + appOpenAd = nil + delegate = nil + isShowing = false + self.adsDate = nil + } +} + +//MARK: -------------- VPAppOpenAdDelegate -------------- +extension SRAppOpenAdManager: SRAppOpenAdDelegate { + + ///广告加载失败 + func appOpenAd(ad: SRAppOpenAd, didLoadFail error: Error) { + cleanTimer() + isLoading = false + requestStatAd(type: "load_failed", errorMsg: error.localizedDescription) + + self.delegate?.appOpenAdManager?(adManager: self, didLoadFail: error) + + clean() + } + ///广告加载成功 + func appOpenAdDidLoadFinish(ad: SRAppOpenAd) { + cleanTimer() + self.isLoading = false + self.delegate?.appOpenAdManagerDidLoadFinish?(adManager: self) + + if needAutoShow { + self.needAutoShow = false + self.showAd() + } + + } + ///广告展示失败 + func appOpenAd(ad: SRAppOpenAd, didDisplayFail error: Error) { + requestStatAd(type: "show_failed", errorMsg: error.localizedDescription) + self.delegate?.appOpenAdManager?(adManager: self, didDisplayFail: error) + clean() + } + ///广告被展示 + func appOpenAdDidShow(ad: SRAppOpenAd) { + adsDate = Date() + requestStatAd(type: "start", errorMsg: nil) + self.delegate?.appOpenAdManagerDidShow?(adManager: self) + } + ///广告被关闭 + func appOpenAdDidDismiss(ad: SRAppOpenAd) { + requestStatAd(type: "close", errorMsg: nil) + self.delegate?.appOpenAdManagerDidDismiss?(adManager: self) + clean() + } + ///广告被点击 + func appOpenAdDidClick(ad: SRAppOpenAd) { + requestStatAd(type: "click", errorMsg: nil) + self.delegate?.appOpenAdManagerDidClick?(adManager: self) + } +} + + +extension SRAppOpenAdManager { + + private func requestStatAd(type: String, errorMsg: String?) { + guard let appOpenAd = self.appOpenAd else { return } + + var seconds = 0 + if let adsDate = self.adsDate { + if type == "click" || type == "close" { + seconds = Int(Date().timeIntervalSince(adsDate)) + } + } + + + let model = VPStatAdModel() + model.type = type + model.view_seconds = seconds + model.ads_id = appOpenAd.adUnitID + model.ad_platform_key = VPAdPlatformKey(rawValue: appOpenAd.adPlatformKey) + model.error_msg = errorMsg + model.scene = .splash + +// VPStatAPI.requestStatAd(model: model) + } + + + @objc private func didEnterBackgroundNotification() { + guard self.isShowing else { return } + + self.requestStatAd(type: "Interrupt", errorMsg: nil) + } +} diff --git a/SynthReel/Base/Admanger/SRAdManger.swift b/SynthReel/Base/Admanger/SRAdManger.swift new file mode 100644 index 0000000..212d856 --- /dev/null +++ b/SynthReel/Base/Admanger/SRAdManger.swift @@ -0,0 +1,101 @@ +// +// SRAdManger.swift +// SynthReel +// +// Created by 澜声世纪 on 2025/12/11. +// Copyright © 2025 SR. All rights reserved. +// + +import UIKit +#if canImport(GoogleMobileAds) +import GoogleMobileAds +#endif +#if canImport(AppLovinSDK) +import AppLovinSDK +#endif + +class SRAdManger: NSObject { + + + static var completer: (() -> Void)? + + static func start() { +#if canImport(GoogleMobileAds) + MobileAds.shared.start() +#endif + + initialize_applovinSdk() + } + + ///初始化AppLovinSDK + static func initialize_applovinSdk(completer: (() -> Void)? = nil) { + if completer != nil { + self.completer = completer + } +#if canImport(AppLovinSDK) + if !ALSdk.shared().isInitialized { + //初始化 + let initConfig = ALSdkInitializationConfiguration(sdkKey: "XW2aulJv9urKD4MIIFT1xcSCuyTHaDZ9qUbDqygnTLS04GkdX7WMQJviGP5vDRWGsk4OJJIyLGRV3mbLqOWx0W") { builder in + builder.mediationProvider = ALMediationProviderMAX +//#if DEBUG +// builder.testDeviceAdvertisingIdentifiers = [JXUUID.idfa()] +//#endif + } + + ALSdk.shared().initialize(with: initConfig) { sdkConfig in + // Start loading ads + self.completer?() + } + } else { + self.completer?() + } +#endif + } + +} + +//MARK: -------------- 单元ID -------------- +extension SRAdManger { + + ///谷歌激励广告单元ID + static var google_rewardedAdUnitID: String { +#if DEBUG + return "ca-app-pub-3940256099942544/1712485313" +#else + return "ca-app-pub-6275401933109862/2121481439" +#endif + } + + ///开屏广告的单元ID + static var google_appOpenAdUnitID: String { +#if DEBUG + return "ca-app-pub-3940256099942544/5575463023" +#else + return "ca-app-pub-6275401933109862/7130265535" +#endif + } + ///横幅广告单元ID + static var google_bannerAdUnitID: String { +#if DEBUG + return "ca-app-pub-3940256099942544/2435281174" +#else + return "ca-app-pub-6275401933109862/7971191024" +#endif + } + + ///激励广告的单元ID + static var applovin_rewardedAdUnitID: String { + return "3708ac6b6026e375" + } + +// ///开屏广告的单元ID +// static var applovin_appOpenAdUnitID: String { +// return "d587df0fd75ff03b" +// } +// ///横幅广告单元ID +// static var applovin_bannerAdUnitID: String { +// return "1eb6278843149711" +// } + + +} diff --git a/SynthReel/Base/Model/SRVersionUpdateModel.swift b/SynthReel/Base/Model/SRVersionUpdateModel.swift new file mode 100644 index 0000000..518c3ec --- /dev/null +++ b/SynthReel/Base/Model/SRVersionUpdateModel.swift @@ -0,0 +1,39 @@ +// +// SRVersionUpdateModel.swift +// SynthReel +// +// Created by 澜声世纪 on 2025/12/10. +// Copyright © 2025 SR. All rights reserved. +// + +import UIKit +import SmartCodable + +struct SRVersionUpdateModel: SmartCodable { + + var version_code: String? + var des: String? + var version_name: String? + + var force: Bool? + + + func canUpdate() -> Bool { + guard let version = version_code else { return false } + + let result = kSRAPPVersion.compare(version, options: .numeric) + if result == .orderedAscending { + return true + } else { + return false + } + } + + + static func mappingForKey() -> [SmartKeyTransformer]? { + return [ + CodingKeys.des <--- ["description"] + ] + } + +} diff --git a/SynthReel/Base/Networking/SRNetwork.swift b/SynthReel/Base/Networking/SRNetwork.swift index f974757..10ea7aa 100644 --- a/SynthReel/Base/Networking/SRNetwork.swift +++ b/SynthReel/Base/Networking/SRNetwork.swift @@ -49,11 +49,15 @@ class SRNetwork: NSObject { static func _request(parameters: SRNetwork.Parameters, completion: ((_ response: SRNetwork.Response) -> Void)?) -> Cancellable { if parameters.isLoding { - SRHud.show() + DispatchQueue.main.async { + SRHud.show() + } } return provider.request(.request(parameters: parameters)) { result in if parameters.isLoding { - SRHud.dismiss() + DispatchQueue.main.async { + SRHud.dismiss() + } } guard let completion = completion else {return} _resultDispose(parameters: parameters, result: result, completion: completion) diff --git a/SynthReel/Base/View/SRNavgationTitleView.swift b/SynthReel/Base/View/SRNavgationTitleView.swift index 44b2bd8..062e52e 100644 --- a/SynthReel/Base/View/SRNavgationTitleView.swift +++ b/SynthReel/Base/View/SRNavgationTitleView.swift @@ -26,7 +26,7 @@ class SRNavgationTitleView: UIView { private let titleLabel: UILabel = { let label = UILabel() - label.font = .font(ofSize: 18, weight: .bold) + label.font = .font(ofSize: 18, weight: .bold).withBoldItalic() label.textAlignment = .center label.textColor = .white return label diff --git a/SynthReel/Base/ViewController/SRAppOpenAdViewController.swift b/SynthReel/Base/ViewController/SRAppOpenAdViewController.swift new file mode 100644 index 0000000..bd93963 --- /dev/null +++ b/SynthReel/Base/ViewController/SRAppOpenAdViewController.swift @@ -0,0 +1,53 @@ +// +// SRAppOpenAdViewController.swift +// SynthReel +// +// Created by 澜声世纪 on 2025/12/11. +// Copyright © 2025 SR. All rights reserved. +// + +import UIKit + +class SRAppOpenAdViewController: SRViewController { + + var didEndBlock: (() -> Void)? + + private(set) lazy var lanuchVC: UIViewController? = { + let vc = SRTool.lanuchViewController + return vc + }() + + override func viewDidLoad() { + super.viewDidLoad() + if let vc = lanuchVC { + addChild(vc) + view.addSubview(vc.view) + } + let manager = SRAppOpenAdManager.manager + manager.delegate = self + manager.showAdIfAvailable() + + } + +} + +//MARK: -------------- VPAppOpenAdManagerDelegate -------------- +extension SRAppOpenAdViewController: SRAppOpenAdManagerDelegate { + + func appOpenAdManagerDidDismiss(adManager: SRAppOpenAdDelegate) { + self.didEndBlock?() + } + + func appOpenAdManager(adManager: SRAppOpenAdDelegate, didLoadFail error: any Error) { + self.didEndBlock?() + } + + func appOpenAdManager(adManager: SRAppOpenAdDelegate, didDisplayFail error: any Error) { + self.didEndBlock?() + } + + func appOpenAdManager(adManager: SRAppOpenAdDelegate, didOtherFail error: any Error) { + self.didEndBlock?() + } + +} diff --git a/SynthReel/Base/ViewController/SRTabBarController.swift b/SynthReel/Base/ViewController/SRTabBarController.swift index f6d7faa..61b9b4d 100644 --- a/SynthReel/Base/ViewController/SRTabBarController.swift +++ b/SynthReel/Base/ViewController/SRTabBarController.swift @@ -32,6 +32,9 @@ class SRTabBarController: ESTabBarController { self.tabBar.standardAppearance = appearance self.tabBar.scrollEdgeAppearance = appearance self.tabBar.isTranslucent = false + + +// SRTool.checkUpdates() } diff --git a/SynthReel/Class/MyShort/V/SRFavoritesCell.swift b/SynthReel/Class/MyShort/V/SRFavoritesCell.swift index 3c6560f..a2f92f6 100644 --- a/SynthReel/Class/MyShort/V/SRFavoritesCell.swift +++ b/SynthReel/Class/MyShort/V/SRFavoritesCell.swift @@ -35,22 +35,24 @@ class SRFavoritesCell: UICollectionViewCell { let videoId = (self.model)?.short_play_video_id let isCollect = false -// Task { -// await SRShortApi.requestShortCollect(shortId: shortId, videoId: videoId, isCollect: isCollect) -// } - Task { - let success = await SRShortApi.requestShortCollect( - shortId: shortId, - videoId: videoId, - isCollect: isCollect - ) - - if success { - self.onCollectChanged?(self) - } else { - print("收藏失败") + let view = SRRemoveCollectAlert() + view.clickHighlightButton = { + Task { + let success = await SRShortApi.requestShortCollect( + shortId: shortId, + videoId: videoId, + isCollect: isCollect + ) + + if success { + self.onCollectChanged?(self) + } else { + print("收藏失败") + } } } + view.show() + })) button.setImage(UIImage(named: "collect_icon_01_selected"), for: .normal) button.setImage(UIImage(named: "collect_icon_01_selected"), for: .selected) diff --git a/SynthReel/Class/Player/V/SRShortDetailControlView.swift b/SynthReel/Class/Player/V/SRShortDetailControlView.swift index 4543a3f..32858b4 100644 --- a/SynthReel/Class/Player/V/SRShortDetailControlView.swift +++ b/SynthReel/Class/Player/V/SRShortDetailControlView.swift @@ -105,10 +105,29 @@ class SRShortDetailControlView: JXPlayerListControlView { guard let shortId = self.shortModel?.short_play_id else { return } let videoId = (self.model as? SRVideoInfoModel)?.short_play_video_id let isCollect = !(self.shortModel?.is_collect ?? false) - - Task { - await SRShortApi.requestShortCollect(shortId: shortId, videoId: videoId, isCollect: isCollect) + + if !isCollect { + let view = SRRemoveCollectAlert() + view.clickHighlightButton = { + Task { + let success = await SRShortApi.requestShortCollect( + shortId: shortId, + videoId: videoId, + isCollect: isCollect + ) + if success { + } else { + print("收藏失败") + } + } + } + view.show() + }else{ + Task { + await SRShortApi.requestShortCollect(shortId: shortId, videoId: videoId, isCollect: isCollect) + } } + })) button.setImage(UIImage(named: "collect_icon_01"), for: .normal) button.setImage(UIImage(named: "collect_icon_01_selected"), for: .selected) diff --git a/SynthReel/Class/Player/V/SRVideoLockView.swift b/SynthReel/Class/Player/V/SRVideoLockView.swift index 83a48e8..ecf261e 100644 --- a/SynthReel/Class/Player/V/SRVideoLockView.swift +++ b/SynthReel/Class/Player/V/SRVideoLockView.swift @@ -99,22 +99,23 @@ extension SRVideoLockView { addSubview(unlockStackView) unlockStackView.addArrangedSubview(unlockButton) - unlockStackView.addArrangedSubview(adlockButton) +// unlockStackView.addArrangedSubview(adlockButton) unlockStackView.snp.makeConstraints { make in make.left.equalToSuperview().offset(45) make.right.equalToSuperview().offset(-45) - make.height.equalTo(43 * 2 + 30) // 两个按钮 + 间距 +// make.height.equalTo(43 * 2 + 30) // 两个按钮 + 间距 make.centerY.equalToSuperview() // 可自定义 + make.height.equalTo(43) } unlockButton.snp.makeConstraints { make in make.height.equalTo(43) } - adlockButton.snp.makeConstraints { make in - make.height.equalTo(43) - } +// adlockButton.snp.makeConstraints { make in +// make.height.equalTo(43) +// } } } diff --git a/SynthReel/Class/User/VC/SRAboutUsController.swift b/SynthReel/Class/User/VC/SRAboutUsController.swift index fc575dc..4b5091d 100644 --- a/SynthReel/Class/User/VC/SRAboutUsController.swift +++ b/SynthReel/Class/User/VC/SRAboutUsController.swift @@ -32,10 +32,14 @@ class SRAboutUsController: SRViewController { override func viewDidLoad() { super.viewDidLoad() - self.title = "About".localized - sr_setupLayout() } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + self.navigationController?.isNavigationBarHidden = false + navigationController?.sr_setNavigationTitle("About".localized, for: self) + } } diff --git a/SynthReel/Class/User/VC/SRUserListViewController.swift b/SynthReel/Class/User/VC/SRUserListViewController.swift index ac30b4b..b9f6f1c 100644 --- a/SynthReel/Class/User/VC/SRUserListViewController.swift +++ b/SynthReel/Class/User/VC/SRUserListViewController.swift @@ -71,6 +71,7 @@ extension SRUserListViewController { var arr = [ SRUserSettingModel(type: .feedback, name: "synthreel_feedback".localized, icon: UIImage(named: "icon_feedback")), SRUserSettingModel(type: .deleteAccount, name: "synthreel_delet_account".localized, icon: UIImage(named: "icon_delet")), + SRUserSettingModel(type: .orderRecord, name: "synthreel_order_Record".localized, icon: UIImage(named: "icon_order")), SRUserSettingModel(type: .about, name: "synthreel_about_us".localized, icon: UIImage(named: "icon_about")), SRUserSettingModel(type: .privacyPolicy, name: "synthreel_privacy_policy".localized, icon: UIImage(named: "icon_privacy")), SRUserSettingModel(type: .userAgreement, name: "synthreel_user_agreement".localized, icon: UIImage(named: "icon_user")), @@ -116,6 +117,10 @@ extension SRUserListViewController: UITableViewDelegate, UITableViewDataSource { case .logout: logout() break + case .orderRecord: + let vc = SRWalletViewController() + self.navigationController?.pushViewController(vc, animated: true) + break case .deleteAccount: deleteAccount() break @@ -138,9 +143,13 @@ extension SRUserListViewController: UITableViewDelegate, UITableViewDataSource { } func logout(){ - Task{ - await SRLogin.manager.logout(completer: nil) + let view = SRLogoutAlert(); + view.clickHighlightButton = { + Task{ + await SRLogin.manager.logout(completer: nil) + } } + view.show() } func deleteAccount() { diff --git a/SynthReel/Class/User/model/SRUserSettingModel.swift b/SynthReel/Class/User/model/SRUserSettingModel.swift index 7e615d1..4466d42 100644 --- a/SynthReel/Class/User/model/SRUserSettingModel.swift +++ b/SynthReel/Class/User/model/SRUserSettingModel.swift @@ -18,6 +18,7 @@ struct SRUserSettingModel { case userAgreement case visitWebsite case login + case orderRecord case logout // ///消费记录 case consumptionRecords diff --git a/SynthReel/Class/wallet/VC/SRWalletViewController.swift b/SynthReel/Class/wallet/VC/SRWalletViewController.swift new file mode 100644 index 0000000..26248c4 --- /dev/null +++ b/SynthReel/Class/wallet/VC/SRWalletViewController.swift @@ -0,0 +1,29 @@ +// +// SRWalletViewController.swift +// SynthReel +// +// Created by 澜声世纪 on 2025/12/10. +// Copyright © 2025 SR. All rights reserved. +// + +import UIKit + +class SRWalletViewController: SRViewController { + + override func viewDidLoad() { + super.viewDidLoad() + sr_setupLayout() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + self.navigationController?.isNavigationBarHidden = false + navigationController?.sr_setNavigationTitle("synthreel_my_wallet".localized, for: self) + } +} + +extension SRWalletViewController { + func sr_setupLayout() { + + } +} diff --git a/SynthReel/Delegate/AppDelegate+SRAPNS.swift b/SynthReel/Delegate/AppDelegate+SRAPNS.swift index 7029b14..7ed9981 100644 --- a/SynthReel/Delegate/AppDelegate+SRAPNS.swift +++ b/SynthReel/Delegate/AppDelegate+SRAPNS.swift @@ -57,7 +57,6 @@ extension SceneDelegate { // if date.fa_isToday { return } // UserDefaults.standard.set(Date(), forKey: kFAApnsAlertDefaultsKey) // #endif - // let view = SRApnsAlert() // view.show() } diff --git a/SynthReel/Libs/Alert/SRApnsAlert.swift b/SynthReel/Libs/Alert/SRApnsAlert.swift index 9d41b82..b0d4db8 100644 --- a/SynthReel/Libs/Alert/SRApnsAlert.swift +++ b/SynthReel/Libs/Alert/SRApnsAlert.swift @@ -12,6 +12,8 @@ class SRApnsAlert: SRBaseAlert { private lazy var imageView = UIImageView(image: UIImage(named: "alertBg")) + private lazy var iconimageView = UIImageView(image: UIImage(named: "通知")) + private lazy var titleLabel: UILabel = { let label = UILabel() label.textAlignment = .center @@ -34,22 +36,19 @@ class SRApnsAlert: SRBaseAlert { private lazy var laterButton: UIButton = { let button = UIButton(type: .custom) - button.layer.cornerRadius = 18 - button.layer.masksToBounds = true - button.layer.borderWidth = 1 - button.layer.borderColor = UIColor.white.cgColor - button.setTitle("fableon_open_notification_later".localized, for: .normal) + button.setBackgroundImage(.laterbg ,for: .normal) + button.setTitle("synthreel_open_notification_later".localized, for: .normal) button.setTitleColor(.white, for: .normal) button.titleLabel?.font = .font(ofSize: 14, weight: .semibold) button.addTarget(self, action: #selector(dismiss), for: .touchUpInside) return button }() - override init(frame: CGRect) { + override init(frame: CGRect) { super.init(frame: frame) - highlightButton.setTitle("fableon_open".localized, for: .normal) - - fa_setupLayout() + highlightButton.setTitle("synthreel_allow".localized, for: .normal) + closeButton.isHidden = true + sr_setupLayout() } @MainActor required init?(coder: NSCoder) { @@ -71,35 +70,43 @@ class SRApnsAlert: SRBaseAlert { extension SRApnsAlert { - private func fa_setupLayout() { - containerView.addSubview(imageView) + private func sr_setupLayout() { + contentView.addSubview(imageView) imageView.addSubview(titleLabel) + imageView.addSubview(iconimageView) imageView.addSubview(textLabel) imageView.addSubview(laterButton) imageView.addSubview(highlightButton) + imageView.isUserInteractionEnabled = true imageView.snp.makeConstraints { make in - make.centerX.equalToSuperview() - make.top.equalToSuperview().offset(-62) + make.edges.equalToSuperview() } titleLabel.snp.makeConstraints { make in make.centerX.equalToSuperview() make.right.lessThanOrEqualToSuperview().offset(-10) - make.top.equalTo(imageView.snp.bottom).offset(10) + make.top.equalTo(10) + make.height.equalTo(18) + } + + iconimageView.snp.makeConstraints { make in + make.top.equalTo(iconimageView.snp.bottom).offset(38) + make.centerX.equalToSuperview() + make.size.equalTo(CGSizeMake(85, 85)) } textLabel.snp.makeConstraints { make in make.centerX.equalToSuperview() make.right.lessThanOrEqualToSuperview().offset(-20) - make.top.equalTo(titleLabel.snp.bottom).offset(12) + make.top.equalTo(iconimageView.snp.bottom).offset(12) } laterButton.snp.makeConstraints { make in make.left.equalToSuperview().offset(23) make.top.equalTo(textLabel.snp.bottom).offset(21) make.bottom.equalToSuperview().offset(-20) - make.height.equalTo(36) + make.height.equalTo(48) } highlightButton.snp.makeConstraints { make in diff --git a/SynthReel/Libs/Alert/SRBaseAlert.swift b/SynthReel/Libs/Alert/SRBaseAlert.swift index 1849294..6ecb219 100644 --- a/SynthReel/Libs/Alert/SRBaseAlert.swift +++ b/SynthReel/Libs/Alert/SRBaseAlert.swift @@ -42,8 +42,6 @@ class SRBaseAlert: UIView { lazy var highlightButton: UIButton = { let button = UIButton(type: .custom) - button.layer.cornerRadius = 16 - button.layer.masksToBounds = true button.setTitleColor(.srGreen, for: .normal) button.setBackgroundImage(.suerButtonBg, for: .normal) button.titleLabel?.font = .font(ofSize: 14, weight: .semibold) diff --git a/SynthReel/Libs/Alert/SRLogoutAlert.swift b/SynthReel/Libs/Alert/SRLogoutAlert.swift new file mode 100644 index 0000000..bda1bc3 --- /dev/null +++ b/SynthReel/Libs/Alert/SRLogoutAlert.swift @@ -0,0 +1,117 @@ +// +// SRLogoutAlert.swift +// SynthReel +// +// Created by 澜声世纪 on 2025/12/10. +// Copyright © 2025 SR. All rights reserved. +// + +import UIKit + +class SRLogoutAlert: SRBaseAlert { + + private lazy var imageView = UIImageView(image: UIImage(named: "alertBg")) + + private lazy var iconimageView = UIImageView(image: UIImage(named: "通知")) + + private lazy var titleLabel: UILabel = { + let label = UILabel() + label.textAlignment = .center + label.numberOfLines = 0 + label.font = .font(ofSize: 18, weight: .semibold) + label.textColor = .white + label.text = "logout_alert_title".localized + return label + }() + + private lazy var textLabel: UILabel = { + let label = UILabel() + label.textAlignment = .center + label.numberOfLines = 0 + label.font = .font(ofSize: 12, weight: .regular) + label.textColor = .white + label.text = "logout_alert_text".localized + return label + }() + + private lazy var laterButton: UIButton = { + let button = UIButton(type: .custom) + button.setBackgroundImage(.laterbg ,for: .normal) + button.setTitle("synthreel_cancel".localized, for: .normal) + button.setTitleColor(.white, for: .normal) + button.titleLabel?.font = .font(ofSize: 14, weight: .semibold) + button.addTarget(self, action: #selector(dismiss), for: .touchUpInside) + return button + }() + + override init(frame: CGRect) { + super.init(frame: frame) + highlightButton.setTitle("synthreel_logout".localized, for: .normal) + closeButton.isHidden = true + sr_setupLayout() + } + + @MainActor required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func handleHighlightButton() { + super.handleHighlightButton() + } + + override func dismiss() { + super.dismiss() + adjustManger.manager.apnsFinish() + } + +} + +extension SRLogoutAlert { + + private func sr_setupLayout() { + contentView.addSubview(imageView) + imageView.addSubview(titleLabel) + imageView.addSubview(iconimageView) + imageView.addSubview(textLabel) + imageView.addSubview(laterButton) + imageView.addSubview(highlightButton) + + imageView.isUserInteractionEnabled = true + imageView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + + titleLabel.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.right.lessThanOrEqualToSuperview().offset(-10) + make.top.equalTo(10) + make.height.equalTo(18) + } + + iconimageView.snp.makeConstraints { make in + make.top.equalTo(iconimageView.snp.bottom).offset(38) + make.centerX.equalToSuperview() + make.size.equalTo(CGSizeMake(85, 85)) + } + + textLabel.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.right.lessThanOrEqualToSuperview().offset(-20) + make.top.equalTo(iconimageView.snp.bottom).offset(12) + } + + laterButton.snp.makeConstraints { make in + make.left.equalToSuperview().offset(23) + make.top.equalTo(textLabel.snp.bottom).offset(21) + make.bottom.equalToSuperview().offset(-20) + make.height.equalTo(48) + } + + highlightButton.snp.makeConstraints { make in + make.width.height.top.equalTo(laterButton) + make.left.equalTo(laterButton.snp.right).offset(11) + make.right.equalToSuperview().offset(-23) + } + } +} + diff --git a/SynthReel/Libs/Alert/SRRemoveCollectAlert.swift b/SynthReel/Libs/Alert/SRRemoveCollectAlert.swift new file mode 100644 index 0000000..3ab894e --- /dev/null +++ b/SynthReel/Libs/Alert/SRRemoveCollectAlert.swift @@ -0,0 +1,117 @@ +// +// SRRemoveCollectAlert.swift +// SynthReel +// +// Created by 澜声世纪 on 2025/12/10. +// Copyright © 2025 SR. All rights reserved. +// + +import UIKit + +class SRRemoveCollectAlert: SRBaseAlert { + + private lazy var imageView = UIImageView(image: UIImage(named: "alertBg")) + + private lazy var iconimageView = UIImageView(image: UIImage(named: "收藏")) + + private lazy var titleLabel: UILabel = { + let label = UILabel() + label.textAlignment = .center + label.numberOfLines = 0 + label.font = .font(ofSize: 18, weight: .semibold) + label.textColor = .white + label.text = "remove_collect_alert_title".localized + return label + }() + + private lazy var textLabel: UILabel = { + let label = UILabel() + label.textAlignment = .center + label.numberOfLines = 0 + label.font = .font(ofSize: 12, weight: .regular) + label.textColor = .white + label.text = "remove_collect_alert_text".localized + return label + }() + + private lazy var laterButton: UIButton = { + let button = UIButton(type: .custom) + button.setBackgroundImage(.laterbg ,for: .normal) + button.setTitle("synthreel_cancel".localized, for: .normal) + button.setTitleColor(.white, for: .normal) + button.titleLabel?.font = .font(ofSize: 14, weight: .semibold) + button.addTarget(self, action: #selector(dismiss), for: .touchUpInside) + return button + }() + + override init(frame: CGRect) { + super.init(frame: frame) + highlightButton.setTitle("synthreel_remove".localized, for: .normal) + highlightButton.setImage(.删除, for: .normal) + closeButton.isHidden = true + sr_setupLayout() + } + + @MainActor required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func handleHighlightButton() { + super.handleHighlightButton() + } + + override func dismiss() { + super.dismiss() + adjustManger.manager.apnsFinish() + } + +} + +extension SRRemoveCollectAlert { + + private func sr_setupLayout() { + contentView.addSubview(imageView) + imageView.addSubview(titleLabel) + imageView.addSubview(iconimageView) + imageView.addSubview(textLabel) + imageView.addSubview(laterButton) + imageView.addSubview(highlightButton) + + imageView.isUserInteractionEnabled = true + imageView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + + titleLabel.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.right.lessThanOrEqualToSuperview().offset(-10) + make.top.equalTo(10) + make.height.equalTo(18) + } + + iconimageView.snp.makeConstraints { make in + make.top.equalTo(iconimageView.snp.bottom).offset(38) + make.centerX.equalToSuperview() + make.size.equalTo(CGSizeMake(85, 85)) + } + + textLabel.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.right.lessThanOrEqualToSuperview().offset(-20) + make.top.equalTo(iconimageView.snp.bottom).offset(12) + } + + laterButton.snp.makeConstraints { make in + make.left.equalToSuperview().offset(23) + make.top.equalTo(textLabel.snp.bottom).offset(21) + make.bottom.equalToSuperview().offset(-20) + make.height.equalTo(48) + } + + highlightButton.snp.makeConstraints { make in + make.width.height.top.equalTo(laterButton) + make.left.equalTo(laterButton.snp.right).offset(11) + make.right.equalToSuperview().offset(-23) + } + } +} diff --git a/SynthReel/Libs/Alert/SRUpdatesAlert.swift b/SynthReel/Libs/Alert/SRUpdatesAlert.swift new file mode 100644 index 0000000..998b835 --- /dev/null +++ b/SynthReel/Libs/Alert/SRUpdatesAlert.swift @@ -0,0 +1,107 @@ +// +// SRUpdatesAlert.swift +// SynthReel +// +// Created by 澜声世纪 on 2025/12/10. +// Copyright © 2025 SR. All rights reserved. +// + +import UIKit + +class SRUpdatesAlert: SRBaseAlert { + + var model: SRVersionUpdateModel? { + didSet { + versionLabel.text = model?.des?.localized + closeButton.isHidden = model?.force ?? false + } + } + private lazy var imageView = UIImageView(image: UIImage(named: "alertBg")) + + private lazy var iconimageView = UIImageView(image: UIImage(named: "升级")) + + private lazy var titleLabel: UILabel = { + let label = UILabel() + label.textAlignment = .center + label.numberOfLines = 0 + label.font = .font(ofSize: 18, weight: .semibold) + label.textColor = .white + label.text = "updates_alert_title".localized + return label + }() + + private lazy var versionLabel: UILabel = { + let label = UILabel() + label.textAlignment = .left + label.numberOfLines = 0 + label.font = .font(ofSize: 15, weight: .regular) + label.textColor = .white + return label + }() + + override init(frame: CGRect) { + super.init(frame: frame) + highlightButton.setTitle("synthreel_update_now".localized, for: .normal) + sr_setupLayout() + } + + @MainActor required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func handleHighlightButton() { + super.handleHighlightButton() + guard let url = URL(string: "https://apps.apple.com/app/id6755756350") else { return } + let application = UIApplication.shared + if application.canOpenURL(url) { + application.open(url) + } + } + + override func dismiss() { + super.dismiss() + adjustManger.manager.apnsFinish() + } + +} + +extension SRUpdatesAlert { + + private func sr_setupLayout() { + contentView.addSubview(imageView) + imageView.addSubview(titleLabel) + imageView.addSubview(versionLabel) + imageView.addSubview(iconimageView) + imageView.addSubview(highlightButton) + + imageView.isUserInteractionEnabled = true + imageView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + + titleLabel.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.right.lessThanOrEqualToSuperview().offset(-10) + make.top.equalTo(10) + make.height.equalTo(18) + } + + iconimageView.snp.makeConstraints { make in + make.top.equalTo(titleLabel.snp.bottom).offset(38) + make.centerX.equalToSuperview() + make.size.equalTo(CGSizeMake(85, 85)) + } + + versionLabel.snp.makeConstraints { make in + make.top.equalTo(iconimageView.snp.bottom).offset(10) + make.left.right.equalToSuperview().inset(20) + } + + highlightButton.snp.makeConstraints { make in + make.top.equalTo(versionLabel.snp.bottom).offset(15) + make.height.equalTo(48) + make.left.right.equalToSuperview().inset(30) + make.right.equalToSuperview().offset(-23) + } + } +} diff --git a/SynthReel/Libs/Tool/SRTool.swift b/SynthReel/Libs/Tool/SRTool.swift index 36b192a..75a034f 100644 --- a/SynthReel/Libs/Tool/SRTool.swift +++ b/SynthReel/Libs/Tool/SRTool.swift @@ -100,3 +100,56 @@ extension SRTool { } } } + +//MARK: 检查更新 +extension SRTool { + + static weak var updateAlert: UIView? + + static func checkUpdates() { + guard self.self.updateAlert == nil else { return } + Task { + let model = await SRUserApi.requestVersionUpdateData() + guard let model = model else { + adjustManger.manager.upgradeAlertFinish = true + await SRTool.sceneDelegate?.retryHandleOpenAppMessage() + return + } + await MainActor.run { + self.showUpdatesAlert(model) + } + } + } + + static func showUpdatesAlert(_ model: SRVersionUpdateModel) { + guard self.self.updateAlert == nil else { return } +//#if !DEBUG +// if model.force != true { +// if let date = UserDefaults.standard.object(forKey: kFAVersionUpdateAlertDefaultsKey) as? Date { +// if date.fa_isToday { +// FAAdjustStateManager.manager.upgradeAlertFinish = true +// FATool.sceneDelegate?.retryHandleOpenAppMessage() +// return +// } +// } +// UserDefaults.standard.set(Date(), forKey: kFAVersionUpdateAlertDefaultsKey) +// } +//#endif // !DEBUG +// if model.canUpdate() { +// +// Task { +// await SRStatAPI.requestEventStat(orderCode: nil, shortPlayId: nil, videoId: nil, eventKey: .forceUpdate, errorMsg: nil, otherParamenters: [ +// "is_force" : model.force == true ? "true" : "false" +// ]) +// } +// let view = SRUpdatesAlert() +// view.model = model +// view.show() +// self.updateAlert = view +// } else { +// adjustManger.manager.upgradeAlertFinish = true +// SRTool.sceneDelegate?.retryHandleOpenAppMessage() +// } + } + +} diff --git a/SynthReel/Source/Assets.xcassets/Image/recordBottomBg.imageset/Contents.json b/SynthReel/Source/Assets.xcassets/Image/recordBottomBg.imageset/Contents.json index 779b252..dbb2ab5 100644 --- a/SynthReel/Source/Assets.xcassets/Image/recordBottomBg.imageset/Contents.json +++ b/SynthReel/Source/Assets.xcassets/Image/recordBottomBg.imageset/Contents.json @@ -7,11 +7,33 @@ { "filename" : "recordBottomBg@2x.png", "idiom" : "universal", + "resizing" : { + "cap-insets" : { + "left" : 235, + "right" : 252 + }, + "center" : { + "mode" : "tile", + "width" : 1 + }, + "mode" : "3-part-horizontal" + }, "scale" : "2x" }, { "filename" : "recordBottomBg@3x.png", "idiom" : "universal", + "resizing" : { + "cap-insets" : { + "left" : 230, + "right" : 306 + }, + "center" : { + "mode" : "tile", + "width" : 1 + }, + "mode" : "3-part-horizontal" + }, "scale" : "3x" } ], diff --git a/SynthReel/Source/Assets.xcassets/myShort/icon_order.imageset/Contents.json b/SynthReel/Source/Assets.xcassets/myShort/icon_order.imageset/Contents.json new file mode 100644 index 0000000..84ef7cb --- /dev/null +++ b/SynthReel/Source/Assets.xcassets/myShort/icon_order.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "icon_order@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "icon_order@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SynthReel/Source/Assets.xcassets/myShort/icon_order.imageset/icon_order@2x.png b/SynthReel/Source/Assets.xcassets/myShort/icon_order.imageset/icon_order@2x.png new file mode 100644 index 0000000..96e8c5f Binary files /dev/null and b/SynthReel/Source/Assets.xcassets/myShort/icon_order.imageset/icon_order@2x.png differ diff --git a/SynthReel/Source/Assets.xcassets/myShort/icon_order.imageset/icon_order@3x.png b/SynthReel/Source/Assets.xcassets/myShort/icon_order.imageset/icon_order@3x.png new file mode 100644 index 0000000..311ea56 Binary files /dev/null and b/SynthReel/Source/Assets.xcassets/myShort/icon_order.imageset/icon_order@3x.png differ diff --git a/SynthReel/Source/Assets.xcassets/myShort/suerButtonBg.imageset/Contents.json b/SynthReel/Source/Assets.xcassets/myShort/suerButtonBg.imageset/Contents.json index d3fa0b4..b504f0c 100644 --- a/SynthReel/Source/Assets.xcassets/myShort/suerButtonBg.imageset/Contents.json +++ b/SynthReel/Source/Assets.xcassets/myShort/suerButtonBg.imageset/Contents.json @@ -7,11 +7,33 @@ { "filename" : "suerButtonBg@2x.png", "idiom" : "universal", + "resizing" : { + "cap-insets" : { + "left" : 99, + "right" : 96 + }, + "center" : { + "mode" : "tile", + "width" : 1 + }, + "mode" : "3-part-horizontal" + }, "scale" : "2x" }, { "filename" : "suerButtonBg@3x.png", "idiom" : "universal", + "resizing" : { + "cap-insets" : { + "left" : 133, + "right" : 136 + }, + "center" : { + "mode" : "tile", + "width" : 1 + }, + "mode" : "3-part-horizontal" + }, "scale" : "3x" } ], diff --git a/SynthReel/Source/Assets.xcassets/normal/laterbg.imageset/Contents.json b/SynthReel/Source/Assets.xcassets/normal/laterbg.imageset/Contents.json new file mode 100644 index 0000000..7ae1d13 --- /dev/null +++ b/SynthReel/Source/Assets.xcassets/normal/laterbg.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "laterbg@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "laterbg@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SynthReel/Source/Assets.xcassets/normal/laterbg.imageset/laterbg@2x.png b/SynthReel/Source/Assets.xcassets/normal/laterbg.imageset/laterbg@2x.png new file mode 100644 index 0000000..9979bf9 Binary files /dev/null and b/SynthReel/Source/Assets.xcassets/normal/laterbg.imageset/laterbg@2x.png differ diff --git a/SynthReel/Source/Assets.xcassets/normal/laterbg.imageset/laterbg@3x.png b/SynthReel/Source/Assets.xcassets/normal/laterbg.imageset/laterbg@3x.png new file mode 100644 index 0000000..97cb90b Binary files /dev/null and b/SynthReel/Source/Assets.xcassets/normal/laterbg.imageset/laterbg@3x.png differ diff --git a/SynthReel/Source/Assets.xcassets/normal/删除.imageset/Contents.json b/SynthReel/Source/Assets.xcassets/normal/删除.imageset/Contents.json new file mode 100644 index 0000000..ce54822 --- /dev/null +++ b/SynthReel/Source/Assets.xcassets/normal/删除.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "删除@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "删除@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SynthReel/Source/Assets.xcassets/normal/删除.imageset/删除@2x.png b/SynthReel/Source/Assets.xcassets/normal/删除.imageset/删除@2x.png new file mode 100644 index 0000000..e5f2a4f Binary files /dev/null and b/SynthReel/Source/Assets.xcassets/normal/删除.imageset/删除@2x.png differ diff --git a/SynthReel/Source/Assets.xcassets/normal/删除.imageset/删除@3x.png b/SynthReel/Source/Assets.xcassets/normal/删除.imageset/删除@3x.png new file mode 100644 index 0000000..8092f76 Binary files /dev/null and b/SynthReel/Source/Assets.xcassets/normal/删除.imageset/删除@3x.png differ diff --git a/SynthReel/Source/Assets.xcassets/normal/弹窗按钮背景.imageset/Contents.json b/SynthReel/Source/Assets.xcassets/normal/弹窗按钮背景.imageset/Contents.json index 4a269be..9b354e6 100644 --- a/SynthReel/Source/Assets.xcassets/normal/弹窗按钮背景.imageset/Contents.json +++ b/SynthReel/Source/Assets.xcassets/normal/弹窗按钮背景.imageset/Contents.json @@ -7,11 +7,33 @@ { "filename" : "弹窗按钮背景@2x.png", "idiom" : "universal", + "resizing" : { + "cap-insets" : { + "left" : 94, + "right" : 92 + }, + "center" : { + "mode" : "tile", + "width" : 1 + }, + "mode" : "3-part-horizontal" + }, "scale" : "2x" }, { "filename" : "弹窗按钮背景@3x.png", "idiom" : "universal", + "resizing" : { + "cap-insets" : { + "left" : 136, + "right" : 141 + }, + "center" : { + "mode" : "tile", + "width" : 1 + }, + "mode" : "3-part-horizontal" + }, "scale" : "3x" } ], diff --git a/SynthReel/Source/Assets.xcassets/normal/收藏.imageset/Contents.json b/SynthReel/Source/Assets.xcassets/normal/收藏.imageset/Contents.json new file mode 100644 index 0000000..2fcc7b2 --- /dev/null +++ b/SynthReel/Source/Assets.xcassets/normal/收藏.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "收藏@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "收藏@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/SynthReel/Source/Assets.xcassets/normal/收藏.imageset/收藏@2x.png b/SynthReel/Source/Assets.xcassets/normal/收藏.imageset/收藏@2x.png new file mode 100644 index 0000000..7f8a87f Binary files /dev/null and b/SynthReel/Source/Assets.xcassets/normal/收藏.imageset/收藏@2x.png differ diff --git a/SynthReel/Source/Assets.xcassets/normal/收藏.imageset/收藏@3x.png b/SynthReel/Source/Assets.xcassets/normal/收藏.imageset/收藏@3x.png new file mode 100644 index 0000000..0387c4a Binary files /dev/null and b/SynthReel/Source/Assets.xcassets/normal/收藏.imageset/收藏@3x.png differ diff --git a/SynthReel/Source/Info.plist b/SynthReel/Source/Info.plist index 8bacbe1..97a8b46 100644 --- a/SynthReel/Source/Info.plist +++ b/SynthReel/Source/Info.plist @@ -25,6 +25,8 @@ 1203129771732470 NSUserTrackingUsageDescription We will use your advertising identifier (IDFA) to provide a personalized advertising experience. + GADApplicationIdentifier + ca-app-pub-6275401933109862~8769451155 FacebookClientToken 3e671125d76ef8555893cd453337ccfc UIApplicationSceneManifest diff --git a/SynthReel/Source/en.lproj/Localizable.strings b/SynthReel/Source/en.lproj/Localizable.strings index 22dbb52..0994a3f 100644 --- a/SynthReel/Source/en.lproj/Localizable.strings +++ b/SynthReel/Source/en.lproj/Localizable.strings @@ -28,6 +28,7 @@ "synthreel_user_agreement" = "User Agreement"; "synthreel_delet_account" = "Delet Account"; "synthreel_visit_website" = "visit website"; +"synthreel_order_Record" = "Order Record"; "Viral Hits" = "Viral Hits"; "Live Trending Rankings" = "Live Trending Rankings"; "empty_title_01" = "No search results"; @@ -102,7 +103,19 @@ "pay_error_6" = "You have unfinished in-app purchases, please restore them first."; "synthreel_open_notification_later" = "later"; +"synthreel_allow" = "Allow"; "coins_pack_alert_title" = "Daily Reward is waiting!"; "synthreel_claim_now" = "Claim Now"; "synthreel_daily_coins" = "Daily Coins"; "apns_alert_title" = "Don’t miss updates!"; +"apns_alert_text" = "Get new episode alerts & rewards."; +"updates_alert_title" = "Discover a new version"; +"synthreel_update_now" = "Upgrade now"; +"logout_alert_title" = "Leaving so soon?"; +"logout_alert_text" = "Your progress will be saved."; +"synthreel_logout" = "Log out"; +"synthreel_cancel" = "Cancel"; +"remove_collect_alert_title" = "Remove from your list?"; +"remove_collect_alert_text" = "This drama will be removed from your saved list."; +"synthreel_remove" = "Remove"; +"synthreel_my_wallet" = "My Wallet"; diff --git a/SynthReel/SynthReel.entitlements b/SynthReel/SynthReel.entitlements index 80b5221..fe942f6 100644 --- a/SynthReel/SynthReel.entitlements +++ b/SynthReel/SynthReel.entitlements @@ -8,5 +8,9 @@ Default + com.apple.developer.associated-domains + + applinks:synthreel.go.link + diff --git a/build/XCBuildData/ed244defbab6d2c20636b52ac76eb0ed.xcbuilddata/build-request.json b/build/XCBuildData/ed244defbab6d2c20636b52ac76eb0ed.xcbuilddata/build-request.json new file mode 100644 index 0000000..38eab09 --- /dev/null +++ b/build/XCBuildData/ed244defbab6d2c20636b52ac76eb0ed.xcbuilddata/build-request.json @@ -0,0 +1,27 @@ +{ + "buildCommand" : { + "command" : "build", + "skipDependencies" : false, + "style" : "buildOnly" + }, + "configuredTargets" : [ + + ], + "continueBuildingAfterErrors" : false, + "dependencyScope" : "workspace", + "enableIndexBuildArena" : false, + "hideShellScriptEnvironment" : false, + "parameters" : { + "action" : "build", + "overrides" : { + + } + }, + "qos" : "utility", + "schemeCommand" : "launch", + "showNonLoggedProgress" : true, + "useDryRun" : false, + "useImplicitDependencies" : false, + "useLegacyBuildLocations" : false, + "useParallelTargets" : true +} \ No newline at end of file diff --git a/build/XCBuildData/ed244defbab6d2c20636b52ac76eb0ed.xcbuilddata/description.msgpack b/build/XCBuildData/ed244defbab6d2c20636b52ac76eb0ed.xcbuilddata/description.msgpack new file mode 100644 index 0000000..c43eb88 Binary files /dev/null and b/build/XCBuildData/ed244defbab6d2c20636b52ac76eb0ed.xcbuilddata/description.msgpack differ diff --git a/build/XCBuildData/ed244defbab6d2c20636b52ac76eb0ed.xcbuilddata/manifest.json b/build/XCBuildData/ed244defbab6d2c20636b52ac76eb0ed.xcbuilddata/manifest.json new file mode 100644 index 0000000..7391713 --- /dev/null +++ b/build/XCBuildData/ed244defbab6d2c20636b52ac76eb0ed.xcbuilddata/manifest.json @@ -0,0 +1 @@ +{"client":{"name":"basic","version":0,"file-system":"device-agnostic","perform-ownership-analysis":"no"},"targets":{"":[""]},"commands":{"":{"tool":"phony","inputs":[""],"outputs":[""]},"P0:::Gate WorkspaceHeaderMapVFSFilesWritten":{"tool":"phony","inputs":[],"outputs":[""]}}} \ No newline at end of file diff --git a/build/XCBuildData/ed244defbab6d2c20636b52ac76eb0ed.xcbuilddata/target-graph.txt b/build/XCBuildData/ed244defbab6d2c20636b52ac76eb0ed.xcbuilddata/target-graph.txt new file mode 100644 index 0000000..b83b158 --- /dev/null +++ b/build/XCBuildData/ed244defbab6d2c20636b52ac76eb0ed.xcbuilddata/target-graph.txt @@ -0,0 +1 @@ +Target dependency graph (0 target) \ No newline at end of file diff --git a/build/XCBuildData/ed244defbab6d2c20636b52ac76eb0ed.xcbuilddata/task-store.msgpack b/build/XCBuildData/ed244defbab6d2c20636b52ac76eb0ed.xcbuilddata/task-store.msgpack new file mode 100644 index 0000000..6cef3fe Binary files /dev/null and b/build/XCBuildData/ed244defbab6d2c20636b52ac76eb0ed.xcbuilddata/task-store.msgpack differ