Compare commits
No commits in common. "54742c4a674d830e750911cda51d56dfd4c20433" and "36b6cf95a0e89d30408063694bb62d1232926315" have entirely different histories.
54742c4a67
...
36b6cf95a0
@ -7,37 +7,6 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
031FDEAC2EAF05FB00F4CAC7 /* FAStoreVipCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDEAB2EAF05FB00F4CAC7 /* FAStoreVipCell.swift */; };
|
||||
031FDEAE2EB093B100F4CAC7 /* FABuyRecordsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDEAD2EB093B100F4CAC7 /* FABuyRecordsModel.swift */; };
|
||||
031FDEB02EB09AB300F4CAC7 /* FARechargeRecordModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDEAF2EB09AB300F4CAC7 /* FARechargeRecordModel.swift */; };
|
||||
031FDEB22EB0A5AF00F4CAC7 /* FASendCoinRecordModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDEB12EB0A5AF00F4CAC7 /* FASendCoinRecordModel.swift */; };
|
||||
031FDEB42EB0AD7D00F4CAC7 /* FACoinPackConfirmView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDEB32EB0AD7D00F4CAC7 /* FACoinPackConfirmView.swift */; };
|
||||
031FDEB62EB0B77F00F4CAC7 /* FACoinPackConfirmItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDEB52EB0B77F00F4CAC7 /* FACoinPackConfirmItemView.swift */; };
|
||||
031FDEB82EB0B80400F4CAC7 /* FACoinPackConfirmItem1View.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDEB72EB0B80400F4CAC7 /* FACoinPackConfirmItem1View.swift */; };
|
||||
031FDEBA2EB0B82600F4CAC7 /* FACoinPackConfirmItem2View.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDEB92EB0B82600F4CAC7 /* FACoinPackConfirmItem2View.swift */; };
|
||||
031FDEBC2EB0C97A00F4CAC7 /* FAOldVideoRechargeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDEBB2EB0C97A00F4CAC7 /* FAOldVideoRechargeView.swift */; };
|
||||
031FDEBE2EB0C99900F4CAC7 /* FANewVideoRechargeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDEBD2EB0C99900F4CAC7 /* FANewVideoRechargeView.swift */; };
|
||||
039CE6042EAA2621007B5EED /* AppDelegate+FAAdjust.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039CE6032EAA2612007B5EED /* AppDelegate+FAAdjust.swift */; };
|
||||
039CE6092EAA2F71007B5EED /* FAAdjustStateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039CE6082EAA2F62007B5EED /* FAAdjustStateManager.swift */; };
|
||||
039CE60B2EAA31CB007B5EED /* FAStatAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039CE60A2EAA31CB007B5EED /* FAStatAPI.swift */; };
|
||||
039CE60E2EAA32A8007B5EED /* FAOpenAppModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039CE60D2EAA32A8007B5EED /* FAOpenAppModel.swift */; };
|
||||
039CE6112EAB0D49007B5EED /* JXIAPManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039CE6102EAB0D47007B5EED /* JXIAPManager.swift */; };
|
||||
039CE6142EAB0E0D007B5EED /* FAIapManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039CE6132EAB0E0D007B5EED /* FAIapManager.swift */; };
|
||||
039CE6162EAB0E30007B5EED /* FAWaitRestoreModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039CE6152EAB0E30007B5EED /* FAWaitRestoreModel.swift */; };
|
||||
039CE6182EAB0E7E007B5EED /* FAStoreAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039CE6172EAB0E7E007B5EED /* FAStoreAPI.swift */; };
|
||||
039CE61A2EAB0EE0007B5EED /* FAIapVerifyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039CE6192EAB0EE0007B5EED /* FAIapVerifyModel.swift */; };
|
||||
039CE61C2EAB0F29007B5EED /* FAIapOrderModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039CE61B2EAB0F29007B5EED /* FAIapOrderModel.swift */; };
|
||||
039CE6202EAB114B007B5EED /* FAPayDateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039CE61F2EAB114B007B5EED /* FAPayDateModel.swift */; };
|
||||
039CE6222EAB1340007B5EED /* FAUserDefaultsKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039CE6212EAB1335007B5EED /* FAUserDefaultsKey.swift */; };
|
||||
039CE6242EAB29D1007B5EED /* FAPayDataRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039CE6232EAB29D1007B5EED /* FAPayDataRequest.swift */; };
|
||||
039CE6262EAB2A72007B5EED /* FAPayAlertModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039CE6252EAB2A72007B5EED /* FAPayAlertModel.swift */; };
|
||||
039CE6282EAB50A9007B5EED /* FAStoreCoinsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039CE6272EAB50A9007B5EED /* FAStoreCoinsView.swift */; };
|
||||
039CE62A2EAB5A8C007B5EED /* FAStoreCoinsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039CE6292EAB5A8C007B5EED /* FAStoreCoinsCell.swift */; };
|
||||
039CE62C2EAB5B07007B5EED /* FAStoreCoinsBigCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039CE62B2EAB5B07007B5EED /* FAStoreCoinsBigCell.swift */; };
|
||||
039CE62E2EAB5B18007B5EED /* FAStoreCoinsSmallCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039CE62D2EAB5B18007B5EED /* FAStoreCoinsSmallCell.swift */; };
|
||||
039CE6302EAB5B26007B5EED /* FAStoreCoinsPackCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039CE62F2EAB5B26007B5EED /* FAStoreCoinsPackCell.swift */; };
|
||||
039CE6322EAB796F007B5EED /* FALabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039CE6312EAB796F007B5EED /* FALabel.swift */; };
|
||||
03DBD8512EAEFF5F00DD04B8 /* FAStoreVipView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03DBD8502EAEFF5F00DD04B8 /* FAStoreVipView.swift */; };
|
||||
03E239632EAA1945004A8CEC /* AppDelegate+FAConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E239612EAA1945004A8CEC /* AppDelegate+FAConfig.swift */; };
|
||||
03E239642EAA1945004A8CEC /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E239602EAA1945004A8CEC /* AppDelegate.swift */; };
|
||||
03E239652EAA1945004A8CEC /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E239622EAA1945004A8CEC /* SceneDelegate.swift */; };
|
||||
@ -296,38 +265,6 @@
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
031FDEAB2EAF05FB00F4CAC7 /* FAStoreVipCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAStoreVipCell.swift; sourceTree = "<group>"; };
|
||||
031FDEAD2EB093B100F4CAC7 /* FABuyRecordsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FABuyRecordsModel.swift; sourceTree = "<group>"; };
|
||||
031FDEAF2EB09AB300F4CAC7 /* FARechargeRecordModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FARechargeRecordModel.swift; sourceTree = "<group>"; };
|
||||
031FDEB12EB0A5AF00F4CAC7 /* FASendCoinRecordModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FASendCoinRecordModel.swift; sourceTree = "<group>"; };
|
||||
031FDEB32EB0AD7D00F4CAC7 /* FACoinPackConfirmView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FACoinPackConfirmView.swift; sourceTree = "<group>"; };
|
||||
031FDEB52EB0B77F00F4CAC7 /* FACoinPackConfirmItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FACoinPackConfirmItemView.swift; sourceTree = "<group>"; };
|
||||
031FDEB72EB0B80400F4CAC7 /* FACoinPackConfirmItem1View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FACoinPackConfirmItem1View.swift; sourceTree = "<group>"; };
|
||||
031FDEB92EB0B82600F4CAC7 /* FACoinPackConfirmItem2View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FACoinPackConfirmItem2View.swift; sourceTree = "<group>"; };
|
||||
031FDEBB2EB0C97A00F4CAC7 /* FAOldVideoRechargeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAOldVideoRechargeView.swift; sourceTree = "<group>"; };
|
||||
031FDEBD2EB0C99900F4CAC7 /* FANewVideoRechargeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FANewVideoRechargeView.swift; sourceTree = "<group>"; };
|
||||
039CE6032EAA2612007B5EED /* AppDelegate+FAAdjust.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+FAAdjust.swift"; sourceTree = "<group>"; };
|
||||
039CE6082EAA2F62007B5EED /* FAAdjustStateManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAAdjustStateManager.swift; sourceTree = "<group>"; };
|
||||
039CE60A2EAA31CB007B5EED /* FAStatAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAStatAPI.swift; sourceTree = "<group>"; };
|
||||
039CE60D2EAA32A8007B5EED /* FAOpenAppModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAOpenAppModel.swift; sourceTree = "<group>"; };
|
||||
039CE6102EAB0D47007B5EED /* JXIAPManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JXIAPManager.swift; sourceTree = "<group>"; };
|
||||
039CE6132EAB0E0D007B5EED /* FAIapManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAIapManager.swift; sourceTree = "<group>"; };
|
||||
039CE6152EAB0E30007B5EED /* FAWaitRestoreModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAWaitRestoreModel.swift; sourceTree = "<group>"; };
|
||||
039CE6172EAB0E7E007B5EED /* FAStoreAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAStoreAPI.swift; sourceTree = "<group>"; };
|
||||
039CE6192EAB0EE0007B5EED /* FAIapVerifyModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAIapVerifyModel.swift; sourceTree = "<group>"; };
|
||||
039CE61B2EAB0F29007B5EED /* FAIapOrderModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAIapOrderModel.swift; sourceTree = "<group>"; };
|
||||
039CE61D2EAB0FE4007B5EED /* Fableon.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Fableon.entitlements; sourceTree = "<group>"; };
|
||||
039CE61F2EAB114B007B5EED /* FAPayDateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAPayDateModel.swift; sourceTree = "<group>"; };
|
||||
039CE6212EAB1335007B5EED /* FAUserDefaultsKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAUserDefaultsKey.swift; sourceTree = "<group>"; };
|
||||
039CE6232EAB29D1007B5EED /* FAPayDataRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAPayDataRequest.swift; sourceTree = "<group>"; };
|
||||
039CE6252EAB2A72007B5EED /* FAPayAlertModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAPayAlertModel.swift; sourceTree = "<group>"; };
|
||||
039CE6272EAB50A9007B5EED /* FAStoreCoinsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAStoreCoinsView.swift; sourceTree = "<group>"; };
|
||||
039CE6292EAB5A8C007B5EED /* FAStoreCoinsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAStoreCoinsCell.swift; sourceTree = "<group>"; };
|
||||
039CE62B2EAB5B07007B5EED /* FAStoreCoinsBigCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAStoreCoinsBigCell.swift; sourceTree = "<group>"; };
|
||||
039CE62D2EAB5B18007B5EED /* FAStoreCoinsSmallCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAStoreCoinsSmallCell.swift; sourceTree = "<group>"; };
|
||||
039CE62F2EAB5B26007B5EED /* FAStoreCoinsPackCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAStoreCoinsPackCell.swift; sourceTree = "<group>"; };
|
||||
039CE6312EAB796F007B5EED /* FALabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FALabel.swift; sourceTree = "<group>"; };
|
||||
03DBD8502EAEFF5F00DD04B8 /* FAStoreVipView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAStoreVipView.swift; sourceTree = "<group>"; };
|
||||
03E239602EAA1945004A8CEC /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
03E239612EAA1945004A8CEC /* AppDelegate+FAConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+FAConfig.swift"; sourceTree = "<group>"; };
|
||||
03E239622EAA1945004A8CEC /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
|
||||
@ -601,54 +538,6 @@
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
039CE6072EAA2F37007B5EED /* AdjustStateManager */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
039CE6082EAA2F62007B5EED /* FAAdjustStateManager.swift */,
|
||||
);
|
||||
path = AdjustStateManager;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
039CE60C2EAA328A007B5EED /* Model */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
039CE60D2EAA32A8007B5EED /* FAOpenAppModel.swift */,
|
||||
);
|
||||
path = Model;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
039CE60F2EAB0D2D007B5EED /* JXIAPManager */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
039CE6102EAB0D47007B5EED /* JXIAPManager.swift */,
|
||||
);
|
||||
path = JXIAPManager;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
039CE6122EAB0DE1007B5EED /* FAIap */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
039CE6132EAB0E0D007B5EED /* FAIapManager.swift */,
|
||||
039CE6232EAB29D1007B5EED /* FAPayDataRequest.swift */,
|
||||
039CE6192EAB0EE0007B5EED /* FAIapVerifyModel.swift */,
|
||||
039CE61B2EAB0F29007B5EED /* FAIapOrderModel.swift */,
|
||||
039CE6152EAB0E30007B5EED /* FAWaitRestoreModel.swift */,
|
||||
);
|
||||
path = FAIap;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
039CE61E2EAB10EC007B5EED /* M */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
039CE61F2EAB114B007B5EED /* FAPayDateModel.swift */,
|
||||
039CE6252EAB2A72007B5EED /* FAPayAlertModel.swift */,
|
||||
031FDEAD2EB093B100F4CAC7 /* FABuyRecordsModel.swift */,
|
||||
031FDEAF2EB09AB300F4CAC7 /* FARechargeRecordModel.swift */,
|
||||
031FDEB12EB0A5AF00F4CAC7 /* FASendCoinRecordModel.swift */,
|
||||
);
|
||||
path = M;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
03E2395F2EAA1900004A8CEC /* Object */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -663,7 +552,6 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
03E2396A2EAA1A29004A8CEC /* Controller */,
|
||||
039CE60C2EAA328A007B5EED /* Model */,
|
||||
03E2396C2EAA1A29004A8CEC /* Define */,
|
||||
03E2397A2EAA1A29004A8CEC /* Extension */,
|
||||
03E239812EAA1A29004A8CEC /* Request */,
|
||||
@ -687,7 +575,6 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
03E2396B2EAA1A29004A8CEC /* FADefine.swift */,
|
||||
039CE6212EAB1335007B5EED /* FAUserDefaultsKey.swift */,
|
||||
);
|
||||
path = Define;
|
||||
sourceTree = "<group>";
|
||||
@ -723,8 +610,6 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
03E2397B2EAA1A29004A8CEC /* FAAPI.swift */,
|
||||
039CE60A2EAA31CB007B5EED /* FAStatAPI.swift */,
|
||||
039CE6172EAB0E7E007B5EED /* FAStoreAPI.swift */,
|
||||
);
|
||||
path = FAAPI;
|
||||
sourceTree = "<group>";
|
||||
@ -752,7 +637,6 @@
|
||||
03E239872EAA1A29004A8CEC /* FAScrollView.swift */,
|
||||
03E239882EAA1A29004A8CEC /* FATableView.swift */,
|
||||
03E239892EAA1A29004A8CEC /* FATableViewCell.swift */,
|
||||
039CE6312EAB796F007B5EED /* FALabel.swift */,
|
||||
);
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
@ -978,8 +862,6 @@
|
||||
03E23A0E2EAA1A4E004A8CEC /* FAPlayerDetailControlView.swift */,
|
||||
03E23A0F2EAA1A4E004A8CEC /* FAPlayerProgressView.swift */,
|
||||
03E23A102EAA1A4E004A8CEC /* FAVideoLockView.swift */,
|
||||
031FDEBB2EB0C97A00F4CAC7 /* FAOldVideoRechargeView.swift */,
|
||||
031FDEBD2EB0C99900F4CAC7 /* FANewVideoRechargeView.swift */,
|
||||
);
|
||||
path = V;
|
||||
sourceTree = "<group>";
|
||||
@ -1003,10 +885,10 @@
|
||||
03E23A162EAA1A4E004A8CEC /* Player */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
03E23A082EAA1A4E004A8CEC /* UI */,
|
||||
03E23A132EAA1A4E004A8CEC /* VC */,
|
||||
03E23A062EAA1A4E004A8CEC /* M */,
|
||||
03E23A082EAA1A4E004A8CEC /* UI */,
|
||||
03E23A112EAA1A4E004A8CEC /* V */,
|
||||
03E23A132EAA1A4E004A8CEC /* VC */,
|
||||
03E23A152EAA1A4E004A8CEC /* VM */,
|
||||
);
|
||||
path = Player;
|
||||
@ -1050,13 +932,13 @@
|
||||
03E23A262EAA1A4E004A8CEC /* C */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
03E23A232EAA1A4E004A8CEC /* FAStoreViewController.swift */,
|
||||
03E23A252EAA1A4E004A8CEC /* FAWalletViewController.swift */,
|
||||
03E23A1F2EAA1A4E004A8CEC /* FACoinRecordViewController.swift */,
|
||||
03E23A202EAA1A4E004A8CEC /* FAConsumptionRecordsViewController.swift */,
|
||||
03E23A212EAA1A4E004A8CEC /* FAOrderRecordsViewController.swift */,
|
||||
03E23A222EAA1A4E004A8CEC /* FARewardCoinsViewController.swift */,
|
||||
03E23A232EAA1A4E004A8CEC /* FAStoreViewController.swift */,
|
||||
03E23A242EAA1A4E004A8CEC /* FAVipRecordViewController.swift */,
|
||||
03E23A252EAA1A4E004A8CEC /* FAWalletViewController.swift */,
|
||||
);
|
||||
path = C;
|
||||
sourceTree = "<group>";
|
||||
@ -1073,17 +955,6 @@
|
||||
03E23A2D2EAA1A4E004A8CEC /* FAWalletCell.swift */,
|
||||
03E23A2E2EAA1A4E004A8CEC /* FAWalletCell.xib */,
|
||||
03E23A2F2EAA1A4E004A8CEC /* FAWalletHeaderView.swift */,
|
||||
039CE6272EAB50A9007B5EED /* FAStoreCoinsView.swift */,
|
||||
03DBD8502EAEFF5F00DD04B8 /* FAStoreVipView.swift */,
|
||||
039CE6292EAB5A8C007B5EED /* FAStoreCoinsCell.swift */,
|
||||
039CE62B2EAB5B07007B5EED /* FAStoreCoinsBigCell.swift */,
|
||||
039CE62D2EAB5B18007B5EED /* FAStoreCoinsSmallCell.swift */,
|
||||
039CE62F2EAB5B26007B5EED /* FAStoreCoinsPackCell.swift */,
|
||||
031FDEAB2EAF05FB00F4CAC7 /* FAStoreVipCell.swift */,
|
||||
031FDEB32EB0AD7D00F4CAC7 /* FACoinPackConfirmView.swift */,
|
||||
031FDEB52EB0B77F00F4CAC7 /* FACoinPackConfirmItemView.swift */,
|
||||
031FDEB72EB0B80400F4CAC7 /* FACoinPackConfirmItem1View.swift */,
|
||||
031FDEB92EB0B82600F4CAC7 /* FACoinPackConfirmItem2View.swift */,
|
||||
);
|
||||
path = V;
|
||||
sourceTree = "<group>";
|
||||
@ -1093,7 +964,6 @@
|
||||
children = (
|
||||
03E23A262EAA1A4E004A8CEC /* C */,
|
||||
03E23A302EAA1A4E004A8CEC /* V */,
|
||||
039CE61E2EAB10EC007B5EED /* M */,
|
||||
);
|
||||
path = Store;
|
||||
sourceTree = "<group>";
|
||||
@ -1101,9 +971,6 @@
|
||||
03E23A962EAA1A65004A8CEC /* Libs */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
039CE6122EAB0DE1007B5EED /* FAIap */,
|
||||
039CE60F2EAB0D2D007B5EED /* JXIAPManager */,
|
||||
039CE6072EAA2F37007B5EED /* AdjustStateManager */,
|
||||
03E23A982EAA1A7F004A8CEC /* Empty */,
|
||||
03E23A9B2EAA1A7F004A8CEC /* FADeviceId */,
|
||||
03E23A9D2EAA1A7F004A8CEC /* FALocalized */,
|
||||
@ -1601,7 +1468,6 @@
|
||||
children = (
|
||||
03E239602EAA1945004A8CEC /* AppDelegate.swift */,
|
||||
03E239612EAA1945004A8CEC /* AppDelegate+FAConfig.swift */,
|
||||
039CE6032EAA2612007B5EED /* AppDelegate+FAAdjust.swift */,
|
||||
03E239622EAA1945004A8CEC /* SceneDelegate.swift */,
|
||||
);
|
||||
path = App;
|
||||
@ -1639,7 +1505,6 @@
|
||||
F3YR32SS1P8731297KD665X5 /* Fableon */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
039CE61D2EAB0FE4007B5EED /* Fableon.entitlements */,
|
||||
F3U31ND27BB4R9G072AN9BM3 /* App */,
|
||||
03E2395F2EAA1900004A8CEC /* Object */,
|
||||
F3IF9S30I6U4301G5521663T /* Source */,
|
||||
@ -1822,16 +1687,11 @@
|
||||
F3Q1B8O8164TYQ9724T34V29 /* OACAbleView.swift in Sources */,
|
||||
F36MZ39RQ295569BV1915908 /* FOMptyView.swift in Sources */,
|
||||
F323CZU4466303487TY7K12U /* YHRegister.swift in Sources */,
|
||||
031FDEB02EB09AB300F4CAC7 /* FARechargeRecordModel.swift in Sources */,
|
||||
F35T0LSS4O974ZP1IJ27TB30 /* BEedbackCenterController.swift in Sources */,
|
||||
F39356S815VILHH18O4HK577 /* BHSSwiftRefresh.swift in Sources */,
|
||||
F33O83184592105998E35JY1 /* VRServiceCenterItem.swift in Sources */,
|
||||
F347N086226Y53261B0285I3 /* QLoginRoundedView.swift in Sources */,
|
||||
031FDEB22EB0A5AF00F4CAC7 /* FASendCoinRecordModel.swift in Sources */,
|
||||
03DBD8512EAEFF5F00DD04B8 /* FAStoreVipView.swift in Sources */,
|
||||
031FDEB62EB0B77F00F4CAC7 /* FACoinPackConfirmItemView.swift in Sources */,
|
||||
F35S8138Z362EG3435ME1455 /* CSGleeView.swift in Sources */,
|
||||
031FDEB42EB0AD7D00F4CAC7 /* FACoinPackConfirmView.swift in Sources */,
|
||||
F31451S3X15B941342J922Q3 /* TConfigCell.swift in Sources */,
|
||||
F3670DZ2KI89TBO3L9L36P57 /* XLoginView.swift in Sources */,
|
||||
F3V24670CK2EGR4595CDQ261 /* AWUModalMageCell.swift in Sources */,
|
||||
@ -1842,7 +1702,6 @@
|
||||
F381909BQ5JWXYI119A49469 /* DREychainCell.swift in Sources */,
|
||||
F39R66F983517825QO331145 /* QCenterEfineView.swift in Sources */,
|
||||
F3II3AF834346F516W51V693 /* GAMainRecommendedView.swift in Sources */,
|
||||
031FDEAE2EB093B100F4CAC7 /* FABuyRecordsModel.swift in Sources */,
|
||||
F377Y22Z3J44H22J23963544 /* CDNewsController.swift in Sources */,
|
||||
F358686093028548K00WQIO1 /* NGleeVionView.swift in Sources */,
|
||||
F3019606DA7P36H41G408X13 /* ZStreamCell.swift in Sources */,
|
||||
@ -1857,13 +1716,11 @@
|
||||
03E239632EAA1945004A8CEC /* AppDelegate+FAConfig.swift in Sources */,
|
||||
03E239642EAA1945004A8CEC /* AppDelegate.swift in Sources */,
|
||||
03E239652EAA1945004A8CEC /* SceneDelegate.swift in Sources */,
|
||||
039CE6092EAA2F71007B5EED /* FAAdjustStateManager.swift in Sources */,
|
||||
F333U95746V7VK13QI9275B3 /* UMenuTransformerCell.swift in Sources */,
|
||||
F3Q234J5M18F1Q5G2948P056 /* NPVBoutModalController.swift in Sources */,
|
||||
F38Y7NBX3M0RE4O142264411 /* EZEFlow.swift in Sources */,
|
||||
F363P024H4W1T8LN2546W883 /* YBanner.swift in Sources */,
|
||||
F3P4D170962A2JAF14W0520R /* ADCheckMageView.swift in Sources */,
|
||||
031FDEBA2EB0B82600F4CAC7 /* FACoinPackConfirmItem2View.swift in Sources */,
|
||||
F3206101P0DVK224N85S1W62 /* XIPathEviceController.swift in Sources */,
|
||||
F31N0S2575E3YC5AOG80WE90 /* TYElyon.swift in Sources */,
|
||||
F3JX29E3JQ40V23245TS8Z36 /* YRegisterController.swift in Sources */,
|
||||
@ -1872,7 +1729,6 @@
|
||||
F39EH05VP4YX3F00P5162031 /* YFddebcdbeeffcebdfCenterView.swift in Sources */,
|
||||
F32T95836171611R26I33D4D /* AJMEychainView.swift in Sources */,
|
||||
F3242J387RV5714007E92OH3 /* BEOConfigController.swift in Sources */,
|
||||
031FDEAC2EAF05FB00F4CAC7 /* FAStoreVipCell.swift in Sources */,
|
||||
F3N346893L1U6DP8228XK227 /* UOLaunch.swift in Sources */,
|
||||
F39S0H806843N21RM0O95488 /* VARResultController.swift in Sources */,
|
||||
F3D03219Y8NV50N2S66014LX /* GPOOllectionFableon.swift in Sources */,
|
||||
@ -1882,25 +1738,20 @@
|
||||
03E23AAC2EAA1A7F004A8CEC /* FALogin.swift in Sources */,
|
||||
03E23AAD2EAA1A7F004A8CEC /* FAKeychainHelper.swift in Sources */,
|
||||
03E23AAE2EAA1A7F004A8CEC /* FATool.swift in Sources */,
|
||||
039CE6262EAB2A72007B5EED /* FAPayAlertModel.swift in Sources */,
|
||||
03E23AAF2EAA1A7F004A8CEC /* FSPagerSwiftUIView.swift in Sources */,
|
||||
03E23AB02EAA1A7F004A8CEC /* FADeviceIDManager.swift in Sources */,
|
||||
03E23AB12EAA1A7F004A8CEC /* FATokenModel.swift in Sources */,
|
||||
03E23AB22EAA1A7F004A8CEC /* FAEmpty.swift in Sources */,
|
||||
03E23AB32EAA1A7F004A8CEC /* FAHUD.swift in Sources */,
|
||||
03E23AB42EAA1A7F004A8CEC /* FAPagerViewTransformer.swift in Sources */,
|
||||
039CE62A2EAB5A8C007B5EED /* FAStoreCoinsCell.swift in Sources */,
|
||||
039CE6242EAB29D1007B5EED /* FAPayDataRequest.swift in Sources */,
|
||||
03E23AB52EAA1A7F004A8CEC /* FAToast.swift in Sources */,
|
||||
03E23AB62EAA1A7F004A8CEC /* FAUserInfo.swift in Sources */,
|
||||
03E23AB72EAA1A7F004A8CEC /* FALocalized.swift in Sources */,
|
||||
039CE6222EAB1340007B5EED /* FAUserDefaultsKey.swift in Sources */,
|
||||
03E23AB82EAA1A7F004A8CEC /* FAWaterfallFlowLayout.swift in Sources */,
|
||||
F3K238643L913I6RK4G7S006 /* CSceneRegister.swift in Sources */,
|
||||
F3ZT3I4VAGB5405FWL36UW12 /* ZFGEtworkCell.swift in Sources */,
|
||||
F35O71332554S53191121042 /* UOModalCell.swift in Sources */,
|
||||
F3L30772U87770116598U282 /* NLaunchDelegate.swift in Sources */,
|
||||
039CE62C2EAB5B07007B5EED /* FAStoreCoinsBigCell.swift in Sources */,
|
||||
F38L64O0092TC8W47P271967 /* COcalizedController.swift in Sources */,
|
||||
03E23A322EAA1A4E004A8CEC /* FAFeedbackViewController.swift in Sources */,
|
||||
03E23A332EAA1A4E004A8CEC /* FAHomeRecommendedItemView.swift in Sources */,
|
||||
@ -1926,7 +1777,6 @@
|
||||
03E23A472EAA1A4E004A8CEC /* FAPlayerDetailControlView.swift in Sources */,
|
||||
03E23A482EAA1A4E004A8CEC /* FARewardCoinsCell.swift in Sources */,
|
||||
03E23A492EAA1A4E004A8CEC /* FAVideoInfoModel.swift in Sources */,
|
||||
039CE6202EAB114B007B5EED /* FAPayDateModel.swift in Sources */,
|
||||
03E23A4A2EAA1A4E004A8CEC /* FAConsumptionRecordsViewController.swift in Sources */,
|
||||
03E23A4B2EAA1A4E004A8CEC /* FAMeCoinsView.swift in Sources */,
|
||||
03E23A4C2EAA1A4E004A8CEC /* FAHomeViewModel.swift in Sources */,
|
||||
@ -1939,7 +1789,6 @@
|
||||
03E23A532EAA1A4E004A8CEC /* FAVideoLockView.swift in Sources */,
|
||||
03E23A542EAA1A4E004A8CEC /* FAHomeViewController.swift in Sources */,
|
||||
03E23A552EAA1A4E004A8CEC /* FAPopularListViewController.swift in Sources */,
|
||||
039CE6042EAA2621007B5EED /* AppDelegate+FAAdjust.swift in Sources */,
|
||||
03E23A562EAA1A4E004A8CEC /* FAPlayerEpUIButton.swift in Sources */,
|
||||
03E23A572EAA1A4E004A8CEC /* FAHistoryCell.swift in Sources */,
|
||||
03E23A582EAA1A4E004A8CEC /* FASearchViewController.swift in Sources */,
|
||||
@ -1972,8 +1821,6 @@
|
||||
03E23A732EAA1A4E004A8CEC /* FASearchRecordCell.swift in Sources */,
|
||||
03E23A742EAA1A4E004A8CEC /* FAShortPlayModel.swift in Sources */,
|
||||
03E23A752EAA1A4E004A8CEC /* FASearchRecommendCell.swift in Sources */,
|
||||
039CE6162EAB0E30007B5EED /* FAWaitRestoreModel.swift in Sources */,
|
||||
039CE6302EAB5B26007B5EED /* FAStoreCoinsPackCell.swift in Sources */,
|
||||
03E23A762EAA1A4E004A8CEC /* FASearchHomeView.swift in Sources */,
|
||||
03E23A772EAA1A4E004A8CEC /* FAHomeNewContentCell.swift in Sources */,
|
||||
03E23A782EAA1A4E004A8CEC /* FAOrderRecordsViewController.swift in Sources */,
|
||||
@ -1983,13 +1830,11 @@
|
||||
03E23A7C2EAA1A4E004A8CEC /* FAMeCell.swift in Sources */,
|
||||
03E23A7D2EAA1A4E004A8CEC /* FAWalletHeaderView.swift in Sources */,
|
||||
03E23A7E2EAA1A4E004A8CEC /* FAPlayerProgressView.swift in Sources */,
|
||||
031FDEB82EB0B80400F4CAC7 /* FACoinPackConfirmItem1View.swift in Sources */,
|
||||
03E23A7F2EAA1A4E004A8CEC /* FAMeItemModel.swift in Sources */,
|
||||
03E23A802EAA1A4E004A8CEC /* FAGenresListCell.swift in Sources */,
|
||||
03E23A812EAA1A4E004A8CEC /* FACollectCell.swift in Sources */,
|
||||
03E23A822EAA1A4E004A8CEC /* FASearchRecommendView.swift in Sources */,
|
||||
03E23A832EAA1A4E004A8CEC /* FAHomeMustSeeShortView.swift in Sources */,
|
||||
039CE60B2EAA31CB007B5EED /* FAStatAPI.swift in Sources */,
|
||||
03E23A842EAA1A4E004A8CEC /* FACoinRecordViewController.swift in Sources */,
|
||||
F3511I08934IV2C80B9Z6X2T /* QDVBoutLayout.swift in Sources */,
|
||||
F311250SJ7I3DZ74X009990N /* XJSelectorCell.swift in Sources */,
|
||||
@ -1997,27 +1842,22 @@
|
||||
F3O215L13X5155316V412904 /* AOkenView.swift in Sources */,
|
||||
F3G0PR235Z2X602JE530X692 /* EQThimraPathController.swift in Sources */,
|
||||
F3563UZ4T03I36J2R93Y31N6 /* IMRefreshManagerController.swift in Sources */,
|
||||
039CE6112EAB0D49007B5EED /* JXIAPManager.swift in Sources */,
|
||||
F3981047B9214665100286YG /* BZOEarchView.swift in Sources */,
|
||||
03E23ABA2EAA1D85004A8CEC /* MNNItemController.swift in Sources */,
|
||||
F3817W6E02182D9A62U02849 /* WHAOastMainCell.swift in Sources */,
|
||||
F32C0941C670UO0IU4114086 /* XHDelegate.swift in Sources */,
|
||||
039CE61A2EAB0EE0007B5EED /* FAIapVerifyModel.swift in Sources */,
|
||||
F3XWY0D08020883935X46FG7 /* FHeaderController.swift in Sources */,
|
||||
F3223B1O80A345NB22134220 /* LAgerShortController.swift in Sources */,
|
||||
F3Q51496018LRJ1691985D08 /* PYMOastCell.swift in Sources */,
|
||||
F33Q5651983154V88746Y001 /* ODPlayerCell.swift in Sources */,
|
||||
F3774560U03XA8151BTQ2Z61 /* HYLLayoutView.swift in Sources */,
|
||||
F3N85463XSRG9VFK665G9028 /* XKRefreshCell.swift in Sources */,
|
||||
039CE6282EAB50A9007B5EED /* FAStoreCoinsView.swift in Sources */,
|
||||
F35K41930D96476I83FHZ0D9 /* YLZFableonAlignmentCell.swift in Sources */,
|
||||
F3M8439X72Q55JY9G8U502D9 /* DXYFire.swift in Sources */,
|
||||
03E239912EAA1A29004A8CEC /* Dictionary+FAAdd.swift in Sources */,
|
||||
03E239922EAA1A29004A8CEC /* FAImageView.swift in Sources */,
|
||||
031FDEBE2EB0C99900F4CAC7 /* FANewVideoRechargeView.swift in Sources */,
|
||||
03E239932EAA1A29004A8CEC /* Date+FAAdd.swift in Sources */,
|
||||
03E239942EAA1A29004A8CEC /* UserDefaults+FAAdd.swift in Sources */,
|
||||
039CE6322EAB796F007B5EED /* FALabel.swift in Sources */,
|
||||
03E239952EAA1A29004A8CEC /* Font+FAAdd.swift in Sources */,
|
||||
03E239962EAA1A29004A8CEC /* FACryptorService.swift in Sources */,
|
||||
03E239972EAA1A29004A8CEC /* FANetworkManager.swift in Sources */,
|
||||
@ -2026,7 +1866,6 @@
|
||||
03E2399A2EAA1A29004A8CEC /* FAViewController.swift in Sources */,
|
||||
03E2399B2EAA1A29004A8CEC /* FAWebMessageModel.swift in Sources */,
|
||||
03E2399C2EAA1A29004A8CEC /* FAGradientButton.swift in Sources */,
|
||||
039CE6142EAB0E0D007B5EED /* FAIapManager.swift in Sources */,
|
||||
03E2399D2EAA1A29004A8CEC /* FAGradientView.swift in Sources */,
|
||||
03E2399E2EAA1A29004A8CEC /* FADefine.swift in Sources */,
|
||||
03E2399F2EAA1A29004A8CEC /* FABaseWebViewController.swift in Sources */,
|
||||
@ -2035,22 +1874,18 @@
|
||||
03E239A22EAA1A29004A8CEC /* FATabBarController.swift in Sources */,
|
||||
03E239A32EAA1A29004A8CEC /* UIStackView+FAAdd.swift in Sources */,
|
||||
03E239A42EAA1A29004A8CEC /* UIScreen+FAAdd.swift in Sources */,
|
||||
039CE6182EAB0E7E007B5EED /* FAStoreAPI.swift in Sources */,
|
||||
03E239A52EAA1A29004A8CEC /* FACollectionView.swift in Sources */,
|
||||
03E239A62EAA1A29004A8CEC /* UIView+FAAdd.swift in Sources */,
|
||||
03E239A72EAA1A29004A8CEC /* FAScrollView.swift in Sources */,
|
||||
03E239A82EAA1A29004A8CEC /* FATableView.swift in Sources */,
|
||||
03E239A92EAA1A29004A8CEC /* CGMutablePath+FARoundedCorner.swift in Sources */,
|
||||
031FDEBC2EB0C97A00F4CAC7 /* FAOldVideoRechargeView.swift in Sources */,
|
||||
03E239AA2EAA1A29004A8CEC /* FAPanModalContentView.swift in Sources */,
|
||||
03E239AB2EAA1A29004A8CEC /* FATableViewCell.swift in Sources */,
|
||||
03E239AC2EAA1A29004A8CEC /* FABaseWebViewController+Script.swift in Sources */,
|
||||
03E239AD2EAA1A29004A8CEC /* FAAppWebViewController.swift in Sources */,
|
||||
03E239AE2EAA1A29004A8CEC /* SwiftUIExtension.swift in Sources */,
|
||||
039CE60E2EAA32A8007B5EED /* FAOpenAppModel.swift in Sources */,
|
||||
03E239AF2EAA1A29004A8CEC /* FAAPI.swift in Sources */,
|
||||
03E239B02EAA1A29004A8CEC /* FAWebView.swift in Sources */,
|
||||
039CE61C2EAB0F29007B5EED /* FAIapOrderModel.swift in Sources */,
|
||||
03E239B12EAA1A29004A8CEC /* FANetworkMonitor.swift in Sources */,
|
||||
03E239B22EAA1A29004A8CEC /* UINavigationBar+FAAdd.swift in Sources */,
|
||||
F3EKB04Y9O2888900KQEO504 /* NHCornerController.swift in Sources */,
|
||||
@ -2068,7 +1903,6 @@
|
||||
F32G5ID338260A2W78SS4618 /* TCFableonCell.swift in Sources */,
|
||||
F31E84U5Y6YW6430Z54X1K40 /* UCHVion.swift in Sources */,
|
||||
F3554P018N62D11QM20Y695Q /* BCMonitorEcommendController.swift in Sources */,
|
||||
039CE62E2EAB5B18007B5EED /* FAStoreCoinsSmallCell.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -2222,7 +2056,6 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Fableon/Fableon.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = 6XALB8RSYF;
|
||||
@ -2243,7 +2076,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.1;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.hn.qinjiu.fableon;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
@ -2263,7 +2096,6 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Fableon/Fableon.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = 6XALB8RSYF;
|
||||
@ -2283,7 +2115,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.1;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.hn.qinjiu.fableon;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
|
||||
@ -1,144 +0,0 @@
|
||||
//
|
||||
// AppDelegate+FAAdjust.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/23.
|
||||
//
|
||||
import UIKit
|
||||
import AdjustSdk
|
||||
import SmartCodable
|
||||
#if canImport(FacebookCore)
|
||||
import FacebookCore
|
||||
#endif
|
||||
|
||||
extension AppDelegate {
|
||||
|
||||
func registerAdjust() {
|
||||
#if DEBUG
|
||||
let config = ADJConfig(appToken: "zyp26mbr3yf4", environment: ADJEnvironmentSandbox)
|
||||
config?.logLevel = .verbose
|
||||
#else
|
||||
let config = ADJConfig(appToken: "zyp26mbr3yf4", environment: ADJEnvironmentProduction)
|
||||
#endif
|
||||
|
||||
config?.delegate = self
|
||||
Adjust.initSdk(config)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//MARK: AdjustDelegate
|
||||
extension AppDelegate: AdjustDelegate {
|
||||
func adjustDeferredDeeplinkReceived(_ deeplink: URL?) -> Bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension SceneDelegate {
|
||||
func handleOpenAppMessage(webpageURL: URL?) {
|
||||
let manager = FAAdjustStateManager.manager
|
||||
guard manager.allowOpenMessage else { return }
|
||||
|
||||
guard FANetworkMonitor.manager.isReachable == true,
|
||||
manager.isOpenApp,
|
||||
manager.idfaAuthorizationFinish //idfa授权完成
|
||||
else {
|
||||
if let webpageURL = webpageURL {
|
||||
manager.webpageURL = webpageURL
|
||||
}
|
||||
manager.isNeedRetry = true
|
||||
return
|
||||
}
|
||||
manager.isNeedRetry = false
|
||||
manager.webpageURL = nil
|
||||
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
self._handleOpenAppMessage(webpageURL: webpageURL)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func _handleOpenAppMessage(webpageURL: URL?) {
|
||||
|
||||
guard FAAdjustStateManager.manager.allowOpenMessage else { return }
|
||||
FAAdjustStateManager.manager.allowOpenMessage = false
|
||||
|
||||
//统计用URL
|
||||
var statUrlStr: String? = webpageURL?.absoluteString
|
||||
var data: [String : Any]? = webpageURL?.query?.urlQuryToDictionary()
|
||||
|
||||
if statUrlStr == nil, let pasteStr = UIPasteboard.general.string, pasteStr.contains("movia") {
|
||||
let tempArr = pasteStr.components(separatedBy: "?")
|
||||
let query = tempArr.last
|
||||
|
||||
let tempData = query?.urlQuryToDictionary()
|
||||
if tempData?["short_play_id"] != nil {
|
||||
data = tempData
|
||||
statUrlStr = pasteStr
|
||||
}
|
||||
}
|
||||
UIPasteboard.general.string = nil
|
||||
|
||||
if let urlStr = statUrlStr {//上报结果
|
||||
FAStatAPI.requestStatW2a(data: urlStr)
|
||||
}
|
||||
|
||||
|
||||
|
||||
guard let data = data else { return }
|
||||
guard let model = FAOpenAppModel.deserialize(from: data) else { return }
|
||||
guard let shortPlayId = model.short_play_id, shortPlayId.count > 0 else { return }
|
||||
|
||||
|
||||
let vc = FAPlayerDetailViewController()
|
||||
vc.shortPlayId = shortPlayId
|
||||
FATool.topViewController?.navigationController?.pushViewController(vc, animated: true)
|
||||
}
|
||||
|
||||
|
||||
///重试
|
||||
func retryHandleOpenAppMessage() {
|
||||
guard FAAdjustStateManager.manager.isNeedRetry else { return }
|
||||
handleOpenAppMessage(webpageURL: FAAdjustStateManager.manager.webpageURL)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension SceneDelegate {
|
||||
|
||||
///URL打开APP
|
||||
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
|
||||
guard let url = URLContexts.first?.url else {
|
||||
return
|
||||
}
|
||||
var result = false
|
||||
|
||||
#if canImport(FacebookCore)
|
||||
result = ApplicationDelegate.shared.application(UIApplication.shared, open: url, sourceApplication: nil, annotation: [UIApplication.OpenURLOptionsKey.annotation])
|
||||
#endif
|
||||
if !result {
|
||||
if let link = ADJDeeplink(deeplink: url) {
|
||||
Adjust.processDeeplink(link)
|
||||
}
|
||||
handleOpenAppMessage(webpageURL: url)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
///UniversalLink 打开app
|
||||
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
|
||||
guard let webpageURL = userActivity.webpageURL else { return }
|
||||
var result = false
|
||||
|
||||
#if canImport(FacebookCore)
|
||||
let result = ApplicationDelegate.shared.application(UIApplication.shared, continue: userActivity)
|
||||
#endif
|
||||
|
||||
if !result {
|
||||
handleOpenAppMessage(webpageURL: webpageURL)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -28,8 +28,6 @@ extension AppDelegate {
|
||||
let appearance = UINavigationBarAppearance.defaultAppearance()
|
||||
UINavigationBar.appearance().scrollEdgeAppearance = appearance
|
||||
UINavigationBar.appearance().standardAppearance = appearance
|
||||
|
||||
registerAdjust()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -19,7 +19,6 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
window = UIWindow(windowScene: windowScene)
|
||||
window?.rootViewController = FATabBarController()
|
||||
window?.makeKeyAndVisible()
|
||||
FAAdjustStateManager.manager.isOpenApp = true
|
||||
}
|
||||
|
||||
func sceneDidDisconnect(_ scene: UIScene) {
|
||||
@ -40,13 +39,14 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
}
|
||||
|
||||
func sceneWillEnterForeground(_ scene: UIScene) {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
self.handleOpenAppMessage(webpageURL: nil)
|
||||
}
|
||||
// Called as the scene transitions from the background to the foreground.
|
||||
// Use this method to undo the changes made on entering the background.
|
||||
}
|
||||
|
||||
func sceneDidEnterBackground(_ scene: UIScene) {
|
||||
FAAdjustStateManager.manager.allowOpenMessage = true
|
||||
// Called as the scene transitions from the foreground to the background.
|
||||
// Use this method to save data, release shared resources, and store enough scene-specific state information
|
||||
// to restore the scene back to its current state.
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
<?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>com.apple.developer.associated-domains</key>
|
||||
<array>
|
||||
<string>applinks:fableon.go.link</string>
|
||||
<string>applinks:kuzt.adj.st</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@ -39,14 +39,6 @@ class FATabBarController: UITabBarController {
|
||||
self.tabBar.standardAppearance = appearance
|
||||
self.tabBar.isTranslucent = false
|
||||
|
||||
///预加载支付数据
|
||||
FAIapManager.manager.preloadingProducts()
|
||||
|
||||
FAIapManager.manager.restore(isLoding: false) { isFinish, buyType in
|
||||
if isFinish {
|
||||
FALogin.manager.requestUserInfo(completer: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override var childForStatusBarStyle: UIViewController? {
|
||||
|
||||
@ -10,7 +10,7 @@ import UIKit
|
||||
|
||||
///当前系统版本号
|
||||
let kFAOsVersion: String = UIDevice.current.systemVersion
|
||||
let kFAAPPBundleIdentifier: String = (Bundle.main.infoDictionary!["CFBundleIdentifier"] as? String) ?? "0"
|
||||
let kBRAPPBundleIdentifier: String = (Bundle.main.infoDictionary!["CFBundleIdentifier"] as? String) ?? "0"
|
||||
|
||||
///app版本号
|
||||
let kFAAPPVersion: String = (Bundle.main.infoDictionary!["CFBundleShortVersionString"] as? String) ?? "0"
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
//
|
||||
// FAUserDefaultsKey.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/24.
|
||||
//
|
||||
|
||||
|
||||
let kFAWaitRestoreIAPDefaultsKey = "kFAWaitRestoreIAPDefaultsKey"
|
||||
@ -9,7 +9,6 @@ import Foundation
|
||||
import SmartCodable
|
||||
import YYCategories
|
||||
|
||||
|
||||
extension String: SmartCodable {
|
||||
|
||||
static func timeZone() -> String {
|
||||
@ -40,22 +39,3 @@ extension String {
|
||||
static let color_333333 = "#333333"
|
||||
static let color_D9D9D9 = "#D9D9D9"
|
||||
}
|
||||
|
||||
extension String {
|
||||
///将url中的参数转换成字典
|
||||
func urlQuryToDictionary() -> [String : Any] {
|
||||
let array = self.components(separatedBy: "&")
|
||||
var tempDic: [String : Any] = [:]
|
||||
|
||||
array.forEach {
|
||||
if let strRange = $0.range(of: "=") {
|
||||
var key: String = String($0.prefix(upTo: strRange.upperBound))
|
||||
key.removeLast()
|
||||
var value: String = String($0.suffix(from: strRange.upperBound))
|
||||
value = value.removingPercentEncoding ?? value
|
||||
tempDic[key] = value
|
||||
}
|
||||
}
|
||||
return tempDic
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
//
|
||||
// FAOpenAppModel.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/23.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SmartCodable
|
||||
|
||||
struct FAOpenAppModel: SmartCodable {
|
||||
|
||||
enum Path: String, SmartCaseDefaultable {
|
||||
case videoDetail = "detail"
|
||||
///反馈列表
|
||||
case feedback = "feedback"
|
||||
///活动
|
||||
case promotion = "promotion"
|
||||
}
|
||||
|
||||
var id: String?
|
||||
var message_id: String?
|
||||
var short_play_id: String?
|
||||
var path: Path?
|
||||
}
|
||||
@ -1,87 +0,0 @@
|
||||
//
|
||||
// FAStatAPI.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/23.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class FAStatAPI: NSObject {
|
||||
enum EventKey: String {
|
||||
case payError = "pay_error" //支付过程中的其它错误
|
||||
case payCallback = "pay_callback" //支付成功,但是后台接口失败
|
||||
case payRestore = "pay_restore" //restore 失败
|
||||
case forceUpdate = "force_update"//更新弹窗
|
||||
case payCancel = "pay_cancel" //用户取消支付
|
||||
case payTemplateDialog = "pay_template_dialog"//详情页面弹出支付模版事件
|
||||
}
|
||||
|
||||
///统计w2a点击
|
||||
static func requestStatW2a(data: String) {
|
||||
|
||||
let parameters = [
|
||||
"data" : data
|
||||
]
|
||||
|
||||
FANetworkManager.manager.request(FABaseURL + "/w2aSelfAttribution",
|
||||
method: .post,
|
||||
parameters: parameters,
|
||||
isLoding: false,
|
||||
isToast: false,
|
||||
) { (response: FANetworkManager.Response<String>) in
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
///事件统计
|
||||
static func requestEventStat(orderCode: String?, shortPlayId: String?, videoId: String?, eventKey: EventKey, errorMsg: String?, otherParamenters: [String : Any]? = nil) {
|
||||
|
||||
var eventName = ""
|
||||
switch eventKey {
|
||||
case .payRestore:
|
||||
eventName = "pay restore"
|
||||
|
||||
case .payCallback:
|
||||
eventName = "pay callback failed"
|
||||
|
||||
case .forceUpdate:
|
||||
eventName = "force update"
|
||||
|
||||
case .payCancel:
|
||||
eventName = "user pay canceled"
|
||||
|
||||
default:
|
||||
eventName = "platform pay failed"
|
||||
}
|
||||
|
||||
var parameters: [String : Any] = [
|
||||
"userId" : FALogin.manager.userInfo?.customer_id ?? "",
|
||||
"short_play_video_id" : videoId ?? "0",
|
||||
"short_play_id" : shortPlayId ?? "0",
|
||||
"event_key" : eventKey.rawValue,
|
||||
"order_code": orderCode ?? "",
|
||||
"event_name" : eventName,
|
||||
]
|
||||
|
||||
if let errorMsg = errorMsg {
|
||||
parameters["error_msg"] = errorMsg
|
||||
}
|
||||
|
||||
|
||||
if let otherParamenters = otherParamenters {
|
||||
otherParamenters.forEach {
|
||||
parameters[$0] = $1
|
||||
}
|
||||
}
|
||||
|
||||
FANetworkManager.manager.request(FABaseURL + "/event/add",
|
||||
method: .post,
|
||||
parameters: parameters,
|
||||
isLoding: false,
|
||||
isToast: false,
|
||||
) { (response: FANetworkManager.Response<String>) in
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,134 +0,0 @@
|
||||
//
|
||||
// FAStoreAPI.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/24.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SmartCodable
|
||||
|
||||
class FAStoreAPI: NSObject {
|
||||
enum BuyType: String, SmartCaseDefaultable {
|
||||
case coins = "coins"
|
||||
case subVip = "sub_vip"
|
||||
case subCoins = "sub_coins"
|
||||
case vip = "vip"
|
||||
}
|
||||
|
||||
|
||||
///创建内购订单
|
||||
static func requestCreateOrder(payId: String, shortPlayId: String, videoId: String, isDiscount: Bool = false, identifierDiscount: String? = nil, completer: ((_ orderModel: FAIapOrderModel?) -> Void)?) {
|
||||
|
||||
let parameters: [String : Any] = [
|
||||
"payment_channel" : "apple",
|
||||
"short_play_id" : shortPlayId,
|
||||
"video_id" : videoId,
|
||||
"pay_setting_id" : payId,
|
||||
"is_discount" : isDiscount ? 1 : 0,
|
||||
"product_discount" : identifierDiscount ?? "",
|
||||
]
|
||||
|
||||
FANetworkManager.manager.request(FABaseURL + "/createOrder",
|
||||
method: .post,
|
||||
parameters: parameters,
|
||||
isLoding: false,
|
||||
isToast: false,
|
||||
) { (response: FANetworkManager.Response<FAIapOrderModel>) in
|
||||
guard let data = response.data else {
|
||||
FAToast.show(text: "network_error_01".localized)
|
||||
completer?(nil)
|
||||
return
|
||||
}
|
||||
if let message = data.message, message.count > 0 {
|
||||
if response.data?.code == 30007 {
|
||||
FAToast.show(text: "pay_error_1".localized)
|
||||
} else {
|
||||
FAToast.show(text: message)
|
||||
}
|
||||
completer?(nil)
|
||||
} else {
|
||||
completer?(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///校验内购
|
||||
static func requestVerifyOrder(parameters: [String : Any], completer: ((_ response: FANetworkManager.Response<FAIapVerifyModel>) -> Void)?) {
|
||||
|
||||
FANetworkManager.manager.request(FABaseURL + "/applePaid",
|
||||
method: .post,
|
||||
parameters: parameters,
|
||||
isLoding: false,
|
||||
isToast: true,
|
||||
) { (response: FANetworkManager.Response<FAIapVerifyModel>) in
|
||||
completer?(response)
|
||||
}
|
||||
}
|
||||
|
||||
///获取支付模版
|
||||
static func requestPayTemplate(isLoding: Bool = false, isToast: Bool = true, completer: ((_ model: FAPayDateModel?) -> Void)?) {
|
||||
let parameters = [
|
||||
"discount" : "1",
|
||||
"purchases_token" : JXIAPManager.manager.getAppStoreReceipt() ?? "",
|
||||
]
|
||||
|
||||
FANetworkManager.manager.request(FABaseURL + "/paySettingsV4",
|
||||
method: .post,
|
||||
parameters: parameters,
|
||||
isLoding: isLoding,
|
||||
isToast: isToast,
|
||||
) { (response: FANetworkManager.Response<FAPayDateModel>) in
|
||||
completer?(response.data)
|
||||
}
|
||||
}
|
||||
|
||||
static func requestBuyRecords(page: Int, completer: ((_ listModel: FANetworkManager.List<FABuyRecordsModel>?) -> Void)?) {
|
||||
let parameters = [
|
||||
"page_size" : 20,
|
||||
"current_page" : page,
|
||||
]
|
||||
|
||||
FANetworkManager.manager.request(FABaseURL + "/getCustomerBuyRecords",
|
||||
method: .get,
|
||||
parameters: parameters,
|
||||
isLoding: false,
|
||||
isToast: true,
|
||||
) { (response: FANetworkManager.Response<FANetworkManager.List<FABuyRecordsModel>>) in
|
||||
completer?(response.data)
|
||||
}
|
||||
}
|
||||
|
||||
static func requestRechargeRecord(page: Int, buyType: BuyType, completer: ((_ listModel: FANetworkManager.List<FARechargeRecordModel>?) -> Void)?) {
|
||||
let parameters: [String : Any] = [
|
||||
"page_size" : 20,
|
||||
"current_page" : page,
|
||||
"buy_type" : buyType.rawValue
|
||||
]
|
||||
|
||||
FANetworkManager.manager.request(FABaseURL + "/getCustomerOrder",
|
||||
method: .get,
|
||||
parameters: parameters,
|
||||
isLoding: false,
|
||||
isToast: true,
|
||||
) { (response: FANetworkManager.Response<FANetworkManager.List<FARechargeRecordModel>>) in
|
||||
completer?(response.data)
|
||||
}
|
||||
}
|
||||
|
||||
static func reuqestSendCoinRecord(page: Int, completer: ((_ listModel: FANetworkManager.List<FASendCoinRecordModel>?) -> Void)?) {
|
||||
let parameters: [String : Any] = [
|
||||
"page_size" : 20,
|
||||
"current_page" : page,
|
||||
]
|
||||
|
||||
FANetworkManager.manager.request(FABaseURL + "/sendCoinList",
|
||||
method: .post,
|
||||
parameters: parameters,
|
||||
isLoding: false,
|
||||
isToast: true,
|
||||
) { (response: FANetworkManager.Response<FANetworkManager.List<FASendCoinRecordModel>>) in
|
||||
completer?(response.data)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,116 +0,0 @@
|
||||
//
|
||||
// FALabel.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/24.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class FALabel: UILabel {
|
||||
|
||||
var textColorImage: UIImage?
|
||||
var fa_textColor: UIColor?
|
||||
var textColors: [CGColor]?
|
||||
var textStartPoint: CGPoint?
|
||||
var textEndPoint: CGPoint?
|
||||
|
||||
var borderLineWidth: CGFloat = 0
|
||||
var borderImage: UIImage?
|
||||
var borderColor: UIColor?
|
||||
var borderColors: [CGColor]?
|
||||
var borderStartPoint: CGPoint?
|
||||
var borderEndPoint: CGPoint?
|
||||
|
||||
|
||||
|
||||
|
||||
override var intrinsicContentSize: CGSize {
|
||||
let size = super.intrinsicContentSize
|
||||
return .init(width: size.width + borderLineWidth / 2, height: size.height)
|
||||
}
|
||||
|
||||
override func drawText(in rect: CGRect) {
|
||||
guard let context = UIGraphicsGetCurrentContext(),
|
||||
let text = self.text else {
|
||||
super.drawText(in: rect)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// var attributes: [NSAttributedString.Key: Any] = [:]
|
||||
//
|
||||
// if let att = self.attributedText?.yy_attributes {
|
||||
// att.forEach {
|
||||
// let key = NSAttributedString.Key.init($0)
|
||||
// attributes[key] = $1
|
||||
// }
|
||||
//
|
||||
// } else if let font = self.font {
|
||||
// attributes = [
|
||||
// .font: font
|
||||
// ]
|
||||
// }
|
||||
|
||||
// let textSize = text.size(withAttributes: attributes)
|
||||
// let x = (rect.width - textSize.width) / 2
|
||||
// let y = (rect.height - textSize.height) / 2
|
||||
|
||||
let textSize = self.attributedText?.boundingRect(with: rect.size, options: [.usesLineFragmentOrigin, .usesFontLeading], context: nil).size ?? .zero
|
||||
let x = 0.0
|
||||
let y = 0.0
|
||||
let textRect = CGRect(x: x, y: y, width: textSize.width, height: textSize.height)
|
||||
|
||||
|
||||
context.setLineWidth(borderLineWidth)
|
||||
context.setLineJoin(.round)
|
||||
// 先描边
|
||||
context.setTextDrawingMode(.stroke)
|
||||
if let image = self.borderImage {
|
||||
self.textColor = UIColor(patternImage: image.sp_resized(to: rect.size))
|
||||
} else if let colors = self.borderColors, let startPoint = self.borderStartPoint, let endPoine = self.borderEndPoint {
|
||||
self.textColor = UIColor(patternImage: UIImage.fa_getGradientImage(size: size, colors: colors, startPoint: startPoint, endPoint: endPoine))
|
||||
} else {
|
||||
self.textColor = self.borderColor ?? .clear
|
||||
}
|
||||
super.drawText(in: textRect)
|
||||
|
||||
// 再填充
|
||||
context.setTextDrawingMode(.fill)
|
||||
if let image = self.textColorImage {
|
||||
self.textColor = UIColor(patternImage: image.sp_resized(to: rect.size))
|
||||
} else if let colors = self.textColors, let startPoint = self.textStartPoint, let endPoine = self.textEndPoint {
|
||||
self.textColor = UIColor(patternImage: UIImage.fa_getGradientImage(size: size, colors: colors, startPoint: startPoint, endPoint: endPoine))
|
||||
} else {
|
||||
self.textColor = fa_textColor // 填充色
|
||||
}
|
||||
super.drawText(in: textRect)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension UIImage {
|
||||
|
||||
static func fa_getGradientImage(size: CGSize, colors: [CGColor], startPoint: CGPoint, endPoint: CGPoint) -> UIImage{
|
||||
|
||||
UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale)
|
||||
guard let context = UIGraphicsGetCurrentContext() else{return UIImage()}
|
||||
let colorSpace = CGColorSpaceCreateDeviceRGB()
|
||||
///设置渐变颜色
|
||||
let gradientRef = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: nil)!
|
||||
let startPoint = CGPoint(x: size.width * startPoint.x, y: size.height * startPoint.y)
|
||||
let endPoint = CGPoint(x: size.width * endPoint.x, y: size.height * endPoint.y)
|
||||
context.drawLinearGradient(gradientRef, start: startPoint, end: endPoint, options: CGGradientDrawingOptions(arrayLiteral: .drawsBeforeStartLocation,.drawsAfterEndLocation))
|
||||
let gradientImage = UIGraphicsGetImageFromCurrentImageContext()
|
||||
UIGraphicsEndImageContext()
|
||||
return gradientImage ?? UIImage()
|
||||
}
|
||||
|
||||
func sp_resized(to size: CGSize) -> UIImage {
|
||||
let renderer = UIGraphicsImageRenderer(size: size)
|
||||
return renderer.image { _ in
|
||||
self.draw(in: CGRect(origin: .zero, size: size))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -14,7 +14,7 @@ class FAAppWebViewController: FABaseWebViewController {
|
||||
|
||||
private var receiveDataCount = 0
|
||||
|
||||
var theme: String? = "theme_1"
|
||||
var theme: String? = "theme_2"
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
@ -95,7 +95,7 @@ extension FAMeViewController: JXPagingViewDelegate {
|
||||
}
|
||||
|
||||
func tableHeaderViewHeight(in pagingView: JXPagingView) -> Int {
|
||||
return Int(ceil(headerView.contentHeight))
|
||||
return Int(ceill(headerView.contentHeight))
|
||||
}
|
||||
|
||||
func tableHeaderView(in pagingView: JXPagingView) -> UIView {
|
||||
|
||||
@ -1,36 +0,0 @@
|
||||
//
|
||||
// FANewVideoRechargeView.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/28.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class FANewVideoRechargeView: FAPanModalContentView {
|
||||
|
||||
var model: FAPayDateModel? {
|
||||
didSet {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
var videoInfo: FAVideoInfoModel? {
|
||||
didSet {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
}
|
||||
|
||||
@MainActor required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func allowsTapBackgroundToDismiss() -> Bool {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -1,290 +0,0 @@
|
||||
//
|
||||
// FAOldVideoRechargeView.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/28.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import HWPanModal
|
||||
|
||||
class FAOldVideoRechargeView: FAPanModalContentView {
|
||||
|
||||
var buyFinishHandle: (() -> Void)?
|
||||
|
||||
var model: FAPayDateModel? {
|
||||
didSet {
|
||||
self.stackView.fa_removeAllArrangedSubview()
|
||||
self.vipView.dataArr = model?.list_sub_vip ?? []
|
||||
self.coinsView.setDataArr(model?.list_coins ?? [])
|
||||
|
||||
if let sort = model?.sort, sort.count > 0 {
|
||||
sort.forEach {
|
||||
if $0 == .vip, model?.list_sub_vip?.isEmpty == false {
|
||||
self.stackView.addArrangedSubview(self.vipView)
|
||||
} else if $0 == .coin, model?.list_coins?.isEmpty == false {
|
||||
self.stackView.addArrangedSubview(self.coinsView)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if model?.list_sub_vip?.isEmpty == false {
|
||||
self.stackView.addArrangedSubview(self.vipView)
|
||||
}
|
||||
if model?.list_coins?.isEmpty == false {
|
||||
self.stackView.addArrangedSubview(self.coinsView)
|
||||
}
|
||||
}
|
||||
|
||||
// self.stackView.addArrangedSubview(self.tipView)
|
||||
|
||||
self.setNeedsLayoutUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
var videoInfo: FAVideoInfoModel? {
|
||||
didSet {
|
||||
self.coinsView.videoId = videoInfo?.short_play_video_id
|
||||
self.coinsView.shortPlayId = videoInfo?.short_play_id
|
||||
self.vipView.videoId = videoInfo?.short_play_video_id
|
||||
self.vipView.shortPlayId = videoInfo?.short_play_id
|
||||
videoCoinsView.coins = videoInfo?.coins ?? 0
|
||||
|
||||
self.requestRestore()
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var closeButton: UIButton = {
|
||||
let button = UIButton(type: .custom, primaryAction: UIAction(handler: { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
FAStatAPI.requestEventStat(orderCode: nil, shortPlayId: self.videoInfo?.short_play_id, videoId: self.videoInfo?.short_play_video_id, eventKey: .payTemplateDialog, errorMsg: nil, otherParamenters: [
|
||||
"event_name" : "pay cancel"
|
||||
])
|
||||
Task {
|
||||
await self.dismiss(animated: true)
|
||||
}
|
||||
}))
|
||||
button.setImage(UIImage(named: "close_icon_02"), for: .normal)
|
||||
return button
|
||||
}()
|
||||
|
||||
private lazy var scrollView: FAScrollView = {
|
||||
let scrollView = FAScrollView()
|
||||
scrollView.clipsToBounds = false
|
||||
return scrollView
|
||||
}()
|
||||
|
||||
private lazy var stackView: UIStackView = {
|
||||
let view = UIStackView()
|
||||
view.axis = .vertical
|
||||
view.spacing = 18
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var coinsView: FAStoreCoinsView = {
|
||||
let view = FAStoreCoinsView()
|
||||
view.buyFinishHandle = { [weak self] in
|
||||
self?.buyFinishHandle?()
|
||||
Task {
|
||||
await self?.dismiss(animated: true)
|
||||
}
|
||||
}
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var vipView: FAStoreVipView = {
|
||||
let view = FAStoreVipView()
|
||||
view.buyFinishHandle = { [weak self] in
|
||||
self?.buyFinishHandle?()
|
||||
Task {
|
||||
await self?.dismiss(animated: true)
|
||||
}
|
||||
}
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var videoCoinsView: FAOldVideoRechargeView.CoinsView = {
|
||||
let view = FAOldVideoRechargeView.CoinsView()
|
||||
view.title = "Price".localized + ":"
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var totalCoinsView: FAOldVideoRechargeView.CoinsView = {
|
||||
let view = FAOldVideoRechargeView.CoinsView()
|
||||
view.title = "Balance".localized + ":"
|
||||
view.coins = FALogin.manager.userInfo?.totalCoins ?? 0
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var titleLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 12, weight: .medium)
|
||||
label.textColor = .FFFFFF
|
||||
label.text = "store_title_1".localized
|
||||
return label
|
||||
}()
|
||||
|
||||
deinit {
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
}
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(userInfoUpdateNotification), name: FALogin.userInfoUpdateNotification, object: nil)
|
||||
self.contentHeight = UIScreen.height - UIScreen.safeTop
|
||||
// self.backgroundColor = ._000000.withAlphaComponent(0.6)
|
||||
self.backgroundColor = .clear
|
||||
self.mainScrollView = self.scrollView
|
||||
fa_setupLayout()
|
||||
}
|
||||
|
||||
@MainActor required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
@objc private func userInfoUpdateNotification() {
|
||||
totalCoinsView.coins = FALogin.manager.userInfo?.totalCoins ?? 0
|
||||
}
|
||||
|
||||
override func present(in view: UIView?) {
|
||||
super.present(in: view)
|
||||
self.hw_contentView.fa_addEffectView(style: .dark)
|
||||
self.hw_contentView.fa_setRoundedCorner(topLeft: 24, topRight: 24, bottomLeft: 0, bottomRight: 0)
|
||||
}
|
||||
|
||||
override func allowsTapBackgroundToDismiss() -> Bool {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
extension FAOldVideoRechargeView {
|
||||
|
||||
private func fa_setupLayout() {
|
||||
addSubview(closeButton)
|
||||
addSubview(videoCoinsView)
|
||||
addSubview(totalCoinsView)
|
||||
addSubview(titleLabel)
|
||||
addSubview(scrollView)
|
||||
scrollView.addSubview(stackView)
|
||||
|
||||
closeButton.snp.makeConstraints { make in
|
||||
make.right.equalToSuperview().offset(-16)
|
||||
make.top.equalToSuperview().offset(12)
|
||||
}
|
||||
|
||||
videoCoinsView.snp.makeConstraints { make in
|
||||
make.centerY.equalTo(closeButton)
|
||||
make.left.equalToSuperview().offset(16)
|
||||
}
|
||||
|
||||
totalCoinsView.snp.makeConstraints { make in
|
||||
make.centerY.equalTo(closeButton)
|
||||
make.left.equalTo(videoCoinsView.snp.right).offset(15)
|
||||
}
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(16)
|
||||
make.top.equalToSuperview().offset(39)
|
||||
}
|
||||
|
||||
scrollView.snp.makeConstraints { make in
|
||||
make.left.right.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(74)
|
||||
make.bottom.equalToSuperview()
|
||||
}
|
||||
|
||||
stackView.snp.makeConstraints { make in
|
||||
make.left.centerX.equalToSuperview()
|
||||
make.top.equalToSuperview()
|
||||
make.bottom.equalToSuperview().offset(-(UIScreen.safeBottom + 10))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FAOldVideoRechargeView {
|
||||
|
||||
@objc private func requestRestore() {
|
||||
guard let shortPlayId = self.videoInfo?.short_play_id, let videoId = self.videoInfo?.short_play_video_id else { return }
|
||||
|
||||
FAIapManager.manager.restore(isLoding: false, shortPlayId: shortPlayId, videoId: videoId) { [weak self] isFinish, buyType in
|
||||
if isFinish {
|
||||
FALogin.manager.requestUserInfo(completer: nil)
|
||||
self?.buyFinishHandle?()
|
||||
Task {
|
||||
await self?.dismiss(animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
extension FAOldVideoRechargeView {
|
||||
|
||||
class CoinsView: UIView {
|
||||
var title: String? {
|
||||
didSet {
|
||||
titleLabel.text = title
|
||||
}
|
||||
}
|
||||
|
||||
var coins: Int = 0 {
|
||||
didSet {
|
||||
coinsLabel.text = "\(coins)"
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var titleLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 14, weight: .regular)
|
||||
label.textColor = .FFFFFF
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var iconImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "coins_icon_08"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var coinsLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 14, weight: .bold)
|
||||
label.textColor = .F_9_F_494
|
||||
return label
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
addSubview(titleLabel)
|
||||
addSubview(iconImageView)
|
||||
addSubview(coinsLabel)
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.bottom.lessThanOrEqualToSuperview()
|
||||
make.left.equalToSuperview()
|
||||
}
|
||||
|
||||
iconImageView.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.bottom.lessThanOrEqualToSuperview()
|
||||
make.left.equalTo(titleLabel.snp.right).offset(6)
|
||||
}
|
||||
|
||||
coinsLabel.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.bottom.lessThanOrEqualToSuperview()
|
||||
make.left.equalTo(iconImageView.snp.right).offset(4)
|
||||
make.right.equalToSuperview()
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -87,19 +87,7 @@ class FAPlayerDetailViewController: JXPlayerListViewController {
|
||||
}
|
||||
self.pause()
|
||||
|
||||
let myCoins = FALogin.manager.userInfo?.totalCoins ?? 0
|
||||
let lockCoins = videoInfo?.coins ?? 0
|
||||
|
||||
if myCoins < lockCoins, (self.fa_viewModel.currentCell as? FAPlayerDetailCell)?.hasLastEpisodeUnlocked != true {
|
||||
self.fa_viewModel.openRechargeView()
|
||||
} else {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in
|
||||
guard let self = self else { return }
|
||||
if (self.fa_viewModel.currentCell as? FAPlayerDetailCell)?.hasLastEpisodeUnlocked != true {
|
||||
self.fa_viewModel.handleUnlockVideo()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -37,10 +37,8 @@ class FAShortDetailViewModel: JXPlayerListViewModel, ObservableObject {
|
||||
|
||||
weak var popView: UIView?
|
||||
|
||||
private var payDataRequest: FAPayDataRequest?
|
||||
|
||||
|
||||
func requestDetailData(indexPath: IndexPath? = nil, completer: ((_ code: Int) -> Void)?) {
|
||||
func requestDetailData(completer: ((_ code: Int) -> Void)?) {
|
||||
FAAPI.requestShortDetailData(shortPlayId: shortPlayId) { [weak self] model, code, msg in
|
||||
guard let self = self else { return }
|
||||
if let model = model {
|
||||
@ -50,9 +48,7 @@ class FAShortDetailViewModel: JXPlayerListViewModel, ObservableObject {
|
||||
guard let self = self else { return }
|
||||
var targetIndexPath = IndexPath(row: 0, section: 0)
|
||||
|
||||
if let indexPath = indexPath, indexPath.row < (model.episodeList?.count ?? 0) {
|
||||
targetIndexPath = indexPath
|
||||
} else if let videoInfo = model.video_info {
|
||||
if let videoInfo = model.video_info {
|
||||
var row: Int?
|
||||
model.episodeList?.enumerated().forEach {
|
||||
if $1.short_play_video_id == videoInfo.short_play_video_id {
|
||||
@ -129,59 +125,11 @@ extension FAShortDetailViewModel {
|
||||
guard let videoInfo = self.currentCell?.model as? FAVideoInfoModel else { return }
|
||||
guard self.popView == nil else { return }
|
||||
|
||||
self.payDataRequest = FAPayDataRequest()
|
||||
if let model = FAIapManager.manager.payDateModel {
|
||||
self._openRechargeView(model, videoInfo)
|
||||
self.payDataRequest?.requestProducts(isLoding: false) { [weak self] model in
|
||||
guard let self = self else { return }
|
||||
guard let model = model else { return }
|
||||
if let view = self.popView as? FAOldVideoRechargeView {
|
||||
view.model = model
|
||||
} else if let view = self.popView as? FANewVideoRechargeView {
|
||||
view.model = model
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.payDataRequest?.requestProducts(isLoding: true) { [weak self] model in
|
||||
guard let self = self else { return }
|
||||
guard let model = model else { return }
|
||||
self._openRechargeView(model, videoInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func _openRechargeView(_ model: FAPayDateModel, _ videoInfo: FAVideoInfoModel) {
|
||||
guard self.popView == nil else { return }
|
||||
FAStatAPI.requestEventStat(orderCode: nil, shortPlayId: videoInfo.short_play_id, videoId: videoInfo.short_play_video_id, eventKey: .payTemplateDialog, errorMsg: nil, otherParamenters: [
|
||||
"event_name" : "pay open"
|
||||
])
|
||||
|
||||
// if model.pay_mode == 1 {
|
||||
// _openNewRechargeView(model, videoInfo)
|
||||
// } else {
|
||||
_openOldRechargeView(model, videoInfo)
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
||||
private func _openOldRechargeView(_ model: FAPayDateModel, _ videoInfo: FAVideoInfoModel) {
|
||||
let view = FAOldVideoRechargeView()
|
||||
view.model = model
|
||||
view.videoInfo = videoInfo
|
||||
view.buyFinishHandle = { [weak self] in
|
||||
guard let self = self else { return }
|
||||
self.requestDetailData(indexPath: self.currentIndexPath, completer: nil)
|
||||
}
|
||||
view.present(in: nil)
|
||||
self.popView = view
|
||||
}
|
||||
|
||||
private func _openNewRechargeView(_ model: FAPayDateModel, _ videoInfo: FAVideoInfoModel) {
|
||||
let view = FANewVideoRechargeView()
|
||||
view.model = model
|
||||
view.videoInfo = videoInfo
|
||||
view.present(in: nil)
|
||||
self.popView = view
|
||||
}
|
||||
}
|
||||
|
||||
extension FAShortDetailViewModel {
|
||||
|
||||
@ -9,8 +9,6 @@ import UIKit
|
||||
|
||||
class FACoinRecordViewController: FAViewController {
|
||||
|
||||
private lazy var dataArr: [FARechargeRecordModel] = []
|
||||
private lazy var page = 1
|
||||
|
||||
private lazy var tableView: FATableView = {
|
||||
let tableView = FATableView(frame: .zero, style: .plain)
|
||||
@ -21,13 +19,6 @@ class FACoinRecordViewController: FAViewController {
|
||||
tableView.separatorInset = .init(top: 0, left: 16, bottom: 0, right: 16)
|
||||
tableView.contentInset = .init(top: 10, left: 0, bottom: UIScreen.safeBottom + 10, right: 0)
|
||||
tableView.register(UINib(nibName: "FAOrderRecordCell", bundle: nil), forCellReuseIdentifier: "cell")
|
||||
tableView.ly_emptyView = FAEmpty.fa_emptyView()
|
||||
tableView.fa_addRefreshHeader(insetTop: tableView.contentInset.top) { [weak self] in
|
||||
self?.handleHeaderRefresh(nil)
|
||||
}
|
||||
tableView.fa_addRefreshFooter(insetBottom: 0) { [weak self] in
|
||||
self?.handleFooterRefresh(nil)
|
||||
}
|
||||
return tableView
|
||||
}()
|
||||
|
||||
@ -41,21 +32,8 @@ class FACoinRecordViewController: FAViewController {
|
||||
make.left.right.bottom.equalToSuperview()
|
||||
make.top.equalToSuperview()
|
||||
}
|
||||
|
||||
requestDataArr(page: 1, completer: nil)
|
||||
}
|
||||
|
||||
override func handleHeaderRefresh(_ completer: (() -> Void)?) {
|
||||
requestDataArr(page: 1) { [weak self] in
|
||||
self?.tableView.fa_endHeaderRefreshing()
|
||||
}
|
||||
}
|
||||
|
||||
override func handleFooterRefresh(_ completer: (() -> Void)?) {
|
||||
requestDataArr(page: self.page + 1) { [weak self] in
|
||||
self?.tableView.fa_endFooterRefreshing()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -63,47 +41,12 @@ class FACoinRecordViewController: FAViewController {
|
||||
extension FACoinRecordViewController: UITableViewDelegate, UITableViewDataSource {
|
||||
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let model = self.dataArr[indexPath.row]
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FAOrderRecordCell
|
||||
if model.type == "send" {
|
||||
cell.titleLabel.text = "Bonus Coins".localized
|
||||
} else {
|
||||
cell.titleLabel.text = "Recharge Coins".localized
|
||||
}
|
||||
cell.dateLabel.text = model.created_at
|
||||
cell.countLabel.text = "+\(model.value ?? "0")"
|
||||
return cell
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return self.dataArr.count
|
||||
return 20
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FACoinRecordViewController {
|
||||
|
||||
private func requestDataArr(page: Int, completer: (() -> Void)?) {
|
||||
FAStoreAPI.requestRechargeRecord(page: page, buyType: .coins) { [weak self] listModel in
|
||||
guard let self = self else { return }
|
||||
guard let listModel = listModel, let list = listModel.list else {
|
||||
completer?()
|
||||
self.tableView.fa_updateNoMoreDataState(listModel?.hasNextPage)
|
||||
return
|
||||
}
|
||||
if page == 1 {
|
||||
self.dataArr.removeAll()
|
||||
}
|
||||
self.dataArr += list
|
||||
|
||||
self.page = page
|
||||
self.tableView.reloadData()
|
||||
|
||||
completer?()
|
||||
self.tableView.fa_updateNoMoreDataState(listModel.hasNextPage)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -9,8 +9,6 @@ import UIKit
|
||||
|
||||
class FAConsumptionRecordsViewController: FAViewController {
|
||||
|
||||
private lazy var dataArr: [FABuyRecordsModel] = []
|
||||
private lazy var page = 1
|
||||
|
||||
private lazy var tableView: FATableView = {
|
||||
let tableView = FATableView(frame: .zero, style: .plain)
|
||||
@ -21,13 +19,6 @@ class FAConsumptionRecordsViewController: FAViewController {
|
||||
tableView.separatorInset = .init(top: 0, left: 34, bottom: 0, right: 34)
|
||||
tableView.contentInset = .init(top: 10, left: 0, bottom: UIScreen.safeBottom + 10, right: 0)
|
||||
tableView.register(UINib(nibName: "FAConsumptionRecordsCell", bundle: nil), forCellReuseIdentifier: "cell")
|
||||
tableView.ly_emptyView = FAEmpty.fa_emptyView()
|
||||
tableView.fa_addRefreshHeader(insetTop: tableView.contentInset.top) { [weak self] in
|
||||
self?.handleHeaderRefresh(nil)
|
||||
}
|
||||
tableView.fa_addRefreshFooter(insetBottom: 0) { [weak self] in
|
||||
self?.handleFooterRefresh(nil)
|
||||
}
|
||||
return tableView
|
||||
}()
|
||||
|
||||
@ -36,8 +27,6 @@ class FAConsumptionRecordsViewController: FAViewController {
|
||||
self.title = "Consumption Records".localized
|
||||
|
||||
fa_setupLayout()
|
||||
|
||||
requestDataArr(page: 1, completer: nil)
|
||||
}
|
||||
|
||||
|
||||
@ -46,18 +35,6 @@ class FAConsumptionRecordsViewController: FAViewController {
|
||||
self.navigationController?.setNavigationBarHidden(false, animated: true)
|
||||
fa_setNavigationStyle()
|
||||
}
|
||||
|
||||
override func handleHeaderRefresh(_ completer: (() -> Void)?) {
|
||||
requestDataArr(page: 1) { [weak self] in
|
||||
self?.tableView.fa_endHeaderRefreshing()
|
||||
}
|
||||
}
|
||||
|
||||
override func handleFooterRefresh(_ completer: (() -> Void)?) {
|
||||
requestDataArr(page: self.page + 1) { [weak self] in
|
||||
self?.tableView.fa_endFooterRefreshing()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -80,37 +57,10 @@ extension FAConsumptionRecordsViewController: UITableViewDelegate, UITableViewDa
|
||||
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FAConsumptionRecordsCell
|
||||
cell.model = dataArr[indexPath.row]
|
||||
return cell
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return dataArr.count
|
||||
return 20
|
||||
}
|
||||
}
|
||||
|
||||
extension FAConsumptionRecordsViewController {
|
||||
|
||||
private func requestDataArr(page: Int, completer: (() -> Void)?) {
|
||||
FAStoreAPI.requestBuyRecords(page: page) { [weak self] listModel in
|
||||
guard let self = self else { return }
|
||||
guard let listModel = listModel, let list = listModel.list else {
|
||||
completer?()
|
||||
self.tableView.fa_updateNoMoreDataState(listModel?.hasNextPage)
|
||||
return
|
||||
}
|
||||
if page == 1 {
|
||||
self.dataArr.removeAll()
|
||||
}
|
||||
self.dataArr += list
|
||||
|
||||
self.page = page
|
||||
self.tableView.reloadData()
|
||||
|
||||
completer?()
|
||||
self.tableView.fa_updateNoMoreDataState(listModel.hasNextPage)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -9,9 +9,6 @@ import UIKit
|
||||
|
||||
class FARewardCoinsViewController: FAViewController {
|
||||
|
||||
private lazy var dataArr: [FASendCoinRecordModel] = []
|
||||
private lazy var page = 1
|
||||
|
||||
private lazy var tableView: FATableView = {
|
||||
let tableView = FATableView(frame: .zero, style: .plain)
|
||||
tableView.delegate = self
|
||||
@ -21,13 +18,6 @@ class FARewardCoinsViewController: FAViewController {
|
||||
tableView.separatorInset = .init(top: 0, left: 16, bottom: 0, right: 16)
|
||||
tableView.contentInset = .init(top: 10, left: 0, bottom: UIScreen.safeBottom + 10, right: 0)
|
||||
tableView.register(UINib(nibName: "FARewardCoinsCell", bundle: nil), forCellReuseIdentifier: "cell")
|
||||
tableView.ly_emptyView = FAEmpty.fa_emptyView()
|
||||
tableView.fa_addRefreshHeader(insetTop: tableView.contentInset.top) { [weak self] in
|
||||
self?.handleHeaderRefresh(nil)
|
||||
}
|
||||
tableView.fa_addRefreshFooter(insetBottom: 0) { [weak self] in
|
||||
self?.handleFooterRefresh(nil)
|
||||
}
|
||||
return tableView
|
||||
}()
|
||||
|
||||
@ -41,8 +31,6 @@ class FARewardCoinsViewController: FAViewController {
|
||||
make.left.right.bottom.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(UIScreen.navBarHeight + 10)
|
||||
}
|
||||
|
||||
requestDataArr(page: 1, completer: nil)
|
||||
}
|
||||
|
||||
|
||||
@ -51,18 +39,6 @@ class FARewardCoinsViewController: FAViewController {
|
||||
self.navigationController?.setNavigationBarHidden(false, animated: true)
|
||||
fa_setNavigationStyle()
|
||||
}
|
||||
|
||||
override func handleHeaderRefresh(_ completer: (() -> Void)?) {
|
||||
requestDataArr(page: 1) { [weak self] in
|
||||
self?.tableView.fa_endHeaderRefreshing()
|
||||
}
|
||||
}
|
||||
|
||||
override func handleFooterRefresh(_ completer: (() -> Void)?) {
|
||||
requestDataArr(page: self.page + 1) { [weak self] in
|
||||
self?.tableView.fa_endFooterRefreshing()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -70,37 +46,10 @@ class FARewardCoinsViewController: FAViewController {
|
||||
extension FARewardCoinsViewController: UITableViewDelegate, UITableViewDataSource {
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FARewardCoinsCell
|
||||
cell.model = self.dataArr[indexPath.row]
|
||||
return cell
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return self.dataArr.count
|
||||
return 20
|
||||
}
|
||||
}
|
||||
|
||||
extension FARewardCoinsViewController {
|
||||
|
||||
private func requestDataArr(page: Int, completer: (() -> Void)?) {
|
||||
FAStoreAPI.reuqestSendCoinRecord(page: page) { [weak self] listModel in
|
||||
guard let self = self else { return }
|
||||
guard let listModel = listModel, let list = listModel.list else {
|
||||
completer?()
|
||||
self.tableView.fa_updateNoMoreDataState(listModel?.hasNextPage)
|
||||
return
|
||||
}
|
||||
if page == 1 {
|
||||
self.dataArr.removeAll()
|
||||
}
|
||||
self.dataArr += list
|
||||
|
||||
self.page = page
|
||||
self.tableView.reloadData()
|
||||
|
||||
completer?()
|
||||
self.tableView.fa_updateNoMoreDataState(listModel.hasNextPage)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -9,11 +9,6 @@ import UIKit
|
||||
|
||||
class FAStoreViewController: FAViewController {
|
||||
|
||||
private var payRequest: FAPayDataRequest?
|
||||
|
||||
///支付数据
|
||||
private var payDataModel = FAIapManager.manager.payDateModel
|
||||
|
||||
private lazy var scrollView: FAScrollView = {
|
||||
let scrollView = FAScrollView()
|
||||
return scrollView
|
||||
@ -27,84 +22,11 @@ class FAStoreViewController: FAViewController {
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var stackView: UIStackView = {
|
||||
let view = UIStackView()
|
||||
view.axis = .vertical
|
||||
view.spacing = 18
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var coinsView: FAStoreCoinsView = {
|
||||
let view = FAStoreCoinsView()
|
||||
view.buyFinishHandle = { [weak self] in
|
||||
self?.buyFinish()
|
||||
}
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var vipView: FAStoreVipView = {
|
||||
let view = FAStoreVipView()
|
||||
view.buyFinishHandle = { [weak self] in
|
||||
self?.buyFinish()
|
||||
}
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var tipView: UIView = {
|
||||
let view = UIView()
|
||||
view.addSubview(tipTitleLabel)
|
||||
view.addSubview(tipTextLabel)
|
||||
|
||||
tipTitleLabel.snp.makeConstraints { make in
|
||||
make.top.equalToSuperview().offset(7)
|
||||
make.left.equalToSuperview().offset(16)
|
||||
}
|
||||
|
||||
tipTextLabel.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(16)
|
||||
make.right.lessThanOrEqualToSuperview().offset(-16)
|
||||
make.top.equalTo(tipTitleLabel.snp.bottom).offset(4)
|
||||
make.bottom.equalToSuperview()
|
||||
}
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var tipTitleLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 12, weight: .medium)
|
||||
label.textColor = .FFFFFF
|
||||
label.text = "store_tips_title".localized
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var tipTextLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 10, weight: .regular)
|
||||
label.textColor = .FFFFFF
|
||||
label.text = "store_tips".localized
|
||||
label.numberOfLines = 0
|
||||
return label
|
||||
}()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.title = "Store".localized
|
||||
let barButtonItem = UIBarButtonItem(title: "Restore".localized, style: .plain, target: self, action: #selector(handleRestore))
|
||||
barButtonItem.tintColor = .FFFFFF
|
||||
self.navigationItem.rightBarButtonItem = barButtonItem
|
||||
|
||||
fa_setupLayout()
|
||||
|
||||
updateLayout()
|
||||
|
||||
requestPayData()
|
||||
|
||||
FAIapManager.manager.restore(isLoding: false) { [weak self] isFinish, buyType in
|
||||
if isFinish {
|
||||
FALogin.manager.requestUserInfo(completer: nil)
|
||||
self?.buyFinish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
@ -113,74 +35,7 @@ class FAStoreViewController: FAViewController {
|
||||
fa_setNavigationStyle()
|
||||
}
|
||||
|
||||
private func buyFinish() {
|
||||
self.requestPayData()
|
||||
}
|
||||
|
||||
@objc private func handleRestore() {
|
||||
FAIapManager.manager.restore { [weak self] isFinish, buyType in
|
||||
if isFinish {
|
||||
FALogin.manager.requestUserInfo(completer: nil)
|
||||
self?.buyFinish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updateLayout() {
|
||||
self.stackView.fa_removeAllArrangedSubview()
|
||||
guard let model = self.payDataModel else { return }
|
||||
|
||||
if model.pay_mode == 1 {
|
||||
self.addCoinsView()
|
||||
} else {
|
||||
if let sort = model.sort, sort.count > 0 {
|
||||
sort.forEach {
|
||||
if $0 == .vip {
|
||||
self.addVipView()
|
||||
} else if $0 == .coin {
|
||||
self.addCoinsView()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.addVipView()
|
||||
self.addCoinsView()
|
||||
}
|
||||
}
|
||||
self.stackView.addArrangedSubview(tipView)
|
||||
}
|
||||
|
||||
private func addCoinsView() {
|
||||
guard let model = self.payDataModel else { return }
|
||||
|
||||
var newList: [FAPayItem] = []
|
||||
|
||||
if model.show_type == 1, model.pay_mode == 1 {
|
||||
if let list = model.list_coins, list.count > 0 {
|
||||
list.forEach {
|
||||
if $0.buy_type == .subCoins {
|
||||
newList.append($0)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if let list = model.list_coins, list.count > 0 {
|
||||
newList = list
|
||||
}
|
||||
}
|
||||
if newList.count > 0 {
|
||||
coinsView.setDataArr(newList)
|
||||
self.stackView.addArrangedSubview(coinsView)
|
||||
}
|
||||
}
|
||||
|
||||
private func addVipView() {
|
||||
guard let list = payDataModel?.list_sub_vip else { return }
|
||||
guard list.count > 0 else { return }
|
||||
|
||||
self.vipView.dataArr = list
|
||||
self.stackView.addArrangedSubview(self.vipView)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
extension FAStoreViewController {
|
||||
@ -188,7 +43,6 @@ extension FAStoreViewController {
|
||||
private func fa_setupLayout() {
|
||||
view.addSubview(scrollView)
|
||||
scrollView.addSubview(titleLabel)
|
||||
scrollView.addSubview(stackView)
|
||||
|
||||
scrollView.snp.makeConstraints { make in
|
||||
make.left.right.bottom.equalToSuperview()
|
||||
@ -199,29 +53,6 @@ extension FAStoreViewController {
|
||||
make.top.equalToSuperview().offset(0)
|
||||
make.centerX.equalToSuperview()
|
||||
}
|
||||
|
||||
stackView.snp.makeConstraints { make in
|
||||
make.left.centerX.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(29)
|
||||
make.bottom.equalToSuperview().offset(-(UIScreen.safeBottom + 10))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FAStoreViewController {
|
||||
|
||||
private func requestPayData() {
|
||||
payRequest = FAPayDataRequest()
|
||||
|
||||
payRequest?.requestProducts { [weak self] model in
|
||||
guard let self = self else { return }
|
||||
guard let model = model else { return }
|
||||
self.payDataModel = model
|
||||
|
||||
self.updateLayout()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -9,9 +9,6 @@ import UIKit
|
||||
|
||||
class FAVipRecordViewController: FAViewController {
|
||||
|
||||
private lazy var dataArr: [FARechargeRecordModel] = []
|
||||
private lazy var page = 1
|
||||
|
||||
private lazy var tableView: FATableView = {
|
||||
let tableView = FATableView(frame: .zero, style: .plain)
|
||||
tableView.delegate = self
|
||||
@ -21,13 +18,6 @@ class FAVipRecordViewController: FAViewController {
|
||||
tableView.separatorInset = .init(top: 0, left: 16, bottom: 0, right: 16)
|
||||
tableView.contentInset = .init(top: 10, left: 0, bottom: UIScreen.safeBottom + 10, right: 0)
|
||||
tableView.register(UINib(nibName: "FAOrderRecordCell", bundle: nil), forCellReuseIdentifier: "cell")
|
||||
tableView.ly_emptyView = FAEmpty.fa_emptyView()
|
||||
tableView.fa_addRefreshHeader(insetTop: tableView.contentInset.top) { [weak self] in
|
||||
self?.handleHeaderRefresh(nil)
|
||||
}
|
||||
tableView.fa_addRefreshFooter(insetBottom: 0) { [weak self] in
|
||||
self?.handleFooterRefresh(nil)
|
||||
}
|
||||
return tableView
|
||||
}()
|
||||
|
||||
@ -41,21 +31,9 @@ class FAVipRecordViewController: FAViewController {
|
||||
make.left.right.bottom.equalToSuperview()
|
||||
make.top.equalToSuperview()
|
||||
}
|
||||
|
||||
requestDataArr(page: 1, completer: nil)
|
||||
}
|
||||
|
||||
override func handleHeaderRefresh(_ completer: (() -> Void)?) {
|
||||
requestDataArr(page: 1) { [weak self] in
|
||||
self?.tableView.fa_endHeaderRefreshing()
|
||||
}
|
||||
}
|
||||
|
||||
override func handleFooterRefresh(_ completer: (() -> Void)?) {
|
||||
requestDataArr(page: self.page + 1) { [weak self] in
|
||||
self?.tableView.fa_endFooterRefreshing()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -63,43 +41,13 @@ class FAVipRecordViewController: FAViewController {
|
||||
extension FAVipRecordViewController: UITableViewDelegate, UITableViewDataSource {
|
||||
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let model = self.dataArr[indexPath.row]
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FAOrderRecordCell
|
||||
cell.iconImageView.isHidden = true
|
||||
cell.titleLabel.text = model.type
|
||||
cell.dateLabel.text = model.created_at
|
||||
cell.countLabel.text = "+\(model.value ?? "")"
|
||||
return cell
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return self.dataArr.count
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FAVipRecordViewController {
|
||||
|
||||
private func requestDataArr(page: Int, completer: (() -> Void)?) {
|
||||
FAStoreAPI.requestRechargeRecord(page: page, buyType: .vip) { [weak self] listModel in
|
||||
guard let self = self else { return }
|
||||
guard let listModel = listModel, let list = listModel.list else {
|
||||
completer?()
|
||||
self.tableView.fa_updateNoMoreDataState(listModel?.hasNextPage)
|
||||
return
|
||||
}
|
||||
if page == 1 {
|
||||
self.dataArr.removeAll()
|
||||
}
|
||||
self.dataArr += list
|
||||
|
||||
self.page = page
|
||||
self.tableView.reloadData()
|
||||
|
||||
completer?()
|
||||
self.tableView.fa_updateNoMoreDataState(listModel.hasNextPage)
|
||||
}
|
||||
|
||||
return 20
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
//
|
||||
// FABuyRecordsModel.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/28.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SmartCodable
|
||||
|
||||
struct FABuyRecordsModel: SmartCodable {
|
||||
|
||||
var created_at: String?
|
||||
var short_play_id: String?
|
||||
var coins: Int?
|
||||
var short_play_video_id: String?
|
||||
var coin_type: Int?
|
||||
var image_url: String?
|
||||
var name: String?
|
||||
var episode: String?
|
||||
}
|
||||
@ -1,24 +0,0 @@
|
||||
//
|
||||
// FAPayAlertModel.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/24.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SmartCodable
|
||||
|
||||
class FAPayAlertModel: NSObject, SmartCodable {
|
||||
|
||||
required override init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
var coins_modal_easy_close: Bool?
|
||||
|
||||
var info: FAPayItem?
|
||||
|
||||
var forced_recharge: Bool?
|
||||
|
||||
var close_label: String?
|
||||
}
|
||||
@ -1,167 +0,0 @@
|
||||
//
|
||||
// FAPayDateModel.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/24.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SmartCodable
|
||||
import StoreKit
|
||||
|
||||
class FAPayDateModel: NSObject, SmartCodable {
|
||||
|
||||
|
||||
required override init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
enum SortName: String, SmartCaseDefaultable {
|
||||
case coin = "list_coins"
|
||||
case vip = "list_sub_vip"
|
||||
}
|
||||
|
||||
var list_coins: [FAPayItem]?
|
||||
var list_sub_vip: [FAPayItem]?
|
||||
var list_sub_coins: [FAPayItem]?
|
||||
var sort: [SortName]?
|
||||
|
||||
///0: 老版支付 1:新版支付
|
||||
var pay_mode: Int?
|
||||
///0: 普通金币 1:金币包模式
|
||||
var show_type: Int?
|
||||
|
||||
}
|
||||
|
||||
|
||||
class FAPayItem: NSObject, SmartCodable {
|
||||
|
||||
required override init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
|
||||
enum VipTypeKey: String, SmartCaseDefaultable {
|
||||
case week = "week"
|
||||
case month = "month"
|
||||
case quarter = "quarter"
|
||||
case year = "year"
|
||||
}
|
||||
|
||||
enum SizeType: String, SmartCaseDefaultable {
|
||||
case big = "big"
|
||||
case small = "small"
|
||||
}
|
||||
|
||||
|
||||
var id: String?
|
||||
var backhaul_price: String?
|
||||
var coins: Int?
|
||||
var status: String?
|
||||
var price: String?
|
||||
var send_coins: Int?
|
||||
var buy_type: FAStoreAPI.BuyType?
|
||||
var origin_price: String?
|
||||
|
||||
var vip_type: String?
|
||||
var vip_type_key: VipTypeKey?
|
||||
var sort: String?
|
||||
var fa_description: String?
|
||||
var brief: String?
|
||||
var title: String?
|
||||
var auto_sub: String?
|
||||
|
||||
|
||||
var send_coin_ttl: Int?
|
||||
|
||||
var size: SizeType?
|
||||
|
||||
|
||||
|
||||
var ios_template_id: String?
|
||||
///角标
|
||||
var corner_marker: String?
|
||||
///平台
|
||||
var platform: String?
|
||||
///货币符号
|
||||
var currency: String?
|
||||
|
||||
var ext_info: FAPayExtInfo?
|
||||
|
||||
///0 无优惠 1 首次购买优惠 2 二次购买优惠
|
||||
var discount_type: Int?
|
||||
|
||||
@SmartIgnored
|
||||
var product: SKProduct?
|
||||
|
||||
///首冲优惠数据
|
||||
var introductionaryOffer: SKProductDiscount? {
|
||||
return product?.introductoryPrice
|
||||
}
|
||||
|
||||
///促销优惠数据
|
||||
var promotionalOffers: [SKProductDiscount]? {
|
||||
return product?.discounts
|
||||
}
|
||||
|
||||
|
||||
static func mappingForKey() -> [SmartKeyTransformer]? {
|
||||
return [
|
||||
CodingKeys.fa_description <--- ["description"]
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
|
||||
func getTimeString() -> String? {
|
||||
switch self.vip_type_key {
|
||||
case .week:
|
||||
return "week".localized
|
||||
|
||||
case .month:
|
||||
return "month".localized
|
||||
|
||||
case .quarter:
|
||||
return "quarter".localized
|
||||
|
||||
case .year:
|
||||
return "year".localized
|
||||
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func getVipTitle() -> String? {
|
||||
switch self.vip_type_key {
|
||||
case .week:
|
||||
return "Weekly VIP".localized
|
||||
|
||||
case .month:
|
||||
return "Monthly VIP".localized
|
||||
|
||||
case .quarter:
|
||||
return "Quarterly VIP".localized
|
||||
|
||||
case .year:
|
||||
return "Yearly VIP".localized
|
||||
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class FAPayExtInfo: NSObject, SmartCodable {
|
||||
|
||||
required override init() {
|
||||
super.init()
|
||||
}
|
||||
|
||||
var extra_day_coins: Int?
|
||||
var receive_coins_rate: String?
|
||||
var max_total_coins: Int?
|
||||
var sub_coins_txt_list: [String]?
|
||||
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
//
|
||||
// FARechargeRecordModel.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/28.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SmartCodable
|
||||
|
||||
struct FARechargeRecordModel: SmartCodable {
|
||||
|
||||
var type: String?
|
||||
var value: String?
|
||||
var created_at: String?
|
||||
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
//
|
||||
// FASendCoinRecordModel.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/28.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SmartCodable
|
||||
|
||||
struct FASendCoinRecordModel: SmartCodable {
|
||||
|
||||
var id: String?
|
||||
var left_coins: String?
|
||||
var created_at: String?
|
||||
var type: String?
|
||||
var diff_datetime: String?
|
||||
var expired_time: TimeInterval?
|
||||
var coins: Int?
|
||||
var is_effective: Int?
|
||||
}
|
||||
@ -1,74 +0,0 @@
|
||||
//
|
||||
// FACoinPackConfirmItem1View.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/28.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class FACoinPackConfirmItem1View: FACoinPackConfirmItemView {
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
titleLabel.text = "Bonus You Get".localized
|
||||
|
||||
let view1 = getItemView(image: UIImage(named: "Group 2072750450"), text: "Weekly Refill Package".localized)
|
||||
let view2 = getItemView(image: UIImage(named: "Group 2072750451"), text: "Dailu Bonuses".localized)
|
||||
|
||||
addSubview(view1)
|
||||
addSubview(view2)
|
||||
|
||||
view1.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(12)
|
||||
make.top.equalTo(titleLabel.snp.bottom).offset(8)
|
||||
make.height.equalTo(83)
|
||||
make.bottom.equalToSuperview().offset(-16)
|
||||
}
|
||||
|
||||
view2.snp.makeConstraints { make in
|
||||
make.left.equalTo(view1.snp.right).offset(12)
|
||||
make.right.equalToSuperview().offset(-12)
|
||||
make.width.height.top.equalTo(view1)
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
private func getItemView(image: UIImage?, text: String) -> UIView {
|
||||
let view = UIView()
|
||||
view.backgroundColor = ._40395_D.withAlphaComponent(0.75)
|
||||
view.layer.cornerRadius = 8
|
||||
view.layer.masksToBounds = true
|
||||
|
||||
let imageView = UIImageView(image: image)
|
||||
imageView.setContentHuggingPriority(.required, for: .horizontal)
|
||||
imageView.setContentCompressionResistancePriority(.required, for: .horizontal)
|
||||
|
||||
let label = UILabel()
|
||||
label.numberOfLines = 0
|
||||
label.font = .font(ofSize: 12, weight: .init(800))
|
||||
label.textColor = .FFFFFF
|
||||
label.text = text
|
||||
|
||||
|
||||
view.addSubview(imageView)
|
||||
view.addSubview(label)
|
||||
|
||||
imageView.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.left.equalToSuperview().offset(8)
|
||||
}
|
||||
|
||||
label.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.left.equalTo(imageView.snp.right).offset(8)
|
||||
make.right.lessThanOrEqualToSuperview().offset(-8)
|
||||
}
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,123 +0,0 @@
|
||||
//
|
||||
// FACoinPackConfirmItem2View.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/28.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class FACoinPackConfirmItem2View: FACoinPackConfirmItemView {
|
||||
|
||||
var list: [String]? {
|
||||
didSet {
|
||||
|
||||
self.stackView.fa_removeAllArrangedSubview()
|
||||
|
||||
list?.forEach {
|
||||
let view = FACoinPackConfirmItem2View.ItemView()
|
||||
view.text = $0
|
||||
self.stackView.addArrangedSubview(view)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var lineView: UIView = {
|
||||
let view = UIView()
|
||||
view.backgroundColor = .FFFFFF.withAlphaComponent(0.1)
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var stackView: UIStackView = {
|
||||
let view = UIStackView()
|
||||
view.axis = .vertical
|
||||
view.spacing = 24
|
||||
return view
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
self.titleLabel.text = "How Do I Receive Coins?"
|
||||
|
||||
fa_setupLayout()
|
||||
}
|
||||
|
||||
@MainActor required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FACoinPackConfirmItem2View {
|
||||
|
||||
private func fa_setupLayout() {
|
||||
addSubview(lineView)
|
||||
addSubview(stackView)
|
||||
|
||||
lineView.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(12)
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalTo(titleLabel.snp.bottom).offset(16)
|
||||
make.height.equalTo(1)
|
||||
}
|
||||
|
||||
stackView.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(16)
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalTo(lineView.snp.bottom).offset(16)
|
||||
make.bottom.equalToSuperview().offset(-16)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FACoinPackConfirmItem2View {
|
||||
|
||||
class ItemView: UIView {
|
||||
var text: String? {
|
||||
didSet {
|
||||
textLabel.text = text
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var iconImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "coins_icon_06"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var textLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 14, weight: .regular)
|
||||
label.textColor = .FFFFFF
|
||||
label.numberOfLines = 0
|
||||
return label
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
addSubview(iconImageView)
|
||||
addSubview(textLabel)
|
||||
|
||||
iconImageView.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview()
|
||||
make.top.equalToSuperview()
|
||||
}
|
||||
|
||||
textLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(iconImageView.snp.right).offset(12)
|
||||
make.right.lessThanOrEqualToSuperview()
|
||||
make.top.equalToSuperview()
|
||||
make.bottom.equalToSuperview()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
//
|
||||
// FACoinPackConfirmItemView.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/28.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class FACoinPackConfirmItemView: UIView {
|
||||
|
||||
lazy var titleLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 18, weight: .bold)
|
||||
label.textColor = ._20_A_1_FF
|
||||
label.textAlignment = .center
|
||||
return label
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
backgroundColor = ._29223_C
|
||||
layer.cornerRadius = 8
|
||||
layer.masksToBounds = true
|
||||
|
||||
addSubview(titleLabel)
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.right.lessThanOrEqualToSuperview().offset(-16)
|
||||
make.top.equalToSuperview().offset(16)
|
||||
}
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,209 +0,0 @@
|
||||
//
|
||||
// FACoinPackConfirmView.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/28.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import HWPanModal
|
||||
|
||||
class FACoinPackConfirmView: FAPanModalContentView {
|
||||
|
||||
var buyFinishHandle: (() -> Void)?
|
||||
|
||||
var shortPlayId: String?
|
||||
var videoId: String?
|
||||
|
||||
var model: FAPayItem? {
|
||||
didSet {
|
||||
item2View.list = model?.ext_info?.sub_coins_txt_list
|
||||
|
||||
var price = model?.price ?? ""
|
||||
if model?.discount_type == 1, let introductoryPrice = model?.introductionaryOffer {
|
||||
price = introductoryPrice.price.stringValue
|
||||
} else if model?.discount_type == 2, let discount = model?.promotionalOffers?.first {
|
||||
price = discount.price.stringValue
|
||||
}
|
||||
|
||||
priceLabel.text = "\(model?.currency ?? "")\(price)/\(model?.getTimeString() ?? "")"
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var bgImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "弹窗背景色"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var bgIconImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "Ellipse 873"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var titleLabel: FALabel = {
|
||||
let label = FALabel()
|
||||
label.font = .font(ofSize: 24, weight: .init(700))
|
||||
label.textColors = [UIColor._53_A_2_F_1.cgColor, UIColor.C_5_DDF_5.cgColor]
|
||||
label.textStartPoint = .init(x: 0, y: 0.5)
|
||||
label.textEndPoint = .init(x: 1, y: 0.5)
|
||||
label.text = "What You Get".localized
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var closeButton: UIButton = {
|
||||
let button = UIButton(type: .custom, primaryAction: UIAction(handler: { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
Task {
|
||||
await self.dismiss(animated: true)
|
||||
}
|
||||
}))
|
||||
button.setImage(UIImage(named: "close_icon_01"), for: .normal)
|
||||
return button
|
||||
}()
|
||||
|
||||
private lazy var scrollView: FAScrollView = {
|
||||
let scrollView = FAScrollView()
|
||||
scrollView.addObserver(self, forKeyPath: "contentSize", context: nil)
|
||||
return scrollView
|
||||
}()
|
||||
|
||||
private lazy var item1View: FACoinPackConfirmItem1View = {
|
||||
let view = FACoinPackConfirmItem1View()
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var item2View: FACoinPackConfirmItem2View = {
|
||||
let view = FACoinPackConfirmItem2View()
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var priceLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 18, weight: .bold)
|
||||
label.textColor = ._20_A_1_FF
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var continueButton: UIButton = {
|
||||
let button = FAGradientButton(type: .custom, primaryAction: UIAction(handler: { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
guard let model = self.model else { return }
|
||||
FAIapManager.manager.start(model: model, shortPlayId: self.shortPlayId, videoId: self.videoId) { [weak self] finish in
|
||||
guard let self = self else { return }
|
||||
if finish {
|
||||
self.buyFinishHandle?()
|
||||
Task {
|
||||
await self.dismiss(animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}))
|
||||
button.layer.cornerRadius = 24
|
||||
button.layer.masksToBounds = true
|
||||
button.fa_colors = [UIColor._53_A_2_F_1.cgColor, UIColor.C_5_DDF_5.cgColor]
|
||||
button.fa_locations = [0, 1]
|
||||
button.fa_startPoint = .init(x: 0, y: 0.5)
|
||||
button.fa_endPoint = .init(x: 1, y: 0.5)
|
||||
button.setTitle("Continue".localized, for: .normal)
|
||||
button.setTitleColor(.FFFFFF, for: .normal)
|
||||
button.titleLabel?.font = .font(ofSize: 14, weight: .bold)
|
||||
return button
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
self.backgroundColor = .clear
|
||||
fa_setupLayout()
|
||||
}
|
||||
|
||||
@MainActor required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
|
||||
if keyPath == "contentSize" {
|
||||
self.panModalSetNeedsLayoutUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
override func allowsTapBackgroundToDismiss() -> Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
override func cornerRadius() -> CGFloat {
|
||||
return 0
|
||||
}
|
||||
|
||||
override func longFormHeight() -> PanModalHeight {
|
||||
let height = 96 + scrollView.contentSize.height + 92 + 10
|
||||
return PanModalHeightMake(.content, height + UIScreen.safeBottom)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FACoinPackConfirmView {
|
||||
|
||||
private func fa_setupLayout() {
|
||||
addSubview(bgImageView)
|
||||
bgImageView.addSubview(bgIconImageView)
|
||||
addSubview(titleLabel)
|
||||
addSubview(closeButton)
|
||||
addSubview(scrollView)
|
||||
scrollView.addSubview(item1View)
|
||||
scrollView.addSubview(item2View)
|
||||
addSubview(priceLabel)
|
||||
addSubview(continueButton)
|
||||
|
||||
bgImageView.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview()
|
||||
}
|
||||
|
||||
bgIconImageView.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalToSuperview()
|
||||
}
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(55)
|
||||
}
|
||||
|
||||
closeButton.snp.makeConstraints { make in
|
||||
make.right.equalToSuperview().offset(-16)
|
||||
make.top.equalToSuperview().offset(24)
|
||||
}
|
||||
|
||||
scrollView.snp.makeConstraints { make in
|
||||
make.left.right.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(96)
|
||||
make.bottom.equalToSuperview().offset(-(92 + UIScreen.safeBottom + 10))
|
||||
}
|
||||
|
||||
item1View.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(16)
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalToSuperview()
|
||||
}
|
||||
|
||||
item2View.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(16)
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalTo(item1View.snp.bottom).offset(12)
|
||||
make.bottom.equalToSuperview()
|
||||
}
|
||||
|
||||
priceLabel.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.centerY.equalTo(scrollView.snp.bottom).offset(22)
|
||||
}
|
||||
|
||||
continueButton.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.left.equalToSuperview().offset(16)
|
||||
make.top.equalTo(scrollView.snp.bottom).offset(44)
|
||||
make.height.equalTo(48)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -9,15 +9,6 @@ import UIKit
|
||||
|
||||
class FAConsumptionRecordsCell: FATableViewCell {
|
||||
|
||||
var model: FABuyRecordsModel? {
|
||||
didSet {
|
||||
titleLabel.text = "Purchase Single Episode".localized
|
||||
subtitleLabel.text = "Ep.##".localizedReplace(text: "\(model?.episode ?? "")") + " " + "\(model?.name ?? "")"
|
||||
dateLabel.text = model?.created_at
|
||||
coinsLabel.text = "-\(model?.coins ?? 0)" + "Coins".localized
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@IBOutlet weak var titleLabel: UILabel!
|
||||
|
||||
@ -31,7 +22,7 @@ class FAConsumptionRecordsCell: FATableViewCell {
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
|
||||
titleLabel.text = "Purchase Single Episode";
|
||||
titleLabel.text = "Purchase Single Episode dafdaaafafaafdasfadfsafdafadsadfas";
|
||||
subtitleLabel.text = "Ep.8 Romantic Flash Marriage In Progress"
|
||||
dateLabel.text = "2024-6-10 23:41:18"
|
||||
coinsLabel.text = "-10 Coins"
|
||||
|
||||
@ -9,27 +9,6 @@ import UIKit
|
||||
|
||||
class FARewardCoinsCell: FATableViewCell {
|
||||
|
||||
var model: FASendCoinRecordModel? {
|
||||
didSet {
|
||||
nameLabel.text = model?.type
|
||||
dateLabel.text = model?.created_at
|
||||
countLabel.text = "+\(model?.coins ?? 0)"
|
||||
remainingLabel.text = model?.left_coins
|
||||
|
||||
if model?.is_effective == 1 {
|
||||
expiresIconImageView.isHidden = false
|
||||
expiresLabel.isHidden = false
|
||||
expiredLabel.isHidden = true
|
||||
expiresLabel.text = "Expires in ## days".localizedReplace(text: model?.diff_datetime ?? "")
|
||||
} else {
|
||||
expiresIconImageView.isHidden = true
|
||||
expiresLabel.isHidden = true
|
||||
expiredLabel.isHidden = false
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@IBOutlet weak var dateLabel: UILabel!
|
||||
|
||||
|
||||
@ -1,173 +0,0 @@
|
||||
//
|
||||
// FAStoreCoinsBigCell.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/24.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class FAStoreCoinsBigCell: FAStoreCoinsCell {
|
||||
|
||||
override var fa_isSelected: Bool {
|
||||
didSet {
|
||||
if fa_isSelected {
|
||||
bgImageView.image = UIImage(named: "Rectangle 6216")
|
||||
} else {
|
||||
bgImageView.image = UIImage(named: "Rectangle 6217")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override var model: FAPayItem? {
|
||||
didSet {
|
||||
let coins = model?.coins ?? 0
|
||||
let sendCoins = model?.send_coins ?? 0
|
||||
|
||||
coinCountLabel.text = "\(coins)"
|
||||
|
||||
priceLabel.text = (model?.currency ?? "") + " " + (model?.price ?? "")
|
||||
|
||||
if sendCoins > 0 {
|
||||
sendCoinsLabel.isHidden = false
|
||||
sendCoinsRatioImageView.isHidden = false
|
||||
sendCoinsLabel.text = "+\(sendCoins) " + "Coins".localized
|
||||
|
||||
let ratio = String(format: "%.0f", CGFloat(sendCoins) / CGFloat(coins) * 100)
|
||||
sendCoinsRatioLabel.text = "+\(ratio)%"
|
||||
} else {
|
||||
sendCoinsLabel.isHidden = true
|
||||
sendCoinsRatioImageView.isHidden = true
|
||||
}
|
||||
|
||||
if let mark = model?.corner_marker, !mark.isEmpty {
|
||||
self.hotImageView.isHidden = false
|
||||
} else {
|
||||
self.hotImageView.isHidden = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var bgImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "Rectangle 6217"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var coinImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "coins_icon_04"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var coinCountLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 16, weight: .medium)
|
||||
label.textColor = .FFFFFF
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var sendCoinsLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 10, weight: .medium)
|
||||
label.textColor = ._000000
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var sendCoinsRatioImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "Rectangle 36"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var sendCoinsRatioLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 12, weight: .medium)
|
||||
label.textColor = .FFFFFF
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var priceBgView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "Frame 3030"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var priceLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 14, weight: .heavy)
|
||||
label.textColor = ._000000
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var hotImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "hot_icon_01"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
fa_setupLayout()
|
||||
}
|
||||
|
||||
@MainActor required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FAStoreCoinsBigCell {
|
||||
|
||||
private func fa_setupLayout() {
|
||||
contentView.addSubview(bgImageView)
|
||||
bgImageView.addSubview(coinImageView)
|
||||
bgImageView.addSubview(coinCountLabel)
|
||||
bgImageView.addSubview(sendCoinsLabel)
|
||||
bgImageView.addSubview(sendCoinsRatioImageView)
|
||||
sendCoinsRatioImageView.addSubview(sendCoinsRatioLabel)
|
||||
contentView.addSubview(priceBgView)
|
||||
priceBgView.addSubview(priceLabel)
|
||||
contentView.addSubview(hotImageView)
|
||||
|
||||
bgImageView.snp.makeConstraints { make in
|
||||
make.left.right.top.equalToSuperview()
|
||||
}
|
||||
|
||||
coinImageView.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(7)
|
||||
}
|
||||
|
||||
coinCountLabel.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalTo(coinImageView.snp.bottom).offset(4)
|
||||
}
|
||||
|
||||
sendCoinsLabel.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalTo(coinCountLabel.snp.bottom).offset(0)
|
||||
}
|
||||
|
||||
sendCoinsRatioImageView.snp.makeConstraints { make in
|
||||
make.top.right.equalToSuperview()
|
||||
}
|
||||
|
||||
sendCoinsRatioLabel.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.left.equalToSuperview().offset(7)
|
||||
make.right.equalToSuperview().offset(-10)
|
||||
}
|
||||
|
||||
priceBgView.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.bottom.equalToSuperview()
|
||||
}
|
||||
|
||||
priceLabel.snp.makeConstraints { make in
|
||||
make.center.equalToSuperview()
|
||||
}
|
||||
|
||||
hotImageView.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(17)
|
||||
make.top.equalToSuperview().offset(-9)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
//
|
||||
// FAStoreCoinsCell.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/24.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class FAStoreCoinsCell: UICollectionViewCell {
|
||||
|
||||
var model: FAPayItem?
|
||||
|
||||
var fa_isSelected = false
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,230 +0,0 @@
|
||||
//
|
||||
// FAStoreCoinsPackCell.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/24.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class FAStoreCoinsPackCell: FAStoreCoinsCell {
|
||||
|
||||
|
||||
override var model: FAPayItem? {
|
||||
didSet {
|
||||
coinsLabel.text = "\(model?.ext_info?.max_total_coins ?? 0)"
|
||||
ratioLabel.text = "\(model?.ext_info?.receive_coins_rate ?? "0%")"
|
||||
|
||||
priceView.setNeedsUpdateConfiguration()
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var bgView: FAGradientView = {
|
||||
let view = FAGradientView()
|
||||
view.fa_colors = [UIColor._524_B_8_E.cgColor, UIColor._303265.cgColor]
|
||||
view.fa_locations = [0, 1]
|
||||
view.fa_startPoint = .init(x: 0, y: 0.5)
|
||||
view.fa_endPoint = .init(x: 1, y: 0.5)
|
||||
view.layer.cornerRadius = 12
|
||||
view.layer.masksToBounds = true
|
||||
view.layer.borderWidth = 1
|
||||
view.layer.borderColor = UIColor.E_5_E_5_E_5.cgColor
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var bgAttachmentView1: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "coin_attachment_01"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var bgAttachmentView2: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "coin_attachment_02"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var coinPileImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "coins_icon_05"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var titleLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 14, weight: .init(700))
|
||||
label.textColor = .FFFFFF
|
||||
label.text = "Weekly Refill".localized
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var coinsImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "coins_icon_06"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var coinsLabel: UILabel = {
|
||||
let label = FALabel()
|
||||
label.font = .font(ofSize: 18, weight: .init(900))
|
||||
label.textColors = [UIColor.FFCE_63.cgColor, UIColor.FFE_1_AA.cgColor]
|
||||
label.textStartPoint = .init(x: 0, y: 0.5)
|
||||
label.textEndPoint = .init(x: 1, y: 0.5)
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var ratioBgView: UIView = {
|
||||
let view = UIView()
|
||||
view.backgroundColor = .FFFFFF.withAlphaComponent(0.15)
|
||||
view.layer.cornerRadius = 4
|
||||
view.layer.masksToBounds = true
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var ratioLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 12, weight: .regular)
|
||||
label.textColor = .FFFFFF
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var priceView: UIButton = {
|
||||
var config = UIButton.Configuration.plain()
|
||||
config.titleAlignment = .center
|
||||
config.titlePadding = 0
|
||||
config.contentInsets = .init(top: 0, leading: 10, bottom: 0, trailing: 10)
|
||||
|
||||
let button = FAGradientButton(configuration: config)
|
||||
button.isUserInteractionEnabled = false
|
||||
button.layer.masksToBounds = true
|
||||
button.layer.cornerRadius = 24
|
||||
button.fa_colors = [UIColor._53_A_2_F_1.cgColor, UIColor.C_5_DDF_5.cgColor]
|
||||
button.fa_startPoint = .init(x: 0, y: 0.5)
|
||||
button.fa_endPoint = .init(x: 0.5, y: 0.5)
|
||||
button.fa_locations = [0, 1]
|
||||
button.configurationUpdateHandler = { [weak self] button in
|
||||
guard let self = self else { return }
|
||||
|
||||
let currency = self.model?.currency ?? ""
|
||||
let timeText = model?.getTimeString() ?? ""
|
||||
let oldPrice = self.model?.price ?? ""
|
||||
var discountPrice: String? = nil
|
||||
|
||||
if self.model?.discount_type == 1, let introductoryPrice = self.model?.introductionaryOffer {
|
||||
discountPrice = introductoryPrice.price.stringValue
|
||||
} else if self.model?.discount_type == 2, let discount = self.model?.promotionalOffers?.first {
|
||||
discountPrice = discount.price.stringValue
|
||||
}
|
||||
|
||||
if let discountPrice = discountPrice {
|
||||
|
||||
let priceString = AttributedString("\(currency)\(discountPrice)", attributes: AttributeContainer([
|
||||
.font : UIFont.font(ofSize: 18, weight: .bold),
|
||||
.foregroundColor : UIColor._114_CEE
|
||||
]))
|
||||
|
||||
|
||||
button.configuration?.attributedTitle = priceString
|
||||
|
||||
var subtitle = AttributedString("\(currency)\(oldPrice)", attributes: AttributeContainer([
|
||||
.font : UIFont.font(ofSize: 12, weight: .regular),
|
||||
.foregroundColor : UIColor._636_F_7_B.withAlphaComponent(0.2),
|
||||
.strikethroughStyle: NSUnderlineStyle.single.rawValue,
|
||||
.strikethroughColor: UIColor._636_F_7_B.withAlphaComponent(0.2)
|
||||
]))
|
||||
|
||||
button.configuration?.attributedSubtitle = subtitle
|
||||
|
||||
} else {
|
||||
|
||||
button.configuration?.attributedTitle = AttributedString("\(currency)\(oldPrice)", attributes: AttributeContainer([
|
||||
.font : UIFont.font(ofSize: 18, weight: .bold),
|
||||
.foregroundColor : UIColor._114_CEE
|
||||
]))
|
||||
|
||||
button.configuration?.attributedSubtitle = AttributedString("/\(timeText)", attributes: AttributeContainer([
|
||||
.font : UIFont.font(ofSize: 12, weight: .regular),
|
||||
.foregroundColor : UIColor._000000.withAlphaComponent(0.5)
|
||||
]))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return button
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
fa_setupLayout()
|
||||
}
|
||||
|
||||
@MainActor required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FAStoreCoinsPackCell {
|
||||
|
||||
private func fa_setupLayout() {
|
||||
contentView.addSubview(bgView)
|
||||
bgView.addSubview(bgAttachmentView1)
|
||||
bgView.addSubview(bgAttachmentView2)
|
||||
bgView.addSubview(coinPileImageView)
|
||||
bgView.addSubview(titleLabel)
|
||||
bgView.addSubview(coinsImageView)
|
||||
bgView.addSubview(coinsLabel)
|
||||
bgView.addSubview(ratioBgView)
|
||||
ratioBgView.addSubview(ratioLabel)
|
||||
bgView.addSubview(priceView)
|
||||
|
||||
bgView.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview()
|
||||
}
|
||||
|
||||
bgAttachmentView1.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(0)
|
||||
make.top.equalToSuperview().offset(0)
|
||||
}
|
||||
|
||||
bgAttachmentView2.snp.makeConstraints { make in
|
||||
make.right.equalToSuperview().offset(-26)
|
||||
make.centerY.equalToSuperview()
|
||||
}
|
||||
|
||||
coinPileImageView.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.left.equalToSuperview().offset(12)
|
||||
}
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.top.equalToSuperview().offset(19)
|
||||
make.left.equalTo(coinPileImageView.snp.right).offset(12)
|
||||
}
|
||||
|
||||
coinsImageView.snp.makeConstraints { make in
|
||||
make.left.equalTo(titleLabel)
|
||||
make.bottom.equalToSuperview().offset(-21)
|
||||
}
|
||||
|
||||
coinsLabel.snp.makeConstraints { make in
|
||||
make.centerY.equalTo(coinsImageView)
|
||||
make.left.equalTo(coinsImageView.snp.right).offset(4)
|
||||
}
|
||||
|
||||
ratioBgView.snp.makeConstraints { make in
|
||||
make.left.equalTo(coinsLabel.snp.right).offset(4)
|
||||
make.height.equalTo(18)
|
||||
make.centerY.equalTo(coinsImageView)
|
||||
}
|
||||
|
||||
ratioLabel.snp.makeConstraints { make in
|
||||
make.center.equalToSuperview()
|
||||
make.left.equalToSuperview().offset(8)
|
||||
}
|
||||
|
||||
priceView.snp.makeConstraints { make in
|
||||
make.right.equalToSuperview().offset(-12)
|
||||
make.centerY.equalToSuperview()
|
||||
make.height.equalTo(48)
|
||||
make.width.greaterThanOrEqualTo(88)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,161 +0,0 @@
|
||||
//
|
||||
// FAStoreCoinsSmallCell.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/24.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class FAStoreCoinsSmallCell: FAStoreCoinsCell {
|
||||
|
||||
override var model: FAPayItem? {
|
||||
didSet {
|
||||
let coins = model?.coins ?? 0
|
||||
let sendCoins = model?.send_coins ?? 0
|
||||
|
||||
coinsLabel.text = "\(coins)"
|
||||
|
||||
priceLabel.text = "\(model?.currency ?? "") \(model?.price ?? "")"
|
||||
|
||||
if let mark = model?.corner_marker, !mark.isEmpty {
|
||||
self.hotImageView.isHidden = false
|
||||
} else {
|
||||
self.hotImageView.isHidden = true
|
||||
}
|
||||
|
||||
if sendCoins > 0 {
|
||||
sendCoinsLabel.isHidden = false
|
||||
sendCoinsRatioView.isHidden = false
|
||||
sendCoinsLabel.text = "+\(sendCoins) " + "Coins".localized
|
||||
|
||||
let ratio = String(format: "%.0f", CGFloat(sendCoins) / CGFloat(coins) * 100)
|
||||
sendCoinsRatioLabel.text = "+\(ratio)%"
|
||||
} else {
|
||||
sendCoinsLabel.isHidden = true
|
||||
sendCoinsRatioView.isHidden = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var coinImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "coins_icon_07"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var coinsLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 16, weight: .medium)
|
||||
label.textColor = .FFFFFF
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var sendCoinsLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 10, weight: .medium)
|
||||
label.textColor = ._000000
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var priceBgView: UIView = {
|
||||
let view = UIView()
|
||||
view.backgroundColor = .B_8_EFFD
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var priceLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 13, weight: .bold)
|
||||
label.textColor = ._000000
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var sendCoinsRatioView: UIView = {
|
||||
let view = UIView()
|
||||
view.backgroundColor = ._2_D_75_FF
|
||||
view.fa_setRoundedCorner(topLeft: 0, topRight: 0, bottomLeft: 8, bottomRight: 0)
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var sendCoinsRatioLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 12, weight: .medium)
|
||||
label.textColor = .FFFFFF
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var hotImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "hot_icon_01"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
contentView.backgroundColor = ._84_C_0_FF.withAlphaComponent(0.77)
|
||||
contentView.layer.cornerRadius = 9
|
||||
contentView.layer.masksToBounds = true
|
||||
|
||||
fa_setupLayout()
|
||||
}
|
||||
|
||||
@MainActor required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FAStoreCoinsSmallCell {
|
||||
|
||||
private func fa_setupLayout() {
|
||||
contentView.addSubview(coinImageView)
|
||||
contentView.addSubview(coinsLabel)
|
||||
contentView.addSubview(sendCoinsLabel)
|
||||
contentView.addSubview(priceBgView)
|
||||
priceBgView.addSubview(priceLabel)
|
||||
addSubview(hotImageView)
|
||||
contentView.addSubview(sendCoinsRatioView)
|
||||
sendCoinsRatioView.addSubview(sendCoinsRatioLabel)
|
||||
|
||||
coinImageView.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(20)
|
||||
}
|
||||
|
||||
coinsLabel.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalTo(coinImageView.snp.bottom).offset(5)
|
||||
}
|
||||
|
||||
sendCoinsLabel.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalTo(coinsLabel.snp.bottom).offset(0)
|
||||
}
|
||||
|
||||
priceBgView.snp.makeConstraints { make in
|
||||
make.left.right.bottom.equalToSuperview()
|
||||
make.height.equalTo(28)
|
||||
}
|
||||
|
||||
priceLabel.snp.makeConstraints { make in
|
||||
make.center.equalToSuperview()
|
||||
}
|
||||
|
||||
hotImageView.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(-8)
|
||||
}
|
||||
|
||||
sendCoinsRatioView.snp.makeConstraints { make in
|
||||
make.right.top.equalToSuperview()
|
||||
make.height.equalTo(17)
|
||||
}
|
||||
|
||||
sendCoinsRatioLabel.snp.makeConstraints { make in
|
||||
make.center.equalToSuperview()
|
||||
make.left.equalToSuperview().offset(7)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,212 +0,0 @@
|
||||
//
|
||||
// FAStoreCoinsView.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/24.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class FAStoreCoinsView: UIView {
|
||||
|
||||
var shortPlayId: String?
|
||||
var videoId: String?
|
||||
|
||||
var buyFinishHandle: (() -> Void)?
|
||||
|
||||
private lazy var dataArr: [[FAPayItem]] = []
|
||||
|
||||
private var selectedIndexPath: IndexPath?
|
||||
|
||||
private lazy var collectionViewLayout: UICollectionViewCompositionalLayout = {
|
||||
let config = UICollectionViewCompositionalLayoutConfiguration()
|
||||
config.interSectionSpacing = 10
|
||||
|
||||
let layout = UICollectionViewCompositionalLayout { [weak self] section, _ in
|
||||
guard let self = self else { return nil}
|
||||
guard let model = dataArr[section].first else { return nil }
|
||||
|
||||
if model.buy_type == .subCoins {
|
||||
return self.coinsBigLayoutSection()
|
||||
} else if model.size == .big {
|
||||
return self.bigLayoutSection()
|
||||
} else {
|
||||
return self.smallLayoutSection()
|
||||
}
|
||||
}
|
||||
layout.configuration = config
|
||||
|
||||
return layout
|
||||
}()
|
||||
|
||||
private lazy var collectionView: FACollectionView = {
|
||||
let collectionView = FACollectionView(frame: .zero, collectionViewLayout: collectionViewLayout)
|
||||
collectionView.delegate = self
|
||||
collectionView.dataSource = self
|
||||
collectionView.clipsToBounds = false
|
||||
collectionView.isScrollEnabled = false
|
||||
collectionView.register(FAStoreCoinsBigCell.self, forCellWithReuseIdentifier: "FAStoreCoinsBigCell")
|
||||
collectionView.register(FAStoreCoinsSmallCell.self, forCellWithReuseIdentifier: "FAStoreCoinsSmallCell")
|
||||
collectionView.register(FAStoreCoinsPackCell.self, forCellWithReuseIdentifier: "FAStoreCoinsPackCell")
|
||||
collectionView.addObserver(self, forKeyPath: "contentSize", context: nil)
|
||||
return collectionView
|
||||
}()
|
||||
|
||||
deinit {
|
||||
collectionView.removeObserver(self, forKeyPath: "contentSize")
|
||||
}
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
fa_setupLayout()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
|
||||
if keyPath == "contentSize" {
|
||||
let height = self.collectionView.contentSize.height + 1
|
||||
self.collectionView.snp.updateConstraints { make in
|
||||
make.height.equalTo(height)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setDataArr(_ arr: [FAPayItem]) {
|
||||
self.dataArr.removeAll()
|
||||
var bigArr: [FAPayItem] = []
|
||||
var smallArr: [FAPayItem] = []
|
||||
var coinPackArr: [FAPayItem] = []
|
||||
|
||||
arr.forEach {
|
||||
if $0.buy_type == .subCoins {
|
||||
coinPackArr.append($0)
|
||||
} else if $0.size == .big {
|
||||
bigArr.append($0)
|
||||
} else {
|
||||
smallArr.append($0)
|
||||
}
|
||||
}
|
||||
|
||||
if bigArr.count > 0 {
|
||||
self.dataArr.append(bigArr)
|
||||
}
|
||||
if coinPackArr.count > 0 {
|
||||
self.dataArr.append(coinPackArr)
|
||||
}
|
||||
if smallArr.count > 0 {
|
||||
self.dataArr.append(smallArr)
|
||||
}
|
||||
self.collectionView.reloadData()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FAStoreCoinsView {
|
||||
|
||||
private func fa_setupLayout() {
|
||||
addSubview(collectionView)
|
||||
|
||||
collectionView.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview()
|
||||
make.height.equalTo(1)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FAStoreCoinsView {
|
||||
|
||||
private func bigLayoutSection() -> NSCollectionLayoutSection {
|
||||
let item = NSCollectionLayoutItem(layoutSize: .init(widthDimension: .fractionalWidth(0.5), heightDimension: .fractionalHeight(1)))
|
||||
|
||||
let group = NSCollectionLayoutGroup.horizontal(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .absolute(100)), subitems: [item])
|
||||
group.interItemSpacing = .fixed(1)
|
||||
|
||||
let layoutSection = NSCollectionLayoutSection(group: group)
|
||||
layoutSection.interGroupSpacing = 10
|
||||
layoutSection.contentInsets = .init(top: 0, leading: 16, bottom: 0, trailing: 16)
|
||||
return layoutSection
|
||||
}
|
||||
|
||||
private func smallLayoutSection() -> NSCollectionLayoutSection {
|
||||
let item = NSCollectionLayoutItem(layoutSize: .init(widthDimension: .fractionalWidth(1 / 3), heightDimension: .fractionalHeight(1)))
|
||||
|
||||
let group = NSCollectionLayoutGroup.horizontal(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .absolute(121)), subitems: [item])
|
||||
group.interItemSpacing = .fixed(8)
|
||||
|
||||
let layoutSection = NSCollectionLayoutSection(group: group)
|
||||
layoutSection.interGroupSpacing = 10
|
||||
layoutSection.contentInsets = .init(top: 0, leading: 16, bottom: 0, trailing: 16)
|
||||
return layoutSection
|
||||
}
|
||||
|
||||
private func coinsBigLayoutSection() -> NSCollectionLayoutSection {
|
||||
let item = NSCollectionLayoutItem(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(1)))
|
||||
|
||||
let group = NSCollectionLayoutGroup.horizontal(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .absolute(84)), subitems: [item])
|
||||
|
||||
|
||||
let layoutSection = NSCollectionLayoutSection(group: group)
|
||||
layoutSection.interGroupSpacing = 10
|
||||
layoutSection.contentInsets = .init(top: 0, leading: 16, bottom: 0, trailing: 16)
|
||||
return layoutSection
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: UICollectionViewDelegate UICollectionViewDataSource
|
||||
extension FAStoreCoinsView: UICollectionViewDelegate, UICollectionViewDataSource {
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||
let model = dataArr[indexPath.section][indexPath.row]
|
||||
|
||||
var identifier = "FAStoreCoinsBigCell"
|
||||
if model.buy_type == .subCoins {
|
||||
identifier = "FAStoreCoinsPackCell"
|
||||
} else if model.size == .small {
|
||||
identifier = "FAStoreCoinsSmallCell"
|
||||
}
|
||||
|
||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: identifier, for: indexPath) as! FAStoreCoinsCell
|
||||
cell.model = model
|
||||
cell.fa_isSelected = selectedIndexPath == indexPath
|
||||
return cell
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
return dataArr[section].count
|
||||
}
|
||||
|
||||
func numberOfSections(in collectionView: UICollectionView) -> Int {
|
||||
return dataArr.count
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||
let model = dataArr[indexPath.section][indexPath.row]
|
||||
self.selectedIndexPath = indexPath
|
||||
collectionView.reloadData()
|
||||
|
||||
if model.buy_type == .subCoins {
|
||||
let view = FACoinPackConfirmView()
|
||||
view.model = model
|
||||
view.buyFinishHandle = { [weak self] in
|
||||
guard let self = self else { return }
|
||||
FALogin.manager.requestUserInfo(completer: nil)
|
||||
self.buyFinishHandle?()
|
||||
}
|
||||
view.present(in: nil)
|
||||
} else {
|
||||
FAIapManager.manager.start(model: model, shortPlayId: self.shortPlayId, videoId: self.videoId) { [weak self] finish in
|
||||
guard let self = self else { return }
|
||||
if finish {
|
||||
FALogin.manager.requestUserInfo(completer: nil)
|
||||
self.buyFinishHandle?()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,278 +0,0 @@
|
||||
//
|
||||
// FAStoreVipCell.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/27.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import YYText
|
||||
|
||||
class FAStoreVipCell: UICollectionViewCell {
|
||||
|
||||
var item: FAPayItem? {
|
||||
didSet {
|
||||
nameLabel.text = item?.title
|
||||
desLabel.text = item?.fa_description
|
||||
// coinTimeLabel.text = item?.auto_sub
|
||||
|
||||
if let coins = item?.send_coins, coins > 0 {
|
||||
sendCoinLabel.text = "+\("extra".localized) \(coins)"
|
||||
sendCoinLabel.isHidden = false
|
||||
coinImageView.isHidden = false
|
||||
} else {
|
||||
sendCoinLabel.isHidden = true
|
||||
coinImageView.isHidden = true
|
||||
}
|
||||
|
||||
let currency = item?.currency ?? ""
|
||||
let oldPrice = item?.price ?? ""
|
||||
let time = "/\(item?.getTimeString() ?? "")"
|
||||
var offerPrice: String?
|
||||
|
||||
if item?.discount_type == 1, let offer = item?.introductionaryOffer {
|
||||
offerPrice = offer.price.stringValue
|
||||
} else if item?.discount_type == 2, let offer = item?.promotionalOffers?.first {
|
||||
offerPrice = offer.price.stringValue
|
||||
}
|
||||
|
||||
if let price = offerPrice {
|
||||
let priceString = NSMutableAttributedString(string: currency + price)
|
||||
priceString.yy_font = .font(ofSize: 28, weight: .init(800))
|
||||
priceLabel.attributedText = priceString
|
||||
|
||||
let oldPriceStr = NSMutableAttributedString(string: oldPrice)
|
||||
oldPriceStr.yy_strikethroughColor = discountLabel.textColor
|
||||
oldPriceStr.yy_strikethroughStyle = .single
|
||||
discountLabel.attributedText = oldPriceStr
|
||||
|
||||
discountLabel.isHidden = false
|
||||
|
||||
} else {
|
||||
let priceString = NSMutableAttributedString(string: currency + oldPrice)
|
||||
priceString.yy_font = .font(ofSize: 28, weight: .init(800))
|
||||
let timeString = NSMutableAttributedString(string: time)
|
||||
timeString.yy_font = .font(ofSize: 14, weight: .medium)
|
||||
timeString.yy_baselineOffset = 1
|
||||
priceString.append(timeString)
|
||||
|
||||
priceLabel.attributedText = priceString
|
||||
discountLabel.isHidden = true
|
||||
}
|
||||
|
||||
|
||||
|
||||
switch item?.vip_type_key {
|
||||
case .week:
|
||||
bgView.image = UIImage(named: "vip_bg_image_week")
|
||||
bgIconView.image = UIImage(named: "vip_bg_icon_week")
|
||||
vipImageView.image = UIImage(named: "vip_image_week")
|
||||
subBgView.backgroundColor = .E_9_F_0_FE
|
||||
nameBgView.backgroundColor = ._6398_FF
|
||||
priceLabel.textColors = [UIColor.FFFFFF.cgColor, UIColor.FFFFFF.cgColor]
|
||||
desLabel.textColor = .FFFFFF
|
||||
sendCoinLabel.textColor = ._679_AFF
|
||||
|
||||
case .month:
|
||||
bgView.image = UIImage(named: "vip_bg_image_month")
|
||||
bgIconView.image = UIImage(named: "vip_bg_icon_month")
|
||||
vipImageView.image = UIImage(named: "vip_image_month")
|
||||
subBgView.backgroundColor = .E_2_F_9_FF
|
||||
nameBgView.backgroundColor = ._58_D_4_F_1
|
||||
priceLabel.textColors = [UIColor.FFFFFF.cgColor, UIColor.FFFFFF.cgColor]
|
||||
desLabel.textColor = .FFFFFF
|
||||
sendCoinLabel.textColor = ._2_DD_7_FF
|
||||
|
||||
case .quarter:
|
||||
bgView.image = UIImage(named: "vip_bg_image_quarter")
|
||||
bgIconView.image = UIImage(named: "vip_bg_icon_quarter")
|
||||
vipImageView.image = UIImage(named: "vip_image_quarter")
|
||||
subBgView.backgroundColor = .EFE_8_FF
|
||||
nameBgView.backgroundColor = ._8_D_5_BF_6
|
||||
priceLabel.textColors = [UIColor.FFFFFF.cgColor, UIColor.FFFFFF.cgColor]
|
||||
desLabel.textColor = .FFFFFF
|
||||
sendCoinLabel.textColor = ._8853_FF
|
||||
|
||||
case .year:
|
||||
bgView.image = UIImage(named: "vip_bg_image_year")
|
||||
bgIconView.image = UIImage(named: "vip_bg_icon_year")
|
||||
vipImageView.image = UIImage(named: "vip_image_year")
|
||||
subBgView.backgroundColor = .FFF_8_D_0
|
||||
nameBgView.backgroundColor = .F_4_A_93_E
|
||||
priceLabel.textColors = [UIColor.DB_9_E_42.cgColor, UIColor._56280_F.cgColor]
|
||||
desLabel.textColor = ._814_E_20
|
||||
sendCoinLabel.textColor = .C_78_C_3_B
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
coinTimeLabel.textColor = sendCoinLabel.textColor
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var bgView: UIImageView = {
|
||||
let view = UIImageView()
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var bgIconView: UIImageView = {
|
||||
let view = UIImageView()
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var subBgView: UIView = {
|
||||
let view = UIView()
|
||||
view.fa_setRoundedCorner(topLeft: 0, topRight: 0, bottomLeft: 15, bottomRight: 15)
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var nameBgView: UIView = {
|
||||
let view = UIView()
|
||||
view.layer.cornerRadius = 4
|
||||
view.layer.masksToBounds = true
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var nameLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 14, weight: .init(800))
|
||||
label.textColor = .FFFFFF
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var vipImageView: UIImageView = {
|
||||
let imageView = UIImageView()
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var priceLabel: FALabel = {
|
||||
let label = FALabel()
|
||||
label.textStartPoint = .init(x: 0, y: 0.5)
|
||||
label.textEndPoint = .init(x: 1, y: 0.5)
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var discountLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 16, weight: .medium)
|
||||
label.textColor = .FFFFFF.withAlphaComponent(0.4)
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var desLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 12, weight: .regular)
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var sendCoinLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 12, weight: .medium)
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var coinImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "coins_icon_08"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var coinTimeLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 10, weight: .regular)
|
||||
return label
|
||||
}()
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
fa_setupLayout()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
|
||||
extension FAStoreVipCell {
|
||||
|
||||
private func fa_setupLayout() {
|
||||
contentView.addSubview(bgView)
|
||||
contentView.addSubview(subBgView)
|
||||
bgView.addSubview(bgIconView)
|
||||
bgView.addSubview(nameBgView)
|
||||
nameBgView.addSubview(nameLabel)
|
||||
bgView.addSubview(vipImageView)
|
||||
bgView.addSubview(priceLabel)
|
||||
bgView.addSubview(desLabel)
|
||||
bgView.addSubview(discountLabel)
|
||||
subBgView.addSubview(sendCoinLabel)
|
||||
subBgView.addSubview(coinImageView)
|
||||
subBgView.addSubview(coinTimeLabel)
|
||||
|
||||
bgView.snp.makeConstraints { make in
|
||||
make.left.right.top.equalToSuperview()
|
||||
}
|
||||
|
||||
subBgView.snp.makeConstraints { make in
|
||||
make.bottom.equalToSuperview()
|
||||
make.top.equalTo(bgView.snp.bottom)
|
||||
make.left.equalToSuperview().offset(30)
|
||||
make.centerX.equalToSuperview()
|
||||
}
|
||||
|
||||
bgIconView.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalToSuperview()
|
||||
}
|
||||
|
||||
nameBgView.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(12)
|
||||
make.top.equalToSuperview().offset(13)
|
||||
make.height.equalTo(18)
|
||||
}
|
||||
|
||||
nameLabel.snp.makeConstraints { make in
|
||||
make.center.equalToSuperview()
|
||||
make.left.equalToSuperview().offset(12)
|
||||
}
|
||||
|
||||
vipImageView.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.right.equalToSuperview().offset(-16)
|
||||
}
|
||||
|
||||
priceLabel.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(12)
|
||||
make.top.equalToSuperview().offset(36)
|
||||
}
|
||||
|
||||
desLabel.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(12)
|
||||
make.bottom.equalToSuperview().offset(-10)
|
||||
}
|
||||
|
||||
discountLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(priceLabel.snp.right).offset(4)
|
||||
make.centerY.equalTo(priceLabel).offset(3)
|
||||
}
|
||||
|
||||
sendCoinLabel.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.left.equalToSuperview().offset(12)
|
||||
}
|
||||
|
||||
coinImageView.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.left.equalTo(sendCoinLabel.snp.right).offset(3)
|
||||
}
|
||||
|
||||
coinTimeLabel.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.right.equalToSuperview().offset(-11)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,113 +0,0 @@
|
||||
//
|
||||
// FAStoreVipView.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/27.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class FAStoreVipView: UIView {
|
||||
|
||||
var dataArr: [FAPayItem] = [] {
|
||||
didSet {
|
||||
collectionView.reloadData()
|
||||
}
|
||||
}
|
||||
|
||||
var shortPlayId: String?
|
||||
var videoId: String?
|
||||
|
||||
var buyFinishHandle: (() -> Void)?
|
||||
|
||||
private lazy var collectionViewLayout: UICollectionViewCompositionalLayout = {
|
||||
|
||||
let item = NSCollectionLayoutItem(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(1)))
|
||||
|
||||
let group = NSCollectionLayoutGroup.horizontal(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .absolute(110)), subitems: [item])
|
||||
group.interItemSpacing = .fixed(14)
|
||||
|
||||
let layoutSection = NSCollectionLayoutSection(group: group)
|
||||
layoutSection.contentInsets = .init(top: 0, leading: 16, bottom: 0, trailing: 16)
|
||||
|
||||
let config = UICollectionViewCompositionalLayoutConfiguration()
|
||||
|
||||
let layout = UICollectionViewCompositionalLayout(section: layoutSection)
|
||||
layout.configuration = config
|
||||
|
||||
return layout
|
||||
}()
|
||||
|
||||
private lazy var collectionView: FACollectionView = {
|
||||
let collectionView = FACollectionView(frame: .zero, collectionViewLayout: collectionViewLayout)
|
||||
collectionView.delegate = self
|
||||
collectionView.dataSource = self
|
||||
collectionView.isScrollEnabled = false
|
||||
collectionView.addObserver(self, forKeyPath: "contentSize", context: nil)
|
||||
collectionView.register(FAStoreVipCell.self, forCellWithReuseIdentifier: "cell")
|
||||
return collectionView
|
||||
}()
|
||||
|
||||
deinit {
|
||||
collectionView.removeObserver(self, forKeyPath: "contentSize")
|
||||
}
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
fa_setupLayout()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
|
||||
if keyPath == "contentSize" {
|
||||
let height = self.collectionView.contentSize.height + 1
|
||||
self.collectionView.snp.updateConstraints { make in
|
||||
make.height.equalTo(height)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FAStoreVipView {
|
||||
|
||||
private func fa_setupLayout() {
|
||||
addSubview(collectionView)
|
||||
|
||||
collectionView.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview()
|
||||
make.height.equalTo(1)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//MARK: UICollectionViewDelegate UICollectionViewDataSource
|
||||
extension FAStoreVipView: UICollectionViewDelegate, UICollectionViewDataSource {
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! FAStoreVipCell
|
||||
cell.item = self.dataArr[indexPath.row]
|
||||
return cell
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
return dataArr.count
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||
let model = self.dataArr[indexPath.row]
|
||||
|
||||
FAIapManager.manager.start(model: model, shortPlayId: self.shortPlayId, videoId: self.videoId) { [weak self] finish in
|
||||
guard let self = self else { return }
|
||||
if finish {
|
||||
FALogin.manager.requestUserInfo(completer: nil)
|
||||
self.buyFinishHandle?()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
//
|
||||
// FAAdjustStateManager.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/23.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class FAAdjustStateManager {
|
||||
static let manager = FAAdjustStateManager()
|
||||
|
||||
var webpageURL: URL?
|
||||
///是否需要重试
|
||||
var isNeedRetry = false
|
||||
|
||||
var allowOpenMessage = true
|
||||
|
||||
var isOpenApp = false
|
||||
|
||||
var idfaAuthorizationFinish = false
|
||||
|
||||
}
|
||||
@ -11,7 +11,7 @@ import LYEmptyView
|
||||
|
||||
struct FAEmpty {
|
||||
|
||||
static func fa_emptyView(image: UIImage? = UIImage(named: "__shop-72"), title: String? = "empty_title_02".localized) -> LYEmptyView {
|
||||
static func fa_emptyView(image: UIImage?, title: String?) -> LYEmptyView {
|
||||
|
||||
let view = LYEmptyView.emptyActionView(with: image, titleStr: title, detailStr: nil, btnTitleStr: nil) {
|
||||
// btnClickBlock?()
|
||||
|
||||
@ -1,292 +0,0 @@
|
||||
//
|
||||
// FAIapManager.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/24.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import StoreKit
|
||||
|
||||
class FAIapManager {
|
||||
typealias CompletionHandler = ((_ finish: Bool) -> Void)
|
||||
///内购模版前缀
|
||||
static let IAPPrefix = "fableon"
|
||||
|
||||
|
||||
static let manager = FAIapManager()
|
||||
|
||||
///成功回调
|
||||
private var completionHandler: CompletionHandler?
|
||||
|
||||
private var shortPlayId: String?
|
||||
private var videoId: String?
|
||||
|
||||
private lazy var iapManager: JXIAPManager = {
|
||||
let manager = JXIAPManager()
|
||||
manager.delegate = self
|
||||
return manager
|
||||
}()
|
||||
|
||||
private var orderCode: String?
|
||||
private var payId: String?
|
||||
|
||||
///预加载数据
|
||||
private var payRequest: FAPayDataRequest?
|
||||
var payDateModel: FAPayDateModel?
|
||||
|
||||
|
||||
///恢复购买使用
|
||||
///等待恢复的数据
|
||||
private var waitRestoreModel: FAWaitRestoreModel? = UserDefaults.fa_object(forKey: kFAWaitRestoreIAPDefaultsKey, as: FAWaitRestoreModel.self)
|
||||
|
||||
|
||||
///开始内购
|
||||
func start(model: FAPayItem, shortPlayId: String? = nil, videoId: String? = nil, hudShowView: UIView? = nil, handler: CompletionHandler? = nil) {
|
||||
|
||||
if let _ = self.waitRestoreModel {
|
||||
FAToast.show(text: "pay_error_6".localized)
|
||||
handler?(false)
|
||||
return
|
||||
}
|
||||
|
||||
guard let payId = model.id else {
|
||||
handler?(false)
|
||||
return
|
||||
}
|
||||
self.shortPlayId = shortPlayId
|
||||
self.videoId = videoId
|
||||
self.completionHandler = handler
|
||||
self.waitRestoreModel = FAWaitRestoreModel()
|
||||
self.waitRestoreModel?.buyType = model.buy_type
|
||||
let productId = getProductId(templateId: model.ios_template_id) ?? ""
|
||||
var isDiscount = false
|
||||
var identifierDiscount: String? = nil
|
||||
if model.discount_type == 1, let _ = model.introductionaryOffer {
|
||||
isDiscount = true
|
||||
} else if model.discount_type == 2, let discount = model.promotionalOffers?.first {
|
||||
isDiscount = true
|
||||
identifierDiscount = discount.identifier
|
||||
}
|
||||
|
||||
FAHUD.show(containerView: hudShowView)
|
||||
|
||||
FAStoreAPI.requestCreateOrder(payId: payId, shortPlayId: shortPlayId ?? "0", videoId: videoId ?? "0", isDiscount: isDiscount, identifierDiscount: identifierDiscount) { orderModel in
|
||||
guard let orderModel = orderModel else {
|
||||
FAHUD.dismiss()
|
||||
self.waitRestoreModel = nil
|
||||
self.completionHandler?(false)
|
||||
self.clean()
|
||||
return
|
||||
}
|
||||
self.orderCode = orderModel.order_code
|
||||
self.payId = payId
|
||||
self.waitRestoreModel?.payId = payId
|
||||
self.waitRestoreModel?.orderCode = orderModel.order_code
|
||||
|
||||
var discount: SKPaymentDiscount? = nil
|
||||
|
||||
if let identifierDiscount = identifierDiscount,
|
||||
let signData = orderModel.discount?.sign_data,
|
||||
let keyIdentifier = signData.keyIdentifier,
|
||||
let nonce = UUID(uuidString: signData.nonce ?? ""),
|
||||
let signature = signData.signature,
|
||||
let timestamp = signData.timestamp
|
||||
{
|
||||
discount = SKPaymentDiscount(identifier: identifierDiscount,
|
||||
keyIdentifier: keyIdentifier,
|
||||
nonce: nonce,
|
||||
signature: signature,
|
||||
timestamp: NSNumber(value: timestamp))
|
||||
}
|
||||
|
||||
self.iapManager.start(productId: productId, orderId: self.orderCode ?? "", applicationUsername: orderModel.discount?.sign_data?.applicationUsername, discount: discount)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func restore(isLoding: Bool = true, shortPlayId: String? = nil, videoId: String? = nil, completer: ((_ isFinish: Bool, _ buyType: FAStoreAPI.BuyType?) -> Void)?) {
|
||||
let buyType = self.waitRestoreModel?.buyType
|
||||
|
||||
guard let waitRestoreModel = self.waitRestoreModel,
|
||||
let orderCode = waitRestoreModel.orderCode,
|
||||
let payId = waitRestoreModel.payId,
|
||||
let receipt = waitRestoreModel.receipt,
|
||||
let transactionId = waitRestoreModel.transactionId
|
||||
else {
|
||||
if isLoding {
|
||||
FAToast.show(text: "pay_error_5".localized)
|
||||
}
|
||||
completer?(false, buyType)
|
||||
return
|
||||
}
|
||||
|
||||
if isLoding {
|
||||
FAHUD.show()
|
||||
}
|
||||
|
||||
let verifyData = self.getVerifyOrderParameters(orderCode: orderCode, payId: payId, transactionId: transactionId, purchaseToken: receipt)
|
||||
|
||||
let statParamenters: [String : Any] = [
|
||||
"type" : isLoding ? "manual" : "auto",
|
||||
"pay_data" : verifyData.toJsonString() ?? ""
|
||||
]
|
||||
FAStatAPI.requestEventStat(orderCode: orderCode, shortPlayId: shortPlayId, videoId: videoId, eventKey: .payRestore, errorMsg: "restore", otherParamenters: statParamenters)
|
||||
|
||||
FAStoreAPI.requestVerifyOrder(parameters: verifyData) { response in
|
||||
if isLoding {
|
||||
FAHUD.dismiss()
|
||||
}
|
||||
|
||||
guard let model = response.data else {
|
||||
completer?(false, buyType)
|
||||
return
|
||||
}
|
||||
self.waitRestoreModel = nil
|
||||
UserDefaults.fa_setObject(nil, forKey: kFAWaitRestoreIAPDefaultsKey)
|
||||
|
||||
if model.status == "success" {
|
||||
if buyType == .subVip {
|
||||
FALogin.manager.userInfo?.is_vip = true
|
||||
}
|
||||
|
||||
if isLoding {
|
||||
FAToast.show(text: "success".localized)
|
||||
}
|
||||
completer?(true, buyType)
|
||||
if buyType == .subVip {
|
||||
NotificationCenter.default.post(name: FAIapManager.buyVipFinishNotification, object: nil)
|
||||
}
|
||||
} else {
|
||||
completer?(false, buyType)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
func getProductId(templateId: String?) -> String? {
|
||||
guard let templateId = templateId else { return nil }
|
||||
return FAIapManager.IAPPrefix + "." + templateId
|
||||
}
|
||||
|
||||
func clean() {
|
||||
self.orderCode = nil
|
||||
self.payId = nil
|
||||
self.shortPlayId = nil
|
||||
self.videoId = nil
|
||||
self.completionHandler = nil
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: JXIAPManagerDelegate
|
||||
extension FAIapManager: JXIAPManagerDelegate {
|
||||
|
||||
func jx_iapPaySuccess(productId: String, receipt: String, transactionIdentifier: String) {
|
||||
guard let orderCode = self.orderCode, let payId = self.payId else {
|
||||
self.waitRestoreModel = nil
|
||||
self.completionHandler?(false)
|
||||
self.clean()
|
||||
FAHUD.dismiss()
|
||||
return
|
||||
}
|
||||
|
||||
self.waitRestoreModel?.productId = productId
|
||||
self.waitRestoreModel?.receipt = receipt
|
||||
self.waitRestoreModel?.transactionId = transactionIdentifier
|
||||
|
||||
UserDefaults.fa_setObject(self.waitRestoreModel, forKey: kFAWaitRestoreIAPDefaultsKey)
|
||||
|
||||
#if DEBUG
|
||||
let verifyData = self.getVerifyOrderParameters(orderCode: orderCode, payId: payId, transactionId: transactionIdentifier, purchaseToken: receipt)
|
||||
#else
|
||||
let verifyData = self.getVerifyOrderParameters(orderCode: orderCode, payId: payId, transactionId: transactionIdentifier, purchaseToken: receipt)
|
||||
#endif
|
||||
|
||||
FAStoreAPI.requestVerifyOrder(parameters: verifyData) { response in
|
||||
FAHUD.dismiss()
|
||||
|
||||
guard let model = response.data else {
|
||||
FAStatAPI.requestEventStat(orderCode: self.orderCode, shortPlayId: self.shortPlayId, videoId: self.videoId, eventKey: .payCallback, errorMsg: verifyData.toJsonString())
|
||||
self.completionHandler?(false)
|
||||
self.clean()
|
||||
return
|
||||
}
|
||||
|
||||
let buyType = self.waitRestoreModel?.buyType
|
||||
self.waitRestoreModel = nil
|
||||
UserDefaults.fa_setObject(nil, forKey: kFAWaitRestoreIAPDefaultsKey)
|
||||
|
||||
if model.status == "success" {
|
||||
if buyType == .subVip {
|
||||
FALogin.manager.userInfo?.is_vip = true
|
||||
}
|
||||
|
||||
FAToast.show(text: "success".localized)
|
||||
self.completionHandler?(true)
|
||||
if buyType == .subVip {
|
||||
NotificationCenter.default.post(name: FAIapManager.buyVipFinishNotification, object: nil)
|
||||
}
|
||||
} else {
|
||||
FAToast.show(text: "pay_error_4".localized)
|
||||
FAStatAPI.requestEventStat(orderCode: self.orderCode, shortPlayId: self.shortPlayId, videoId: self.videoId, eventKey: .payCallback, errorMsg: verifyData.toJsonString())
|
||||
self.completionHandler?(false)
|
||||
}
|
||||
self.clean()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func jx_iapPayFailed(productId: String, code: JXIAPManagerCode, msg: String?) {
|
||||
FAHUD.dismiss()
|
||||
|
||||
if code == .noProduct {
|
||||
FAToast.show(text: "pay_error_2".localized)
|
||||
} else if code == .cancelled {
|
||||
FAToast.show(text: "pay_error_3".localized)
|
||||
}
|
||||
|
||||
if code == .cancelled {
|
||||
FAStatAPI.requestEventStat(orderCode: self.orderCode, shortPlayId: self.shortPlayId, videoId: self.videoId, eventKey: .payCancel, errorMsg: "user cancel")
|
||||
} else {
|
||||
FAStatAPI.requestEventStat(orderCode: self.orderCode, shortPlayId: self.shortPlayId, videoId: self.videoId, eventKey: .payError, errorMsg: msg)
|
||||
}
|
||||
|
||||
self.completionHandler?(false)
|
||||
|
||||
self.waitRestoreModel = nil
|
||||
self.clean()
|
||||
}
|
||||
}
|
||||
|
||||
extension FAIapManager {
|
||||
|
||||
func getVerifyOrderParameters(orderCode: String, payId: String, transactionId: String, purchaseToken: String) -> [String : Any] {
|
||||
let parameters: [String : Any] = [
|
||||
"order_code" : orderCode,
|
||||
"pay_setting_id" : payId,
|
||||
"pkg_name" : kFAAPPBundleIdentifier,
|
||||
"transaction_id": transactionId,
|
||||
"purchases_token" : purchaseToken
|
||||
]
|
||||
return parameters
|
||||
}
|
||||
|
||||
///预加载支付项
|
||||
func preloadingProducts() {
|
||||
JXIAPManager.manager.fetchReceipt { _ in
|
||||
self.payRequest = FAPayDataRequest()
|
||||
self.payRequest?.requestProducts(isLoding: false, isToast: false) { model in
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FAIapManager {
|
||||
///成功购买会员
|
||||
@objc static let buyVipFinishNotification = NSNotification.Name(rawValue: "FAIapManager.buyVipFinishNotification")
|
||||
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
//
|
||||
// FAIapOrderModel.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/24.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SmartCodable
|
||||
|
||||
struct FAIapOrderModel: SmartCodable {
|
||||
|
||||
var code: Int?
|
||||
var message: String?
|
||||
var order_code: String?
|
||||
var is_backhaul: String?
|
||||
var money: String?
|
||||
var discount: FAIapOrderDiscountModel?
|
||||
|
||||
}
|
||||
|
||||
struct FAIapOrderDiscountModel: SmartCodable {
|
||||
|
||||
var discount_code: String?
|
||||
var is_discount: Bool?
|
||||
var sign_data: FAIapOrderDiscountSign?
|
||||
}
|
||||
|
||||
struct FAIapOrderDiscountSign: SmartCodable {
|
||||
|
||||
var keyIdentifier: String?
|
||||
var nonce: String?
|
||||
var timestamp: TimeInterval?
|
||||
var applicationUsername: String?
|
||||
var signature: String?
|
||||
}
|
||||
|
||||
@ -1,17 +0,0 @@
|
||||
//
|
||||
// FAIapVerifyModel.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/24.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SmartCodable
|
||||
|
||||
struct FAIapVerifyModel: SmartCodable {
|
||||
|
||||
var money: String?
|
||||
var status: String?
|
||||
var is_backhaul: String?
|
||||
var code: String?
|
||||
}
|
||||
@ -1,181 +0,0 @@
|
||||
//
|
||||
// FAPayDataRequest.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/24.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import StoreKit
|
||||
|
||||
class FAPayDataRequest: NSObject {
|
||||
|
||||
private var oldTemplateModel: FAPayDateModel?
|
||||
private(set) var newTemplateModel: FAPayDateModel?
|
||||
|
||||
private var payAlertModel: FAPayAlertModel?
|
||||
|
||||
private var completerBlock: ((_ model: FAPayDateModel?) -> Void)?
|
||||
private var payAlertBlock: ((_ model: FAPayAlertModel?) -> Void)?
|
||||
|
||||
private var isLoding = false
|
||||
private var isToast = false
|
||||
|
||||
|
||||
func requestProducts(isLoding: Bool = false, isToast: Bool = true, completer: @escaping ((_ model: FAPayDateModel?) -> Void)) {
|
||||
self.payAlertBlock = nil
|
||||
self.completerBlock = completer
|
||||
self.isLoding = isLoding
|
||||
self.isToast = isToast
|
||||
|
||||
if isLoding {
|
||||
FAHUD.show()
|
||||
}
|
||||
|
||||
FAStoreAPI.requestPayTemplate(isToast: isToast) { [weak self] model in
|
||||
guard let self = self else { return }
|
||||
guard let model = model else {
|
||||
if isLoding {
|
||||
FAHUD.dismiss()
|
||||
}
|
||||
self.completerBlock?(nil)
|
||||
return
|
||||
}
|
||||
self.oldTemplateModel = model
|
||||
|
||||
var productIdArr: [String] = []
|
||||
model.list_sub_vip?.forEach { item in
|
||||
productIdArr.append(FAIapManager.manager.getProductId(templateId: item.ios_template_id) ?? "")
|
||||
}
|
||||
model.list_coins?.forEach { item in
|
||||
productIdArr.append(FAIapManager.manager.getProductId(templateId: item.ios_template_id) ?? "")
|
||||
}
|
||||
|
||||
let set = Set(productIdArr)
|
||||
let productsRequest = SKProductsRequest(productIdentifiers: set)
|
||||
productsRequest.delegate = self
|
||||
productsRequest.start()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func requestCoinAlertData(completer: @escaping ((_ model: FAPayAlertModel?) -> Void)) {
|
||||
self.completerBlock = nil
|
||||
self.payAlertBlock = completer
|
||||
|
||||
// BRStoreAPI.requestCoinAlertInfo { [weak self] model in
|
||||
// guard let self = self else { return }
|
||||
//
|
||||
// guard let model = model else {
|
||||
// self.payAlertBlock?(nil)
|
||||
// return
|
||||
// }
|
||||
// self.payAlertModel = model
|
||||
//
|
||||
// let productId = BRIAP.manager.getProductId(templateId: model.info?.ios_template_id) ?? ""
|
||||
//
|
||||
// let set = Set([productId])
|
||||
// let productsRequest = SKProductsRequest(productIdentifiers: set)
|
||||
// productsRequest.delegate = self
|
||||
// productsRequest.start()
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
///挽留信息
|
||||
func requestRetainVipPayInfo(completer: ((_ model: FAPayAlertModel?) -> Void)?) {
|
||||
self.completerBlock = nil
|
||||
self.payAlertBlock = completer
|
||||
|
||||
// FAStoreAPI.requestRetainVipPayInfo { [weak self] model in
|
||||
// guard let self = self else { return }
|
||||
// guard let model = model else {
|
||||
// self.payAlertBlock?(nil)
|
||||
// return
|
||||
// }
|
||||
// self.payAlertModel = model
|
||||
//
|
||||
// let productId = BRIAP.manager.getProductId(templateId: model.info?.ios_template_id) ?? ""
|
||||
//
|
||||
// let set = Set([productId])
|
||||
// let productsRequest = SKProductsRequest(productIdentifiers: set)
|
||||
// productsRequest.delegate = self
|
||||
// productsRequest.start()
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//MARK: SKProductsRequestDelegate
|
||||
extension FAPayDataRequest: SKProductsRequestDelegate {
|
||||
|
||||
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
|
||||
if isLoding {
|
||||
FAHUD.dismiss()
|
||||
}
|
||||
let products = response.products
|
||||
|
||||
if let block = self.completerBlock {
|
||||
guard let templateModel = self.oldTemplateModel else { return }
|
||||
|
||||
var newCoinList: [FAPayItem] = []
|
||||
var newVipList: [FAPayItem] = []
|
||||
|
||||
templateModel.list_coins?.forEach { item in
|
||||
let productId = FAIapManager.manager.getProductId(templateId: item.ios_template_id) ?? ""
|
||||
for product in products {
|
||||
if productId == product.productIdentifier {
|
||||
item.price = product.price.stringValue
|
||||
item.currency = product.priceLocale.currencySymbol
|
||||
item.product = product
|
||||
newCoinList.append(item)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
templateModel.list_sub_vip?.forEach { item in
|
||||
let productId = FAIapManager.manager.getProductId(templateId: item.ios_template_id) ?? ""
|
||||
for product in products {
|
||||
if productId == product.productIdentifier {
|
||||
item.price = product.price.stringValue
|
||||
item.currency = product.priceLocale.currencySymbol
|
||||
item.product = product
|
||||
newVipList.append(item)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
templateModel.list_coins = newCoinList
|
||||
templateModel.list_sub_vip = newVipList
|
||||
|
||||
self.newTemplateModel = templateModel
|
||||
FAIapManager.manager.payDateModel = templateModel
|
||||
|
||||
DispatchQueue.main.async {
|
||||
block(templateModel)
|
||||
}
|
||||
|
||||
} else if let block = self.payAlertBlock {
|
||||
guard let coinalertModel = self.payAlertModel else { return }
|
||||
let productId = FAIapManager.manager.getProductId(templateId: coinalertModel.info?.ios_template_id) ?? ""
|
||||
|
||||
for product in products {
|
||||
if productId == product.productIdentifier {
|
||||
coinalertModel.info?.price = product.price.stringValue
|
||||
coinalertModel.info?.currency = product.priceLocale.currencySymbol
|
||||
coinalertModel.info?.product = product
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
block(coinalertModel)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,49 +0,0 @@
|
||||
//
|
||||
// FAWaitRestoreModel.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/24.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class FAWaitRestoreModel: NSObject, NSSecureCoding {
|
||||
|
||||
|
||||
var orderCode: String?
|
||||
var payId: String?
|
||||
var productId: String?
|
||||
var receipt: String?
|
||||
var buyType: FAStoreAPI.BuyType?
|
||||
var transactionId: String?
|
||||
|
||||
|
||||
required override init() { }
|
||||
|
||||
static var supportsSecureCoding: Bool {
|
||||
get {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func encode(with coder: NSCoder) {
|
||||
coder.encode(orderCode, forKey: "orderCode")
|
||||
coder.encode(payId, forKey: "payId")
|
||||
coder.encode(productId, forKey: "productId")
|
||||
coder.encode(receipt, forKey: "receipt")
|
||||
coder.encode(buyType?.rawValue, forKey: "buyType")
|
||||
coder.encode(transactionId, forKey: "transactionId")
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
super.init()
|
||||
orderCode = coder.decodeObject(of: NSString.self, forKey: "orderCode") as? String
|
||||
payId = coder.decodeObject(of: NSString.self, forKey: "payId") as? String
|
||||
productId = coder.decodeObject(of: NSString.self, forKey: "productId") as? String
|
||||
receipt = coder.decodeObject(of: NSString.self, forKey: "receipt") as? String
|
||||
transactionId = coder.decodeObject(of: NSString.self, forKey: "transactionId") as? String
|
||||
if let type = coder.decodeObject(of: NSString.self, forKey: "buyType") as? String {
|
||||
buyType = FAStoreAPI.BuyType(rawValue: type)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,215 +0,0 @@
|
||||
//
|
||||
// JXIAPManager.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/24.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import StoreKit
|
||||
|
||||
@objc protocol JXIAPManagerDelegate {
|
||||
/// 购买成功
|
||||
@objc optional func jx_iapPaySuccess(productId: String, receipt: String, transactionIdentifier: String)
|
||||
/// 购买失败
|
||||
@objc optional func jx_iapPayFailed(productId: String, code: JXIAPManagerCode, msg: String?)
|
||||
/// 恢复商品(仅限永久有效商品)
|
||||
@objc optional func iapPayRestore(productIds: [String], transactionIds: [String])
|
||||
}
|
||||
|
||||
@objc enum JXIAPManagerCode: Int {
|
||||
///未知错误
|
||||
case unknown
|
||||
///取消交易
|
||||
case cancelled
|
||||
///没有商品
|
||||
case noProduct
|
||||
}
|
||||
|
||||
class JXIAPManager: NSObject {
|
||||
|
||||
|
||||
static let manager: JXIAPManager = JXIAPManager()
|
||||
|
||||
weak var delegate: JXIAPManagerDelegate?
|
||||
|
||||
private var payment: SKPayment?
|
||||
|
||||
private var product: SKProduct?
|
||||
private var productId: String?
|
||||
|
||||
private var discount: SKPaymentDiscount?
|
||||
private var orderId: String?
|
||||
private var applicationUsername: String?
|
||||
|
||||
var receiptCompletion: ((URL?) -> Void)?
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
SKPaymentQueue.default().add(self)
|
||||
}
|
||||
|
||||
|
||||
func start(productId: String, orderId: String, applicationUsername: String?, discount: SKPaymentDiscount? = nil) {
|
||||
self.product = nil
|
||||
self.productId = productId
|
||||
self.orderId = orderId
|
||||
self.discount = discount
|
||||
self.applicationUsername = applicationUsername
|
||||
|
||||
let set = Set([productId])
|
||||
let productsRequest = SKProductsRequest(productIdentifiers: set)
|
||||
productsRequest.delegate = self
|
||||
productsRequest.start()
|
||||
}
|
||||
|
||||
/// 购买商品
|
||||
private func buyProduct() {
|
||||
guard let product = self.product else { return }
|
||||
|
||||
// 要购买商品,开个小票
|
||||
let payment = SKMutablePayment(product: product)
|
||||
payment.applicationUsername = self.applicationUsername
|
||||
if let discount = self.discount {
|
||||
payment.paymentDiscount = discount
|
||||
self.discount = nil
|
||||
}
|
||||
|
||||
self.payment = payment
|
||||
|
||||
// 去收银台排队,准备购买
|
||||
SKPaymentQueue.default().add(payment)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//MARK: -------------- SKProductsRequestDelegate --------------
|
||||
extension JXIAPManager: SKProductsRequestDelegate {
|
||||
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
|
||||
guard let product = response.products.first else {
|
||||
DispatchQueue.main.async {
|
||||
if let productId = self.productId {
|
||||
self.productId = nil
|
||||
self.delegate?.jx_iapPayFailed?(productId: productId, code: .noProduct, msg: nil)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
self.product = product
|
||||
|
||||
self.buyProduct()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: -------------- SKPaymentTransactionObserver --------------
|
||||
extension JXIAPManager: SKPaymentTransactionObserver {
|
||||
///购买回调
|
||||
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
|
||||
|
||||
for transaction in transactions {
|
||||
switch transaction.transactionState {
|
||||
case .purchased:
|
||||
DispatchQueue.main.async {
|
||||
self.completeTransaction(transaction: transaction)
|
||||
}
|
||||
SKPaymentQueue.default().finishTransaction(transaction)
|
||||
|
||||
case .failed:
|
||||
DispatchQueue.main.async {
|
||||
self.failedTransaction(transaction: transaction)
|
||||
}
|
||||
SKPaymentQueue.default().finishTransaction(transaction)
|
||||
// case .restored:
|
||||
// self.restoreTransaction(transaction: transaction)
|
||||
|
||||
case .purchasing:
|
||||
break
|
||||
default:
|
||||
SKPaymentQueue.default().finishTransaction(transaction)
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// func paymentQueue(_ queue: SKPaymentQueue, shouldAddStorePayment payment: SKPayment, for product: SKProduct) -> Bool {
|
||||
// return true
|
||||
// }
|
||||
|
||||
/// 恢复购买回调
|
||||
func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension JXIAPManager {
|
||||
|
||||
|
||||
private func completeTransaction(transaction: SKPaymentTransaction) {
|
||||
guard let encodeStr = getAppStoreReceipt() else { return }
|
||||
guard let transactionIdentifier = transaction.transactionIdentifier else { return }
|
||||
|
||||
guard let productId = self.productId, productId == transaction.payment.productIdentifier else { return }
|
||||
self.productId = nil
|
||||
self.delegate?.jx_iapPaySuccess?(productId: productId, receipt: encodeStr, transactionIdentifier: transactionIdentifier)
|
||||
|
||||
}
|
||||
|
||||
private func failedTransaction(transaction: SKPaymentTransaction) {
|
||||
let error = transaction.error as? SKError
|
||||
guard let productId = self.productId else { return }
|
||||
self.productId = nil
|
||||
|
||||
switch error?.code {
|
||||
case SKError.paymentCancelled:
|
||||
self.delegate?.jx_iapPayFailed?(productId: productId, code: .cancelled, msg: error?.localizedDescription)
|
||||
default:
|
||||
self.delegate?.jx_iapPayFailed?(productId: productId, code: .unknown, msg: error?.localizedDescription)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
extension JXIAPManager: SKRequestDelegate {
|
||||
|
||||
func getAppStoreReceipt() -> String? {
|
||||
guard let receiptURL = Bundle.main.appStoreReceiptURL else { return nil }
|
||||
let receiptData = NSData(contentsOf: receiptURL)
|
||||
return receiptData?.base64EncodedString(options: .endLineWithLineFeed)
|
||||
}
|
||||
|
||||
///获取凭证
|
||||
func fetchReceipt(completion: @escaping (URL?) -> Void) {
|
||||
let receiptURL = Bundle.main.appStoreReceiptURL
|
||||
if let url = receiptURL, FileManager.default.fileExists(atPath: url.path) {
|
||||
completion(url)
|
||||
return
|
||||
}
|
||||
|
||||
let request = SKReceiptRefreshRequest()
|
||||
request.delegate = self
|
||||
request.start()
|
||||
// 在 delegate 回调里处理
|
||||
self.receiptCompletion = completion
|
||||
}
|
||||
|
||||
func requestDidFinish(_ request: SKRequest) {
|
||||
let receiptURL = Bundle.main.appStoreReceiptURL
|
||||
if let url = receiptURL, FileManager.default.fileExists(atPath: url.path) {
|
||||
receiptCompletion?(url)
|
||||
} else {
|
||||
receiptCompletion?(nil)
|
||||
}
|
||||
}
|
||||
|
||||
func request(_ request: SKRequest, didFailWithError error: Error) {
|
||||
print("Receipt request failed: \(error)")
|
||||
receiptCompletion?(nil)
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xEE",
|
||||
"green" : "0x4C",
|
||||
"red" : "0x11"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xFF",
|
||||
"green" : "0xA1",
|
||||
"red" : "0x20"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x3C",
|
||||
"green" : "0x22",
|
||||
"red" : "0x29"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xFF",
|
||||
"green" : "0x75",
|
||||
"red" : "0x2D"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xFF",
|
||||
"green" : "0xD7",
|
||||
"red" : "0x2D"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x65",
|
||||
"green" : "0x32",
|
||||
"red" : "0x30"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x5D",
|
||||
"green" : "0x39",
|
||||
"red" : "0x40"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x8E",
|
||||
"green" : "0x4B",
|
||||
"red" : "0x52"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xF1",
|
||||
"green" : "0xA2",
|
||||
"red" : "0x53"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x0F",
|
||||
"green" : "0x28",
|
||||
"red" : "0x56"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xF1",
|
||||
"green" : "0xD4",
|
||||
"red" : "0x58"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x7B",
|
||||
"green" : "0x6F",
|
||||
"red" : "0x63"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xFF",
|
||||
"green" : "0x98",
|
||||
"red" : "0x63"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xFF",
|
||||
"green" : "0x9A",
|
||||
"red" : "0x67"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x20",
|
||||
"green" : "0x4E",
|
||||
"red" : "0x81"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xFF",
|
||||
"green" : "0xC0",
|
||||
"red" : "0x84"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xFF",
|
||||
"green" : "0x53",
|
||||
"red" : "0x88"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xF6",
|
||||
"green" : "0x5B",
|
||||
"red" : "0x8D"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xFD",
|
||||
"green" : "0xEF",
|
||||
"red" : "0xB8"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xF5",
|
||||
"green" : "0xDD",
|
||||
"red" : "0xC5"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x3B",
|
||||
"green" : "0x8C",
|
||||
"red" : "0xC7"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x42",
|
||||
"green" : "0x9E",
|
||||
"red" : "0xDB"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xFF",
|
||||
"green" : "0xF9",
|
||||
"red" : "0xE2"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xE5",
|
||||
"green" : "0xE5",
|
||||
"red" : "0xE5"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xFE",
|
||||
"green" : "0xF0",
|
||||
"red" : "0xE9"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xFF",
|
||||
"green" : "0xE8",
|
||||
"red" : "0xEF"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x3E",
|
||||
"green" : "0xA9",
|
||||
"red" : "0xF4"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x94",
|
||||
"green" : "0xF4",
|
||||
"red" : "0xF9"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x63",
|
||||
"green" : "0xCE",
|
||||
"red" : "0xFF"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xAA",
|
||||
"green" : "0xE1",
|
||||
"red" : "0xFF"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xD0",
|
||||
"green" : "0xF8",
|
||||
"red" : "0xFF"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -1,22 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Ellipse 873@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Ellipse 873@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 170 KiB |
|
Before Width: | Height: | Size: 358 KiB |
@ -1,22 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Frame 3030@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Frame 3030@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 15 KiB |
@ -1,22 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Group 2072750450@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Group 2072750450@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 19 KiB |
@ -1,22 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Group 2072750451@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Group 2072750451@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 23 KiB |
@ -1,44 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Rectangle 36@2x.png",
|
||||
"idiom" : "universal",
|
||||
"resizing" : {
|
||||
"cap-insets" : {
|
||||
"left" : 27,
|
||||
"right" : 24
|
||||
},
|
||||
"center" : {
|
||||
"mode" : "tile",
|
||||
"width" : 1
|
||||
},
|
||||
"mode" : "3-part-horizontal"
|
||||
},
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Rectangle 36@3x.png",
|
||||
"idiom" : "universal",
|
||||
"resizing" : {
|
||||
"cap-insets" : {
|
||||
"left" : 31,
|
||||
"right" : 35
|
||||
},
|
||||
"center" : {
|
||||
"mode" : "tile",
|
||||
"width" : 1
|
||||
},
|
||||
"mode" : "3-part-horizontal"
|
||||
},
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 602 B |
|
Before Width: | Height: | Size: 818 B |
@ -1,22 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Rectangle 6216@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Rectangle 6216@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 67 KiB |
@ -1,44 +0,0 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Rectangle 6217@2x.png",
|
||||
"idiom" : "universal",
|
||||
"resizing" : {
|
||||
"cap-insets" : {
|
||||
"left" : 71,
|
||||
"right" : 65
|
||||
},
|
||||
"center" : {
|
||||
"mode" : "tile",
|
||||
"width" : 1
|
||||
},
|
||||
"mode" : "3-part-horizontal"
|
||||
},
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Rectangle 6217@3x.png",
|
||||
"idiom" : "universal",
|
||||
"resizing" : {
|
||||
"cap-insets" : {
|
||||
"left" : 89,
|
||||
"right" : 103
|
||||
},
|
||||
"center" : {
|
||||
"mode" : "tile",
|
||||
"width" : 1
|
||||
},
|
||||
"mode" : "3-part-horizontal"
|
||||
},
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||