登陆功能
2
Podfile
@ -20,7 +20,7 @@ target 'SynthReel' do
|
|||||||
pod 'YYCategories'
|
pod 'YYCategories'
|
||||||
pod 'YYText'
|
pod 'YYText'
|
||||||
pod 'Kingfisher'
|
pod 'Kingfisher'
|
||||||
pod 'SmartCodable'
|
pod 'SmartCodable','5.0.15'
|
||||||
pod 'Moya'
|
pod 'Moya'
|
||||||
pod 'SVProgressHUD'
|
pod 'SVProgressHUD'
|
||||||
pod 'Toast'
|
pod 'Toast'
|
||||||
|
|||||||
@ -146,6 +146,24 @@
|
|||||||
3754ACFC2ED9A36C009EBCAD /* SRCoinsPackModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3754ACFB2ED9A36C009EBCAD /* SRCoinsPackModel.swift */; };
|
3754ACFC2ED9A36C009EBCAD /* SRCoinsPackModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3754ACFB2ED9A36C009EBCAD /* SRCoinsPackModel.swift */; };
|
||||||
3754ACFE2ED9A3A0009EBCAD /* SRCoinsPackReceiveModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3754ACFD2ED9A3A0009EBCAD /* SRCoinsPackReceiveModel.swift */; };
|
3754ACFE2ED9A3A0009EBCAD /* SRCoinsPackReceiveModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3754ACFD2ED9A3A0009EBCAD /* SRCoinsPackReceiveModel.swift */; };
|
||||||
3754AD022EDA8AF7009EBCAD /* SRLoginController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3754AD012EDA8AF7009EBCAD /* SRLoginController.swift */; };
|
3754AD022EDA8AF7009EBCAD /* SRLoginController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3754AD012EDA8AF7009EBCAD /* SRLoginController.swift */; };
|
||||||
|
3754AD1A2EDD745A009EBCAD /* SRVideoLockView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3754AD192EDD745A009EBCAD /* SRVideoLockView.swift */; };
|
||||||
|
3754AD1C2EDD77BA009EBCAD /* SRVideoUnlockResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3754AD1B2EDD77BA009EBCAD /* SRVideoUnlockResult.swift */; };
|
||||||
|
3754AD202EDD866F009EBCAD /* FacebookBasics in Frameworks */ = {isa = PBXBuildFile; productRef = 3754AD1F2EDD866F009EBCAD /* FacebookBasics */; };
|
||||||
|
3754AD222EDD866F009EBCAD /* FacebookCore in Frameworks */ = {isa = PBXBuildFile; productRef = 3754AD212EDD866F009EBCAD /* FacebookCore */; };
|
||||||
|
3754AD242EDD866F009EBCAD /* FacebookLogin in Frameworks */ = {isa = PBXBuildFile; productRef = 3754AD232EDD866F009EBCAD /* FacebookLogin */; };
|
||||||
|
3754AD272EDD86FB009EBCAD /* FirebaseAnalytics in Frameworks */ = {isa = PBXBuildFile; productRef = 3754AD262EDD86FB009EBCAD /* FirebaseAnalytics */; };
|
||||||
|
3754AD292EDD86FB009EBCAD /* FirebaseAnalyticsCore in Frameworks */ = {isa = PBXBuildFile; productRef = 3754AD282EDD86FB009EBCAD /* FirebaseAnalyticsCore */; };
|
||||||
|
3754AD2B2EDD86FB009EBCAD /* FirebaseCore in Frameworks */ = {isa = PBXBuildFile; productRef = 3754AD2A2EDD86FB009EBCAD /* FirebaseCore */; };
|
||||||
|
3754AD2D2EDD86FB009EBCAD /* FirebaseCrashlytics in Frameworks */ = {isa = PBXBuildFile; productRef = 3754AD2C2EDD86FB009EBCAD /* FirebaseCrashlytics */; };
|
||||||
|
3754AD2F2EDD86FB009EBCAD /* FirebaseMessaging in Frameworks */ = {isa = PBXBuildFile; productRef = 3754AD2E2EDD86FB009EBCAD /* FirebaseMessaging */; };
|
||||||
|
3754AD312EDD939A009EBCAD /* SRUserLoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3754AD302EDD939A009EBCAD /* SRUserLoginView.swift */; };
|
||||||
|
3754AD332EDD96E0009EBCAD /* SRLoginButtonView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3754AD322EDD96E0009EBCAD /* SRLoginButtonView.swift */; };
|
||||||
|
3754AD362EDD9AA7009EBCAD /* SRLogin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3754AD352EDD9AA7009EBCAD /* SRLogin.swift */; };
|
||||||
|
3754AD382EDD9B5D009EBCAD /* SRTokenModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3754AD372EDD9B5D009EBCAD /* SRTokenModel.swift */; };
|
||||||
|
3754AD3A2EDD9BB1009EBCAD /* SRLogin+apple.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3754AD392EDD9BB1009EBCAD /* SRLogin+apple.swift */; };
|
||||||
|
3754AD3C2EDD9C01009EBCAD /* SRThirdModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3754AD3B2EDD9C01009EBCAD /* SRThirdModel.swift */; };
|
||||||
|
3754AD3E2EDD9C88009EBCAD /* SRLogin+FB.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3754AD3D2EDD9C88009EBCAD /* SRLogin+FB.swift */; };
|
||||||
|
3754AEF82EDE94CD009EBCAD /* SRUserRewardCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3754AEF72EDE94CD009EBCAD /* SRUserRewardCell.swift */; };
|
||||||
3779D0612ECF1CB8006B1698 /* SRShortHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3779D0602ECF1CB8006B1698 /* SRShortHeaderView.swift */; };
|
3779D0612ECF1CB8006B1698 /* SRShortHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3779D0602ECF1CB8006B1698 /* SRShortHeaderView.swift */; };
|
||||||
47BB39E2DD30787FA591F8EB /* Pods_SynthReel.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9255BF4D4B1CFDDB5CFFB43 /* Pods_SynthReel.framework */; };
|
47BB39E2DD30787FA591F8EB /* Pods_SynthReel.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F9255BF4D4B1CFDDB5CFFB43 /* Pods_SynthReel.framework */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
@ -291,6 +309,17 @@
|
|||||||
3754ACFB2ED9A36C009EBCAD /* SRCoinsPackModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRCoinsPackModel.swift; sourceTree = "<group>"; };
|
3754ACFB2ED9A36C009EBCAD /* SRCoinsPackModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRCoinsPackModel.swift; sourceTree = "<group>"; };
|
||||||
3754ACFD2ED9A3A0009EBCAD /* SRCoinsPackReceiveModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRCoinsPackReceiveModel.swift; sourceTree = "<group>"; };
|
3754ACFD2ED9A3A0009EBCAD /* SRCoinsPackReceiveModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRCoinsPackReceiveModel.swift; sourceTree = "<group>"; };
|
||||||
3754AD012EDA8AF7009EBCAD /* SRLoginController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRLoginController.swift; sourceTree = "<group>"; };
|
3754AD012EDA8AF7009EBCAD /* SRLoginController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRLoginController.swift; sourceTree = "<group>"; };
|
||||||
|
3754AD192EDD745A009EBCAD /* SRVideoLockView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRVideoLockView.swift; sourceTree = "<group>"; };
|
||||||
|
3754AD1B2EDD77BA009EBCAD /* SRVideoUnlockResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRVideoUnlockResult.swift; sourceTree = "<group>"; };
|
||||||
|
3754AD1D2EDD84DD009EBCAD /* SynthReel.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SynthReel.entitlements; sourceTree = "<group>"; };
|
||||||
|
3754AD302EDD939A009EBCAD /* SRUserLoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRUserLoginView.swift; sourceTree = "<group>"; };
|
||||||
|
3754AD322EDD96E0009EBCAD /* SRLoginButtonView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRLoginButtonView.swift; sourceTree = "<group>"; };
|
||||||
|
3754AD352EDD9AA7009EBCAD /* SRLogin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRLogin.swift; sourceTree = "<group>"; };
|
||||||
|
3754AD372EDD9B5D009EBCAD /* SRTokenModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRTokenModel.swift; sourceTree = "<group>"; };
|
||||||
|
3754AD392EDD9BB1009EBCAD /* SRLogin+apple.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SRLogin+apple.swift"; sourceTree = "<group>"; };
|
||||||
|
3754AD3B2EDD9C01009EBCAD /* SRThirdModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRThirdModel.swift; sourceTree = "<group>"; };
|
||||||
|
3754AD3D2EDD9C88009EBCAD /* SRLogin+FB.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SRLogin+FB.swift"; sourceTree = "<group>"; };
|
||||||
|
3754AEF72EDE94CD009EBCAD /* SRUserRewardCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRUserRewardCell.swift; sourceTree = "<group>"; };
|
||||||
3779D0602ECF1CB8006B1698 /* SRShortHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRShortHeaderView.swift; sourceTree = "<group>"; };
|
3779D0602ECF1CB8006B1698 /* SRShortHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SRShortHeaderView.swift; sourceTree = "<group>"; };
|
||||||
59DC746604B26E9FF802D317 /* Pods-SynthReel.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SynthReel.debug.xcconfig"; path = "Target Support Files/Pods-SynthReel/Pods-SynthReel.debug.xcconfig"; sourceTree = "<group>"; };
|
59DC746604B26E9FF802D317 /* Pods-SynthReel.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SynthReel.debug.xcconfig"; path = "Target Support Files/Pods-SynthReel/Pods-SynthReel.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
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 = "<group>"; };
|
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 = "<group>"; };
|
||||||
@ -302,9 +331,17 @@
|
|||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
3754AD272EDD86FB009EBCAD /* FirebaseAnalytics in Frameworks */,
|
||||||
03B1A84D2EC5DA43006C353F /* SnapKit in Frameworks */,
|
03B1A84D2EC5DA43006C353F /* SnapKit in Frameworks */,
|
||||||
|
3754AD222EDD866F009EBCAD /* FacebookCore in Frameworks */,
|
||||||
|
3754AD242EDD866F009EBCAD /* FacebookLogin in Frameworks */,
|
||||||
|
3754AD202EDD866F009EBCAD /* FacebookBasics in Frameworks */,
|
||||||
03B1A84A2EC5CE37006C353F /* ESTabBarController in Frameworks */,
|
03B1A84A2EC5CE37006C353F /* ESTabBarController in Frameworks */,
|
||||||
47BB39E2DD30787FA591F8EB /* Pods_SynthReel.framework in Frameworks */,
|
47BB39E2DD30787FA591F8EB /* Pods_SynthReel.framework in Frameworks */,
|
||||||
|
3754AD2D2EDD86FB009EBCAD /* FirebaseCrashlytics in Frameworks */,
|
||||||
|
3754AD2B2EDD86FB009EBCAD /* FirebaseCore in Frameworks */,
|
||||||
|
3754AD2F2EDD86FB009EBCAD /* FirebaseMessaging in Frameworks */,
|
||||||
|
3754AD292EDD86FB009EBCAD /* FirebaseAnalyticsCore in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -477,6 +514,7 @@
|
|||||||
children = (
|
children = (
|
||||||
03B1A8EE2EC72C78006C353F /* SRShortModel.swift */,
|
03B1A8EE2EC72C78006C353F /* SRShortModel.swift */,
|
||||||
03B1A9272ECC05B1006C353F /* SRShortDetailModel.swift */,
|
03B1A9272ECC05B1006C353F /* SRShortDetailModel.swift */,
|
||||||
|
3754AD1B2EDD77BA009EBCAD /* SRVideoUnlockResult.swift */,
|
||||||
);
|
);
|
||||||
path = M;
|
path = M;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -511,6 +549,7 @@
|
|||||||
03B1A94D2ECD604B006C353F /* SREpSelectorCell.swift */,
|
03B1A94D2ECD604B006C353F /* SREpSelectorCell.swift */,
|
||||||
3754ACD42ED82722009EBCAD /* SRDetailRecommendview.swift */,
|
3754ACD42ED82722009EBCAD /* SRDetailRecommendview.swift */,
|
||||||
3754ACD62ED82774009EBCAD /* SRDetailRecommendCell.swift */,
|
3754ACD62ED82774009EBCAD /* SRDetailRecommendCell.swift */,
|
||||||
|
3754AD192EDD745A009EBCAD /* SRVideoLockView.swift */,
|
||||||
);
|
);
|
||||||
path = V;
|
path = V;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -536,6 +575,7 @@
|
|||||||
03E9A7C82EC47177000D1067 /* SynthReel */ = {
|
03E9A7C82EC47177000D1067 /* SynthReel */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
3754AD1D2EDD84DD009EBCAD /* SynthReel.entitlements */,
|
||||||
03E9A7D02EC471D6000D1067 /* Delegate */,
|
03E9A7D02EC471D6000D1067 /* Delegate */,
|
||||||
03E9A7D22EC47204000D1067 /* Base */,
|
03E9A7D22EC47204000D1067 /* Base */,
|
||||||
03E9A7D32EC4720F000D1067 /* Class */,
|
03E9A7D32EC4720F000D1067 /* Class */,
|
||||||
@ -599,6 +639,7 @@
|
|||||||
03E9A7D42EC4764A000D1067 /* Libs */ = {
|
03E9A7D42EC4764A000D1067 /* Libs */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
3754AD342EDD9A8F009EBCAD /* SRLogin */,
|
||||||
3754ACD82ED83724009EBCAD /* FSPagerView */,
|
3754ACD82ED83724009EBCAD /* FSPagerView */,
|
||||||
3754ACCF2ED81F2F009EBCAD /* Alert */,
|
3754ACCF2ED81F2F009EBCAD /* Alert */,
|
||||||
3754ACC22ED6ED92009EBCAD /* Empty */,
|
3754ACC22ED6ED92009EBCAD /* Empty */,
|
||||||
@ -717,6 +758,9 @@
|
|||||||
370D2F242ED5807600571E77 /* SRAboutHeaderVIew.swift */,
|
370D2F242ED5807600571E77 /* SRAboutHeaderVIew.swift */,
|
||||||
370D2F262ED581BB00571E77 /* SRAboutCell.swift */,
|
370D2F262ED581BB00571E77 /* SRAboutCell.swift */,
|
||||||
3754ACF32ED98609009EBCAD /* SRCoinPackCell.swift */,
|
3754ACF32ED98609009EBCAD /* SRCoinPackCell.swift */,
|
||||||
|
3754AD302EDD939A009EBCAD /* SRUserLoginView.swift */,
|
||||||
|
3754AD322EDD96E0009EBCAD /* SRLoginButtonView.swift */,
|
||||||
|
3754AEF72EDE94CD009EBCAD /* SRUserRewardCell.swift */,
|
||||||
);
|
);
|
||||||
path = view;
|
path = view;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -825,6 +869,18 @@
|
|||||||
path = VC;
|
path = VC;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
3754AD342EDD9A8F009EBCAD /* SRLogin */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
3754AD352EDD9AA7009EBCAD /* SRLogin.swift */,
|
||||||
|
3754AD372EDD9B5D009EBCAD /* SRTokenModel.swift */,
|
||||||
|
3754AD392EDD9BB1009EBCAD /* SRLogin+apple.swift */,
|
||||||
|
3754AD3B2EDD9C01009EBCAD /* SRThirdModel.swift */,
|
||||||
|
3754AD3D2EDD9C88009EBCAD /* SRLogin+FB.swift */,
|
||||||
|
);
|
||||||
|
path = SRLogin;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
3779D05F2ECF1C8D006B1698 /* V */ = {
|
3779D05F2ECF1C8D006B1698 /* V */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -904,6 +960,8 @@
|
|||||||
packageReferences = (
|
packageReferences = (
|
||||||
03B1A8482EC5CE37006C353F /* XCRemoteSwiftPackageReference "ESTabBarController" */,
|
03B1A8482EC5CE37006C353F /* XCRemoteSwiftPackageReference "ESTabBarController" */,
|
||||||
03B1A84B2EC5DA43006C353F /* XCRemoteSwiftPackageReference "SnapKit" */,
|
03B1A84B2EC5DA43006C353F /* XCRemoteSwiftPackageReference "SnapKit" */,
|
||||||
|
3754AD1E2EDD866F009EBCAD /* XCRemoteSwiftPackageReference "facebook-ios-sdk" */,
|
||||||
|
3754AD252EDD86FB009EBCAD /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */,
|
||||||
);
|
);
|
||||||
preferredProjectObjectVersion = 77;
|
preferredProjectObjectVersion = 77;
|
||||||
productRefGroup = 03E9A7A82EC4716A000D1067 /* Products */;
|
productRefGroup = 03E9A7A82EC4716A000D1067 /* Products */;
|
||||||
@ -1041,11 +1099,13 @@
|
|||||||
370D2F1E2ED54C7F00571E77 /* SRHelpCenterController.swift in Sources */,
|
370D2F1E2ED54C7F00571E77 /* SRHelpCenterController.swift in Sources */,
|
||||||
03E9A7CA2EC47177000D1067 /* SceneDelegate.swift in Sources */,
|
03E9A7CA2EC47177000D1067 /* SceneDelegate.swift in Sources */,
|
||||||
370D2F252ED5807600571E77 /* SRAboutHeaderVIew.swift in Sources */,
|
370D2F252ED5807600571E77 /* SRAboutHeaderVIew.swift in Sources */,
|
||||||
|
3754AD332EDD96E0009EBCAD /* SRLoginButtonView.swift in Sources */,
|
||||||
03B1A8402EC5CA37006C353F /* AppDelegate+Config.swift in Sources */,
|
03B1A8402EC5CA37006C353F /* AppDelegate+Config.swift in Sources */,
|
||||||
03B1A9152ECAEE63006C353F /* SRHomeViralHitsCell.swift in Sources */,
|
03B1A9152ECAEE63006C353F /* SRHomeViralHitsCell.swift in Sources */,
|
||||||
03B1A8472EC5CBCF006C353F /* SRViewController.swift in Sources */,
|
03B1A8472EC5CBCF006C353F /* SRViewController.swift in Sources */,
|
||||||
370D2F052ED3FEE700571E77 /* SRHistoryCell.swift in Sources */,
|
370D2F052ED3FEE700571E77 /* SRHistoryCell.swift in Sources */,
|
||||||
3754ACEA2ED94065009EBCAD /* SRBaseWebViewController + Script.swift in Sources */,
|
3754ACEA2ED94065009EBCAD /* SRBaseWebViewController + Script.swift in Sources */,
|
||||||
|
3754AD3A2EDD9BB1009EBCAD /* SRLogin+apple.swift in Sources */,
|
||||||
03B1A9032EC8555B006C353F /* SRHomeYouLikeView.swift in Sources */,
|
03B1A9032EC8555B006C353F /* SRHomeYouLikeView.swift in Sources */,
|
||||||
03B1A9362ECC1D1D006C353F /* SRSearchRecordView.swift in Sources */,
|
03B1A9362ECC1D1D006C353F /* SRSearchRecordView.swift in Sources */,
|
||||||
03B1A8D82EC6D051006C353F /* SRCollectionView.swift in Sources */,
|
03B1A8D82EC6D051006C353F /* SRCollectionView.swift in Sources */,
|
||||||
@ -1058,16 +1118,19 @@
|
|||||||
03B1A83B2EC5C8E0006C353F /* SRToast.swift in Sources */,
|
03B1A83B2EC5C8E0006C353F /* SRToast.swift in Sources */,
|
||||||
03B1A9302ECC10D1006C353F /* SRSearchViewController.swift in Sources */,
|
03B1A9302ECC10D1006C353F /* SRSearchViewController.swift in Sources */,
|
||||||
03B1A8432EC5CB99006C353F /* SRTabBarController.swift in Sources */,
|
03B1A8432EC5CB99006C353F /* SRTabBarController.swift in Sources */,
|
||||||
|
3754AD3E2EDD9C88009EBCAD /* SRLogin+FB.swift in Sources */,
|
||||||
03B1A8EF2EC72C78006C353F /* SRShortModel.swift in Sources */,
|
03B1A8EF2EC72C78006C353F /* SRShortModel.swift in Sources */,
|
||||||
03B1A8ED2EC72C1F006C353F /* SRHomeModuleItem.swift in Sources */,
|
03B1A8ED2EC72C1F006C353F /* SRHomeModuleItem.swift in Sources */,
|
||||||
370D2F102ED4534500571E77 /* SRUserViewController.swift in Sources */,
|
370D2F102ED4534500571E77 /* SRUserViewController.swift in Sources */,
|
||||||
03B1A9112ECAC927006C353F /* SRHomeBingeWorthyCell.swift in Sources */,
|
03B1A9112ECAC927006C353F /* SRHomeBingeWorthyCell.swift in Sources */,
|
||||||
03E9A7F22EC4A8F6000D1067 /* UserDefaults+SRAdd.swift in Sources */,
|
03E9A7F22EC4A8F6000D1067 /* UserDefaults+SRAdd.swift in Sources */,
|
||||||
370D2F2B2ED597F700571E77 /* SRTopChartsCell.swift in Sources */,
|
370D2F2B2ED597F700571E77 /* SRTopChartsCell.swift in Sources */,
|
||||||
|
3754AD3C2EDD9C01009EBCAD /* SRThirdModel.swift in Sources */,
|
||||||
03B1A93A2ECC3F54006C353F /* SRSearchViewModel.swift in Sources */,
|
03B1A93A2ECC3F54006C353F /* SRSearchViewModel.swift in Sources */,
|
||||||
03E9A7F62EC4A9B1000D1067 /* SRUserInfo.swift in Sources */,
|
03E9A7F62EC4A9B1000D1067 /* SRUserInfo.swift in Sources */,
|
||||||
03B1A8F92EC813BC006C353F /* SRScrollView.swift in Sources */,
|
03B1A8F92EC813BC006C353F /* SRScrollView.swift in Sources */,
|
||||||
03B1A8E92EC721CD006C353F /* SRLabel.swift in Sources */,
|
03B1A8E92EC721CD006C353F /* SRLabel.swift in Sources */,
|
||||||
|
3754AD1A2EDD745A009EBCAD /* SRVideoLockView.swift in Sources */,
|
||||||
03B1A9282ECC05B1006C353F /* SRShortDetailModel.swift in Sources */,
|
03B1A9282ECC05B1006C353F /* SRShortDetailModel.swift in Sources */,
|
||||||
03980F592ECEED190006E317 /* SRMyShortViewController.swift in Sources */,
|
03980F592ECEED190006E317 /* SRMyShortViewController.swift in Sources */,
|
||||||
3754ACD32ED82113009EBCAD /* SRGradientbutton.swift in Sources */,
|
3754ACD32ED82113009EBCAD /* SRGradientbutton.swift in Sources */,
|
||||||
@ -1090,8 +1153,12 @@
|
|||||||
03B1A9012EC852B2006C353F /* SRHomeModuleView.swift in Sources */,
|
03B1A9012EC852B2006C353F /* SRHomeModuleView.swift in Sources */,
|
||||||
03E9A7EF2EC4A8AF000D1067 /* SRAccountManager.swift in Sources */,
|
03E9A7EF2EC4A8AF000D1067 /* SRAccountManager.swift in Sources */,
|
||||||
03B1A8F52EC81277006C353F /* SRHomeBannerView.swift in Sources */,
|
03B1A8F52EC81277006C353F /* SRHomeBannerView.swift in Sources */,
|
||||||
|
3754AD312EDD939A009EBCAD /* SRUserLoginView.swift in Sources */,
|
||||||
|
3754AD1C2EDD77BA009EBCAD /* SRVideoUnlockResult.swift in Sources */,
|
||||||
3754ACDC2ED83F80009EBCAD /* SRHomeHistoryBottomView.swift in Sources */,
|
3754ACDC2ED83F80009EBCAD /* SRHomeHistoryBottomView.swift in Sources */,
|
||||||
|
3754AEF82EDE94CD009EBCAD /* SRUserRewardCell.swift in Sources */,
|
||||||
03B1A9132ECAED04006C353F /* SRHomeViralHitsView.swift in Sources */,
|
03B1A9132ECAED04006C353F /* SRHomeViralHitsView.swift in Sources */,
|
||||||
|
3754AD382EDD9B5D009EBCAD /* SRTokenModel.swift in Sources */,
|
||||||
03B1A8DC2EC6D0EB006C353F /* SRHomeChildCell.swift in Sources */,
|
03B1A8DC2EC6D0EB006C353F /* SRHomeChildCell.swift in Sources */,
|
||||||
03B1A8552EC5E434006C353F /* UIFont+SRAdd.swift in Sources */,
|
03B1A8552EC5E434006C353F /* UIFont+SRAdd.swift in Sources */,
|
||||||
3779D0612ECF1CB8006B1698 /* SRShortHeaderView.swift in Sources */,
|
3779D0612ECF1CB8006B1698 /* SRShortHeaderView.swift in Sources */,
|
||||||
@ -1108,6 +1175,7 @@
|
|||||||
370D2F1C2ED4770800571E77 /* SRUserInfoModel.swift in Sources */,
|
370D2F1C2ED4770800571E77 /* SRUserInfoModel.swift in Sources */,
|
||||||
03B1A93C2ECC406E006C353F /* SRHotSearchView.swift in Sources */,
|
03B1A93C2ECC406E006C353F /* SRHotSearchView.swift in Sources */,
|
||||||
03B1A8E32EC6F577006C353F /* SRHomeMenuCell.swift in Sources */,
|
03B1A8E32EC6F577006C353F /* SRHomeMenuCell.swift in Sources */,
|
||||||
|
3754AD362EDD9AA7009EBCAD /* SRLogin.swift in Sources */,
|
||||||
3754ACE12ED93C4D009EBCAD /* SRCoinPackController.swift in Sources */,
|
3754ACE12ED93C4D009EBCAD /* SRCoinPackController.swift in Sources */,
|
||||||
3754ACD52ED82722009EBCAD /* SRDetailRecommendview.swift in Sources */,
|
3754ACD52ED82722009EBCAD /* SRDetailRecommendview.swift in Sources */,
|
||||||
);
|
);
|
||||||
@ -1141,6 +1209,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = SynthReel/SynthReel.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
@ -1160,7 +1229,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.hbqinjiu.SynthReel;
|
PRODUCT_BUNDLE_IDENTIFIER = com.drama.hive;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
@ -1184,6 +1253,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
CODE_SIGN_ENTITLEMENTS = SynthReel/SynthReel.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "Apple Development";
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
@ -1201,7 +1271,7 @@
|
|||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.hbqinjiu.SynthReel;
|
PRODUCT_BUNDLE_IDENTIFIER = com.drama.hive;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
@ -1380,6 +1450,22 @@
|
|||||||
minimumVersion = 5.7.1;
|
minimumVersion = 5.7.1;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
3754AD1E2EDD866F009EBCAD /* XCRemoteSwiftPackageReference "facebook-ios-sdk" */ = {
|
||||||
|
isa = XCRemoteSwiftPackageReference;
|
||||||
|
repositoryURL = "https://github.com/facebook/facebook-ios-sdk";
|
||||||
|
requirement = {
|
||||||
|
kind = upToNextMajorVersion;
|
||||||
|
minimumVersion = 14.1.0;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
3754AD252EDD86FB009EBCAD /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = {
|
||||||
|
isa = XCRemoteSwiftPackageReference;
|
||||||
|
repositoryURL = "https://github.com/firebase/firebase-ios-sdk";
|
||||||
|
requirement = {
|
||||||
|
kind = upToNextMajorVersion;
|
||||||
|
minimumVersion = 12.6.0;
|
||||||
|
};
|
||||||
|
};
|
||||||
/* End XCRemoteSwiftPackageReference section */
|
/* End XCRemoteSwiftPackageReference section */
|
||||||
|
|
||||||
/* Begin XCSwiftPackageProductDependency section */
|
/* Begin XCSwiftPackageProductDependency section */
|
||||||
@ -1393,6 +1479,46 @@
|
|||||||
package = 03B1A84B2EC5DA43006C353F /* XCRemoteSwiftPackageReference "SnapKit" */;
|
package = 03B1A84B2EC5DA43006C353F /* XCRemoteSwiftPackageReference "SnapKit" */;
|
||||||
productName = SnapKit;
|
productName = SnapKit;
|
||||||
};
|
};
|
||||||
|
3754AD1F2EDD866F009EBCAD /* FacebookBasics */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = 3754AD1E2EDD866F009EBCAD /* XCRemoteSwiftPackageReference "facebook-ios-sdk" */;
|
||||||
|
productName = FacebookBasics;
|
||||||
|
};
|
||||||
|
3754AD212EDD866F009EBCAD /* FacebookCore */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = 3754AD1E2EDD866F009EBCAD /* XCRemoteSwiftPackageReference "facebook-ios-sdk" */;
|
||||||
|
productName = FacebookCore;
|
||||||
|
};
|
||||||
|
3754AD232EDD866F009EBCAD /* FacebookLogin */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = 3754AD1E2EDD866F009EBCAD /* XCRemoteSwiftPackageReference "facebook-ios-sdk" */;
|
||||||
|
productName = FacebookLogin;
|
||||||
|
};
|
||||||
|
3754AD262EDD86FB009EBCAD /* FirebaseAnalytics */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = 3754AD252EDD86FB009EBCAD /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
|
||||||
|
productName = FirebaseAnalytics;
|
||||||
|
};
|
||||||
|
3754AD282EDD86FB009EBCAD /* FirebaseAnalyticsCore */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = 3754AD252EDD86FB009EBCAD /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
|
||||||
|
productName = FirebaseAnalyticsCore;
|
||||||
|
};
|
||||||
|
3754AD2A2EDD86FB009EBCAD /* FirebaseCore */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = 3754AD252EDD86FB009EBCAD /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
|
||||||
|
productName = FirebaseCore;
|
||||||
|
};
|
||||||
|
3754AD2C2EDD86FB009EBCAD /* FirebaseCrashlytics */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = 3754AD252EDD86FB009EBCAD /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
|
||||||
|
productName = FirebaseCrashlytics;
|
||||||
|
};
|
||||||
|
3754AD2E2EDD86FB009EBCAD /* FirebaseMessaging */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
package = 3754AD252EDD86FB009EBCAD /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
|
||||||
|
productName = FirebaseMessaging;
|
||||||
|
};
|
||||||
/* End XCSwiftPackageProductDependency section */
|
/* End XCSwiftPackageProductDependency section */
|
||||||
};
|
};
|
||||||
rootObject = 03E9A79F2EC4716A000D1067 /* Project object */;
|
rootObject = 03E9A79F2EC4716A000D1067 /* Project object */;
|
||||||
|
|||||||
@ -1,6 +1,24 @@
|
|||||||
{
|
{
|
||||||
"originHash" : "0e62262c59a183f44748a161870cc0f2b76e1b0e46f648559704e4be9de523b9",
|
"originHash" : "deb3ea9bc9f7ea16d149d6025086ec795e4f5fc740540ae9e5e8308e4e3e8aec",
|
||||||
"pins" : [
|
"pins" : [
|
||||||
|
{
|
||||||
|
"identity" : "abseil-cpp-binary",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/google/abseil-cpp-binary.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "bbe8b69694d7873315fd3a4ad41efe043e1c07c5",
|
||||||
|
"version" : "1.2024072200.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "app-check",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/google/app-check.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "61b85103a1aeed8218f17c794687781505fbbef5",
|
||||||
|
"version" : "11.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"identity" : "estabbarcontroller",
|
"identity" : "estabbarcontroller",
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
@ -10,6 +28,114 @@
|
|||||||
"version" : "2.9.0"
|
"version" : "2.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"identity" : "facebook-ios-sdk",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/facebook/facebook-ios-sdk",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "c19607d535864533523d1f437c84035e5fb101cf",
|
||||||
|
"version" : "14.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "firebase-ios-sdk",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/firebase/firebase-ios-sdk",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "087bb95235f676c1a37e928769a5b6645dcbd325",
|
||||||
|
"version" : "12.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "google-ads-on-device-conversion-ios-sdk",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/googleads/google-ads-on-device-conversion-ios-sdk",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "35b601a60fbbea2de3ea461f604deaaa4d8bbd0c",
|
||||||
|
"version" : "3.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "googleappmeasurement",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/google/GoogleAppMeasurement.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "c2d59acf17a8ba7ed80a763593c67c9c7c006ad1",
|
||||||
|
"version" : "12.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "googledatatransport",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/google/GoogleDataTransport.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "617af071af9aa1d6a091d59a202910ac482128f9",
|
||||||
|
"version" : "10.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "googleutilities",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/google/GoogleUtilities.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "60da361632d0de02786f709bdc0c4df340f7613e",
|
||||||
|
"version" : "8.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "grpc-binary",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/google/grpc-binary.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "75b31c842f664a0f46a2e590a570e370249fd8f6",
|
||||||
|
"version" : "1.69.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "gtm-session-fetcher",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/google/gtm-session-fetcher.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "fb7f2740b1570d2f7599c6bb9531bf4fad6974b7",
|
||||||
|
"version" : "5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "interop-ios-for-google-sdks",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/google/interop-ios-for-google-sdks.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "040d087ac2267d2ddd4cca36c757d1c6a05fdbfe",
|
||||||
|
"version" : "101.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "leveldb",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/firebase/leveldb.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "a0bc79961d7be727d258d33d5a6b2f1023270ba1",
|
||||||
|
"version" : "1.22.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "nanopb",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/firebase/nanopb.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "b7e1104502eca3a213b46303391ca4d3bc8ddec1",
|
||||||
|
"version" : "2.30910.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "promises",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/google/promises.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "540318ecedd63d883069ae7f1ed811a2df00b6ac",
|
||||||
|
"version" : "2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"identity" : "snapkit",
|
"identity" : "snapkit",
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
@ -18,6 +144,15 @@
|
|||||||
"revision" : "2842e6e84e82eb9a8dac0100ca90d9444b0307f4",
|
"revision" : "2842e6e84e82eb9a8dac0100ca90d9444b0307f4",
|
||||||
"version" : "5.7.1"
|
"version" : "5.7.1"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"identity" : "swift-protobuf",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/apple/swift-protobuf.git",
|
||||||
|
"state" : {
|
||||||
|
"revision" : "c169a5744230951031770e27e475ff6eefe51f9d",
|
||||||
|
"version" : "1.33.3"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"version" : 3
|
"version" : 3
|
||||||
|
|||||||
@ -89,6 +89,24 @@ struct SRShortApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static func requestCoinUnlockVideo(shortId: String?, videoId: String?) async -> SRVideoUnlockResult? {
|
||||||
|
|
||||||
|
await withCheckedContinuation { continuation in
|
||||||
|
var param = SRNetwork.Parameters(path: "/buy_video")
|
||||||
|
param.isToast = true
|
||||||
|
param.method = .post
|
||||||
|
param.parameters = [
|
||||||
|
"short_play_id": shortId ?? "",
|
||||||
|
"video_id": videoId ?? "0"
|
||||||
|
]
|
||||||
|
|
||||||
|
SRNetwork.request(parameters: param) { (response: SRNetwork.Response<SRVideoUnlockResult>) in
|
||||||
|
continuation.resume(returning: response.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -22,4 +22,93 @@ struct SRUserApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static func requestregister() async -> SRTokenModel? {
|
||||||
|
|
||||||
|
await withCheckedContinuation { continuation in
|
||||||
|
var param = SRNetwork.Parameters(path: "/customer/register")
|
||||||
|
param.method = .get
|
||||||
|
SRNetwork.request(parameters: param) { (response: SRNetwork.Response<SRTokenModel>) in
|
||||||
|
continuation.resume(returning: response.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func requestLeave() async {
|
||||||
|
await withCheckedContinuation { continuation in
|
||||||
|
var param = SRNetwork.Parameters(path: "/customer/leaveApp")
|
||||||
|
param.method = .post
|
||||||
|
SRNetwork.request(parameters: param) { (_: SRNetwork.Response<String>) in
|
||||||
|
continuation.resume()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func requestEnterApp() async {
|
||||||
|
await withCheckedContinuation { continuation in
|
||||||
|
var param = SRNetwork.Parameters(path: "/customer/enterTheApp")
|
||||||
|
param.method = .post
|
||||||
|
SRNetwork.request(parameters: param) { (_: SRNetwork.Response<String>) in
|
||||||
|
continuation.resume()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func requestStatOnLine() async {
|
||||||
|
await withCheckedContinuation { continuation in
|
||||||
|
var param = SRNetwork.Parameters(path: "/customer/onLine")
|
||||||
|
param.method = .post
|
||||||
|
SRNetwork.request(parameters: param) { (_: SRNetwork.Response<String>) in
|
||||||
|
continuation.resume()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func requestStatApnsClick(id: String, title: String) async {
|
||||||
|
await withCheckedContinuation { continuation in
|
||||||
|
var param = SRNetwork.Parameters(path: "/message/sendReport")
|
||||||
|
param.method = .post
|
||||||
|
param.parameters = [
|
||||||
|
"message_id" : id,
|
||||||
|
"title" : title
|
||||||
|
]
|
||||||
|
SRNetwork.request(parameters: param) { (_: SRNetwork.Response<String>) in
|
||||||
|
continuation.resume()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func requestUploadApnsDeviceToken(token: String) async {
|
||||||
|
await withCheckedContinuation { continuation in
|
||||||
|
var param = SRNetwork.Parameters(path: "/customer/onLine")
|
||||||
|
param.method = .post
|
||||||
|
param.parameters = [
|
||||||
|
"fcm_token": token
|
||||||
|
]
|
||||||
|
SRNetwork.request(parameters: param) { (_: SRNetwork.Response<String>) in
|
||||||
|
continuation.resume()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func requestSignThirdLogin(model: SRThirdModel) async -> SRTokenModel? {
|
||||||
|
await withCheckedContinuation { continuation in
|
||||||
|
var param = SRNetwork.Parameters(path: "/customer/login")
|
||||||
|
param.method = .post
|
||||||
|
param.parameters = model.toDictionary()
|
||||||
|
SRNetwork.request(parameters: param) { (response: SRNetwork.Response<SRTokenModel>) in
|
||||||
|
continuation.resume(returning: response.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func requestLogout() async -> SRTokenModel? {
|
||||||
|
await withCheckedContinuation { continuation in
|
||||||
|
var param = SRNetwork.Parameters(path: "/customer/signout")
|
||||||
|
param.method = .post
|
||||||
|
SRNetwork.request(parameters: param) { (response: SRNetwork.Response<SRTokenModel>) in
|
||||||
|
continuation.resume(returning: response.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,7 +30,7 @@ extension SRNetwork {
|
|||||||
var data: T?
|
var data: T?
|
||||||
var msg: String?
|
var msg: String?
|
||||||
|
|
||||||
@SmartIgnored
|
@IgnoredKey
|
||||||
var rawData: Any?
|
var rawData: Any?
|
||||||
|
|
||||||
var isSuccess: Bool {
|
var isSuccess: Bool {
|
||||||
|
|||||||
@ -15,13 +15,16 @@ class SRPanModalContentView: HWPanModalContentView {
|
|||||||
|
|
||||||
var contentHeight = UIScreen.height * (2 / 3)
|
var contentHeight = UIScreen.height * (2 / 3)
|
||||||
|
|
||||||
|
var bgImage: UIImage? = UIImage(named: "pan_bg_image_01")
|
||||||
|
|
||||||
|
|
||||||
///更新UI contentSize发生变化时调用
|
///更新UI contentSize发生变化时调用
|
||||||
func setNeedsLayoutUpdate() {
|
func setNeedsLayoutUpdate() {
|
||||||
self.panModalSetNeedsLayoutUpdate()
|
self.panModalSetNeedsLayoutUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy var bgImageView: UIImageView = {
|
lazy var bgImageView: UIImageView = {
|
||||||
let imageView = UIImageView(image: UIImage(named: "pan_bg_image_01"))
|
let imageView = UIImageView(image: bgImage)
|
||||||
return imageView
|
return imageView
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -35,6 +38,18 @@ class SRPanModalContentView: HWPanModalContentView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 子类更新背景图
|
||||||
|
func updateBackgroundImage(_ img: UIImage?) {
|
||||||
|
self.bgImage = img
|
||||||
|
self.bgImageView.image = img
|
||||||
|
}
|
||||||
|
|
||||||
|
// 子类更新高度
|
||||||
|
func updateContentHeight(_ height: CGFloat) {
|
||||||
|
self.contentHeight = height
|
||||||
|
self.panModalSetNeedsLayoutUpdate()
|
||||||
|
}
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
required init?(coder: NSCoder) {
|
||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,7 +32,7 @@ class SRShortModel: NSObject, SmartCodable {
|
|||||||
|
|
||||||
var category_name :String?
|
var category_name :String?
|
||||||
var category_id :String?
|
var category_id :String?
|
||||||
@SmartIgnored
|
@IgnoredKey
|
||||||
var cellHeight: CGFloat = 0
|
var cellHeight: CGFloat = 0
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
25
SynthReel/Class/Player/M/SRVideoUnlockResult.swift
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
//
|
||||||
|
// SRVideoUnlockResult.swift
|
||||||
|
// SynthReel
|
||||||
|
//
|
||||||
|
// Created by CSGY on 2025/12/1.
|
||||||
|
// Copyright © 2025 SR. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import SmartCodable
|
||||||
|
|
||||||
|
struct SRVideoUnlockResult: SmartCodable {
|
||||||
|
enum Status: String, SmartCaseDefaultable {
|
||||||
|
///前面还有没购买的剧
|
||||||
|
case jump = "jump"
|
||||||
|
///没找到视频
|
||||||
|
case noPlay = "no_play"
|
||||||
|
///金币不足跳充值
|
||||||
|
case notEnough = "not_enough"
|
||||||
|
///购买成功
|
||||||
|
case success = "success"
|
||||||
|
}
|
||||||
|
|
||||||
|
var status: Status?
|
||||||
|
}
|
||||||
@ -15,6 +15,7 @@ class SREpSelectorCell: UICollectionViewCell {
|
|||||||
var model: SRVideoInfoModel? {
|
var model: SRVideoInfoModel? {
|
||||||
didSet {
|
didSet {
|
||||||
numLabel.text = model?.episode
|
numLabel.text = model?.episode
|
||||||
|
lockImageview.isHidden = !(model?.is_lock ?? true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,6 +49,8 @@ class SREpSelectorCell: UICollectionViewCell {
|
|||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
lazy var lockImageview = UIImageView.init(image: .lock)
|
||||||
|
|
||||||
lazy var boderLayer: CAShapeLayer = {
|
lazy var boderLayer: CAShapeLayer = {
|
||||||
let layer = CAShapeLayer()
|
let layer = CAShapeLayer()
|
||||||
return layer
|
return layer
|
||||||
@ -64,6 +67,7 @@ class SREpSelectorCell: UICollectionViewCell {
|
|||||||
contentView.addSubview(boderView)
|
contentView.addSubview(boderView)
|
||||||
boderView.layer.addSublayer(boderLayer)
|
boderView.layer.addSublayer(boderLayer)
|
||||||
contentView.addSubview(numLabel)
|
contentView.addSubview(numLabel)
|
||||||
|
contentView.addSubview(lockImageview)
|
||||||
|
|
||||||
numLabel.snp.makeConstraints { make in
|
numLabel.snp.makeConstraints { make in
|
||||||
make.center.equalToSuperview()
|
make.center.equalToSuperview()
|
||||||
@ -73,6 +77,12 @@ class SREpSelectorCell: UICollectionViewCell {
|
|||||||
make.edges.equalToSuperview()
|
make.edges.equalToSuperview()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lockImageview.snp.makeConstraints { make in
|
||||||
|
make.right.top.equalToSuperview().inset(4)
|
||||||
|
make.width.height.equalTo(12)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -105,7 +105,6 @@ class SREpSelectorView: SRPanModalContentView {
|
|||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
|
|
||||||
sr_setupUI()
|
sr_setupUI()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,6 +188,21 @@ extension SREpSelectorView: UICollectionViewDelegate, UICollectionViewDataSource
|
|||||||
}
|
}
|
||||||
|
|
||||||
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||||
|
|
||||||
|
guard let epList = self.model?.episodeList else { return }
|
||||||
|
if self.selectedIndex == indexPath.row { return }
|
||||||
|
|
||||||
|
let lastIndex = indexPath.row - 1
|
||||||
|
var lastIsLock = false
|
||||||
|
if lastIndex > 0 && lastIndex < epList.count {
|
||||||
|
let lastModel = epList[lastIndex]
|
||||||
|
lastIsLock = lastModel.is_lock ?? false
|
||||||
|
}
|
||||||
|
if lastIsLock {
|
||||||
|
SRToast.show(text: "buy_fail_toast_02".localized)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
self.didSelected?(indexPath.row)
|
self.didSelected?(indexPath.row)
|
||||||
Task {
|
Task {
|
||||||
await self.dismiss(animated: true)
|
await self.dismiss(animated: true)
|
||||||
|
|||||||
@ -116,6 +116,7 @@ class SRShortDetailControlView: JXPlayerListControlView {
|
|||||||
return button
|
return button
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
||||||
lazy var playerImageView: UIImageView = {
|
lazy var playerImageView: UIImageView = {
|
||||||
let imageView = UIImageView(image: UIImage(named: "play_icon_02"))
|
let imageView = UIImageView(image: UIImage(named: "play_icon_02"))
|
||||||
imageView.isHidden = true
|
imageView.isHidden = true
|
||||||
@ -191,7 +192,7 @@ extension SRShortDetailControlView {
|
|||||||
addSubview(epButton)
|
addSubview(epButton)
|
||||||
addSubview(collectButton)
|
addSubview(collectButton)
|
||||||
addSubview(playerImageView)
|
addSubview(playerImageView)
|
||||||
|
|
||||||
progressBgView.snp.makeConstraints { make in
|
progressBgView.snp.makeConstraints { make in
|
||||||
make.left.equalToSuperview().offset(15)
|
make.left.equalToSuperview().offset(15)
|
||||||
make.centerX.equalToSuperview()
|
make.centerX.equalToSuperview()
|
||||||
|
|||||||
@ -23,16 +23,42 @@ class SRShortDetailPlayerCell: JXPlayerListCell {
|
|||||||
return self.viewModel as? SRShortPlayerViewModel
|
return self.viewModel as? SRShortPlayerViewModel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var hasLastEpisodeUnlocked: Bool = false {
|
||||||
|
didSet {
|
||||||
|
self.lockView.hasLastEpisodeUnlocked = hasLastEpisodeUnlocked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private lazy var lockView: SRVideoLockView = {
|
||||||
|
let view = SRVideoLockView()
|
||||||
|
view.clickUnlockButton = { [weak self] in
|
||||||
|
Task {
|
||||||
|
await self?.sr_viewModel?.handleUnlockVideo()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
override var model: Any? {
|
override var model: Any? {
|
||||||
didSet {
|
didSet {
|
||||||
let model = self.model as? SRVideoInfoModel
|
let model = self.model as? SRVideoInfoModel
|
||||||
self.player.setPlayUrl(url: model?.video_url ?? "")
|
self.player.setPlayUrl(url: model?.video_url ?? "")
|
||||||
|
|
||||||
// self.lockView.isHidden = !(model?.is_lock ?? true)
|
self.lockView.isHidden = !(model?.is_lock ?? true)
|
||||||
// lockView.videoInfo = model
|
lockView.videoInfo = model
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
|
||||||
|
sr_setupLayout()
|
||||||
|
}
|
||||||
|
|
||||||
|
@MainActor required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
var shortModel: SRShortModel? {
|
var shortModel: SRShortModel? {
|
||||||
didSet {
|
didSet {
|
||||||
self.sr_controlView.shortModel = shortModel
|
self.sr_controlView.shortModel = shortModel
|
||||||
@ -41,3 +67,16 @@ class SRShortDetailPlayerCell: JXPlayerListCell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extension SRShortDetailPlayerCell {
|
||||||
|
|
||||||
|
private func sr_setupLayout() {
|
||||||
|
addSubview(lockView)
|
||||||
|
|
||||||
|
lockView.snp.makeConstraints { make in
|
||||||
|
make.edges.equalToSuperview()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
120
SynthReel/Class/Player/V/SRVideoLockView.swift
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
//
|
||||||
|
// SRVideoLockView.swift
|
||||||
|
// SynthReel
|
||||||
|
//
|
||||||
|
// Created by CSGY on 2025/12/1.
|
||||||
|
// Copyright © 2025 SR. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class SRVideoLockView: UIView {
|
||||||
|
|
||||||
|
var clickUnlockButton: (() -> Void)?
|
||||||
|
|
||||||
|
var adUnlockButton: (() -> Void)?
|
||||||
|
|
||||||
|
var videoInfo: SRVideoInfoModel? {
|
||||||
|
didSet {
|
||||||
|
unlockButton.setNeedsUpdateConfiguration()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var hasLastEpisodeUnlocked = false {
|
||||||
|
didSet {
|
||||||
|
unlockButton.setNeedsUpdateConfiguration()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy var unlockStackView: UIStackView = {
|
||||||
|
let stack = UIStackView()
|
||||||
|
stack.axis = .vertical
|
||||||
|
stack.spacing = 12
|
||||||
|
stack.distribution = .fillEqually
|
||||||
|
return stack
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var unlockButton: UIButton = {
|
||||||
|
var config = UIButton.Configuration.plain()
|
||||||
|
config.image = UIImage(named: "lock")
|
||||||
|
config.imagePadding = 6
|
||||||
|
// 设置背景图片(使用 UIImage 作为背景)
|
||||||
|
config.background.image = UIImage(named: "unlockButtonBg")
|
||||||
|
config.background.imageContentMode = .scaleToFill // 让背景图铺满按钮
|
||||||
|
|
||||||
|
let button = UIButton(configuration: config, primaryAction: UIAction(handler: { [weak self] _ in
|
||||||
|
guard let self = self else { return }
|
||||||
|
self.clickUnlockButton?()
|
||||||
|
}))
|
||||||
|
button.configurationUpdateHandler = { [weak self] button in
|
||||||
|
guard let self = self else { return }
|
||||||
|
let attributeContainer = AttributeContainer([
|
||||||
|
.font : UIFont.font(ofSize: 14, weight: .medium),
|
||||||
|
.foregroundColor : UIColor._51_D_4_FF
|
||||||
|
])
|
||||||
|
if hasLastEpisodeUnlocked {
|
||||||
|
button.configuration?.attributedTitle = .init("video_lock_tip_text".localized, attributes: attributeContainer)
|
||||||
|
} else {
|
||||||
|
button.configuration?.attributedTitle = .init("synthreel_unlocking_coins_notice".localizedReplace(text: "\(videoInfo?.coins ?? 0)"), attributes: attributeContainer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return button
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var adlockButton: UIButton = {
|
||||||
|
var config = UIButton.Configuration.plain()
|
||||||
|
config.image = UIImage(named: "adlock")
|
||||||
|
config.imagePadding = 6
|
||||||
|
// 设置背景图片(使用 UIImage 作为背景)
|
||||||
|
config.background.image = UIImage(named: "unlockButtonBg")
|
||||||
|
config.background.imageContentMode = .scaleToFill // 让背景图铺满按钮
|
||||||
|
let attr = AttributeContainer([
|
||||||
|
.font: UIFont.font(ofSize: 14, weight: .medium),
|
||||||
|
.foregroundColor: UIColor.white
|
||||||
|
])
|
||||||
|
config.attributedTitle = AttributedString("Watch 2ads to unlock".localized, attributes: attr)
|
||||||
|
|
||||||
|
let button = UIButton(configuration: config, primaryAction: UIAction(handler: { [weak self] _ in
|
||||||
|
guard let self = self else { return }
|
||||||
|
self.adUnlockButton?()
|
||||||
|
}))
|
||||||
|
return button
|
||||||
|
}()
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
backgroundColor = ._000000.withAlphaComponent(0.6)
|
||||||
|
sr_setupLayout()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SRVideoLockView {
|
||||||
|
|
||||||
|
private func sr_setupLayout() {
|
||||||
|
addSubview(unlockStackView)
|
||||||
|
|
||||||
|
unlockStackView.addArrangedSubview(unlockButton)
|
||||||
|
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.centerY.equalToSuperview() // 可自定义
|
||||||
|
}
|
||||||
|
|
||||||
|
unlockButton.snp.makeConstraints { make in
|
||||||
|
make.height.equalTo(43)
|
||||||
|
}
|
||||||
|
|
||||||
|
adlockButton.snp.makeConstraints { make in
|
||||||
|
make.height.equalTo(43)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -70,11 +70,31 @@ class SRDetailPlayerViewController: JXPlayerListViewController {
|
|||||||
|
|
||||||
override func play() {
|
override func play() {
|
||||||
let videoInfo = self.viewModel.currentCell?.model as? SRVideoInfoModel
|
let videoInfo = self.viewModel.currentCell?.model as? SRVideoInfoModel
|
||||||
super.play()
|
|
||||||
|
|
||||||
Task {
|
if videoInfo?.is_lock != true {
|
||||||
await SRShortApi.requestCreatePlayHistory(shortId: videoInfo?.short_play_id, videoId: videoInfo?.short_play_video_id)
|
super.play()
|
||||||
|
Task {
|
||||||
|
await SRShortApi.requestCreatePlayHistory(shortId: videoInfo?.short_play_id, videoId: videoInfo?.short_play_video_id)
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
self.pause()
|
||||||
|
let myCoins = SRAccountManager.manager.userInfo?.totalCoins ?? 0
|
||||||
|
let lockCoins = videoInfo?.coins ?? 0
|
||||||
|
|
||||||
|
if myCoins < lockCoins, (self.sr_viewModel.currentCell as? SRShortDetailPlayerCell)?.hasLastEpisodeUnlocked != true {
|
||||||
|
// self.sr_viewModel.openRechargeView()
|
||||||
|
} else {
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in
|
||||||
|
guard let self = self else { return }
|
||||||
|
if (self.sr_viewModel.currentCell as? SRShortDetailPlayerCell)?.hasLastEpisodeUnlocked != true {
|
||||||
|
Task {
|
||||||
|
await self.sr_viewModel.handleUnlockVideo()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func handleBackButton() {
|
@objc private func handleBackButton() {
|
||||||
@ -123,6 +143,13 @@ extension SRDetailPlayerViewController: JXPlayerListViewControllerDelegate, JXPl
|
|||||||
let cell = self.dequeueReusableCell(withReuseIdentifier: "SRShortDetailPlayerCell", for: indexPath) as! SRShortDetailPlayerCell
|
let cell = self.dequeueReusableCell(withReuseIdentifier: "SRShortDetailPlayerCell", for: indexPath) as! SRShortDetailPlayerCell
|
||||||
cell.model = self.sr_viewModel.dataArr[indexPath.section].episodeList?[indexPath.row]
|
cell.model = self.sr_viewModel.dataArr[indexPath.section].episodeList?[indexPath.row]
|
||||||
cell.shortModel = self.sr_viewModel.dataArr[indexPath.section].shortPlayInfo
|
cell.shortModel = self.sr_viewModel.dataArr[indexPath.section].shortPlayInfo
|
||||||
|
|
||||||
|
let upRow = indexPath.row - 1
|
||||||
|
if upRow >= 0, let videoInfo = self.sr_viewModel.dataArr[indexPath.section].episodeList?[upRow], videoInfo.is_lock == true {
|
||||||
|
cell.hasLastEpisodeUnlocked = true
|
||||||
|
} else {
|
||||||
|
cell.hasLastEpisodeUnlocked = false
|
||||||
|
}
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -28,8 +28,9 @@ class SRShortPlayerViewModel: JXPlayerListViewModel {
|
|||||||
nonisolated required init() {
|
nonisolated required init() {
|
||||||
super.init()
|
super.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@MainActor
|
||||||
func requestShortDetail(indexPath: IndexPath? = nil) async -> Int? {
|
func requestShortDetail(indexPath: IndexPath? = nil) async -> Int? {
|
||||||
let (model, code, _) = await SRShortApi.requestShortDetail(shortId)
|
let (model, code, _) = await SRShortApi.requestShortDetail(shortId)
|
||||||
guard let model = model else { return code }
|
guard let model = model else { return code }
|
||||||
@ -41,27 +42,67 @@ class SRShortPlayerViewModel: JXPlayerListViewModel {
|
|||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
var targetIndexPath = IndexPath(row: 0, section: 0)
|
var targetIndexPath = IndexPath(row: 0, section: 0)
|
||||||
|
|
||||||
if let indexPath = indexPath, indexPath.row < (model.episodeList?.count ?? 0) {
|
if let indexPath = indexPath,
|
||||||
|
indexPath.row < (model.episodeList?.count ?? 0) {
|
||||||
targetIndexPath = indexPath
|
targetIndexPath = indexPath
|
||||||
} else if let videoInfo = model.video_info {
|
} else if let videoInfo = model.video_info {
|
||||||
var row: Int?
|
if let row = model.episodeList?.firstIndex(where: {
|
||||||
model.episodeList?.enumerated().forEach {
|
$0.short_play_video_id == videoInfo.short_play_video_id
|
||||||
if $1.short_play_video_id == videoInfo.short_play_video_id {
|
}) {
|
||||||
row = $0
|
targetIndexPath = IndexPath(row: row, section: 0)
|
||||||
}
|
|
||||||
}
|
|
||||||
if let row = row {
|
|
||||||
targetIndexPath = .init(row: row, section: 0)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isShowRecommand = false
|
isShowRecommand = false
|
||||||
recommandTimer?.invalidate()
|
recommandTimer?.invalidate()
|
||||||
recommandTimer = nil
|
recommandTimer = nil
|
||||||
recommandTimer = Timer.scheduledTimer(timeInterval: 6, target: YYTextWeakProxy(target: self), selector: #selector(handleRecommandTimer), userInfo: nil, repeats: false)
|
recommandTimer = Timer.scheduledTimer(
|
||||||
|
timeInterval: 6,
|
||||||
|
target: YYTextWeakProxy(target: self),
|
||||||
|
selector: #selector(handleRecommandTimer),
|
||||||
|
userInfo: nil,
|
||||||
|
repeats: false
|
||||||
|
)
|
||||||
|
|
||||||
self.playerListVC?.scrollToItem(indexPath: targetIndexPath, animated: false)
|
self.playerListVC?.scrollToItem(indexPath: targetIndexPath, animated: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
private func unlockVideo(completer: ((_ finish: Bool) -> Void)?) async {
|
||||||
|
guard let videoInfo = self.currentCell?.model as? SRVideoInfoModel else { return }
|
||||||
|
guard let shortPlayId = videoInfo.short_play_id else { return }
|
||||||
|
guard let videoId = videoInfo.short_play_video_id else { return }
|
||||||
|
|
||||||
|
let (model) = await SRShortApi.requestCoinUnlockVideo(shortId: shortPlayId,videoId: videoId)
|
||||||
|
guard let model = model else {
|
||||||
|
completer?(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch model.status {
|
||||||
|
case .jump:
|
||||||
|
SRToast.show(text: "buy_fail_toast_02".localized)
|
||||||
|
case .noPlay:
|
||||||
|
SRToast.show(text: "buy_fail_toast_01".localized)
|
||||||
|
case .notEnough:
|
||||||
|
break
|
||||||
|
//跳广告解锁
|
||||||
|
// self.openRechargeView()
|
||||||
|
default: break
|
||||||
|
}
|
||||||
|
|
||||||
|
if model.status == .success {
|
||||||
|
Task {
|
||||||
|
await SRAccountManager.manager.updateUserInfo()
|
||||||
|
videoInfo.is_lock = false
|
||||||
|
completer?(true)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
completer?(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -85,6 +126,21 @@ extension SRShortPlayerViewModel {
|
|||||||
self.recommandList = model
|
self.recommandList = model
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
func handleUnlockVideo() async {
|
||||||
|
await unlockVideo { [weak self] finish in
|
||||||
|
guard let self = self else { return }
|
||||||
|
|
||||||
|
if finish {
|
||||||
|
SRToast.show(text: "synthreel_success".localized)
|
||||||
|
self.playerListVC?.reloadData {
|
||||||
|
self.playerListVC?.play()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@objc private func handleRecommandTimer() {
|
@objc private func handleRecommandTimer() {
|
||||||
self.isShowRecommand = true
|
self.isShowRecommand = true
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,14 +17,6 @@ class SRHelpCenterController: UIViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
// MARK: - Navigation
|
|
||||||
|
|
||||||
// In a storyboard-based application, you will often want to do a little preparation before navigation
|
|
||||||
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
|
||||||
// Get the new view controller using segue.destination.
|
|
||||||
// Pass the selected object to the new view controller.
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,16 +15,6 @@ class SRPrivacyController: UIViewController {
|
|||||||
|
|
||||||
// Do any additional setup after loading the view.
|
// Do any additional setup after loading the view.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
// MARK: - Navigation
|
|
||||||
|
|
||||||
// In a storyboard-based application, you will often want to do a little preparation before navigation
|
|
||||||
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
|
||||||
// Get the new view controller using segue.destination.
|
|
||||||
// Pass the selected object to the new view controller.
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,4 @@ class SRRewardController: SRAppWebViewController {
|
|||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
// Do any additional setup after loading the view.
|
// Do any additional setup after loading the view.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,6 +26,7 @@ class SRUserViewController: SRViewController {
|
|||||||
collectionView.register(SRUserSettingCell.self, forCellWithReuseIdentifier: "cell")
|
collectionView.register(SRUserSettingCell.self, forCellWithReuseIdentifier: "cell")
|
||||||
collectionView.register(SRUserTopCell.self, forCellWithReuseIdentifier: "topcell")
|
collectionView.register(SRUserTopCell.self, forCellWithReuseIdentifier: "topcell")
|
||||||
collectionView.register(SRCoinPackCell.self, forCellWithReuseIdentifier: "coincell")
|
collectionView.register(SRCoinPackCell.self, forCellWithReuseIdentifier: "coincell")
|
||||||
|
collectionView.register(SRUserRewardCell.self, forCellWithReuseIdentifier: "rewardCell")
|
||||||
|
|
||||||
collectionView.sr_addRefreshHeader { [weak self] in
|
collectionView.sr_addRefreshHeader { [weak self] in
|
||||||
Task {
|
Task {
|
||||||
@ -44,6 +45,8 @@ class SRUserViewController: SRViewController {
|
|||||||
setDataArr()
|
setDataArr()
|
||||||
// Do any additional setup after loading the view.
|
// Do any additional setup after loading the view.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,8 +70,12 @@ extension SRUserViewController: UICollectionViewDelegate, UICollectionViewDataSo
|
|||||||
} else if indexPath.section == 1 {
|
} else if indexPath.section == 1 {
|
||||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "coincell", for: indexPath) as! SRCoinPackCell
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "coincell", for: indexPath) as! SRCoinPackCell
|
||||||
return cell
|
return cell
|
||||||
|
}else if indexPath.section == 2 {
|
||||||
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "rewardCell", for: indexPath) as! SRUserRewardCell
|
||||||
|
return cell
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! SRUserSettingCell
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! SRUserSettingCell
|
||||||
cell.model = self.dataArr[indexPath.row];
|
cell.model = self.dataArr[indexPath.row];
|
||||||
return cell
|
return cell
|
||||||
@ -102,6 +109,10 @@ extension SRUserViewController: UICollectionViewDelegate, UICollectionViewDataSo
|
|||||||
let aboutvc = SRAboutUsController ();
|
let aboutvc = SRAboutUsController ();
|
||||||
self.navigationController?.pushViewController(aboutvc, animated: true)
|
self.navigationController?.pushViewController(aboutvc, animated: true)
|
||||||
break
|
break
|
||||||
|
case .login:
|
||||||
|
let loginview = SRUserLoginView()
|
||||||
|
loginview.present(in: nil)
|
||||||
|
break
|
||||||
case .feedback:
|
case .feedback:
|
||||||
// let vc = SRFeedBackController ();
|
// let vc = SRFeedBackController ();
|
||||||
// self.navigationController?.pushViewController(vc, animated: true)
|
// self.navigationController?.pushViewController(vc, animated: true)
|
||||||
@ -157,6 +168,7 @@ extension SRUserViewController {
|
|||||||
|
|
||||||
let arr = [
|
let arr = [
|
||||||
SRUserSettingModel(type: .feedback, name: "synthreel_feedback".localized, icon: UIImage(named: "icon_feedback")),
|
SRUserSettingModel(type: .feedback, name: "synthreel_feedback".localized, icon: UIImage(named: "icon_feedback")),
|
||||||
|
SRUserSettingModel(type: .login, name: "synthreel_login".localized, icon: UIImage(named: "icon_login")),
|
||||||
SRUserSettingModel(type: .about, name: "synthreel_about_us".localized, icon: UIImage(named: "icon_about")),
|
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: .privacyPolicy, name: "synthreel_privacy_policy".localized, icon: UIImage(named: "icon_privacy")),
|
||||||
SRUserSettingModel(type: .userAgreement, name: "synthreel_user_agreement".localized, icon: UIImage(named: "icon_user")),
|
SRUserSettingModel(type: .userAgreement, name: "synthreel_user_agreement".localized, icon: UIImage(named: "icon_user")),
|
||||||
|
|||||||
@ -17,12 +17,14 @@ struct SRUserSettingModel {
|
|||||||
case privacyPolicy
|
case privacyPolicy
|
||||||
case userAgreement
|
case userAgreement
|
||||||
case visitWebsite
|
case visitWebsite
|
||||||
|
case login
|
||||||
|
case logout
|
||||||
// ///消费记录
|
// ///消费记录
|
||||||
// case consumptionRecords
|
case consumptionRecords
|
||||||
// ///购买记录
|
// ///购买记录
|
||||||
// case purchaseRecords
|
case purchaseRecords
|
||||||
// ///金币奖励
|
// ///金币奖励
|
||||||
// case rewardCoins
|
case rewardCoins
|
||||||
case deleteAccount
|
case deleteAccount
|
||||||
case language
|
case language
|
||||||
}
|
}
|
||||||
|
|||||||
66
SynthReel/Class/User/view/SRLoginButtonView.swift
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
//
|
||||||
|
// SRLoginButtonView.swift
|
||||||
|
// SynthReel
|
||||||
|
//
|
||||||
|
// Created by CSGY on 2025/12/1.
|
||||||
|
// Copyright © 2025 SR. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class SRLoginButtonView: UIControl {
|
||||||
|
|
||||||
|
private let bgImageView = UIImageView()
|
||||||
|
private let iconView = UIImageView()
|
||||||
|
private lazy var titleLabel: SRLabel = {
|
||||||
|
let label = SRLabel()
|
||||||
|
label.font = .font(ofSize: 14, weight: .medium)
|
||||||
|
label.textColors = [UIColor._4_CFFD_4.cgColor, UIColor._51_D_4_FF.cgColor]
|
||||||
|
label.textStartPoint = .init(x: 0.5, y: 0)
|
||||||
|
label.textEndPoint = .init(x: 0.5, y: 1)
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
private let arrowView = UIImageView(image: UIImage(named: "arrow_right_icon_01"))
|
||||||
|
|
||||||
|
init(icon: UIImage?, title: String, background: UIImage?) {
|
||||||
|
super.init(frame: .zero)
|
||||||
|
bgImageView.image = background
|
||||||
|
|
||||||
|
iconView.image = icon
|
||||||
|
titleLabel.text = title
|
||||||
|
setupUI()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setupUI() {
|
||||||
|
addSubview(bgImageView)
|
||||||
|
addSubview(iconView)
|
||||||
|
addSubview(titleLabel)
|
||||||
|
addSubview(arrowView)
|
||||||
|
|
||||||
|
bgImageView.snp.makeConstraints { make in
|
||||||
|
make.edges.equalToSuperview()
|
||||||
|
}
|
||||||
|
|
||||||
|
iconView.snp.makeConstraints { make in
|
||||||
|
make.left.equalToSuperview().offset(10)
|
||||||
|
make.centerY.equalToSuperview()
|
||||||
|
make.width.height.equalTo(20)
|
||||||
|
}
|
||||||
|
|
||||||
|
titleLabel.snp.makeConstraints { make in
|
||||||
|
make.centerY.equalToSuperview()
|
||||||
|
make.centerX.equalToSuperview()
|
||||||
|
}
|
||||||
|
|
||||||
|
arrowView.snp.makeConstraints { make in
|
||||||
|
make.right.equalToSuperview().offset(-16)
|
||||||
|
make.centerY.equalToSuperview()
|
||||||
|
make.width.equalTo(10)
|
||||||
|
make.height.equalTo(10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
84
SynthReel/Class/User/view/SRUserLoginView.swift
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
//
|
||||||
|
// SRUserLoginView.swift
|
||||||
|
// SynthReel
|
||||||
|
//
|
||||||
|
// Created by CSGY on 2025/12/1.
|
||||||
|
// Copyright © 2025 SR. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class SRUserLoginView: SRPanModalContentView {
|
||||||
|
|
||||||
|
private let fbLoginView = SRLoginButtonView(
|
||||||
|
icon: UIImage(named: "fb_icon"),
|
||||||
|
title: "Login With Facebook".localized,
|
||||||
|
background: UIImage(named: "FacebookBg")
|
||||||
|
)
|
||||||
|
|
||||||
|
private let appleLoginView = SRLoginButtonView(
|
||||||
|
icon: UIImage(named: "apple_icon"),
|
||||||
|
title: "Login With Apple".localized,
|
||||||
|
background: UIImage(named: "appleBg")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
sr_setupUI()
|
||||||
|
self.updateContentHeight(246)
|
||||||
|
self.updateBackgroundImage(.loginBg)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SRUserLoginView {
|
||||||
|
|
||||||
|
func sr_setupUI() {
|
||||||
|
|
||||||
|
addSubview(fbLoginView)
|
||||||
|
addSubview(appleLoginView)
|
||||||
|
|
||||||
|
fbLoginView.snp.makeConstraints { make in
|
||||||
|
make.top.equalToSuperview().offset(35)
|
||||||
|
make.left.equalToSuperview().offset(48)
|
||||||
|
make.right.equalToSuperview().offset(-48)
|
||||||
|
make.height.equalTo(48)
|
||||||
|
}
|
||||||
|
|
||||||
|
appleLoginView.snp.makeConstraints { make in
|
||||||
|
make.top.equalTo(fbLoginView.snp.bottom).offset(20)
|
||||||
|
make.left.right.height.equalTo(fbLoginView)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 点击事件
|
||||||
|
fbLoginView.addTarget(self, action: #selector(tapFB), for: .touchUpInside)
|
||||||
|
appleLoginView.addTarget(self, action: #selector(tapApple), for: .touchUpInside)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func tapFB() {
|
||||||
|
self.login(type: .faceBook)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func tapApple() {
|
||||||
|
self.login(type: .apple)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func login(type: SRLogin.LoginType) {
|
||||||
|
SRHud.show()
|
||||||
|
SRLogin.manager.thirdLogin(type: type, presentingViewController: nil) { [weak self] isFinish in
|
||||||
|
SRHud.dismiss()
|
||||||
|
guard let self = self else { return }
|
||||||
|
if isFinish {
|
||||||
|
Task {
|
||||||
|
await self.dismiss(animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
13
SynthReel/Class/User/view/SRUserRewardCell.swift
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
//
|
||||||
|
// SRUserRewardCell.swift
|
||||||
|
// SynthReel
|
||||||
|
//
|
||||||
|
// Created by CSGY on 2025/12/2.
|
||||||
|
// Copyright © 2025 SR. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class SRUserRewardCell: UICollectionViewCell {
|
||||||
|
|
||||||
|
}
|
||||||
@ -52,7 +52,7 @@ extension SRUserSettingCell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
titleLabel.snp.makeConstraints { make in
|
titleLabel.snp.makeConstraints { make in
|
||||||
make.left.equalTo(iconImage.snp_rightMargin).offset(10)
|
make.left.equalTo(iconImage.snp.right).offset(10)
|
||||||
make.centerY.equalToSuperview()
|
make.centerY.equalToSuperview()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -7,12 +7,15 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
import FacebookCore
|
||||||
|
|
||||||
extension AppDelegate {
|
extension AppDelegate {
|
||||||
|
|
||||||
func setConfig() {
|
func setConfig() {
|
||||||
SRToast.config()
|
SRToast.config()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sr_registThirdparty(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
|
||||||
|
ApplicationDelegate.shared.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
SRTool.appDelegate = self
|
SRTool.appDelegate = self
|
||||||
|
|
||||||
SRNetworkReachableManager.manager.startMonitoring()
|
SRNetworkReachableManager.manager.startMonitoring()
|
||||||
|
sr_registThirdparty(application, didFinishLaunchingWithOptions: launchOptions)
|
||||||
self.setConfig()
|
self.setConfig()
|
||||||
|
|
||||||
|
|
||||||
@ -24,6 +24,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
await SRAccountManager.manager.updateUserInfo()
|
await SRAccountManager.manager.updateUserInfo()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
60
SynthReel/Libs/SRLogin/SRLogin+FB.swift
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
//
|
||||||
|
// SRLogin+FB.swift
|
||||||
|
// SynthReel
|
||||||
|
//
|
||||||
|
// Created by CSGY on 2025/12/1.
|
||||||
|
// Copyright © 2025 SR. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import FacebookLogin
|
||||||
|
|
||||||
|
extension SRLogin {
|
||||||
|
|
||||||
|
func facebookLogin(presentingViewController: UIViewController?, completer: ((_ model: SRThirdModel?) -> Void)?) {
|
||||||
|
|
||||||
|
let loginManager = LoginManager()
|
||||||
|
loginManager.logOut()
|
||||||
|
loginManager.defaultAudience = .everyone
|
||||||
|
|
||||||
|
loginManager.logIn(permissions: ["public_profile", "email"], from: presentingViewController) { result, error in
|
||||||
|
guard error == nil, let result = result else {
|
||||||
|
completer?(nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if result.isCancelled {
|
||||||
|
completer?(nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let request = GraphRequest(graphPath: "me", parameters: ["fields" : "id,name,email,picture"], httpMethod: .get)
|
||||||
|
request.start { connection, result, error in
|
||||||
|
guard let result = result as? [String : Any] else {
|
||||||
|
completer?(nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var model = SRThirdModel()
|
||||||
|
model.platform = .faceBook
|
||||||
|
model.third_id = result["id"] as? String
|
||||||
|
model.email = result["email"] as? String
|
||||||
|
|
||||||
|
if let picture = result["picture"] as? [String : Any],
|
||||||
|
let data = picture["data"] as? [String : Any],
|
||||||
|
let url = data["url"] as? String
|
||||||
|
{
|
||||||
|
model.avator = url
|
||||||
|
}
|
||||||
|
|
||||||
|
if let name = result["name"] as? String {
|
||||||
|
model.family_name = name
|
||||||
|
} else {
|
||||||
|
model.family_name = result["first_name"] as? String
|
||||||
|
model.giving_name = result["last_name"] as? String
|
||||||
|
}
|
||||||
|
completer?(model)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
116
SynthReel/Libs/SRLogin/SRLogin+apple.swift
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
//
|
||||||
|
// SRLogin+third.swift
|
||||||
|
// SynthReel
|
||||||
|
//
|
||||||
|
// Created by CSGY on 2025/12/1.
|
||||||
|
// Copyright © 2025 SR. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import AuthenticationServices
|
||||||
|
|
||||||
|
extension SRLogin {
|
||||||
|
|
||||||
|
private struct AssociatedKeys {
|
||||||
|
static var appleLoginHandle: Int?
|
||||||
|
}
|
||||||
|
|
||||||
|
private var appleLoginHandle: ((_ model: SRThirdModel?) -> Void)? {
|
||||||
|
set {
|
||||||
|
objc_setAssociatedObject(self, &AssociatedKeys.appleLoginHandle, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC)
|
||||||
|
}
|
||||||
|
get {
|
||||||
|
return objc_getAssociatedObject(self, &AssociatedKeys.appleLoginHandle) as? ((_ model: SRThirdModel?) -> Void)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func appleLogin(completer: ((_ model: SRThirdModel?) -> Void)?) {
|
||||||
|
self.appleLoginHandle = completer
|
||||||
|
|
||||||
|
let appleIDProvider = ASAuthorizationAppleIDProvider()
|
||||||
|
let request = appleIDProvider.createRequest()
|
||||||
|
request.requestedScopes = [.fullName, .email]
|
||||||
|
|
||||||
|
let authorizationController = ASAuthorizationController(authorizationRequests: [request])
|
||||||
|
authorizationController.delegate = self
|
||||||
|
authorizationController.presentationContextProvider = self
|
||||||
|
authorizationController.performRequests()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func jwtDecode(jwtStr: String) -> [String: Any]? {
|
||||||
|
let segments = jwtStr.components(separatedBy: ".")
|
||||||
|
guard segments.count > 1 else { return nil }
|
||||||
|
|
||||||
|
var base64String = segments[1]
|
||||||
|
|
||||||
|
// 处理 Base64 补齐
|
||||||
|
let requiredLength = 4 * Int(ceil(Double(base64String.count) / 4.0))
|
||||||
|
let paddingLength = requiredLength - base64String.count
|
||||||
|
if paddingLength > 0 {
|
||||||
|
base64String += String(repeating: "=", count: paddingLength)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 替换 URL 安全字符
|
||||||
|
base64String = base64String.replacingOccurrences(of: "-", with: "+")
|
||||||
|
base64String = base64String.replacingOccurrences(of: "_", with: "/")
|
||||||
|
|
||||||
|
// 解码 Base64 数据
|
||||||
|
guard let data = Data(base64Encoded: base64String),
|
||||||
|
let jsonObject = try? JSONSerialization.jsonObject(with: data, options: []),
|
||||||
|
let payload = jsonObject as? [String: Any] else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return payload
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//MARK: ASAuthorizationControllerDelegate
|
||||||
|
extension SRLogin: ASAuthorizationControllerDelegate {
|
||||||
|
|
||||||
|
func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
|
||||||
|
if let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential {
|
||||||
|
|
||||||
|
let userIdentifier = appleIDCredential.user
|
||||||
|
let fullName = appleIDCredential.fullName
|
||||||
|
let email = appleIDCredential.email
|
||||||
|
|
||||||
|
let identityToken = appleIDCredential.identityToken.flatMap { String(data: $0, encoding: .utf8) }
|
||||||
|
let identityTokenParams = self.jwtDecode(jwtStr: identityToken ?? "")
|
||||||
|
|
||||||
|
|
||||||
|
var model = SRThirdModel()
|
||||||
|
model.platform = .apple
|
||||||
|
model.third_id = userIdentifier
|
||||||
|
model.giving_name = fullName?.givenName
|
||||||
|
model.family_name = fullName?.familyName
|
||||||
|
model.avator = identityTokenParams?["picture"] as? String
|
||||||
|
model.email = identityTokenParams?["email"] as? String
|
||||||
|
|
||||||
|
|
||||||
|
debugLog(userIdentifier)
|
||||||
|
debugLog(fullName)
|
||||||
|
debugLog(email)
|
||||||
|
|
||||||
|
appleLoginHandle?(model)
|
||||||
|
appleLoginHandle = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
|
||||||
|
appleLoginHandle?(nil)
|
||||||
|
appleLoginHandle = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//MARK: ASAuthorizationControllerPresentationContextProviding
|
||||||
|
extension SRLogin: ASAuthorizationControllerPresentationContextProviding {
|
||||||
|
|
||||||
|
func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
|
||||||
|
return SRTool.keyWindow!
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
133
SynthReel/Libs/SRLogin/SRLogin.swift
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
//
|
||||||
|
// SRLogin.swift
|
||||||
|
// SynthReel
|
||||||
|
//
|
||||||
|
// Created by CSGY on 2025/12/1.
|
||||||
|
// Copyright © 2025 SR. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import SmartCodable
|
||||||
|
|
||||||
|
|
||||||
|
class SRLogin: NSObject {
|
||||||
|
enum LoginType: String, SmartCaseDefaultable {
|
||||||
|
case apple = "Apple"
|
||||||
|
case faceBook = "Facebook"
|
||||||
|
case google = "Google"
|
||||||
|
case tiktok = "Tiktok"
|
||||||
|
}
|
||||||
|
|
||||||
|
static let manager = SRLogin()
|
||||||
|
|
||||||
|
private(set) var token = UserDefaults.sr_object(forKey: kSRAccountTokenDefaultsKey, as: SRTokenModel.self)
|
||||||
|
private(set) var userInfo = UserDefaults.sr_object(forKey: kSRUserInfoDefaultsKey, as: SRUserInfo.self)
|
||||||
|
|
||||||
|
var isLogin: Bool {
|
||||||
|
return !(userInfo?.is_tourist ?? true)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setToken(_ token: SRTokenModel?) {
|
||||||
|
self.token = token
|
||||||
|
UserDefaults.sr_setObject(token, forKey: kSRAccountTokenDefaultsKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setUserInfo(_ userInfo: SRUserInfo?) {
|
||||||
|
self.userInfo = userInfo
|
||||||
|
UserDefaults.sr_setObject(userInfo, forKey: kSRUserInfoDefaultsKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
///第三方登录
|
||||||
|
func thirdLogin(type: LoginType, presentingViewController: UIViewController?, completer: ((_ isFinish: Bool) -> Void)?) {
|
||||||
|
switch type {
|
||||||
|
case .apple:
|
||||||
|
appleLogin { [weak self] model in
|
||||||
|
self?.requestSignThirdLogin(thirdSignModel: model, completer: completer)
|
||||||
|
}
|
||||||
|
|
||||||
|
case .faceBook:
|
||||||
|
facebookLogin(presentingViewController: presentingViewController) { [weak self] model in
|
||||||
|
self?.requestSignThirdLogin(thirdSignModel: model, completer: completer)
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///后台验证三方登录
|
||||||
|
private func requestSignThirdLogin(thirdSignModel: SRThirdModel?, completer: ((_ isFinish: Bool) -> Void)?) {
|
||||||
|
guard let thirdSignModel = thirdSignModel else {
|
||||||
|
completer?(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Task {
|
||||||
|
await SRUserApi.requestLeave()
|
||||||
|
let tokenModel = await SRUserApi.requestSignThirdLogin(model: thirdSignModel)
|
||||||
|
guard let token = tokenModel else {
|
||||||
|
completer?(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.setToken(token)
|
||||||
|
self.userInfo?.is_tourist = false
|
||||||
|
await self.requestUserInfo(completer: nil)
|
||||||
|
await SRUserApi.requestEnterApp()
|
||||||
|
await SRUserApi.requestStatOnLine()
|
||||||
|
completer?(true)
|
||||||
|
await MainActor.run {
|
||||||
|
NotificationCenter.default.post(name: SRLogin.userInfoUpdateNotification, object: nil)
|
||||||
|
NotificationCenter.default.post(name: SRLogin.loginStatusChangeNotification, object: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func logout(completer: ((_ isFinish: Bool) -> Void)?) async {
|
||||||
|
await SRUserApi.requestLeave()
|
||||||
|
let tokenModel = await SRUserApi.requestLogout()
|
||||||
|
guard let token = tokenModel else {
|
||||||
|
completer?(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.setToken(token)
|
||||||
|
self.userInfo?.is_tourist = true
|
||||||
|
await self.requestUserInfo(completer: nil)
|
||||||
|
await SRUserApi.requestEnterApp()
|
||||||
|
await SRUserApi.requestStatOnLine()
|
||||||
|
completer?(true)
|
||||||
|
await MainActor.run {
|
||||||
|
NotificationCenter.default.post(name: SRLogin.userInfoUpdateNotification, object: nil)
|
||||||
|
NotificationCenter.default.post(name: SRLogin.loginStatusChangeNotification, object: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SRLogin {
|
||||||
|
|
||||||
|
func requestUserInfo(completer: (() -> Void)?) async {
|
||||||
|
let userInfo = await SRUserApi.requestUserInfo()
|
||||||
|
if let user = userInfo {
|
||||||
|
self.setUserInfo(user)
|
||||||
|
}
|
||||||
|
completer?()
|
||||||
|
}
|
||||||
|
|
||||||
|
func requestUserToken(completer: (() -> Void)?) async {
|
||||||
|
let tokenModel = await SRUserApi.requestregister()
|
||||||
|
if let token = tokenModel {
|
||||||
|
self.setToken(token)
|
||||||
|
}
|
||||||
|
completer?()
|
||||||
|
NotificationCenter.default.post(name: Self.userInfoUpdateNotification, object: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SRLogin {
|
||||||
|
|
||||||
|
///用户信息更新
|
||||||
|
@objc static let userInfoUpdateNotification = NSNotification.Name(rawValue: "FALogin.userInfoUpdateNotification")
|
||||||
|
///登录状态发生变化
|
||||||
|
@objc static let loginStatusChangeNotification = NSNotification.Name(rawValue: "FALogin.loginStatusChangeNotification")
|
||||||
|
|
||||||
|
}
|
||||||
24
SynthReel/Libs/SRLogin/SRThirdModel.swift
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
//
|
||||||
|
// SRThirdModel.swift
|
||||||
|
// SynthReel
|
||||||
|
//
|
||||||
|
// Created by CSGY on 2025/12/1.
|
||||||
|
// Copyright © 2025 SR. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import SmartCodable
|
||||||
|
|
||||||
|
struct SRThirdModel: SmartCodable {
|
||||||
|
|
||||||
|
var third_id: String?
|
||||||
|
var email: String?
|
||||||
|
//姓
|
||||||
|
var family_name: String?
|
||||||
|
//名
|
||||||
|
var giving_name: String?
|
||||||
|
|
||||||
|
var avator: String?
|
||||||
|
|
||||||
|
var platform: SRLogin.LoginType?
|
||||||
|
}
|
||||||
37
SynthReel/Libs/SRLogin/SRTokenModel.swift
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
//
|
||||||
|
// SRTokenModel.swift
|
||||||
|
// SynthReel
|
||||||
|
//
|
||||||
|
// Created by CSGY on 2025/12/1.
|
||||||
|
// Copyright © 2025 SR. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import SmartCodable
|
||||||
|
|
||||||
|
|
||||||
|
class SRTokenModel: NSObject,SmartCodable, NSSecureCoding {
|
||||||
|
|
||||||
|
var auto_login: Int?
|
||||||
|
var customer_id: String?
|
||||||
|
var token: String?
|
||||||
|
|
||||||
|
required override init() { }
|
||||||
|
|
||||||
|
static var supportsSecureCoding: Bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func encode(with coder: NSCoder) {
|
||||||
|
coder.encode(token, forKey: "token")
|
||||||
|
coder.encode(customer_id, forKey: "customer_id")
|
||||||
|
coder.encode(auto_login, forKey: "auto_login")
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
super.init()
|
||||||
|
token = coder.decodeObject(of: NSString.self, forKey: "token") as? String
|
||||||
|
customer_id = coder.decodeObject(of: NSString.self, forKey: "customer_id") as? String
|
||||||
|
auto_login = coder.decodeObject(of: NSNumber.self, forKey: "auto_login")?.intValue
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,6 +8,14 @@
|
|||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
func debugLog(_ msg: Any, file: String = #file, function: String = #function, line: Int = #line) {
|
||||||
|
print("\n\(Date(timeIntervalSinceNow: 8 * 60 * 60)) \(file.components(separatedBy: "/").last ?? "") \(function) \(line): \(msg)")
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
func debugLog(_ msg: Any) { }
|
||||||
|
#endif
|
||||||
|
|
||||||
class SRTool {
|
class SRTool {
|
||||||
|
|
||||||
static var appDelegate: AppDelegate?
|
static var appDelegate: AppDelegate?
|
||||||
|
|||||||
22
SynthReel/Source/Assets.xcassets/Image/apple_icon.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "apple_icon@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "apple_icon@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
SynthReel/Source/Assets.xcassets/Image/apple_icon.imageset/apple_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
SynthReel/Source/Assets.xcassets/Image/apple_icon.imageset/apple_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
22
SynthReel/Source/Assets.xcassets/Image/fb_icon.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "fb_icon@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "fb_icon@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
SynthReel/Source/Assets.xcassets/Image/fb_icon.imageset/fb_icon@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
SynthReel/Source/Assets.xcassets/Image/fb_icon.imageset/fb_icon@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
22
SynthReel/Source/Assets.xcassets/Image/icon_login.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "icon_login@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "icon_login@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
SynthReel/Source/Assets.xcassets/Image/icon_login.imageset/icon_login@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 750 B |
BIN
SynthReel/Source/Assets.xcassets/Image/icon_login.imageset/icon_login@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 1004 B |
22
SynthReel/Source/Assets.xcassets/Image/icon_logout.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "icon_logout@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "icon_logout@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
SynthReel/Source/Assets.xcassets/Image/icon_logout.imageset/icon_logout@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 921 B |
BIN
SynthReel/Source/Assets.xcassets/Image/icon_logout.imageset/icon_logout@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
22
SynthReel/Source/Assets.xcassets/Image/unlockButtonBg.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "unlockButtonBg@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "unlockButtonBg@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
SynthReel/Source/Assets.xcassets/Image/unlockButtonBg.imageset/unlockButtonBg@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
SynthReel/Source/Assets.xcassets/Image/unlockButtonBg.imageset/unlockButtonBg@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 29 KiB |
22
SynthReel/Source/Assets.xcassets/myShort/FacebookBg.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "FacebookBg@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "FacebookBg@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
SynthReel/Source/Assets.xcassets/myShort/FacebookBg.imageset/FacebookBg@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
SynthReel/Source/Assets.xcassets/myShort/FacebookBg.imageset/FacebookBg@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 28 KiB |
22
SynthReel/Source/Assets.xcassets/myShort/adlock.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "adlock@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "adlock@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
SynthReel/Source/Assets.xcassets/myShort/adlock.imageset/adlock@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 648 B |
BIN
SynthReel/Source/Assets.xcassets/myShort/adlock.imageset/adlock@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 880 B |
22
SynthReel/Source/Assets.xcassets/myShort/appleBg.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "appleBg@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "appleBg@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
SynthReel/Source/Assets.xcassets/myShort/appleBg.imageset/appleBg@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
SynthReel/Source/Assets.xcassets/myShort/appleBg.imageset/appleBg@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 27 KiB |
22
SynthReel/Source/Assets.xcassets/myShort/lock.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "lock@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "lock@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
SynthReel/Source/Assets.xcassets/myShort/lock.imageset/lock@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
SynthReel/Source/Assets.xcassets/myShort/lock.imageset/lock@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
22
SynthReel/Source/Assets.xcassets/myShort/loginBg.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "loginBg@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "loginBg@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
SynthReel/Source/Assets.xcassets/myShort/loginBg.imageset/loginBg@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
SynthReel/Source/Assets.xcassets/myShort/loginBg.imageset/loginBg@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 146 KiB |
@ -2,8 +2,29 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>UIDesignRequiresCompatibility</key>
|
<key>CFBundleURLTypes</key>
|
||||||
<true/>
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Editor</string>
|
||||||
|
<key>CFBundleURLSchemes</key>
|
||||||
|
<array>
|
||||||
|
<string>synthreel</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Editor</string>
|
||||||
|
<key>CFBundleURLSchemes</key>
|
||||||
|
<array>
|
||||||
|
<string>fb1765365954312054</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
<key>FacebookAppID</key>
|
||||||
|
<string>1765365954312054</string>
|
||||||
|
<key>FacebookClientToken</key>
|
||||||
|
<string>7a0b78de0a5f0e04738e8596b1b50aaa</string>
|
||||||
<key>UIApplicationSceneManifest</key>
|
<key>UIApplicationSceneManifest</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>UIApplicationSupportsMultipleScenes</key>
|
<key>UIApplicationSupportsMultipleScenes</key>
|
||||||
@ -21,5 +42,12 @@
|
|||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
|
<key>UIBackgroundModes</key>
|
||||||
|
<array>
|
||||||
|
<string>fetch</string>
|
||||||
|
<string>remote-notification</string>
|
||||||
|
</array>
|
||||||
|
<key>UIDesignRequiresCompatibility</key>
|
||||||
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@ -34,9 +34,19 @@
|
|||||||
"Keep the Drama Going" = "Keep the Drama Going";
|
"Keep the Drama Going" = "Keep the Drama Going";
|
||||||
"synthreel_feedback" = "FeedBack";
|
"synthreel_feedback" = "FeedBack";
|
||||||
"synthreel_feedback_history" = "Feedback History";
|
"synthreel_feedback_history" = "Feedback History";
|
||||||
|
"synthreel_login" = "login";
|
||||||
|
"synthreel_logout" = "logout";
|
||||||
"synthreel_feedback_detail" = "Feedback Details";
|
"synthreel_feedback_detail" = "Feedback Details";
|
||||||
"synthreel_account_deletion" = "Account Deletion";
|
"synthreel_account_deletion" = "Account Deletion";
|
||||||
"Rewards" = "Rewards";
|
"Rewards" = "Rewards";
|
||||||
"Daily reward ready !" = "Daily reward ready !";
|
"Daily reward ready !" = "Daily reward ready !";
|
||||||
"Claim your rewards now" = "Claim your rewards now";
|
"Claim your rewards now" = "Claim your rewards now";
|
||||||
"My Refills" = "My Refills";
|
"My Refills" = "My Refills";
|
||||||
|
"synthreel_unlocking_coins_notice" = "Unlock";
|
||||||
|
"video_lock_tip_text" = "Pre.locked";
|
||||||
|
"Watch 2ads to unlock" = "Watch 2ads to unlock";
|
||||||
|
"synthreel_success" = "success";
|
||||||
|
"buy_fail_toast_01" = "Purchase failed, please try again later!";
|
||||||
|
"buy_fail_toast_02" = "The prequel to this series is not unlocked. Please unlock the prequel before unlocking this series";
|
||||||
|
"Login With Facebook" = "Login With Facebook";
|
||||||
|
"Login With Apple" = "Login With Apple";
|
||||||
|
|||||||
12
SynthReel/SynthReel.entitlements
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>aps-environment</key>
|
||||||
|
<string>development</string>
|
||||||
|
<key>com.apple.developer.applesignin</key>
|
||||||
|
<array>
|
||||||
|
<string>Default</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||